Media: Reduce failing uploads following 4.7.1.
[39831] introduced more strict MIME type checking for uploads, which resulted in unintetionally blocking several filetypes that were previously valid. This change uses a more targeted approach to MIME validation to restore previous behavior for most types. Props blobfolio, iandunn, ipstenu, markoheijnen, xknown, joemcgill. Merges [40124] and [40125] to the 4.7 branch. Fixes #39550, #39552. git-svn-id: https://develop.svn.wordpress.org/branches/4.7@40134 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
9cf5b91e9c
commit
f055694b32
|
@ -2268,15 +2268,15 @@ function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
|
||||||
return compact( 'ext', 'type', 'proper_filename' );
|
return compact( 'ext', 'type', 'proper_filename' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$real_mime = false;
|
||||||
|
|
||||||
// Validate image types.
|
// Validate image types.
|
||||||
if ( $type && 0 === strpos( $type, 'image/' ) ) {
|
if ( $type && 0 === strpos( $type, 'image/' ) ) {
|
||||||
|
|
||||||
// Attempt to figure out what type of image it actually is
|
// Attempt to figure out what type of image it actually is
|
||||||
$real_mime = wp_get_image_mime( $file );
|
$real_mime = wp_get_image_mime( $file );
|
||||||
|
|
||||||
if ( ! $real_mime ) {
|
if ( $real_mime && $real_mime != $type ) {
|
||||||
$type = $ext = false;
|
|
||||||
} elseif ( $real_mime != $type ) {
|
|
||||||
/**
|
/**
|
||||||
* Filters the list mapping image mime types to their respective extensions.
|
* Filters the list mapping image mime types to their respective extensions.
|
||||||
*
|
*
|
||||||
|
@ -2307,18 +2307,29 @@ function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
|
||||||
$ext = $wp_filetype['ext'];
|
$ext = $wp_filetype['ext'];
|
||||||
$type = $wp_filetype['type'];
|
$type = $wp_filetype['type'];
|
||||||
} else {
|
} else {
|
||||||
$type = $ext = false;
|
// Reset $real_mime and try validating again.
|
||||||
|
$real_mime = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ( function_exists( 'finfo_file' ) ) {
|
}
|
||||||
// Use finfo_file if available to validate non-image files.
|
|
||||||
|
// Validate files that didn't get validated during previous checks.
|
||||||
|
if ( $type && ! $real_mime && extension_loaded( 'fileinfo' ) ) {
|
||||||
$finfo = finfo_open( FILEINFO_MIME_TYPE );
|
$finfo = finfo_open( FILEINFO_MIME_TYPE );
|
||||||
$real_mime = finfo_file( $finfo, $file );
|
$real_mime = finfo_file( $finfo, $file );
|
||||||
finfo_close( $finfo );
|
finfo_close( $finfo );
|
||||||
|
|
||||||
// If the extension does not match the file's real type, return false.
|
/*
|
||||||
if ( $real_mime !== $type ) {
|
* If $real_mime doesn't match what we're expecting, we need to do some extra
|
||||||
$type = $ext = false;
|
* vetting of application mime types to make sure this type of file is allowed.
|
||||||
|
* Other mime types are assumed to be safe, but should be considered unverified.
|
||||||
|
*/
|
||||||
|
if ( $real_mime && ( $real_mime !== $type ) && ( 0 === strpos( $real_mime, 'application' ) ) ) {
|
||||||
|
$allowed = get_allowed_mime_types();
|
||||||
|
|
||||||
|
if ( ! in_array( $real_mime, $allowed ) ) {
|
||||||
|
$type = $ext = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="64" height="64">
|
||||||
|
<circle cx="32" cy="32" r="25" stroke="white" stroke-width="7" fill="black" fill-opacity="0.2"/>
|
||||||
|
<polygon points="26,22 26,42 43,32" fill="white"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 274 B |
|
@ -898,4 +898,165 @@ class Tests_Functions extends WP_UnitTestCase {
|
||||||
$unique_uuids = array_unique( $uuids );
|
$unique_uuids = array_unique( $uuids );
|
||||||
$this->assertEquals( $uuids, $unique_uuids );
|
$this->assertEquals( $uuids, $unique_uuids );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ticket 39550
|
||||||
|
* @dataProvider _wp_check_filetype_and_ext_data
|
||||||
|
*/
|
||||||
|
function test_wp_check_filetype_and_ext( $file, $filename, $expected ) {
|
||||||
|
if ( ! extension_loaded( 'fileinfo' ) ) {
|
||||||
|
$this->markTestSkipped( 'The fileinfo PHP extension is not loaded.' );
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertEquals( $expected, wp_check_filetype_and_ext( $file, $filename ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ticket 39550
|
||||||
|
*/
|
||||||
|
function test_wp_check_filetype_and_ext_with_filtered_svg() {
|
||||||
|
if ( ! extension_loaded( 'fileinfo' ) ) {
|
||||||
|
$this->markTestSkipped( 'The fileinfo PHP extension is not loaded.' );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_multisite() ) {
|
||||||
|
$this->markTestSkipped( 'Test does not run in multisite' );
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = DIR_TESTDATA . '/uploads/video-play.svg';
|
||||||
|
$filename = 'video-play.svg';
|
||||||
|
|
||||||
|
$expected = array(
|
||||||
|
'ext' => 'svg',
|
||||||
|
'type' => 'image/svg+xml',
|
||||||
|
'proper_filename' => false,
|
||||||
|
);
|
||||||
|
|
||||||
|
add_filter( 'upload_mimes', array( $this, '_filter_mime_types_svg' ) );
|
||||||
|
$this->assertEquals( $expected, wp_check_filetype_and_ext( $file, $filename ) );
|
||||||
|
|
||||||
|
// Cleanup.
|
||||||
|
remove_filter( 'upload_mimes', array( $this, '_test_add_mime_types_svg' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ticket 39550
|
||||||
|
*/
|
||||||
|
function test_wp_check_filetype_and_ext_with_filtered_woff() {
|
||||||
|
if ( ! extension_loaded( 'fileinfo' ) ) {
|
||||||
|
$this->markTestSkipped( 'The fileinfo PHP extension is not loaded.' );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_multisite() ) {
|
||||||
|
$this->markTestSkipped( 'Test does not run in multisite' );
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = DIR_TESTDATA . '/uploads/dashicons.woff';
|
||||||
|
$filename = 'dashicons.woff';
|
||||||
|
|
||||||
|
$expected = array(
|
||||||
|
'ext' => 'woff',
|
||||||
|
'type' => 'application/font-woff',
|
||||||
|
'proper_filename' => false,
|
||||||
|
);
|
||||||
|
|
||||||
|
add_filter( 'upload_mimes', array( $this, '_filter_mime_types_woff' ) );
|
||||||
|
$this->assertEquals( $expected, wp_check_filetype_and_ext( $file, $filename ) );
|
||||||
|
|
||||||
|
// Cleanup.
|
||||||
|
remove_filter( 'upload_mimes', array( $this, '_test_add_mime_types_woff' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function _filter_mime_types_svg( $mimes ) {
|
||||||
|
$mimes['svg'] = 'image/svg+xml';
|
||||||
|
return $mimes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function _filter_mime_types_woff( $mimes ) {
|
||||||
|
$mimes['woff'] = 'application/font-woff';
|
||||||
|
return $mimes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function _wp_check_filetype_and_ext_data() {
|
||||||
|
$data = array(
|
||||||
|
// Standard image.
|
||||||
|
array(
|
||||||
|
DIR_TESTDATA . '/images/canola.jpg',
|
||||||
|
'canola.jpg',
|
||||||
|
array(
|
||||||
|
'ext' => 'jpg',
|
||||||
|
'type' => 'image/jpeg',
|
||||||
|
'proper_filename' => false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Image with wrong extension.
|
||||||
|
array(
|
||||||
|
DIR_TESTDATA . '/images/test-image-mime-jpg.png',
|
||||||
|
'test-image-mime-jpg.png',
|
||||||
|
array(
|
||||||
|
'ext' => 'jpg',
|
||||||
|
'type' => 'image/jpeg',
|
||||||
|
'proper_filename' => 'test-image-mime-jpg.jpg',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Image without extension.
|
||||||
|
array(
|
||||||
|
DIR_TESTDATA . '/images/test-image-no-extension',
|
||||||
|
'test-image-no-extension',
|
||||||
|
array(
|
||||||
|
'ext' => false,
|
||||||
|
'type' => false,
|
||||||
|
'proper_filename' => false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Valid non-image file with an image extension.
|
||||||
|
array(
|
||||||
|
DIR_TESTDATA . '/formatting/big5.txt',
|
||||||
|
'big5.jpg',
|
||||||
|
array(
|
||||||
|
'ext' => 'jpg',
|
||||||
|
'type' => 'image/jpeg',
|
||||||
|
'proper_filename' => false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Non-image file not allowed.
|
||||||
|
array(
|
||||||
|
DIR_TESTDATA . '/export/crazy-cdata.xml',
|
||||||
|
'crazy-cdata.xml',
|
||||||
|
array(
|
||||||
|
'ext' => false,
|
||||||
|
'type' => false,
|
||||||
|
'proper_filename' => false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test a few additional file types on single sites.
|
||||||
|
if ( ! is_multisite() ) {
|
||||||
|
$data = array_merge( $data, array(
|
||||||
|
// Standard non-image file.
|
||||||
|
array(
|
||||||
|
DIR_TESTDATA . '/formatting/big5.txt',
|
||||||
|
'big5.txt',
|
||||||
|
array(
|
||||||
|
'ext' => 'txt',
|
||||||
|
'type' => 'text/plain',
|
||||||
|
'proper_filename' => false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Non-image file with wrong sub-type.
|
||||||
|
array(
|
||||||
|
DIR_TESTDATA . '/uploads/pages-to-word.docx',
|
||||||
|
'pages-to-word.docx',
|
||||||
|
array(
|
||||||
|
'ext' => 'docx',
|
||||||
|
'type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||||
|
'proper_filename' => false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue