diff --git a/wp-includes/formatting.php b/wp-includes/formatting.php index 37b75229e3..9b3a891e50 100644 --- a/wp-includes/formatting.php +++ b/wp-includes/formatting.php @@ -605,6 +605,39 @@ function sanitize_file_name( $filename ) { $filename = str_replace($special_chars, '', $filename); $filename = preg_replace('/[\s-]+/', '-', $filename); $filename = trim($filename, '.-_'); + + // Split the filename into a base and extension[s] + $parts = explode('.', $filename); + + // Return if only one extension + if ( count($parts) <= 2 ) + return apply_filters('sanitize_file_name', $filename, $filename_raw); + + // Process multiple extensions + $filename = array_shift($parts); + $extension = array_pop($parts); + $mimes = get_allowed_mime_types(); + + // Loop over any intermediate extensions. Munge them with a trailing underscore if they are a 2 - 5 character + // long alpha string not in the extension whitelist. + foreach ( (array) $parts as $part) { + $filename .= '.' . $part; + + if ( preg_match("/^[a-zA-Z]{2,5}\d?$/", $part) ) { + $allowed = false; + foreach ( $mimes as $ext_preg => $mime_match ) { + $ext_preg = '!(^' . $ext_preg . ')$!i'; + if ( preg_match( $ext_preg, $part ) ) { + $allowed = true; + break; + } + } + if ( !$allowed ) + $filename .= '_'; + } + } + $filename .= '.' . $extension; + return apply_filters('sanitize_file_name', $filename, $filename_raw); } diff --git a/wp-includes/functions.php b/wp-includes/functions.php index 3984a3164f..a26cc3a4e2 100644 --- a/wp-includes/functions.php +++ b/wp-includes/functions.php @@ -2226,8 +2226,36 @@ function wp_ext2type( $ext ) { * @return array Values with extension first and mime type. */ function wp_check_filetype( $filename, $mimes = null ) { - // Accepted MIME types are set here as PCRE unless provided. - $mimes = ( is_array( $mimes ) ) ? $mimes : apply_filters( 'upload_mimes', array( + if ( null === $mimes ) + $mimes = get_allowed_mime_types(); + $type = false; + $ext = false; + + foreach ( $mimes as $ext_preg => $mime_match ) { + $ext_preg = '!\.(' . $ext_preg . ')$!i'; + if ( preg_match( $ext_preg, $filename, $ext_matches ) ) { + $type = $mime_match; + $ext = $ext_matches[1]; + break; + } + } + + return compact( 'ext', 'type' ); +} + +/** + * Retrieve list of allowed mime types and file extensions. + * + * @since 2.8.6 + * + * @return array Array of mime types keyed by the file extension regex corresponding to those types. + */ +function get_allowed_mime_types() { + static $mimes = false; + + if ( !$mimes ) { + // Accepted MIME types are set here as PCRE unless provided. + $mimes = apply_filters( 'upload_mimes', array( 'jpg|jpeg|jpe' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png', @@ -2273,24 +2301,11 @@ function wp_check_filetype( $filename, $mimes = null ) { 'odc' => 'application/vnd.oasis.opendocument.chart', 'odb' => 'application/vnd.oasis.opendocument.database', 'odf' => 'application/vnd.oasis.opendocument.formula', - ) - ); - - $type = false; - $ext = false; - - foreach ( $mimes as $ext_preg => $mime_match ) { - $ext_preg = '!\.(' . $ext_preg . ')$!i'; - if ( preg_match( $ext_preg, $filename, $ext_matches ) ) { - $type = $mime_match; - $ext = $ext_matches[1]; - break; - } + ) ); } - return compact( 'ext', 'type' ); + return $mimes; } - /** * Retrieve nonce action "Are you sure" message. *