Vale. Reconozco que muy normal no tiene que ser. He escrito una clase para PHP que muestra al usuario una especie de "CAPTCHA", cuya principal característica es que no se vale de imágenes, con los beneficios que esto conlleva. Ahora bien, este mismo hecho hace que el "CAPTCHA" en cuestión pueda ser "saltado" por alguien que se proponga hacerlo... no es que se lo dejemos tirado, pero, si le pone un poco de interés lo logrará.

Pero yo no quería hablar exactamente de esta clase, esto es, iba a preparar una especie de "tutorial" sobre cómo llevar a cabo algo así, explicando método por método la clase de marras, en fin, algo chulo, algo útil, pero, mira tú por dónde, será el calor o qué sé yo lo que será, que, al final, hablo del asunto en cuestión, de acuerdo, pero, voy a presentar la última majadería que se me ha ocurrido, mientras daba vueltas al asunto de la preparación de esta entrada.

Antes de presentar el código fuente de la clase "Captcha", mejor dicho, de la clase "C"... recalco lo de arriba, y es que, aunque funciona (abajo se incluye un ejemplo de uso), no es que se trate de un "CAPTCHA" muy seguro, que digamos. intenta confundir, utiliza alguna que otra triquiñuela, pide al usuario que resuelva una suma, cuyos operandos le serán presentados "en letra", o en números romanos... pero, después de todo, ya digo, si alguien quiere saltárselo, se lo saltará.

Sea como sea, aquí el código fuente de la clase "C", te pido disculpas de antemano, y verás porqué:

class C{
  const H='ch';
  const R='cr';
  const S='cs';
  public static function V(){
    $r=$_REQUEST;
    if(isset($r[self::H]) 
     && isset($r[self::R])){
       return ($r[self::H]== 
        self::H($r[self::R]));
    }else{
      return false;  
    }
  }
  public static function S(){
    $o=self::O();
    echo'
    <input type="hidden" name="'.self::H.'" id="'.self::H.'" value="'.$o[self::H].'" />    
    <input type="text" name="'.self::R.'" id="'.self::R.'" /> '.$o[self::S];
  }
  private static function O(){
    $a=rand(1,9); 
    $b=rand(1,9);
    $c=self::R($a);
    $d=self::R($b);
    $s=sprintf('%s + %s',$c,$d);
    $h=self::H($a+$b);
    return array(
      self::H=>$h,
      self::S=>$s
    );
  }
  private static function R($n){
    switch(rand(0,1)){
      case 0:$r=array(
          1=>'I',2=>'II',3=>'III', 
          4=>'IV',5=>'V',6=>'VI', 
          7=>'VII',8=>'VIII',9=>'IX');
        $r=$r[$n]; 
        break;      	
      case 1:$l=array(
          1=>'One',2=>'Two',3=>'Three', 
          4=>'Four',5=>'Five',6=>'Six', 
          7=>'Seven',8=>'Eight',9=>'Nine');
        $r=$l[$n];
        break;        
    }
    return$r;
  }
  private static function H($r){
    return substr(md5($r),10,4);
  }  
}

Y, como lo prometido es deuda, aquí el código que sirve como ejemplo de uso de la clase "C":

<?php
require('c.class.php');
if(isset($_POST['submit'])){
  if(C::V()){
    echo'Valid CAPTCHA';  
  }else{
    echo'Invalid CAPTCHA';      
  }  
}
?>
<form action="./index.php" method="post">
  <div><?php C::S()?></div>
  <div><input name="submit" type="submit" /></div>
</form>

Supongo que estarás pensando algo así como "Pues vaya gilipollez"... y, mira tú por dónde, estoy de acuerdo contigo. Pero, bueno, al menos deja que te diga que yo no tengo la culpa, que no, que no, que no soy culpable, señor juez, que es el calor, ¡este maldito calor! Debería servir como atenuante este calor, para lo que sea. Ah, y no te molestes en probar la clase "C", que, ya te digo yo que funciona como se espera.

En todo caso, desde aquí puedes descargar la clase "C" y el ejemplo de uso. Chico, estoy pensando en vender la moto con algo como "El CAPTCHA más pequeño jamás desarrollado", "El CAPTCHA de sólo 60 líneas, ¡sin comprimir!", "El CAPTCHA..."... pero esto se lo dejaré a mi equipo de marquetín, que lo estudie bien, que yo ya he hecho bastante con lo que he hecho. ¿No te parece?