Description :
I have given the interface to the user where he/she can upload pdf,doc,docx,img files perfectly.
Every thing is done except I have a confusion on one little piece of code. So before knowing any reason why its done I cant just write it in my php.
While uploading any file at first we do check the type of file before taking any further actions.
Now there are two ways by which we can check one is
$ext = end(explode(".",$_FILES['upload'][name]));
if(in_array($ext,$array_name_of_all_allowed_extensions))
OR
if($_FILES['upload']['type'] == "application/pdf")
{
//any action
}
but every where I see the code for uploading the file is as
$allowedExts = array("pdf", "doc", "docx");
$extension = end(explode(".", $_FILES["file"]["name"]));
if ((($_FILES["file"]["type"] == "application/pdf")
|| ($_FILES["file"]["type"] == "application/msword"))
&& ($_FILES["file"]["size"] < 20000000)
&& in_array($extension, $allowedExts))
{
if ($_FILES["file"]["error"] > 0)
{
echo "Return Code: " . $_FILES["file"]["error"] . "<br>";
}
every one seems to be using the both .. the if condition for the type and in_array() as well.
Can any one tell me why is that. I mean using any one of them in_array() preferred should do the job
Is this understandable :
$ext = end(explode(".",$_FILES['upload'][name]));
if(in_array($ext,$array_name_of_all_allowed_extensions))
the above piece of code my fellow programmer is to check the extension of the file user uploaded it can be any weird extension that you don't your web app to upload so you define an array that only the files that end with ".jpeg , .jpg , .pdf" etc are allowed to be uploaded
if ((($_FILES["file"]["type"] == "application/pdf")
this above line of code checks the type of uploaded file that whether it is the type you allow or not
you can write .exe at the end of any pdf file and it will update the name of the file to mypdf.exe how ever the type of the file will still remain pdf document and it will open as regular as it should ... So checking through if is just a little work that the file being uploaded has a correct name and not been tampered with ...
Its entirely your choice otherwise if you make an array of the allowed file type and then use in_array() that is enough too ... hope that helps :) ile that whether
Related
Hi can someone help with this bit of code I am trying use to handle and test my file uploads in PHPMailer? It basically checks that the file is correct and then renames the file name by using the users name plus field name and a date and time. There are multiple files but I am not using a multi uploader but instead separate fields so I can keep a track of which file is which.
The script seems to work and there are no errors in the php error logs but I'm told this is a security flaw in my previous post and that my "pathinfo call should be testing the path to the tmp_name of the actual file and NOT the given original name. This is a serious security flaw."
Unfortunately I'm not sure which of the 2 usages of pathinfo is wrong. If I change $file["name"] to $file["tmp_name"] for $imageFileExt then I don't get a file extension and if I change $file["name"] to $file["tmp_name"] on $imageFileType then I just get wrongfile error. Any help would be much appreciated. Thanks.
foreach ( $_FILES as $key => $file ) {
//get the file extension
$imageFileExt = strtolower( pathinfo( $file["name"], PATHINFO_EXTENSION ) );
//change the name of each file in $_FILES array to
//the persons name plus file field plus date plus time plus file extension
//such as :joe_bloggs_bank_statement_1_9_10_21_10_55.jpg
//and joe_bloggs_pay_slip_1_9_10_21_10_55.jpg
$file['name'] = clean($_POST['appName']). "_" . $key . "_" . $dateKey . "." . $imageFileExt;
// get the file type
$target_file = $target_dir . basename($file["name"]);
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
// get file size
$check = getimagesize($file["tmp_name"]);
if($check === false) {
$fileMessage .= $key."=noimage,";
$uploadOk = 0;
}
// Allow certain file formats
else if($imageFileType !== "jpg" && $imageFileType !== "png" && $imageFileType !== "jpeg"
&& $imageFileType !== "gif" ) {
$fileMessage .= $key."=wrongfile,";
$uploadOk = 0;
}
// Check if file already exists
else if (file_exists($target_file)) {
$fileMessage .= $key."=fileexists,";
$uploadOk = 0;
}
// Check file size
else if ($file["size"] > 20000000) { //20mb
$fileMessage .= $key."=toobig,";
$uploadOk = 0;
}
// creates a set of links to the uploaded files on the server
// to be placed in the body of the email (the files themselves do not get attached in the email
$fileString .= strtoupper($key).": <a href='example.com/uploads/".$file['name']."'>".$file['name']."</a><br>";
}
I think you may be confused by the distinction between these things. The file itself is a bunch of bytes provided by the user. Its filename is metadata about that file, also supplied by the user. The tmp_name is also metadata about the file, but is safe because it is not supplied by the user.
At no point are you using move_uploaded_file() or is_uploaded_file(). These are necessary to validate that the uploaded files are real uploaded files that have been handled correctly by PHP before your script is run. That's the very first thing you should do before trusting anything else in $_FILES.
The reason it's important to not trust the name property is that filenames can be used as an attack vector, for example by including path traversal sequences (such as ../), SQL escapes ('), or characters that might do unexpected things if used in shell contexts (\, >, etc). The tmp_name is generated by PHP itself and does not contain user-supplied data, though you need to use the functions mentioned above to ensure that this is real data and not also injected
by the user.
Similarly, the filename can't be relied upon to tell you accurately what type a file is – search for "polyglot files" for why that can be a problem.
You don't show what's in your clean() function, so we can't say whether what it does is effective.
In your previous question I referred you to the PHPMailer send file upload example. This shows how to handle an upload safely. For example, it takes whatever name is provided and hashes it, producing a string that is guaranteed to be safe from user-supplied data that is not.
Good morning guys. I have created two php files that successfully upload files to my server. One file is the visual part for my website called upload.php and the other is the upload file part called upload_file.php.
the code to upload my files is
move_uploaded_file($_FILES['file']['tmp_name'],"./medetrax_backup/{$_FILES['file']['name']}");
This works perfectly however it lets me upload any file type. So since I want to only allow zipped folders i tried this if statement.
if($type=="application/zip" ){
move_uploaded_file($_FILES['file']['tmp_name'],"./medetrax_backup/{$_FILES['file']['name']}");
echo "<div id='mes'> File upload complete</div>";}
else{
echo "<div id='mes'>This file type cannot be uploaded. Only zip folders with the naming convention INITIAL.DATE.TIME are accepted</div>";
}
where $type=$_FILES['file']['type'];
But now it doesnt let me upload any files not even zipped ones. So what do i need to put in my if statement to only allow zipped folders to be upload? And if your really good guys what do i need to put in my if statement to allow only zipped foleders with the naming convention of USERINITIAL.DATE.TIME or USERINITIAL/DATE/TIME or can this not be done?
You can use this solution
$fileName = strtolower($fileName);
$allowedExts = array('zip');
$extension = explode(".", $fileName);
$extension = end($extension);
if(in_array($extension, $allowedExts))
{
//move file to custom folder
}
IMPORTANT *
Never not use from mime time for identification file type,because it bypass with tamper data.
Best way:
Move your all uploaded file into out of public_html,and Always rename file name,when you want upload this.
And so,save uploaded file name into database,and read file from one php file,for example:
read.php?id=5
in your read.php file,you should get id number and search on database for it,then,return file name from db and download or read this file with read.php file.
Due to some discussion on this thread, heres a little bonus info.
Generally speaking, it's really, really hard to determine if a file is actually the kind of file we want. You can check the mime type, which can be modified by the client. You can check the file extension, which can also be modified by the client- Vice versa.
You can even check the first few lines of a file, which typically contains some sort of header, explaining what kind of file we'r handling. But still then, the file might be modified by some evil genius making the executing program buffer overflow or exploits some library used, to open/view/taste/throw the file.
Lets check both file extension and mime.
First, the extension.
$extension = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
$isZipExtension = ( $extension == "zip" ? true : false );
On your "$_FILES" array, you have a index called "Type".
Now, you would like to restrict the upload to only accept Zip files.
Theres a few types defining a potential zip file. So lets create an array.
$zipTypes = array('application/zip', 'application/x-zip-compressed',
'multipart/x-zip', 'application/x-compressed');
Now, lets check if the type uploaded, is part of the array.
$isZipFile = in_array( $_FILES['file']["type"], $zipTypes );
If, the file is in the array, do your upload process.
if( $isZipFile && $isZipExtension) {
move_uploaded_file($_FILES['file']['tmp_name'],"./medetrax_backup/{$_FILES['file']['name']}");
echo "<div id='mes'> File upload complete</div>";
} else {
echo "<div id='mes'>This file type cannot be uploaded. Only zip folders with the naming convention INITIAL.DATE.TIME are accepted</div>";
}
All together
$zipTypes = array('application/zip', 'application/x-zip-compressed',
'multipart/x-zip', 'application/x-compressed');
$extension = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
$isZipExtension = ( $extension == "zip" ? true : false );
$isZipFile = in_array( $_FILES['file']["type"], $zipTypes );
if( $isZipFile && $isZipExtension) {
move_uploaded_file($_FILES['file']['tmp_name'],"./medetrax_backup/{$_FILES['file']['name']}");
echo "<div id='mes'> File upload complete</div>";
} else {
echo "<div id='mes'>This file type cannot be uploaded. Only zip folders with the naming convention INITIAL.DATE.TIME are accepted</div>";
}
Hope it helps.
Ironically, you should never use the type key to check the type of file being uploaded. That's because the value of that key is set by the client and can be trivially spoofed.
What you should be doing instead is checking the file extension (which at least makes sure that no well-configured program on your server will treat the upload in an unexpected manner):
$ext = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
$allowed = ['zip'];
if (in_array($ext, $allowed)) {
// process the file
}
I'm trying to implement Valum's file uploader (improved by Ben Colon https://github.com/bencolon/file-uploader) and I'm running into a problem. Previously, my upload.php had the upload target set in accordance to certain input fields. See here:
//Directory where files are stored
if ($grade == '9')
{
$target = "storage/g9/";
}
elseif ($grade == '10')
{
$target = "storage/g10/";
}
elseif ($grade == '11')
{
$target = "storage/g11/";
}
elseif ($grade == '12')
{
$target = "storage/g12/";
}
$target = $target . $_POST['snumber'] . "." . $extension;
move_uploaded_file($_FILES['upload']['tmp_name'], $target);
Now, with an AJAX based file uploader it starts uploading before you even hit submit so PHP doesn't get a chance to pickup the input fields to decide what the upload path is going to be, it can only go to a predefined one. To see how the AJAX file uploader does it, view their PHP on GitHub. How do I make it so the upload path changes depending on the user input fields?
I believe PHP needs to know where to save the file as soon as you start uploading it. But, you can move the file once it's finished uploading, via PHP's rename() function.
There's also move_uploaded_file() (although I've never used it myself).
Recently I am developing website baker's module. There is one option to upload image. I am using php image upload code but give the following error and image didn't upload.
Warning: move_uploaded_file(http://localhost/wb/media/gallery/mypic.jpg) [function.move-uploaded-file]: failed to open stream: HTTP wrapper does not support writeable connections in C:\wamp\www\wb\modules\hotelmod\save_picture.php on line 84
Warning: move_uploaded_file() [function.move-uploaded-file]: Unable to move 'C:\wamp\tmp\phpBBBD.tmp' to 'http://localhost/wb/media/gallery/mypic.jpg' in C:\wamp\www\wb\modules\hotelmod\save_picture.php on line 84
here's the code that i use:
if (($_FILES["image"]["type"] == "image/jpeg" || $_FILES["image"]["type"] == "image/pjpeg" || $_FILES["image"]["type"] == "image/gif" || $_FILES["image"]["type"] == "image/x-png") && ($_FILES["image"]["size"] < 4000000))
{
// if uploaded image was JPG/JPEG
if($_FILES["image"]["type"] == "image/jpeg" || $_FILES["image"]["type"] == "image/pjpeg"){
$image_source = imagecreatefromjpeg($_FILES["image"]["tmp_name"]);
}
// if uploaded image was GIF
if($_FILES["image"]["type"] == "image/gif"){
$image_source = imagecreatefromgif($_FILES["image"]["tmp_name"]);
}
// BMP doesn't seem to be supported so remove it form above image type test (reject bmps)
// if uploaded image was BMP
if($_FILES["image"]["type"] == "image/bmp"){
$image_source = imagecreatefromwbmp($_FILES["image"]["tmp_name"]);
}
// if uploaded image was PNG
if($_FILES["image"]["type"] == "image/x-png"){
$image_source = imagecreatefrompng($_FILES["image"]["tmp_name"]);
}
$remote_file = WB_URL.'/modules/hotelmod/images/'.$_FILES["image"]["name"];
move_uploaded_file($_FILES['image']['tmp_name'], $remote_file);
}
How can I resolve this? Thanks in advance.
You're probably trying to do something like:
move_uploaded_file($_FILES['somefile']['tmp_name'], 'http://localhost/wb/media/gallery/mypic.jpg');
This is incorrect. Attempting to write to a URL would only trigger yet another HTTP upload, which is what you're already trying to handle.
The destination/target of move_uploaded_files() must be a file system path, something like
/home/sites/yoursite/document_root/images/mypic.jpg
instead.
You're passing a URL to move_uploaded_file(). move_uploaded_file() needs a path. Not a URL. Probably something like (for windows) C:\path\to\save\uploads
You destination must be a file system path, not a URL. Its up to your web server to map URLs to filesystem paths to find the file (but of course your scripts need to know how it does that so you can create links to it).
E.g., you could configure your server to serve http://example.com/uploads/ from /srv/www/example.com/uploads/. Then you'd have your PHP script move the file to /srv/www/example/com/uploads/FOO.png.
Make sure to turn off PHP (and CGI, etc.) in your upload directory for security reasons. E.g., in Apache, you'd do:
<Directory /srv/www/example.com/uploads>
php_admin_flag engine off
</Directory>
I'm trying to add a file upload script in php to a website I'm designing. I've used an online example (I know it's not secure and I plan on making it secure, I just want the basic functionality working first).
Basically what's happening is that when I click the "submit" button, the page stalls and says "loading xyz server.." forever and doesn't ever go to the post action php page! This is very frustrating and I can't see why it won't work!
The code is below and I've tried this on 2 different servers with same results. I'd be very grateful if someone could let me know what I'm possibly doing wrong?
<html>
<body>
<form enctype="multipart/form-data" action="do.php" method="post">
<input type="hidden" name="MAX_FILE_SIZE" value="1000000" />
Choose a file to upload: <input name="uploaded_file" type="file" />
<input type="submit" value="Upload" />
</form>
</body>
</html>
<?php
//Сheck that we have a file
if((!empty($_FILES["uploaded_file"])) && ($_FILES['uploaded_file']['error'] == 0)) {
//Check if the file is JPEG image and it's size is less than 350Kb
$filename = basename($_FILES['uploaded_file']['name']);
$ext = substr($filename, strrpos($filename, '.') + 1);
if (($ext == "jpg") && ($_FILES["uploaded_file"]["type"] == "image/jpeg") &&
($_FILES["uploaded_file"]["size"] < 350000)) {
//Determine the path to which we want to save this file
$newname = dirname(__FILE__).'/upload/'.$filename;
//Check if the file with the same name is already exists on the server
if (!file_exists($newname)) {
//Attempt to move the uploaded file to it's new place
if ((move_uploaded_file($_FILES['uploaded_file']['tmp_name'],$newname))) {
echo "It's done! The file has been saved as: ".$newname;
} else {
echo "Error: A problem occurred during file upload!";
}
} else {
echo "Error: File ".$_FILES["uploaded_file"]["name"]." already exists";
}
} else {
echo "Error: Only .jpg images under 350Kb are accepted for upload";
}
} else {
echo "Error: No file uploaded";
}
?>
Thanks very much for your time, I have searched for hours to fix this with no luck!
If you post to an Iframe it won't lock your page. Then watch the Iframe contents to see what the server response is, or better: use Firebug on Firefox and inspect he NET tab to see what's going on with your post request.
How big of a file are you uploading? Most browsers do not display any kind of upload progress bar, and only recently has PHP supported even bare bones progress reports. For a large file, all you'd see is the "... loading ..." status bar text with no indication that data's actually being uploaded.
As for the rest of the code, here's a few things you need to clean up before putting this into production:
$_FILES['uploaded_file']['error'] == 0
This will evaluate to true if the ['error'] element isn't set. Use === instead, which does forces value and type to be equal, not merely value.
if (($ext == "jpg") && ($_FILES["uploaded_file"]["type"] == "image/jpeg") &&
The filename and filetype values in the $_FILES array are what's supplied by the remote user, and can be easily mainipulated. Best to use a server-side mime-type identifer (getimagesize() for pictures works well) to see what the file really is.
Nevermind! It turns out it was something to do with the wireless network at my University. I got home, refreshed the page and it worked fine. I will have to have words with the system administrator about the time I wasted trying to solve a problem made by them.
Thanks for the help anyway guys,
Scott