As of PHP 4.2.0, rather than automatically assuming a failed file uploaded is a file attack, you can use the error code associated with the file upload to check and see why the upload failed. This error code is stored in the userfile array (ex: $HTTP_POST_FILES['userfile']['error']).
Here's an example of a switch:
if (is_uploaded_file($userfile)) {
//include code to copy tmp file to final location here...
}else{
switch($HTTP_POST_FILES['userfile']['error']){
case 0: //no error; possible file attack!
echo "There was a problem with your upload.";
break;
case 1: //uploaded file exceeds the upload_max_filesize directive in php.ini
echo "The file you are trying to upload is too big.";
break;
case 2: //uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form
echo "The file you are trying to upload is too big.";
break;
case 3: //uploaded file was only partially uploaded
echo "The file you are trying upload was only partially uploaded.";
break;
case 4: //no file was uploaded
echo "You must select an image for upload.";
break;
default: //a default error, just in case! :)
echo "There was a problem with your upload.";
break;
}
Additionally, by testing the 'name' element of the file upload array, you can filter out unwanted file types (.exe, .zip, .bat, etc). Here's an example of a filter that can be added before testing to see if the file was uploaded:
//rejects all .exe, .com, .bat, .zip, .doc and .txt files
if(preg_match("/.exe$|.com$|.bat$|.zip$|.doc$|.txt$/i", $HTTP_POST_FILES['userfile']['name'])){
exit("You cannot upload this type of file.");
}
//if file is not rejected by the filter, continue normally
if (is_uploaded_file($userfile)) {
/*rest of code*/