how to verify an image format with php - php

i need to verify a lot of images files for an application, the situations is that i have 10 directories with almost 10,000 images on each one, something like 100,000 files. Those files are supposed to be gif files but a lot of them (and really mean a lot) were jpg files that a designer change the extension from .jpg to .gif without converting the file format. This is causing the application crash, it creates pdf files using those images, and if i tell to the programm that use the file somefile.gif but it really is a jpg with the extension renamed the pdf creator crashes. I don't want to open every file in something like irfanview or photoshop to verify the format and then modify it if is necessary. Is there a library, class, plugin or something in php or another language that tell me the format of files with no base in the extension but in the headers of the file?
I can't find any ideas to do this, some one can help me?
Thanxs a lot in advance!!!

I personally use exif_imagetype for a true verification rather than checking extensions or mime types.

If you need to find out between gif or jpeg, the function getimagesize() can do that for you. See http://php.net/getimagesize.
list(,,$imageType) = getimagesize($path);
if ($imageType === IMAGETYPE_GIF) {
// GIF found
}

Related

tif to pdf/png enocoding

I am working on application where input files having extension .tif(Tagged Image File Format (TIFF)). The basic problem is to display .tif files in all browser which is not applicable on all major browsers. The solution i have accept is to convert them into png
I have am converting .tif file to png using http://image.intervention.io/api/encode in PHP Laravel 5.5
Image intervention is depends on imagick for tif encoding, i have installed this dependency but the encoding scheme is converting/display/store first image from tif file, not all files.
Can any one have solution from tif to PNG or PDF conversion using any PHP library?
I found very nice article here, the approach to solve this problem is,
$file = Storage::disk('s3')->get(request()->file_name);
$file_pdf =storage_path("app/bundle/tmp/".end($name).".pdf");
$document =new \Imagick();
$document->readImageBlob($file);
if (!$document->writeImages($file_pdf, true)) {
echo "Unable to write the file";
} else {
$document->clear();
}
return response()->file($file_pdf)->deleteFileAfterSend(true);
I have read s3 file stream using laravel storage and pass that blob using Imagick readImageBlob() method. The state of the art is $document->writeImages("to_pdf.pdf") file. At the end you can clear the file variable
My suggestion is: You have to use gdal2tiles.py to convert your .tif file into .png.
gdal2tiles Documentation
When you run this command its create an output folder, in which you get openlayers.html file, open it and see your .tif file in every browser easily.
If you need any help related to this, do comment. I'll guide you.

Saving different image types with php and just renaming the target file path?

How much difference does it make if I want to save all uploaded images to my site as gif if I just do...
$target = 'images/avatars/' . md5($user['id']) . '.gif';
Rather than creating a gif in php copying the temp image and then saving? Will the browser still load the file? Will it still recognise the old file type? Does it really matter from a point of view where these images will never be downloaded purposelly through my site?
Thanks
Yes, you can rename images to .gif and browsers will still display them as jpg even if you load them with a .gif extension.
It will still have a jpg filetype, just with a .gif extension. (Just tested this)

Secure User Image Upload Capabilities in PHP

I'm implementing a user-based image uploading tool for my website. The system should allow any users to upload JPEG and PNG files only. I'm, of course, worried about security and so I'm wondering how the many smarter people than myself feel about the following checks for allowing uploads:
1) First white list the allowable file extensions in PHP to allow only PNG, png, jpg, JPG and JPEG. Retrieve the user's file's extension via a function such as:
return end(explode(".", $filename));
This should help disallow the user from uploading something malicious like .png.php. If this passes, move to step 2.
2) Run the php function getimageize() on the TMP file. Via something like:
getimagesize($_FILES['userfile']['tmp_name']);
If this does not return false, proceed.
3) Ensure a .htaccess file is placed within the uploads directory so that any files within this directory cannot parse PHP files:
php_admin_value engine Off
4) Rename the user's file to something pre-determined. I.E.
$filename = 'some_pre_determined_unique_value' . $the_file_extension;
This will also help prevent SQL injection as the filename will be the only user-determined variable in any queries used.
If I perform the above, how vulnerable for attack am I still? Before accepting a file I should hopefully have 1) only allowed jpgs and pngs, 2) Verified that PHP says it's a valid image, 3) disabled the directory the images are in from executing .php files and 4) renamed the users file to something unique.
Thanks,
Regarding file names, random names are definitely a good idea and take away a lot of headaches.
If you want to make totally sure the content is clean, consider using GD or ImageMagick to copy the incoming image 1:1 into a new, empty one.
That will slightly diminish image quality because content gets compressed twice, but it will remove any EXIF information present in the original image. Users are often not even aware how much info gets put into the Metadata section of JPG files! Camera info, position, times, software used... It's good policy for sites that host images to remove that info for the user.
Also, copying the image will probably get rid of most exploits that use faulty image data to cause overflows in the viewer software, and inject malicious code. Such manipulated images will probably simply turn out unreadable for GD.
Regarding your number 2), don't just check for FALSE. getimagesize will also return the mime type of the image. This is by far a more secure way to check proper image type than looking at the mime type the client supplies:
$info = getimagesize($_FILES['userfile']['tmp_name']);
if ($info === FALSE) {
die("Couldn't read image");
}
if (($info[2] !== IMAGETYPE_PNG) && ($info[2] !== IMAGETYPE_JPEG)) {
die("Not a JPEG or PNG");
}
All the checks seem good, number 3 in particular. If performance is not an issue, or you are doing this in the background, you could try accessing the image using GD and seeing if it is indeed an image and not just a bunch of crap that someone is trying to fill your server with.
Concerning No. 2, I read on php.net (documentation of the function getimagesize() ):
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.

