Code snippets for symfony 1.x

Navigation

Refine Tags

Snippets tagged "verification"

Simple Captcha with GD

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.

by Jason Ibele on 2006-06-13, tagged captcha  image  verification 
(15 comments)