Mes impressions sur le web, les standards et autres…


Wamailer et OpenPGP

J’ai terminé cette nuit l’implémentation d’OpenPGP/MIME dans Wamailer. L’extension gnupg de PHP étant considérée comme expérimentale, les opérations de signature et de chiffrement sont faites en exécutant des commandes systèmes à destination du programme GnuPG.

Je ne sais ce qu’il en est du support d’OpenPGP/MIME dans la plupart des clients mail, mais je suppose qu’il doit être largement supporté, vu la relative facilité avec laquelle j’ai appréhendé le principe des clés et implémenté OpenPGP/MIME dans Wamailer.

J’ai aussi mis à jour la page de garde du wiki et ajouté la page OpenPgp pour fournir des explications et exemples.

SQL et structure arborescente

Dans le cadre d’un projet que je développe en ce moment, j’ai besoin de stocker un arbre dans une base de données, c’est à dire un groupe d’éléments reliés par une relation de type parent-enfant. Plusieurs solutions existent :

Les listes adjacentes

C’est la méthode la plus naturelle et celle à laquelle j’ai d’abord penser. Le principe est tout simplement d’associer à chaque nœud l’identifiant du nœud parent. On peut ensuite extraire nos données de différentes façons avec des auto-jointures (voir le lien vers mysql en fin de billet).

Le problème est que cela n’est pas applicable si la profondeur de l’arbre n’est pas fixée. Il faut alors en passer par une routine récursive (en PHP dans mon cas) pour construire l’arbre et travailler dessus. C’est bourrin, c’est coûteux…

Les ensembles imbriquées ou représentation intervallaire

Moins facile à appréhender, cette technique offre en revanche une bien plus grande facilité pour lire tout ou partie de l’arbre. La plupart des opérations de lecture ne nécessitent qu’une requête SQL !

Le principe est d’assigner à chaque élément deux bornes, les descendants de cet élément étant englobés dans l’interval créé par ces deux bornes. Je me permets de copier ici la représentation visuelle en tranche donnée dans l’article de SQLpro, ça permet de tout de suite se faire une bonne idée du mécanisme :

Représentation sous forme de tranches englobantes du mécanisme des ensembles imbriqués

Je ne m’attarde pas sur les requêtes SQL à utiliser pour consulter un tel arbre, consultez l’excellent article Gestion d'arbres par représentation intervallaire pour en savoir plus.

Ici, donc, pas besoin de récursivité, la lecture est simple et claire. Mais les choses se gâtent dès qu’on souhaite effectuer des changements sur notre arbre. Souhaite t-on ajouter un élément dans notre arbre ? Paf, trois requêtes ! Une pour décaler les bornes droite, une autre pour décaler les bornes gauches, et enfin, la requête pour insérer le nouvel élément. Et si plusieurs modifications peuvent potentiellement survenir quasiment au même moment, ne pas utiliser les transactions, et donc, dans le cas de MySQL, les tables innoDB, serait plutôt hasardeux.

Autres idées

Comme autre technique, il y en a une qui consiste à stocker carrément le chemin canonisé d’un élément à la racine. Pas super élégant et viable seulement pour des petits arbrisseaux ;¬)

J’ai vaguement pensé à stocker la structure de l’arbre sous forme XML, elle-même stockée dans la base de données, mais là comme ça, sans creuser l’idée, je me dis que les performances ne seront pas vraiment au rendez-vous. Qu’en penses-tu toi, visiteur perdu sur mon journal ? Et si tu as d’autres idées pour gérer un arbre, n’hésite pas ;¬)

Un cookie pas si récalcitrant

Errata concernant mon précédent billet sur le sujet.

D’abord, en envoyant un cookie avec pour domaine de validité .example.com, celui-ci sera viable également sur example.com. L’extension View Cookies de Firefox m’a induit en erreur.

Il semble que seuls les cookies dont le domaine de validité matche exactement le domaine courant soient affichés par cette extension, les cookies avec un domaine de validité de type .example.com valides sur plusieurs sous-domaines ne sont pas du tout affichés. Un coup d’œil à liveHttpHeaders ou avec print_r($_COOKIE); montre qu’ils sont bien actifs.

Ensuite, concernant le nombre minimum de caractères point dans le domaine de validité, celui-ci doit contenir au moins un point "embarqué" (x.y est bon, .y ou x. ne l’est pas) et la partie précédent le domaine de validité du cookie dans le nom d’hôte courant ne doit pas contenir de point. Example : le cookie avec le domaine de validité .foo.com sera valide sur foo.com et n’importe quel sous-domaine *.foo.com où * est une chaîne ne contenant pas de caractère point. Donc le cookie n’est pas valable sur *.bar.foo.com.

Au vu de ces règles (extraites de la RFC 2965), je ne vois plus ce qui empêche en principe d’émettre un cookie avec un domaine de validité tel que .co.uk et qui serait valable par exemple sur blah.co.uk. Ce billet est donc sujet à une mise à jour ultérieure, quand j’aurais éclairci ce point :¬)

Un cookie récalcitrant

Je viens de passer une demi-heure sur un problème à la con. La réponse servira peut-être à d’autres personnes :

L’attribut domain d’un cookie ne peut cibler qu’un sous-domaine (le nom complet doit comporter au moins deux points, par exemple www.example.com). Pour que le cookie soit actif sur tous les sous-domaines, n’indiquez pas de sous-domaine (mais laissez le point en tête) : .example.com
Problème : example.com ne fait pas partie des heureux élus.

Compte tenu de l’obligation d’indiquer un nom de domaine comportant au moins deux points, toute tentative d’envoyer un cookie sur la racine d’un domaine (example.com) en précisant le domaine dans la fonction setcookie() sera vouée à l’échec. La seule solution est de ne pas préciser le domaine de validité du cookie (= cookie valable uniquement sur example.com dans notre cas).

D’après la spécification, cette limitation est là pour éviter des émissions de cookie dans des domaines de validité tels que .com ou encore .co.uk.
je lis d’ailleurs à l’instant que le nombre de caractères points minimum est porté à trois si l’extension du domaine n’est pas dans la liste des extensions "spéciales" : "COM", "EDU", "NET", "ORG", "GOV", "MIL", et "INT".