PHP Upload File Validation

I am creating file upload script and I'm looking for the best techniques and practices to validate uploaded files.
Allowed extensions are:
$allowed_extensions = array('gif','jpg','png','swf','doc','docx','pdf','zip','rar','rtf','psd');
Here's the list of what I'm doing.
Checking file extension
$path_info = pathinfo($filename);
if( !in_array($path_info['extension'], $allowed_extensions) ) {
die('File #'.$i.': Incorrent file extension.');
}
Checking file mime type
$allowed_mimes = array('image/jpeg','image/png','image/gif','text/richtext','multipart/x-zip','application/x-shockwave-flash','application/msword','application/pdf','application/x-rar-compressed','image/vnd.adobe.photoshop');
if( !in_array(finfo_file($finfo, $file), $allowed_mimes) ) {
die('File #'.$i.': Incorrent mime type.');
}
Checking file size.
What should I do to make sure uploaded files are valid files? I noticed strange thing. I changed .jpg file extension to .zip and... it was uploaded. I thought it will have incorrect MIME type but after that I noticed I'm not checking for a specific type but if a specific MIME type exist in array. I'll fix it later, that presents no problems for me (of course if you got any good solution/idea, do not hesitate to share it, please).
I know what to do with images (try to resize, rotate, crop, etc.), but have no idea how to validate other extensions.
Now's time for my questions.
Do you know good techniques to validate such files? Maybe I should unpack archives for .zip/.rar files, but what about documents (doc, pdf)?
Will rotating, resizing work for .psd files?
Basically I thought that .psd file has following mime: application/octet-stream but when
I tried to upload .psd file it showed me (image/vnd.adobe.photoshop). I'm a bit confused about this. Do files always have the same MIME type?
Also, I cannot force code block to work. Does anyone have a guess as to why?
Lots of file formats have a pretty standard set of starting bytes to indicate the format. If you do a binary read for the first several bytes and test them against the start bytes of known formats it should be a fairly reliable way to confirm the file type matches the extension.
For example, JPEG's start bytes are 0xFF, 0xD8; so something like:
$fp = fopen("filename.jpg", "rb");
$startbytes = fread($fp, 8);
$chunked = str_split($startbytes,1);
if ($chunked[0] == 0xFF && $chunked[1] == 0xD8){
$exts[] = "jpg";
$exts[] = "jpeg";
}
then check against the exts.
could work.
If you want to validate images, a good thing to do is use getimagesize(), and see if it returns a valid set of sizes - or errors out if its an invalid image file. Or use a similar function for whatever files you are trying to support.
The key is that the file name means absolutely nothing. The file extensions (.jpg, etc), the mime types... are for humans.
The only way you can guarantee that a file is of the correct type is to open it and evaluate it byte by byte. That is, obviously, a pretty daunting task if you want to try to validate a large number of file types. At the simplest level, you'd look at the first few bytes of the file to ensure that they match what is expected of a file of that type.

why some mp3s on mime_content_type return application/octet-stream

Why is it that on some mp3s files, when I call mime_content_type($mp3_file_path) it returns application/octet-stream?
This is my code:
if (!empty($_FILES)) {
$tempFile = $_FILES['Filedata']['tmp_name'];
$image = getimagesize($tempFile);
$mp3_mimes = array('audio/mpeg', 'audio/x-mpeg', 'audio/mp3', 'audio/x-mp3', 'audio/mpeg3', 'audio/x-mpeg3', 'audio/mpg', 'audio/x-mpg', 'audio/x-mpegaudio');
if (in_array(mime_content_type($tempFile), $mp3_mimes)) {
echo json_encode("mp3");
} elseif ($image['mime']=='image/jpeg') {
echo json_encode("jpg");
} else{
echo json_encode("error");
}
}
EDIT:
I've found a nice class here:
http://www.zedwood.com/article/127/php-calculate-duration-of-mp3
MP3 files are a strange beast when it comes to identifying them. You can have an MP3 stored with a .wav container. There can be an ID3v2 header at the start of the file. You can embed an MP3 essentially within any file.
The only way to detect them reliably is to parse slowly through the file and try to find something that looks like an MP3 frame. A frame is the smallest unit of valid MP3 data possible, and represents (going off memory) 0.028 seconds of audio. The size of the frame varies based on bitrate and sampling rate, so you can't just grab the bitrate/sample rate of the first frame and assume all the other frames will be the same size - a VBR mp3 must be parsed in its entirety to calculate the total playing time.
All this boils down to that identifying an MP3 by using PHP's fileinfo and the like isn't reliable, as the actual MP3 data can start ANYWHERE in a file. fileinfo only looks at the first kilobyte or two of data, so if it says it's not an MP3, it might very well be lying because the data started slightly farther in.
application/octet-stream is probably mime_content_type s fallback type when it fails to recognize a file.
The MP3 in that case is either not a real MP3 file, or - more likely - the file is a real MP3 file, but does not contain the "magic bytes" the PHP function uses to recognize the format - maybe because it's a different sub-format or has a variable bitrate or whatever.
You could try whether getid3 gives you better results. I've never worked with it but it looks like a pretty healthy library to get lots of information out of multimedia files.
If you have access to PHP's configuration, you may also be able to change the mime.magic file PHP uses, although I have no idea whether a better file exists that is able to detect your MP3s. (The mime.magic file is the file containing all the byte sequences that mime_content_type uses to recognize certain file types.)
Fleep is the answer to this question. Allowing application/octet-stream is dangerous since .exe and other dangerous files can display with that mime type.
See this answer https://stackoverflow.com/a/52570299/14482130

Categories