Validating image uploads with PHP - php

I have an image upload program setup that I made with PHP to allow the public to submit their images. I am having trouble finding a method to make sure the file is actually an image. I'm checking the file type, and also using getimagesize(), amongst other checks but if I rename a text file to become a JPG file my validation allows the file. How can I ensure this is actually an image? I don't want my boss to execute any infected files.

you can use Imagick's identifyImage() command.
if it gives you back image data its an image if it hands back an error or no image data then its not an image. there is a command line version of this tool you can use to: http://www.imagemagick.org/script/identify.php if you do not have php compiled with imagemagick

Check allowed extensions
.gif .jpg .jpeg .png should be allowed

How about to use Exif module's exit-imagetype() function?
http://www.php.net/manual/en/function.exif-imagetype.php
<?php
if (exif_imagetype('image.gif') != IMAGETYPE_GIF) {
echo 'The picture is not a gif';
}
?>

Reproduce the uploaded image using gd. If the image isn't reproduced, it's not an image!
If this function returns false, then it's not a valid image. I haven't worked with any more than jpg, png and gif, so there might be some more image types out there that can fit into this function (bmp?)...
function checkFileType($filetype,$tmp_name)
{
$return_val = false;
switch($filetype){
case 'image/jpg':
case 'image/jpeg':
case 'image/pjpeg':
$return_val = #imagecreatefromjpeg($tmp_name);
break;
case 'image/gif':
$return_val = #imagecreatefromgif($tmp_name);
break;
case 'image/png':
case 'image/x-png':
$return_val = #imagecreatefrompng($tmp_name);
break;
}
return $return_val;
}

Related

What should I do to make specific images show for certain file extension types?

I'm trying to implement a php, mySQL Admin panel/dashboard which shows a small preview image of the file that has been uploaded, if the file is not a jpg, jpeg, png or gif then I would like to display a placeholder image.
So for example if the uploaded file is actually a jpg, the preview column in the table would show the image associated to the file name stored in the db (this I have working) but if it's a pdf then it should show a stock/filler/predefined image of my choosing.
I'm hoping to do this in php but have very limited knowledge in this area with this project being my first large php project.
I have tried to implement this functionality using a js/jquery switch but have had no such luck, Code for the last attempt included below:
$(document).ready(function() {
var fileName, fileExtension;
fileName = event.target.innerHTML;
fileExtension = fileName.replace(/^.*\./, '');
switch (fileExtension) {
case 'png': case 'jpeg': case 'jpg':
$('#tableImg').attr("src","<?php echo $row["fileName"]; ?>");
break;
case 'zip':
$('#tableImg').attr("src","images/pdf.png");
break;
case 'pdf':
$('#tableImg').attr("src","images/pdf.png");
break;
}
});
I am no longer using this method, it was just my last attempt to get it working.
The preview column is currently called in the php file like so;
<img id="tableImg" class="admin-thumb" src="<?php echo $row["fileName"]; ?>" alt="">
I know that my current methodology will only allow the files with jpg, png and other image related extensions to show but I can't figure out how to swap out the echo $row["filename"]
What I think I'm after, and please correct me if I'm wrong is either an if, else if, else or a php switch. I just have no idea how to make it work the way mentioned earlier.
To recap:
I need an assist making a preview column of a table show either the image associated to the file name/URL or if the file type is a zip, pdf or non image file it shows a placeholder image selected by me. I did have a screenshot to share but I don't have 10 rep to do so, yet.
Any help is appreciated and my thanks in advance.
Limur
SplFileInfo should provide the extention and then just use a switch statement to set the image you want to show.
$myfile=$row["fileName"];
$info = new SplFileInfo($myfile);
$ext = $info->getExtension();
switch ($ext) {
case 'zip':
$image='zip.png';
break;
case 'pdf':
$image='pdf.png';
break;
default:
$image=$myFile;
}
<img id="tableImg" class="admin-thumb" src="<?= $image ?>" alt="">

Image resize with php image magician

I'm using PHP IMAGE MAGICIAN for resizing the images of my website.
When I try to resize the image with a changed extension (e.g. changing image.jpg to image.gif), the function returns an error because the image is invalid in this situation. I want to avoid this error.
I tried a lot of methods to check is the image valid but without success.
The error which appear is:
"file
/Users/.../uploads/1541963916_4dd672e5f3a3060ced41f3f7975453c9.gif is
missing or invalid"
Every image I upload to my website I am renaming to a new filename with its extension.
This is the part of code which I am using.
$workWithImage = new imageLib(UPLOADS_DIR . $original);
$workWithImage->resizeImage($width, $height, $type);
$workWithImage->saveImage(UPLOADS_DIR . $thumbnail, $imageQuality);
I searched for this problem but I could not find a solution.
Unfortunately looking at source this library seems to not handle this situation at all. You can create bug report at library home page. What you can do is compare mime type of file with it's extension and either do you own error handling or rename file name to have correct extension. Mime type detection code used by this library is
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $file);
finfo_close($finfo);
switch($mimeType) {
case 'image/jpeg':
case 'image/gif':
case 'image/png':
case 'image/bmp':
case 'image/x-windows-bmp':
$isImage = true;
break;
default:
$isImage = false;
}
Your File Path is not valid.
You have a path error like : "/Users/.../uploads/1541963916_4dd672e5f3a3060ced41f3f7975453c9.gif"
After /Users/ you have stille three dots "..." that is not passible .. dots for a folder backwards. And one dot . for root direcotory.
Your Errocode, says: "file /Users/.../uploads/1541963916_4dd672e5f3a3060ced41f3f7975453c9.gif is missing or invalid"
Ist Invalid PATH, that means he cant find your file in your system.

