Changeset 51706
- Timestamp:
- 08/31/2021 11:56:11 PM (3 years ago)
- Location:
- branches/5.8
- Files:
-
- 4 edited
- 4 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/5.8
-
branches/5.8/src/wp-includes/class-wp-image-editor.php
r51444 r51706 592 592 */ 593 593 protected static function get_extension( $mime_type = null ) { 594 $extensions = explode( '|', array_search( $mime_type, wp_get_mime_types(), true ) ); 595 596 if ( empty( $extensions[0] ) ) { 594 if ( empty( $mime_type ) ) { 597 595 return false; 598 596 } 599 597 600 return $extensions[0];598 return wp_get_default_extension_for_mime_type( $mime_type ); 601 599 } 602 600 } -
branches/5.8/src/wp-includes/functions.php
r51223 r51706 2486 2486 $ext2 = null; 2487 2487 2488 // Initialize vars used in the wp_unique_filename filter. 2489 $number = ''; 2490 $alt_filenames = array(); 2491 2488 2492 // Separate the filename into a name and extension. 2489 2493 $ext = pathinfo( $filename, PATHINFO_EXTENSION ); … … 2506 2510 $filename = call_user_func( $unique_filename_callback, $dir, $name, $ext ); 2507 2511 } else { 2508 $number = ''; 2509 $fname = pathinfo( $filename, PATHINFO_FILENAME ); 2512 $fname = pathinfo( $filename, PATHINFO_FILENAME ); 2510 2513 2511 2514 // Always append a number to file names that can potentially match image sub-size file names. … … 2517 2520 } 2518 2521 2519 // Change '.ext' to lower case. 2520 if ( $ext && strtolower( $ext ) != $ext ) { 2521 $ext2 = strtolower( $ext ); 2522 $filename2 = preg_replace( '|' . preg_quote( $ext ) . '$|', $ext2, $filename ); 2523 2524 // Check for both lower and upper case extension or image sub-sizes may be overwritten. 2525 while ( file_exists( $dir . "/{$filename}" ) || file_exists( $dir . "/{$filename2}" ) ) { 2526 $new_number = (int) $number + 1; 2527 $filename = str_replace( array( "-{$number}{$ext}", "{$number}{$ext}" ), "-{$new_number}{$ext}", $filename ); 2528 $filename2 = str_replace( array( "-{$number}{$ext2}", "{$number}{$ext2}" ), "-{$new_number}{$ext2}", $filename2 ); 2529 $number = $new_number; 2522 // Get the mime type. Uploaded files were already checked with wp_check_filetype_and_ext() 2523 // in _wp_handle_upload(). Using wp_check_filetype() would be sufficient here. 2524 $file_type = wp_check_filetype( $filename ); 2525 $mime_type = $file_type['type']; 2526 2527 $is_image = ( ! empty( $mime_type ) && 0 === strpos( $mime_type, 'image/' ) ); 2528 $upload_dir = wp_get_upload_dir(); 2529 $lc_filename = null; 2530 2531 $lc_ext = strtolower( $ext ); 2532 $_dir = trailingslashit( $dir ); 2533 2534 // If the extension is uppercase add an alternate file name with lowercase extension. Both need to be tested 2535 // for uniqueness as the extension will be changed to lowercase for better compatibility with different filesystems. 2536 // Fixes an inconsistency in WP < 2.9 where uppercase extensions were allowed but image sub-sizes were created with 2537 // lowercase extensions. 2538 if ( $ext && $lc_ext !== $ext ) { 2539 $lc_filename = preg_replace( '|' . preg_quote( $ext ) . '$|', $lc_ext, $filename ); 2540 } 2541 2542 // Increment the number added to the file name if there are any files in $dir whose names match one of the 2543 // possible name variations. 2544 while ( file_exists( $_dir . $filename ) || ( $lc_filename && file_exists( $_dir . $lc_filename ) ) ) { 2545 $new_number = (int) $number + 1; 2546 2547 if ( $lc_filename ) { 2548 $lc_filename = str_replace( array( "-{$number}{$lc_ext}", "{$number}{$lc_ext}" ), "-{$new_number}{$lc_ext}", $lc_filename ); 2530 2549 } 2531 2550 2532 $filename = $filename2; 2533 } else { 2534 while ( file_exists( $dir . "/{$filename}" ) ) { 2535 $new_number = (int) $number + 1; 2536 2537 if ( '' === "{$number}{$ext}" ) { 2538 $filename = "{$filename}-{$new_number}"; 2539 } else { 2540 $filename = str_replace( array( "-{$number}{$ext}", "{$number}{$ext}" ), "-{$new_number}{$ext}", $filename ); 2541 } 2542 2543 $number = $new_number; 2551 if ( '' === "{$number}{$ext}" ) { 2552 $filename = "{$filename}-{$new_number}"; 2553 } else { 2554 $filename = str_replace( array( "-{$number}{$ext}", "{$number}{$ext}" ), "-{$new_number}{$ext}", $filename ); 2544 2555 } 2556 2557 $number = $new_number; 2558 } 2559 2560 // Change the extension to lowercase if needed. 2561 if ( $lc_filename ) { 2562 $filename = $lc_filename; 2545 2563 } 2546 2564 2547 2565 // Prevent collisions with existing file names that contain dimension-like strings 2548 2566 // (whether they are subsizes or originals uploaded prior to #42437). 2549 $upload_dir = wp_get_upload_dir(); 2567 2568 $files = array(); 2569 $count = 10000; 2550 2570 2551 2571 // The (resized) image files would have name and extension, and will be in the uploads dir. … … 2577 2597 2578 2598 if ( ! empty( $files ) ) { 2579 // The extension case may have changed above. 2580 $new_ext = ! empty( $ext2 ) ? $ext2 : $ext; 2599 $count = count( $files ); 2581 2600 2582 2601 // Ensure this never goes into infinite loop 2583 2602 // as it uses pathinfo() and regex in the check, but string replacement for the changes. 2584 $count = count( $files ); 2585 $i = 0; 2603 $i = 0; 2586 2604 2587 2605 while ( $i <= $count && _wp_check_existing_file_names( $filename, $files ) ) { 2588 2606 $new_number = (int) $number + 1; 2589 $filename = str_replace( array( "-{$number}{$new_ext}", "{$number}{$new_ext}" ), "-{$new_number}{$new_ext}", $filename ); 2590 $number = $new_number; 2607 2608 // If $ext is uppercase it was replaced with the lowercase version after the previous loop. 2609 $filename = str_replace( array( "-{$number}{$lc_ext}", "{$number}{$lc_ext}" ), "-{$new_number}{$lc_ext}", $filename ); 2610 2611 $number = $new_number; 2591 2612 $i++; 2592 2613 } 2593 2614 } 2594 2615 } 2616 2617 // Check if an image will be converted after uploading or some existing images sub-sizes file names may conflict 2618 // when regenerated. If yes, ensure the new file name will be unique and will produce unique sub-sizes. 2619 if ( $is_image ) { 2620 $output_formats = apply_filters( 'image_editor_output_format', array(), $_dir . $filename, $mime_type ); 2621 $alt_types = array(); 2622 2623 if ( ! empty( $output_formats[ $mime_type ] ) ) { 2624 // The image will be converted to this format/mime type. 2625 $alt_mime_type = $output_formats[ $mime_type ]; 2626 2627 // Other types of images whose names may conflict if their sub-sizes are regenerated. 2628 $alt_types = array_keys( array_intersect( $output_formats, array( $mime_type, $alt_mime_type ) ) ); 2629 $alt_types[] = $alt_mime_type; 2630 } elseif ( ! empty( $output_formats ) ) { 2631 $alt_types = array_keys( array_intersect( $output_formats, array( $mime_type ) ) ); 2632 } 2633 2634 // Remove duplicates and the original mime type. It will be added later if needed. 2635 $alt_types = array_unique( array_diff( $alt_types, array( $mime_type ) ) ); 2636 2637 foreach ( $alt_types as $alt_type ) { 2638 $alt_ext = wp_get_default_extension_for_mime_type( $alt_type ); 2639 2640 if ( ! $alt_ext ) { 2641 continue; 2642 } 2643 2644 $alt_ext = ".{$alt_ext}"; 2645 $alt_filename = preg_replace( '|' . preg_quote( $lc_ext ) . '$|', $alt_ext, $filename ); 2646 2647 $alt_filenames[ $alt_ext ] = $alt_filename; 2648 } 2649 2650 if ( ! empty( $alt_filenames ) ) { 2651 // Add the original filename. It needs to be checked again together with the alternate filenames 2652 // when $number is incremented. 2653 $alt_filenames[ $lc_ext ] = $filename; 2654 2655 // Ensure no infinite loop. 2656 $i = 0; 2657 2658 while ( $i <= $count && _wp_check_alternate_file_names( $alt_filenames, $_dir, $files ) ) { 2659 $new_number = (int) $number + 1; 2660 2661 foreach ( $alt_filenames as $alt_ext => $alt_filename ) { 2662 $alt_filenames[ $alt_ext ] = str_replace( array( "-{$number}{$alt_ext}", "{$number}{$alt_ext}" ), "-{$new_number}{$alt_ext}", $alt_filename ); 2663 } 2664 2665 // Also update the $number in (the output) $filename. 2666 // If the extension was uppercase it was already replaced with the lowercase version. 2667 $filename = str_replace( array( "-{$number}{$lc_ext}", "{$number}{$lc_ext}" ), "-{$new_number}{$lc_ext}", $filename ); 2668 2669 $number = $new_number; 2670 $i++; 2671 } 2672 } 2673 } 2595 2674 } 2596 2675 … … 2599 2678 * 2600 2679 * @since 4.5.0 2680 * @since 5.8.1 The `$alt_filenames` and `$number` parameters were added. 2601 2681 * 2602 2682 * @param string $filename Unique file name. … … 2604 2684 * @param string $dir Directory path. 2605 2685 * @param callable|null $unique_filename_callback Callback function that generates the unique file name. 2686 * @param string[] $alt_filenames Array of alternate file names that were checked for collisions. 2687 * @param int|string $number The highest number that was used to make the file name unique 2688 * or an empty string if unused. 2606 2689 */ 2607 return apply_filters( 'wp_unique_filename', $filename, $ext, $dir, $unique_filename_callback ); 2690 return apply_filters( 'wp_unique_filename', $filename, $ext, $dir, $unique_filename_callback, $alt_filenames, $number ); 2691 } 2692 2693 /** 2694 * Helper function to test if each of an array of file names could conflict with existing files. 2695 * 2696 * @since 5.8.1 2697 * @access private 2698 * 2699 * @param string[] $filenames Array of file names to check. 2700 * @param string $dir The directory containing the files. 2701 * @param array $files An array of existing files in the directory. May be empty. 2702 * @return bool True if the tested file name could match an existing file, false otherwise. 2703 */ 2704 function _wp_check_alternate_file_names( $filenames, $dir, $files ) { 2705 foreach ( $filenames as $filename ) { 2706 if ( file_exists( $dir . $filename ) ) { 2707 return true; 2708 } 2709 2710 if ( ! empty( $files ) && _wp_check_existing_file_names( $filename, $files ) ) { 2711 return true; 2712 } 2713 } 2714 2715 return false; 2608 2716 } 2609 2717 … … 2789 2897 } 2790 2898 } 2899 } 2900 2901 /** 2902 * Returns first matched extension for the mime-type, 2903 * as mapped from wp_get_mime_types(). 2904 * 2905 * @since 5.8.1 2906 * 2907 * @param string $mime_type 2908 * 2909 * @return string|false 2910 */ 2911 function wp_get_default_extension_for_mime_type( $mime_type ) { 2912 $extensions = explode( '|', array_search( $mime_type, wp_get_mime_types(), true ) ); 2913 2914 if ( empty( $extensions[0] ) ) { 2915 return false; 2916 } 2917 2918 return $extensions[0]; 2791 2919 } 2792 2920 -
branches/5.8/tests/phpunit/tests/functions.php
r50814 r51706 169 169 170 170 // Sanity check. 171 $this->assertSame( 'abcdefg.png', wp_unique_filename( $testdir, 'abcdefg.png' ), ' Sanitiy check failed' );172 173 // Check number is appended for file already exists.171 $this->assertSame( 'abcdefg.png', wp_unique_filename( $testdir, 'abcdefg.png' ), 'Test non-existing file, file name should be unchanged.' ); 172 173 // Ensure correct images exist. 174 174 $this->assertFileExists( $testdir . 'test-image.png', 'Test image does not exist' ); 175 $this->assertSame( 'test-image-1.png', wp_unique_filename( $testdir, 'test-image.png' ), 'Number not appended correctly' );176 175 $this->assertFileNotExists( $testdir . 'test-image-1.png' ); 176 177 // Check number is appended if file already exists. 178 $this->assertSame( 'test-image-1.png', wp_unique_filename( $testdir, 'test-image.png' ), 'File name not unique, number not appended.' ); 179 180 // Check file with uppercase extension. 181 $this->assertSame( 'test-image-1.png', wp_unique_filename( $testdir, 'test-image.PNG' ), 'File name with uppercase extension not unique, number not appended.' ); 182 183 // Check file name with already added number. 184 $this->assertSame( 'test-image-2-1.gif', wp_unique_filename( $testdir, 'test-image-2.gif' ), 'File name not unique, number not appended correctly.' ); 177 185 178 186 // Check special chars. … … 220 228 $upload_dir['basedir'] = DIR_TESTDATA . '/images/'; 221 229 return $upload_dir; 230 } 231 232 /** 233 * @ticket 53668 234 */ 235 function test_wp_unique_filename_with_additional_image_extension() { 236 $testdir = DIR_TESTDATA . '/images/'; 237 238 add_filter( 'upload_dir', array( $this, 'upload_dir_patch_basedir' ) ); 239 240 // Set conversions for uploaded images. 241 add_filter( 'image_editor_output_format', array( $this, 'image_editor_output_format_handler' ) ); 242 243 // Ensure the test images exist. 244 $this->assertFileExists( $testdir . 'test-image-1-100x100.jpg', 'test-image-1-100x100.jpg does not exist' ); 245 $this->assertFileExists( $testdir . 'test-image-2.gif', 'test-image-2.gif does not exist' ); 246 $this->assertFileExists( $testdir . 'test-image-3.jpg', 'test-image-3.jpg does not exist' ); 247 $this->assertFileExists( $testdir . 'test-image-4.png', 'test-image-4.png does not exist' ); 248 249 // Standard test: file does not exist and there are no possible intersections with other files. 250 $this->assertSame( 251 'abcdef.png', 252 wp_unique_filename( $testdir, 'abcdef.png' ), 253 'The abcdef.png, abcdef.gif, and abcdef.jpg images do not exist. The file name should not be changed.' 254 ); 255 256 // Actual clash recognized. 257 $this->assertSame( 258 'canola-1.jpg', 259 wp_unique_filename( $testdir, 'canola.jpg' ), 260 'The canola.jpg image exists. The file name should be unique.' 261 ); 262 263 // Same name with different extension and the image will be converted. 264 $this->assertSame( 265 'canola-1.png', 266 wp_unique_filename( $testdir, 'canola.png' ), 267 'The canola.jpg image exists. Uploading canola.png that will be converted to canola.jpg should produce unique file name.' 268 ); 269 270 // Same name with different uppercase extension and the image will be converted. 271 $this->assertSame( 272 'canola-1.png', 273 wp_unique_filename( $testdir, 'canola.PNG' ), 274 'The canola.jpg image exists. Uploading canola.PNG that will be converted to canola.jpg should produce unique file name.' 275 ); 276 277 // Actual clash with several images with different extensions. 278 $this->assertSame( 279 'test-image-5.png', 280 wp_unique_filename( $testdir, 'test-image.png' ), 281 'The test-image.png, test-image-1-100x100.jpg, test-image-2.gif, test-image-3.jpg, and test-image-4.png images exist.' . 282 'All of them may clash when creating sub-sizes or regenerating thumbnails in the future. The filename should be unique.' 283 ); 284 285 // Possible clash with regenerated thumbnails in the future. 286 $this->assertSame( 287 'codeispoetry-1.jpg', 288 wp_unique_filename( $testdir, 'codeispoetry.jpg' ), 289 'The codeispoetry.png image exists. When regenerating thumbnails for it they will be converted to JPG.' . 290 'The name of the newly uploaded codeispoetry.jpg should be made unique.' 291 ); 292 293 remove_filter( 'image_editor_output_format', array( $this, 'image_editor_output_format_handler' ) ); 294 remove_filter( 'upload_dir', array( $this, 'upload_dir_patch_basedir' ) ); 295 } 296 297 /** 298 * Changes the output format when editing images. When uploading a PNG file 299 * it will be converted to JPEG, GIF to JPEG, and PICT to BMP 300 * (if the image editor in PHP supports it). 301 * 302 * @param array $formats 303 * 304 * @return array 305 */ 306 public function image_editor_output_format_handler( $formats ) { 307 $formats['image/png'] = 'image/jpeg'; 308 $formats['image/gif'] = 'image/jpeg'; 309 $formats['image/pct'] = 'image/bmp'; 310 311 return $formats; 222 312 } 223 313 … … 1922 2012 ); 1923 2013 } 2014 2015 /** 2016 * @ticket 53668 2017 */ 2018 public function test_wp_get_default_extension_for_mime_type() { 2019 $this->assertEquals( 'jpg', wp_get_default_extension_for_mime_type( 'image/jpeg' ), 'jpg not returned as default extension for "image/jpeg"' ); 2020 $this->assertNotEquals( 'jpeg', wp_get_default_extension_for_mime_type( 'image/jpeg' ), 'jpeg should not be returned as default extension for "image/jpeg"' ); 2021 $this->assertEquals( 'png', wp_get_default_extension_for_mime_type( 'image/png' ), 'png not returned as default extension for "image/png"' ); 2022 $this->assertFalse( wp_get_default_extension_for_mime_type( 'wibble/wobble' ), 'false not returned for unrecognized mime type' ); 2023 $this->assertFalse( wp_get_default_extension_for_mime_type( '' ), 'false not returned when empty string as mime type supplied' ); 2024 $this->assertFalse( wp_get_default_extension_for_mime_type( ' ' ), 'false not returned when empty string as mime type supplied' ); 2025 $this->assertFalse( wp_get_default_extension_for_mime_type( 123 ), 'false not returned when int as mime type supplied' ); 2026 $this->assertFalse( wp_get_default_extension_for_mime_type( null ), 'false not returned when null as mime type supplied' ); 2027 } 1924 2028 }
Note: See TracChangeset
for help on using the changeset viewer.