8
votes

I’m working on an upload form in PHP that must allow only MP3 files.

When the upload is done, I analyze the file to check whether is it really an MP3. The first step is to detect the mime type as audio/mpeg. I use the libraries finfo_file() and works fine except that during the tests some MP3 files are rejected because their MIME type results as application/octet-stream.

My questions are:

  • Should my app definitely refuse those MP3 files? They actually play audio.
  • Is there any reason why this MIME type is an MP3?
  • is the detection of MIME type the most sure way to know the kind of file?
3

3 Answers

3
votes

In most of my applications where upload is necessary, I sometimes settle for validating the MIME that is passed by the browser (client) against a list of predefined MIME types. This approach makes a general assumption that if something suspicious is going on where the browser is unable to communicate the MIME type of a file being uploaded, I probably don't want to bother processing it at this time.

<?php

$valid_mp3_mimes = array(
    'audio/mpeg',
    'audio/x-mpeg',
    'audio/mp3',
    'audio/x-mp3',
    'audio/mpeg3',
    'audio/x-mpeg3',
    'audio/x-mpeg-3',
    'audio/mpg',
    'audio/x-mpg',
    'audio/x-mpegaudio',
    'video/mpeg',
    'video/x-mpeg',
);

$uploaded_file_mime = $_FILES['upload_field_name']['type'];

if(!in_array($uploaded_file_mime, $valid_mp3_mimes))
{
    die('Upload is not a valid MP3 file.');
}

You may or may not feel this is sufficient method for your purposes. The PHP Manual explicitly states that this information is available if the browser provided this information and that the MIME type is NOT checked on the server side and therefore should not be taken for granted.

One thing to take into consideration is the availability of resources on the server that allow you to authenticate the true MIME type of a file.

As PHP developers, we love the flexibility of creating platform independent code for the most part (e.g. our web applications built on a Windows system running XAMPP can be deployed to a Linux hosting environment with very little modification). However, when validating MIME types, we begin introducing platform dependent methods that necessitate verifying the existence of these tools (such as "file" or "finfo_file").

This might be one implementation worth studying (taken from the CodeIgniter GitHub repository) that utilizes these tools and is about as thorough of a working example as you're going to get within the scope of PHP:

File MIME type detects the (actual) MIME type of the uploaded file, if possible. https://github.com/EllisLab/CodeIgniter/blob/develop/system/libraries/Upload.php#L983


Sources

PHP Manual POST method uploads - http://www.php.net/manual/en/features.file-upload.post-method.php

Webmaster Toolkit Mime Types - http://www.webmaster-toolkit.com/mime-types.shtml

FILExt .MP3 File - http://filext.com/file-extension/MP3

0
votes

If you want an extremely robust way of detecting filetypes without just trusting the client to provide the correct MIME type, use the file utility on UNIX.

$ file Black\ Sands\ 01\ Prelude.mp3
Black Sands 01 Prelude.mp3: Audio file with ID3 version 2.2.0, contains: MPEG ADTS, layer III, v1, 320 kbps, 44.1 kHz, Stereo

$ file homework/math475-hw8.docx
homework/math475-hw8.docx: Microsoft Word 2007+

In PHP you can use the exec function to invoke it.

0
votes

The best method of file detection is using the "magic byte" or "magic number" scheme, in addition to MIME. Unix file (as well as finfo_file) actually uses "magic bytes" to do this file detection. So, in short: yes.

Don't worry so much about what your file looks like, and more about what you can do with it. As long as it plays, the file should be okay.

If you really want to do more, you can check for the magic bytes yourself. There is a list of them here.