un captcha avec sfCryptographPlugin

après avoir mis en place sfPropelActAsCommentableBehaviorPlugin, j’y ai ajouté quelques personnalisations

Intégration de FCK

j’ai réécrit le template _commentForm.php pour y mettre un éditeur « riche » : FCKeditor (il doit bien entendu être configuré au préalable dans le /apps/myapp/config/settings.yml) en modifiant

<?php echo textarea_tag('sf_comment', '', array('cols' => 40, 'rows' => 8)) ?>

en

<?php echo textarea_tag('sf_comment', '', 'tool=Basic rich=fck size=40x8 disabled=false')?>

J’ai ensuite stocké le fichier modifié au niveau de l’appli /apps/myapp/modules/sfComment/templates/_commentForm.php afin de ne pas toucher au code du plugin

FCK se sent obligé de mettre une ligne vide en valeur par défaut ce qui fait que la directive required ne suffit pas, puisque ligne vide n’est pas vide.
J’ai donc réécrit la validation en tant qu’anonyme en y ajoutant

sf_comment:
  required:
    msg:           The message is required
  # blank from FCK
  sfCallbackValidator:
    callback:      strip_tags
    invalid_error: The message is required

J’ai stocké le fichier modifié au niveau de l’appli /apps/myapp/modules/sfComment/validate/anonymousComment.yml

Liens en nofollow

Mettre un lien en nofollow fait que ce lien n’est pas suivi par les moteurs de recherche, ce qui évite la transmission du PR … y en a que ça énerve d’ailleurs le nofollow ;-)
Pour commencer par supprimer l’intérêt de laisser un lien dans un commenatire, je me suis fait une fonction noFollow() dans /lib/myTools.php, qui prend en entrée du code html et réécrit en sortie tous les liens avec l’attribut rel= »nofollow ».

class myTools
{
  public static function noFollow ($str) {
    $str = stripslashes($str);
    $preg = "/<a href=\"(.*)\">(.*?)<\/a>/U";
    preg_match_all($preg, $str, $match);
    if(count($match[1]))
    {
        foreach ($match[1] as $key=>$val)
        {
            $pattern[] = '/'.preg_quote($match[0][$key],'/').'/';
            $replace[] = "<a href=\"".$val."\" rel=\"nofollow\">".$match[2][$key]."</a>";
        }
        return preg_replace($pattern, $replace, $str);
    }
    else
    {
       return $str;
    }
  }
}

J’ai ensuite réécrit l’affichage des commentaires en changeant ce passage à la fin de _commentView.php

<?php
  echo __('<span>%1%</span>, <a href="#sf_comment_%2%">%3%</a>',
    array(
      '%1%' => myTools::noFollow($author),
      '%2%' => $comment['Id'],
      '%3%' => $date
    )
  )
?>
<div>
  <?php echo myTools::noFollow($comment['Text']); ?>
</div>

En stockant ensuite ce fichier au niveau de mon application /apps/myapp/modules/sfComment/templates/_commentView.yml

Après ça je n’ai toujours pas réglé réellement le problème du spam … les bots des spamers ayant une approche pas très fine, ils ne prendront pas la peine de vérifier si leurs liens sont bien suivables par les moteurs de recherche dans les commentaires qu’ils ont laissés … en revanche ils vont repasser à intervalles réguliers ce qui est très désagréable!!

formulaire javascript

J’ai donc testé une des solutions js proposées sur cette page en remplacant les balise de formulaires dans /apps/myapp/modules/sfComment/templates/_commentForm.php par

...
<script language="JavaScript" type="text/javascript">
    document.write('<?echo form_tag('sfComment/'.$action, $options);?>');
</script>
...
<script language="JavaScript" type="text/javascript">
    document.write('</form>');
</script>
...

Naïf et rapide mais pas suffisant :-/

Captcha

Pour régler définitivement le problème j’ai mis en place sfCryptographpPlugin.
Comme la doc laisse un peu à désirer, voici une version traduite et adaptée de Howto do a Captcha in Symfony

installation

symfony plugin-install http://plugins.symfony-project.com/sfCaptchaPlugin

activer le module dans le settings.yml de l’application

all:
  .settings:
    enabled_modules: [default, sfCaptcha]

Personnellement je n’avais ni jpgraph_antispam-digits.class.php, ni jpgraph.class.php dans le répertoire lib/ du plugin je l’ai donc téléchargé ici https://trac.anl.gov/scavenger/browser/trunk/web/jpgraph/src/jpgraph_antispam-digits.php … en le sauvant dans lib/jpgraph_antispam-digits.class.php du plugin et changé:

require_once 'jpgraph_antispam.class.php';

en

require_once 'jpgraph_antispam-digits.class.php'

L’idée c’est que dans l’action qui doit afficher le captcha on le sauve (le captcha) dans une session pour ensuite l’afficher dans le tempate. J’ai donc ajouté le code suivant dans les actions qui affichent des posts de blog ou des pages. Vu que le captacha est sauvé session il sera forcément le même pour tous les posts lors d’un affichage par liste :-/

$g = new Captcha();
$this->getUser()->setAttribute('captcha', $g->generate());
<span style="font-family: verdana;">...</span>

il suffit maintenant d’afficher le captcha dans le template d’affichage de formulaire de commentaires que nous avons déjà modifié tout à l’heure, en ajoutant

<div class="required">
  <img src="<?php echo url_for('sfCaptcha/index'); ?>" alt="captcha" />
  &nbsp; &nbsp; &nbsp;
  <?php echo form_error('captcha'); ?>
  <?php echo input_tag('captcha',''); ?>
</div>

Il reste à modifier le validateur anonymousComment.yml en ajoutant le contrôle du captcha

captcha:
  required:
    msg: Please enter the numbers in the captcha image
  captchaValidator:
    error: Incorrect code

reste à effacer le cache du projet

symfony cc

et le captcha devrait fonctionner

Au passage un petit tips qui sert bien quand on joue avec les plugins dans symfony : How to fix a manually deleted plugin directory

  • del.icio.us
  • Twitter
  • Facebook
  • Tumblr
  • FriendFeed
  • LinkedIn
  • MySpace
  • StumbleUpon
  • Digg
  • Google Bookmarks
  • MSN Reporter
  • Netvibes
  • Ping.fm
  • Wikio FR
  • Reddit
  • Scoopeo
  • Slashdot
  • email
  • PDF
  • Print

poster un commentaire

votre email ne sera jamais publié ou communiqué. les champs obligatoires sont marqués par une *

*
*