PHP Classes
Icontem

File: as_snipercaptcha.php


  Search   All class groups All class groups   Latest entries Latest entries   Top 10 charts Top 10 charts   Newsletter Newsletter   Blog Blog   Forums Forums   Help FAQ Help FAQ  
  Login   Register  
Recommend this page to a friend! ReTweet ReTweet Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Alexander Selifonov  >  DHTML and CSS CAPTCHA  >  as_snipercaptcha.php  
File: as_snipercaptcha.php
Role: Class source
Content type: text/plain
Description: Main class file
Class: DHTML and CSS CAPTCHA
CAPTCHA validation using colored boxes and AJAX
 

Contents

Class file image Download
<?PHP
/**
* @desc as_snipercaptcha.php :
* Another CAPTCHA engine for anti-BOT site protecting.
* It doesn't use any graphic libraries (like GDI) for generating image "on the fly".
* Instead it uses Javascript and DHTML to show "aiming" grid, where user must click on some cells.
* @Author Alexander Selifonov <as-works [at] narod.ru> <alex [at] selifan.ru>
* @link http://www.selifan.ru/phpfiles.php
* @Copyright Alexander Selifonov 2008 , under GPL license
* @Version 1.03.007
* Last modified: 10.12.2008
*/
if(!defined('IMGPATH')) define('IMGPATH','');
class CSniperCaptcha {
  var $serverscript = '';
  var $codelen = 4; # how many user clicks in test sequence
  var $idlist = ''; # string with all random generated id's for sniper grid
  var $x_len = 0;   # grid dimensions
  var $y_len = 0;
  var $cellsize;
  var $var_curpos = 0; # entered 'numbers' counter
  var $prevcode = -1;
  var $startx = 0;
  var $starty = 0;
  var $accumulated = '';
  var $useranswer = '';
  var $submitbutton_id = '';
  var $jscodepassed = '';
  var $jscodefailed = '';
  var $b_buffered = false;
  var $reinit_action = false;
  /**
  * @desc CSniperCaptcha constructor
  * @param int/string - pass code length (how many times user should point & click on the grid
  * @param string - ID of 'submit' form button. It'll become enabled whrn all code "entered"
  * @param string - javascript function name, that will be fired instantly on last user click,
  *        if code correct (CAPTCHA test passed)
  * @param string - this function will call if test failed
  * @param  mixed $reinit activates captcha re-init feature
  */
  function CSniperCaptcha($codelen=4, $submitid='', $jscode_success='',$jscode_fail='',$reinit=false) {
    $this->codelen = $codelen;
    $this->submitbutton_id = $submitid;
    $this->serverscript = $_SERVER['PHP_SELF'];
    $this->jscodepassed = $jscode_success;
    $this->jscodefailed = $jscode_fail;
    $this->reinit_action = $reinit;
    if(!isset($_SESSION)) @session_start();
  }
  /**
  * @desc all output will be redirected to returned var, no immediate echo
  */
  function SetBufferedOutput($buffered=true) { $this->b_buffered = $buffered; }
  /**
  * @desc echoes STYLE ref to a CSS file with styles needed by CAPTCHA, and ref to the common func. js file.
  */
  function DrawRefs($csspath='',$jspath='') {
    $ret = '';
    if($csspath!==false) $ret .="<link rel=\"stylesheet\" type=\"text/css\" href=\"{$csspath}captcha_styles.css\" >\n";
    if($jspath!==false) $ret .="<SCRIPT SRC=\"{$jspath}as_jsfunclib.js\" type=\"text/javascript\"></SCRIPT>\n";
    if(isset($this) && $this->b_buffered) return $ret;
    echo $ret;
  }
  # SetServerScript: sets backend server script URI
  function SetServerScript($uri) { $this->serverscript = $uri; }

