How to make your own CAPTCHA system
I guess everybody has had to enter some letters that they see in a image. Right? Well, this is just for avoiding spam or creating unused accounts. Some webmasters put this on their site so as to have a clean database.
In this tutorial, we are going to make a fully customizable CAPTCHA system.
We are going to start by creating the structure of the files and folders. Just create empty files for now. To start, I recommend you to create a separate folder named Captcha. Inside this folder, create two PHP files: one named captcha.php and one named config.php. Also, create two subfolders named Backgrounds and Fonts.
TIP: Create empty index.html files under the main folder but also under the subfolders, in case somebody wants to see the structure of the captcha system. In this way, an empty page will appear in the user’s browser, instead of the Apache index.
After the structure of the CAPTCHA system is created, let’s start by filling the config.php file.
This will be the name of the session: captcha_session.
<?php
$captcha_session = ‘captcha_session’;
Next, we define what characters the script should include in the image. You know that 0 (zero) could be easily mistaken with O (letter) so it’s better not to include one of these.
$captcha_characters = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789′;
Here we define the minimum and maximum length of the code. If you define the same value on minimum or maximum, no variation will be noticed.
$captcha_minimum_length = 5;
$captcha_maximum_length = 7;
Now we play with each character’s font size. The script will randomize the font size based on these values.
$captcha_minimum_size = 30;
$captcha_maximum_size = 35;
This is the letter spacing. The space between each letter will be randomized based on these values.
$captcha_minimum_spacing = 3;
$captcha_maximum_spacing = 7;
These values will just rotate the letters left or right, in order to make the code harder to read for robots.
$captcha_rotation_left = 20;
$captcha_rotation_right = 20;
This will just control the space from the top of the image to the letters.
$captcha_vertical_displacement = 10;
The first one controls the space from the margin to the actual text. The second one is the text color.
$captcha_text_padding = 5;
$captcha_text_color = array (’124, 85, 112′);
Now we specify the folder were some fonts should be placed. Remember the folder structure? After that, we define some fonts the script can use. You can find some fonts on DaFont.com.
$captcha_font_folder = ‘fonts/’;
$captcha_font_files = array (’1.ttf’, ‘2.ttf’, ‘3.ttf’);
At the end of this script, we specify the backgrounds folder and some background images.
$captcha_background_folder = ‘backgrounds/’;
$captcha_background_files = array (’1.png’, ‘2.png’);?>
You can now save this file. Next we are going to build our captcha.php file. This one is going to create the actual image and session. Remember that you need your sessions activated because this is the way to verify if the user has entered the correct code.
Start the captcha.php file by including the other one. If this file is not found, the script will stop executing.
<?php
@require_once (’config.php’);
Now we start the session and define it as blank.
session_start();
$_SESSION[$captcha_session] = ”;
We create a function to handle the size of the characters. We want these characters to be included in the image, right?
function character_size ($font_file, $character, $size, $angle = 0) {
if (is_file ($font_file) && strlen ($character) == 1 && $size > 0):
$corners = @imagettfbbox ($size, $angle, $font_file, $character);
$left = ($corners[0] > $corners[6]) ? $corners[6] : $corners[0];
$right = ($corners[2] > $corners[4]) ? $corners[2] : $corners[4];
$top = ($corners[5] > $corners[7]) ? $corners[7] : $corners[5];
$bottom = ($corners[1] > $corners[3]) ? $corners[1] : $corners[3];
$width = $right - $left + 4;
$height = abs ($top - $bottom) + 4;
$return = array (’width’ => $width, ‘height’ => $height, ‘bottom’ => $bottom, ‘right’ => $right, ‘top’ => $top, ‘left’ => $left);
else:
$return = FALSE;
endif;
return $return;
}
Also we create a function to convert a color to hexadecimal. We need this later.
function hexadecimal_color ($color) {
if (substr_count ($color, ‘,’) == 2):
list ($red, $green, $blue) = array_map (’trim’, explode (’,', $color));
else:
$red = hexdec ($color[0] . $color[1]);
$green = hexdec ($color[2] . $color[3]);
$blue = hexdec ($color[4] . $color[5]);
endif;
return array (’red’ => $red, ‘green’ => $green, ‘blue’ => $blue);
}
We now start by telling the script that the initial values of the size of the image are 0. We also find out what will be the length of the code.
$image_width = 0;
$image_height = 0;
$code_length = rand ($captcha_minimum_length, $captcha_maximum_length);
We now type the code which will write the letters.
for ($c = 1; $c <= $code_length; $c++):
$character[$c]['char'] = $captcha_characters[rand (0, strlen ($captcha_characters) - 1)];
$character[$c]['color'] = hexadecimal_color ($captcha_text_color[rand (0, count ($captcha_text_color) - 1)]);
$character[$c]['displacement'] = rand (0, $captcha_vertical_displacement * 2) - $captcha_vertical_displacement;
$character[$c]['font'] = $captcha_font_folder . $captcha_font_files[rand (0, count ($captcha_font_files) - 1)];
$character[$c]['size'] = rand ($captcha_minimum_size, $captcha_maximum_size);
$character[$c]['angle'] = rand (0, $captcha_rotation_left + $captcha_rotation_right) - $captcha_rotation_right;
$character[$c]['space'] = rand ($captcha_minimum_spacing, $captcha_maximum_spacing);
$properties = character_size ($character[$c]['font'], $character[$c]['char'], $character[$c]['size'], $character[$c]['angle']);
$width = $properties['width'];
$height = $properties['height'];
$image_width += $width;
if ($c != $code_length) $image_width += $character[$c]['space'];
if (($height + abs ($character[$c]['displacement'])) > $image_height) $image_height = $height + abs ($character[$c]['displacement']);
$_SESSION[$captcha_session] .= $character[$c]['char'];
endfor;
Now we play with the background image but we also increase the image size based on the padding we defined.
$image_width += $captcha_text_padding * 2;
$image_height += $captcha_text_padding * 2 + $captcha_vertical_displacement;
$image = imagecreatetruecolor ($image_width, $image_height);
$background = rand (0, count ($captcha_background_files) - 1);
list ($background_width, $background_height) = getimagesize ($captcha_background_folder . $captcha_background_files[$background]);
$background_width_difference = rand (0, $background_width - $image_width);
$background_height_difference = rand (0, $background_height - $image_height);
$background_image = imagecreatefrompng ($captcha_background_folder . $captcha_background_files[$background]);
We create a copy of the image we created until now and then we destroy the actual one.
imagecopy ($image, $background_image, 0, 0, $background_width_difference, $background_height_difference, $image_width, $image_height);
imagedestroy ($background_image);
Now we color the text and build our final image.
$cursor = $captcha_text_padding;
for ($c = 1; $c <= $code_length; $c++):
$color = imagecolorallocate ($image, $character[$c]['color']['red'], $character[$c]['color']['green'], $character[$c]['color']['blue']);
$properties = character_size ($character[$c]['font'], $character[$c]['char'], $character[$c]['size'], $character[$c]['angle']);
$width = $properties['width'];
$height = $properties['height'];
$bottom = $properties['bottom'];
$y = $character[$c]['displacement'] + $captcha_vertical_displacement + $height - $bottom;
imagettftext ($image, $character[$c]['size'], $character[$c]['angle'], $cursor, $y, $color, $character[$c]['font'], $character[$c]['char']);
$cursor += $width + $character[$c]['space'];
endfor;
After the image is created, we apply a blur effect, but only if imagefilter function exists.
if (function_exists (’imagefilter’)):
imagefilter ($image, IMG_FILTER_GAUSSIAN_BLUR);
endif;
We also define our headers, so when the script will be called in a html tag, our browser should recognize it as an image and not as a php file.
header(’Cache-Control: no-store, no-cache, must-revalidate’);
header(’Cache-Control: post-check=0, pre-check=0′, FALSE);
header(’Pragma: no-cache’);
header(’Content-type: image/png’);
Finally, we output the image in PNG format and later destroy it from the script. The result will be a CAPTCHA image!
imagepng ($image);
imagedestroy ($image);
?>
So, how do you verify? This way:
if ($_POST['{captcha_field}'] == $_SESSION['captcha_session']):
// OK
else:
// WRONG
endif;
were {captcha_field} is your form text field. That’s all!



