Hopefully someone here might have an answer to my question.
I have a basic form that contains simple fields, like name, number, email address etc and 1 file upload field.
I am trying to add some validation into my script that detects if the file is too large and then rejects the user back to the form to select/upload a smaller file.
My problem is, if a user selects a file that is bigger than my validation file size rule and larger than php.ini POST_MAX_SIZE/UPLOAD_MAX_FILESIZE and pushes submit, then PHP seems to try process the form only to fail on the POST_MAX_SIZE settings and then clears the entire $_POST array and returns nothing back to the form.
Is there a way around this? Surely if someone uploads something > than the max size configured in the php.ini then you can still get the rest of the $_POST data???
Here is my code.
<?php
function validEmail($email)
{
$isValid = true;
$atIndex = strrpos($email, "@");
if (is_bool($atIndex) && !$atIndex)
{
$isValid = false;
} else {
$domain = substr($email, $atIndex+1);
$local = substr($email, 0, $atIndex);
$localLen = strlen($local);
$domainLen = strlen($domain);
if ($localLen < 1 || $localLen > 64)
{
// local part length exceeded
$isValid = false;
}
else if ($domainLen < 1 || $domainLen > 255)
{
// domain part length exceeded
$isValid = false;
}
else if ($local[0] == '.' || $local[$localLen-1] == '.')
{
// local part starts or ends with '.'
$isValid = false;
}
else if (preg_match('/\\.\\./', $local))
{
// local part has two consecutive dots
$isValid = false;
}
else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain))
{
// character not valid in domain part
$isValid = false;
}
else if (preg_match('/\\.\\./', $domain))
{
// domain part has two consecutive dots
$isValid = false;
}
else if
(!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\","",$local)))
{
// character not valid in local part unless
// local part is quoted
if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\","",$local)))
{
$isValid = false;
}
}
}
return $isValid;
}
//setup post variables
@$name = htmlspecialchars(trim($_REQUEST['name']));
@$emailCheck = htmlspecialchars(trim($_REQUEST['email']));
@$organisation = htmlspecialchars(trim($_REQUEST['organisation']));
@$title = htmlspecialchars(trim($_REQUEST['title']));
@$phone = htmlspecialchars(trim($_REQUEST['phone']));
@$location = htmlspecialchars(trim($_REQUEST['location']));
@$description = htmlspecialchars(trim($_REQUEST['description']));
@$fileError = 0;
@$phoneError = "";
//setup file upload handler
$target_path = 'uploads/';
$filename = basename( @$_FILES['uploadedfile']['name']);
$max_size = 8000000; // maximum file size (8mb in bytes) NB: php.ini max filesize upload is 10MB on test environment.
$allowed_filetypes = Array(".pdf", ".doc", ".zip", ".txt", ".xls", ".docx", ".csv", ".rtf"); //put extensions in here that should be uploaded only.
$ext = substr($filename, strpos($filename,'.'), strlen($filename)-1); // Get the extension from the filename.
if(!is_writable($target_path)) die('You cannot upload to the specified directory, please CHMOD it to 777.'); //Check if we can upload to the specified upload folder.
//display form function
function displayForm($name, $emailCheck, $organisation, $phone, $title, $location, $description, $phoneError, $allowed_filetypes, $ext, $filename, $fileError)
{
//make $emailCheck global so function can get value from global scope.
global $emailCheck;
global $max_size;
echo '<form action="geodetic_form.php" method="post" name="contact" id="contact" enctype="multipart/form-data">'."\n".
'<fieldset>'."\n".'<div>'."\n";
//name
echo '<label for="name"><span class="mandatory">*</span>Your name:</label>'."\n".
'<input type="text" name="name" id="name" class="inputText required" value="'. $name .'" />'."\n";
//check if name field is filled out
if (isset($_REQUEST['submit']) && empty($name))
{
echo '<label for="name" class="error">Please enter your name.</label>'."\n";
}
echo '</div>'."\n". '<div>'."\n";
//Email
echo '<label for="email"><span class="mandatory">*</span>Your email:</label>'."\n".
'<input type="text" name="email" id="email" class="inputText required email" value="'. $emailCheck .'" />'."\n";
// check if email field is filled out and proper format
if (isset($_REQUEST['submit']) && validEmail($emailCheck) == false)
{
echo '<label for="email" class="error">Invalid email address entered.</label>'."\n";
}
echo '</div>'."\n". '<div>'."\n";
//organisation
echo '<label for="phone">Organisation:</label>'."\n".
'<input type="text" name="organisation" id="organisation" class="inputText" value="'. $organisation .'" />'."\n";
echo '</div>'."\n". '</fieldset>'."\n".'<fieldset>'. "\n" . '<div>'."\n";
//title
echo '<label for="phone">Title:</label>'."\n".
'<input type="text" name="title" id="title" class="inputText" value="'. $title .'" />'."\n";
echo '</div>'."\n". '</fieldset>'."\n".'<fieldset>'. "\n" . '<div>'."\n";
//phone
echo '<label for="phone"><span class="mandatory">*</span>Phone <br /><span class="small">(include area code)</span>:</label>'."\n".
'<input type="text" name="phone" id="phone" class="inputText required" value="'. $phone .'" />'."\n";
// check if phone field is filled out that it has numbers and not characters
if (isset($_REQUEST['submit']) && $phoneError == "true" && empty($phone)) echo '<label for="email" class="error">Please enter a valid phone number.</label>'."\n";
echo '</div>'."\n". '</fieldset>'."\n".'<fieldset>'. "\n" . '<div>'."\n";
//Location
echo '<label class="location" for="location"><span class="mandatory">*</span>Location:</label>'."\n".
'<textarea name="location" id="location" class="required">'. $location .'</textarea>'."\n";
//check if message field is filled out
if (isset($_REQUEST['submit']) && empty($_REQUEST['location'])) echo '<label for="location" class="error">This field is required.</label>'."\n";
echo '</div>'."\n". '</fieldset>'."\n".'<fieldset>'. "\n" . '<div>'."\n";
//description
echo '<label class="description" for="description">Description:</label>'."\n".
'<textarea name="description" id="queryComments">'. $description .'</textarea>'."\n";
echo '</div>'."\n". '</fieldset>'."\n".'<fieldset>'. "\n" . '<div>'."\n";
//file upload
echo '<label class="uploadedfile" for="uploadedfile">File:</label>'."\n".
'<input type="file" name="uploadedfile" id="uploadedfile" value="'. $filename .'" />'."\n";
// Check if the filetype is allowed, if not DIE and inform the user.
switch ($fileError)
{
case "1":
echo '<label for="uploadedfile" class="error">The file you attempted to upload is not allowed.</label>';
break;
case "2":
echo '<label for="uploadedfile" class="error">The file you attempted to upload is too large.</label>';
break;
}
echo '</div>'."\n". '</fieldset>';
//end of form
echo '<div class="submit"><input type="submit" name="submit" value="Submit" id="submit" /></div>'.
'<div class="clear"><p><br /></p></div>';
} //end function
//setup error validations
if (isset($_REQUEST['submit']) && !empty($_REQUEST['phone']) && !is_numeric($_REQUEST['phone'])) $phoneError = "true";
if (isset($_REQUEST['submit']) && $_FILES['uploadedfile']['error'] != 4 && !in_array($ext, $allowed_filetypes)) $fileError = 1;
if (isset($_REQUEST['submit']) && $_FILES["uploadedfile"]["size"] > $max_size) $fileError = 2; echo "this condition " . $fileError;
$POST_MAX_SIZE = ini_get('post_max_size');
$mul = substr($POST_MAX_SIZE, -1);
$mul = ($mul == 'M' ? 1048576 : ($mul == 'K' ? 1024 : ($mul == 'G' ? 1073741824 : 1)));
if ($_SERVER['CONTENT_LENGTH'] > $mul*(int)$POST_MAX_SIZE && $POST_MAX_SIZE) echo "too big!!";
echo $POST_MAX_SIZE;
if(empty($name) || empty($phone) || empty($location) || validEmail($emailCheck) == false || $phoneError == "true" || $fileError != 0)
{
displayForm($name, $emailCheck, $organisation, $phone, $title, $location, $description, $phoneError, $allowed_filetypes, $ext, $filename, $fileError);
echo $fileError;
echo "max size is: " .$max_size;
echo "and file size is: " . $_FILES["uploadedfile"]["size"];
exit;
} else {
//copy file from temp to upload directory
$path_of_uploaded_file = $target_path . $filename;
$tmp_path = $_FILES["uploadedfile"]["tmp_name"];
echo $tmp_path;
echo "and file size is: " . filesize($_FILES["uploadedfile"]["tmp_name"]);
exit;
if(is_uploaded_file($tmp_path))
{
if(!copy($tmp_path,$path_of_uploaded_file))
{
echo 'error while copying the uploaded file';
}
}
//test debug stuff
echo "sending email...";
exit;
}
?>
PHP is returning this error in the log: [29-Apr-2010 10:32:47] PHP Warning: POST Content-Length of 57885895 bytes exceeds the limit of 10485760 bytes in Unknown on line 0
Excuse all the debug stuff :)
FTR, I am running PHP 5.1.2 on IIS.
PHP throws all the POST data away because there was no room to put it. There is nothing reliable to be had from only part of the data.
I would work around this problem by uploading the necessary files in a separate step, a different form. You can store the values already obtained in session, ensuring they are not lost because of excessive POST data.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With