PHP Forums Archive

PHP CAPTCHA, image validation

Tags: php, script, hosting, image, captcha, recaptcha

Olaf posted on 2010-02-05 18:16:53 #

Use this script to protect your contact form, your whois query tool or just a form where some extra validation is needed. How does it work?
A session will be created inside a dynamic image file (requires GD library). The random value of this image appears inside the generated CAPTCHA image. The user has to enter this value into a form field. While processing the form, the entered value get checked against the session value. Without entering the correct string a form will not be processed. This mechanism is very useful to protect your form again (spam) bots.


The PHP code snippet


Create a php file with that code an call it "random.php"

<?php
session_start();

if (empty($_SESSION['rand_code'])) {
    $str = "";
    $length = 0;
    for ($i = 0; $i < 4; $i++) {
        // this numbers refer to numbers of the ascii table (small-caps)
        $str .= chr(rand(97, 122));
    }
    $_SESSION['rand_code'] = $str;
}

$imgX = 60;
$imgY = 20;
$image = imagecreatetruecolor(60, 20);

$backgr_col = imagecolorallocate($image, 238,239,239);
$border_col = imagecolorallocate($image, 208,208,208);
$text_col = imagecolorallocate($image, 46,60,31);

imagefilledrectangle($image, 0, 0, 60, 20, $backgr_col);
imagerectangle($image, 0, 0, 59, 19, $border_col);

$font = "VeraSe.ttf"; // it's a Bitstream font check www.gnome.org for more
$font_size = 10;
$angle = 0;
$box = imagettfbbox($font_size, $angle, $font, $_SESSION['rand_code']);
$x = (int)($imgX - $box[4]) / 2;
$y = (int)($imgY - $box[5]) / 2;
imagettftext($image, $font_size, $angle, $x, $y, $text_col, $font, $_SESSION['rand_code']);

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

How-to use it?


Use this HTML code in your form:

<input type="text" name="validator" id="validator" size="4" />
<img src="random.php" alt="CAPTCHA image" align="top" />

This is the code to test the entered value:

if (!empty($_POST['validator']) && $_POST['validator'] == $_SESSION['rand_code']) {
    // process your form here
    // at least destroy the session
    unset($_SESSION['rand_code']);
}

Comments / discussions

melgurt posted on 2010-03-05 17:49:29 #

Great script!! works well.. below where my improvements..it generates a new image on refresh now

Random.php

<?php
session_start();
$imgX = 60;
$imgY = 20;
$image = imagecreatetruecolor(60, 20);

$backgr_col = imagecolorallocate($image, 238,239,239);
$border_col = imagecolorallocate($image, 208,208,208);
$text_col = imagecolorallocate($image, 46,60,31);

imagefilledrectangle($image, 0, 0, 60, 20, $backgr_col);
imagerectangle($image, 0, 0, 59, 19, $border_col);

$font = "VeraSe.ttf"; // it's a Bitstream font check <a rel="nofollow" href="http://www.gnome.org" rel="nofollow">http://www.gnome.org</a> for more
$font_size = 10;
$angle = 0;
$box = imagettfbbox($font_size, $angle, $font, $_SESSION['rand_code']);
$x = (int)($imgX - $box[4]) / 2;
$y = (int)($imgY - $box[5]) / 2;
imagettftext($image, $font_size, $angle, $x, $y, $text_col, $font, $_SESSION['rand_code']);

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

Signup.php

session_start();
unset($_SESSION['rand_code']);
if (empty($_SESSION['rand_code'])) {
    $str = "";
    $length = 0;
    for ($i = 0; $i < 4; $i++) {
        // this numbers refer to numbers of the ascii table (small-caps)
        $str .= chr(rand(97, 122));
    }
    $_SESSION['rand_code'] = $str;
}
?>
<input type="text" name="validator" id="validator" size="4" />
<img src="random.php" alt="CAPTCHA image" align="top" />

Olaf posted on 2010-03-09 08:41:40 #

Hi,

thanks for the suggestion. I did the same in the beginning but changed it because I hate it to insert a new "string" if my form doesn't validate.
I use this button in my contact form for more than 2 years and never got spam (sure I got spam from humans).
May I ask you to edit your post to mention only the changed code? that makes it much easier for other users.

skillfilluk posted on 2010-08-10 23:56:18 #

Hi,
Can someone please help me with the Captcha code above, I have done what it says but on my contact form there is only a box showing with no image above the box. I have checked with my hosting which they say GD library is installed. Also can the script be added to a registration form? Thanks

Olaf posted on 2010-08-11 05:27:48 #

Hi,

maybe that the "custom" font is not supported?

skillfilluk posted on 2010-08-11 09:34:25 #

I spoke to my hosting and they do not support custom fonts so is there anything I can change to get this working, as I'm getting loads of spam.

Olaf posted on 2010-08-11 12:41:31 #

Try this reCAPTCHA tutorial

tallestguy posted on 2010-09-21 09:57:13 #

Pls, Olaf the CAPTCHA image code is only displaying blank image, pls help out in a more elaborate manner. Thanks.

