PHP Contact Form Dissected, Part 1

For those who want to understand the secure PHP contact form that I wrote and released last month, here is part 1 of the dissection of the code with the whys and hows.

I was planning to just do one post with a complete dissection but I’ve had this sitting here for a couple of weeks and am just a little pushed for time right now, so I’ll get the parts out as and when I’ve got a chance! I’ll link all of the posts together once they’re all done.

If you haven’t already got it, download the Contact Form and open up the PHP 4.4 version in your own text editor, ideally with line numbers as I’ll be referring to them.

Setting the variables

First off is the code to set the variables. This makes it easier for those who don’t want to poke around in the PHP to find what to change.

Code Excerpt
  1. // Change the $to_email to the address you want the email to be sent to
  2. $to_email = “you@yourdomain.com”;
  3.  
  4. // Change $redirect to where you want the user to be redirected to, usually a thankyou page
  5. $redirect = “thankyou.html”;
  6.  
  7. // Change the $subject to the subject of the email that you what
  8. $subject = “Online contact form from your site”;
  9.  
  10. // Specify the required fields
  11. $req_fields = array(“cfname”, “cfemail”, “cfmessage”);

The first 3 variables, $to_email, $redirect and $subject, should be straightforward. The final variable is the array $req_fields. This is an array of fieldnames used in the form, which need to be checked to ensure content has been entered into each form field specified. By listing them in an array it makes it easy for the user to add more fields without having to edit the PHP lower down.

The Processing Script

The processing script is above the start of the HTML output so that if a successful email is sent the header redirect can run and redirect the user to a thank you page. The first line of the processing script checks to make sure that the form has been submitted to the page (else there’s no point running the script at this point). The if statement below checks to see if the submit button has been pressed and also checks that it has a value (as the isset() function will be true if the variable tested has been created, regardless of being empty or not).

Code Excerpt
  1. // this bit does the mailing
  2. if (isset($_POST[‘cfsubmit’]) && trim($_POST[‘cfsubmit’]) != “”) :

Then we specify a few functions to validate the email address supplied to ensure that it’s safe and secure (I’ve written in the past about email header injections).

Code Excerpt
  1. // check no additional lines have been added to the email field
  2. function has_newlines($text) {
  3. return preg_match(“/(%0A|%0D|\n+|\r+)/i”, $text);
  4. }
  5.  
  6. // Check that additional headers haven’t been added
  7. function has_emailheaders($text) {
  8. return preg_match(“/(%0A|%0D|\n+|\r+)(content-type:|to:|cc:|bcc:)/i”, $text);
  9. }
  10. // check the email is of a valid form
  11. function is_valid($text) {
  12. return preg_match(“/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix”,$text);
  13. }

To briefly explain these functions, the first, has_newlines, checks to see if the email address supplied spans more than one line, by detecting a \n or \r in it. It returns TRUE if any instance of a new line is found. The second, has_emailheaders, checks for the instance of a header injection and returns TRUE if anything is found. The final function checks the validity of the email address, it checks that it follows the format of how an email address should be constructed and returns TRUE if the email address provided is valid.

Next is a foreach() statement that cleans up the form data. It uses the foreach() loop as to allow this form to be flexible, ie. allowing extra fields, we cannot predetermine the fieldnames in use, so this runs through every key in the $_POST array, ie. every fieldname used in the form. On line 45 the code checks to see if the Magic Quotes setting in the php.ini file is set to on (most hosts have this on to try and combat insecure scripts, let’s not get started on that debate though!), if it is then it will have had all the form content run through the addslashes() function, so we reverse that work using stripslashes(). For those asking why, first off this is a form that’s going to be emailed through, so the ‘security’ that magic_quotes gives isn’t needed in this instance, and if it was going into a database then I’d use a more secure escape method. Then on line 49 we also run the strip_tags() function, which will strip away any additional HTML added to the form. The final result is saved in an associative array called $formstuff with the key being the same as the key in the $_POST array ie. the fieldname.

Clean up the Form Content
  1. foreach ($_POST AS $key => $value) :
  2. if (get_magic_quotes_gpc()) :
  3. $value = stripslashes($value);
  4. endif;
  5.  
  6. $formstuff[$key] = strip_tags($value);
  7. endforeach;

Then, in another foreach() loop, we have the code which checks that the required fields (specified in the array on line 21) contain data, this runs through the required fields array, taking each fieldname one at a time. First it trims all excess white space off the field input, then it checks to see if the field’s value is empty. If it is then the variable $formerror is set to TRUE and the rest of the processing won’t run as per the if statement on line 61, instead the user is returned to the form to try again.

Check required fields are complete.
  1. $formerror = FALSE;
  2. foreach ($req_fields AS $formlabel) :
  3. $value = trim($formstuff[$formlabel]);
  4. if (empty($value)) :
  5. $formerror = TRUE;
  6. endif;
  7. endforeach;
  8.  
  9. if (!$formerror) :

Part 2 coming soon!

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

%d bloggers like this: