Accueil > Code > BOM, BOM, BOM…

BOM, BOM, BOM…

Une BOM, ou Byte-Order Mark, c’est le code de caractères U+FEFF au début d’un flux de données, genre un fichier. BOM, c’est un instrument de torture de l’Unicode. Il est sensé permettre d’établir simplement en regardant les premiers bits d’un flux quel est l’encodage de ce flux. Il existe basiquement autant de BOM que de spécifications différentes de l’Unicode, c’est à dire quelques tetrachiées.

Et les BOM sont viles…

Voici un tableau des différentes BOM.

UTF-32, big-endian    -> 00 00 FE FF UTF-32, little-endian -> FF FE 00 00 UTF-16, big-endian    -> FE FF UTF-16, little-endian -> FF FE UTF-8                 -> EF BB BF

Absolument affreux, me direz-vous avec raison. Et qui sont au juste ces frères ‘endian’? Une pâle copie de Laurel et Hardy? Ben non.

Pour résumer de façon plus ou moins obscure (comme le veut la tradition informatique), les types de données plus long qu’un octet (donc tous les UTF plus grand que 8, le nombre suivant l’UTF définissant le nombre de bit par caractère, et un octet faisant huit bits, il faut suivre, bon sang) peuvent être stocké en mémoire avec son MSB (Most Significant Byte) au début ou à la fin. Le premier cas est appellé ‘big-endian’ tandit que le second est ‘little-endian’. Lorsque les données sont échangées en suivant l’ordre des octets dans lequel elles se trouvaient en premier lieu (ce qui est généralement le cas), l’ordre peut être renversé à la réception. Dans ce cas, une BOM devrait ressembler à 0xFFFE, ce qui n’est pas un caractère Unicode, et permettre donc au système de réorganiser les octets dans le sens qu’ils se doivent d’être!

Dieu merci, l’Unicode le plus courant sur le Web, UTF-8, ne souffre pas de ce problème, puisque chaque caractère est encore encodé sous la forme d’un octet. La BOM ne sert du coup plus qu’à identifier un flux UTF-8 comme étant bien un flux UTF-8.

Ce petit court d’informatique technique passé, j’aimerais attirer votre attention sur un élément particulièrement vil et perfide de l’existence de ces BOM. Lors de l’ouverture d’un fichier Unicode, la BOM ne s’affiche pas. Même le notepad de Windows, que je pensais aussi précis qu’un éditeur hexadécimal en matière d’affichage d’informations qui ne devraient pas être affichées, ôte consciencieusement la BOM des yeux de l’utilisateur. Et là, c’est le drame.

La plupart des gens qui ont utilisé PHP au moins une fois dans leur vie ont utilisé le principe de l’inclusion. Inclusion qui permet d’organiser ses fichiers, de séparer ses classes, de jouer avec des templates, etc. C’est même l’un des principe de base du fonctionnement de PHP. Et en tant que développeur consciencieux, vous vous efforcez d’encoder vos fichier de la manière la plus universelle possible, et c’est sur l’Unicode que vous avez jeté votre dévolu lors du choix fatidique. La BOM trône donc fièrement au début de chacun de vos fichiers, comme il se doit. Pas vrai?

Et bien vous venez de générer à la volée des pages dont l’encodage est faux. Eh si.

La BOM a cette très facheuse tendance qu’ont la plupart des trucs à moitié supporté par la moitié des logiciels de se coincer dans les rouages là où il ne faut pas. Hors, elle, tend à se reproduire. En effet, il arrive parfois que l’on ouvre un fichier BOMé, et qu’en le sauvegardant, on y appose… Une deuxième BOM. Et là, badaboum.

Suffit de faire attention, me direz-vous. Certes. Mais il y a plus vil. Revenons au principe de l’inclusion… Ah, je vois une étincelle s’illuminer dans votre regard…

Eh oui, l’inclusion de PHP ne vire pas les BOM des fichiers inclus. Sur votre page de rendu final, vous allez donc être victime d’une démultiplication des BOM, faisant du même coup couiner le validateur W3C, et péter la plupart des mangeurs de XML.

C’est donc pour ceci que je vous recommande, au même titre que le W3C d’ailleurs, de ne pas utiliser les BOM pour vos pages web. Les anciens navigateurs ne les supportent pas et ont tendance à afficher un joli paté à la place de ce qui devrait lui servir à vous identifier comme un saint du respect des standards, et en plus, PHP n’aime pas ça non plus.

En bonus, un petit script qui permet de bouter les BOM hors de vos fichiers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php function unBOM($dir) {
	$d = dir($dir);
	while (false !== ($e = $d->read())) {
		$s = $dir . '/' . $e;
		if(is_file($s)) {
			$sContent = file_get_contents($s);
			if(substr($sContent, 0, 3) == "\xEF\xBB\xBF") {
				echo $s . " -> BOM trouvée!";
				file_put_contents($s, substr($sContent, 3));
				echo " ...Et éliminée!\n";
			}
			else echo $s . " -> BOM introuvable!\n";
		} elseif(is_dir($s) && $e != '.' && $e != '..')
			unBOM ($s);
	}
}
unBOM('.'); // Oh c'est mignon on dirait un smiley nippon... Heum. ?>

A utiliser plusieures fois si vous soupçonnez vos BOM de s’être inopinément multipliées.

On en reparlera avec PHP6… Allez, salut.

Categories: Code Tags:
  1. 23/10/2008 à 20:49 | #1

    Bonjour, sur ce poin : "comme le veut la tradition informatique" ; je ne vous suis pas tout à fzit :) billet intéressant en tout cas !n toujours un plaisir de vou slire, @+

  1. Pas encore de trackbacks