Skip to content

Error when an (image) upload’s mime type is unsupported #8322

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
2c7ce70
allowedMimeTypes: filter types that are not supported by the server.
adamsilverstein May 8, 2024
93c4813
Cleanup
adamsilverstein May 8, 2024
760f13f
Use Yoda consitionals, I must
adamsilverstein May 8, 2024
a8e1e2e
Merge branch 'trunk' into ticket/61167
adamsilverstein May 8, 2024
67c71f1
Merge branch 'trunk' into ticket/61167
adamsilverstein Feb 14, 2025
a510e39
revert previous version
adamsilverstein Feb 14, 2025
ff2e0c0
Error when an (image) upload’s mime type is unsupported
adamsilverstein Feb 14, 2025
0bfaf95
phpcbf
adamsilverstein Feb 14, 2025
86e9f38
Customize: Accessibility: Restore heading semantics in sections.
joedolson Feb 14, 2025
27c455a
Coding Standards: Use strict comparison in `wp_get_comment_status()`.
SergeyBiryukov Feb 15, 2025
c7c17c3
Coding Standards: Use strict comparison in `pingback()`.
SergeyBiryukov Feb 16, 2025
fe8630b
Security: Switch to using bcrypt for hashing user passwords and BLAKE…
johnbillion Feb 17, 2025
18910a5
Docs: Correct formatting for `get_the_date` and `get_the_time` DocBlo…
SergeyBiryukov Feb 17, 2025
738772d
General: Fix `force_ssl_admin()` to always return bool.
swissspidy Feb 17, 2025
a88eff4
Security: Remove use of `innerHTML` in the `the_block_template_skip_l…
johnbillion Feb 17, 2025
eb41d06
Test uploading unsupported image type
adamsilverstein Feb 17, 2025
595a95d
remove namespace copied from gutenberg PR
adamsilverstein Feb 17, 2025
29cfa8c
Merge branch 'trunk' into ticket/61167
adamsilverstein Feb 17, 2025
36c52a5
phpcbf
adamsilverstein Feb 17, 2025
a14653d
ensure file type set before using
adamsilverstein Feb 17, 2025
d8db732
Add and test new wp_prevent_unsupported_image_uploads filter
adamsilverstein Feb 17, 2025
60639c5
Add wp_prevent_unsupported_image_uploads filter to media.php
adamsilverstein Feb 20, 2025
c22a952
Cleanup
adamsilverstein Feb 20, 2025
305352b
phpcbf
adamsilverstein Feb 20, 2025
d15c5f7
Merge branch 'trunk' into ticket/61167
adamsilverstein Mar 5, 2025
54f2a7d
Merge branch 'ticket/61167' of github.com:adamsilverstein/wordpress-d…
adamsilverstein Mar 5, 2025
8969678
phpcbf
adamsilverstein Mar 5, 2025
036f1a1
Merge branch 'trunk' into ticket/61167
adamsilverstein Mar 17, 2025
cdb9d8b
Add missing `@since` tag
adamsilverstein Mar 17, 2025
d9ca746
Add mime type as a second parameter and rename filter
adamsilverstein Mar 17, 2025
d7c5b64
update doc block
adamsilverstein Mar 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions src/wp-admin/includes/media.php
Original file line number Diff line number Diff line change
Expand Up @@ -2194,14 +2194,19 @@ function media_upload_form( $errors = null ) {
$plupload_init['multi_selection'] = false;
}

// Check if WebP images can be edited.
if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/webp' ) ) ) {
$plupload_init['webp_upload_error'] = true;
}
/** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php */
$prevent_unsupported_uploads = apply_filters( 'wp_prevent_unsupported_mime_type_uploads', true, null );

if ( $prevent_unsupported_uploads ) {
// Check if WebP images can be edited.
if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/webp' ) ) ) {
$plupload_init['webp_upload_error'] = true;
}

// Check if AVIF images can be edited.
if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/avif' ) ) ) {
$plupload_init['avif_upload_error'] = true;
// Check if AVIF images can be edited.
if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/avif' ) ) ) {
$plupload_init['avif_upload_error'] = true;
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,36 @@ public function create_item_permissions_check( $request ) {
array( 'status' => rest_authorization_required_code() )
);
}
$files = $request->get_file_params();

/**
* Filter whether the server should prevent uploads for image types it doesn't support. Default true.
*
* Developers can use this filter to enable uploads of certain image types. By default image types that are not
* supported by the server are prevented from being uploaded.
*
* @since 6.8.0
*
* @param bool $check_mime Whether to prevent uploads of unsupported image types.
* @param string|null $mime_type The mime type of the file being uploaded (if available).
*/
$prevent_unsupported_uploads = apply_filters( 'wp_prevent_unsupported_mime_type_uploads', true, isset( $files['file']['type'] ) ? $files['file']['type'] : null );

// If the upload is an image, check if the server can handle the mime type.
if (
$prevent_unsupported_uploads &&
isset( $files['file']['type'] ) &&
str_starts_with( $files['file']['type'], 'image/' )
) {
// Check if the image editor supports the type.
if ( ! wp_image_editor_supports( array( 'mime_type' => $files['file']['type'] ) ) ) {
return new WP_Error(
'rest_upload_image_type_not_supported',
__( 'The web server cannot generate responsive image sizes for this image. Convert it to JPEG or PNG before uploading.' ),
array( 'status' => 400 )
);
}
}

return true;
}
Expand Down
62 changes: 62 additions & 0 deletions tests/phpunit/tests/rest-api/rest-attachments-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
*/
private static $test_file2;

/**
* @var string The path to the AVIF test image.
*/
private static $test_avif_file;

/**
* @var array The recorded posts query clauses.
*/
Expand Down Expand Up @@ -72,6 +77,9 @@ public static function wpTearDownAfterClass() {
if ( file_exists( self::$test_file2 ) ) {
unlink( self::$test_file2 );
}
if ( file_exists( self::$test_avif_file ) ) {
unlink( self::$test_avif_file );
}

self::delete_user( self::$editor_id );
self::delete_user( self::$author_id );
Expand Down Expand Up @@ -101,6 +109,12 @@ public function set_up() {
copy( $orig_file2, self::$test_file2 );
}

$orig_avif_file = DIR_TESTDATA . '/images/avif-lossy.avif';
self::$test_avif_file = get_temp_dir() . 'avif-lossy.avif';
if ( ! file_exists( self::$test_avif_file ) ) {
copy( $orig_avif_file, self::$test_avif_file );
}

add_filter( 'rest_pre_dispatch', array( $this, 'wpSetUpBeforeRequest' ), 10, 3 );
add_filter( 'posts_clauses', array( $this, 'save_posts_clauses' ), 10, 2 );
}
Expand Down Expand Up @@ -2541,4 +2555,52 @@ static function () {
}
);
}

/**
* Test that uploading unsupported image types throws a `rest_upload_image_type_not_supported` error.
*
* @ticket 61167
*/
public function test_upload_unsupported_image_type() {

// Only run this test when the editor doesn't support AVIF.
if ( wp_image_editor_supports( array( 'AVIF' ) ) ) {
$this->markTestSkipped( 'The image editor suppports AVIF.' );
}

$request = new WP_REST_Request( 'POST', '/wp/v2/media' );

wp_set_current_user( self::$author_id );
$request->set_header( 'Content-Type', 'image/avif' );
$request->set_header( 'Content-Disposition', 'attachment; filename=avif-lossy.avif' );
$request->set_body( file_get_contents( self::$test_avif_file ) );
$response = rest_get_server()->dispatch( $request );

$this->assertErrorResponse( 'rest_upload_image_type_not_supported', $response, 400 );
}

/**
* Test that the `wp_prevent_unsupported_image_uploads` filter enables uploading of unsupported image types.
*
* @ticket 61167
*/
public function test_upload_unsupported_image_type_with_filter() {

// Only run this test when the editor doesn't support AVIF.
if ( wp_image_editor_supports( array( 'AVIF' ) ) ) {
$this->markTestSkipped( 'The image editor suppports AVIF.' );
}

add_filter( 'wp_prevent_unsupported_image_uploads', '__return_false' );

$request = new WP_REST_Request( 'POST', '/wp/v2/media' );

wp_set_current_user( self::$author_id );
$request->set_header( 'Content-Type', 'image/avif' );
$request->set_header( 'Content-Disposition', 'attachment; filename=avif-lossy.avif' );
$request->set_body( file_get_contents( self::$test_avif_file ) );
$response = rest_get_server()->dispatch( $request );

$this->assertSame( 201, $response->get_status() );
}
}
Loading