Simple PHP math captcha image
Friday, June 22nd, 2007 in PHP
There are tons of captcha scripts on the web. The problem is that, from the enthusiasm of making them more flexible, a lot of code and pages are added and instead of a simple solution one may end up with several files necessary to display the captcha image. I’m not saying that they are useless, but for most of the time, such complexity is not quite welcomed. I strongly believe that less is more and that things should be kept simple. Having that in mind, I want to share a way to protect your forms using a math captcha image that requires a single PHP file and a font file.
This is a very simple, easy to understand example that shows you how to display a math captcha image that requires the user to do a little thinking. Simple operation like subtraction or addition is displayed on the math captcha and the user needs to input the result. Math captcha result is stored in session and from the page doing the form validation you just need to compare the value from session with the value that the user inputed.
If you want to implement the code ‘as is’, you have several options you can set. To do that, open image.php and play with the following settings:
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | // captcha width $captcha_w = 150; // captcha height $captcha_h = 50; // minimum font size; each operation element changes size $min_font_size = 12; // maximum font size $max_font_size = 18; // rotation angle $angle = 20; // background grid size $bg_size = 13; // path to font - needed to display the operation elements $font_path = 'fonts/courbd.ttf'; // array of possible operators $operators=array('+','-','*'); // first number random value; keep it lower than $second_num $first_num = rand(1,5); // second number random value $second_num = rand(6,11); |
$captcha_w and $captcha_h are the math captcha width and height values. For each of the operation’s elements, font will vary on each page load/reload. To set the minimum and maximum font sizes used to display the elements, set a minimum font size on $min_font_size and a maximum font size on $max_font_size. I think it’s obvious that the font size must be significantly smaller than the math captcha height, otherwise you’ll end up with an image showing only parts of the operators used so don’t exagerate on the max font size.
Again, for each element from the captcha, you can set a rotation angle. The angle takes values from -angle to angle in a random way. If for example you set this to 10 degrees, it will take values from anything in between -10 to 10.
On the background, the captcha displays a grid. To set the size of that grid, you’ll need to change the $bg_size value to whatever you feel comfortable with. The grid starts from top left, so any loose ends will end up on the right and bottom.
This captcha uses the GD library with freetype support. This means that the math operation displayed on the captcha uses a true type font that must be uploaded on the server and you’ll need to provide the path to that font file ( in this example’s case courbd.ttf). You can use any other font you want or like but always remember to set its path on the $font_path variable. For example you could use multiple fonts like this:
1 2 3 | $my_fonts = array('font_file_1.ttf','font_file_2.ttf','font_file_3.ttf'...); $element = rand(0, count($my_fonts)-1 ); $font_path = $my_fonts[$element]; |
Where font_file_1.ttf … include the complete path to the font files.
The last 3 variables ( $operators, $first_num and $second_num ) are the actual operation elements. You can extend the $operators array with let’s say division, but you’ll end up with operations that probably are a little hard for humans ( for example: 11/7 ) so stickying to this example’s values would be more than enough. Again, to not confuse the user, keep the second operand ($second_num) bigger that the first one ( $first_num ) so that you won’t end up with negative values that may confuse people ( ie: 3-9 ).
The rest of the script is for display purposes and it’s the actual code that displays the captcha. You probably won’t even have to change anything, but if you do, all the code is commented so I’m more than sure you’ll find your way.






