user4271704
user4271704

Reputation: 763

How to validate a file type against its extension?

I want to create an uploader script and I want to define a few allowed file types to be uploaded, to prevent trick by renaming the file extension I use this array: PHP / Mime Types - List of mime types publically available? first it checks if file extension is allowed (e.g. .xsl) then it uses finfo to get mimtype to check with that array to see if mimetype matches the extension.

I uploaded an .xsl file, finfo retruns file type as application/octet-stream but that array for xsl extension returns application/x-msexcel so it will not be equal and not become validated.

Should I actually forget about mimetype matching with filename extension validator for the script and I should just check file extensions? or what should I do?

Upvotes: 1

Views: 4491

Answers (1)

swidmann
swidmann

Reputation: 2792

Basically you are doing it right. You should never rely on the mime type headers, that are sent from the upload form, because you can fake that easily or it is not present, then you will often get the application/octet-stream header.

So it would be a good way to check if the file extension is matching the allowed mime type for this file extension.

I saw you linked this list here. It´s surely a good list, but not really usable for php, because in the array is too much ovverriden, for example:

$mimeTypes = array(
    'xlm' => 'application/vnd.ms-excel',//overridden
    'xlm' => 'application/x-excel',
    'xls' => 'application/excel',//overridden
    'xls' => 'application/vnd.ms-excel'
);

var_dump( $mimeTypes );

This will only output two values instead of four, you should use an array like this:

$mimeTypes = array(
    'xlm' => array( 'application/vnd.ms-excel', 'application/x-excel' ),
    'xls' => array( 'application/excel', 'application/vnd.ms-excel' ),
    'txt' => array( 'text/plain' )
);

var_dump( $mimeTypes );

So you can simply check the mimetype with in_array() if you already have the file extension.

This is a basic example you you could solve it. NOTE: This is not a working example, but I think you know where I want to point out:

// you have your file, you said it´s excel but you uploaded it with extension txt
$filepath = "excel.txt";

if( strpos( $filepath, '.' ) === false ) {
    // no file extension
    // return ?
}
// get the file extension
// well there is surely a better way
$filenameParts = explode( ".", $filepath );
$fileExt = array_pop( $filenameParts );// return the las element of the array and REMOVES it from the array

// your fopen stuff to get the mime type
// ok let´s say we are getting back the follwing mime type
$fileMimeType = 'application/vnd.ms-excel';

// now check if filextension is in array and if mimetype for this extension is correct
if( isset( $mimeTypes[$fileExt] ) && in_array( $fileMimeType, $mimeTypes[$fileExt] ) ) {
    // file extension is OK AND mime type matches the file extension
} else {
    // not passed unknown file type, unknown mime type, or someone tricked you
    // your excel.txt should end up here
}

Upvotes: 1

Related Questions