Thomas Touhey
:
Des couleurs pas invalides pour tout le monde !
Pour la construction d’un traducteur BBcode pour le futur site de
Planète Casio, nommé textout() puisque c’est le nom qui
a été donné à la fonction qui se chargeait de la traduction avant que
je ne rejoigne, et parce que je suis curieux, pour la balise [color]
,
j’essaye d’implémenter un décodeur tolérant sur ce qu’il reçoit,
et strict sur ce qu’il renvoie. Pour cela, je n’émets que des couleurs en RGB
(avec une un alpha lorsque la couleur est semi-transparente, en seconde
définition pour qu’au cas où le navigateur comprenne toujours au moins la
forme sans l’alpha), et j’essaye de recevoir ce que les navigateurs
comprennent en HTML et CSS. Et au-delà des fonctions telles que rgb()
,
hsl()
ou hwb()
, j’ai pu découvrir que « chucknorris » était une
couleur valide.
Il semblerait qu’il s’agisse d’un héritage de Microsoft Internet Explorer, qui a un décodeur tolérant — un peu trop, puisque l’abus de ce décodeur a été utilisée par du spam au point d’arriver dans le Spammers’ Compendium, une référence des techniques utilisées dans les spams par e-mail des années 2000, sous le nom de « Flex Hex ». J’ai découvert cette particularité au travers du message de dash sur StackOverflow, en réponse à une question qui avait été pas mal partagée par des contacts à une époque (je ne saurais dire quand exactement). C’est même dans la spec’ HTML ! J’ai mis un temps à comprendre la technique, alors je me suis dit qu’en plus de partager ça, j’essaierai d’expliquer un peu plus (et en français) de quoi il en retourne.
Prenons une couleur qui m’a posé problème par exemple, LuckyCharms
.
Puisque l’on n’utilise pas une fonction ici, on suppose qu’il s’agit d’un
code hexadécimal. Il n’y a pas de #
à l’entrée, mais s’il y en avait un,
on aurait commencé par l’éliminer. De plus, si la chaîne à traiter faisait
plus de 128 caractères, il aurait fallu la couper à 128 caractères.
La première étape est de remplacer tout ce qui n’est pas hexadécimal par un
0
: ici, cela nous donnera 00c00c0a000
. On ajoute ensuite des zéros à
la fin jusqu’à ce que la longueur soit divisible par trois : ici, on part de
onze pour arriver à douze, on doit donc ajouter un zéro à la fin. Puis on
sépare en trois parties (une pour chaque composante, rouge, vert, bleu). Cela
nous donne donc 00c0 0c0a 0000
. Si les parties avaient fait plus de huit
caractères, on n’aurait pris que les huit caractères les plus à droite, mais
ici, ce n’est pas le cas.
Ensuite, c’est là où ça se corse : on doit retirer les zéros des trois groupes en même temps, à deux conditions :
- il faut que le zéro soit commun aux trois groupes ;
- il faut qu’il reste strictement plus de deux caractères.
Ici, on ne peut donc retirer que le premier zéro, puisque le second n’est pas
un zéro sur le deuxième groupe ! Cela nous donne donc 0c0 c0a 000
. S’il
nous reste strictement plus de deux caractères par groupe, on ne prend que
les deux premiers : ici, cela nous donnera donc 0c c0 00
. La couleur
LuckyCharms
correspond donc à la couleur #0CC000
(ce qui correspond à du
vert) !
Pour donner un autre exemple avec ce souci des zéros, sur l’entrée
00a0 00b0 0c00
, on n’aurait enlevé que le premier zéro pour arriver
sur 0a0 0b0 c00
. Je ne comprenais pas ça, mon décodeur enlevait donc les
zéros indépendamment et je me retrouvais avec a0 b0 c0
, ce qui est incorrect
puisque la sortie attendue ici est 0a 0b c0
!
Un autre exemple, suggéré par Sam Schinke sur son blog et qui met
vraiment en exergue ces contraintes de longueur, est une chaîne
hexadécimale quelconque : 6db6ec49efd278cd0bc92d1e5e072d689
, qui fait
trente-trois caractères. Pas besoin d’ajouter de zéro, trente-trois
est déjà divisible par trois, on a donc onze caractères par groupe.
C’est trop ! On passera donc les trois premiers caractères de chaque groupe
pour en obtenir huit par groupe (le maximum), cela nous donne donc
6ec49efd cd0bc92d e072d689
. Pas de zéros à passer, on peut donc se
contenter de couper à deux caractères, et on obtient donc la couleur
6e cd e0
(un bleu léger).
Un dernier exemple, parce que je ne pouvais pas vous laisser sans vous le
faire, est chucknorris
. En éliminant les caractères inconnus, cela nous
fait c00c0000000
. On ajoute un zéro à la fin pour que ça fasse douze
caractères, ce qui nous donne c00c 0000 0000
. Les groupes font moins de
huit caractères chacun, et on ne peut pas enlever les zéros au début car
il n’y en a pas au début du premier groupe, on n’a plus qu’à couper, cela
nous donne c0 00 00
, donc du rouge plutôt clair.
Comme quoi, l’auteur de cette réponse n’avait pas tort : Chuck Norris
ne se conforme pas aux standards du web, ce sont les standards du web
qui se conforment à lui. #BADA55
! Si vous avez la moindre question,
suggestion ou correction vis-à-vis de cet article, mes coordonnées sont dans
la section « À propos » :)