Video icon 64
Learning to code? Skill up faster with our practical video courses. Start your free trial today.
Advertisement

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.


Advertisement