How to check if an uploaded file is an image without mime type?

My thought about the subject is simple: all uploaded images are evil.

And not only because they can contain malicious codes, but particularly because of meta-tags. I’m aware about crawlers that browse the web to find some protected images using their hidden meta-tags, and then play with their copyright. Perhaps a bit paranoid, but as user-uploaded images are out of control over copyright issues, I take it seriousely into account.

To get rid of those issues, I systematically convert all uploaded images to png using gd. This have a lot of advantages: image is clean from eventual malicious codes and meta tags, I only have one format for all uploaded images, I can adjust the image size to fit with my standard, and… I immediately know if the image is valid or not! If the image can’t be opened for conversion (using imagecreatefromstring which doesn’t care about image format), then I consider the image as invalid.

A simple implementation could look like this:

function imageUploaded($source, $target)
{
   // check for image size (see @DaveRandom's comment)
   $size = getimagesize($source);
   if ($size === false) {
      throw new Exception("{$source}: Invalid image.");
   }
   if ($size[0] > 2000 || $size[1] > 2000) {
      throw new Exception("{$source}: Too large.");
   }

   // loads it and convert it to png
   $sourceImg = @imagecreatefromstring(@file_get_contents($source));
   if ($sourceImg === false) {
      throw new Exception("{$source}: Invalid image.");
   }
   $width = imagesx($sourceImg);
   $height = imagesy($sourceImg);
   $targetImg = imagecreatetruecolor($width, $height);
   imagecopy($targetImg, $sourceImg, 0, 0, 0, 0, $width, $height);
   imagedestroy($sourceImg);
   imagepng($targetImg, $target);
   imagedestroy($targetImg);
}

To test it:

header('Content-type: image/png');
imageUploaded('http://www.dogsdata.com/wp-content/uploads/2012/03/Companion-Yellow-dog.jpg', 'php://output');

This does not exactly answer your question as this is the same kind of hack than the accepted answer, but I give you my reasons to use it, at least 🙂

Leave a Comment