Cette classe étends la classe de base, et s'utilise pareillement, mais elle ajoute un captcha simplissime qui consiste seulement à demander à l'utilisateur d'écrire un chiffre entre zéro et neuf, en chiffre. L'astuce étant que l'on demande de recopier un chiffre mais on l'écrit en lettre, ça bluffe les robots simplistes de nos amis chinois ou russes (ou même anglais) qui ne comprennent pas forcément la langue de Molière.
<?php
/*
* formlaire pour poster des commentaires
* contient : nom mail url et message
* etend formclass.php
* ajoute un captcha simpliste :
* "Ecrivez le chiffre 'cinq' ... en chiffre :"
* ajouter une fonction antiflood dans la validation
*/
class comment extends form {
private $captcha = array('z�ro', 'un', 'deux', 'trois', 'quatre', 'cinq', 'six', 'sept', 'huit', 'neuf');
// protection anti flood : ne pas poster plus de X messages par minute
protected $last_post;
protected $first_post;
protected $nb_posts;
function __construct($cond = null) {
// liste des champs necessaires - sauf token non crypte
//$this->fields = array('nom', 'url', 'email', 'texto');
$this->fields['nom'] = array('type'=>'text', 'name'=>'nom', 'size'=>18, 'maxlength'=>20, 'value'=>'', 'label'=>array('txt'=>'Nom : '));
$this->fields['email'] = array('type'=>'text', 'name'=>'email', 'size'=>22, 'maxlength'=>40, 'value'=>'', 'label'=>array('txt'=>'Email : '));
$this->fields['url'] = array('type'=>'text', 'name'=>'url', 'size'=>25, 'maxlength'=>50, 'value'=>'http://', 'label'=>array('txt'=>'URL : '));
$this->fields['texto'] = array('type'=>'textarea', 'name'=>'texto', 'cols'=>60, 'rows'=>4, 'wrap'=>'virtual', 'value'=>'');
$this->fields['submit'] = array('type'=>'submit', 'name'=>'Submit', 'value'=>'Envoyer',
'label'=>array('txt'=>'Nom et message obligatoires.'));
$this->fields['question'] = array('type'=>'text', 'size'=>2, 'name'=>'question');
$this->fields['answer'] = array('type'=>'hidden', 'name'=>'answer');
parent::__construct($cond);
}
function getForm() {
$date = get_date();
$now = time();
$token = sha1(self::SALT.$now.self::SALT);
$signed = $now.'#'.$token;
// demander la question piege et ajouter la reponse
$answer = rand(0,9);
$this->fields['question']['label']['txt'] = 'Ecrivez le chiffre '. $this->captcha[$answer] . ' en chiffre :';
$this->fields['answer']['value'] = $this->captcha[$answer];
// crypter les noms des champs
$fld = array();
foreach($this->fields as $key => $value) {
$this->names[$key] = form::crypt($key, $token);
$value['name'] = $this->names[$key];
$fld[$key] = parent::getField($value);
}
return <<
$date
{$fld['nom']}
{$fld['email']}
{$fld['url']}
{$fld['texto']}
{$fld['question']}
{$fld['submit']}
{$fld['answer']}
{$fld['message']}
MYFORM;
}
public function validateForm() {
if (parent::validateForm()) {
// tester la bonne r�ponse au captcha
if(!is_numeric($this->values['question']))
{
$this->valide = false;
$this->err = 'Question = "'.$this->values['question'] . '" pas num�rique';
}
else if (!isset($this->captcha[$this->values['question']]))
{
$this->valide = false;
$this->err = 'Question = "'.$this->values['question'] . '" hors champs';
}
else if ($this->values['answer'] != $this->captcha[$this->values['question']])
{
$this->valide = false;
$this->err = 'Question = "'.$this->values['answer'] . '" Reponse="' . $this->values['question'] .'"';
}
else
{
// formulaire valide
$this->last_post = request('last_post', 'int', 'session');
$this->first_post = request('first_post', 'int', 'session',0);
$this->nb_posts = request('nb_posts', 'uint', 'session',0);
// MAJ des infos antiflood en session
$_SESSION['last_post'] = time();
if(isset($_SESSION['nb_posts']))
$_SESSION['nb_posts'] ++;
else
{
$_SESSION['nb_posts'] = 1;
$_SESSION['first_post'] = time(); // heure du 1er post
}
}
}
return $this->valide;
}
// fonction anti-flood : enregistrer en session les temps et nb de $_POST � chaque validation de formulaire
function antiflood() {
// protection anti flood : ne pas poster plus de X messages par minute
$duree = time() - $this->last_post;
$dureeh = time_elapsed($duree);
if($this->last_post && $duree < 30) {
$this->err = "Anti-spam : moins d'un message par 30 secondes svp ($duree = $dureeh).";
return true;
}
if ($this->nb_posts > 20) {
$duree = time() - $this->first_post;
if ($this->first_post && $duree < 3600) {
$this->err = "Anti-spam : moins de 20 messages par heure svp !! ($nb_posts, $duree, $dureeh)";
return true;
}
}
return false;
}
}