diff -r be944660c56a -r 3d72ae0968f4 wp/wp-admin/includes/file.php --- a/wp/wp-admin/includes/file.php Wed Sep 21 18:19:35 2022 +0200 +++ b/wp/wp-admin/includes/file.php Tue Sep 27 16:37:53 2022 +0200 @@ -223,7 +223,7 @@ ); /** - * Filters the list of file types allowed for editing in the plugin editor. + * Filters the list of file types allowed for editing in the plugin file editor. * * @since 2.8.0 * @since 4.9.0 Added the `$plugin` parameter. @@ -282,12 +282,12 @@ ); /** - * Filters the list of file types allowed for editing in the theme editor. + * Filters the list of file types allowed for editing in the theme file editor. * * @since 4.4.0 * * @param string[] $default_types An array of editable theme file extensions. - * @param WP_Theme $theme The current theme object. + * @param WP_Theme $theme The active theme object. */ $file_types = apply_filters( 'wp_theme_editor_filetypes', $default_types, $theme ); @@ -715,7 +715,7 @@ wp_die( __( 'Sorry, that file cannot be edited.' ) ); // case 2 : - // wp_die( __('Sorry, can’t call files with their real path.' )); + // wp_die( __('Sorry, cannot call files with their real path.' )); case 3: wp_die( __( 'Sorry, that file cannot be edited.' ) ); @@ -733,9 +733,16 @@ * * @see wp_handle_upload_error * - * @param string[] $file Reference to a single element of `$_FILES`. - * Call the function once for each uploaded file. - * @param array|false $overrides { + * @param array $file { + * Reference to a single element from `$_FILES`. Call the function once for each uploaded file. + * + * @type string $name The original name of the file on the client machine. + * @type string $type The mime type of the file, if the browser provided this information. + * @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server. + * @type int $size The size, in bytes, of the uploaded file. + * @type int $error The error code associated with this file upload. + * } + * @param array|false $overrides { * An array of override parameters for this file, or boolean false if none are provided. * * @type callable $upload_error_handler Function to call when there is an error during the upload process. @@ -749,11 +756,17 @@ * @type bool $test_type Whether to test that the mime type of the file is as expected. * @type string[] $mimes Array of allowed mime types keyed by their file extension regex. * } - * @param string $time Time formatted in 'yyyy/mm'. - * @param string $action Expected value for `$_POST['action']`. - * @return string[] On success, returns an associative array of file attributes. - * On failure, returns `$overrides['upload_error_handler']( &$file, $message )` - * or `array( 'error' => $message )`. + * @param string $time Time formatted in 'yyyy/mm'. + * @param string $action Expected value for `$_POST['action']`. + * @return array { + * On success, returns an associative array of file attributes. + * On failure, returns `$overrides['upload_error_handler']( &$file, $message )` + * or `array( 'error' => $message )`. + * + * @type string $file Filename of the newly-uploaded file. + * @type string $url URL of the newly-uploaded file. + * @type string $type Mime type of the newly-uploaded file. + * } */ function _wp_handle_upload( &$file, $overrides, $time, $action ) { // The default error handler. @@ -776,7 +789,15 @@ * @since 2.9.0 as 'wp_handle_upload_prefilter'. * @since 4.0.0 Converted to a dynamic hook with `$action`. * - * @param string[] $file An array of data for the file. Reference to a single element of `$_FILES`. + * @param array $file { + * Reference to a single element from `$_FILES`. + * + * @type string $name The original name of the file on the client machine. + * @type string $type The mime type of the file, if the browser provided this information. + * @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server. + * @type int $size The size, in bytes, of the uploaded file. + * @type int $error The error code associated with this file upload. + * } */ $file = apply_filters( "{$action}_prefilter", $file ); @@ -794,7 +815,15 @@ * * @param array|false $overrides An array of override parameters for this file. Boolean false if none are * provided. @see _wp_handle_upload(). - * @param string[] $file An array of data for the file. Reference to a single element of `$_FILES`. + * @param array $file { + * Reference to a single element from `$_FILES`. + * + * @type string $name The original name of the file on the client machine. + * @type string $type The mime type of the file, if the browser provided this information. + * @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server. + * @type int $size The size, in bytes, of the uploaded file. + * @type int $error The error code associated with this file upload. + * } */ $overrides = apply_filters( "{$action}_overrides", $overrides, $file ); @@ -902,7 +931,7 @@ } if ( ( ! $type || ! $ext ) && ! current_user_can( 'unfiltered_upload' ) ) { - return call_user_func_array( $upload_error_handler, array( &$file, __( 'Sorry, this file type is not permitted for security reasons.' ) ) ); + return call_user_func_array( $upload_error_handler, array( &$file, __( 'Sorry, you are not allowed to upload this file type.' ) ) ); } if ( ! $type ) { @@ -935,7 +964,15 @@ * @since 4.9.0 * * @param mixed $move_new_file If null (default) move the file after the upload. - * @param string[] $file An array of data for a single file. + * @param array $file { + * Reference to a single element from `$_FILES`. + * + * @type string $name The original name of the file on the client machine. + * @type string $type The mime type of the file, if the browser provided this information. + * @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server. + * @type int $size The size, in bytes, of the uploaded file. + * @type int $error The error code associated with this file upload. + * } * @param string $new_file Filename of the newly-uploaded file. * @param string $type Mime type of the newly-uploaded file. */ @@ -1017,12 +1054,12 @@ * * @param array $file Reference to a single element of `$_FILES`. * Call the function once for each uploaded file. + * See _wp_handle_upload() for accepted values. * @param array|false $overrides Optional. An associative array of names => values * to override default variables. Default false. + * See _wp_handle_upload() for accepted values. * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null. - * @return array On success, returns an associative array of file attributes. - * On failure, returns `$overrides['upload_error_handler']( &$file, $message )` - * or `array( 'error' => $message )`. + * @return array See _wp_handle_upload() for return value. */ function wp_handle_upload( &$file, $overrides = false, $time = null ) { /* @@ -1048,12 +1085,12 @@ * * @param array $file Reference to a single element of `$_FILES`. * Call the function once for each uploaded file. + * See _wp_handle_upload() for accepted values. * @param array|false $overrides Optional. An associative array of names => values * to override default variables. Default false. + * See _wp_handle_upload() for accepted values. * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null. - * @return array On success, returns an associative array of file attributes. - * On failure, returns `$overrides['upload_error_handler']( &$file, $message )` - * or `array( 'error' => $message )`. + * @return array See _wp_handle_upload() for return value. */ function wp_handle_sideload( &$file, $overrides = false, $time = null ) { /* @@ -1075,6 +1112,7 @@ * * @since 2.5.0 * @since 5.2.0 Signature Verification with SoftFail was added. + * @since 5.9.0 Support for Content-Disposition filename was added. * * @param string $url The URL of the file to download. * @param int $timeout The timeout for the request to download the file. @@ -1089,7 +1127,11 @@ return new WP_Error( 'http_no_url', __( 'Invalid URL Provided.' ) ); } - $url_filename = basename( parse_url( $url, PHP_URL_PATH ) ); + $url_path = parse_url( $url, PHP_URL_PATH ); + $url_filename = ''; + if ( is_string( $url_path ) && '' !== $url_path ) { + $url_filename = basename( $url_path ); + } $tmpfname = wp_tempnam( $url_filename ); if ( ! $tmpfname ) { @@ -1141,6 +1183,33 @@ return new WP_Error( 'http_404', trim( wp_remote_retrieve_response_message( $response ) ), $data ); } + $content_disposition = wp_remote_retrieve_header( $response, 'content-disposition' ); + + if ( $content_disposition ) { + $content_disposition = strtolower( $content_disposition ); + + if ( 0 === strpos( $content_disposition, 'attachment; filename=' ) ) { + $tmpfname_disposition = sanitize_file_name( substr( $content_disposition, 21 ) ); + } else { + $tmpfname_disposition = ''; + } + + // Potential file name must be valid string. + if ( $tmpfname_disposition && is_string( $tmpfname_disposition ) + && ( 0 === validate_file( $tmpfname_disposition ) ) + ) { + $tmpfname_disposition = dirname( $tmpfname ) . '/' . $tmpfname_disposition; + + if ( rename( $tmpfname, $tmpfname_disposition ) ) { + $tmpfname = $tmpfname_disposition; + } + + if ( ( $tmpfname !== $tmpfname_disposition ) && file_exists( $tmpfname_disposition ) ) { + unlink( $tmpfname_disposition ); + } + } + } + $content_md5 = wp_remote_retrieve_header( $response, 'content-md5' ); if ( $content_md5 ) { @@ -1175,9 +1244,8 @@ // WordPress.org stores signatures at $package_url.sig. $signature_url = false; - $url_path = parse_url( $url, PHP_URL_PATH ); - if ( '.zip' === substr( $url_path, -4 ) || '.tar.gz' === substr( $url_path, -7 ) ) { + if ( is_string( $url_path ) && ( '.zip' === substr( $url_path, -4 ) || '.tar.gz' === substr( $url_path, -7 ) ) ) { $signature_url = str_replace( $url_path, $url_path . '.sig', $url ); } @@ -1206,7 +1274,7 @@ } // Perform the checks. - $signature_verification = verify_file_signature( $tmpfname, $signature, basename( parse_url( $url, PHP_URL_PATH ) ) ); + $signature_verification = verify_file_signature( $tmpfname, $signature, $url_filename ); } if ( is_wp_error( $signature_verification ) ) { @@ -1318,7 +1386,6 @@ ), array( 'php' => phpversion(), - // phpcs:ignore PHPCompatibility.Constants.NewConstants.sodium_library_versionFound 'sodium' => defined( 'SODIUM_LIBRARY_VERSION' ) ? SODIUM_LIBRARY_VERSION : ( defined( 'ParagonIE_Sodium_Compat::VERSION_STRING' ) ? ParagonIE_Sodium_Compat::VERSION_STRING : false ), ) ); @@ -1330,7 +1397,10 @@ // Allow for an old version of Sodium_Compat being loaded before the bundled WordPress one. if ( method_exists( 'ParagonIE_Sodium_Compat', 'runtime_speed_test' ) ) { - // Run `ParagonIE_Sodium_Compat::runtime_speed_test()` in optimized integer mode, as that's what WordPress utilises during signing verifications. + /* + * Run `ParagonIE_Sodium_Compat::runtime_speed_test()` in optimized integer mode, + * as that's what WordPress utilizes during signing verifications. + */ // phpcs:disable WordPress.NamingConventions.ValidVariableName $old_fastMult = ParagonIE_Sodium_Compat::$fastMult; ParagonIE_Sodium_Compat::$fastMult = true; @@ -1351,7 +1421,6 @@ ), array( 'php' => phpversion(), - // phpcs:ignore PHPCompatibility.Constants.NewConstants.sodium_library_versionFound 'sodium' => defined( 'SODIUM_LIBRARY_VERSION' ) ? SODIUM_LIBRARY_VERSION : ( defined( 'ParagonIE_Sodium_Compat::VERSION_STRING' ) ? ParagonIE_Sodium_Compat::VERSION_STRING : false ), 'polyfill_is_fast' => false, 'max_execution_time' => ini_get( 'max_execution_time' ), @@ -1425,7 +1494,6 @@ 'skipped_key' => $skipped_key, 'skipped_sig' => $skipped_signature, 'php' => phpversion(), - // phpcs:ignore PHPCompatibility.Constants.NewConstants.sodium_library_versionFound 'sodium' => defined( 'SODIUM_LIBRARY_VERSION' ) ? SODIUM_LIBRARY_VERSION : ( defined( 'ParagonIE_Sodium_Compat::VERSION_STRING' ) ? ParagonIE_Sodium_Compat::VERSION_STRING : false ), ) ); @@ -1598,7 +1666,7 @@ * Require we have enough space to unzip the file and copy its contents, with a 10% buffer. */ if ( wp_doing_cron() ) { - $available_space = @disk_free_space( WP_CONTENT_DIR ); + $available_space = function_exists( 'disk_free_space' ) ? @disk_free_space( WP_CONTENT_DIR ) : false; if ( $available_space && ( $uncompressed_size * 2.1 ) > $available_space ) { return new WP_Error( @@ -1739,7 +1807,7 @@ * Require we have enough space to unzip the file and copy its contents, with a 10% buffer. */ if ( wp_doing_cron() ) { - $available_space = @disk_free_space( WP_CONTENT_DIR ); + $available_space = function_exists( 'disk_free_space' ) ? @disk_free_space( WP_CONTENT_DIR ) : false; if ( $available_space && ( $uncompressed_size * 2.1 ) > $available_space ) { return new WP_Error( @@ -2078,7 +2146,7 @@ * @since 2.5.0 * @since 4.6.0 The `$context` parameter default changed from `false` to an empty string. * - * @global string $pagenow + * @global string $pagenow The filename of the current screen. * * @param string $form_post The URL to post the form to. * @param string $type Optional. Chosen type of filesystem. Default empty.