- Timestamp:
- 07/05/2026 01:15:23 AM (3 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-admin/includes/class-wp-filesystem-ftpext.php
r61311 r62637 13 13 * 14 14 * @see WP_Filesystem_Base 15 * @phpstan-type Options array{ 16 * hostname: string, 17 * username: string, 18 * password: string, 19 * port: non-negative-int, 20 * ssl: bool, 21 * } 22 * @phpstan-import-type FileListing from WP_Filesystem_Base 15 23 */ 16 24 class WP_Filesystem_FTPext extends WP_Filesystem_Base { … … 23 31 24 32 /** 33 * @since 7.1.0 34 * @var array 35 * @phpstan-var Options 36 */ 37 public $options; 38 39 /** 25 40 * Constructor. 26 41 * 27 42 * @since 2.5.0 28 43 * 29 * @param array $opt 30 */ 31 public function __construct( $opt = '' ) { 32 $this->method = 'ftpext'; 33 $this->errors = new WP_Error(); 44 * @param array $opt { 45 * Array of connection options. 46 * 47 * @type string $hostname Required. FTP server hostname. 48 * @type string $username Required. FTP username. 49 * @type string $password Required. FTP password. 50 * @type int $port Optional. FTP server port. Default 21. 51 * @type string $connection_type Optional. Connection type. Use 'ftps' to enable SSL. 52 * } 53 * @phpstan-param array{ 54 * hostname: non-empty-string, 55 * username: non-empty-string, 56 * password: string, 57 * port?: non-negative-int, 58 * connection_type?: 'ftps', 59 * }|null $opt 60 */ 61 public function __construct( $opt = null ) { 62 $this->method = 'ftpext'; 63 $this->errors = new WP_Error(); 64 $this->options = array( 65 'port' => 21, 66 'hostname' => '', 67 'username' => '', 68 'password' => '', 69 'ssl' => false, 70 ); 34 71 35 72 // Check if possible to use ftp functions. … … 44 81 } 45 82 46 if ( empty( $opt['port'] ) ) { 47 $this->options['port'] = 21; 48 } else { 83 if ( ! is_array( $opt ) ) { 84 $opt = array(); 85 } 86 87 if ( ! empty( $opt['port'] ) ) { 49 88 $this->options['port'] = $opt['port']; 50 89 } … … 69 108 } 70 109 71 $this->options['ssl'] = false;72 73 110 if ( isset( $opt['connection_type'] ) && 'ftps' === $opt['connection_type'] ) { 74 111 $this->options['ssl'] = true; … … 84 121 */ 85 122 public function connect() { 123 /* 124 * Bail if the constructor recorded a configuration error. Connection and 125 * authentication errors are excluded so that a failed connection attempt 126 * can be retried on the same instance. 127 */ 128 if ( $this->errors->has_errors() && ! array_intersect( array( 'connect', 'auth' ), $this->errors->get_error_codes() ) ) { 129 return false; 130 } 131 86 132 if ( isset( $this->options['ssl'] ) && $this->options['ssl'] && function_exists( 'ftp_ssl_connect' ) ) { 87 133 $this->link = @ftp_ssl_connect( $this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT ); … … 136 182 */ 137 183 public function get_contents( $file ) { 184 if ( ! $this->link ) { 185 return false; 186 } 187 138 188 $tempfile = wp_tempnam( $file ); 139 189 $temphandle = fopen( $tempfile, 'w+' ); … … 169 219 * 170 220 * @param string $file Path to the file. 171 * @return array|false File contents in an array on success, false on failure.221 * @return string[]|false File contents in an array on success, false on failure. 172 222 */ 173 223 public function get_contents_array( $file ) { 174 return explode( "\n", $this->get_contents( $file ) ); 224 $contents = $this->get_contents( $file ); 225 if ( is_string( $contents ) ) { 226 return explode( "\n", $contents ); 227 } 228 return false; 175 229 } 176 230 … … 295 349 * 296 350 * @param string $file Path to the file. 297 * @return string| false Username of the owner on success, false on failure.351 * @return string|int<1, max>|false Username of the owner on success, false on failure. 298 352 */ 299 353 public function owner( $file ) { … … 323 377 * 324 378 * @param string $file Path to the file. 325 * @return string| false The group on success, false on failure.379 * @return string|int<1, max>|false The group on success, false on failure. 326 380 */ 327 381 public function group( $file ) { … … 466 520 */ 467 521 public function is_dir( $path ) { 468 $cwd = $this->cwd(); 522 $cwd = $this->cwd(); 523 if ( false === $cwd ) { 524 return false; 525 } 526 469 527 $result = @ftp_chdir( $this->link, trailingslashit( $path ) ); 528 529 if ( ! $this->link ) { 530 return false; 531 } 470 532 471 533 if ( $result && $path === $this->cwd() || $this->cwd() !== $cwd ) { … … 623 685 * False if unable to list directory contents. 624 686 * } 687 * @phpstan-return FileListing|'' 625 688 */ 626 689 public function parselisting( $line ) { … … 648 711 } 649 712 650 $b['size'] = $lucifer[7]; 651 $b['month'] = $lucifer[1]; 652 $b['day'] = $lucifer[2]; 653 $b['year'] = $lucifer[3]; 654 $b['hour'] = $lucifer[4]; 655 $b['minute'] = $lucifer[5]; 656 $b['time'] = mktime( $lucifer[4] + ( strcasecmp( $lucifer[6], 'PM' ) === 0 ? 12 : 0 ), $lucifer[5], 0, $lucifer[1], $lucifer[2], $lucifer[3] ); 657 $b['am/pm'] = $lucifer[6]; 658 $b['name'] = $lucifer[8]; 713 $b['size'] = $lucifer[7]; 714 $b['time'] = mktime( (int) $lucifer[4] + ( strcasecmp( $lucifer[6], 'PM' ) === 0 ? 12 : 0 ), (int) $lucifer[5], 0, (int) $lucifer[1], (int) $lucifer[2], (int) $lucifer[3] ); 715 $b['name'] = $lucifer[8]; 659 716 } elseif ( ! $is_windows ) { 660 717 $lucifer = preg_split( '/[ ]/', $line, 9, PREG_SPLIT_NO_EMPTY ); … … 687 744 688 745 if ( 8 === $lcount ) { 689 sscanf( $lucifer[5], '%d-%d-%d', $ b['year'], $b['month'], $b['day']);690 sscanf( $lucifer[6], '%d:%d', $ b['hour'], $b['minute']);691 692 $b['time'] = mktime( $b['hour'], $b['minute'], 0, $b['month'], $b['day'], $b['year']);746 sscanf( $lucifer[5], '%d-%d-%d', $year, $month, $day ); 747 sscanf( $lucifer[6], '%d:%d', $hour, $minute ); 748 749 $b['time'] = mktime( (int) $hour, (int) $minute, 0, (int) $month, (int) $day, (int) $year ); 693 750 $b['name'] = $lucifer[7]; 694 751 } else { 695 $ b['month']= $lucifer[5];696 $ b['day']= $lucifer[6];752 $month = $lucifer[5]; 753 $day = $lucifer[6]; 697 754 698 755 if ( preg_match( '/([0-9]{2}):([0-9]{2})/', $lucifer[7], $l2 ) ) { 699 $ b['year']= gmdate( 'Y' );700 $ b['hour']= $l2[1];701 $ b['minute']= $l2[2];756 $year = gmdate( 'Y' ); 757 $hour = $l2[1]; 758 $minute = $l2[2]; 702 759 } else { 703 $ b['year']= $lucifer[7];704 $ b['hour']= 0;705 $ b['minute']= 0;760 $year = $lucifer[7]; 761 $hour = 0; 762 $minute = 0; 706 763 } 707 764 708 $b['time'] = strtotime( sprintf( '%d %s %d %02d:%02d', $ b['day'], $b['month'], $b['year'], $b['hour'], $b['minute']) );765 $b['time'] = strtotime( sprintf( '%d %s %d %02d:%02d', $day, $month, $year, $hour, $minute ) ); 709 766 $b['name'] = $lucifer[8]; 710 767 } … … 714 771 // Replace symlinks formatted as "source -> target" with just the source name. 715 772 if ( isset( $b['islink'] ) && $b['islink'] ) { 716 $b['name'] = preg_replace( '/(\s*->\s*.*)$/', '', $b['name'] );717 } 718 719 return $b ;773 $b['name'] = (string) preg_replace( '/(\s*->\s*.*)$/', '', $b['name'] ); 774 } 775 776 return $b ?? ''; 720 777 } 721 778 … … 748 805 * @type string|false $lastmod Last modified month (3 letters) and day (without leading 0), or 749 806 * false if not available. 750 * @type string|false $time Last modified time, or false if not available.807 * @type int|string|false $time Last modified time as a Unix timestamp, or false if not available. 751 808 * @type string $type Type of resource. 'f' for file, 'd' for directory, 'l' for link. 752 809 * @type array|false $files If a directory and `$recursive` is true, contains another array of … … 754 811 * } 755 812 * } 813 * @phpstan-return array<string, FileListing>|false 756 814 */ 757 815 public function dirlist( $path = '.', $include_hidden = true, $recursive = false ) { 816 if ( ! $this->link ) { 817 return false; 818 } 819 758 820 if ( $this->is_file( $path ) ) { 759 821 $limit_file = basename( $path ); … … 764 826 765 827 $pwd = ftp_pwd( $this->link ); 828 if ( ! is_string( $pwd ) ) { 829 return false; 830 } 766 831 767 832 if ( ! @ftp_chdir( $this->link, $path ) ) { // Can't change to folder = folder doesn't exist. … … 769 834 } 770 835 836 /** @var string[]|false $list */ 771 837 $list = ftp_rawlist( $this->link, '-a', false ); 772 838
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)