![]() |
|
Snippets |
|
Ever wanted to have a captcha image verification, but didn't want to go through the trouble of using the jgraph lib? Me too! Here's what I came up with.
sfCaptcha.class.php in /lib
class sfCaptcha { public $securityCode; private $codeLength=6; private $imageFile= 'captchaImg.jpg'; public $fontSize = 12; public $fontColor = array("252525","8b8787","550707"); public function simpleRandString($length, $list="23456789ABDEFGHJKLMNQRTYabdefghijkmnqrty") { /* * Generates a random string with the specified length * Chars are chosen from the provided [optional] list */ mt_srand((double)microtime()*1000000); $newstring = ""; if ($length > 0) { while (strlen($newstring) < $length) { $newstring .= $list[mt_rand(0, strlen($list)-1)]; } } return $newstring; } public function generateImage() { $this->securityCode = $this->simpleRandString($this->codeLength); $img_path = dirname(__FILE__)."/../web/uploads/"; if(!is_writable($img_path) && !is_dir($img_path)){ $error = "The image path $img_path does not appear to be writable or the folder does not exist. Please verify your settings"; throw new Exception($error); } $this->img = ImageCreateFromJpeg($img_path.$this->imageFile); $img_size = getimagesize($img_path.$this->imageFile); foreach($this->fontColor as $fcolor) { $color[] = imagecolorallocate($this->img, hexdec(substr($fcolor, 1, 2)), hexdec(substr($fcolor, 3, 2)), hexdec(substr($fcolor, 5, 2)) ); } $line = imagecolorallocate($this->img,255,255,255); $line2 = imagecolorallocate($this->img,200,200,200); $fw = imagefontwidth($this->fontSize)+3; $fh = imagefontheight($this->fontSize); // create a new string with a blank space between each letter so it looks better $newstr = ""; for ($i = 0; $i < strlen($this->securityCode); $i++) { $newstr .= $this->securityCode[$i] ." "; } // remove the trailing blank $newstr = trim($newstr); // center the string $x = ($img_size[0] - strlen($newstr) * $fw ) / 2; $font[0] = 'arial.ttf'; $font[1] = 'TIMES.ttf'; $font[2] = 'COURI.ttf'; // create random lines over text for($i=0; $i <3;$i++){ $s_x = rand(40,180); $s_y = rand(5,35); $e_x = rand(($s_x-50), ($s_x+50)); $e_y = rand(5,35); $c = rand(0, (count($color)-1)); imageline($this->img, $s_x,$s_y, $e_x,$e_y, $color[$c]); } // random bg ellipses imageellipse($this->img, $s_x, $s_y, $e_x, $e_y, $line); imageellipse($this->img, $e_x, $e_y, $s_x, $s_y, $line2); // output each character at a random height and standard horizontal spacing for ($i = 0; $i < strlen($newstr); $i++) { $hz = mt_rand( 10, $img_size[1] - $fh - 5); // randomize rotation $rotate = rand(-35, 35); // randomize font size $this->fontSize = rand(14, 18); // radomize color $c = rand(0, (count($color)-1)); // imagechar( $this->img, $this->fontSize, $x + ($fw*$i), $hz, $newstr[$i], $color); imagettftext($this->img, $this->fontSize,$rotate , $x + ($fw*$i), $hz + 12, $color[0], $font[$c], $newstr[$i]); } } }
in the moduleyou want to use, in my case the user module add the following to your actions.
// replace XXX with the name of the action that is calling the form, like validateRegistration if your action is executeRegistration. // This function validates the stored captcha against the users input and returns true if they match, or returns an error back to the form if they don't. public function validateXXX() { if($this->getRequest()->getMethod() == sfRequest::POST) { $captcha = $this->getRequestParameter('captcha'); $session_captcha = $this->getUser()->getAttribute('captcha'); if($captcha != $session_captcha) { $this->getRequest()->setError('captcha', 'The code you entered did not match the one provided, please try again.'); return false; } } return true; } // action that executes the actual image public function executeGetImage() { $this->getResponse()->setContentType('image/jpeg'); $captcha = new sfCaptcha(); $captcha->generateImage(); $this->getUser()->setAttribute('captcha', $captcha->securityCode); imagejpeg($captcha->img); imageDestroy($captcha->img); }
and the in the view showing the image and form
<div class='error'><?php echo form_error('captcha') ?></div> <img src='<?php echo url_for('user/getimage'); ?>'><br> <?php echo input_tag('captcha') ?>
Note that the image source user/getimage refers to my user module and the executeGetImage() function we added above.
You'll need to add a JPG to your /web/uploads/ directory with the size of 200px w x 40px h and the name "captchaImg.jpg" (you can change the name in the sfCaptcha.classs.php file too). This is used to generate the captcha image and if you choose so you can create a background in the image that will be used. Otherwise, just leave it blank.