-
Notifications
You must be signed in to change notification settings - Fork 3.5k
REST API: Add dimension validation to sideload endpoint #11100
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
base: trunk
Are you sure you want to change the base?
Changes from 26 commits
0229c11
3832e25
0dcab83
2fe2162
133ec0f
a868b57
e5baa99
5405e38
02a9794
458d94c
978ac79
eeca10e
ae029f1
a484e07
fbe7458
b30edb6
56c05e4
d558ceb
851f14a
6a95756
2cb2454
5474fcd
394bec7
0cec0b0
2566f7c
3a17ad8
5b3d79c
c57a975
642209e
5634d1d
c7ea9f6
5a46435
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1968,6 +1968,107 @@ public function sideload_item_permissions_check( $request ) { | |
| return $this->edit_media_item_permissions_check( $request ); | ||
| } | ||
|
|
||
| /** | ||
| * Validates that uploaded image dimensions are appropriate for the specified image size. | ||
| * | ||
| * @since 7.0.0 | ||
| * | ||
| * @param int $width Uploaded image width. | ||
| * @param int $height Uploaded image height. | ||
| * @param string $image_size The target image size name. | ||
| * @param int $attachment_id The attachment ID. | ||
| * @return true|WP_Error True if valid, WP_Error if invalid. | ||
| */ | ||
| private function validate_image_dimensions( int $width, int $height, string $image_size, int $attachment_id ) { | ||
| // All image sizes require positive dimensions. | ||
| if ( $width <= 0 || $height <= 0 ) { | ||
| return new WP_Error( | ||
| 'rest_upload_invalid_dimensions', | ||
| __( 'Uploaded image must have positive dimensions.' ), | ||
| array( 'status' => 400 ) | ||
| ); | ||
| } | ||
|
|
||
| // 'original' size: should match original attachment dimensions. | ||
| if ( 'original' === $image_size ) { | ||
| $metadata = wp_get_attachment_metadata( $attachment_id, true ); | ||
| if ( is_array( $metadata ) && isset( $metadata['width'], $metadata['height'] ) ) { | ||
| $expected_width = (int) $metadata['width']; | ||
| $expected_height = (int) $metadata['height']; | ||
|
|
||
| if ( $width !== $expected_width || $height !== $expected_height ) { | ||
| return new WP_Error( | ||
| 'rest_upload_dimension_mismatch', | ||
| sprintf( | ||
| /* translators: 1: Actual width, 2: actual height, 3: expected width, 4: expected height. */ | ||
| __( 'Uploaded image dimensions (%1$dx%2$d) do not match original image dimensions (%3$dx%4$d).' ), | ||
| $width, | ||
| $height, | ||
| $expected_width, | ||
| $expected_height | ||
| ), | ||
| array( 'status' => 400 ) | ||
| ); | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| // 'full' size (PDF thumbnails) and 'scaled': no further constraints. | ||
| if ( 'full' === $image_size || 'scaled' === $image_size ) { | ||
| return true; | ||
| } | ||
|
|
||
| // Regular image sizes: validate against registered size constraints. | ||
| $registered_sizes = wp_get_registered_image_subsizes(); | ||
|
|
||
| if ( ! isset( $registered_sizes[ $image_size ] ) ) { | ||
| return new WP_Error( | ||
| 'rest_upload_unknown_size', | ||
| __( 'Unknown image size.' ), | ||
| array( 'status' => 400 ) | ||
| ); | ||
| } | ||
|
|
||
| $size_data = $registered_sizes[ $image_size ]; | ||
| $max_width = (int) $size_data['width']; | ||
| $max_height = (int) $size_data['height']; | ||
|
|
||
| // Validate dimensions don't exceed the registered size maximums. | ||
| // Allow 1px tolerance for rounding differences. | ||
| $tolerance = 1; | ||
|
|
||
| if ( $max_width > 0 && $width > $max_width + $tolerance ) { | ||
| return new WP_Error( | ||
| 'rest_upload_dimension_mismatch', | ||
| sprintf( | ||
| /* translators: 1: Image size name, 2: maximum width, 3: actual width. */ | ||
| __( 'Uploaded image width (%3$d) exceeds maximum for "%1$s" size (%2$d).' ), | ||
| $image_size, | ||
| $max_width, | ||
| $width | ||
| ), | ||
| array( 'status' => 400 ) | ||
| ); | ||
| } | ||
|
|
||
| if ( $max_height > 0 && $height > $max_height + $tolerance ) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see two times for this Are these 2 the sole ones? Or will others come?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good call — these are the only two, but extracted into a private |
||
| return new WP_Error( | ||
| 'rest_upload_dimension_mismatch', | ||
| sprintf( | ||
| /* translators: 1: Image size name, 2: maximum height, 3: actual height. */ | ||
| __( 'Uploaded image height (%3$d) exceeds maximum for "%1$s" size (%2$d).' ), | ||
| $image_size, | ||
| $max_height, | ||
| $height | ||
| ), | ||
| array( 'status' => 400 ) | ||
| ); | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| /** | ||
| * Side-loads a media file without creating a new attachment. | ||
| * | ||
|
|
@@ -2047,6 +2148,18 @@ public function sideload_item( WP_REST_Request $request ) { | |
|
|
||
| $image_size = $request['image_size']; | ||
|
|
||
| $size = wp_getimagesize( $path ); | ||
|
|
||
| // Validate dimensions match expected size. | ||
| if ( is_array( $size ) ) { | ||
| $validation = $this->validate_image_dimensions( $size[0], $size[1], $image_size, $attachment_id ); | ||
| if ( is_wp_error( $validation ) ) { | ||
| // Clean up the uploaded file. | ||
| wp_delete_file( $path ); | ||
| return $validation; | ||
| } | ||
| } | ||
|
|
||
| $metadata = wp_get_attachment_metadata( $attachment_id, true ); | ||
|
|
||
| if ( ! $metadata ) { | ||
|
|
@@ -2100,8 +2213,6 @@ public function sideload_item( WP_REST_Request $request ) { | |
| } else { | ||
| $metadata['sizes'] = $metadata['sizes'] ?? array(); | ||
|
|
||
| $size = wp_getimagesize( $path ); | ||
|
|
||
|
adamsilverstein marked this conversation as resolved.
|
||
| $metadata['sizes'][ $image_size ] = array( | ||
| 'width' => $size ? $size[0] : 0, | ||
| 'height' => $size ? $size[1] : 0, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
have you considered
in_array()instead of||?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call — switched to
in_array( $image_size, array( 'full', 'scaled' ), true )in c57a975.