Make WordPress Core

Changeset 60084


Ignore:
Timestamp:
03/25/2025 02:04:47 PM (17 months ago)
Author:
adamsilverstein
Message:

Media: prevent uploading image types the server doesn’t support.

Normalize behavior between uploading in the media library and uploading directly to the block editor. Now, when uploading an image with a mime type the server does not support (either in the media library or the block editor), the user will see an error message “This image cannot be processed by the web server. Convert it to JPEG or PNG before uploading”.

Alos, add a new filter wp_prevent_unsupported_mime_type_uploads which determines whether the server should prevent uploads for image types it doesn't support. The default value is true and the filter also receives the uploaded image mime type.

Props: joomskys, adamsilverstein, azaozz, swissspidy, joemcgill, flixos90, audrasjb. 

Fixes #61167

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/media.php

    r59767 r60084  
    21952195        }
    21962196
    2197         // Check if WebP images can be edited.
    2198         if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/webp' ) ) ) {
    2199                 $plupload_init['webp_upload_error'] = true;
    2200         }
    2201 
    2202         // Check if AVIF images can be edited.
    2203         if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/avif' ) ) ) {
    2204                 $plupload_init['avif_upload_error'] = true;
     2197        /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php */
     2198        $prevent_unsupported_uploads = apply_filters( 'wp_prevent_unsupported_mime_type_uploads', true, null );
     2199
     2200        if ( $prevent_unsupported_uploads ) {
     2201                // Check if WebP images can be edited.
     2202                if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/webp' ) ) ) {
     2203                        $plupload_init['webp_upload_error'] = true;
     2204                }
     2205
     2206                // Check if AVIF images can be edited.
     2207                if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/avif' ) ) ) {
     2208                        $plupload_init['avif_upload_error'] = true;
     2209                }
    22052210        }
    22062211
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php

    r58865 r60084  
    134134                                array( 'status' => rest_authorization_required_code() )
    135135                        );
     136                }
     137                $files = $request->get_file_params();
     138
     139                /**
     140                 * Filter whether the server should prevent uploads for image types it doesn't support. Default true.
     141                 *
     142                 * Developers can use this filter to enable uploads of certain image types. By default image types that are not
     143                 * supported by the server are prevented from being uploaded.
     144                 *
     145                 * @since 6.8.0
     146                 *
     147                 * @param bool        $check_mime Whether to prevent uploads of unsupported image types.
     148                 * @param string|null $mime_type  The mime type of the file being uploaded (if available).
     149                 */
     150                $prevent_unsupported_uploads = apply_filters( 'wp_prevent_unsupported_mime_type_uploads', true, isset( $files['file']['type'] ) ? $files['file']['type'] : null );
     151
     152                // If the upload is an image, check if the server can handle the mime type.
     153                if (
     154                        $prevent_unsupported_uploads &&
     155                        isset( $files['file']['type'] ) &&
     156                        str_starts_with( $files['file']['type'], 'image/' )
     157                ) {
     158                        // Check if the image editor supports the type.
     159                        if ( ! wp_image_editor_supports( array( 'mime_type' => $files['file']['type'] ) ) ) {
     160                                return new WP_Error(
     161                                        'rest_upload_image_type_not_supported',
     162                                        __( 'The web server cannot generate responsive image sizes for this image. Convert it to JPEG or PNG before uploading.' ),
     163                                        array( 'status' => 400 )
     164                                );
     165                        }
    136166                }
    137167
  • trunk/tests/phpunit/tests/rest-api/rest-attachments-controller.php

    r60068 r60084  
    2929
    3030        /**
     31         * @var string The path to the AVIF test image.
     32         */
     33        private static $test_avif_file;
     34
     35        /**
    3136         * @var array The recorded posts query clauses.
    3237         */
     
    7378                        unlink( self::$test_file2 );
    7479                }
     80                if ( file_exists( self::$test_avif_file ) ) {
     81                        unlink( self::$test_avif_file );
     82                }
    7583
    7684                self::delete_user( self::$editor_id );
     
    100108                if ( ! file_exists( self::$test_file2 ) ) {
    101109                        copy( $orig_file2, self::$test_file2 );
     110                }
     111
     112                $orig_avif_file       = DIR_TESTDATA . '/images/avif-lossy.avif';
     113                self::$test_avif_file = get_temp_dir() . 'avif-lossy.avif';
     114                if ( ! file_exists( self::$test_avif_file ) ) {
     115                        copy( $orig_avif_file, self::$test_avif_file );
    102116                }
    103117
     
    25422556                );
    25432557        }
     2558
     2559        /**
     2560         * Test that uploading unsupported image types throws a `rest_upload_image_type_not_supported` error.
     2561         *
     2562         * @ticket 61167
     2563         */
     2564        public function test_upload_unsupported_image_type() {
     2565
     2566                // Only run this test when the editor doesn't support AVIF.
     2567                if ( wp_image_editor_supports( array( 'AVIF' ) ) ) {
     2568                        $this->markTestSkipped( 'The image editor suppports AVIF.' );
     2569                }
     2570
     2571                $request = new WP_REST_Request( 'POST', '/wp/v2/media' );
     2572
     2573                wp_set_current_user( self::$author_id );
     2574                $request->set_header( 'Content-Type', 'image/avif' );
     2575                $request->set_header( 'Content-Disposition', 'attachment; filename=avif-lossy.avif' );
     2576                $request->set_body( file_get_contents( self::$test_avif_file ) );
     2577                $response = rest_get_server()->dispatch( $request );
     2578
     2579                $this->assertErrorResponse( 'rest_upload_image_type_not_supported', $response, 400 );
     2580        }
     2581
     2582        /**
     2583         * Test that the `wp_prevent_unsupported_image_uploads` filter enables uploading of unsupported image types.
     2584         *
     2585         * @ticket 61167
     2586         */
     2587        public function test_upload_unsupported_image_type_with_filter() {
     2588
     2589                // Only run this test when the editor doesn't support AVIF.
     2590                if ( wp_image_editor_supports( array( 'AVIF' ) ) ) {
     2591                        $this->markTestSkipped( 'The image editor suppports AVIF.' );
     2592                }
     2593
     2594                add_filter( 'wp_prevent_unsupported_image_uploads', '__return_false' );
     2595
     2596                $request = new WP_REST_Request( 'POST', '/wp/v2/media' );
     2597
     2598                wp_set_current_user( self::$author_id );
     2599                $request->set_header( 'Content-Type', 'image/avif' );
     2600                $request->set_header( 'Content-Disposition', 'attachment; filename=avif-lossy.avif' );
     2601                $request->set_body( file_get_contents( self::$test_avif_file ) );
     2602                $response = rest_get_server()->dispatch( $request );
     2603
     2604                $this->assertSame( 201, $response->get_status() );
     2605        }
    25442606}
Note: See TracChangeset for help on using the changeset viewer.