Advertisement
PHP

Build Your Own Captcha and Contact Form

by

Ever get hit with spam through the contact form on your personal site? Well, here is a short tutorial on how to build a custom captcha to keep the bad guys out.

Step 1: captcha.php and the Session

First we need to build a new PHP page and save it as captcha.php. Then, in out new script, open a server session by using the session_start() command. Also, code an empty variable named "string". We will use this variable later to hold our randomly generated captcha text.

<?php

session_start();

$string = '';

?>

Step 2: Random String

Next, we need to write a for loop that will generate a random string. We will then take this random string and set it in a session variable called "random_code".

<?php

session_start();

$string = '';

for ($i = 0; $i < 5; $i++) {
	$string .= chr(rand(97, 122));
}

$_SESSION['random_code'] = $string;

This for loop, you'll notice, adds a lower case ascii character, using the chr() function, to our $string variable on every pass. My example generates 5 characters, but you can adjust that number by changing "$i < 5" in the loop statement to something more custom, like "$i < 7". Once your loop is complete, make sure you define your session variable.

Step 3: Storage Folder and Colors

This is where the tutorial gets a little more complicated. Next we need to define a storage folder for the font we are going to use, build the base captcha image, and define the colors we'll use to fill our image. This is all simple code, but they're functions that don't get used often by developers.

$dir = 'fonts/';

$image = imagecreatetruecolor(170, 60);
$black = imagecolorallocate($image, 0, 0, 0);
$color = imagecolorallocate($image, 200, 100, 90); // red
$white = imagecolorallocate($image, 255, 255, 255);

Initially, I'm just defining the folder where my fonts are stored in the $dir variable. The $image variable, where we use the imagecreatetruecolor() function is the money spot. This is where the base captcha image is built using PHP. The function imagecreatetruecolor() returns an image identifier representing a black image of the specified size. As you can see, I'm making my image 170px wide by 60px tall.

Finally, in this step, I define some colors we can use in our final image. The numbers passed to the imagecolorallocate() function are RGB values.

Step 4: Building the Image

Next, we're going to fill our image with a white rectangle, which will act as the image background, and then add our random text string to the image.

imagefilledrectangle($image,0,0,200,100,$white);
imagettftext($image, 30, 0, 10, 40, $alt, $dir."arial.ttf", $_SESSION['rand_code']);

The imagefilledrectangle() function draws a rectangle in the specified image. The four numbers passed in the function represent coordinates for the corners of the rectangle. Make sure the rectangle you draw here is larger than the base image. You'll notice my rectangle is 200px wide and 100px tall.

The imagettftext() lets us add text to an image using True Type fonts. And you'll see that this function that can handle quite a few parameters. I'd like to highlight all of the different parameters in this function, but you'll only need to remember a few.

imagettftext($image, $font_size, $angle, $x, $y, $color ,$font_file ,$text);

Once you compare my example to the code immediately above, you'll see that the values passed to the imagettftext() function are easy to understand. First is the image, then font size, angle of the text, the x and y coordinates of the text (starting with the top left corner), text color, the location of the font file, and finally the text (our random string).

Step 5: Image Final

Next, with our script, we need to tell our browser what type of image we are using, with a header() function, and build the final image. These functions are so straight-forward, not much can be explained about them. Also, don't forget to close your PHP script.

header("Content-type: image/png");
imagepng($image);

?>

Once previewed in a browser, you script should generate a png image that contains some text. If you receive errors, make sure your script can link to your .ttf font file, and that you have created the empty $string variable from earlier in the tutorial.

This is what the final code for your captcha.php page should look like:

<?php
session_start();

$string = '';

for ($i = 0; $i < 5; $i++) {
	// this numbers refer to numbers of the ascii table (lower case)
	$string .= chr(rand(97, 122));
}

$_SESSION['rand_code'] = $string;

$dir = 'fonts/';

$image = imagecreatetruecolor(170, 60);
$black = imagecolorallocate($image, 0, 0, 0);
$color = imagecolorallocate($image, 200, 100, 90); // red
$white = imagecolorallocate($image, 255, 255, 255);

imagefilledrectangle($image,0,0,399,99,$white);
imagettftext ($image, 30, 0, 10, 40, $color, $dir."arial.ttf", $_SESSION['random_code']);

header("Content-type: image/png");
imagepng($image);
?>

Step 6: contact.php

Build a new PHP contact page and save it as contact.php. This page will contain our contact form that will validate using our captcha.

Step 7: HTML & CSS

Let's add an HTML form to our contact.php page. Pay particular attention to the image source we use for the random text.

<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" enctype="multipart/form-data">
	<p><input type="text" name="name" /></p>
	<p><input type="text" name="email" /></p>
	<p><textarea name="message"></textarea></p>
	<img src="captcha.php"/>
	<p><input type="text" name="code" /></p>
	<p><input type="reset" name="submit" value="Send" /></p>
</form>

You can also add the following bit of CSS to your page to make it look better than default.

<style type="text/css">
form {
	margin:0;
	padding:0;
}
input {
	padding:2px;
	width:200px;
}
textarea {
	padding:2px;
	width:200px;
	height:100px;
}
.button {
	width:60px;
}
p {
	margin:0 0 5px 0;
	padding:0;
}
.error {
	color:#FF0000;
	margin:0 0 10px 0;
}
.accept {
	color:#339966;
	margin:0 0 10px 0;
}
</style>

