* @copyright Copyright (c) 2004-2006 Interspire Pty. Ltd. * @package ArticleLive NX * */ class AL_CAPTCHA { /** * Holds the secret captcha code. * * @var string */ var $__secret; /** * Determines the length of the code. Default is 6. * * @var integer */ var $length; /** * Contains the path to the TTF font file to be used for GD. * * @var string */ var $fontPath; /** * Contains the path to the list of letter images to be used * when GD isn't installed on the server. * * @var string */ var $imgDir; /** * Determines the size of the font when using GD * * @var integer */ var $fontSize; /** * Determines the color of the font when using GD * * @var hexidecimal */ var $textColor; /** * Determines one of the gradient values for the image background when * using GD * * @var html color value */ var $bgCol1; /** * Determines one of the gradient values for the image background when * using GD * * @var html color value */ var $bgCol2; /** * Determines the shape of the gradient fill in the image background when * using GD * * @var string */ var $bgFillStyle; /** * Constructor * * Sets variables needed by the class */ function AL_CAPTCHA () { // Detect if the server has GD installed or not // Set variables for later use if (function_exists('imageCreateFromPNG')) { $this->type = 'dynamic'; }else{ $this->type = 'static'; } // all variables $this->length = 6; // img captcha variables $this->imgDir = realpath(dirname(__FILE__).'/../../admin/images/captcha'); // gd type captcha variables $this->fontPath = realpath(dirname(__FILE__).'/../../admin/images/fonts/captcha.ttf'); $this->fontSize = '20'; $this->textColor = '000000'; $this->bgCol1 = '#ffffff'; $this->bgCol2 = '#bcbcbc'; $this->bgFillStyle = 'square'; } /** * CreateSecret * * Generates a new random secret captcha code * * @return true; */ function CreateSecret(){ // get random characters, set the secret variable to it $this->__secret = $this->GetRandom($this->length); //set the session variable $this->SetSecret(); return true; } /** * GetSecret * * Detects if there is already a secret saved, if so the function returns the secret * otherwise it generates a new one. * * @return string */ function GetSecret(){ if(!isset($this->__secret) OR $this->__secret == ''){ // if the secret is not already set, create it return $this->LoadSecret(); }else{ // otherwise return it return $this->__secret; } } /** * LoadSecret * * If the secret is stored in the Session, retrieve and decode it * Otherwise create a new secret. * * @return secret */ function LoadSecret(){ // if the secret stored in the session, retreive it // otherwise create a new secret if(isset($_SESSION['captchaCode'])){ $this->__secret = base64_decode($_SESSION['captchaCode']); }else{ $this->CreateSecret(); } return $this->__secret; } /** * SetSecret * * Sets the session variable to the current secret code * * @return unknown */ function SetSecret(){ // delete current secret unset($_SESSION['captchaCode']); // set new secret to the session if($_SESSION['captchaCode'] = base64_encode($this->GetSecret())){ return true; }else{ return false; } } /** * GetRandom * * Generates a string of random alphanumeric characters of a length * determined by $length * * @param integer $length * @return string */ function GetRandom($length=5){ // init $returnRandom = ''; // make sure its an integer $length = (int)$length; // If we are running php less than 4.2.0 we have to manually seed // mt_rand otherwise php does it for us if (version_compare(phpversion(), '4.2.0') < 0) { // seed with microseconds function make_seed() { list($usec, $sec) = explode(' ', microtime()); return (float) $sec + ((float) $usec * 100000); } mt_srand(make_seed()); } for ($i=0;$i<$length;$i++){ $nextChar = mt_rand(0, 35); // 10 digits + 26 lowercase = 36 chars if(($nextChar >=10) && ($nextChar < 36)){ // lowercase letters $nextChar -= 10; // bases the number at 0 instead of 10 $nextChar = chr($nextChar + 97); // ord('a') == 97 } else { // 0-9 $nextChar = chr($nextChar + 48); // ord('0') == 48 } $returnRandom .= $nextChar; } return $returnRandom; } /** * EncodeLetter * * Takes in 1 letter and outputs it in a jumbled string * * @param char $letter * @return string */ function EncodeLetter($letter){ // make sure we have 1 letter $letter = substr($letter,0,1); // we are going to hide the single letter in // a string of 15 characters, 10 before, 4 after. // get the first random 10 $random = $this->GetRandom(10); // get the last random 4 $random2 = $this->GetRandom(4); // put it all together $together = $random.$letter.$random2; // encode it for the session storage $together = base64_encode($together); return $together; } /** * DecodeLetter * * Takes in a string and extracts the hidden character inside * * @param string $string * @return char */ function DecodeLetter($string){ // decode the session value $string = base64_decode($string); // pic out letter out of the random string of characters $letter = substr($string,10,1); return $letter; } /** * LoadImage * * Outputs an image determined by $this->type * * @param char $letter * @return binary */ function LoadImage($letter='') { // if dynamic, use GD, otherwise open imagefile if($this->type == 'dynamic'){ // buffer everything so its all returned together ob_start(); // are we using a preset background image if (!is_file($this->bg)) { $img_handle = imageCreate(110,40); } else { $img_handle = imageCreateFromPNG($this->bg); } // grab text color $col = hex2rgb($this->textColor); // set background gd_gradient_fill($img_handle, $this->bgFillStyle, $this->bgCol1, $this->bgCol2); // use the image value we set, if its not valid, default to black if ($col) { $text_color = ImageColorAllocate ($img_handle, $col['r'], $col['g'], $col['b']); } else { $text_color = ImageColorAllocate ($img_handle, 0, 0, 0); } // if the font-file exists then use it, otherwise, use the GD default text if (file_exists($this->fontPath)) { imagettftext($img_handle, $this->fontSize, 0, 4, 35, $text_color, $this->fontPath, $this->__secret); } else { ImageString ($img_handle, 5, 20, 13, $this->__secret, $text_color); } // create the image ImagePng ($img_handle); ImageDestroy ($img_handle); $content = ob_get_contents(); ob_end_clean(); return $content; }else{ $filename = $this->imgDir.'/'.strtolower($letter).'.png'; // check to see if the settings are correct if (!is_dir($this->imgDir)) return false; if (!is_file($filename)) return false; ob_start(); // output image file readfile($filename); $content = ob_get_contents(); ob_end_clean(); return $content; } } /** * OutputImage * * Outputs the image header, then the content of the image * */ function OutputImage(){ // check to see what action we need to take if($this->type == 'dynamic'){ $this->LoadSecret(); // send several headers to make sure the image is not cached // a date in the past header("Expires: Mon, 23 Jul 1993 05:00:00 GMT"); // always modified header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); // HTTP/1.1 header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0, max-age=0", false); header('Content-type: image/png'); echo $this->LoadImage(); }else{ // find the encoded string $crypted = substr($_SERVER['REQUEST_URI'],strpos($_SERVER['REQUEST_URI'],'__captcha')+strlen('__captcha/'),15); // get the single letter $letter = $this->DecodeLetter($crypted); // output image header('Content-type: image/png'); echo $this->LoadImage($letter); } die(); } /** * ShowCaptcha * * Returns the html img tags for the captcha image(s) * * @return string */ function ShowCaptcha(){ // determine what we need to show for the captcha if($this->type == 'dynamic'){ // single GD generated image $return = ''; $return .= "img".$i.""; return $return; }else{ // multiple static images $return = ''; for ($i=0;$i__secret);$i++){ $return .= "EncodeLetter(substr($this->__secret,$i,1))."/' alt='img".$i."'>"; } return $return; } } } ?>