Décoder une URL

Collez une chaîne en encodage-pourcent et relisez-la. La plupart du temps, ce qui arrive ici est une URL sortie d’un fichier de journal ou d’un export d’analytics, où la partie qui vous intéresse est enfouie quelque part sous une suite de `%3A%2F%2F`. Les caractères multi-octets sont réassemblés correctement, si bien que les accents et les emoji reviennent tels quels et non sous forme de points d’interrogation.

Les query strings issus de formulaires HTML écrivent les espaces avec un +. Dans un chemin, un plus est un plus.

Résultat

La réponse apparaît ici pendant que vous écrivez.

  • Où cela s’exécute

    Rien n’est envoyé, puisqu’il n’y a pas de fichier : tout est calculé dans cette page.

  • Sans file d’attente et sans compte

    Il répond aussi vite que votre machine le permet, et ne demande jamais qui vous êtes.

  • Autant de fois que vous voulez

    Rien n’est compté ni plafonné : répondre à nouveau ne nous coûte rien.

Comment cela fonctionne

  1. Collez le texte encodé dans le champ.
  2. Décidez ce que signifie un signe plus. Dans un query string issu d’un formulaire c’est une espace ; dans un chemin c’est un plus.
  3. Lisez le résultat. Rien n’a été envoyé pour l’obtenir.

Une séquence de pourcentage est un octet, pas une lettre

Décoder n’est pas consulter une table qui ferait passer de `%41` à `A`. Chaque séquence désigne un octet, et les octets forment ensemble des caractères UTF-8 — donc `%C3%A9` est un unique `é` construit à partir de deux séquences, et un emoji en demande quatre. Un décodeur qui traduit séquence par séquence produit deux caractères de mojibake là où il devrait n’y en avoir qu’un.

C’est aussi pourquoi une séquence incomplète ne peut pas être simplement ignorée. `%E0%A4` est le début d’un caractère de trois octets ; il n’existe pas de sortie correcte, seulement une supposition. Cette page la signale comme malformée plutôt que de deviner, ce qui fait la différence entre savoir que votre entrée était tronquée et croire tranquillement à une mauvaise réponse.

Le signe plus est une vraie ambiguïté

Aucune règle ne permet de trancher à partir de la chaîne seule. `application/x-www-form-urlencoded` — ce que poste un formulaire HTML, et ce que sont la plupart des query strings en pratique — écrit une espace `+`. L’encodage-pourcent lui-même n’a pas cette règle, donc dans un chemin `+` est simplement un caractère plus.

Les mêmes huit caractères se décodent donc de deux façons selon leur provenance, et vous seul savez laquelle. Le réglage est proposé plutôt que supposé pour cette raison. Si vous décodez un query string, l’espace est presque toujours le bon choix ; si vous décodez un chemin ou une valeur qui peut légitimement contenir un plus — un numéro de téléphone au format `+33`, une recherche sur `C++` — ce ne l’est pas.

Repérer une chaîne encodée deux fois

Si le résultat contient encore des séquences de pourcentage, la chaîne avait été encodée deux fois et vous venez d’en retirer une couche. La signature est `%2520` : c’est `%20` dont le `%` a lui-même été encodé en `%25`. Décoder une fois donne `%20`, décoder encore donne l’espace.

Cela vaut la peine d’être remarqué plutôt que décodé deux fois par réflexe, parce que le double encodage est un défaut situé en amont — en général un framework qui encode une valeur et un gabarit qui l’encode à nouveau. Le symptôme visible est un `Bonjour%20le%20monde` dans un titre de page, et à ce stade il est à plusieurs systèmes de son origine.

Lire une URL sortie d’un fichier de journal

C’est la raison la plus fréquente d’être ici. Un journal d’accès ou un export d’analytics conserve la ligne de requête complète, et toute URL qui était elle-même un paramètre — cible de redirection, callback, référent — arrive encodée une fois pour son propre compte et une seconde fois pour celle qui la contient.

Décodez la couche extérieure et l’URL intérieure devient lisible ; décodez encore et ce sont ses propres paramètres qui le deviennent. Ne décodez pas une troisième fois par habitude : à ce stade vous décodez des séquences qui étaient du texte littéral au départ, et vous transformerez en autre chose un `%` qui appartenait au terme de recherche de quelqu’un.

Pourquoi celui-ci mérite aussi d’être fait en local

Les URL sorties d’un journal transportent des identifiants de session, des tokens placés dans des paramètres où ils n’auraient pas dû être, des termes de recherche et, assez souvent, une adresse électronique. C’est la même catégorie de chose que les tokens de la page Base64, et cela mérite le même traitement.

Rien ici n’est envoyé. Le décodage tient en quelques lignes d’arithmétique dans la page que vous lisez, et l’onglet réseau est la façon de le vérifier plutôt qu’une phrase sur une page commerciale. C’est aussi ce qui rend l’outil utilisable sur un extrait de journal de production, ce qu’une charte interne interdit en général d’envoyer ailleurs.

