Geekeries et d'autres choses - Mot-clé - captcha2024-01-29T10:26:26+01:00urn:md5:51ff50324f4f72c0e78683659647f2c8DotclearMise à jour du plugin Accessible Captcha pour Dotclear 2.2urn:md5:ffccd3881eaabe32a5de04ff6d4070862011-05-09T09:03:00+02:002011-05-09T08:28:22+02:00Julien WajsbergInformatiqueaccessiblecaptchadotclearmysqlpostgresql<p>J'ai mis à jour mon <a href="http://www.everlong.org/blog/index.php/post/2009/11/Plug-in-captcha-accessible-pour-Dotclear-2" hreflang="fr" title="Plug-in captcha accessible pour Dotclear 2">plugin captcha accessible</a> pour Dotclear 2.2.</p>
<p>Une seule modification : il supporte à présent MySQL !</p>
<p>En effet, dans la version 1.0, je n'avais testé que sur mon installation avec PostgreSQL, et, pour supprimer les anciennes références de captchas affichés, j'utilisais une syntaxe SQL propre à PostgreSQL (et, en tout cas, incompatible avec MySQL) pour faire une opération d'ajout d'intervalle de temps.</p> <p>Une petite explication ? Ok, mais c'est bien parce que vous insistez.</p>
<p>J'utilisais le code PHP suivant :</p>
<pre class="php php" style="font-family:inherit"><span style="color: #666666; font-style: italic;">// suppression du captcha</span>
<span style="color: #000088;">$query</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'delete from '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$core</span><span style="color: #339933;">-></span><span style="color: #004000;">prefix</span> <span style="color: #339933;">.</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$table_hash</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">" where hash = '"</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$con</span><span style="color: #339933;">-></span><span style="color: #004000;">escape</span><span style="color: #009900;">(</span><span style="color: #000088;">$hash</span><span style="color: #009900;">)</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">"'"</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// et on en profite pour enlever les anciens</span>
<span style="color: #000088;">$current_datetime</span> <span style="color: #339933;">=</span> <span style="color: #990000;">date</span><span style="color: #009900;">(</span><span style="color: #0000ff;">'Y-m-d H:i:s'</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$query</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">" or timestamp + interval '"</span> <span style="color: #339933;">.</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$hash_ttl_min</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">" min' < '"</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$con</span><span style="color: #339933;">-></span><span style="color: #004000;">escape</span><span style="color: #009900;">(</span><span style="color: #000088;">$current_datetime</span><span style="color: #009900;">)</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">"'"</span><span style="color: #339933;">;</span></pre>
<p><code>$hash</code> contient le hash qui correspond à la référence du captcha à supprimer, <code>self::$table_hash</code> contient le nom de la table, <code>$core->prefix</code> est un DCism qui retourne le préfixe des tables Dotclear, <code>$con->escape</code> est un autre DCism qui permet d'avoir des données sécurisées, et enfin <code>self::$hash_ttl_min</code> est le temps en minutes avant l'expiration d'un captcha.</p>
<p>Ça génère une requête SQL qui ressemble à ça :</p>
<pre class="sql sql" style="font-family:inherit"><span style="color: #993333; font-weight: bold;">DELETE</span> <span style="color: #993333; font-weight: bold;">FROM</span> dc_captcha_hash <span style="color: #993333; font-weight: bold;">WHERE</span> hash <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'XXX'</span> <span style="color: #993333; font-weight: bold;">OR</span> timestamp <span style="color: #66cc66;">+</span> interval <span style="color: #ff0000;">'60 min'</span> <span style="color: #66cc66;"><</span> <span style="color: #ff0000;">'2011-05-09 09:14:14'</span></pre>
<p>Ce qui marche pas dans MySQL, c'est la partie <code>timestamp + interval '60 min'</code>.</p>
<p>Dans MySQL, il faudrait la requête suivante :</p>
<pre class="sql sql" style="font-family:inherit"><span style="color: #993333; font-weight: bold;">DELETE</span> <span style="color: #993333; font-weight: bold;">FROM</span> dc_captcha_hash <span style="color: #993333; font-weight: bold;">WHERE</span> hash <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'XXX'</span> <span style="color: #993333; font-weight: bold;">OR</span> timestamp <span style="color: #66cc66;">+</span> interval <span style="color: #cc66cc;">60</span> minute <span style="color: #66cc66;"><</span> <span style="color: #ff0000;">'2011-05-09 09:14:14'</span></pre>
<p>On remarque : l'intervalle n'est pas mis dans une chaîne de caractères, et on utilise <code>minute</code> au lieu de <code>min</code>.</p>
<p>Comme je n'avais pas envie de faire un gros @@if@ qui tâche pour créer une requête ou l'autre, j'ai décidé de refaire le calcul en PHP. À partir de PHP 5.3, il y a la <a href="http://fr.php.net/manual/fr/class.datetime.php" hreflang="fr">classe DateTime</a> très pratique pour faire ce genre de choses, mais je voulais être compatible avec les versions plus vieilles<sup>[<a href="https://everlong.org/blog/index.php/post/2011/05/Mise-%C3%A0-jour-du-plugin-Accessible-Captcha-pour-Dotclear-2.2#pnote-428-1" id="rev-pnote-428-1">1</a>]</sup>. J'y suis donc allé à l'ancienne !</p>
<pre class="php php" style="font-family:inherit"><span style="color: #666666; font-style: italic;">// suppression du captcha</span>
<span style="color: #000088;">$query</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'delete from '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$core</span><span style="color: #339933;">-></span><span style="color: #004000;">prefix</span> <span style="color: #339933;">.</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$table_hash</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">" where hash = '"</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$con</span><span style="color: #339933;">-></span><span style="color: #004000;">escape</span><span style="color: #009900;">(</span><span style="color: #000088;">$hash</span><span style="color: #009900;">)</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">"'"</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// et on en profite pour enlever les anciens</span>
<span style="color: #000088;">$expired_timestamp</span> <span style="color: #339933;">=</span> <span style="color: #990000;">gmmktime</span><span style="color: #009900;">(</span><span style="color: #990000;">gmdate</span><span style="color: #009900;">(</span><span style="color: #0000ff;">'H'</span><span style="color: #009900;">)</span><span style="color: #339933;">,</span> <span style="color: #990000;">gmdate</span><span style="color: #009900;">(</span><span style="color: #0000ff;">'i'</span><span style="color: #009900;">)</span> <span style="color: #339933;">-</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$hash_ttl_min</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$expired_datetime</span> <span style="color: #339933;">=</span> <span style="color: #990000;">gmdate</span><span style="color: #009900;">(</span><span style="color: #0000ff;">'Y-m-d H:i:s'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$expired_timestamp</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$query</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">" or timestamp < '"</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$con</span><span style="color: #339933;">-></span><span style="color: #004000;">escape</span><span style="color: #009900;">(</span><span style="color: #000088;">$expired_datetime</span><span style="color: #009900;">)</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">"'"</span><span style="color: #339933;">;</span></pre>
<p>C'est beau comme du PHP un lundi matin.</p>
<div class="footnotes"><h4>Notes</h4>
<p>[<a href="https://everlong.org/blog/index.php/post/2011/05/Mise-%C3%A0-jour-du-plugin-Accessible-Captcha-pour-Dotclear-2.2#rev-pnote-428-1" id="pnote-428-1">1</a>] car tout simplement mon blog tourne sur une version plus vieille.</p></div>
Plug-in captcha accessible pour Dotclear 2urn:md5:3b0515fca8772971269538d44412fc382009-11-22T22:40:00+01:002011-05-09T17:53:15+02:00Julien WajsbergInformatiqueaccessibleaccessibleCaptchacaptchadotclearmercurialplug-in <p><strong>Mise à jour</strong>: La version 1.1 est sortie pour supporter MySQL. Voir plus bas !</p>
<p>Ça fait quelques semaines que je travaille sur un plug-in captcha accessible pour Dotclear 2. Ce plugin
existait pour Dotclear 1 et je l'utilisais, et donc il m'a manqué lorsque je suis
passé sous Dotclear 2<sup>[<a href="https://everlong.org/blog/index.php/post/2009/11/Plug-in-captcha-accessible-pour-Dotclear-2#pnote-397-1" id="rev-pnote-397-1">1</a>]</sup>.</p>
<h3>C'est quoi, un captcha ?</h3>
<p>Un captcha, c'est un mécanisme qui permet de s'assurer que ce qui interagit avec le programme est bien un être humain. Pour cela, plusieurs techniques sont utilisables. Vous avez sans doute déjà rencontré ces images avec du texte tordu à l'intérieur, qu'il faut recopier dans une case, pour prouver qu'on n'est pas une machine.</p>
<h3>Pourquoi un captcha accessible ?</h3>
<p>Je ne sais pas pour vous, mais moi, les images avec du texte tordu, ça me saoule : non seulement <a href="http://caca.zoy.org/wiki/PWNtcha" hreflang="en">ce n'est pas complètement efficace</a>, mais en plus je n'y arrive pas toujours du premier coup ! À force de vouloir les faire inviolables, ils en deviennent inviolables même pour des vrais humains !</p>
<p>Et ne parlons même pas des personnes qui ont vraiment des problèmes handicapants.</p>
<p>Un captcha accessible devra montrer que l'être qui commente sur un billet est bien un être humain, et ce de manière moins agressive que les captchas graphiques.</p>
<h3>C'est quoi le principe ?</h3>
<p>Le principe est simple : lorsque quelqu'un veut poser un commentaire,
il doit aussi répondre à une question simple, du genre "combien font
deux et deux ?". Si il n'y répond pas ou s'il répond à côté, le
message est marqué comme "indésirable". Dans le cas idéal, il faudrait que, lorsqu'on répond mal, le plug-in propose de répondre à nouveau, jusqu'à un certain nombre d'échecs (2 ou 3 ?), mais ce n'est pas fait pour le moment.</p>
<p>De fait, lorsque j'utilisais ce plug-in dans le passé, je n'ai
jamais eu de problème de spam, alors que j'en ai aujourd'hui avec Dotclear 2 et ses
plugins de spam par défaut.</p>
<h3>Comment ça marche ? Un peu de technique</h3>
<p>On stocke la liste des questions en base de données. J'en suis à
construire la gui pour cela en m'inspirant du filtre des bad words.
Dans la base, on a aussi une table de correspondance entre un hash,
créé lorsque le formulaire de commentaires est affiché, et la question
posée. Cela évite le rejeu (genre si on fait qu'un hash de la
question, il suffit de donner le hash avec la réponse qui va bien, et
voilà, l'antispam est contourné), et permet de vérifier néanmoins que
la réponse est correcte.</p>
<h3>Une version 1.0</h3>
<p>Je me dis qu'il y a encore beaucoup de choses à faire, mais voici néanmoins une version 1.0 (voir les fichiers attachés).</p>
<p>Voici les fonctionnalités implementées :</p>
<ul>
<li>Gestion des questions/réponses depuis l'interface d'admin</li>
<li>Installation automatique de la base de données et d'une question par défaut</li>
<li>Purge des sessions stockées en base</li>
<li>Traduction française et anglaise</li>
</ul>
<p>Ce qu'il me reste à faire avant d'être pleinement satisfait :</p>
<ul>
<li>faire une passe sur l'architecture, peut-être repenser les objets existants</li>
<li>renommer certaines classes pour coller aux conventions Dotclear</li>
<li>implémenter la possibilité de se tromper une ou deux fois</li>
<li>peut-être implémenter l'install dans mon objet AccessibleCaptcha, qui serait juste appelé dans _install.php.</li>
</ul>
<h3>Version 1.1</h3>
<p>La version 1.1 est sortie le 9 mai 2011. Son seul changement est que le calcul des dates est maintenant fait en PHP, et pas en SQL, ce qui permet d'être compatible à la fois avec MySQL et PostgreSQL. La version 1.0 n'était pas compatible MySQL.</p>
<h3>Gestionnaire de versions</h3>
<p>J'en ai profité pour essayer <a href="http://mercurial.selenic.com/" hreflang="en">mercurial</a>, donc <a href="http://bitbucket.org/julienw/dotclear-accessible-captcha/" hreflang="en">j'ai créé un repo sur bitbucket</a> :</p>
<ul>
<li><a href="http://bitbucket.org/julienw/dotclear-accessible-captcha/" hreflang="en">http://bitbucket.org/julienw/dotclear-accessible-captcha/</a></li>
</ul>
<h3>Page sur DotAddict</h3>
<ul>
<li><a href="http://plugins.dotaddict.org/dc2/details/accessibleCaptcha" hreflang="fr">Accessible Captcha sur DotAddict</a></li>
</ul>
<h3>Pages sur le wiki de Dotclear Lab (obsolète)</h3>
<ul>
<li><a href="http://lab.dotclear.org/wiki/plugin/accessibleCaptcha/fr" hreflang="fr">en français</a></li>
<li><a href="http://lab.dotclear.org/wiki/plugin/accessibleCaptcha" hreflang="en">en anglais</a></li>
</ul>
<h3>Mes références</h3>
<ul>
<li><a href="http://mudry.org/blog/post/2006/12/31/342-traduction-d-un-plugin-dotclear2" hreflang="fr">Un billet sur la traduction des plug-ins</a></li>
<li><a href="http://fr.dotclear.org/documentation/2.0/resources/plugins" hreflang="fr">La doc de réalisation de plug-ins</a></li>
</ul>
<div class="footnotes"><h4>Notes</h4>
<p>[<a href="https://everlong.org/blog/index.php/post/2009/11/Plug-in-captcha-accessible-pour-Dotclear-2#rev-pnote-397-1" id="pnote-397-1">1</a>] Et en plus le site du plugin pour Dotclear 1 n'existe plus. Si besoin, je dois en avoir une copie dans un coin !</p></div>