38 comments
I stumbled across this tutorial actually looking for some information about arithmetic in PHP eval(). For some reason, I am not able to do addition. When I use a ‘+’ – it shows up as a single white space and I get the following error:
Parse error: syntax error, unexpected T_LNUMBER
I am able to do subtraction, multiplication, and division, but not addition.
I used your example of creating an array of operators, which is when I realized that the ‘+’ was showing up as a single whitespace. Have you had any issues like this? If so, what would you suggest I try? I’ll paste some code for you.
$operators= array("+","*","-");
$oneDay = 60 * 60 * 24;
//works
//$minTime = 28 * $oneDay - 3600;
//doesn't work
$maxTime = 28 * $oneDay + 3600;
//still testing
$minTime = "28".$operators[1].$oneDay.$operators[2]."3600";
//still testing - '+' shows up as ' '
$maxTime = "28".$operators[1].$oneDay.$operators[0]."3600";
The deal is to put valid PHP code for evaluation. This is from the php.net manual:
There are some factors to keep in mind when using eval(). Remember that the string passed must be valid PHP code, including things like terminating statements with a semicolon so the parser doesn’t die on the line after the eval(), and properly escaping things in code_str. To mix HTML output and PHP code you can use a closing PHP tag to leave PHP mode.
Your example will return a value in the case below:
$operators= array(“+”,”*”,”-”);
$oneDay = 60 * 60 * 24;
$maxTime = “28″.$operators[1].$oneDay.$operators[0].”3600″;
eval (“\$value=28″.$maxTime.”;”);
echo $value;
For a more simple example, try this:
$string=”1+1″;
eval(“\$value=”.$string.”;”);
echo $value;
As you may have noticed, the resulting evaluation is stored in $value, declared inside eval().
I hope I understood your problem right. If not, please give more details.
Thank you for sharing this captcha code!!! After examining a dozen different scripts, your solution is the easiest to implement within a form.
On lines 16 & 17 $img should be $captcha. Thanks for the code, regardless.
You’re right. Modified the code. Thanks!
Constantin,
I have been looking for a really simple captcha. I think your is the one. But I still can’t even get it to work.
I am new in these php programming.
I have placed the codes in my form as shown below. The captcha image does not show up anywhere. Please help If you can. Thanks in advance.
Note: Code removed by admin.
Hi Alan,
Have you downloaded the example files? Please upload those on your server and see if it works. Try to access the image.php file directly and see if any errors appear.
For this to work, you need to run GD lib on your server with freetype support.
If the captcha image is on laseralliance.com, please revise the font location. In order to display the math operation as image, the script needs the font ( on the downloadable example there’s a fonts folder ).
If you’re looking at image.php, on line 20 there’s imagettftext(….,”fonts/courbd.ttf”,…). The path to the font must be valid so I bet my tonight beer that either you missed to upload the folder or the path is invalid. I would appreciate it if you could digg this article.
Constantin,
Thanks for the reply.
I checked and it seems all the codes are in the right place.
The font is in the “fonts” folder. GD lib is enabled with freetype. still no image.
Note from Josh : On lines 16 & 17 $img should be $captcha. Thanks for the code, regardless.
Do I have to change these?
Thanks again for your help.
Alan
Have you tried with the new example? No, Josh was referring to the code on page and modifications were made to the script. Please try the new code and let me know. I’ll be around.
Later note
If the script you’re trying to install is on laseralliance.com, it may have something to do with the fact that PHP is installed as CGI program. I’m no expert in web servers configuration; I found this after a Google search: see the users comments. I hope it helps somehow.
I have gotten this all set up fine, and it works fine with the image displaying as well.. but a problem: When testing the form, I can put in the wrong answer or just type a couple of random letters, and it gives no error, plus still lets the form mail send to me. Help?
Do you verify the user input? Something like:
if( $_POST['user_input'] != $_SESSION['captcha value'] )
error code here
How you secure your form is up to you. The captcha only displays a math operation and stores the result in session. If you verify it or not it’s up to you.
Okay, missed that and fixed that part. So for:
if( $_POST['user_input'] != $_SESSION['captcha value'] )
error code here
Where you state “enter code here”, can I direct that to an html error page. I inserted that code as you showed in your example above the doctype in the page, but now when I test it with an incorrect answer, errors go to a 404 page not found. Forgive me, I am not well versed in php.
This is what I inserted above the doctype:
Run and write calc.”;
}
else
{
$error = “Man, you’re good! Your result is correct.”;
}
}
?>
The code in my example only validates the captcha in a very simple way and it’s just for example purposes. I suggest you search more info on form validation and practices, try to understand what’s going on and implement them into your pages. There are lots of tutorials regarding this subject, no point discussing it here. What I can pass on to you is this: never trust the user. I know this doesn’t solve your problem, but the best thing you can do for yourself is to search and read more info on this.
would be nice if you could also do “one plus two” or “two multiply 3″ which would really throw spambot off
It can be done. I’ll post an example with this soon.
Hello
well it doesn’t seem like so but the download zip dose not work for me win zip says ‘it does not appear to be a valid archive’
Hi Downloaded and the code working fine !
if you answer incorrect you can refresh and have another go and this displays a message ! thats fine BUT what i need to know is if answered correctly i want it to go to another page , how do i alter this to work ?
regards
Jamie
Hi Jamie,
It depends on how you want the validation processed. If you need to go to another page after you validated entries from user, you could do a redirect: header(“Location:post_processing.php”);
I have downloaded and tested this script. When I fill action=”process.php”, the script will not work but when I leave it blank (action=’ ‘) the script will work.
Can you help me about this?!
Thanks in advanced.
Hi Rico,
The script itself is the captcha image. Form processing and everything else is just for demo purposes. Anyway, about your problem, when you tell it to send the form to process.php, you must actually have that page and all form processing must be in process.php. I don’t know how you implemented your forms in your pages but if you used directly the files in demo, processing is done in index.php so by simply setting the form action to process.php, you tell it to send all data to process.php, file that either doesn’t exist or it doesn’t process the entry.
Thanks for your reply.
I use Php Form Generator (http://phpformgen.sourceforge.net/). I ensure you that all script work. I wish to add captcha for this form.
Thanks
Hi thanks for the info regarding it to go to another page , what i done is put the link in the top section of the page along with the message saying correct
Is there a chance i can make the questions alot harder or more of a longer question
for example
2*3+7-9 =
many thanks jamie
Yes, it should be possible. Check the code in captcha and let me know if you can figure something out.
Hi does anyone know how to do this or edit the code ive tried but failed to do so ?
I want to do like Rico. I want to after I put in the math equation and press submit, it performs an action. I have a mailer.php that sends it information to the owners email. Do i replace the the top part saying you got the question right with some other php?
Hi Brandon,
Basically, what you have to do in a very simplistic manner is to check if data validates and everything is OK. To verify the captcha result, you should compare the entry from your user ( in $_POST['captcha'] or whatever name you have for that input field ) with what you got stored in session by the captcha.
Do i replace the the top part saying you got the question right with some other php?
I really don’t know how your code looks like. In order to use this you should first have a good knowledge on data validation. There are tons of tutorials regarding this on the internet, please try and read a few and understand why you need to have proper validation on your forms before even thinking of using that data. Don’t just copy code, understand it first.
Instead of using eval:
switch($operators[0])
{
case “+”: $session_var = intval($second_num + $first_num); break;
case “-”: $session_var = intval($second_num – $first_num); break;
case “*”: $session_var = intval($second_num * $first_num); break;
}
[...] the “captcha” I’ve half used simple PHP math captcha image. I say half-used as my current host doesn’t support FreeType so I am currently unable to use [...]
hi I was trying to use your math captcha in http://uniquetrails.com/math_captcha/ but the image is not displayed for some reason. I checked and I understand it does have gd. what could be the reason that I am unable to use math captcha?
Thanks in advance for your response
Hi Suresh,
Yes, GD is enabled, but if you read above, you need GD with FreeType Support. If you open image.php directly, you’ll see that it gives an error saying
Fatal error: Call to undefined function imagettftext() in … on line 84
By the way, remove that phpinfo file from there. It’s not safe to expose that info so easily.
Hi Constantin,
Thank you for reply and warning me about the phpinfo file. But can you suggest what shall I do to get the captcha working? where do I get GD with FreeType Support and how do I install it? Sorry, I am quiet new to this.
Thank you once again.
Talk to your server administrator about this. It’s not something that you can do ( unless you have full access to your hosting server ).
Hi,
great captcha, but there is a failure in it:
The result of the calculation is always wrong when you open the website with your captcha for the first time when surfing with Safari, Firefox and IE . Only Opera calculates it right on the first try.
After the first submit all browsers calculate it right.
This is also the case at your demo.
Do you have any idea?
cheers
Erik
I tested my demo on Firefox 3.5.9, IE8 and Safari for Win XP. Everything worked just fine, can’t say why isn’t working in your case. You have a demo page anywhere?
There must be a problem with Windows 7 or something else, I’ve tested your demo: http://www.php-help.ro/examples/math_captcha_image/ on two Win 7 systems and everytime I get the wrong result on the first attempt on the second third forth … attempt all works fine….
Because I’ve tested it on my Win XP system and all browsers works fine.
Hmm, this is weird. I can’t test on Win7 but I’ll ask a friend tomorrow to do it for me. I’ll get back with news.
dude can you do the captcha without using session?
Sorry but no. This script uses session, others might work without it. If I may ask, why is it a problem using session?
Leave a comment