diff --git a/features/file-upload.xml b/features/file-upload.xml index d11df3a1a8..027c5163e1 100644 --- a/features/file-upload.xml +++ b/features/file-upload.xml @@ -33,33 +33,44 @@ Send this file: <INPUT NAME="userfile" TYPE="file"> The _URL_ should point to a PHP file. The MAX_FILE_SIZE hidden - field must precede the file input field and its value is the maximum - filesize accepted. The value is in bytes. In this destination file, - the following variables will be defined upon a successful upload: + field must precede the file input field and its value is the + maximum filesize accepted. The value is in bytes. + + In PHP 3, the following variables will be defined within the + destination script upon a successful upload, assuming that register_globals is turned + on in php.ini. If track_vars is turned on, they will + also be available within the global array + $HTTP_POST_VARS. Note that the following + variable names assume the use of the file upload name 'userfile', + as used in the example above: + - $userfile - The temporary filename in which the uploaded file - was stored on the server machine. + $userfile - The temporary filename in which + the uploaded file was stored on the server machine. - $userfile_name - The original name or path of the file on the - sender's system. + $userfile_name - The original name or path + of the file on the sender's system. - $userfile_size - The size of the uploaded file in bytes. + $userfile_size - The size of the uploaded + file in bytes. - $userfile_type - The mime type of the file if the browser - provided this information. An example would be + $userfile_type - The mime type of the file + if the browser provided this information. An example would be "image/gif". @@ -67,32 +78,119 @@ Send this file: <INPUT NAME="userfile" TYPE="file"> Note that the "$userfile" part of the above variables is whatever the name of the INPUT field of TYPE=file is in the upload form. In the above upload form example, we chose to call it - "userfile". + "userfile" + + + In PHP 4, the behaviour is slightly different, in that the new + global array $HTTP_POST_FILES is provided to + contain the uploaded file information. This is still only + available if track_vars is + turned on, but track_vars is + always turned on in versions of PHP after PHP 4.0.2. + + + + The contents of $HTTP_POST_FILES are as + follows. Note that this assumes the use of the file upload name + 'userfile', as used in the example above: + + + $HTTP_POST_FILES['userfile']['name'] + + + The original name of the file on the client machine. + + + + + $HTTP_POST_FILES['userfile']['type'] + + + The mime type of the file, if the browser provided this + information. An example would be + "image/gif". + + + + + $HTTP_POST_FILES['userfile']['size'] + + + The size, in bytes, of the uploaded file. + + + + + $HTTP_POST_FILES['userfile']['tmp_name'] + + + The temporary filename of the file in which the uploaded file + was stored on the server. + + + + + + Files will by default be stored in the server's default temporary - directory. This can be changed by setting the environment variable - TMPDIR in the environment in which PHP runs. Setting - it using putenv from within a PHP script will - not work. This environment variable can also be used to make sure - that other operations are working on uploaded files, as well. + directory, unless another location has been given with the upload_tmp_dir directive in + php.ini. The server's default directory can + be changed by setting the environment variable + TMPDIR in the environment in which PHP runs. + Setting it using putenv from within a PHP + script will not work. This environment variable can also be used + to make sure that other operations are working on uploaded files, + as well. - Validating file uploads. - -<? -// Make sure file is coming from upload directory -$uploadpath = get_cfg_var('upload_tmp_dir') . '/' . basename($userfile); + Validating file uploads + + The following examples are for versions of PHP 3 greater than + 3.0.16, and versions of PHP 4 greater than 4.0.2. See the + function entries for is_uploaded_file and + move_uploaded_file. + + +<?php +if (is_uploaded_file($userfile)) { + copy($userfile, "/place/to/put/uploaded/file"); +} else { + echo "Possible file upload attack: filename '$userfile'."; +} +/* ...or... */ +move_uploaded_file($userfile, "/place/to/put/uploaded/file"); +?> + + + For earlier versions of PHP, you'll need to do something like + the following. + + + This will not work in versions of PHP 4 + after 4.0.2. It depends on internal functionality of PHP which + changed after that version. + + + + +<?php +/* Userland test for uploaded file. */ +function is_uploaded_file($filename) { + if (!$tmp_file = get_cfg_var('upload_tmp_dir')) { + $tmp_file = dirname(tempnam('', '')); + } + $tmp_file .= '/' . basename($filename); + /* User might have trailing slash in php.ini... */ + return (ereg_replace('/+', '/', $tmp_file) == $filename); +} -// If you have not set your TMPDIR in pnp.ini, the following line -// can be uncommented, and used instead of the above line -// $uploadpath = dirname(tempnam('', '')) . '/' . basename($userfile); - -if (file_exists($uploadpath)){ - copy ("$uploadpath", "/place/to/put/uploaded/file"); - } else { - echo "Not an uploaded file!"; - exit; - } +if (is_uploaded_file($userfile)) { + copy($userfile, "/place/to/put/uploaded/file"); +} else { + echo "Possible file upload attack: filename '$userfile'."; +} ?> @@ -100,12 +198,13 @@ if (file_exists($uploadpath)){ The PHP script which receives the uploaded file should implement whatever logic is necessary for determining what should be done - with the uploaded file. You can for example use the $file_size - variable to throw away any files that are either too small or too - big. You could use the $file_type variable to throw away any - files that didn't match a certain type criteria. Whatever the - logic, you should either delete the file from the temporary - directory or move it elsewhere. + with the uploaded file. You can for example use the + $file_size variable to throw away any files + that are either too small or too big. You could use the + $file_type variable to throw away any files + that didn't match a certain type criteria. Whatever the logic, + you should either delete the file from the temporary directory or + move it elsewhere. The file will be deleted from the temporary directory at the end diff --git a/functions/filesystem.xml b/functions/filesystem.xml index aa496ab8a7..f8a9ec2e32 100644 --- a/functions/filesystem.xml +++ b/functions/filesystem.xml @@ -438,7 +438,7 @@ $df = diskfreespace("/"); // $df contains the number of bytes fgetcsv parses the line it reads for fields in CSV format and returns an array containing the fields read. The field delimiter is a comma, unless you - specifiy another delimiter with the optional third parameter. + specify another delimiter with the optional third parameter. Fp must be a valid file pointer to a file @@ -454,9 +454,9 @@ $df = diskfreespace("/"); // $df contains the number of bytes end of file. - NB A blank line in a CSV file will be returned as an array - comprising just one single null field, and will not be treated as - an error. + N.B. A blank line in a CSV file will be returned as an array + comprising a single null field, and will not be treated as an + error. @@ -1751,6 +1751,48 @@ if($fp){ </refsect1> </refentry> + <refentry id="function.is-uploaded-file"> + <refnamediv> + <refname>is_uploaded_file</refname> + <refpurpose>Tells whether the file was uploaded via HTTP POST.</refpurpose> + </refnamediv> + <refsect1> + <title>Description + + + bool is_uploaded_file + string filename + + + + + This function is available only in versions of PHP 3 after PHP + 3.0.16, and in versions of PHP 4 after 4.0.2. + + + + Returns true if the file named by filename was + uploaded via HTTP POST. This is useful to help ensure that a + malicious user hasn't tried to trick the script into working on + files upon which it should not be working--for instance, + /etc/passwd. + + + + This sort of check is especially important if there is any chance + that anything done with uploaded files could reveal their + contents to the user, or even to other users on the same + system. + + + + See also move_uploaded_file, and the section + Handling file uploads + for a simple usage example. + + + + link @@ -1848,6 +1890,63 @@ mkdir ("/path/to/my/dir", 0700); + + + move_uploaded_file + Moves an uploaded file to a new location. + + + Description + + + bool move_uploaded_file + string filename + string destination + + + + + This function is available only in versions of PHP 3 after PHP + 3.0.16, and in versions of PHP 4 after 4.0.2. + + + + This function checks to ensure that the file designated by + filename is a valid upload file (meaning + that it was uploaded via PHP's HTTP POST upload mechanism). If + the file is valid, it will be moved to the filename given by + destination. + + + + If filename is not a valid upload file, + then no action will occur, and + move_uploaded_file will return + false. + + + + If filename is a valid upload file, but + cannot be moved for some reason, no action will occur, and + move_uploaded_file will return + false. Additionally, a warning will be issued. + + + + This sort of check is especially important if there is any chance + that anything done with uploaded files could reveal their + contents to the user, or even to other users on the same + system. + + + + See also is_uploaded_file, and the section + Handling file uploads + for a simple usage example. + + + + pclose diff --git a/language/variables.xml b/language/variables.xml index 6726899337..5dcc19089c 100644 --- a/language/variables.xml +++ b/language/variables.xml @@ -528,8 +528,15 @@ $bar = &test(); // Invalid. An associative array of variables containing information - about files uploaded via the HTTP POST method. + about files uploaded via the HTTP POST method. See POST method + uploads for information on the contents of + $HTTP_POST_FILES. + + $HTTP_POST_FILES is available only in PHP + 4.0.0 and later. +