TalkPHP
 
 
Account Login
Latest Articles
» The basic usage of PHPTAL, a XML/XHTML template library for PHP
» Vulnerable methods and the areas they are commonly trusted in.
» Simple way to protect a form from bot
» The Basics On: How Session Stealing Works
» How to keep your forms from double posting data
IRC Channel
IRC Speech Bubble Join the friendly bunch on IRC...
(#TalkPHP on Freenode)

...Also available via a web interface.

See this thread for information on the TalkPHP Free Hugs Initiative™. Subject to availability.
Associates
Associates
CSS Tutorials
Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old 09-25-2007, 09:22 PM   #1 (permalink)
daz
The Contributor
Upcoming Programmer 
 
Join Date: Sep 2007
Posts: 31
Thanks: 0
daz is on a distinguished road
Default Uploading Files with PHP

Uploading Files with PHP
With the release of PHP 4.1.0 came an easier and more secure method of uploading files. In this tutorial, we’ll be looking at the superglobal $_FILES, which allows us to create a basic PHP uploader in only a few lines of code. Because it is a superglobal, it is available in all scopes throughout the script.

Our first step in coding an upload script is creating the HTML form. This form will allow a user to browse for a file and then upload it to a directory. This is the code we will be using:

PHP Code:
<form action="index.php" method="post" enctype="multipart/form-data">
<
p><label for="file"><strong>File to Upload:</strong></label>
<
input type="file" name="file" id="file" /></p>
<
input type="submit" name="submit" value="Submit" /></p>
</
form
I’ll assume you have basic knowledge of HTML, so the above code should be easy to understand. Moving on to the PHP, we first need to check the form has been submitted. This is done like so:
PHP Code:
if (!isset($_POST['submit'])) {
//display the form
else {
// otherwise, process the data

Now that we know the form has been submitted, we can process the data. Luckily for us, PHP does all the work. $_FILES stores the submitted data in an array which we can access like so (“file” being the name of our form input and “name” being the file name):

PHP Code:
$_FILES["file"]["name"
Firstly, to check if there were any errors, we can use an if statement and then use die() to output an error message and stop the execution of the script.

PHP Code:
if ($_FILES["file"]["error"] > 0) {
    die(
"There was a problem uploading your file!");

Next, we need to check the type of the file. There are several ways to do this. We could use substr() to get the extension of the file or we could check the mime type of the file. We’re going to check the mime type because it’s safer and we don’t want any script kiddies uploading any malicious files. To get the mime type of a file, we use:
PHP Code:
$_FILES["file"]["type"
Then, we can make an array of allowed mime types and compare them to the uploaded file. In this tutorial, we will be checking to see if the file is an image.

PHP Code:
$types = array("image/gif""image/jpeg""image/pjpeg""image/png"); 
We can use PHP’s function in_array() to check if the file type matches any of the types in the array and then use an if statement to display an error message. We also need to make sure the file doesn’t already exist by using the file_exists() function. File_exists() checks a directory (in this case, upload/) and returns true if the file exists.

PHP Code:
if (in_array($_FILES["file"]["type"], $typestrue
    && !
file_exists("upload/" $_FILES["file"]["name"])) {
    
// continue with the script
}
else {
    die(
"File type is not allowed, or the file already exists");

Before uploading the file, we need to check the file size. This is simply done by using the following code (the size is in bytes):
PHP Code:
if($_FILES["file"]["size"] <= 120000) {
    
// continue with the script
}
else {
    die(
"File is too big!");

Now we can upload the file using move_uploaded_file(). Before the file is uploaded to the directory it is given a temporary name (“tmp_name”). Upload/ is just the directory we want to upload to.
PHP Code:
move_uploaded_file ($_FILES["file"]["tmp_name"], "upload/" $_FILES["file"]["name"]); 
Now we will put all the code together and display a message saying the file has been uploaded. Lastly, I used require() to load the HTML form.
PHP Code:
<?php
if (!isset($_POST['submit'])) {
    require(
'form.php');
}
else {

$types = array("image/gif""image/jpeg""image/pjpeg""image/png");

    if (
$_FILES["file"]["error"] > 0) {
        die(
"There was a problem uploading your file!");
    }
    else {

        if (
in_array($_FILES["file"]["type"], $typestrue
        && !
file_exists("upload/" $_FILES["file"]["name"])) {
                
            if(
$_FILES["file"]["size"] <= 120000) {
        
                if (
move_uploaded_file ($_FILES["file"]["tmp_name"], "upload/" $_FILES["file"]["name"])) {
                    echo 
"Your file was successfully uploaded!";
                }
                else {
                    die(
"The file could not be uploaded!");
                }
            }
            else {
                die(
"File is too big!");
            }
        }
        else {
            die(
"File type is not allowed, or the file already exists!");
        }
    }
}

?>
There you have it, a basic PHP file uploader. To get the script to work, you need to create a directory called upload and CHMOD it to 777. :)
daz is offline  
Reply With Quote
Old 09-25-2007, 09:29 PM   #2 (permalink)
The Reckoner
Advanced Programmer Top Contributor 
 
Karl's Avatar
 
Join Date: Sep 2007
Posts: 437
Thanks: 22
Karl is on a distinguished road
Default

Nice introduction to file uploads. Thanks for contributing daz :)
Karl is offline  
Reply With Quote
Old 09-25-2007, 09:47 PM   #3 (permalink)
La Vida es Sueño
Advanced Programmer Top Contributor 
 
Wildhoney's Avatar
 
Join Date: Sep 2007
Location: Oldham
Posts: 2,280
Thanks: 90
Wildhoney is on a distinguished road
Default

Just to add onto this article. There is a function in PHP that allows you to check if the file is actually uploaded, and that it's not coming from anywhere else: is_uploaded_file(). I would also be tempted to check both the extension and the MIME type for extra security. Perhaps that's just me being somewhat cautious though.

Thanks for the article. It's very much appreciated and I'm sure it will give many people a helping hand!
__________________
The man who comes back through the Door in the Wall will never be quite the same as the man who went out.
Send a message via AIM to Wildhoney Send a message via MSN to Wildhoney Send a message via Yahoo to Wildhoney
Wildhoney is offline  
Reply With Quote
Old 09-30-2007, 06:23 PM   #4 (permalink)
The Wanderer
 
Join Date: Sep 2007
Location: Sydney, Australia
Posts: 19
Thanks: 0
jordie is on a distinguished road
Default

Cool! Nice tutorial. :)

IE is kinda funny with how it gives it's mime types. For example it sends image/pjpeg where firefox or other browsers would just use image/jpeg. You've already got it in your list, but there is another one that IE uses for PNG, so you might want to expand the allowed types to:

PHP Code:
$types = array("image/gif""image/jpeg""image/pjpeg""image/png""image/x-png"); 
But I would definitely not rely solely on the mime-type. The mime-type is sent from the browser, so it is client-side generated data and therefore can be faked. Though not through a standard browser, one could infact build their own program to post a file to a site with a different mime-type. Using this method they could send a PHP file with a mime type of "image/jpeg".

Though I wouldn't stop using this method as its definitely a good test, it should in fact be built upon using the other method you and Wildhoney suggested where the actual file extension is checked. If we do this, we can ensure that no file that is uploaded has a .php/.pl/etc extension and thus can't be executed.

To do this, we'd use a white list again that is a a list of allowed extensions:

PHP Code:
$AllowedExtensions = array("png""gif""jpg""jpeg"); 
and then test using this:

PHP Code:
$FileInfo pathinfo($_FILES["file"]["name"]);
if(
in_array($FileInfo['extension'], $AllowedExtensions)){
    
// we can safely upload the file
} else {
    
// not an allowed file

Another reportedly good method if you're just uploading images, is to use the getimagesize() function. This function returns an array of the image sizes, or false if its not an image. So you could use it in this manner:

PHP Code:
if(($myImageSizes getimagesize($_FILES["file"]["tmp_name"])) !== false){
// seems like a good image! Also now have access to the width in $myImageSizes[0] and the height in $myImageSizes[1] 
} else {
// not a valid image!


Last edited by jordie : 09-30-2007 at 06:25 PM. Reason: Wrote the condition incorrectly on the last PHP snippet :)
jordie is offline  
Reply With Quote
Reply



Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


All times are GMT. The time now is 05:41 AM.

 
     

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.1.0
Inactive Reminders By Icora Web Design