Understanding if a file is an image or a video from its content

I can not find a way to understand if a file is really a video or an image.
For example: I have a .jpg image renamed .mp4, if I open it via computer or browser I can not see anything because it is not really a video.
What I'm looking for is a way to understand if a video / image beyond the required extension is also really a video or an image, depending on the request.
In theory I would like a similar result:
$ImageOrVideo = pathinfo($_FILES["file"]["tmp_name"],PATHINFO_EXTENSION);
switch($ImageOrVideo){
case 'jpg': //check if a real image
case 'mp4': // check if a real video
default: exit('stop');
}
I had thought of some solutions, for example in the past I had used for the images getimagesize (), but now the php documentation says:
Caution This function expects filename to be a valid image file. If a
non-image file is supplied, it may be incorrectly detected as an image
and the function will return successfully, but the array may contain
nonsensical values.
Do not use getimagesize() to check that a given file is a valid image.
Use a purpose-built solution such as the Fileinfo extension instead.
$ImageOrVideo = $_FILES["file"]["tmp_name"];
switch(mime_content_type($ImageOrVideo)){
case 'image/jpeg':
// ........
break;
case 'video/mp4':
// ........
break;
default:
exit('stop');
}

PHP imagecreate() PNG from any commonly used file-format?

I currently have an image upload input that only accepts PNG, JPG/JPEG, GIF images.
If the file is valid, it then proceeds to create a thumbnail from the image using
imagecreatefrompng()
imagecopy()
imagejpg()
This works fine, but ONLY for png images, obviously.
What is the most logical and efficient way to use "imagecreatefrompng()" except using the proper file format that was submitted? All I can think of is if/else using multiple "imagecreatefrom__()" but that doesn't seem right.
Also, how can my outputted format always be PNG no matter what was submitted instead of the current imagejpg() I have now.
You will have to use a switch and determine the image type like so:
$extension = strtolower(strrchr($file, '.'));
switch ($extension) {
case '.jpg':
case '.jpeg':
$img = #imagecreatefromjpeg($file);
break;
case '.gif':
$img = #imagecreatefromgif($file);
break;
case '.png':
$img = #imagecreatefrompng($file);
break;
default:
$img = false;
break;
}
-EDIT- Didn't see the second part of your question, you just need to save it using imagepng to save it to a PNG, no need to do anything else.
Using imagecreatefromstring( file_get_contents( $filename)) would be the lazy option here.
And if you always want a png output, then just exchanging imagejpg for imagepng would do.

Not able to get image file extension

I'm using Uploadify to upload an image to the server.
The image is uploaded, and placed in the temp folder of the web server.
Now I need to work with the file beore moving it to it's real location, and I have the following code:
// Get the filepath and filename from server temp dir
$sourceFile = $_FILES[ 'Filedata' ][ 'tmp_name' ]; // e.g. c:\server\path\tmp\php159.tmp
// Solution 1 for getting file extension
$fileExt1 = pathinfo($sourceFile, PATHINFO_EXTENSION); // <-- This only returns .tmp
// Solution 2 with getimagesize
list(,,$extension) = getimagesize($sourceFile);
$fileExt2 = $extension; // this only returns the number 2.
// Solution 3 with getimagesize
$img = getimagesize($sourceFile);
$fileExt3 = $img[2]; // this only returns the number 2.
I'm not using regex to read filename, because a user may name the file anything, so I have to read file data.
Any sugegstions anyone?
Well, first off $sourceFile should be $_FILES['Filedata']['name'] instead of $_FILES['Filedata']['tmp_name'] but only for your first solution.
Now regarding your solutions/problems:
pathinfo($sourceFile, PATHINFO_EXTENSION); // should work now
getimagesize() returns a constant indicating the image type in the second index
same as point 2
Keep in mind that exif_imagetype() returns exactly the same information as the second index of getimagesize(), if you have access to this function it should perform way better.
Now for the image constants, the most common three are:
IMAGETYPE_GIF = 1
IMAGETYPE_JPEG = 2
IMAGETYPE_PNG = 3
Checking is as simple as doing something like this:
switch (exif_imagetype($_FILES['Filedata']['tmp_name']))
{
case IMAGETYPE_GIF:
echo 'is a GIF';
break;
case IMAGETYPE_JPEG:
echo 'is a JPEG';
break;
case IMAGETYPE_PNG:
echo 'is a PNG';
break;
case default:
echo 'is something else;
break;
}
One more thing, it's better to use getimagesize() / exif_imagetype() than to rely on the file extension, since the extension can be easily changed.
Your solutions #2 and #3 both work already. From the getimagesize() manual page:
Returns an array with 7 elements.
...
Index 2 is one of the IMAGETYPE_XXX constants indicating the type of the image.
So for a .gif then this should be the integer 2. To get the file extension use image_type_to_extension() since you already are using the gd library. eg.
$img = getimagesize($sourceFile);
$fileExt = image_type_to_extension($img[2])
exif_imagetype() can determine a number of graphics formats, is fast and doesn't even use GD.
Edit: I see you are already using getimagesize() and have trouble translating the constants. The exif_imagetype() page linked above has a translation of all returned image types that should be valid for getimagesize() as well.

Categories