Ticket #40175: 40175.2.diff
| File 40175.2.diff, 11.3 KB (added by , 9 years ago) |
|---|
-
src/wp-includes/functions.php
diff --git src/wp-includes/functions.php src/wp-includes/functions.php index 2720f590af..69e1319a84 100644
function _wp_upload_dir( $time = null ) { 2023 2023 } 2024 2024 2025 2025 /** 2026 * Assign a new extension to a filename. 2027 * 2028 * @since 4.9 2029 * 2030 * @param string $filename The original filename. 2031 * @param string $ext The new extension. 2032 * @return string The renamed file. 2033 */ 2034 function wp_update_filename_extension( $filename, $ext ) { 2035 $ext = strtolower( $ext ); 2036 $ext = rtrim( $ext, '.' ); 2037 $ext = ltrim( $ext, '.' ); 2038 2039 $filename_parts = explode( '.', $filename ); 2040 2041 // Remove the old extension. 2042 if ( count( $filename_parts ) > 1 ) { 2043 array_pop( $filename_parts ); 2044 } 2045 2046 // Add the new extension. 2047 if ( strlen( $ext ) ) { 2048 $filename_parts[] = $ext; 2049 } 2050 2051 return implode( '.', $filename_parts ); 2052 } 2053 2054 /** 2026 2055 * Get a filename that is sanitized and unique for the given directory. 2027 2056 * 2028 2057 * If the filename is not unique, then a number will be added to the filename … … function wp_check_filetype( $filename, $mimes = null ) { 2267 2296 function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) { 2268 2297 $proper_filename = false; 2269 2298 2270 // Do basic extension validation and MIME mapping 2299 // Do basic extension validation and MIME mapping. 2271 2300 $wp_filetype = wp_check_filetype( $filename, $mimes ); 2272 2301 $ext = $wp_filetype['ext']; 2273 2302 $type = $wp_filetype['type']; 2274 2303 2275 // We can't do any further validation without a file to work with 2304 // We can't do any further validation without a file to work with. 2276 2305 if ( ! file_exists( $file ) ) { 2277 2306 return compact( 'ext', 'type', 'proper_filename' ); 2278 2307 } … … function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) { 2282 2311 // Validate image types. 2283 2312 if ( $type && 0 === strpos( $type, 'image/' ) ) { 2284 2313 2285 // Attempt to figure out what type of image it actually is 2314 // Attempt to figure out what type of image it actually is. 2286 2315 $real_mime = wp_get_image_mime( $file ); 2287 2316 2288 2317 if ( $real_mime && $real_mime != $type ) { … … function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) { 2294 2323 * @param array $mime_to_ext Array of image mime types and their matching extensions. 2295 2324 */ 2296 2325 $mime_to_ext = apply_filters( 'getimagesize_mimes_to_exts', array( 2297 'image/jpeg' => 'jpg', 2298 'image/png' => 'png', 2299 'image/gif' => 'gif', 2300 'image/bmp' => 'bmp', 2301 'image/tiff' => 'tif', 2326 'image/jpeg' => 'jpg', 2327 'image/png' => 'png', 2328 'image/gif' => 'gif', 2329 'image/bmp' => 'bmp', 2330 'image/x-ms-bmp' => 'bmp', 2331 'image/tiff' => 'tif', 2302 2332 ) ); 2303 2333 2304 // Re place whatever is after the last period in the filename with the correct extension2334 // Rename the file with the correct extension. 2305 2335 if ( ! empty( $mime_to_ext[ $real_mime ] ) ) { 2306 $filename_parts = explode( '.', $filename ); 2307 array_pop( $filename_parts ); 2308 $filename_parts[] = $mime_to_ext[ $real_mime ]; 2309 $new_filename = implode( '.', $filename_parts ); 2336 $new_filename = wp_update_filename_extension( $filename, $mime_to_ext[ $real_mime ] ); 2310 2337 2311 2338 if ( $new_filename != $filename ) { 2312 $proper_filename = $new_filename; // Mark that it changed 2339 $proper_filename = $new_filename; // Mark that it changed. 2313 2340 } 2314 2341 // Redefine the extension / MIME 2315 2342 $wp_filetype = wp_check_filetype( $new_filename, $mimes ); … … function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) { 2323 2350 } 2324 2351 2325 2352 // Validate files that didn't get validated during previous checks. 2326 if ( $type && ! $real_mime && extension_loaded( 'fileinfo' ) ) { 2353 if ( 2354 $type && 2355 ! $real_mime && 2356 extension_loaded( 'fileinfo' ) && 2357 defined( 'FILEINFO_MIME_TYPE' ) 2358 ) { 2327 2359 $finfo = finfo_open( FILEINFO_MIME_TYPE ); 2328 2360 $real_mime = finfo_file( $finfo, $file ); 2329 2361 finfo_close( $finfo ); 2330 2362 2331 2363 /* 2332 2364 * If $real_mime doesn't match what we're expecting, we need to do some extra 2333 * vetting of applicationmime types to make sure this type of file is allowed.2365 * vetting of greylisted mime types to make sure this type of file is allowed. 2334 2366 * Other mime types are assumed to be safe, but should be considered unverified. 2335 2367 */ 2336 if ( $real_mime && ( $real_mime !== $type ) && ( 0 === strpos( $real_mime, 'application' ) ) ) { 2337 $allowed = get_allowed_mime_types(); 2368 if ( $real_mime && ( $real_mime !== $type ) ) { 2369 // Get the true file extension for a greylisted filetype. 2370 $greylist = get_greylisted_mime_types(); 2371 $real_mime = strtolower( sanitize_mime_type( $real_mime ) ); 2372 $real_ext = false; 2373 foreach ( $greylist as $exts => $greylist_types ) { 2374 if ( in_array( $real_mime, $greylist_types, true ) ) { 2375 $real_ext = $exts; 2376 break; 2377 } 2378 } 2379 2380 if ( $real_ext ) { 2381 // This MIME type is greylisted, so make sure the extension is allowed. 2382 $allowed = get_allowed_mime_types(); 2383 $found = false; 2384 foreach ( $allowed as $exts => $allowed_type ) { 2385 $exts = explode( '|', $exts ); 2386 if ( in_array( $real_ext, $exts, true ) ) { 2387 // Rename the file with the correct extension. 2388 if ( $ext !== $real_ext ) { 2389 $new_filename = wp_update_filename_extension( $filename, $real_ext ); 2390 2391 if ( $new_filename != $filename ) { 2392 $proper_filename = $new_filename; // Mark that it changed. 2393 } 2394 2395 $ext = $real_ext; 2396 } 2338 2397 2339 if ( ! in_array( $real_mime, $allowed ) ) { 2340 $type = $ext = false; 2398 // Always prefer the MIME type from get_allowed_mimes(). 2399 $type = $allowed_type; 2400 2401 $found = true; 2402 break; 2403 } 2404 } 2405 2406 // Unauthorized file. 2407 if ( ! $found ) { 2408 $ext = $type = false; 2409 } 2341 2410 } 2342 2411 } 2343 2412 } … … function wp_get_ext_types() { 2546 2615 } 2547 2616 2548 2617 /** 2618 * Retrieve list of greylisted mime types and file extensions. 2619 * 2620 * These are file types deserving of extra validation during uploads. Unlike 2621 * get_allowed_mime_types, each entry consists of a single file extension 2622 * with multiple MIME types. 2623 * 2624 * @since 4.9 2625 * 2626 * @return array Array of mime types keyed by the file extension corresponding 2627 * to those types. 2628 */ 2629 function get_greylisted_mime_types() { 2630 $greylist = array( 2631 'air' => array( 2632 'application/adobe.air-application-installer-package+zip', 2633 'application/vnd.adobe.air-application-installer-package+zip', 2634 'application/x-adobe.air-application-installer-package+zip', 2635 ), 2636 'fla' => array( 2637 'application/dtg.local.flash', 2638 'application/vnd.dtg.local.flash', 2639 'application/x-dtg.local.flash', 2640 ), 2641 'flv' => array( 2642 'application/flash-video', 2643 'application/vnd.flash-video', 2644 'application/x-flash-video', 2645 'flv-application/octet-stream', 2646 'video/flv', 2647 'video/x-flv', 2648 ), 2649 'swf' => array( 2650 'application/adobe.flash.movie', 2651 'application/futuresplash', 2652 'application/shockwave-flash', 2653 'application/vnd.adobe.flash.movie', 2654 'application/vnd.futuresplash', 2655 'application/vnd.shockwave-flash', 2656 'application/x-adobe.flash.movie', 2657 'application/x-futuresplash', 2658 'application/x-shockwave-flash', 2659 ), 2660 'spl' => array( 2661 'application/adobe.flash.movie', 2662 'application/futuresplash', 2663 'application/shockwave-flash', 2664 'application/vnd.adobe.flash.movie', 2665 'application/vnd.futuresplash', 2666 'application/vnd.shockwave-flash', 2667 'application/x-adobe.flash.movie', 2668 'application/x-futuresplash', 2669 'application/x-shockwave-flash', 2670 ), 2671 ); 2672 2673 /** 2674 * Filters the greylist results. 2675 * 2676 * @since 4.9 2677 * 2678 * @param array $greylist Array of mime types keyed by the file extension corresponding 2679 * to those types. 2680 */ 2681 return apply_filters( 'get_greylisted_mime_types', $greylist ); 2682 } 2683 2684 /** 2549 2685 * Retrieve list of allowed mime types and file extensions. 2550 2686 * 2551 2687 * @since 2.8.6 -
new file tests/phpunit/data/uploads/test.swf
diff --git tests/phpunit/data/uploads/test.swf tests/phpunit/data/uploads/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..c6195c41eebe7b3b2006eff39a268320e973feac GIT binary patch literal 140 zcmZ<@4`%OSU|^_VV2x*B;9tPNz{AL3&zuVs>d;|eVaQD_E>28OWk@bcO)N<bNv$Yx z%S_ElVJHEz7(7yQa`F|z^NVs)6d9&zF|Zo}wXvrF2{s@G12}`75y<CYU<V0sFxrYw UV*>JIrm-+^FmW*ZGdKW+0pm9pO8@`> -
tests/phpunit/tests/functions.php
literal 0 HcmV?d00001 diff --git tests/phpunit/tests/functions.php tests/phpunit/tests/functions.php index 7c8736ab67..778071b6e3 100644
class Tests_Functions extends WP_UnitTestCase { 122 122 ); 123 123 } 124 124 125 /** 126 * @dataProvider _wp_update_filename_extension 127 */ 128 function test_wp_update_filename_extension( $filename, $ext, $expected ) { 129 $this->assertEquals( $expected, wp_update_filename_extension( $filename, $ext ) ); 130 } 131 125 132 function test_wp_unique_filename() { 126 133 127 134 $testdir = DIR_TESTDATA . '/images/'; … … class Tests_Functions extends WP_UnitTestCase { 1044 1051 } 1045 1052 1046 1053 /** 1054 * @ticket 39550 1055 * 1056 * @dataProvider _wp_check_filetype_and_ext_with_filtered_swf 1057 */ 1058 function test_wp_check_filetype_and_ext_with_filtered_swf( $file, $filename, $expected ) { 1059 if ( ! extension_loaded( 'fileinfo' ) ) { 1060 $this->markTestSkipped( 'The fileinfo PHP extension is not loaded.' ); 1061 } 1062 1063 if ( is_multisite() ) { 1064 $this->markTestSkipped( 'Test does not run in multisite' ); 1065 } 1066 1067 add_filter( 'upload_mimes', array( $this, '_filter_mime_types_swf' ) ); 1068 $this->assertEquals( $expected, wp_check_filetype_and_ext( $file, $filename ) ); 1069 1070 // Cleanup. 1071 remove_filter( 'upload_mimes', array( $this, '_test_add_mime_types_swf' ) ); 1072 } 1073 1074 /** 1047 1075 * Data profider for test_wp_get_image_mime(); 1048 1076 */ 1049 1077 public function _wp_get_image_mime() { … … class Tests_Functions extends WP_UnitTestCase { 1130 1158 'proper_filename' => false, 1131 1159 ), 1132 1160 ), 1161 // Flash file with invalid extension. 1162 array( 1163 DIR_TESTDATA . '/uploads/test.swf', 1164 'big5.jpg', 1165 array( 1166 'ext' => false, 1167 'type' => false, 1168 'proper_filename' => false, 1169 ), 1170 ), 1171 // Flash file with valid extension. 1172 array( 1173 DIR_TESTDATA . '/uploads/test.swf', 1174 'test.swf', 1175 array( 1176 'ext' => false, 1177 'type' => false, 1178 'proper_filename' => false, 1179 ), 1180 ), 1133 1181 ); 1134 1182 1135 1183 // Test a few additional file types on single sites. … … class Tests_Functions extends WP_UnitTestCase { 1161 1209 return $data; 1162 1210 } 1163 1211 1212 public function _filter_mime_types_swf( $mimes ) { 1213 $mimes['swf'] = 'application/x-shockwave-flash'; 1214 return $mimes; 1215 } 1216 1217 public function _wp_update_filename_extension() { 1218 $data = array( 1219 array( 1220 'test.jpg', 1221 'png', 1222 'test.png', 1223 ), 1224 array( 1225 'test', 1226 'png', 1227 'test.png', 1228 ), 1229 array( 1230 'test', 1231 '.png', 1232 'test.png', 1233 ), 1234 array( 1235 'test.jpg', 1236 '', 1237 'test', 1238 ), 1239 ); 1240 1241 return $data; 1242 } 1243 1244 public function _wp_check_filetype_and_ext_with_filtered_swf() { 1245 $data = array( 1246 // Correctly named SWF. 1247 array( 1248 DIR_TESTDATA . '/uploads/test.swf', 1249 'test.swf', 1250 array( 1251 'ext' => 'swf', 1252 'type' => 'application/x-shockwave-flash', 1253 'proper_filename' => false, 1254 ), 1255 ), 1256 // Incorrectly named SWF. 1257 array( 1258 DIR_TESTDATA . '/uploads/test.swf', 1259 'test.jpg', 1260 array( 1261 'ext' => 'swf', 1262 'type' => 'application/x-shockwave-flash', 1263 'proper_filename' => 'test.swf', 1264 ), 1265 ), 1266 ); 1267 1268 return $data; 1269 } 1164 1270 }