12 * @since 2.5.0 |
12 * @since 2.5.0 |
13 * |
13 * |
14 * @see WP_Filesystem_Base |
14 * @see WP_Filesystem_Base |
15 */ |
15 */ |
16 class WP_Filesystem_FTPext extends WP_Filesystem_Base { |
16 class WP_Filesystem_FTPext extends WP_Filesystem_Base { |
|
17 |
|
18 /** |
|
19 * @since 2.5.0 |
|
20 * @var resource |
|
21 */ |
17 public $link; |
22 public $link; |
18 |
23 |
19 /** |
24 /** |
|
25 * Constructor. |
|
26 * |
|
27 * @since 2.5.0 |
20 * |
28 * |
21 * @param array $opt |
29 * @param array $opt |
22 */ |
30 */ |
23 public function __construct( $opt = '' ) { |
31 public function __construct( $opt = '' ) { |
24 $this->method = 'ftpext'; |
32 $this->method = 'ftpext'; |
25 $this->errors = new WP_Error(); |
33 $this->errors = new WP_Error(); |
26 |
34 |
27 // Check if possible to use ftp functions. |
35 // Check if possible to use ftp functions. |
28 if ( ! extension_loaded('ftp') ) { |
36 if ( ! extension_loaded( 'ftp' ) ) { |
29 $this->errors->add('no_ftp_ext', __('The ftp PHP extension is not available')); |
37 $this->errors->add( 'no_ftp_ext', __( 'The ftp PHP extension is not available' ) ); |
30 return; |
38 return; |
31 } |
39 } |
32 |
40 |
33 // This Class uses the timeout on a per-connection basis, Others use it on a per-action basis. |
41 // This Class uses the timeout on a per-connection basis, Others use it on a per-action basis. |
34 |
42 |
35 if ( ! defined('FS_TIMEOUT') ) |
43 if ( ! defined( 'FS_TIMEOUT' ) ) { |
36 define('FS_TIMEOUT', 240); |
44 define( 'FS_TIMEOUT', 240 ); |
37 |
45 } |
38 if ( empty($opt['port']) ) |
46 |
|
47 if ( empty( $opt['port'] ) ) { |
39 $this->options['port'] = 21; |
48 $this->options['port'] = 21; |
40 else |
49 } else { |
41 $this->options['port'] = $opt['port']; |
50 $this->options['port'] = $opt['port']; |
42 |
51 } |
43 if ( empty($opt['hostname']) ) |
52 |
44 $this->errors->add('empty_hostname', __('FTP hostname is required')); |
53 if ( empty( $opt['hostname'] ) ) { |
45 else |
54 $this->errors->add( 'empty_hostname', __( 'FTP hostname is required' ) ); |
|
55 } else { |
46 $this->options['hostname'] = $opt['hostname']; |
56 $this->options['hostname'] = $opt['hostname']; |
|
57 } |
47 |
58 |
48 // Check if the options provided are OK. |
59 // Check if the options provided are OK. |
49 if ( empty($opt['username']) ) |
60 if ( empty( $opt['username'] ) ) { |
50 $this->errors->add('empty_username', __('FTP username is required')); |
61 $this->errors->add( 'empty_username', __( 'FTP username is required' ) ); |
51 else |
62 } else { |
52 $this->options['username'] = $opt['username']; |
63 $this->options['username'] = $opt['username']; |
53 |
64 } |
54 if ( empty($opt['password']) ) |
65 |
55 $this->errors->add('empty_password', __('FTP password is required')); |
66 if ( empty( $opt['password'] ) ) { |
56 else |
67 $this->errors->add( 'empty_password', __( 'FTP password is required' ) ); |
|
68 } else { |
57 $this->options['password'] = $opt['password']; |
69 $this->options['password'] = $opt['password']; |
|
70 } |
58 |
71 |
59 $this->options['ssl'] = false; |
72 $this->options['ssl'] = false; |
60 if ( isset($opt['connection_type']) && 'ftps' == $opt['connection_type'] ) |
73 if ( isset( $opt['connection_type'] ) && 'ftps' == $opt['connection_type'] ) { |
61 $this->options['ssl'] = true; |
74 $this->options['ssl'] = true; |
62 } |
75 } |
63 |
76 } |
64 /** |
77 |
65 * |
78 /** |
66 * @return bool |
79 * Connects filesystem. |
|
80 * |
|
81 * @since 2.5.0 |
|
82 * |
|
83 * @return bool True on success, false on failure. |
67 */ |
84 */ |
68 public function connect() { |
85 public function connect() { |
69 if ( isset($this->options['ssl']) && $this->options['ssl'] && function_exists('ftp_ssl_connect') ) |
86 if ( isset( $this->options['ssl'] ) && $this->options['ssl'] && function_exists( 'ftp_ssl_connect' ) ) { |
70 $this->link = @ftp_ssl_connect($this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT); |
87 $this->link = @ftp_ssl_connect( $this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT ); |
71 else |
88 } else { |
72 $this->link = @ftp_connect($this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT); |
89 $this->link = @ftp_connect( $this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT ); |
|
90 } |
73 |
91 |
74 if ( ! $this->link ) { |
92 if ( ! $this->link ) { |
75 $this->errors->add( 'connect', |
93 $this->errors->add( |
|
94 'connect', |
76 /* translators: %s: hostname:port */ |
95 /* translators: %s: hostname:port */ |
77 sprintf( __( 'Failed to connect to FTP Server %s' ), |
96 sprintf( |
|
97 __( 'Failed to connect to FTP Server %s' ), |
78 $this->options['hostname'] . ':' . $this->options['port'] |
98 $this->options['hostname'] . ':' . $this->options['port'] |
79 ) |
99 ) |
80 ); |
100 ); |
81 return false; |
101 return false; |
82 } |
102 } |
83 |
103 |
84 if ( ! @ftp_login( $this->link,$this->options['username'], $this->options['password'] ) ) { |
104 if ( ! @ftp_login( $this->link, $this->options['username'], $this->options['password'] ) ) { |
85 $this->errors->add( 'auth', |
105 $this->errors->add( |
|
106 'auth', |
86 /* translators: %s: username */ |
107 /* translators: %s: username */ |
87 sprintf( __( 'Username/Password incorrect for %s' ), |
108 sprintf( |
|
109 __( 'Username/Password incorrect for %s' ), |
88 $this->options['username'] |
110 $this->options['username'] |
89 ) |
111 ) |
90 ); |
112 ); |
91 return false; |
113 return false; |
92 } |
114 } |
93 |
115 |
94 // Set the Connection to use Passive FTP |
116 // Set the Connection to use Passive FTP |
95 @ftp_pasv( $this->link, true ); |
117 @ftp_pasv( $this->link, true ); |
96 if ( @ftp_get_option($this->link, FTP_TIMEOUT_SEC) < FS_TIMEOUT ) |
118 if ( @ftp_get_option( $this->link, FTP_TIMEOUT_SEC ) < FS_TIMEOUT ) { |
97 @ftp_set_option($this->link, FTP_TIMEOUT_SEC, FS_TIMEOUT); |
119 @ftp_set_option( $this->link, FTP_TIMEOUT_SEC, FS_TIMEOUT ); |
|
120 } |
98 |
121 |
99 return true; |
122 return true; |
100 } |
123 } |
101 |
124 |
102 /** |
125 /** |
103 * Retrieves the file contents. |
126 * Reads entire file into a string. |
104 * |
127 * |
105 * @since 2.5.0 |
128 * @since 2.5.0 |
106 * |
129 * |
107 * @param string $file Filename. |
130 * @param string $file Name of the file to read. |
108 * @return string|false File contents on success, false if no temp file could be opened, |
131 * @return string|false Read data on success, false if no temporary file could be opened, |
109 * or if the file couldn't be retrieved. |
132 * or if the file couldn't be retrieved. |
110 */ |
133 */ |
111 public function get_contents( $file ) { |
134 public function get_contents( $file ) { |
112 $tempfile = wp_tempnam($file); |
135 $tempfile = wp_tempnam( $file ); |
113 $temp = fopen($tempfile, 'w+'); |
136 $temp = fopen( $tempfile, 'w+' ); |
114 |
137 |
115 if ( ! $temp ) { |
138 if ( ! $temp ) { |
116 unlink( $tempfile ); |
139 unlink( $tempfile ); |
117 return false; |
140 return false; |
118 } |
141 } |
174 |
205 |
175 fseek( $temp, 0 ); // Skip back to the start of the file being written to |
206 fseek( $temp, 0 ); // Skip back to the start of the file being written to |
176 |
207 |
177 $ret = @ftp_fput( $this->link, $file, $temp, FTP_BINARY ); |
208 $ret = @ftp_fput( $this->link, $file, $temp, FTP_BINARY ); |
178 |
209 |
179 fclose($temp); |
210 fclose( $temp ); |
180 unlink($tempfile); |
211 unlink( $tempfile ); |
181 |
212 |
182 $this->chmod($file, $mode); |
213 $this->chmod( $file, $mode ); |
183 |
214 |
184 return $ret; |
215 return $ret; |
185 } |
216 } |
186 |
217 |
187 /** |
218 /** |
188 * |
219 * Gets the current working directory. |
189 * @return string |
220 * |
|
221 * @since 2.5.0 |
|
222 * |
|
223 * @return string|false The current working directory on success, false on failure. |
190 */ |
224 */ |
191 public function cwd() { |
225 public function cwd() { |
192 $cwd = @ftp_pwd($this->link); |
226 $cwd = @ftp_pwd( $this->link ); |
193 if ( $cwd ) |
227 if ( $cwd ) { |
194 $cwd = trailingslashit($cwd); |
228 $cwd = trailingslashit( $cwd ); |
|
229 } |
195 return $cwd; |
230 return $cwd; |
196 } |
231 } |
197 |
232 |
198 /** |
233 /** |
199 * |
234 * Changes current directory. |
200 * @param string $dir |
235 * |
201 * @return bool |
236 * @since 2.5.0 |
202 */ |
237 * |
203 public function chdir($dir) { |
238 * @param string $dir The new current directory. |
204 return @ftp_chdir($this->link, $dir); |
239 * @return bool True on success, false on failure. |
205 } |
240 */ |
206 |
241 public function chdir( $dir ) { |
207 /** |
242 return @ftp_chdir( $this->link, $dir ); |
208 * |
243 } |
209 * @param string $file |
244 |
210 * @param int $mode |
245 /** |
211 * @param bool $recursive |
246 * Changes filesystem permissions. |
212 * @return bool |
247 * |
213 */ |
248 * @since 2.5.0 |
214 public function chmod($file, $mode = false, $recursive = false) { |
249 * |
|
250 * @param string $file Path to the file. |
|
251 * @param int|false $mode Optional. The permissions as octal number, usually 0644 for files, |
|
252 * 0755 for directories. Default false. |
|
253 * @param bool $recursive Optional. If set to true, changes file group recursively. |
|
254 * Default false. |
|
255 * @return bool True on success, false on failure. |
|
256 */ |
|
257 public function chmod( $file, $mode = false, $recursive = false ) { |
215 if ( ! $mode ) { |
258 if ( ! $mode ) { |
216 if ( $this->is_file($file) ) |
259 if ( $this->is_file( $file ) ) { |
217 $mode = FS_CHMOD_FILE; |
260 $mode = FS_CHMOD_FILE; |
218 elseif ( $this->is_dir($file) ) |
261 } elseif ( $this->is_dir( $file ) ) { |
219 $mode = FS_CHMOD_DIR; |
262 $mode = FS_CHMOD_DIR; |
220 else |
263 } else { |
221 return false; |
264 return false; |
|
265 } |
222 } |
266 } |
223 |
267 |
224 // chmod any sub-objects if recursive. |
268 // chmod any sub-objects if recursive. |
225 if ( $recursive && $this->is_dir($file) ) { |
269 if ( $recursive && $this->is_dir( $file ) ) { |
226 $filelist = $this->dirlist($file); |
270 $filelist = $this->dirlist( $file ); |
227 foreach ( (array)$filelist as $filename => $filemeta ) |
271 foreach ( (array) $filelist as $filename => $filemeta ) { |
228 $this->chmod($file . '/' . $filename, $mode, $recursive); |
272 $this->chmod( $file . '/' . $filename, $mode, $recursive ); |
|
273 } |
229 } |
274 } |
230 |
275 |
231 // chmod the file or directory |
276 // chmod the file or directory |
232 if ( ! function_exists('ftp_chmod') ) |
277 if ( ! function_exists( 'ftp_chmod' ) ) { |
233 return (bool)@ftp_site($this->link, sprintf('CHMOD %o %s', $mode, $file)); |
278 return (bool) @ftp_site( $this->link, sprintf( 'CHMOD %o %s', $mode, $file ) ); |
234 return (bool)@ftp_chmod($this->link, $mode, $file); |
279 } |
235 } |
280 return (bool) @ftp_chmod( $this->link, $mode, $file ); |
236 |
281 } |
237 /** |
282 |
238 * |
283 /** |
239 * @param string $file |
284 * Gets the file owner. |
240 * @return string |
285 * |
241 */ |
286 * @since 2.5.0 |
242 public function owner($file) { |
287 * |
243 $dir = $this->dirlist($file); |
288 * @param string $file Path to the file. |
244 return $dir[$file]['owner']; |
289 * @return string|false Username of the owner on success, false on failure. |
245 } |
290 */ |
246 /** |
291 public function owner( $file ) { |
247 * |
292 $dir = $this->dirlist( $file ); |
248 * @param string $file |
293 return $dir[ $file ]['owner']; |
249 * @return string |
294 } |
250 */ |
295 |
251 public function getchmod($file) { |
296 /** |
252 $dir = $this->dirlist($file); |
297 * Gets the permissions of the specified file or filepath in their octal format. |
253 return $dir[$file]['permsn']; |
298 * |
254 } |
299 * @since 2.5.0 |
255 |
300 * |
256 /** |
301 * @param string $file Path to the file. |
257 * |
302 * @return string Mode of the file (the last 3 digits). |
258 * @param string $file |
303 */ |
259 * @return string |
304 public function getchmod( $file ) { |
260 */ |
305 $dir = $this->dirlist( $file ); |
261 public function group($file) { |
306 return $dir[ $file ]['permsn']; |
262 $dir = $this->dirlist($file); |
307 } |
263 return $dir[$file]['group']; |
308 |
264 } |
309 /** |
265 |
310 * Gets the file's group. |
266 /** |
311 * |
267 * |
312 * @since 2.5.0 |
268 * @param string $source |
313 * |
269 * @param string $destination |
314 * @param string $file Path to the file. |
270 * @param bool $overwrite |
315 * @return string|false The group on success, false on failure. |
271 * @param string|bool $mode |
316 */ |
272 * @return bool |
317 public function group( $file ) { |
273 */ |
318 $dir = $this->dirlist( $file ); |
274 public function copy($source, $destination, $overwrite = false, $mode = false) { |
319 return $dir[ $file ]['group']; |
275 if ( ! $overwrite && $this->exists($destination) ) |
320 } |
276 return false; |
321 |
277 $content = $this->get_contents($source); |
322 /** |
278 if ( false === $content ) |
323 * Copies a file. |
279 return false; |
324 * |
280 return $this->put_contents($destination, $content, $mode); |
325 * @since 2.5.0 |
281 } |
326 * |
282 |
327 * @param string $source Path to the source file. |
283 /** |
328 * @param string $destination Path to the destination file. |
284 * |
329 * @param bool $overwrite Optional. Whether to overwrite the destination file if it exists. |
285 * @param string $source |
330 * Default false. |
286 * @param string $destination |
331 * @param int|false $mode Optional. The permissions as octal number, usually 0644 for files, |
287 * @param bool $overwrite |
332 * 0755 for dirs. Default false. |
288 * @return bool |
333 * @return bool True on success, false on failure. |
289 */ |
334 */ |
290 public function move($source, $destination, $overwrite = false) { |
335 public function copy( $source, $destination, $overwrite = false, $mode = false ) { |
291 return ftp_rename($this->link, $source, $destination); |
336 if ( ! $overwrite && $this->exists( $destination ) ) { |
292 } |
337 return false; |
293 |
338 } |
294 /** |
339 $content = $this->get_contents( $source ); |
295 * |
340 if ( false === $content ) { |
296 * @param string $file |
341 return false; |
297 * @param bool $recursive |
342 } |
298 * @param string $type |
343 return $this->put_contents( $destination, $content, $mode ); |
299 * @return bool |
344 } |
300 */ |
345 |
301 public function delete($file, $recursive = false, $type = false) { |
346 /** |
302 if ( empty($file) ) |
347 * Moves a file. |
303 return false; |
348 * |
304 if ( 'f' == $type || $this->is_file($file) ) |
349 * @since 2.5.0 |
305 return @ftp_delete($this->link, $file); |
350 * |
306 if ( !$recursive ) |
351 * @param string $source Path to the source file. |
307 return @ftp_rmdir($this->link, $file); |
352 * @param string $destination Path to the destination file. |
308 |
353 * @param bool $overwrite Optional. Whether to overwrite the destination file if it exists. |
309 $filelist = $this->dirlist( trailingslashit($file) ); |
354 * Default false. |
310 if ( !empty($filelist) ) |
355 * @return bool True on success, false on failure. |
311 foreach ( $filelist as $delete_file ) |
356 */ |
312 $this->delete( trailingslashit($file) . $delete_file['name'], $recursive, $delete_file['type'] ); |
357 public function move( $source, $destination, $overwrite = false ) { |
313 return @ftp_rmdir($this->link, $file); |
358 return ftp_rename( $this->link, $source, $destination ); |
314 } |
359 } |
315 |
360 |
316 /** |
361 /** |
317 * |
362 * Deletes a file or directory. |
318 * @param string $file |
363 * |
319 * @return bool |
364 * @since 2.5.0 |
320 */ |
365 * |
321 public function exists($file) { |
366 * @param string $file Path to the file or directory. |
322 $list = @ftp_nlist($this->link, $file); |
367 * @param bool $recursive Optional. If set to true, changes file group recursively. |
|
368 * Default false. |
|
369 * @param string|false $type Type of resource. 'f' for file, 'd' for directory. |
|
370 * Default false. |
|
371 * @return bool True on success, false on failure. |
|
372 */ |
|
373 public function delete( $file, $recursive = false, $type = false ) { |
|
374 if ( empty( $file ) ) { |
|
375 return false; |
|
376 } |
|
377 if ( 'f' == $type || $this->is_file( $file ) ) { |
|
378 return @ftp_delete( $this->link, $file ); |
|
379 } |
|
380 if ( ! $recursive ) { |
|
381 return @ftp_rmdir( $this->link, $file ); |
|
382 } |
|
383 |
|
384 $filelist = $this->dirlist( trailingslashit( $file ) ); |
|
385 if ( ! empty( $filelist ) ) { |
|
386 foreach ( $filelist as $delete_file ) { |
|
387 $this->delete( trailingslashit( $file ) . $delete_file['name'], $recursive, $delete_file['type'] ); |
|
388 } |
|
389 } |
|
390 return @ftp_rmdir( $this->link, $file ); |
|
391 } |
|
392 |
|
393 /** |
|
394 * Checks if a file or directory exists. |
|
395 * |
|
396 * @since 2.5.0 |
|
397 * |
|
398 * @param string $file Path to file or directory. |
|
399 * @return bool Whether $file exists or not. |
|
400 */ |
|
401 public function exists( $file ) { |
|
402 $list = @ftp_nlist( $this->link, $file ); |
323 |
403 |
324 if ( empty( $list ) && $this->is_dir( $file ) ) { |
404 if ( empty( $list ) && $this->is_dir( $file ) ) { |
325 return true; // File is an empty directory. |
405 return true; // File is an empty directory. |
326 } |
406 } |
327 |
407 |
328 return !empty($list); //empty list = no file, so invert. |
408 return ! empty( $list ); //empty list = no file, so invert. |
329 } |
409 } |
330 |
410 |
331 /** |
411 /** |
332 * |
412 * Checks if resource is a file. |
333 * @param string $file |
413 * |
334 * @return bool |
414 * @since 2.5.0 |
335 */ |
415 * |
336 public function is_file($file) { |
416 * @param string $file File path. |
337 return $this->exists($file) && !$this->is_dir($file); |
417 * @return bool Whether $file is a file. |
338 } |
418 */ |
339 |
419 public function is_file( $file ) { |
340 /** |
420 return $this->exists( $file ) && ! $this->is_dir( $file ); |
341 * |
421 } |
342 * @param string $path |
422 |
343 * @return bool |
423 /** |
344 */ |
424 * Checks if resource is a directory. |
345 public function is_dir($path) { |
425 * |
346 $cwd = $this->cwd(); |
426 * @since 2.5.0 |
347 $result = @ftp_chdir($this->link, trailingslashit($path) ); |
427 * |
|
428 * @param string $path Directory path. |
|
429 * @return bool Whether $path is a directory. |
|
430 */ |
|
431 public function is_dir( $path ) { |
|
432 $cwd = $this->cwd(); |
|
433 $result = @ftp_chdir( $this->link, trailingslashit( $path ) ); |
348 if ( $result && $path == $this->cwd() || $this->cwd() != $cwd ) { |
434 if ( $result && $path == $this->cwd() || $this->cwd() != $cwd ) { |
349 @ftp_chdir($this->link, $cwd); |
435 @ftp_chdir( $this->link, $cwd ); |
350 return true; |
436 return true; |
351 } |
437 } |
352 return false; |
438 return false; |
353 } |
439 } |
354 |
440 |
355 /** |
441 /** |
356 * |
442 * Checks if a file is readable. |
357 * @param string $file |
443 * |
358 * @return bool |
444 * @since 2.5.0 |
359 */ |
445 * |
360 public function is_readable($file) { |
446 * @param string $file Path to file. |
|
447 * @return bool Whether $file is readable. |
|
448 */ |
|
449 public function is_readable( $file ) { |
361 return true; |
450 return true; |
362 } |
451 } |
363 |
452 |
364 /** |
453 /** |
365 * |
454 * Checks if a file or directory is writable. |
366 * @param string $file |
455 * |
367 * @return bool |
456 * @since 2.5.0 |
368 */ |
457 * |
369 public function is_writable($file) { |
458 * @param string $file Path to file or directory. |
|
459 * @return bool Whether $file is writable. |
|
460 */ |
|
461 public function is_writable( $file ) { |
370 return true; |
462 return true; |
371 } |
463 } |
372 |
464 |
373 /** |
465 /** |
374 * |
466 * Gets the file's last access time. |
375 * @param string $file |
467 * |
376 * @return bool |
468 * @since 2.5.0 |
377 */ |
469 * |
378 public function atime($file) { |
470 * @param string $file Path to file. |
|
471 * @return int|false Unix timestamp representing last access time, false on failure. |
|
472 */ |
|
473 public function atime( $file ) { |
379 return false; |
474 return false; |
380 } |
475 } |
381 |
476 |
382 /** |
477 /** |
383 * |
478 * Gets the file modification time. |
384 * @param string $file |
479 * |
385 * @return int |
480 * @since 2.5.0 |
386 */ |
481 * |
387 public function mtime($file) { |
482 * @param string $file Path to file. |
388 return ftp_mdtm($this->link, $file); |
483 * @return int|false Unix timestamp representing modification time, false on failure. |
389 } |
484 */ |
390 |
485 public function mtime( $file ) { |
391 /** |
486 return ftp_mdtm( $this->link, $file ); |
392 * |
487 } |
393 * @param string $file |
488 |
394 * @return int |
489 /** |
395 */ |
490 * Gets the file size (in bytes). |
396 public function size($file) { |
491 * |
397 return ftp_size($this->link, $file); |
492 * @since 2.5.0 |
398 } |
493 * |
399 |
494 * @param string $file Path to file. |
400 /** |
495 * @return int|false Size of the file in bytes on success, false on failure. |
401 * |
496 */ |
402 * @param string $file |
497 public function size( $file ) { |
403 * @return bool |
498 return ftp_size( $this->link, $file ); |
404 */ |
499 } |
405 public function touch($file, $time = 0, $atime = 0) { |
500 |
|
501 /** |
|
502 * Sets the access and modification times of a file. |
|
503 * |
|
504 * Note: If $file doesn't exist, it will be created. |
|
505 * |
|
506 * @since 2.5.0 |
|
507 * |
|
508 * @param string $file Path to file. |
|
509 * @param int $time Optional. Modified time to set for file. |
|
510 * Default 0. |
|
511 * @param int $atime Optional. Access time to set for file. |
|
512 * Default 0. |
|
513 * @return bool True on success, false on failure. |
|
514 */ |
|
515 public function touch( $file, $time = 0, $atime = 0 ) { |
406 return false; |
516 return false; |
407 } |
517 } |
408 |
518 |
409 /** |
519 /** |
410 * |
520 * Creates a directory. |
411 * @param string $path |
521 * |
412 * @param mixed $chmod |
522 * @since 2.5.0 |
413 * @param mixed $chown |
523 * |
414 * @param mixed $chgrp |
524 * @param string $path Path for new directory. |
415 * @return bool |
525 * @param int|false $chmod Optional. The permissions as octal number (or false to skip chmod). |
416 */ |
526 * Default false. |
417 public function mkdir($path, $chmod = false, $chown = false, $chgrp = false) { |
527 * @param string|int $chown Optional. A user name or number (or false to skip chown). |
418 $path = untrailingslashit($path); |
528 * Default false. |
419 if ( empty($path) ) |
529 * @param string|int $chgrp Optional. A group name or number (or false to skip chgrp). |
420 return false; |
530 * Default false. |
421 |
531 * @return bool True on success, false on failure. |
422 if ( !@ftp_mkdir($this->link, $path) ) |
532 */ |
423 return false; |
533 public function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) { |
424 $this->chmod($path, $chmod); |
534 $path = untrailingslashit( $path ); |
|
535 if ( empty( $path ) ) { |
|
536 return false; |
|
537 } |
|
538 |
|
539 if ( ! @ftp_mkdir( $this->link, $path ) ) { |
|
540 return false; |
|
541 } |
|
542 $this->chmod( $path, $chmod ); |
425 return true; |
543 return true; |
426 } |
544 } |
427 |
545 |
428 /** |
546 /** |
429 * |
547 * Deletes a directory. |
430 * @param string $path |
548 * |
431 * @param bool $recursive |
549 * @since 2.5.0 |
432 * @return bool |
550 * |
433 */ |
551 * @param string $path Path to directory. |
434 public function rmdir($path, $recursive = false) { |
552 * @param bool $recursive Optional. Whether to recursively remove files/directories. |
435 return $this->delete($path, $recursive); |
553 * Default false. |
436 } |
554 * @return bool True on success, false on failure. |
437 |
555 */ |
438 /** |
556 public function rmdir( $path, $recursive = false ) { |
439 * |
557 return $this->delete( $path, $recursive ); |
|
558 } |
|
559 |
|
560 /** |
440 * @staticvar bool $is_windows |
561 * @staticvar bool $is_windows |
441 * @param string $line |
562 * @param string $line |
442 * @return array |
563 * @return array |
443 */ |
564 */ |
444 public function parselisting($line) { |
565 public function parselisting( $line ) { |
445 static $is_windows = null; |
566 static $is_windows = null; |
446 if ( is_null($is_windows) ) |
567 if ( is_null( $is_windows ) ) { |
447 $is_windows = stripos( ftp_systype($this->link), 'win') !== false; |
568 $is_windows = stripos( ftp_systype( $this->link ), 'win' ) !== false; |
448 |
569 } |
449 if ( $is_windows && preg_match('/([0-9]{2})-([0-9]{2})-([0-9]{2}) +([0-9]{2}):([0-9]{2})(AM|PM) +([0-9]+|<DIR>) +(.+)/', $line, $lucifer) ) { |
570 |
|
571 if ( $is_windows && preg_match( '/([0-9]{2})-([0-9]{2})-([0-9]{2}) +([0-9]{2}):([0-9]{2})(AM|PM) +([0-9]+|<DIR>) +(.+)/', $line, $lucifer ) ) { |
450 $b = array(); |
572 $b = array(); |
451 if ( $lucifer[3] < 70 ) |
573 if ( $lucifer[3] < 70 ) { |
452 $lucifer[3] +=2000; |
574 $lucifer[3] += 2000; |
453 else |
575 } else { |
454 $lucifer[3] += 1900; // 4digit year fix |
576 $lucifer[3] += 1900; // 4digit year fix |
455 $b['isdir'] = ( $lucifer[7] == '<DIR>'); |
577 } |
456 if ( $b['isdir'] ) |
578 $b['isdir'] = ( $lucifer[7] == '<DIR>' ); |
|
579 if ( $b['isdir'] ) { |
457 $b['type'] = 'd'; |
580 $b['type'] = 'd'; |
458 else |
581 } else { |
459 $b['type'] = 'f'; |
582 $b['type'] = 'f'; |
460 $b['size'] = $lucifer[7]; |
583 } |
461 $b['month'] = $lucifer[1]; |
584 $b['size'] = $lucifer[7]; |
462 $b['day'] = $lucifer[2]; |
585 $b['month'] = $lucifer[1]; |
463 $b['year'] = $lucifer[3]; |
586 $b['day'] = $lucifer[2]; |
464 $b['hour'] = $lucifer[4]; |
587 $b['year'] = $lucifer[3]; |
|
588 $b['hour'] = $lucifer[4]; |
465 $b['minute'] = $lucifer[5]; |
589 $b['minute'] = $lucifer[5]; |
466 $b['time'] = @mktime($lucifer[4] + (strcasecmp($lucifer[6], "PM") == 0 ? 12 : 0), $lucifer[5], 0, $lucifer[1], $lucifer[2], $lucifer[3]); |
590 $b['time'] = @mktime( $lucifer[4] + ( strcasecmp( $lucifer[6], 'PM' ) == 0 ? 12 : 0 ), $lucifer[5], 0, $lucifer[1], $lucifer[2], $lucifer[3] ); |
467 $b['am/pm'] = $lucifer[6]; |
591 $b['am/pm'] = $lucifer[6]; |
468 $b['name'] = $lucifer[8]; |
592 $b['name'] = $lucifer[8]; |
469 } elseif ( !$is_windows && $lucifer = preg_split('/[ ]/', $line, 9, PREG_SPLIT_NO_EMPTY)) { |
593 } elseif ( ! $is_windows && $lucifer = preg_split( '/[ ]/', $line, 9, PREG_SPLIT_NO_EMPTY ) ) { |
470 //echo $line."\n"; |
594 //echo $line."\n"; |
471 $lcount = count($lucifer); |
595 $lcount = count( $lucifer ); |
472 if ( $lcount < 8 ) |
596 if ( $lcount < 8 ) { |
473 return ''; |
597 return ''; |
474 $b = array(); |
598 } |
475 $b['isdir'] = $lucifer[0]{0} === 'd'; |
599 $b = array(); |
|
600 $b['isdir'] = $lucifer[0]{0} === 'd'; |
476 $b['islink'] = $lucifer[0]{0} === 'l'; |
601 $b['islink'] = $lucifer[0]{0} === 'l'; |
477 if ( $b['isdir'] ) |
602 if ( $b['isdir'] ) { |
478 $b['type'] = 'd'; |
603 $b['type'] = 'd'; |
479 elseif ( $b['islink'] ) |
604 } elseif ( $b['islink'] ) { |
480 $b['type'] = 'l'; |
605 $b['type'] = 'l'; |
481 else |
606 } else { |
482 $b['type'] = 'f'; |
607 $b['type'] = 'f'; |
483 $b['perms'] = $lucifer[0]; |
608 } |
|
609 $b['perms'] = $lucifer[0]; |
484 $b['permsn'] = $this->getnumchmodfromh( $b['perms'] ); |
610 $b['permsn'] = $this->getnumchmodfromh( $b['perms'] ); |
485 $b['number'] = $lucifer[1]; |
611 $b['number'] = $lucifer[1]; |
486 $b['owner'] = $lucifer[2]; |
612 $b['owner'] = $lucifer[2]; |
487 $b['group'] = $lucifer[3]; |
613 $b['group'] = $lucifer[3]; |
488 $b['size'] = $lucifer[4]; |
614 $b['size'] = $lucifer[4]; |
489 if ( $lcount == 8 ) { |
615 if ( $lcount == 8 ) { |
490 sscanf($lucifer[5], '%d-%d-%d', $b['year'], $b['month'], $b['day']); |
616 sscanf( $lucifer[5], '%d-%d-%d', $b['year'], $b['month'], $b['day'] ); |
491 sscanf($lucifer[6], '%d:%d', $b['hour'], $b['minute']); |
617 sscanf( $lucifer[6], '%d:%d', $b['hour'], $b['minute'] ); |
492 $b['time'] = @mktime($b['hour'], $b['minute'], 0, $b['month'], $b['day'], $b['year']); |
618 $b['time'] = @mktime( $b['hour'], $b['minute'], 0, $b['month'], $b['day'], $b['year'] ); |
493 $b['name'] = $lucifer[7]; |
619 $b['name'] = $lucifer[7]; |
494 } else { |
620 } else { |
495 $b['month'] = $lucifer[5]; |
621 $b['month'] = $lucifer[5]; |
496 $b['day'] = $lucifer[6]; |
622 $b['day'] = $lucifer[6]; |
497 if ( preg_match('/([0-9]{2}):([0-9]{2})/', $lucifer[7], $l2) ) { |
623 if ( preg_match( '/([0-9]{2}):([0-9]{2})/', $lucifer[7], $l2 ) ) { |
498 $b['year'] = date("Y"); |
624 $b['year'] = date( 'Y' ); |
499 $b['hour'] = $l2[1]; |
625 $b['hour'] = $l2[1]; |
500 $b['minute'] = $l2[2]; |
626 $b['minute'] = $l2[2]; |
501 } else { |
627 } else { |
502 $b['year'] = $lucifer[7]; |
628 $b['year'] = $lucifer[7]; |
503 $b['hour'] = 0; |
629 $b['hour'] = 0; |
504 $b['minute'] = 0; |
630 $b['minute'] = 0; |
505 } |
631 } |
506 $b['time'] = strtotime( sprintf('%d %s %d %02d:%02d', $b['day'], $b['month'], $b['year'], $b['hour'], $b['minute']) ); |
632 $b['time'] = strtotime( sprintf( '%d %s %d %02d:%02d', $b['day'], $b['month'], $b['year'], $b['hour'], $b['minute'] ) ); |
507 $b['name'] = $lucifer[8]; |
633 $b['name'] = $lucifer[8]; |
508 } |
634 } |
509 } |
635 } |
510 |
636 |
511 // Replace symlinks formatted as "source -> target" with just the source name |
637 // Replace symlinks formatted as "source -> target" with just the source name |