Olaf posted on 2010-09-21 10:02:03 #

Quote from: tallestguy
"Pls, Olaf the CAPTCHA image code is only displaying blank image, pls help out in a more elaborate manner. Thanks."

Check the previous posts from this topic, it seems that custom fonts are not supported by several hosting providers. I posted also a link to a tutorial about reCaptcha.

tallestguy posted on 2010-10-10 15:52:05 #

Thanks guy,I changed the custom font:$font = "VeraSe.ttf"; to: $font = "arial"; the normal default font and it works. more power to you.

tallestguy posted on 2010-10-10 16:18:54 #

Please, what if i need the code to consist of both alphabets and numbers, what will i do or which part of the code do i need to change.

Olaf posted on 2010-10-10 17:55:52 #

Quote from: tallestguy
"Please, what if i need the code to consist of both alphabets and numbers, what will i do or which part of the code do i need to change."

check this part:

// this numbers refer to numbers of the ascii table (small-caps)
        $str .= chr(rand(97, 122));

Check the ascii table for more "numbers"

Boettgerie posted on 2010-10-13 21:41:09 #

Hi!
I can display the CAPTCHA on my website.
But nothing is checked. Only my standard checks are done, but the system doesn't care about the CAPTCHA. Does anyone have an idea how I have to implement this?

Here my code:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta http-equiv="pragma" content=no-cache">
  <meta http-equiv="cache-control" content="no-cache">
  <meta http-equiv="expires" content="0">
  <title>Forumsbeitrag</title>
<script language="Javascript">
function compare()
{
	if (this.document.forum.user.value == "")
	{
	  alert("Bitte geben Sie Ihren Namen an !");
	  return false;
	}
	if (this.document.forum.betreff.value == "")
	{
	  alert("Bitte geben Sie einen Betreff an !");
	  return false;
	}
	if ( (this.document.forum.email.value.indexOf('@', 0) == -1) || (this.document.forum.email.value.indexOf('.', 0) == -1) )
	{
	  alert("Bitte geben Sie eine korrekte E-Mail-Adresse ein !");
	  return false;
	}
}
</script>
</head>
<body>
<div style="font-family:arial">
<h2>Ihr Forumsbeitrag:</h2>
<form name="forum" action="new.php" method="post" onSubmit="return compare();">
<table border="0">
  <tr>
    <td>Ihr Name</td>
    <td><input type="text" name="user"></td>
  </tr>
  <tr>
    <td>Ihre E-Mail-Adresse</td>
    <td><input type="text" name="email"></td>
  </tr>
  <tr>
    <td>Betreff-Zeile</td>
    <td><input type="text" name="betreff"></td>
  </tr>
  <tr>
    <td>Ihr Eintrag</td>
    <td>
      <textarea name="beitragstext" cols="40" rows="5"> </textarea>
    </td>
  </tr>
  <tr>
    <td>

<?php
session_start();
unset($_SESSION['rand_code']);
if (empty($_SESSION['rand_code'])) {
    $str = "";
    $length = 0;
    for ($i = 0; $i < 4; $i++) {
        // this numbers refer to numbers of the ascii table (small-caps)
        $str .= chr(rand(97, 122));
    }
    $_SESSION['rand_code'] = $str;
}
?>

<input type="text" name="validator" id="validator" size="4" />
CAPTCHA image

      <input type="submit" name="submit" value="Abschicken">
      <input type="reset" value="Löschen">
    </td>
  </tr>
</table>
</form>
</div>
</body>
</html>

Thanks and regards,
Heiko

Olaf posted on 2010-10-14 09:57:37 #

Hallo Heiko,

You're using the script in wrong way, check the contact form from this website and also the explanation from the first post in this topic.

Boettgerie posted on 2010-10-14 10:55:43 #

Hello Olaf,

OK, I assume that I am using it the wrong way otherwise it would work LOL.
I have checked the contact form and can see how it works, this is how I have expected the script works also in my code.
I have also checked the explanation from the first topic. But I further have no clue.
I found out that I was missing this part of the code:

if (!empty($_POST['validator']) && $_POST['validator'] == $_SESSION['rand_code']) {
    // process your form here
    // at least destroy the session
    unset($_SESSION['rand_code']);
}

But I don't know where to put this. As you can see in my code I am using JAVASCRIPT to check if all fields are filled.

Could you give me a hint where and how to implement this?

Thanks and regards,
Heiko

Olaf posted on 2010-10-14 10:59:49 #

Hi Heiko,

you can't use the a Javascript validation with server side validation in PHP.
Maybe you should try something really cool stuff using jQuery

Boettgerie posted on 2010-10-14 14:34:53 #

Hi Olaf,

it is possible. I just implemented something like this:

$captcha = $_SESSION['rand_code'];
?>
<script type=text/javascript>
var Captcha="<? echo $captcha; ?>";
</script>
<?php

Thanks for your help!

Heiko

Olaf posted on 2010-10-16 10:18:24 #

Heiko, this is not safe. Spambots are still able to send mail through your form