I wrote a small captcha class a few years ago that has served me decently, The code is not pretty, as I wrote it a long time ago, but I'm positive it would be a decent starting ground for a new more php5'ish class(es).
All that is needed is a ttf font located in captcha::font_file..
Code: Select all
<?php
class captcha {
var $key;
var $length;
var $lx;
var $ly;
var $path="tmp";
var $nb_noise;
var $filename;
var $imagetype="png";
var $public_key;
var $font_file="includes/comic.ttf";
function captcha($length=6,$lx=200,$ly=60,$nb_noise=115) {
$this->key=md5("A1l y0ur b4se ar3 b3l0ng t0 u$");
$this->length=$length;
$this->lx=$lx;
$this->ly=$ly;
$this->nb_noise=$nb_noise;
$this->public_key=$this->generate_public();
}
function get_filename($public="") {
if ($public=="") $public=$this->public_key;
if (!is_dir($this->path)) mkdir($this->path);
return $this->path."/".$public.".".$this->imagetype;
}
function generate_private($public="") {
if ($public=="") $public=$this->public_key;
return substr(md5($this->key.$public),16-$this->length/2,$this->length);
}
function generate_public() {
return substr(md5(mt_rand()),mt_rand(0,(31-$this->length)),$this->length);
}
function check_captcha($public,$private) {
$this->cleanTmp($this->path);
if (file_exists($this->get_filename($public))) unlink($this->get_filename($public));
return (strtolower($private)==strtolower($this->generate_private($public)));
}
function cleanTmp($path) {
if (substr($path, -1) != "/") $path.="/";
if ($dir = opendir($path)) {
while (false !== ($file = readdir($dir))) {
if ($file != "." && $file != ".." && end(explode(".",$file)) == "png") unlink ($path.$file);
}
closedir($dir);
}
}
function make_captcha($noise=true) {
$private_key = $this->generate_private();
$image = imagecreatetruecolor($this->lx,$this->ly);
$back=ImageColorAllocate($image,intval(rand(224,255)),intval(rand(224,255)),intval(rand(224,255)));
ImageFilledRectangle($image,0,0,$this->lx,$this->ly,$back);
if ($noise) { // rand characters in background with random position, angle, color
for ($i=0;$i<$this->nb_noise;$i++) {
$size=intval(rand(6,14));
$angle=intval(rand(0,360));
$x=intval(rand(10,$this->lx-10));
$y=intval(rand(0,$this->ly-5));
$color=imagecolorallocate($image,intval(rand(160,224)),intval(rand(160,224)),intval(rand(160,224)));
$text=chr(intval(rand(45,250)));
ImageTTFText ($image,$size,$angle,$x,$y,$color,$this->font_file,$text);
}
} else { // random grid color
for ($i=0;$i<$this->lx;$i+=10) {
$color=imagecolorallocate($image,intval(rand(160,224)),intval(rand(160,224)),intval(rand(160,224)));
imageline($image,$i,0,$i,$this->ly,$color);
}
for ($i=0;$i<$this->ly;$i+=10) {
$color=imagecolorallocate($image,intval(rand(160,224)),intval(rand(160,224)),intval(rand(160,224)));
imageline($image,0,$i,$this->lx,$i,$color);
}
}
for ($i=0,$x=5; $i<$this->length;$i++) {
$r=intval(rand(0,128));
$g=intval(rand(0,128));
$b=intval(rand(0,128));
$color = ImageColorAllocate($image, $r,$g,$b);
$shadow= ImageColorAllocate($image, $r+128, $g+128, $b+128);
$size=intval(rand(20,25));
$angle=intval(rand(-30,30));
$text=strtoupper(substr($private_key,$i,1));
ImageTTFText($image,$size,$angle,$x+18,$size+26,$shadow,$this->font_file,$text);
ImageTTFText($image,$size,$angle,$x+18,$size+20,$color,$this->font_file,$text);
$x+=$size+2;
}
if ($this->imagetype=="jpg") imagejpeg($image, $this->get_filename(), 100);
else imagepng($image, $this->get_filename());
ImageDestroy($image);
}
function show($noise=true) {
$this->make_captcha($noise);
$res="<input type=hidden name='public_key' value='".$this->public_key."'/>";
$alt= "Please type the {$this->length} chars within 0..9 and A..F";
$res.="<img id=\"captchaImg\" src='".$this->get_filename()."' alt='$alt'/>";
echo $res;
}
}
?>