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