Hello,
I don't really know much about php and needed to make a web contact form for a client where the user can upload images which are then sent as an attachment with the resulting email.
I kind of cheated and bought a bit of software which creates the script for you. This works great, but I am concerned about people uploading things other than images - especially after seeing this thread:
http://www.phpbuilder.com/board/showthread.php?t=10315994&highlight=upload+email+file+type
Now, obviously there is a bit of script in one of the replies which addressed my issue, but I don't know enough about php to adapt it for my own script. Therefore, I was wondering if someone would be so kind as to point out where I need to make changes and what those changes would be.
I need to allow only common image files and to disallow any of the nasty stuff described in the above thread.
I have created this stripped down script with my software, which addresses the essentials of uploaded image and resulting email to which it is attached, plus a section which deals with errors, http referers and stop words for security. The actual script includes more fields, but I thought it would take up too much space!
<?PHP
DEFINE('kOptional', True);
DEFINE('kMandatory', False);
error_reporting(E_ERROR | E_WARNING | E_PARSE);
ini_set('track_errors', true);
#----------
# Filter by Stop Words
function stopwords_check()
{
$specialchars = array('?', '\\', '.', '[', ']', '^', '$', '/');
$escapedchars = array('\\?', '\\\\', '\\.', '\\[', '\\]', '\\^', '\\$', '\\/');
$bannedstopwords[] = 'sex';
$bannedstopwords[] = 'sexual';
$bannedstopwords[] = 'explicit';
$bannedstopwords[] = 'hack';
$bannedstopwords[] = 'hacker';
foreach ($_POST as $fieldname => $fieldvalue) {
foreach ($bannedstopwords as $stopword_key => $stopword_value) {
$stopword_value = str_replace($specialchars, $escapedchars, $stopword_value);
$pattern = "/.*$stopword_value.*/i";
if (is_array($fieldvalue)) {
$fieldvalue = implode(",", $fieldvalue);
}
if (preg_match($pattern, $fieldvalue)) {
header("Location: http://www.mydomain.com/forbidden.html");
exit;
}
}
}
}
#----------
# Filter by Referer
function referer_check()
{
$allowedreferers[] = 'http://mydomain.com';
$allowedreferers[] = 'http://www.mydomain.com';
$notfound = true;
foreach ($allowedreferers as $referer_key => $referer_value) {
if ($referer_value == $_SERVER['HTTP_REFERER']) {
$notfound = false;
break;
}
}
if ($notfound === true) {
header("Location: http://www.mydomain.com/forbidden.html");
exit;
}
}
function DoStripSlashes($FieldValue)
{
if ( get_magic_quotes_gpc() ) {
if (is_array($FieldValue) ) {
return array_map('DoStripSlashes', $FieldValue);
} else {
return stripslashes($FieldValue);
}
} else {
return $FieldValue;
}
}
#----------
# FilterCChars:
function FilterCChars($TheString)
{
return preg_replace('/[\x00-\x1F]/', '', $TheString);
}
#----------
# Validate: Email
function check_email($email, $optional)
{
if ( (strlen($email) == 0) && ($optional === true) ) {
return true;
} elseif ( eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$", $email) ) {
return true;
} else {
return false;
}
}
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ClientIP = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$ClientIP = $_SERVER['REMOTE_ADDR'];
}
stopwords_check();
referer_check();
$FTGMAX_FILE_SIZE = DoStripSlashes( $_REQUEST['MAX_FILE_SIZE'] );
$FTGuserfile = $_FILES['userfile']['name'];
$FTGemail = DoStripSlashes( $_REQUEST['email'] );
$FTGMAX_FILE_SIZE = strip_tags($FTGMAX_FILE_SIZE);
$FTGemail = strip_tags($FTGemail);
# Fields Validations
$ValidationFailed = false;
if (!check_email($FTGemail, kMandatory)) {
$ValidationFailed = true;
$FTGemail_errmsg = "Please enter a valid email address!";
$ErrorList .= $FTGemail_errmsg . '<br/>';
}
# Embed error page and dump it to the browser
if ($ValidationFailed == true) {
$FileErrorPage = 'http://www.mydomain.com/error.html';
if (file_exists($FileErrorPage) === false) {
echo 'The error page: <b>' . $FileErrorPage. '</b> cannot be found on the server.';
exit;
}
$FileHandle = fopen ($FileErrorPage, "r");
$ErrorPage = fread ($FileHandle, filesize($FileErrorPage));
fclose ($FileHandle);
$ErrorPage = str_replace('<!--VALIDATIONERROR-->', $ErrorList, $ErrorPage);
$ErrorPage = str_replace('<!--FIELDVALUE:MAX_FILE_SIZE-->', $FTGMAX_FILE_SIZE, $ErrorPage);
$ErrorPage = str_replace('<!--FIELDVALUE:userfile-->', $FTGuserfile, $ErrorPage);
$ErrorPage = str_replace('<!--FIELDVALUE:email-->', $FTGemail, $ErrorPage);
$ErrorPage = str_replace('<!--ERRORMSG:email-->', $FTGemail_errmsg, $ErrorPage);
echo $ErrorPage;
exit;
}
# Email to Form Owner
$emailSubject = FilterCChars("You file");
$emailBody = "--FTG_BOUNDRY\n"
. "Content-Type: text/plain; charset=\"ISO-8859-1\"\n"
. "Content-Transfer-Encoding: 8bit\n"
. "\n"
. "Here is your file\n"
. "\n"
. "File name : $FTGuserfile\n"
. "email : $FTGemail\n"
. ""
. "\n";
if ( is_uploaded_file($_FILES['userfile']['tmp_name']) ) {
$fileName = $_FILES['userfile']['tmp_name'];
$fileHandle = fopen($fileName, 'r');
$fileAttach = fread($fileHandle, filesize ($fileName));
fclose($fileHandle);
$fileAttach = chunk_split(base64_encode($fileAttach));
$emailBody .= "--FTG_BOUNDRY\n"
. "Content-Type: " . $_FILES['userfile']['type'] . "; name=\"" . $_FILES['userfile']['name'] . "\"\n"
. "Content-disposition: attachment\n"
. "Content-transfer-encoding: base64\n"
. "\n"
. "$fileAttach\n"
. "\n";
}
$emailBody .= "--FTG_BOUNDRY--\n";
$emailTo = "Fred <email@mydomain.com>";
$emailFrom = FilterCChars("email@mydomain2.com");
$emailHeader = "From: [email]email@mydomain2.com[/email]\n"
. "MIME-Version: 1.0\n"
. "Content-Type: multipart/mixed; boundary=\"FTG_BOUNDRY\"\n"
. "This is a multi-part Content MIME format.\n";
mail($emailTo, $emailSubject, $emailBody, $emailHeader);
# Redirect user to success page
header("Location: http://www.mydomain.com/success.html");
exit;
?>
Any advice woule be greatly appreciated!
Thanks 🙂