Step 8: Validate with PHP

Now that our form is built and we have out captcha image displaying, all we need to do now is validate our form, being sure to include some validation rules for out captcha.

Below is what the final validation PHP should look like. Two important features required for this validation process are session_start(); and the if($_POST['code'] == $_SESSION['rand_code']) elements. These allow us to access out session variable and check it against the text someone writes in the code field of our form. Without these, our captcha would be useless.

<?php
session_start();

if(isset($_POST['submit'])) {
	
	if(!empty($_POST['name']) && !empty($_POST['email']) && !empty($_POST['message']) && !empty($_POST['code'])) {
	
		if($_POST['code'] == $_SESSION['rand_code']) {
		
			// send email
			$accept = "Thank you for contacting me.";
		
		} else {
		
			$error = "Please verify that you typed in the correct code.";
		
		}
		
	} else {
	
		$error = "Please fill out the entire form.";
	
	}

}
?>

If you know much about PHP, the rest of this validation should be easy to understand. We are essentially looking to make sure none of our form fields are empty. If they are empty, errors are thrown to make sure our user inputs information. You'll also notice I am not validating whether the email is well formed, which is something your should should include. Email validation is done using regular expressions.

Here is what your final contact.php file should look like. I am including the CSS, which you may want to drop in its own CSS file.

<?php

session_start();

if(isset($_POST['submit'])) {
	
	if(!empty($_POST['name']) && !empty($_POST['email']) && !empty($_POST['message']) && !empty($_POST['code'])) {
	
		if($_POST['code'] == $_SESSION['rand_code']) {
		
			// send email
			$accept = "Thank you for contacting me.";
		
		} else {
		
			$error = "Please verify that you typed in the correct code.";
		
		}
		
	} else {
	
		$error = "Please fill out the entire form.";
	
	}

}

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Contact Us</title>
<style type="text/css">
form {
	margin:0;
	padding:0;
}
input {
	padding:2px;
	width:200px;
}
textarea {
	padding:2px;
	width:200px;
	height:100px;
}
.button {
	width:60px;
}
p {
	margin:0 0 5px 0;
	padding:0;
}
.error {
	color:#FF0000;
	margin:0 0 10px 0;
}
.accept {
	color:#339966;
	margin:0 0 10px 0;
}
</style>
</head>

<body>

<?php if(!empty($error)) echo '<div class="error">'.$error.'</div>'; ?>
<?php if(!empty($accept)) echo '<div class="accept">'.$accept.'</div>'; ?>

<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" enctype="multipart/form-data">
	<p><input type="text" name="name" /> Name</p>
	<p><input type="text" name="email" /> Email</p>
	<p><textarea name="message"></textarea></p>
	<img src="captcha.php"/>
	<p><input type="text" name="code" /> Are you human?</p>
   <p><input type="submit" name="submit" value="Send" class="button" /></p>
</form>

</body>
</html>

You're Done

Once your validation is working, your captcha contact form should be working great. What are your thoughts? Thanks so much for reading.


Related Posts
  • Web Design
    HTML/CSS
    Creating Friendlier, “Conversational” Web FormsForm retina
    Web forms are constantly a hot topic when it comes to web design and user interaction. The reasons for this are vast, but one of the more obvious reasons is that forms are the most basic way for a user to input information into your application. In this article, we'll discuss a few techniques that allow your forms to respond to the user's input, while helping to obscure unnecessarily confusing or overwhelming elements.Read More…
  • Code
    PHP
    Validation and Exception Handling: From the UI to the BackendProcedural to oop php retina preview
    Sooner or later in your programming career you will be faced with the dilemma of validation and exception handling. This was the case with me and my team also. A couple or so years ago we reached a point when we had to take architectural actions to accommodate all the exceptional cases our quite large software project needed to handle. Below is a list of practices we came to value and apply when it comes to validation and exception handling.Read More…
  • Code
    PHP
    Creating a Photo Tag Wall With Twilio Picture Messaging & PHPProcedural to oop php retina preview
    Twilio's recently announced Picture Messaging has vastly opened up what we can do with text messaging, now we can attach photos to our text messages and have them get used in different ways. In our case, we are going to build a Photo Tag Wall, which will contain photos linked to tags that will be displayed on a website.Read More…
  • Code
    PHP
    Acceptance Testing With CodeceptionIntro to codeception retina preview
    Typically new features for web applications are tested by visiting the appropriate page in a browser, maybe filling out some form data, submitting the form, and then developers or testers hope to see their desired result. This is the natural way most web developers test their apps. We can continue with this natural testing process and improve upon it to ensure our apps are as stable as possible by using Codeception. Read More…
  • Code
    PHP
    Authentication With Laravel 4Laravel 4 auth retina preview
    Authentication is required for virtually any type of web application. In this tutorial, I'd like to show you how you can go about creating a small authentication application using Laravel 4. We'll start from the very beginning by creating our Laravel app using composer, creating the database, loading in the Twitter Bootstrap, creating a main layout, registering users, logging in and out, and protecting routes using filters. We've got a lot of code to cover, so let's get started!Read More…
  • Web Design
    UX
    Implementing the Float Label Form PatternForm float input retina
    Using Matt Smith’s mobile form interaction design as a guide, we will create a stunning form interaction for the web that’s both beautiful and accessible using HTML, CSS and JavaScript.Read More…