* @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 .= "
";
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;
}
}
}
?>