Ticket #42437: 42437.4.diff
File 42437.4.diff, 6.4 KB (added by , 5 years ago) |
---|
-
src/wp-includes/functions.php
2409 2409 // Separate the filename into a name and extension. 2410 2410 $ext = pathinfo( $filename, PATHINFO_EXTENSION ); 2411 2411 $name = pathinfo( $filename, PATHINFO_BASENAME ); 2412 2412 2413 if ( $ext ) { 2413 2414 $ext = '.' . $ext; 2414 2415 } … … 2426 2427 $filename = call_user_func( $unique_filename_callback, $dir, $name, $ext ); 2427 2428 } else { 2428 2429 $number = ''; 2430 $fname = pathinfo( $filename, PATHINFO_FILENAME ); 2429 2431 2432 // Always append a number to file names that can potentially match image sub-size file names. 2433 if ( $fname && preg_match( '/-(?:\d+x\d+|scaled|rotated)$/', $fname ) ) { 2434 $number = 1; 2435 2436 // At this point the file name may not be unique. This is tested below and the $number is incremented. 2437 $filename = str_replace( "{$fname}{$ext}", "{$fname}-{$number}{$ext}", $filename ); 2438 } 2439 2430 2440 // Change '.ext' to lower case. 2431 2441 if ( $ext && strtolower( $ext ) != $ext ) { 2432 2442 $ext2 = strtolower( $ext ); … … 2433 2443 $filename2 = preg_replace( '|' . preg_quote( $ext ) . '$|', $ext2, $filename ); 2434 2444 2435 2445 // Check for both lower and upper case extension or image sub-sizes may be overwritten. 2436 while ( file_exists( $dir . "/ $filename" ) || file_exists( $dir . "/$filename2" ) ) {2446 while ( file_exists( $dir . "/{$filename}" ) || file_exists( $dir . "/{$filename2}" ) ) { 2437 2447 $new_number = (int) $number + 1; 2438 $filename = str_replace( array( "- $number$ext", "$number$ext" ), "-$new_number$ext", $filename );2439 $filename2 = str_replace( array( "- $number$ext2", "$number$ext2" ), "-$new_number$ext2", $filename2 );2448 $filename = str_replace( array( "-{$number}{$ext}", "{$number}{$ext}" ), "-{$new_number}{$ext}", $filename ); 2449 $filename2 = str_replace( array( "-{$number}{$ext2}", "{$number}{$ext2}" ), "-{$new_number}{$ext2}", $filename2 ); 2440 2450 $number = $new_number; 2441 2451 } 2442 2452 2443 /** 2444 * Filters the result when generating a unique file name. 2445 * 2446 * @since 4.5.0 2447 * 2448 * @param string $filename Unique file name. 2449 * @param string $ext File extension, eg. ".png". 2450 * @param string $dir Directory path. 2451 * @param callable|null $unique_filename_callback Callback function that generates the unique file name. 2452 */ 2453 return apply_filters( 'wp_unique_filename', $filename2, $ext, $dir, $unique_filename_callback ); 2453 $filename = $filename2; 2454 } else { 2455 while ( file_exists( $dir . "/{$filename}" ) ) { 2456 $new_number = (int) $number + 1; 2457 2458 if ( '' === "{$number}{$ext}" ) { 2459 $filename = "{$filename}-{$new_number}"; 2460 } else { 2461 $filename = str_replace( array( "-{$number}{$ext}", "{$number}{$ext}" ), "-{$new_number}{$ext}", $filename ); 2462 } 2463 2464 $number = $new_number; 2465 } 2454 2466 } 2455 2467 2456 while ( file_exists( $dir . "/$filename" ) ) { 2457 $new_number = (int) $number + 1; 2458 if ( '' == "$number$ext" ) { 2459 $filename = "$filename-" . $new_number; 2460 } else { 2461 $filename = str_replace( array( "-$number$ext", "$number$ext" ), '-' . $new_number . $ext, $filename ); 2468 // Prevent collisions with existing file names that contain dimension-like strings 2469 // (whether they are subsizes or originals uploaded prior to #42437). 2470 2471 // The (resized) image files would have name and extension. 2472 if ( $name && $ext ) { 2473 // List of all files and directories contained in $dir (with the "dot" files removed). 2474 $files = array_diff( scandir( $dir ), array( '.', '..' ) ); 2475 2476 if ( ! empty( $files ) ) { 2477 while ( _wp_check_existing_file_names( $filename, $files ) ) { 2478 $new_number = (int) $number + 1; 2479 $filename = str_replace( array( "-{$number}{$ext}", "{$number}{$ext}" ), "-{$new_number}{$ext}", $filename ); 2480 $number = $new_number; 2481 } 2462 2482 } 2463 $number = $new_number;2464 2483 } 2465 2484 } 2466 2485 2467 /** This filter is documented in wp-includes/functions.php */ 2486 /** 2487 * Filters the result when generating a unique file name. 2488 * 2489 * @since 4.5.0 2490 * 2491 * @param string $filename Unique file name. 2492 * @param string $ext File extension, eg. ".png". 2493 * @param string $dir Directory path. 2494 * @param callable|null $unique_filename_callback Callback function that generates the unique file name. 2495 */ 2468 2496 return apply_filters( 'wp_unique_filename', $filename, $ext, $dir, $unique_filename_callback ); 2469 2497 } 2470 2498 2471 2499 /** 2500 * Helper function to check if a file name could match an existing image sub-size file name. 2501 * 2502 * @since 5.3.1 2503 * @access private 2504 * 2505 * @param string $filename The file name to check. 2506 * $param array $files An array of existing files in the directory. 2507 * $return bool True if the tested file name could match an existing file, false otherwise. 2508 */ 2509 function _wp_check_existing_file_names( $filename, $files ) { 2510 $fname = pathinfo( $filename, PATHINFO_FILENAME ); 2511 $ext = pathinfo( $filename, PATHINFO_EXTENSION ); 2512 2513 // Edge case, file names like `.ext` 2514 if ( empty( $fname ) ) { 2515 return false; 2516 } 2517 2518 if ( $ext ) { 2519 $ext = ".$ext"; 2520 } 2521 2522 $regex = '/^' . preg_quote( $fname ) . '-(?:\d+x\d+|scaled|rotated)' . preg_quote( $ext ) . '$/'; 2523 2524 foreach ( $files as $file ) { 2525 if ( preg_match( $regex, $file ) ) { 2526 return true; 2527 } 2528 } 2529 2530 return false; 2531 } 2532 2533 /** 2472 2534 * Create a file in the upload folder with given content. 2473 2535 * 2474 2536 * If there is an error, then the key 'error' will exist with the error message. -
tests/phpunit/tests/functions.php
195 195 $this->assertEquals( 'abcdefg.png', wp_unique_filename( $testdir, 'abcde\\\fg.png' ), 'Tripple slashed not removed' ); 196 196 } 197 197 198 /** 199 * @group 42437 200 */ 201 function test_unique_filename_with_dimension_like_filename() { 202 $testdir = DIR_TESTDATA . '/images/'; 203 204 // test collision with "dimension-like" original filename. 205 $this->assertEquals( 'one-blue-pixel-100x100-1.png', wp_unique_filename( $testdir, 'one-blue-pixel-100x100.png' ) ); 206 // test collision with existing sub-size filename. 207 $this->assertEquals( 'one-blue-pixel-1.png', wp_unique_filename( $testdir, 'one-blue-pixel.png' ) ); 208 } 209 198 210 function test_is_serialized() { 199 211 $cases = array( 200 212 serialize( null ),