diff -r 7b1b88e27a20 -r 48c4eec2b7e6 wp/wp-admin/includes/class-wp-filesystem-ftpext.php --- a/wp/wp-admin/includes/class-wp-filesystem-ftpext.php Thu Sep 29 08:06:27 2022 +0200 +++ b/wp/wp-admin/includes/class-wp-filesystem-ftpext.php Fri Sep 05 18:40:08 2025 +0200 @@ -40,7 +40,7 @@ // This class uses the timeout on a per-connection basis, others use it on a per-action basis. if ( ! defined( 'FS_TIMEOUT' ) ) { - define( 'FS_TIMEOUT', 240 ); + define( 'FS_TIMEOUT', 4 * MINUTE_IN_SECONDS ); } if ( empty( $opt['port'] ) ) { @@ -358,13 +358,20 @@ } /** - * Moves a file. + * Moves a file or directory. + * + * After moving files or directories, OPcache will need to be invalidated. + * + * If moving a directory fails, `copy_dir()` can be used for a recursive copy. + * + * Use `move_dir()` for moving directories with OPcache invalidation and a + * fallback to `copy_dir()`. * * @since 2.5.0 * - * @param string $source Path to the source file. - * @param string $destination Path to the destination file. - * @param bool $overwrite Optional. Whether to overwrite the destination file if it exists. + * @param string $source Path to the source file or directory. + * @param string $destination Path to the destination file or directory. + * @param bool $overwrite Optional. Whether to overwrite the destination if it exists. * Default false. * @return bool True on success, false on failure. */ @@ -412,14 +419,25 @@ * Checks if a file or directory exists. * * @since 2.5.0 + * @since 6.3.0 Returns false for an empty path. * - * @param string $file Path to file or directory. - * @return bool Whether $file exists or not. + * @param string $path Path to file or directory. + * @return bool Whether $path exists or not. */ - public function exists( $file ) { - $list = ftp_nlist( $this->link, $file ); + public function exists( $path ) { + /* + * Check for empty path. If ftp_nlist() receives an empty path, + * it checks the current working directory and may return true. + * + * See https://core.trac.wordpress.org/ticket/33058. + */ + if ( '' === $path ) { + return false; + } - if ( empty( $list ) && $this->is_dir( $file ) ) { + $list = ftp_nlist( $this->link, $path ); + + if ( empty( $list ) && $this->is_dir( $path ) ) { return true; // File is an empty directory. } @@ -475,10 +493,10 @@ * * @since 2.5.0 * - * @param string $file Path to file or directory. - * @return bool Whether $file is writable. + * @param string $path Path to file or directory. + * @return bool Whether $path is writable. */ - public function is_writable( $file ) { + public function is_writable( $path ) { return true; } @@ -515,7 +533,9 @@ * @return int|false Size of the file in bytes on success, false on failure. */ public function size( $file ) { - return ftp_size( $this->link, $file ); + $size = ftp_size( $this->link, $file ); + + return ( $size > -1 ) ? $size : false; } /** @@ -582,7 +602,24 @@ /** * @param string $line - * @return array + * @return array { + * Array of file information. + * + * @type string $name Name of the file or directory. + * @type string $perms *nix representation of permissions. + * @type string $permsn Octal representation of permissions. + * @type string|false $number File number as a string, or false if not available. + * @type string|false $owner Owner name or ID, or false if not available. + * @type string|false $group File permissions group, or false if not available. + * @type string|false $size Size of file in bytes as a string, or false if not available. + * @type string|false $lastmodunix Last modified unix timestamp as a string, or false if not available. + * @type string|false $lastmod Last modified month (3 letters) and day (without leading 0), or + * false if not available. + * @type string|false $time Last modified time, or false if not available. + * @type string $type Type of resource. 'f' for file, 'd' for directory, 'l' for link. + * @type array|false $files If a directory and `$recursive` is true, contains another array of files. + * False if unable to list directory contents. + * } */ public function parselisting( $line ) { static $is_windows = null; @@ -692,18 +729,28 @@ * @param bool $recursive Optional. Whether to recursively include file details in nested directories. * Default false. * @return array|false { - * Array of files. False if unable to list directory contents. + * Array of arrays containing file information. False if unable to list directory contents. + * + * @type array ...$0 { + * Array of file information. Note that some elements may not be available on all filesystems. * - * @type string $name Name of the file or directory. - * @type string $perms *nix representation of permissions. - * @type string $permsn Octal representation of permissions. - * @type string $owner Owner name or ID. - * @type int $size Size of file in bytes. - * @type int $lastmodunix Last modified unix timestamp. - * @type mixed $lastmod Last modified month (3 letter) and day (without leading 0). - * @type int $time Last modified time. - * @type string $type Type of resource. 'f' for file, 'd' for directory. - * @type mixed $files If a directory and `$recursive` is true, contains another array of files. + * @type string $name Name of the file or directory. + * @type string $perms *nix representation of permissions. + * @type string $permsn Octal representation of permissions. + * @type int|string|false $number File number. May be a numeric string. False if not available. + * @type string|false $owner Owner name or ID, or false if not available. + * @type string|false $group File permissions group, or false if not available. + * @type int|string|false $size Size of file in bytes. May be a numeric string. + * False if not available. + * @type int|string|false $lastmodunix Last modified unix timestamp. May be a numeric string. + * False if not available. + * @type string|false $lastmod Last modified month (3 letters) and day (without leading 0), or + * false if not available. + * @type string|false $time Last modified time, or false if not available. + * @type string $type Type of resource. 'f' for file, 'd' for directory, 'l' for link. + * @type array|false $files If a directory and `$recursive` is true, contains another array of + * files. False if unable to list directory contents. + * } * } */ public function dirlist( $path = '.', $include_hidden = true, $recursive = false ) { @@ -752,12 +799,13 @@ $dirlist[ $entry['name'] ] = $entry; } - $ret = array(); + $path = trailingslashit( $path ); + $ret = array(); foreach ( (array) $dirlist as $struc ) { if ( 'd' === $struc['type'] ) { if ( $recursive ) { - $struc['files'] = $this->dirlist( $path . '/' . $struc['name'], $include_hidden, $recursive ); + $struc['files'] = $this->dirlist( $path . $struc['name'], $include_hidden, $recursive ); } else { $struc['files'] = array(); }