Le mojibake, et à quoi il ressemble en français

Quand un décodeur lit des octets UTF-8 comme du Latin-1, `é` devient `é`, `à` devient `à ` et `ç` devient `ç`. Ce motif — un `Ã` suivi d’un caractère bizarre — est le signe le plus reconnaissable du problème, et il apparaît dans les journaux beaucoup plus souvent qu’on ne l’imagine.

La cause n’est jamais l’encodage-pourcent lui-même, qui a fidèlement restitué les octets. Elle est dans la couche qui a transformé ces octets en caractères, en général un composant configuré sur un jeu de caractères hérité. Cette page lit toujours en UTF-8, donc si le résultat ici est correct et qu’il est cassé ailleurs, vous savez de quel côté chercher.

Ce que le décodage ne rend pas

Il ne rend pas la structure. Décoder une URL entière transforme ses `%3F` et ses `%26` en `?` et `&` réels, et le résultat n’est plus analysable de façon fiable : impossible de dire, à la lecture, si un `&` séparait deux paramètres ou faisait partie d’une valeur.

C’est pourquoi il vaut mieux découper avant de décoder, et pourquoi la page qui analyse un query string existe séparément : elle sépare d’abord les paires puis décode chaque valeur, dans cet ordre. Décoder d’abord et découper ensuite est une erreur silencieuse, qui ne se voit que sur les valeurs contenant justement une esperluette.

Les caractères de contrôle qui reviennent

Une séquence peut désigner n’importe quel octet, y compris un retour à la ligne (`%0A`), une tabulation (`%09`) ou un octet nul (`%00`). Décodés, ils réapparaissent dans le résultat sans être visibles, ce qui peut donner une valeur qui semble courte à l’écran et qui ne l’est pas.

C’est aussi un motif d’attaque connu : injecter `%0D%0A` dans une valeur qui finira dans un en-tête HTTP permet d’en fabriquer un second. Si vous décodez une valeur venue de l’extérieur pour la réinjecter quelque part, ce qui est visible dans un champ de texte n’est pas la mesure de ce qu’elle contient.

Quand la chaîne n’était pas encodée du tout

Un texte ordinaire passé par un décodeur en ressort inchangé, tant qu’il ne contient ni `%` ni `+`. C’est rassurant et c’est aussi un piège : cela veut dire qu’un décodage superflu ne se voit pas, et qu’un pipeline qui décode deux fois par sécurité paraît fonctionner pendant des mois.

Il finit par casser sur la première valeur contenant un pourcentage littéral — un taux, une remise, une chaîne de format. `-20%` suivi d’autre chose devient soit une erreur de séquence malformée, soit un caractère inattendu. Décoder doit être fait une fois, à un endroit connu, et pas « au cas où ».

Décoder une URL : questions fréquentes

Pourquoi mon résultat contient-il encore des signes pourcent ?

Parce que la chaîne avait été encodée deux fois. Cherchez un %25, qui est un signe pourcent encodé : décodez encore une fois et vous obtiendrez le vrai texte. Il vaut la peine de remonter à l’origine du second encodage, car c’est en général un framework et un gabarit qui échappent la même valeur.

Un + doit-il devenir une espace ?

Dans un query string, presque toujours oui : c’est ce que spécifie l’encodage des formulaires HTML, et c’est ce que sont la plupart des query strings. Dans un chemin, ou dans une valeur qui peut vraiment contenir un plus comme un numéro au format +33 ou une recherche sur C++, non. Rien dans la chaîne ne le dit, d’où un réglage plutôt qu’une supposition.

L’outil dit que la séquence est malformée. Qu’est-ce que cela veut dire ?

Que les octets épelés par ces séquences ne forment pas de caractères UTF-8 valides — en général parce que la chaîne a été tronquée au milieu d’un caractère multi-octets, ou parce qu’elle a été encodée en Latin-1 par quelque chose d’ancien. Il n’existe alors pas de sortie correcte, donc le problème est signalé plutôt qu’inventé.

Les textes non latins sont-ils gérés ?

Oui. Les séquences sont réassemblées en UTF-8 avant d’être transformées en caractères, donc le cyrillique, le devanagari, le CJK et les emoji reviennent intacts. Un décodeur qui travaille séquence par séquence produit du mojibake pour tous, ce qui est la façon la plus courante dont cela se passe mal.

Ce que je colle est-il conservé ou journalisé ?

Ni l’un ni l’autre. Cela ne quitte jamais votre navigateur, il n’y a donc rien à conserver ici. Cela vaut particulièrement pour cet outil : les URL tirées de journaux transportent couramment des identifiants de session, des tokens et des termes de recherche qui n’ont jamais été destinés à un tiers.

Autres outils