Changeset 62619 for trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php
- Timestamp:
- 07/01/2026 09:32:34 PM (3 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php
r62617 r62619 2168 2168 2169 2169 /** 2170 * Validates that uploaded image dimensions are appropriate for the specified image size. 2171 * 2172 * @since 7.1.0 2173 * 2174 * @param int $width Uploaded image width. 2175 * @param int $height Uploaded image height. 2176 * @param string $image_size The target image size name. 2177 * @param int $attachment_id The attachment ID. 2178 * @return true|WP_Error True if valid, WP_Error if invalid. 2179 */ 2180 private function validate_image_dimensions( int $width, int $height, string $image_size, int $attachment_id ) { 2181 // All image sizes require positive dimensions. 2182 if ( $width <= 0 || $height <= 0 ) { 2183 return new WP_Error( 2184 'rest_upload_invalid_dimensions', 2185 __( 'Uploaded image must have positive dimensions.' ), 2186 array( 'status' => 400 ) 2187 ); 2188 } 2189 2190 // 'original' size: should match original attachment dimensions. 2191 if ( 'original' === $image_size ) { 2192 $metadata = wp_get_attachment_metadata( $attachment_id, true ); 2193 if ( is_array( $metadata ) && isset( $metadata['width'], $metadata['height'] ) ) { 2194 $expected_width = (int) $metadata['width']; 2195 $expected_height = (int) $metadata['height']; 2196 2197 if ( $width !== $expected_width || $height !== $expected_height ) { 2198 return new WP_Error( 2199 'rest_upload_dimension_mismatch', 2200 sprintf( 2201 /* translators: 1: Actual width, 2: actual height, 3: expected width, 4: expected height. */ 2202 __( 'Uploaded image dimensions (%1$dx%2$d) do not match original image dimensions (%3$dx%4$d).' ), 2203 $width, 2204 $height, 2205 $expected_width, 2206 $expected_height 2207 ), 2208 array( 'status' => 400 ) 2209 ); 2210 } 2211 } 2212 return true; 2213 } 2214 2215 // 'full' size (PDF thumbnails) and 'scaled': no further constraints. 2216 if ( in_array( $image_size, array( 'full', 'scaled' ), true ) ) { 2217 return true; 2218 } 2219 2220 // Regular image sizes: validate against registered size constraints. 2221 $registered_sizes = wp_get_registered_image_subsizes(); 2222 2223 if ( ! isset( $registered_sizes[ $image_size ] ) ) { 2224 return new WP_Error( 2225 'rest_upload_unknown_size', 2226 __( 'Unknown image size.' ), 2227 array( 'status' => 400 ) 2228 ); 2229 } 2230 2231 $size_data = $registered_sizes[ $image_size ]; 2232 $max_width = (int) $size_data['width']; 2233 $max_height = (int) $size_data['height']; 2234 2235 // Validate dimensions don't exceed the registered size maximums. 2236 // Allow 1px tolerance for rounding differences. 2237 $tolerance = 1; 2238 2239 if ( $this->dimension_exceeds_max( $width, $max_width, $tolerance ) ) { 2240 return new WP_Error( 2241 'rest_upload_dimension_mismatch', 2242 sprintf( 2243 /* translators: 1: Image size name, 2: maximum width, 3: actual width. */ 2244 __( 'Uploaded image width (%3$d) exceeds maximum for "%1$s" size (%2$d).' ), 2245 $image_size, 2246 $max_width, 2247 $width 2248 ), 2249 array( 'status' => 400 ) 2250 ); 2251 } 2252 2253 if ( $this->dimension_exceeds_max( $height, $max_height, $tolerance ) ) { 2254 return new WP_Error( 2255 'rest_upload_dimension_mismatch', 2256 sprintf( 2257 /* translators: 1: Image size name, 2: maximum height, 3: actual height. */ 2258 __( 'Uploaded image height (%3$d) exceeds maximum for "%1$s" size (%2$d).' ), 2259 $image_size, 2260 $max_height, 2261 $height 2262 ), 2263 array( 'status' => 400 ) 2264 ); 2265 } 2266 2267 return true; 2268 } 2269 2270 /** 2271 * Checks whether a dimension exceeds the maximum allowed value. 2272 * 2273 * A maximum of zero means the dimension is unconstrained. 2274 * 2275 * @since 7.1.0 2276 * 2277 * @param int $value The actual dimension in pixels. 2278 * @param int $max The maximum allowed dimension in pixels. Zero means no constraint. 2279 * @param int $tolerance Pixel tolerance allowed for rounding differences. 2280 * @return bool True if the value exceeds the maximum plus tolerance. 2281 */ 2282 private function dimension_exceeds_max( int $value, int $max, int $tolerance ): bool { 2283 return $max > 0 && $value > $max + $tolerance; 2284 } 2285 2286 /** 2170 2287 * Side-loads a media file without creating a new attachment. 2171 2288 * … … 2244 2361 $path = $file['file']; 2245 2362 2363 /** @var non-empty-string $image_size */ 2246 2364 $image_size = $request['image_size']; 2365 2366 /* 2367 * Validate raster sub-sizes before storing them. Source-format companion 2368 * originals (e.g. a HEIC or JXL kept next to its JPEG derivative) are 2369 * exempt: their dimensions are neither validated nor recorded, and the 2370 * source format may not be readable by wp_getimagesize() at all. 2371 */ 2372 if ( self::IMAGE_SIZE_SOURCE_ORIGINAL !== $image_size ) { 2373 /* 2374 * Read the dimensions up front. A file whose dimensions cannot be 2375 * read is corrupted or an unsupported format and must be rejected 2376 * rather than silently stored with zero dimensions. 2377 */ 2378 $size = wp_getimagesize( $path ); 2379 2380 if ( ! $size ) { 2381 // Clean up the uploaded file. 2382 wp_delete_file( $path ); 2383 return new WP_Error( 2384 'rest_upload_invalid_image', 2385 __( 'Could not read image dimensions. The file may be corrupted or an unsupported format.' ), 2386 array( 'status' => 400 ) 2387 ); 2388 } 2389 2390 /* 2391 * Validate the dimensions match the expected size. An array 2392 * $image_size represents multiple registered sizes sharing a single 2393 * file; those are handled by the per-size branch below, so only 2394 * scalar sizes are validated here. 2395 */ 2396 if ( ! is_array( $image_size ) ) { 2397 $validation = $this->validate_image_dimensions( $size[0], $size[1], $image_size, $attachment_id ); 2398 if ( is_wp_error( $validation ) ) { 2399 // Clean up the uploaded file. 2400 wp_delete_file( $path ); 2401 return $validation; 2402 } 2403 } 2404 } 2247 2405 2248 2406 // Build sub-size data to return to the client.
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)