[wp-trac] [WordPress Trac] #39963: MIME Alias Handling

WordPress Trac noreply at wordpress.org
Fri Nov 10 22:43:55 UTC 2017


#39963: MIME Alias Handling
--------------------------------------+-----------------------------
 Reporter:  blobfolio                 |       Owner:
     Type:  enhancement               |      Status:  reopened
 Priority:  normal                    |   Milestone:  5.0
Component:  Media                     |     Version:
 Severity:  normal                    |  Resolution:
 Keywords:  has-patch has-unit-tests  |     Focuses:  administration
--------------------------------------+-----------------------------

Comment (by blobfolio):

 All rightie, got a new patch in place (`39963.diff` and a few files for
 unit tests in `phpunit-data.zip`).

 [[BR]]


 '''Functions:'''

 This patch includes 5 new functions.

 [[BR]]

 The file-renaming logic that sometimes happens during a file upload has
 been abstracted into its own function, `wp_update_filename_extension()`.
 This simply replaces the extension on the end of the file name.
 {{{#!php
 /**
  * Assign a new extension to a filename.
  *
  * @since 5.0.0
  *
  * @param string $filename The original filename.
  * @param string $ext      The new extension.
  * @return string          The renamed file.
  */
 function wp_update_filename_extension( $filename, $ext ) {
 }}}

 [[BR]]

 In terms of actual MIME alias work, the most basic check is
 `wp_check_mime_alias()`, which is used to see whether or not a given MIME
 type is appropriate for a given file extension.
 {{{#!php
 /**
  * Check extension and MIME pairing.
  *
  * @since 5.0.0
  *
  * @param string $ext  File extension.
  * @param string $mime MIME type.
  * @return bool True/false.
  */
 function wp_check_mime_alias( $ext = '', $mime = '' ) {
 }}}

 [[BR]]

 To go a little deeper, we have `wp_check_allowed_mime_aliases()`, which
 checks to see whether a given MIME type is in the official `upload_mimes`
 list, or is an alias of a type that is in that list. ''The `upload_mimes`
 types always take priority.'' This will return an array with `ext` and
 `type` keys (the type being the official whitelist entry) if it is
 allowed, otherwise `false`.
 {{{#!php
 /**
  * Check Allowed Aliases
  *
  * This will cycle through each allowed ext/MIME pair to see if an alias
  * matches anything.
  *
  * @since 5.0.0
  *
  * @param string $alias MIME alias.
  * @param array  $mimes Allowed MIME types.
  * @return array|bool Array containing ext and type keys or false.
  */
 function wp_check_allowed_mime_aliases( $alias, $mimes = null ) {
 }}}

 [[BR]]

 Finally, we have a function that applies this alias-matching to an actual
 file. This uses a tiered approach to determine the best guess about what
 kind of a file a file actually is, and whether or not it is allowed by WP.

 This staged approach begins with a basic call to `wp_check_filetype()`,
 which determines type solely based on the file name. After that it will
 evaluate content via `EXIF` and `fileinfo.so` (if it is able to do so). If
 the "real" MIME differs from the name-based MIME, alias matching comes
 into play, and if that file is still allowed, the `ext` and `type`
 returned are updated accordingly to match reality.

 Like the original `wp_check_filetype()` function, invalid/illegal files
 result in an array with `ext` and `type` set to `false` being returned.

 {{{#!php
 /**
  * Retrieve the "real" file type from the file.
  *
  * This extends `wp_check_filetype()` to additionally consider content-
  * based indicators of a file's true type.
  *
  * The content-based type will override the name-based type if available
  * and included in the $mimes list.
  *
  * A false response will be set if the extension is not allowed, or if a
  * "real MIME" was found and that MIME is not allowed.
  *
  * @since 5.0.0
  *
  * @see wp_check_filetype()
  * @see wp_check_filetype_and_ext()
  *
  * @param string $file     Full path to the file.
  * @param string $filename The name of the file (may differ from $file due
 to $file being in a tmp directory).
  * @param array  $mimes    Optional. Key is the file extension with value
 as the mime type.
  * @return array Values with extension first and mime type.
  */
 function wp_check_real_filetype( $file, $filename = null, $mimes = null )
 {
 }}}

 [[BR]]

 And last but not least, we have a function that returns the full database
 of MIME aliases, which is auto-generated and stored in `wp-includes/media-
 mimes.php`. This data is an array, each key is a file extension, the
 values are arrays of MIME type(s) for said extension.

 {{{#!php
 /**
  * Return MIME Aliases
  *
  * @since 5.0.0
  *
  * @return array MIME aliases organized by file extension. See data below
 for example.
  */
 function wp_get_mime_aliases() {
 }}}

 [[BR]]

 '''Filters:'''

 Many of these new functions have eponymous filters that users can hook
 into to change the results:
  * `wp_get_mime_aliases`
  * `wp_check_real_filetype`
  * `wp_check_mime_alias`

 There is one additional filter that needs a bit of background:

 Most libraries will assign a file type of `application/octet-stream` to
 any file they don't understand. It is the equivalent of "I dunno." Because
 of this, the `wp_check_mime_alias()` function implicitly passes (i.e.
 returns `true`) for any extension paired with this unhelpful type.

 The filter `wp_check_mime_alias_application_octet_stream` was added to
 allow users to decide whether or not `application/octet-stream` deserves
 full checks or not. (`true` means actually check this, `false` (the
 default) means don't worry.)

 [[BR]]

 '''Behavior:'''

 The behavioral changes from this patch all stem from modifications to the
 existing `wp_check_filetype_and_ext()` function, which is called as part
 of the file upload process.

 Previously, that function ran some content-based checks on certain types
 of files, but did so in a way that resulted in false positives and
 negatives.

 Now that functionality is offloaded to `wp_check_real_filetype()`.

 First and foremost, this means that ''all'' uploaded files are now
 subjected to content-based analysis (for environments that support it).
 This fixes the security issues the changes in `4.7.1` were meant to
 handle, but also expands them to fix a lot of similar, unpublished issues.

 This also means that WordPress can now intelligently rename files that are
 using the wrong extension (but are otherwise allowed).

 [[BR]]

 '''Testing:'''

 This functionality has existed in the `Lord of the Files` plugin for some
 time and worked wonders there, but please give this patch a shot to make
 sure it behaves the same way. (Also, be sure to deactivate `LotF` if it is
 installed on your test sites.)

 For those interested in checking out the build script (that compiles the
 `media-mimes.php` file), you can find that at https://github.com/Blobfolio
 /wp-blob-mimes.

--
Ticket URL: <https://core.trac.wordpress.org/ticket/39963#comment:37>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list