<?php
/******************************************************************
Copyright (C) 2010 Andre Campos Rodovalho. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
******************************************************************/
/**
* This class is intended to block the action of spam bots or robots (as Captcha), employing inteligent
* tactics on human detection
*
* @autor Andre Campos Rodovalho - hide@address.com
* @date 02-08-10
* @update 05-11-10
* @version 3.5
* @copyright Copyright (C) 2010 Andre Campos Rodovalho. All rights reserved.
* @license GNU/LGPL, see COPYING.LESSER
*/
class AntiBot{
var $coresString = array( 0=>'red', 1=>'yellow', 2=>'pink', 3=>'green', 4=>'brown',
5=>'orange', 6=>'blue', 7=>'gray' );
var $coresHexa = array( 0=>'#FF0000', 1=>'#E0E000', 2=>'#FF00FF', 3=>'#339900', 4=>'#934900',
5=>'#FB9600', 6=>'#0000FF', 7=>'#999999' );
var $numerosString = array( 0=>'zero', 1=>'one', 2=>'two', 3=>'three', 4=>'four', 5=>'five',
6=>'six', 7=>'seven', 8=>'eight', 9=>'nine' );
/**
* Creates an instance of the class and when requested outputs an new question
* @param boolean $iniciarCharada Flag to output question
* @param boolean $charadasRandomicas Flag to make questions randomly
* @param int $charadaChamar When $charadasRandomicas is false, calls the corresponding method
*/
function AntiBot($iniciarCharada=true,$charadasRandomicas=true,$charadaChamar=0){
@session_start();
if( $charadasRandomicas )
$charadaChamar = rand(0,3);
if( $iniciarCharada ){
switch( $charadaChamar ){
case 0: echo $this->montaCharadaConta(); break;
case 1: echo $this->montaCharadaContaLetra(); break;
case 2: echo $this->montaCharadaCoresLetras(); break;
case 3: echo $this->montaCharadaInverteTira(); break;
}
}
}
/**
* Generates and random arithmetic question
* @param string $guardarReposta Flag to store or not the answer generated
* @return string $pergunta
*/
function montaCharadaConta($guardarReposta=true){
$operacoesString = array(0=>'plus',1=>'minus',2=>'fold');
$indiceNumero1 = rand(0,9);
$indiceNumero2 = rand(0,9);
$indiceOperacao = rand(0,2);
$resposta = 0;
switch($indiceOperacao){
case 0: $resposta = $indiceNumero1 + $indiceNumero2; break;
case 1: $resposta = $indiceNumero1 - $indiceNumero2; break;
case 2: $resposta = $indiceNumero1 * $indiceNumero2; break;
}
if( $guardarReposta ) $this->guardaResposta($resposta);
$variavel = 'sujeira'.rand(0,2);
$$variavel = $this->montaSujeira();
$pergunta = 'Which integer ('.$sujeira2.'considering the signal)
results'.$sujeira0.' from operation "'.
$this->numerosString[$indiceNumero1].' '.$operacoesString[$indiceOperacao].' '.
$this->numerosString[$indiceNumero2].'" ?'.$sujeira1;
if( $guardarReposta ) { // evita chamadas recursivas
$posicao = 'pos'.rand(0,1);
$$posicao = '<span><div style="display:none">'.$this->montaCharadaContaLetra(false).
'</div></span>';
}
return $pos1.'<span><div style="display:none">'.time().'</div>'.$pergunta.'</span>'.$pos0;
}
/**
* Stores answer on a SESSION
* @param string $resposta Answer to be stored
* @return void
*/
function guardaResposta($resposta){
$_SESSION['resposta'] = $resposta;
}
/**
* Checks if sent answer and the stored answer matches
* @param string $resposta Sent answer (user input)
* @return boolean
*/
function verificaResposta($resposta){
if( ($_SESSION['resposta'] == $resposta) && !empty($_SESSION['resposta']) ) return true;
else{ $_SESSION['resposta'] = ''; return false; };
}
/**
* Generates an random question to count how many times an character occurs on a string
* @param string $guardarReposta Flag to store or not the answer generated
* @return string $pergunta
*/
function montaCharadaContaLetra($guardarReposta=true){
$tamanho_palavra = 9;
$palavra = $this->geraPalavra($tamanho_palavra);
$indiceSorteado = rand(1,$tamanho_palavra);
$caracterSorteado = substr( $palavra, $indiceSorteado, 1 );
$resposta = substr_count( $palavra, $caracterSorteado );
if( $guardarReposta ) $this->guardaResposta($resposta);
$variavel = 'sujeira'.rand(0,2);
$$variavel = $this->montaSujeira();
$pergunta = 'How many times '.$sujeira0.'(integer value) the character '.$sujeira1.'"'.
$caracterSorteado.'" occurs on: '.$sujeira2.'<b>'.$palavra.'</b> ?';
if( $guardarReposta ) {
$posicao = 'pos'.rand(0,1);
$$posicao = '<span><div style="display:none;">'.$this->montaCharadaConta(false).
'</div></span>';
}
return $pos1.'<span><div style="display:none;">'.time().'</div>'.$pergunta.'</span>'.$pos0;
}
/**
* Generates an word (main)
* @param int $tamanho_palavra Desired lenght
* @return string $palavra
*/
function geraPalavra($tamanho_palavra=5){
$vogais = array('a','e','i','o','u');
$consoantes = array('b','c','d','f','g','h','nh','lh','ch','j','k','l','m','n','p','qu',
'r','rr','s','ss','t','v','w','x','y','z');
$palavra = '';
$contar_silabas = 0;
while($contar_silabas < $tamanho_palavra){
$vogal = $vogais[rand(0,count($vogais)-1)];
$consoante = $consoantes[rand(0,count($consoantes)-1)];
$silaba = $consoante.$vogal;
$palavra .=$silaba;
$contar_silabas++;
unset($vogal,$consoante,$silaba);
}
return $palavra;
}
/**
* Generates an random html to "muddy" the question, and probably cheat bots
* @return string $sujeira
*/
function montaSujeira(){
$abreTag = array('<p style="display:none">','<span style="display:none">',
'<tt style="display:none">','<font style="display:none">',
'<div style="display:none">','<cite style="display:none">');
$fechaTag = array('</p>','</span>','</tt>','</font>','</div>','</cite>');
$indiceTags = rand(0,5);
if( rand(0,1) )
$sujeira = time();
else
$sujeira = $this->geraPalavra( rand(4,11) );
$sujeira = $abreTag[$indiceTags].$sujeira.$fechaTag[$indiceTags];
if( rand(0,1) ) $sujeira = str_replace('">', ';">', $sujeira);
if( rand(0,1) ) $sujeira = str_replace('none', ' none', $sujeira);
return $sujeira;
}
/**
* Generates an question to type the chars with an specific color from a string
* @param string $guardarReposta Flag to store or not the answer generated
* @return string $pergunta
*/
function montaCharadaCoresLetras($guardarReposta=true){
$str = array();
$tamanho = 15;
$numeroDeColoridas = rand(1,5); //reposta
$resposta = array();
$indiceDaCor = rand(0,7); //sorteada
$outrasCores = array();
while(1){ //sorteia tres diferentes cores
if( sizeof($outrasCores) > 2 )
break;
else{
$indice = rand(0,7);
if( $indice != $indiceDaCor )
$outrasCores[] = $this->coresHexa[$indice];
}
}
$verbete = $this->geraVerbete($tamanho);
$verbete = str_split($verbete);
$y = 0; // contador de quantas letras foram com a cor sorteada
for( $i = 0; $i<$tamanho; $i++ ) { //loop que constroi um array "miolo" de charada
$letra = $verbete[$i];
// verifica se deve colocar cor sorteada
if( ($y < $numeroDeColoridas) && ($numeroDeColoridas != 0) ){
$cor = $this->coresHexa[$indiceDaCor];
$resposta[$letra.$i] = $letra;
$y++;
}else{ // sortea cor sujeira
$indice = rand(0,2);
$cor = $outrasCores[$indice];
}
$str[$letra.$i] = '<font color="'.$cor.'">'.$letra.'</font> ';
}
ksort($resposta);
ksort($str);
$str = implode($str);
$resposta = implode($resposta);
if( $guardarReposta ) $this->guardaResposta($resposta);
$variavel = 'sujeira'.rand(0,2);
$$variavel = $this->montaSujeira();
$pergunta = 'Type characters on '.$this->coresString[$indiceDaCor].
', considering the case, present'.$sujeira0.
' on <br />( <strong>'.$str.$sujeira2.'</strong> )'.$sujeira1;
if( $guardarReposta ) {
$posicao = 'pos'.rand(0,1);
$$posicao = '<span><div style="display: none">'.$this->montaCharadaInverteTira(false).
'</div></span>';
}
return $pos1.'<span><div style="display: none">'.time().'</div>'.$pergunta.'</span>'.$pos0;
}
/**
* Generates an entry (main)
* @param int $tamanho Desired lenght
* @return string $verbete
*/
function geraVerbete($tamanho=5){
$verbete = '';
srand( (double)microtime()*1000000 );
$data = "AbcDE123IJKLMN67QRSTUVWXYZ";
$data .= "aBCdefghijklmn123opq45rs67tuv89wxyz";
$data .= "FGH45P89";
for( $i = 0; $i<$tamanho; $i++ ) {
$verbete .= substr($data, (rand()%(strlen($data))), 1);
}
return $verbete;
}
/**
* Generates an question to type chars without an determined number, inverting or not
* @return string $pergunta
*/
function montaCharadaInverteTira($guardarReposta=true){
$caracteres = $this->geraVerbete(5);
$caracteres = str_split($caracteres);
$retirarEste = 0;
foreach($caracteres as $char){ // acha um numero na str para retirar
$char = $char *= 1; // converte pra int
if( $char != 0 ){
$retirarEste = $char;
break;
}
}
if( $retirarEste == 0 ){ // se nao tiver numeros, faz um
$retirarEste = rand(1,9); // nao coloco zero
$caracteres[] = $retirarEste;
}
$caracteres = implode($caracteres);
$resposta = str_replace($retirarEste,'',$caracteres);
if( rand(0,1) ) {
$resposta = strrev( $resposta );
$inverter = '<strong>invert</strong> all string and';
}
if( $guardarReposta ) $this->guardaResposta($resposta);
$variavel = 'sujeira'.rand(0,2);
$$variavel = $this->montaSujeira();
$pergunta = 'Given <font color="'.$this->coresHexa[rand(0,7)].'">'.
$caracteres.'</font> '.$inverter.' ignore'.$sujeira1.' the number
<strong>'.$this->numerosString[$retirarEste].'</strong>'.$sujeira0.
' - to answer, consider the'.$sujeira2.' case';
if( $guardarReposta ) {
$posicao = 'pos'.rand(0,1);
$$posicao = '<span><div style="display: none;">'.$this->montaCharadaCoresLetras(false).
'</div></span>';
}
return $pos1.'<span><div style="display: none;">'.time().'</div>'.$pergunta.'</span>'.$pos0;
}
}