Code toujours, tu m'intéresses.
Par une remarquable tendance à la perversité de l'esprit humain, certains protocoles "applicatifs"
(SMTP par exemple) ont été conçu avec comme
axiome de départ qu'il devraient transporter du texte, alors qu'il est clair
qu'ils n'auraient à transporter que des valeurs numériques binaires, puisqu'un
système numérique ne sait finalement faire que cela.
D'ailleurs, le premier besoin qui s'est fait sentir, c'est de pouvoir
attacher aux e-mails des fichiers qui sont tout, sauf du texte pur.
Pourquoi le parti pris du texte ?
A cause des caractères de contrôle ! C'est très pratique de disposer
de caractères spéciaux qui permettent, comme leur nom l'indique, de contrôler
le flux de données. Avec le codage ASCII, nous avons vu qu'il en existait pas
mal, même si nous ne sommes pas entré dans le détail de leur signification.
De plus, nous n'avons pas parlé du codage des valeurs numériques. Si un
nombre entier ne pose pas trop de problèmes (1, 2 octets ou plus,
éventuellement, encore que reste à savoir dans quel ordre on va les passer),
les nombres réels, codés sous la forme mantisse / exposant sont un réel
casse-tête. Un exemple faux mais qui fait comprendre : Le nombre
1 245 389 789 726 986 425 ne va pas s'utiliser ainsi,
on va d'abord l'écrire, par exemple sous la forme 1245,389789726986425 10 15.
On s'attachera alors à stocker en mémoire ce réel sous une forme approchée
en utilisant systématiquement, disons trois octets. Sa partie entière, 1245
dans l'exemple, sera codée sur deux octets et la puissance de 10, 15 dans
l'exemple, sur un octet.
Cet exemple n'a pas de réalité, mais le principe est à peu près juste.
Suivant les plateformes et les langages de programmation, nous aurons nos
réels stockés sur 4, 6 ou 8 octets, avec plus ou moins de précision sur
la mantisse, ou plus ou moins d'espace sur la puissance de 10, suivant la nature
des calculs à réaliser (aviez-vous pensé que la notion d'infini ne peut être
gérée par un calculateur ?). Au final, il est souvent plus simple de
communiquer des valeurs numériques à un tiers sous leur forme ASCII (telles
qu'on peut les afficher ou les imprimer, avec des symboles d'écriture, donc),
plutôt que telles qu'elles sont stockées en mémoire.
La conséquence ?
Ces protocoles ne peuvent pas simplement transférer des données
numériques, puisqu'un octet est à priori considéré comme l'image d'un
caractère et non comme une donnée numérique en elle même. Ainsi, si vous
voulez transférer un fichier qui contient une représentation "bitmap"
d'une image, comme un fichier jpeg, png ou gif, par exemple, vous ne pouvez pas
considérer que c'est du texte, puisque à priori, chaque octet peut prendre
n'importe quelle valeur, y compris celle d'un caractère de contrôle. Vous
connaissez beaucoup de pages Web sans aucune image dedans ? Vous n'avez jamais
envoyé un e-mail avec une image en pièce jointe ?
La conclusion est qu'il a fallu trouver une astuce pour transporter des
données purement numériques sur un protocole qui n'est pas prévu pour ça.
Codage à tous les étages.
Le jeu va consister maintenant à coder une donnée purement numérique sous
une forme alphabétique, elle-même codée sur des valeurs numériques, pour
qu'elle puisse être transportée sur un système qui ne connaît que des 0 et
des 1.
Tordu, n'est-ce pas ?
Oui, mais comment faire autrement ? Les révolutions, c'est bien, mais on ne
peut pas en faire tous les jours, sinon, c'est le chaos permanent. Vous allez
voir que les solutions apportées sont certes parfois tordues, mais astucieuses et
surtout efficaces.
Comme il est clair, à la lueur de ce que nous avons vu jusqu'ici, que la
seule convention qui soit à peu près universellement acceptée et correctement
transportée par les protocoles applicatifs est la norme iso-646 (US-ASCII), il
faudra trouver des conventions de codage pour convertir un octet en un
ensemble de caractères sur 7 bits.
C'est parti pour la grande cuisine.
Le codage "quoted printable".
Ce codage est principalement employé pour transformer un texte écrit avec
un codage sur 8 bits en un texte qui ne contiendra que des caractères codables
sur 7 bits. Vous allez voir comme
c'est simple :
D'abord, il faut savoir sur quel codage 8 bits on va s'appuyer, en général,
pour nous, iso-8859-1.
Ensuite, nous allons utiliser un "code d'échappement" (c'est une
technique assez courante, nous la rencontrons souvent en informatique). Ici, le caractère
d'échappement est le signe =. Ce signe signifie que les deux
caractères qui vont le suivre représenteront le code hexadécimal d'un
caractère et non le caractère lui-même. Bien entendu, il faudra aussi coder le
caractère d'échappement.
Un petit exemple vaudra bien mieux qu'un long discours...
- le é dont le code 8 bits est E9, sera codé sur trois caractères
de 7 bits de la façon suivante : =E9
- De la même façon, le è sera codé =E8.
- le ç donnera =E7
- le à donnera =E0
- Comme le = revêt une signification particulière : C'est le code
d'échappement, il sera lui-même codé en =3D.
L'expression çà et là sera donc transmise sous la forme =E7=E0
et l=E0
Ainsi, nous transporterons nos données uniquement sous la forme de
caractères US-ASCII (7 bits), même s'ils nécessitent 8 bits pour être
définis. En effet, les caractères =, E, et 0 ont tous des codes ASCII
sur 7 bits.
Astucieux non ?
Bien entendu, il vaut mieux le savoir pour décoder correctement le message.
Cette méthode est utilisée principalement pour les e-mails. En voici un
exemple :
Return-Path: <christian.caleca@free.fr>
...
From: "Christian Caleca" <christian.caleca@free.fr>
To: <christian.caleca@free.fr>
Subject: quoted
Date: Tue, 5 Nov 2002 10:51:34 +0100
MIME-Version: 1.0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
...
X-Mailer: Microsoft Outlook Express 6.00.2800.1106
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106
=E7=E0 et l=E0
Notez que l'on parle ici de MIME, en indiquant, la nature du contenu (text/plain),
le jeu de caractères utilisé (iso-8859-1) et le mode d'encodage :
quoted-printable. Nous y reviendrons plus tard.
Le codage Base64.
Plus généralement, ce codage permettra de passer non seulement du texte
codé sur 8 bits, mais aussi tout type de données constituées d'octets. Voyons
d'abord avec du texte.
Là aussi, il faudra commencer par indiquer en quel code est écrit le texte
initial. Pour nous, toujours iso-8859-1.
Trois caractères de 8 bits (24 bits au total) sont découpés sous la forme de
4 paquets de 6 bits (toujours 24 bits au total). Chaque valeur sur 6 bits,
comprise donc entre 0 et 3F en hexadécimal, sera symbolisée par un caractère
présent, et avec le même code, dans toutes les versions de code ASCII
et EBCDIC. La table d'équivalence est celle qui suit. Remarquez que les
caractères choisis sont tous codés sur 7 bits en US-ASCII, mais que la valeur
qu'ils représentent n'est pas leur code ASCII
dec |
hex |
car. |
|
dec |
hex |
car. |
|
dec |
hex |
car. |
|
dec |
hex |
car. |
0 |
0 |
A |
16 |
10 |
Q |
32 |
20 |
g |
48 |
30 |
w |
1 |
1 |
B |
17 |
11 |
R |
33 |
21 |
h |
49 |
31 |
x |
2 |
2 |
C |
18 |
12 |
S |
34 |
22 |
i |
50 |
32 |
y |
3 |
3 |
D |
19 |
13 |
T |
35 |
23 |
j |
51 |
33 |
z |
4 |
4 |
E |
20 |
14 |
U |
36 |
24 |
k |
52 |
34 |
0 |
5 |
5 |
F |
21 |
15 |
V |
37 |
25 |
l |
53 |
35 |
1 |
6 |
6 |
G |
22 |
16 |
W |
38 |
26 |
m |
54 |
36 |
2 |
7 |
7 |
H |
23 |
17 |
X |
39 |
27 |
n |
55 |
37 |
3 |
8 |
8 |
I |
24 |
18 |
Y |
40 |
28 |
o |
56 |
38 |
4 |
9 |
9 |
J |
25 |
19 |
Z |
41 |
29 |
p |
57 |
39 |
5 |
10 |
A |
K |
26 |
1A |
a |
42 |
2A |
q |
58 |
3A |
6 |
11 |
B |
L |
27 |
1B |
b |
43 |
2B |
r |
59 |
3B |
7 |
12 |
C |
M |
28 |
1C |
c |
44 |
2C |
s |
60 |
3C |
8 |
13 |
D |
N |
29 |
1D |
d |
45 |
2D |
t |
61 |
3D |
9 |
14 |
E |
O |
30 |
1E |
e |
46 |
2E |
u |
62 |
3E |
+ |
15 |
F |
P |
31 |
1F |
f |
47 |
2F |
v |
63 |
3F |
/ |
Comme cette explication doit paraître fumeuse à plus d'un (moi-même, plus
je la relis, plus je la trouve fumeuse), là encore, prenons un exemple. Soit à coder
le texte extrêmement simple : 012
Ce texte est destiné à être écrit avec un codage iso-8859-1.
caractère initial |
0 |
1 |
2 |
Code ASCII hexa |
30 |
31 |
32 |
Code ASCII binaire |
00110000 |
00110001 |
00110010 |
Bien. nous avons donc la suite de 24 bits suivante : 001100000011000100110010. Nous allons maintenant la couper en quatre morceaux
de 6 bits :
les valeurs sur 6 bits |
001100 |
000011 |
000100 |
110010 |
Equivalent hexadécimal |
0C |
03 |
04 |
32 |
Caractère équivalent en Base64 |
M |
D |
E |
y |
Et voilà. 012 donne, une fois codé en Base 64 MDEy. Constatez
comme c'est simple. Constatez surtout que ces caractères seront transcrits en
US-ASCII, donc sur 7 bits.
Pour décoder, il suffit de le faire dans l'autre sens.
Refaisons la manip avec un e-mail codé en Base64 :
Return-Path: <christian.caleca@free.fr>
...
From: "Christian Caleca" <christian.caleca@free.fr>
To: <christian.caleca@free.fr>
Subject: Base 64 (1)
Date: Tue, 5 Nov 2002 11:07:11 +0100
MIME-Version: 1.0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: base64
...
X-Mailer: Microsoft Outlook Express 6.00.2800.1106
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106
MDEy
Et voilà le travail.
Ca, c'est une démo "commerciale", c'est à dire "qui ne
montre que ce qui est facile et qui marche bien". Vos messages
contiennent tous un nombre de caractères qui est un exacte multiple de 3 ?
Dans ce cas (nombre de caractères qui n'est pas un multiple de 3) , le système de codage va "remplir le trou" avec un
caractère spécial, qui ne sera pas interprété à l'arrivée. Ce caractère
est le signe =
Voyons ce que ça donne si le texte initial ne contient plus que le seul
caractère 0.
- Le premier groupe de 6 octets sera toujours le même : 001100 qui donne M
- Le second sera : 00 (complété avec des 0, donc : 000000) qui donne A
- Comme il faut 24 bits quand même, on ajoutera deux fois le caractère =
Au total, on aura MA==
Vérification par l'e-mail : Return-Path: <christian.caleca@free.fr>
...
From: "Christian Caleca" <christian.caleca@free.fr>
To: <christian.caleca@free.fr>
Subject: base 64 (3)
Date: Tue, 5 Nov 2002 11:18:06 +0100
MIME-Version: 1.0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: base64
...
X-Mailer: Microsoft Outlook Express 6.00.2800.1106
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106
MA==
CQFD. Et les autres...
uuencode.
Bien entendu, d'autres conventions existent, mais n'appartiennent pas aux
système MIME. Par exemple UUENCODE, assez proche de Base64, mais antérieur,
utilisé sur plateformes Unix.
BinHex.
Un codage propriétaire, créé dans le monde Macintosh pour les mêmes
raisons...
Vous le voyez, les astuces ne manquent pas pour utiliser exclusivement de l'ASCII
7 bits dans le transport de n'importe quelle donnée.
Conclusions.
En plus du codage des caractères dans des tables de 7 , 8 ou
même 16 bits, il faut donc ajouter des systèmes qui vont s'efforcer de
représenter tout type de donnée sous forme de texte 7 bits. Ceci
nous amène naturellement à parler de MIME...
|