Here is my code:
if ( $_FILES['photo']['type'] != "image/jpeg" )
echo "You attempted to upload a file of type: " . $_FILES['photo']['type'] . " ... The file must be a JPEG.";
As you can see... my code is checking to see whether or not the file type is a JPEG... if it is, it continues, else, it does not.
But even though the type IS a JPEG, I keep getting the echo that it's not:
"You attempted to upload a file of type: image/jpeg ... The file must be a JPEG."
There is just no way that that echo statement should ever be executed unless the file was NOT a JPEG.
Don't trust the mime types. If you want to be pretty sure, open the file, read the first couple of bytes, and check if it's a JPEG file header.
If you want to be really really sure, use imagecreatefromjpeg to actually load the jpeg file. If this fails, then it's apparently not a real jpeg file, no matter what mime types and file headers tell you. Note, that you need to have GD available to use this function.
I use a simple code for file upload. It actually checks file extension, not mime type. The code is below -
function getFileExtention($name) {
$split = explode('.',$name);
$splitCount = count($split) - 1;
return strtolower($split[$splitCount]);
}
if(getFileExtention($_FILES['input']['name'] != "jpg" && getFileExtention($_FILES['input']['name'] != "jpeg") {
echo "You attempted to upload a file of type: " . $_FILES['photo']['type'] . " ... The file must be a JPEG.";
}
It is unsafe to rely on the mime-type or the filename given in the $_FILES array, as they are given by the browser.
Use finfo_file instead, which will check on the server-side, based on the header/content of the file:
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $_FILES['input']['tmp_name']);
if ($mimeType != "image/jpeg") {
echo "You attempted to upload a file of type: " . $mimeType . " ... The file must be a JPEG.";
}
finfo_close($finfo);
See http://php.net/manual/en/function.finfo-file.php for documentation.
use $ext = pathinfo($_FILES["$key"]['name'], PATHINFO_EXTENSION);
Information directly from PHP's api.
Related
$filename=$_FILES['file']['name'];
$type=$_FILES['file']['type'];
$extension=strtolower(substr($filename, strpos($filename, '.')+1));
$size=$_FILES['file']['size'];
if(($extension=='jpg' || $extension=='jpeg') && ($type!='image/jpg' || $type!='image/jpeg')){...
I have a input file, can let user upload jpg/jpeg image only, I have check type, extension, size.
However I'm not sure how to check if user change extension.(ex. abc.php -> abc.jpg)
any thing else I need to check before I save user's image into my server?
You can check the image with exif_imagetype()
http://www.php.net/manual/en/function.exif-imagetype.php
exif_imagetype() reads the first bytes of an image and checks its
signature.
I would suggest using finfo:
<?php
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
foreach (glob("*") as $filename) {
echo finfo_file($finfo, $filename) . "\n";
}
finfo_close($finfo);
/* outputs:
text/html
image/gif
application/vnd.ms-excel
*/
?>
example taken from php document site.
see more info on the php document page http://www.php.net/manual/en/function.finfo-file.php
#Fabian's answer looks good for checking the type of file. While I would suggest a different approach to getting the extension of the file.
Consider a file named stack.overflow.jpg.
$filename = 'stack.overflow.jpg';
// With your code $extension = 'overflow.jpg'
$extension=strtolower( substr( $filename, strpos( $filename, '.' ) +1 ) );
// With pathinfo() $extension = 'jpg'
$extension = pathinfo( $filename, PATHINFO_EXTENSION );
Consider using pathinfo() to get the file extension: http://www.php.net/manual/en/function.pathinfo.php
I've read the Secure PHP Upload Scripts thread but I'm having difficulty getting this known good script to accept changes. I want this script to only allow .jpeg, .png, and .gif files. Could someone advise me on how to modify this script to do so?
<?php
$result=0;
if (trim($_POST["action"]) == "Upload File") { //**** User Clicked the Upload File Button
//*********** Execute the Following Code to Upload File *************
$imagename = basename($_FILES['image_file']['name']); // grab name of file
$result = #move_uploaded_file($_FILES['image_file']['tmp_name'], $imagename); // upload it
if ($result==1) echo("Successfully uploaded: <b>".$imagename."</b>"); // did it work?
} // end if
?>
<?php
if ($result==1) echo("<img src='".$imagename."'>"); // display the uploaded file
?>
$filename = $_FILES['image_file']['name'];
$ext = pathinfo($filename, PATHINFO_EXTENSION);
if($ext !== 'jpg' && $ext !== 'png' && $ext !== 'gif') {echo 'error';}
is a very bad idea for validation.
echo '<pre>';
$filename = 'image.php\0.jpg';
$extension = pathinfo($filename, PATHINFO_EXTENSION);
var_dump($ext);
The var_dump displays jpg
And the php function move_uploaded_file is vulnerable with null bytes \0.
After the move_uploaded_file the server will create a image.php file..
If you want to stop the upload before it reaches your server, you can filter it with javascript. See this SO answer for more information: stackoverflow.com/questions/71944/… – Kevin Apr 26 at 22:13
Never never never never neverever put trust in client side validation...
Coding a safe upload is hard. Very hard.
You can't trust file extensions or mime type because clients can change this.
If you only want an upload for gif, jpeg or png you could take these steps. With png you can have trouble because of the encoding that can bypass some of these.
Read the temp file by file_get_contents().
Run strip_tags() on it.
Create new images with the GD library
Serve the image by read() - Don't use include() or require()
Disable php engine on that directory
For the sake of brevity, i'm not doing any error checking.. but you can evaluate the extension of a file like this:
$filename = $_FILES['image_file']['name'];
$ext = pathinfo($filename, PATHINFO_EXTENSION);
if($ext !== 'jpg' && $ext !== 'png' && $ext !== 'gif') {echo 'error';}
I have a page for uploading videos, and I want the file types to be mp4 flash and webm files. all the mp4 extension files and webm files work fine but the flash files (.flv and .f4v) are not recognized and therefore php returns the value 'application/octet-stream' which I believe is the default MIME for any files which aren't recognized. is there a better method than this code that will recognize the flash files for there true MIMES (video/x-flv and video/x-f4v) respectively?
$type = $_FILES["uploaded"]["type"];
$allowedTypes = ["video/mp4","video/quicktime","video/x-flv","video/x- f4v",
"video/webm"];
$isRefusedType = !in_array($type, $allowedTypes);
if ($isRefusedType)
{
$message="not an accepted file type";
}
else $message="OK";
Perhaps you can try this code:
<?php
$finfo = finfo_open(FILEINFO_MIME_TYPE); // mimetype
$type = finfo_file($finfo, $filename);
finfo_close($finfo);
?>
As described here, you will need PHP >= 5.3.0, is it a problem?
Another idea could be to check the data signature (see there):
<?php
$s = file_get_contents($_FILES["uploaded"]["tmp_name"]);
if ( substr($s,0,3) == 'FLV' ) { /* It's good! */ }
?>
Watching at the description of $_FILES['userfile']['type'] in the php documentation we can see:
The mime type of the file, if the browser provided this information.
An example would be "image/gif". This mime type is however not checked
on the PHP side and therefore don't take its value for granted.
So the Tiger-222 option seems to be your best chance to get the real value:
<?php
$finfo = finfo_open();
$fileinfo = finfo_file($finfo, $file, FILEINFO_MIME);
finfo_close($finfo);
?>
I used this code to check for the type of images,
$f_type=$_FILES['fupload']['type'];
if ($f_type== "image/gif" OR $f_type== "image/png" OR $f_type== "image/jpeg" OR $f_type== "image/JPEG" OR $f_type== "image/PNG" OR $f_type== "image/GIF")
{
$error=False;
}
else
{
$error=True;
}
but some users complain they get an error while uploading any type of images, while some others don't get any errors!
I was wondering if this fixes the problem:
if (mime_content_type($_FILES['fupload']['type']) == "image/gif"){...
Any comments?
Never use $_FILES..['type']. The information contained in it is not verified at all, it's a user-defined value. Test the type yourself. For images, exif_imagetype is usually a good choice:
$allowedTypes = array(IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF);
$detectedType = exif_imagetype($_FILES['fupload']['tmp_name']);
$error = !in_array($detectedType, $allowedTypes);
Alternatively, the finfo functions are great, if your server supports them.
In addition to #deceze, you may also finfo() to check the MIME-type of non-image-files:
$finfo = new finfo();
$fileMimeType = $finfo->file($path . $filename, FILEINFO_MIME_TYPE);
Sure you could check if it's an image with exif, but a better way I think is to do with finfo like this:
$allowed_types = array ( 'application/pdf', 'image/jpeg', 'image/png' );
$fileInfo = finfo_open(FILEINFO_MIME_TYPE);
$detected_type = finfo_file( $fileInfo, $_FILES['datei']['tmp_name'] );
if ( !in_array($detected_type, $allowed_types) ) {
die ( 'Please upload a pdf or an image ' );
}
finfo_close( $fileInfo );
The best way in my opinion is first to use getimagesize() followed by imagecreatefromstring().
$size = getimagesize($filename);
if ($size === false) {
throw new Exception("{$filename}: Invalid image.");
}
if ($size[0] > 2500 || $size[1] > 2500) {
throw new Exception("{$filename}: Image too large.");
}
if (!$img = #imagecreatefromstring(file_get_contents($filename))) {
throw new Exception("{$filename}: Invalid image content.");
}
Checking by getimagesize() prevents some DoS attacks, because we don't have to try to imagecreatefromstring() from every file provided by the user, either non-image file or file too big. Unfortunately, according to PHP docs cannot be relied on for checking image type content.
The imagecreatefromstring() finally tries to open the file as an image - if is succeeds - we have an image.
This is a simple, one line script that I use often.
$image = "/var/www/Core/temp/image.jpg";
$isImage = explode("/", mime_content_type())[0] == "image";
Basically I am using mime_content_type() to get something like "image/jpg" and then exploding it by "/" and checking against the first element of the array to see if it says "image".
I hope it works!
In PHP 5.5 I use this function for getting file type and check if image:
function getFileType( $file ) {
return image_type_to_mime_type( exif_imagetype( $file ) );
}
// Get file type
$file_type = getFileType( 'path/to/images/test.png' );
echo $file_type;
// Prints image/png
// 1. All images have mime type starting with "image"
// 2. No other non-image mime types contain string "image" in it
Then you could do:
if ( strpos( $filetype, 'image' ) !== false ) {
// This is an image
}
Complete list of mime types: http://www.sitepoint.com/web-foundations/mime-types-complete-list/
That last line is close. You can use:
if (mime_content_type($_FILES['fupload']['tmp_name']) == "image/gif"){...
In the case I'm currently working on, my $_FILES..['type'] reports itself as "text/csv", while both mime_content_type() and finfo() (suggested by others) report "text/plain.". As #deceze points out, $_FILES..['type'] is only useful to know what type a client thinks a file is.
you can try this
$file_extension = explode('.',$file['name']);
$file_extension = strtolower(end($file_extension));
$accepted_formate = array('jpeg','jpg','png');
if(in_array($file_extension,$accepted_formate)) {
echo "This is jpeg/jpg/png file";
} else {
echo $file_extension.' This is file not allowed !!';
}
WARNING: the following answer does not actually check the file type. It only checks the name. It is not suitable for actual security purposes.
EDIT: Don't Use this method as it serves no security check. I am leaving this answer here so that no one makes the same mistake like me by trying this.
I tried the following and it worked for me:
$allowed = array('gif','png' ,'jpg', 'pdf');
$filename = $_FILES['input_tag_name']['name'];
$ext = pathinfo($filename, PATHINFO_EXTENSION);
if(!in_array($ext,$allowed) ) {
echo 'error';
}
Source link
Please can someone help? I have the following code which uploads a file to my server and renames it to whoever the logged in user is. For example the user 'coca-cola-lover' uploads a jpeg - the script would also rename the jpeg 'coca-cola-lover.jpg'.
My problem is that I need it to limit the upload to just jpegs - and also limit the file size to 2mb.
Please help - I was trying to find a solution all night.
Thanks in advance
// Your file name you are uploading
$file_name = $HTTP_POST_FILES['ufile']['name'];
$username = $row_Recordset1['username'];
$ext = end(explode('.', $file_name));
$renamed_file_name = $username;
$new_file_name=$renamed_file_name.'.'.$ext;
//set where you want to store files
//in this example we keep file in folder upload
//$new_file_name = new upload file name
//for example upload file name cartoon.gif . $path will be upload/cartoon.gif
$path= "../sites/images/users/".$new_file_name;
if($ufile !=none)
{
if(copy($HTTP_POST_FILES['ufile']['tmp_name'], $path))
{
echo "Successful<BR/>";
//$new_file_name = new file name
//$HTTP_POST_FILES['ufile']['size'] = file size
//$HTTP_POST_FILES['ufile']['type'] = type of file
echo "File Name :".$new_file_name."<BR/>";
echo "File Size :".$HTTP_POST_FILES['ufile']['size']."<BR/>";
echo "File Type :".$HTTP_POST_FILES['ufile']['type']."<BR/>";
}
else
{
echo "Error";
}
}
getimagesize tells you what format the file is in
as per bgy's comment, you should also force the file extension to be what you want:
$new_file_name=$renamed_file_name.'.'.$ext; // wrong, uses data from the client
$new_file_name=$renamed_file_name.'.jpg'; // ok, just what we want
never trust and never use filenames provided by the client.
I would recommend exif_imagetype:
<?php
if (exif_imagetype('image.gif') != IMAGETYPE_GIF) {
die(The picture is not a gif');
}
For details see here: http://php.net/manual/en/function.exif-imagetype.php
You can use any of the four to detect a mimetype of the file:
finfo_open (by default enabled as of 5.3)
getimagesize (requires enabled GD)
exif_imagetype (requires enabled Exif)
mime_content_type (deprecated as of 5.3)
You can also limit the MimeType from the FileUpload element, but since this is client-side code, it can easily be removed by malicious users (and it's also buggy across browsers):
<input type="file" name="picture" id="picture" accept="image/jpeg"/>
For further information on how to handle file uploads with PHP (including limiting file size), check the manual.
There is also a lot of very similar questions on Stack Overflow already, one being:
Check picture file type and size before file upload in php
You restrict the size via the normal mechanisms, but you'll need to use the fileinfo functions to determine the filetype after uploading.
A few advices for the current code
Use $_FILES instead of $HTTP_POST_FILES.
If you need to get file extensions use $extension = pathinfo($filename, PATHINFO_EXTENSION);.
Use is_uploaded_file and move_uploaded_file.
Don't relay on $_FILES['file']['type'] - it can be modified by user.
Indent your code.
If you want to limit file upload to the following requirements:
Filesize: max 2mb.
File type: image/jpeg
Do something like that:
$tmpName = $_FILES['file']['tmp_name'];
if (file_is_uploaded($tmpName) {
$filesize = fielsize($tmpName);
$mimeType = exif_imagetype('image.gif');
if ($filesize <= 2 * 1024 * 1024 && $mimeType == IMAGETYPE_JPEG) {
$filename = $USERNAME . '.jpg';
if (move_uploaded_file($tmpName, $filename) == false) {
// sth goes wrong
}
} else {
die('Invalid.');
}
}