Restrict file upload to just jpegs with php - php

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.');
}
}

Related

In Codeigniter How to check if the uploaded file is actually a pdf or jpg or png?

In Codeigniter How to check if the uploaded file is actually a pdf or jpg or png? Because, if we upload an .exe file with .pdf extension then also it gets uploaded without any problem. So, it there a proper way to actually check the file and its content to be able to determine whether it is actually a pdf or exe. Because with just the file extension anything can be uploaded. Please, help me find a proper solution for this. Is there any native php function through which we can achieve this. If so a sample code might be helpful.
you can use mime_content_type() function which is in built in php it provides actual content type even if the extension is changed
php docs
<?php
echo mime_content_type('abcd.pdf') //application/pdf
?>
checking mime_content_type while uploading
$mimetype = mime_content_type($_FILES['file']['tmp_name']);
if(in_array($mimetype, array('image/jpeg', 'image/gif', 'image/png'))) {
move_uploaded_file($_FILES['file']['tmp_name'], '/whatever/something/imagedir/' . $_FILES['file']['name']);
echo 'OK';
} else {
echo 'It is not an image';
}
You need to check real file type and given file type like this:
$config['upload_path'] = './uploads/';
$config['allowed_types'] = 'gif|jpg|png|pdf';
$this->load->library('upload', $config);
$file = $_FILES['userfile'];
// given file type
$gftype=pathinfo($file['name'], PATHINFO_EXTENSION);;
// real file type
$rftype = explode('/',mime_content_type($file['tmp_name']))[1];
if($gftype === $rftype){
if (! $this->upload->do_upload('userfile')){
echo "Error";
}else{
echo "Success";
}
}else{
echo 'This is not real extension';
}

How to compress image size before uploading using php

I already searched lots of stuff, some of them are from stackoverflow. But none of them helped me. What I want to do is reduce the image file size, and after reducing the image will now be uploaded. Here's my current code:
<?php
include 'cloud_functions.php';
// GET THE USER'S ID
$userid = _clean($con, $_POST['userid']);
if(!is_dir("uploads/user/".$userid."/")){
mkdir("uploads/user/".$userid."/", 0755);
}
$temp = explode(".", _clean($con,$_FILES["file"]["name"]));
$targetPath = "uploads/user/".$userid."/";
// RENAME THE IMAGE USING ROUND();
$newFN = round(microtime(true)) . '.' . end($temp);
$targetPath = $targetPath . $newFN;
// GET THE FILE EXTENSION
$type = pathinfo(_clean($con, $_POST['filename']), PATHINFO_EXTENSION);
$all_types = array('jpg', 'png', 'jpeg');
$type = strtolower($type);
if(in_array($type, $all_types)){
if(move_uploaded_file($_FILES['file']['tmp_name'], $targetPath)){
// image uploaded w/o compressing size
echo "1/".$newFN;
}else{
echo $targetPath;
echo "There was an error uploading the file, please try again!";
}
}else{
echo "Please upload a valid image.";
}
?>
In that way I can upload image successfully without compressing its size. Please tell me how to do compress image size before upload. Thanks.
You need to compress image on client side. All the code you posted here is of server side. This code will run after uploading the image to the server.
There are lot of client side libraries for this purpose.
This link will further help. You can choose use any library of your choice.
https://github.com/brunobar79/J-I-C - js library
I think better way - compress image on server after uploading, that to decrease using user memory. It's special important for slow smartphones.

How Can I Secure This PHP Upload Script

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';}

$_FILES['input']['type'] not working?

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.

Only allow .jpg and .png files only [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I only allow certain filetypes on upload in php?
How can I make the script below only allow .jpg images or .png images?
It uploads an image directory to a mysql table based on a session username match. Is it possible to restrict the file types? Because I only need .jpg or .png
if ($_POST['submit']) {
//get file attributes
$Name = $_FILES['myfile']['name'];
$tmp_name = $_FILES['myfile']['tmp_name'];
error_reporting(E_ERROR | E_PARSE);
if ($Name) {
$location = "avatars/$Name";
move_uploaded_file($tmp_name, $location ) or die('Failed to upload picture');
$query = mysql_query("UPDATE fgusers3 SET imagelocation='$location' WHERE name='$name'") or die("Your profile image has been uploaded!");
}}
echo "Upload your image below:
<form action='profilepic.php' method='POST' enctype='multipart/form-data'>
Profile Picture: <input type='file' name='myfile'> <input type='submit' name='submit' value='upload'>
</form>";
if($_FILES){
$allowedExtensions = array("jpg","png");
foreach($_FILES as $key=>$val){
if(!empty($val['tmp_name'])){
$ext = end(explode(".",strtolower(basename($val['name']))));
if(in_array($ext,$allowedExtensions)){
$file = 'PATH_TO_UPLOAD'.basename($val['name']);
if(move_uploaded_file($val['tmp_name'],$file)){
//SUCCESS_MESSAGE
}
}else{
//FAIL_MESSAGE
}
}
}
}
You can use exif_imagetype($tmp_name) to check the actual type of the file based on its header. This checks the type based on the contents of the file, so it is the most reliable (e.g. it will give you the right information even if somebody gives you a JPG with a ".png" extension).
There is also the type property ($_FILES['myfile']['type']), which will give you the MIME type that the browser claims the file is. However, this cannot be trusted if someone maliciously forges the request.
You can try using pathinfo & exif_imagetype
if(pathinfo($Name,PATHINFO_EXTENSION) != "jpg" || exif_imagetype($Name) != IMAGETYPE_JPEG)
{
// throw error
}
See More Info to detect Fake Images
$imageType = getimagesize($tmp_name);
switch ($imageType['mime'] != "image/jpg" OR $imageType['mim'] != "image/png") {
//error code here.
}
It is a bit safer than checking the extension, as the extension can be changed easily. The mime type can be changed as well but requires more knowledge xD
Of course, you can limit by file extension, but it's not safe. You can try rename a gif-file and upload it. A little bit safer is using mime-type to detect file type (but still no guarantee). Look at:
How do I find the mime-type of a file with php?
I think more safer is trying to get size of image or if convert to another image type is successful.
$whitelist = array(".jpg",".png");
foreach ($whitelist as $item) {
if(preg_match("/$item\$/i", $_FILES['uploadfile']['name'])) {
$uploaddir='uploads/uploads_image/';
// or code
}
}

Categories