Skip to content
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

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

Open
wants to merge 24 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 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
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_image_uploads', true );

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 @@ -135,6 +135,32 @@ public function create_item_permissions_check( $request ) {
);
}

/**
* 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.
*
* @param bool $check_mime Whether to prevent uploads of unsupported image types.
*/
$prevent_unsupported_uploads = apply_filters( 'wp_prevent_unsupported_image_uploads', true );

// If the upload is an image, check if the server can handle the mime type.
$files = $request->get_file_params();
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 @@
*/
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 @@
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 @@
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 @@
}
);
}

/**
* 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.
*

Check failure on line 2584 in tests/phpunit/tests/rest-api/rest-attachments-controller.php

View workflow job for this annotation

GitHub Actions / PHP coding standards / Run coding standards checks

Whitespace found at end of line
* @ticket 61167
*/
public function test_upload_unsupported_image_type_with_filter() {

Check failure on line 2588 in tests/phpunit/tests/rest-api/rest-attachments-controller.php

View workflow job for this annotation

GitHub Actions / PHP coding standards / Run coding standards checks

Whitespace found at end of line
// 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