@@ -2341,17 +2341,52 @@ function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
2341
2341
$ real_mime = finfo_file ( $ finfo , $ file );
2342
2342
finfo_close ( $ finfo );
2343
2343
2344
+ // fileinfo often misidentifies obscure files as one of these types
2345
+ $ nonspecific_types = array (
2346
+ 'application/octet-stream ' ,
2347
+ 'application/encrypted ' ,
2348
+ 'application/CDFV2-encrypted ' ,
2349
+ 'application/zip ' ,
2350
+ );
2351
+
2344
2352
/*
2345
- * If $real_mime doesn't match what we're expecting, we need to do some extra
2346
- * vetting of application mime types to make sure this type of file is allowed.
2347
- * Other mime types are assumed to be safe, but should be considered unverified .
2353
+ * If $real_mime doesn't match the content type we're expecting from the file's extension,
2354
+ * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
2355
+ * allowed some leeway, but anything else must exactly match the real content type .
2348
2356
*/
2349
- if ( $ real_mime && ( $ real_mime !== $ type ) && ( 0 === strpos ( $ real_mime , 'application ' ) ) ) {
2350
- $ allowed = get_allowed_mime_types ();
2357
+ if ( in_array ( $ real_mime , $ nonspecific_types , true ) ) {
2358
+ // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
2359
+ if ( !in_array ( substr ( $ type , 0 , strcspn ( $ type , '/ ' ) ), array ( 'application ' , 'video ' , 'audio ' ) ) ) {
2360
+ $ type = $ ext = false ;
2361
+ }
2362
+ } elseif ( 0 === strpos ( $ real_mime , 'video/ ' ) || 0 === strpos ( $ real_mime , 'audio/ ' ) ) {
2363
+ /*
2364
+ * For these types, only the major type must match the real value.
2365
+ * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
2366
+ * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
2367
+ */
2351
2368
2352
- if ( ! in_array ( $ real_mime , $ allowed ) ) {
2369
+ if ( substr ( $ real_mime , 0 , strcspn ( $ real_mime , '/ ' ) ) !== substr ( $ type , 0 , strcspn ( $ type , '/ ' ) ) ) {
2370
+ $ type = $ ext = false ;
2371
+ }
2372
+ } else {
2373
+ if ( $ type !== $ real_mime ) {
2374
+ /*
2375
+ * Everything else including image/* and application/*:
2376
+ * If the real content type doesn't match the file extension, assume it's dangerous.
2377
+ */
2353
2378
$ type = $ ext = false ;
2354
2379
}
2380
+
2381
+ }
2382
+ }
2383
+
2384
+ // The mime type must be allowed
2385
+ if ( $ type ) {
2386
+ $ allowed = get_allowed_mime_types ();
2387
+
2388
+ if ( ! in_array ( $ type , $ allowed ) ) {
2389
+ $ type = $ ext = false ;
2355
2390
}
2356
2391
}
2357
2392
0 commit comments