  function Draw($width=0, $height=0, $cellsize=0, $tovar=0) {
    global $sitestrings;
    $gen = array();
    $jsdigvar = '0';
    $ret = '';
    $x_len = ($width)? $width: intval(mt_rand(4,10));
    $y_len = ($height)? $height : intval(mt_rand(3,6));
    $this->cellsize = array(0,0);
    if(empty($cellsize) || $cellsize<=8) {
      $this->cellsize[1] = round(mt_rand(10,20));
      $this->cellsize[0] = round(mt_rand($this->cellsize[1],$this->cellsize[1]+10));
    }
    else $this->cellsize = array($cellsize,$cellsize);
    $ret.="<table border='0' cellspacing='1' cellpadding='0' id='captchaTable'>";
    $this->idlist = 'xxx';
    $init_prompt = isset($sitestrings['captcha_init'])? $sitestrings['captcha_init'] : '';
    for($y=1;$y<=$y_len;$y++) {
      $ret.="<tr>";
      for($x=1;$x<=$x_len;$x++) {
        $cellid = chr(intval(mt_rand(97,122))).chr(intval(mt_rand(97,122))).chr(intval(mt_rand(97,122))).$y.$x;
        $this->idlist .= '|'.$cellid;
        $ret.= "<td id='$cellid' onClick=\"return CaptchOneShot(this)\" class=\"captcha_cell\" style=\"cursor:hand\"
        onMouseOver='this.className=\"captcha_cellmo\"' onMouseOut='this.className=\"captcha_cell\"'><img src='".IMGPATH."empty.gif' width={$this->cellsize[0]} height={$this->cellsize[1]}/></td>";
      }
      # if needed, draw 'initialize' button, to start captcha from very beginning
      if($y==1 && ($this->reinit_action)) $ret .="<td rowspan=\"$y_len\" valign=top><a href=\"javascript://\" onclick=\"CaptchaReinit(true)\"><img src=\"".IMGPATH."captcha_init.gif\" width=16 height=16 border=0 />$init_prompt</a></td>";
      $ret.= "</tr>";
    }
    $ret .= "<tr><td colspan='$x_len' class='captcha_cell' style='text-align:left'><img id='caprogress' src='".IMGPATH."cap_progress.png' width='1' height='8' /></td></tr>";
    $ret.= "</table><img id='cap_sight' src='".IMGPATH."captchasight.png' width=7 height=7 style='z-index:10; position:absolute; display:none;' />";
    $_SESSION['captcha_idlist'] = $this->idlist;
    $_SESSION['captcha_lenx'] = $x_len;
    $_SESSION['captcha_leny'] = $y_len;
    $_SESSION['captcha_cellsize'] = $this->cellsize;
    $_SESSION['captcha_codelen'] = $this->codelen;
    $_SESSION['captcha_accumulated'] = $_SESSION['captcha_useranswer'] = 'xxx';
    $this->var_curpos = $_SESSION['captcha_curpos'] = 0;
    $this->prevcode = $_SESSION['captcha_prevcode'] =  -1;
    if(($tovar) || ($this->b_buffered)) return $ret;
    echo $ret;
  } # Draw() end
  /**
  * @desc DrawJsCode() prints all needed javascript code for CAPTCHA processing
  * @param integer/boolean if non-empty, CAPTCHA client-server exchange sequence will start immediately
  */
  function DrawJsCode($autostart=1) {
    $ret ="
<script language=\"JavaScript\" type=\"text/javascript\">
<!--
var busyxml = false;
var handlerurl = \"{$this->serverscript}\";
var captable = false;
var finished = 0;
var as_resize_handled=false;
var as_captcha_tmer = null;
function CaptchaReinit(evt) {
  cap_imgobj=0;".(!empty($this->submitbutton_id)?"asGetObj('{$this->submitbutton_id}').disabled=true;":'')."
  SendCaptchaChecking(0);
  ".(is_string($this->reinit_action)? "if(evt){ {$this->reinit_action} }":'')."
}
function CaptchaResizing() {
  if(finished>=500) return;
  if(as_captcha_tmer!=null) try { clearTimeout(as_captcha_tmer); as_captcha_tmer=null;} catch(e){};
  as_captcha_tmer=setTimeout(\"CaptchaResized()\",300);
}
var rz_cnt = 0;
function CaptchaResized() {
  as_captcha_tmer=null;
  CaptchaReinit();
}
function SendCaptchaChecking(obj) {
//  alert(typeof(obj));
  if(busyxml) return false;
  if(typeof(obj)!=\"string\") {
    captable = asGetObj('captchaTable');
    txy = getPosition(captable);
    params = \"sniper_capaction=coord&tx=\"+txy[0]+\"&ty=\"+txy[1];
    if(!as_resize_handled) {
      window.onresize = CaptchaResizing;
      as_resize_handled=true;
    }
  }
  else {
    params = \"sniper_capaction=donext&oid=\"+obj;
  }
  var xmlreq = NewXMLHttpRequest();
  if(!xmlreq) { return false; }
  xmlbusy=true;
  xmlreq.onreadystatechange= function() {
    if (xmlreq.readyState == 4) {
      var sresponse= xmlreq.responseText;
      delete xmlreq;
      xmlbusy = false;
      var spl = sresponse.split('|');
      if(spl.length<2) { alert(\"undefined server response: \"+sresponse); return false; }
      finished = spl[0]-0;
      if(spl[0]=='err') {
        alert('Captcha error!'); finished=200; return false;
      }
      var imgprogress= asGetObj('caprogress');
      imgprogress.style.width = spl[0]+'%';
      if(spl[0]=='100') {
        finished = (spl[1]==\"yes\")?500:0;
        MoveSight(-1,-1,0);\n";

  if($this->submitbutton_id !='') $ret.="        if(spl[1]==\"yes\") asGetObj(\"{$this->submitbutton_id}\").disabled=false;\n";
  if(!empty($this->jscodepassed)) $ret.="        if(spl[1]==\"yes\") { {$this->jscodepassed}  }\n";
  if(!empty($this->jscodefailed)) $ret.="        if(spl[1]==\"no\")  { {$this->jscodefailed}  }\n";
   $ret .="
      }
      else {
         nextx = spl[1]-0;
         nexty = spl[2]-0;
         MoveSight(nextx,nexty,1);
      }
    }
  }
  xmlreq.open(\"POST\",handlerurl,true);
  xmlreq.setRequestHeader(\"Content-Type\",postcont);
  xmlreq.send(params);
  return false;
}
function getPosition(oElement) {
  var ret = [0,0];
  while( oElement != null ) {
    ret[0] +=oElement.offsetLeft;
    ret[1] +=oElement.offsetTop;
    oElement = oElement.offsetParent;
  }
  return ret;
}
var cap_imgobj = 0;
var htimer = false;
var imgOpacity = -1;
var capimg_nextpos = [];
function MoveSight(to_x,to_y, slowly) {
  if(cap_imgobj==0) {
    cap_imgobj = asGetObj('cap_sight');
    cap_imgobj.style.display='';
  }
  if(to_x<0) cap_imgobj.style.display='none'; // clicking finish
  else {
    if(finished>0) {
      capimg_nextpos = [to_x,to_y];
      cap_imgobj.capacity = imgOpacity = 100;
      htimer = setInterval(\"CapFadeOutEvt()\",50);
    }
    else {
      cap_imgobj.style.top = to_y+\"px\";
      cap_imgobj.style.left = to_x+\"px\";
    }
  }
}
function CaptchOneShot(obj) {
  if(finished>=100) return false;
  var tagid = obj.getAttribute(\"id\");
  SendCaptchaChecking(tagid);
}

function CapFadeOutEvt() {
  cap_imgobj.opacity = imgOpacity = imgOpacity-20;
  if (document.all) cap_imgobj.style.filter = 'alpha(opacity=' + imgOpacity+')';
  if(imgOpacity<=10) {
    clearTimeout(htimer);
    cap_imgobj.style.left = capimg_nextpos[0]+'px';
    cap_imgobj.style.top = capimg_nextpos[1]+'px';
//    alert(cap_imgobj+' style.left= '+typeof(cap_imgobj.style.left)+' '+cap_imgobj.style.left+' '+cap_imgobj.style.top);
    htimer = setInterval(\"CapFadeInEvt()\",50);
  }
}

function CapFadeInEvt() {
  cap_imgobj.opacity = imgOpacity = imgOpacity+20;
  if (document.all) cap_imgobj.style.filter = 'alpha(opacity=' + imgOpacity+')';
  if(imgOpacity>=100) {
    clearTimeout(htimer);
  }
}
function setOpacity (imgid, step, delay) {
  if (document.all) img.style.filter = 'alpha(opacity = ' + img.opacity + ')';
}";
    if($autostart) $ret .="\nSendCaptchaChecking();\n";

    $ret .="//-->\n</script>\n";
    if($this->b_buffered) return $ret;
    echo $ret;
  } # DrawJsCode end

  /**
  * @desc handle AJAX call from client. Generates and sends next sight position
  */
  function HandleClientRequest() {
    $ret = '100';
    $this->idlist = isset($_SESSION['captcha_idlist'])? $_SESSION['captcha_idlist']: '';
    $this->x_len = isset($_SESSION['captcha_lenx'])? $_SESSION['captcha_lenx']: 0;
    $this->y_len = isset($_SESSION['captcha_leny'])? $_SESSION['captcha_leny']: 0;
    $this->codelen = isset($_SESSION['captcha_codelen'])? $_SESSION['captcha_codelen']: 0;
    $this->var_curpos = isset($_SESSION['captcha_curpos'])? $_SESSION['captcha_curpos']: 0;
    $this->prevcode = isset($_SESSION['captcha_prevcode'])? $_SESSION['captcha_prevcode']: -1;
    $this->startx = isset($_SESSION['captcha_startx'])?$_SESSION['captcha_startx']:0;
    $this->starty = isset($_SESSION['captcha_starty'])?$_SESSION['captcha_starty']:0;
    $this->cellsize = isset($_SESSION['captcha_cellsize'])?$_SESSION['captcha_cellsize']: array(10,10);
    $this->accumulated = isset($_SESSION['captcha_accumulated'])?$_SESSION['captcha_accumulated']:'xxx';
    $this->useranswer = isset($_SESSION['captcha_useranswer'])?$_SESSION['captcha_useranswer']:'xxx';

    if(empty($this->idlist) || empty($this->x_len) || empty($this->y_len)) { echo 'err'; exit; } # Wrong call. May be no session support

    if($_POST['sniper_capaction']==='coord') {# initial coords passed   tx=NNN ty=MMM
      $_SESSION['captcha_startx'] = $this->startx = isset($_POST['tx'])?$_POST['tx']:0;
      $_SESSION['captcha_starty'] = $this->starty = isset($_POST['ty'])?$_POST['ty']:0;
      $this->var_curpos = $_SESSION['captcha_curpos'] = 0;
      $this->accumulated = $_SESSION['captcha_accumulated']=$this->useranswer = $_SESSION['captcha_useranswer']='xxx';
    }
    if(!empty($_POST['oid'])) {
      $_SESSION['captcha_useranswer'] = $this->useranswer = $this->useranswer.'|'.$_POST['oid'];
    }
    $percent = intval(100*$this->var_curpos/$this->codelen); # progress bar width, NN%
    $ret = '';
    $this->var_curpos++;
    if($percent<100) {
      $nextcode = $this->prevcode;
      while($nextcode == $this->prevcode) $nextcode = intval(mt_rand(0,($this->x_len*$this->y_len)-1));
      $this->prevcode = $nextcode;
      $idarr = explode('|',$this->idlist);
      $this->accumulated .= '|'.$idarr[$nextcode+1];
      $row_y = floor($nextcode/$this->x_len);
      $row_x = fmod($nextcode,$this->x_len);
      $next_posx = 2 + $this->startx+($row_x*($this->cellsize[0]+3));
      $next_posy = 2 + $this->starty+($row_y*($this->cellsize[1]+3));
      $_SESSION['captcha_curpos'] = $this->var_curpos;
      $_SESSION['captcha_prevcode'] = $this->prevcode;
      $_SESSION['captcha_accumulated'] = $this->accumulated;
      $ret = "$percent|$next_posx|$next_posy";
    }
    else $ret = "$percent|".($this->useranswer===$this->accumulated ? 'yes':'no');
    echo $ret; #AJAX server response
    exit;

  } # HandleClientRequest() end

  /**
  * @desc CheckPassed compares code passed from client POST with SESSION saved.
  * @Return true if codes match.
  */
  function CheckPassed() {
    $this->accumulated = isset($_SESSION['captcha_accumulated'])?$_SESSION['captcha_accumulated']:'';
    $this->useranswer = isset($_SESSION['captcha_useranswer'])?$_SESSION['captcha_useranswer']:'';
    if(empty($this->accumulated)) return false;
    return ($this->accumulated===$this->useranswer);
  }
} # class definition End

if(!empty($_POST['sniper_capaction'])) {
  $captcha_handler = new CSniperCaptcha();
  $captcha_handler->HandleClientRequest();
}
?>

 
  Advertise on this site Advertise on this site   Site map Site map   Statistics Statistics   Site tips Site tips   Privacy policy Privacy policy   Contact Contact  

For more information send a message to :
info at phpclasses dot org.
Copyright (c) Icontem 1999-2009 PHP Classes - PHP Class Scripts
  PHP Book Reviews - Reviews of books and other products