PluginProbe
Import WP – CSV & XML Import Export for WordPress / 2.15.2
Import WP – CSV & XML Import Export for WordPress v2.15.2
2.15.2 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 All 145 releases
← All changes | class/Common/Filesystem/Filesystem.php +105 -2 2.14.23 → 2.15.2 View file →
@@ -126,8 +126,12 @@
126 126 } elseif ($filetype === 'csv') {
127 127 if (preg_match('/\.(csv|zip|gz)$/', $filename) === 0) {
128 128 $filename .= '.csv';
129 129 }
130 + } elseif ($filetype === 'json') {
131 + if (preg_match('/\.(json|zip|gz)$/', $filename) === 0) {
132 + $filename .= '.json';
133 + }
130 134 }
131 135
132 136 $dest = wp_unique_filename($wp_upload_dir['path'], $filename);
133 137 $wp_dest = $wp_upload_dir['path'] . '/' . $dest;
@@ -144,8 +148,11 @@
144 148 $headers['Accept'] = 'text/xml';
145 149 } elseif ($filetype === 'csv') {
146 150 $headers['Content-Type'] = 'text/csv';
147 151 $headers['Accept'] = 'text/csv';
152 + } elseif ($filetype === 'json') {
153 + $headers['Content-Type'] = 'application/json';
154 + $headers['Accept'] = 'application/json';
148 155 }
149 156
150 157 $result = $http->download_file_stream($remote_url, $wp_dest, $headers);
151 158 if (is_wp_error($result)) {
@@ -183,10 +190,10 @@
183 190
184 191 public function file_exists($src)
185 192 {
186 193 try {
187 - if (!file_exists($src)) {
188 - throw new \Exception(sprintf(__("File not found: %s", 'jc-importer'), $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 : ''));
189 196 }
190 197
191 198 $size = filesize($src);
192 199 if ($size == 0) {
@@ -279,8 +286,99 @@
279 286
280 287 return $path;
281 288 }
282 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 +
283 381 public function check_mime_header($mime)
284 382 {
285 383 switch ($mime) {
286 384 case 'text/comma-separated-values':
@@ -295,8 +393,11 @@
295 393 case 'text/xml':
296 394 case 'application/xml':
297 395 case 'application/x-xml':
298 396 return 'xml';
397 + case 'application/json':
398 + case 'text/json':
399 + return 'json';
299 400 }
300 401
301 402 return $this->event_handler->run('importer.allowed_mime_types', [false, $mime]);
302 403 }
@@ -324,8 +425,10 @@
324 425 if (stripos($file, '.csv')) {
325 426 $filetype = 'csv';
326 427 } elseif (stripos($file, '.xml')) {
327 428 $filetype = 'xml';
429 + } elseif (stripos($file, '.json')) {
430 + $filetype = 'json';
328 431 }
329 432
330 433 $filetype = apply_filters('iwp/get_filetype_from_ext', $filetype, $file);
331 434