File-type verification Published the 2020-05-25 When allowing users to upload files, it's important to make sure that it's the expected format(s). There are lots of solutions on Internet, but some are just plain awful, bad practices, and only still around due to misconceptions and bad habits. ## Bad idea: Using the extension to check a file's format For everyone used to knowing that a `.jpeg` file is an image, `.pptx` file is a presentation file, and `.html` is a HTML file, here's a huge news: your computer *doesn't give a fuck* about the thing at the end of the file. You can call your image `thisisnotanimage.mp4` and it won't change the fact that *it is* an image. What does that mean? Well, simply that if you validate file type by checking the extension, and if someone want to upload, for example, a malicious PHP file, they can simply add an "accepted" extension. You'd then receive a file named `virus.php.png`, and you'd gladly accept it! Solutions based on file extension should simply be dropped. ## Good idea: Using the mime-type to check a file's format The first question to ask is "what does *format* means?". Basically, if the file respects a certain structure, which is tied to a certain format specification, it is recognized to be of said format. The current "best-practice" solution to check this "structure" is the "Mime-type" mechanism. Basically, a Mime is a set of expected indexes and values for a given format. For example, a very naïve way to check if an image is a PNG file is to check if the file is *at least* 4 bytes long, and to check if the first 4 bytes are of value `%PNG`. A PNG file being expected to have this format, that means that any file following this format would be considered as a valid PNG file. > Note that it's a dumbed-down rule, to keep the example simple. So, for PHP, how do you actually check a file's format? [mct]: https://secure.php.net/manual/en/function.mime-content-type.php You have several ways, the simplest being [`mime_content_type($filename);`][mct]. As an example, if the file you want to test is available at a path stored in `$path`, the following code would return the mime-type. ```php