Make WordPress Core

Changeset 60084


Ignore:
Timestamp:
03/25/2025 02:04:47 PM (7 weeks 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.