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 +145 -23 2.9.0 → 2.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,9 +223,9 @@
214 223 }
215 224
216 225 return array(
217 226 'dest' => $wp_dest,
218 - 'type' => $this->get_filetype($wp_dest),
227 + 'type' => is_null($filetype) ? $this->get_filetype($wp_dest) : $filetype,
219 228 'mime' => $this->get_file_mime($wp_dest)
220 229 );
221 230 }
222 231
@@ -226,9 +235,9 @@
226 235 $dest = wp_unique_filename($wp_upload_dir['path'], $filename);
227 236 $wp_dest = $wp_upload_dir['path'] . '/' . $dest;
228 237
229 238 if (file_put_contents($wp_dest, $string) === false) {
230 - return new \WP_Error('IWP_FS_SF', "Unable to write string to file");
239 + return new \WP_Error('IWP_FS_SF', __("Unable to write string to file", 'jc-importer'));
231 240 }
232 241
233 242 return array(
234 243 'dest' => $wp_dest,
@@ -243,25 +252,133 @@
243 252 * Get and/or create the plugins tmp directory
244 253 *
245 254 * @return string
246 255 */
247 - public function get_temp_directory($url = false)
256 +
257 + public function get_temp_directory($url = false, $folder = 'importwp')
248 258 {
249 - $base = $url ? WP_CONTENT_URL : WP_CONTENT_DIR;
259 + $dir = wp_upload_dir();
260 +
261 + $base = $url ? $dir['baseurl'] : $dir['basedir'];
250 262 $ds = $url ? '/' : DIRECTORY_SEPARATOR;
251 - $path = $base . $ds . 'uploads';
252 - if (!is_dir($path)) {
253 - 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);
254 269 }
255 270
256 - $path .= $ds . 'importwp';
257 - if (!is_dir($path)) {
258 - 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>");
259 281 }
260 282
283 + if (!file_exists($dir_path . '/index.html')) {
284 + touch($dir_path . '/index.html');
285 + }
286 +
261 287 return $path;
262 288 }
263 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 +
264 381 public function check_mime_header($mime)
265 382 {
266 383 switch ($mime) {
267 384 case 'text/comma-separated-values':
@@ -276,8 +393,11 @@
276 393 case 'text/xml':
277 394 case 'application/xml':
278 395 case 'application/x-xml':
279 396 return 'xml';
397 + case 'application/json':
398 + case 'text/json':
399 + return 'json';
280 400 }
281 401
282 402 return $this->event_handler->run('importer.allowed_mime_types', [false, $mime]);
283 403 }
@@ -305,8 +425,10 @@
305 425 if (stripos($file, '.csv')) {
306 426 $filetype = 'csv';
307 427 } elseif (stripos($file, '.xml')) {
308 428 $filetype = 'xml';
429 + } elseif (stripos($file, '.json')) {
430 + $filetype = 'json';
309 431 }
310 432
311 433 $filetype = apply_filters('iwp/get_filetype_from_ext', $filetype, $file);
312 434