Writing your own script as Everah suggests is a good idea (and exercise). When you post the code here you'll get good feedback on the quality of it.
Central to a script like this (or any other) is: filter/validate all input and escape all output. Only let data go through based on a whitelist approach. If you expect someone to fill in an email address, make sure to check the filled in string looks like one, by using a good email regex.
Maybe something like below is a good starting point:
Code: Select all
<?php
// start by declaring empty arrays for the various sets of data
$clean = array();
$errors = array();
$errormessage = '';
// first setup some functions you'll use later
/* start with emailvalidation function, like this one
* from http://www.ilovejackdaniels.com/php/ema ... alidation/
* there are better ones then this, but I think this one is pretty good
----------------------------------------------------------------------*/
function check_email_address($email) {
// First, we check that there's one @ symbol, and that the lengths are right
if (!ereg("^[^@]{1,64}@[^@]{1,255}$", $email)) {
// Email invalid because wrong number of characters in one section, or wrong number of @ symbols.
return false;
}
// Split it into sections to make life easier
$email_array = explode("@", $email);
$local_array = explode(".", $email_array[0]);
for ($i = 0; $i < sizeof($local_array); $i++) {
if (!ereg("^(([A-Za-z0-9!#$%&'*+/=?^_`{|}~-][A-Za-z0-9!#$%&'*+/=?^_`{|}~\.-]{0,63})|(\"[^(\\|\")]{0,62}\"))$", $local_array[$i])) {
return false;
}
}
if (!ereg("^\[?[0-9\.]+\]?$", $email_array[1])) { // Check if domain is IP. If not, it should be valid domain name
$domain_array = explode(".", $email_array[1]);
if (sizeof($domain_array) < 2) {
return false; // Not enough parts to domain
}
for ($i = 0; $i < sizeof($domain_array); $i++) {
if (!ereg("^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]+))$", $domain_array[$i])) {
return false;
}
}
}
return true;
}
/* Function: validatestring.
--------------------------------------------------*/
function isValidString($value) {
$stringpattern = '/^[a-z0-9()\/\'":\*+|,.\t\n\r; \- !?&#$@]{2,2000}$/i';
if (preg_match($stringpattern, $value)) {
return TRUE;
} else {
return FALSE;
}
}
/* if form is posted start processing
----------------------------------------------------------------------*/
if (isset($_POST['submit'])) {
// validate name field
if( strlen($_POST['name']) > 1
&& strlen($_POST['name']) < 100
&& isValidString($_POST['name'])
&& ctype_print($_POST['name']) )
{
$clean['name'] = $_POST['name'];
}
else
{
$errors[] = 'The data in the form field name are invalid.';
}
// validate subject field
if( strlen($_POST['subject']) > 3
&& strlen($_POST['subject']) < 100
&& isValidString($_POST['subject'])
&& ctype_print($_POST['subject']) )
{
$clean['subject'] = $_POST['subject'];
}
else
{
$errors[] = 'The data in the form field subject are invalid.';
}
// validate message field
if( strlen($_POST['message']) > 5
&& strlen($_POST['message']) < 1000
&& isValidString($_POST['message']) )
{
$clean['message'] = $_POST['message'];
}
else
{
$errors[] = 'The data in the form field message are invalid.';
}
// validate email field
if( check_email_address($_POST['email'])
&& ctype_print($_POST['email']) )
{
$clean['email'] = $_POST['email'];
}
else
{
$errors[] = 'The email adrress is invalid.';
}
if(count($errors) > 0) {
// some errors occured, show error messages
$errormessage = '<strong>Please correct the following errors:</strong><br />';
foreach ($errors as $key => $value)
{
$errormessage .= $value . "<br />";
}
}
else
{
// everything is ok, continue
$to = 'info@yourdomain.com';
$from = $clean['email'];
$subject = $clean['subject'];
$message = 'Filled in contactform' . "\n"
. 'by: ' . $clean['name'] . ':' . "\n\n" . $clean['message'];
mail("$to","$subject","$message","From: $from");
unset($_POST);
$errormessage = 'Your message has been sent.';
}
}
?>
<html>
<body>
<?php echo (isset($errormessage) && strlen($errormessage)>0 ) ? '<p class="error">' . $errormessage . '</p>' : "" ?>
<form id="contactform" action="/contact/" method="POST">
<fieldset>
<div>
<label for="name">Your name <em>*</em></label>
<input id="name" type="text" name="name" value="<?php echo (isset($_POST['name'])) ? htmlentities($_POST['name'], ENT_QUOTES, 'UTF-8') : ""; ?>" />
</div>
<div>
<label for="email">Email address <em>*</em></label>
<input id="email" type="text" name="email" value="<?php echo (isset($_POST['email'])) ? htmlentities($_POST['email'], ENT_QUOTES, 'UTF-8') : ""; ?>" />
</div>
<div>
<label for="subject">Subject <em>*</em></label>
<input id="subject" type="text" name="subject" value="<?php echo (isset($_POST['subject'])) ? htmlentities($_POST['subject'], ENT_QUOTES, 'UTF-8') : ""; ?>" />
</div>
<div>
<label for="message">Message </label>
<textarea name="message" id="message" cols="40" rows="6"><?php echo (isset($_POST['message'])) ? htmlentities($_POST['message'], ENT_QUOTES, 'UTF-8') : ""; ?></textarea>
</div>
<div id="fm-submit"><label for="submit">Send </label><input type="submit" name="submit" id="submit" value="Send" /></div>
</fieldset>
</form>
</body>
</html>
As a disclaimer, I'm sure this code can be improved and might not be 100% bulletproof (so any suggestions from others are welcome) but I think it can be a step in the right direction. One thing I see now is that I could declare another array $html = array(); and then put the escaping rules (with the htmlentities) in the top part of the script instead of within the html form. A bit cleaner.
There are many ways to code forms, so how you do it can be personal preference.