PluginProbe
Import WP – CSV & XML Import Export for WordPress / 2.15.0
Import WP – CSV & XML Import Export for WordPress v2.15.0
2.15.1 2.15.0 2.14.24 2.14.23 2.7.0 2.7.1 2.7.10 2.7.11 2.7.12 2.7.13 2.7.14 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 2.8.0 2.8.1 2.8.2 2.8.3 2.9.0 2.9.1 All 144 releases
← All changes | class/Common/Filesystem/Filesystem.php +160 -21 2.7.122.15.0 View file →
@@ -27,33 +27,35 @@
27 27 $this->event_handler = $event_handler;
28 28 $this->container = Container::getInstance();
29 29 }
30 30
31 - public function copy($source, $destination, $allowed_mimes = null)
31 + public function copy($source, $destination, $allowed_mimes = null, $filetype = null)
32 32 {
33 33
34 34 if (!file_exists($source)) {
35 35 Logger::write('File doesn`t exist on local filesystem: ' . $source);
36 - return new \WP_Error('IWP_FS_7', 'File doesn`t exist on local filesystem.');
36 + return new \WP_Error('IWP_FS_7', __('File doesn`t exist on local filesystem.', 'jc-importer'));
37 37 }
38 38
39 - $filetype = $this->get_filetype($source);
39 + if (is_null($filetype)) {
40 + $filetype = $this->get_filetype($source);
41 + }
40 42
41 43 if (!is_null($allowed_mimes)) {
42 44
43 45 if (!$filetype) {
44 46 Logger::write('Unable to determine filetype: ' . $source);
45 - return new \WP_Error('IWP_FS_6', 'Unable to determine filetype.');
47 + return new \WP_Error('IWP_FS_6', __('Unable to determine filetype.', 'jc-importer'));
46 48 }
47 49
48 50 if (!in_array($filetype, $allowed_mimes, true)) {
49 51 Logger::write('Invalid filetype: ' . $filetype . ', allowed(' . implode(', ', $allowed_mimes) . ')');
50 - return new \WP_Error('IWP_FS_4', 'Invalid filetype.');
52 + return new \WP_Error('IWP_FS_4', __('Invalid filetype.', 'jc-importer'));
51 53 }
52 54 }
53 55
54 56 if (!copy($source, $destination)) {
55 - return new \WP_Error('IWP_FS_4', 'Unable to copy file: ' . $source . '.');
57 + return new \WP_Error('IWP_FS_4', sprintf(__('Unable to copy file: %s.', 'jc-importer'), $source));
56 58 }
57 59
58 60 $type = $this->get_file_mime($source);
59 61 Logger::write('Copied file: ' . $destination . ' -type=' . $filetype . ' -mime=' . $type);
@@ -86,9 +88,9 @@
86 88
87 89 // determine file type from mimetype.
88 90 if (!is_null($allowed_mimes) && !in_array($filetype, $allowed_mimes, true)) {
89 91 Logger::write('Invalid filetype: ' . $filetype . ', allowed(' . implode(', ', $allowed_mimes) . ')');
90 - return new \WP_Error('IWP_FS_4', 'Invalid filetype.');
92 + return new \WP_Error('IWP_FS_4', __('Invalid filetype.', 'jc-importer'));
91 93 }
92 94
93 95 Logger::write('Uploaded file: ' . $file . ' -type=' . $filetype . ' -mime=' . $type);
94 96
@@ -108,9 +110,9 @@
108 110 $filetype = $this->get_filetype_from_ext($remote_url_temp);
109 111 }
110 112 if (!in_array($filetype, $allowed_mimes, true)) {
111 113 Logger::write('Invalid filetype: ' . $filetype . ', allowed(' . implode(', ', $allowed_mimes) . ')');
112 - return new \WP_Error('IWP_FS_4', 'Invalid filetype.');
114 + return new \WP_Error('IWP_FS_4', __('Invalid filetype.', 'jc-importer'));
113 115 }
114 116 }
115 117
116 118 $wp_upload_dir = wp_upload_dir();
@@ -124,8 +126,12 @@
124 126 } elseif ($filetype === 'csv') {
125 127 if (preg_match('/\.(csv|zip|gz)$/', $filename) === 0) {
126 128 $filename .= '.csv';
127 129 }
130 + } elseif ($filetype === 'json') {
131 + if (preg_match('/\.(json|zip|gz)$/', $filename) === 0) {
132 + $filename .= '.json';
133 + }
128 134 }
129 135
130 136 $dest = wp_unique_filename($wp_upload_dir['path'], $filename);
131 137 $wp_dest = $wp_upload_dir['path'] . '/' . $dest;
@@ -142,8 +148,11 @@
142 148 $headers['Accept'] = 'text/xml';
143 149 } elseif ($filetype === 'csv') {
144 150 $headers['Content-Type'] = 'text/csv';
145 151 $headers['Accept'] = 'text/csv';
152 + } elseif ($filetype === 'json') {
153 + $headers['Content-Type'] = 'application/json';
154 + $headers['Accept'] = 'application/json';
146 155 }
147 156
148 157 $result = $http->download_file_stream($remote_url, $wp_dest, $headers);
149 158 if (is_wp_error($result)) {
@@ -181,16 +190,16 @@
181 190
182 191 public function file_exists($src)
183 192 {
184 193 try {
185 - if (!file_exists($src)) {
186 - throw new \Exception("File not found: " . $src);
194 + if (!is_string($src) || $src === '' || !file_exists($src)) {
195 + throw new \Exception(sprintf(__("File not found: %s", 'jc-importer'), is_string($src) ? $src : ''));
187 196 }
188 197
189 198 $size = filesize($src);
190 199 if ($size == 0) {
191 200 unlink($src);
192 - throw new \Exception("File not found or empty: " . $src);
201 + throw new \Exception(sprintf(__("File not found or empty: %s", 'jc-importer'), $src));
193 202 }
194 203 } catch (\Exception $e) {
195 204 return new \WP_Error('IWP_FS_8', $e->getMessage());
196 205 }
@@ -197,9 +206,9 @@
197 206
198 207 return true;
199 208 }
200 209
201 - public function copy_file($remote_url, $allowed_mimes = null, $override_filename = null, $prefix = '')
210 + public function copy_file($remote_url, $allowed_mimes = null, $override_filename = null, $prefix = '', $filetype = null)
202 211 {
203 212 $remote_url = strtok($remote_url, '?');
204 213
205 214 $wp_upload_dir = wp_upload_dir();
@@ -207,9 +216,9 @@
207 216 $filename = !empty($override_filename) ? $override_filename : $prefix . basename($remote_url);
208 217 $dest = wp_unique_filename($wp_upload_dir['path'], $filename);
209 218 $wp_dest = $wp_upload_dir['path'] . '/' . $dest;
210 219
211 - $result = $this->copy($remote_url, $wp_dest, $allowed_mimes);
220 + $result = $this->copy($remote_url, $wp_dest, $allowed_mimes, $filetype);
212 221 if (is_wp_error($result)) {
213 222 return $result;
214 223 }
215 224
@@ -214,8 +223,25 @@
214 223 }
215 224
216 225 return array(
217 226 'dest' => $wp_dest,
227 + 'type' => is_null($filetype) ? $this->get_filetype($wp_dest) : $filetype,
228 + 'mime' => $this->get_file_mime($wp_dest)
229 + );
230 + }
231 +
232 + public function string_to_file($string, $filename)
233 + {
234 + $wp_upload_dir = wp_upload_dir();
235 + $dest = wp_unique_filename($wp_upload_dir['path'], $filename);
236 + $wp_dest = $wp_upload_dir['path'] . '/' . $dest;
237 +
238 + if (file_put_contents($wp_dest, $string) === false) {
239 + return new \WP_Error('IWP_FS_SF', __("Unable to write string to file", 'jc-importer'));
240 + }
241 +
242 + return array(
243 + 'dest' => $wp_dest,
218 244 'type' => $this->get_filetype($wp_dest),
219 245 'mime' => $this->get_file_mime($wp_dest)
220 246 );
221 247 }
@@ -226,25 +252,133 @@
226 252 * Get and/or create the plugins tmp directory
227 253 *
228 254 * @return string
229 255 */
230 - public function get_temp_directory($url = false)
256 +
257 + public function get_temp_directory($url = false, $folder = 'importwp')
231 258 {
232 - $base = $url ? WP_CONTENT_URL : WP_CONTENT_DIR;
259 + $dir = wp_upload_dir();
260 +
261 + $base = $url ? $dir['baseurl'] : $dir['basedir'];
233 262 $ds = $url ? '/' : DIRECTORY_SEPARATOR;
234 - $path = $base . $ds . 'uploads';
235 - if (!is_dir($path)) {
236 - mkdir($path);
263 + $path = $base . $ds . $folder;
264 +
265 + // create folders and files if required, force to be dir path instead of url.
266 + $dir_path = $dir['basedir'] . DIRECTORY_SEPARATOR . $folder;
267 + if (!is_dir($dir_path)) {
268 + mkdir($dir_path);
237 269 }
238 270
239 - $path .= $ds . 'importwp';
240 - if (!is_dir($path)) {
241 - mkdir($path);
271 + if (!file_exists($dir_path . '/.htaccess')) {
272 + file_put_contents($dir_path . '/.htaccess', "# Apache 2.4+
273 +<IfModule mod_authz_core.c>
274 + Require all denied
275 +</IfModule>
276 +
277 +# Apache 2.2 and older (or when mod_authz_core isn't available)
278 +<IfModule !mod_authz_core.c>
279 + Deny from all
280 +</IfModule>");
242 281 }
243 282
283 + if (!file_exists($dir_path . '/index.html')) {
284 + touch($dir_path . '/index.html');
285 + }
286 +
244 287 return $path;
245 288 }
246 289
290 + /**
291 + * Whether a path looks absolute (Unix or Windows).
292 + *
293 + * @param string $path
294 + * @return bool
295 + */
296 + public static function is_absolute_path($path)
297 + {
298 + if (!is_string($path) || $path === '') {
299 + return false;
300 + }
301 +
302 + if ($path[0] === '/' || $path[0] === '\\') {
303 + return true;
304 + }
305 +
306 + return strlen($path) > 2 && ctype_alpha($path[0]) && $path[1] === ':';
307 + }
308 +
309 + /**
310 + * Convert an absolute path under the uploads basedir to a relative path.
311 + * Paths outside uploads are returned unchanged.
312 + *
313 + * @param string $path
314 + * @return string
315 + */
316 + public static function to_uploads_relative_path($path)
317 + {
318 + $path = wp_normalize_path((string) $path);
319 + $basedir = wp_normalize_path(untrailingslashit(wp_upload_dir()['basedir']));
320 +
321 + if ($path === $basedir) {
322 + return '';
323 + }
324 +
325 + if (strpos($path, $basedir . '/') === 0) {
326 + return ltrim(substr($path, strlen($basedir)), '/');
327 + }
328 +
329 + return $path;
330 + }
331 +
332 + /**
333 + * Resolve a stored importer file path to an absolute path under the current uploads directory.
334 + *
335 + * Avoids calling file_exists() on legacy absolute paths that may sit outside open_basedir
336 + * after a site move / hosting path change.
337 + *
338 + * @param string $stored
339 + * @return string|false Absolute filesystem path if the file exists, otherwise false.
340 + */
341 + public static function resolve_importer_file_path($stored)
342 + {
343 + if (!is_string($stored) || $stored === '') {
344 + return false;
345 + }
346 +
347 + $stored = wp_normalize_path(trim($stored));
348 + $basedir = wp_normalize_path(untrailingslashit(wp_upload_dir()['basedir']));
349 + $candidates = [];
350 +
351 + if (self::is_absolute_path($stored)) {
352 + if (strpos($stored, $basedir . '/') === 0 || $stored === $basedir) {
353 + $candidates[] = $stored;
354 + } else {
355 + // Remap legacy absolute paths that still contain the importwp suffix.
356 + if (preg_match('#/(importwp(?:/[^/]+)*/.+)$#', $stored, $matches)) {
357 + $candidates[] = $basedir . '/' . ltrim($matches[1], '/');
358 + }
359 + $candidates[] = $basedir . '/importwp/uploads/' . basename($stored);
360 + }
361 + } else {
362 + $candidates[] = $basedir . '/' . ltrim($stored, '/');
363 + }
364 +
365 + foreach (array_unique($candidates) as $candidate) {
366 + $candidate = wp_normalize_path($candidate);
367 +
368 + // Never probe paths outside the current uploads basedir (open_basedir safe).
369 + if ($candidate !== $basedir && strpos($candidate, $basedir . '/') !== 0) {
370 + continue;
371 + }
372 +
373 + if (file_exists($candidate)) {
374 + return $candidate;
375 + }
376 + }
377 +
378 + return false;
379 + }
380 +
247 381 public function check_mime_header($mime)
248 382 {
249 383 switch ($mime) {
250 384 case 'text/comma-separated-values':
@@ -259,8 +393,11 @@
259 393 case 'text/xml':
260 394 case 'application/xml':
261 395 case 'application/x-xml':
262 396 return 'xml';
397 + case 'application/json':
398 + case 'text/json':
399 + return 'json';
263 400 }
264 401
265 402 return $this->event_handler->run('importer.allowed_mime_types', [false, $mime]);
266 403 }
@@ -288,8 +425,10 @@
288 425 if (stripos($file, '.csv')) {
289 426 $filetype = 'csv';
290 427 } elseif (stripos($file, '.xml')) {
291 428 $filetype = 'xml';
429 + } elseif (stripos($file, '.json')) {
430 + $filetype = 'json';
292 431 }
293 432
294 433 $filetype = apply_filters('iwp/get_filetype_from_ext', $filetype, $file);
295 434