Bonjour,

Suite à mon sujet PHP : Traitements des chaînes de caractère (ISO-8859-1) (qui n'a pas rencontré un succès probant d'ailleurs !) j'aurais quelques questions supplémentaires à poser.

Qu'est-ce qu'un caractère illégal pour un charset donné ? (par exemple pour l'ISO-8859-1)

Si j'ai bien compris, c'est un caractère impossible à encoder directement, donc on doit passer par une alternative à savoir son entité HTML ou sa référence numérique.

J'aimerais en avoir confirmation.

Dans ce cas, est-ce que tous les caractères invalides doivent être transformés en entité HTML (ou référence numérique) pour être stockés dans une base de données du même charset ?

En tout cas dans phpmyadmin, et sur une base de données encodées en ISO-8859-1, j'ai rentré un dans une table sans problème !

J'y comprends plus rien là Smiley sweatdrop
Modifié par 84mickael (22 Aug 2005 - 22:21)
84mickael a écrit :

Qu'est-ce qu'un caractère illégal pour un charset donné ? (par exemple pour l'ISO-8859-1)

Si j'ai bien compris, c'est un caractère impossible à encoder directement


C’est un caractère dont l’encodage correspond à un des caractères de contrôle dans le jeu de caractères utilisé.

a écrit :

donc on doit passer par une alternative à savoir son entité HTML ou sa référence numérique.


C’est une possibilité mais ce n’est pas l’idéal.
L’idéal est d’utiliser unicode (<- jeu de caractère) et de stocker les données en utf-8 (<- un des encodages possibles du jeu de caractère unicode).

Mais cela va poser problème si ta base de données ne gère pas les encodages multi-octets comme utf-8 et que tu as besoin de faire des traitements de chaîne dans tes requètes SQL.

a écrit :

En tout cas dans phpmyadmin, et sur une base de données encodées en ISO-8859-1, j'ai rentré un dans une table sans problème !

J'y comprends plus rien là Smiley sweatdrop


Alors. Dans le jeu de caractère ISO-8859-1, il y a des caractères dits "de contrôle".
Ils sont situés dans les intervalles 00-1F et 7F-9F. Ces caractères ne sont généralement pas utilisés, ou bien dans certains cas particuliers.
En tout cas, ils n’ont pas leur place dans une page web (sauf le retour chariot (0D), le saut de ligne (0A) et la tabulation (09)).

Certaines entreprises ont créé d’autres jeux de caractères dans lesquels les espaces alloués à ces caractères de contrôle (et cela dans tous les charset ISO-*, pas seulement ISO-8859-1) sont utilisés pour des caractères plus "utiles".
Dans le cas qui nous occupe, il s’agit du jeu de caractère Windows-1252 et dans lequel le signe euro existe. Par la force des choses, la plupart des logiciels considèrent que les chaînes déclarées en iso-8859-1 sont en fait encodées en Windows-1252.

Bref, ton navigateur détecte un de ces caractères de contrôle dans la page que tu affiches, voit que la page a été déclarée en iso-8859-1 et en conclue donc que c’est en fait du Windows-1252 (et affiche donc le caractère correspondant dans ce jeu de caractère).

Voilà comment on se retrouve avec un signe euro dans une page pourtant déclarée en iso-8859-1.
Modifié par Bobe (22 Aug 2005 - 23:19)
Merci pour tes réponses très précises.

Si j'ai bien compris, sachant que MySQL 4.1.x gère l'UTF-8, les solutions possibles sont :

* Charset ISO-8859-1 et BD ISO-8859-1 :
Saisie
- transformation des caractères invalides ISO-8859-1 en entités
- encodage en ISO-8859-1

Base de données
Affichage

* Charset UTF-8 et BD en UTF-8 :
Saisie
- encodage en UTF-8
Base de données
Affichage

* Charset ISO-8859-1 et BD UTF-8 :
Saisie
- encodage en UTF-8
Base de données
- transformation des caractères invalides ISO-8859-1 en entités
- encodage en ISO-8859-1
Affichage

Je n'utiliserai pas la dernière solution car ça fait beaucoup de traitements, par contre j'hésite entre les 2 premières.

Est-ce que des problèmes liés à l'utilisation d'UTF-8 persistent ?
* traitements différents avec PHP (strlen...)
* incompatibilités dûs à l'utilisation par défaut d'ISO-8859-1
* ...

De plus si quelqu'un sait comment transformer en PHP du texte saisi par un utilisateur en chaîne de type UTF-8 ou ISO-8859-1 + entités HTML valide, ce serait gentil de me le dire ici ou sur le sujet dont le lien est cité plus haut.

Je cherche désespérément la réponse depuis hier et ça me bloque dans on travail Smiley ohwell .
Modifié par 84mickael (23 Aug 2005 - 00:21)
84mickael a écrit :

Est-ce que des problèmes liés à l'utilisation d'UTF-8 persistent ?
* traitements différents avec PHP (strlen...)


Oui. Un e accent aïgu encodé en UTF-8 prend deux octets (d’où le terme d’encodage multi-octets). Avec le "é" en utf-8 dans les exemples suivants :

echo strlen('é'); // renverra 2
$a = substr('é', 0, 1); // va "couper" le é en deux, il ne reste plus que le premier octet le composant

Il te faut donc le module mbstring de PHP :
http://fr.php.net/manual/fr/ref.mbstring.php

Vérifie qu’il est effectivement installé sur ton serveur avant de prendre ta décision. Smiley smile

84mickael a écrit :

* incompatibilités dûs à l'utilisation par défaut d'ISO-8859-1


Je ne comprend pas.

84mickael a écrit :

De plus si quelqu'un sait comment transformer en PHP du texte saisi par un utilisateur en chaîne de type UTF-8 ou ISO-8859-1 + entités HTML valide, ce serait gentil de me le dire ici ou sur le sujet dont le lien est cité plus haut.


chaîne en entrée : ISO-8859-1 (donc probablement Windows-1252)
chaîne en sortie : UTF-8 valide


function myutf8_encode($str)
{
	$cp1252_map = array(
	   "\xc2\x80" => "\xe2\x82\xac", /* EURO SIGN */
	   "\xc2\x82" => "\xe2\x80\x9a", /* SINGLE LOW-9 QUOTATION MARK */
	   "\xc2\x83" => "\xc6\x92",     /* LATIN SMALL LETTER F WITH HOOK */
	   "\xc2\x84" => "\xe2\x80\x9e", /* DOUBLE LOW-9 QUOTATION MARK */
	   "\xc2\x85" => "\xe2\x80\xa6", /* HORIZONTAL ELLIPSIS */
	   "\xc2\x86" => "\xe2\x80\xa0", /* DAGGER */
	   "\xc2\x87" => "\xe2\x80\xa1", /* DOUBLE DAGGER */
	   "\xc2\x88" => "\xcb\x86",     /* MODIFIER LETTER CIRCUMFLEX ACCENT */
	   "\xc2\x89" => "\xe2\x80\xb0", /* PER MILLE SIGN */
	   "\xc2\x8a" => "\xc5\xa0",     /* LATIN CAPITAL LETTER S WITH CARON */
	   "\xc2\x8b" => "\xe2\x80\xb9", /* SINGLE LEFT-POINTING ANGLE QUOTATION */
	   "\xc2\x8c" => "\xc5\x92",     /* LATIN CAPITAL LIGATURE OE */
	   "\xc2\x8e" => "\xc5\xbd",     /* LATIN CAPITAL LETTER Z WITH CARON */
	   "\xc2\x91" => "\xe2\x80\x98", /* LEFT SINGLE QUOTATION MARK */
	   "\xc2\x92" => "\xe2\x80\x99", /* RIGHT SINGLE QUOTATION MARK */
	   "\xc2\x93" => "\xe2\x80\x9c", /* LEFT DOUBLE QUOTATION MARK */
	   "\xc2\x94" => "\xe2\x80\x9d", /* RIGHT DOUBLE QUOTATION MARK */
	   "\xc2\x95" => "\xe2\x80\xa2", /* BULLET */
	   "\xc2\x96" => "\xe2\x80\x93", /* EN DASH */
	   "\xc2\x97" => "\xe2\x80\x94", /* EM DASH */
	
	   "\xc2\x98" => "\xcb\x9c",     /* SMALL TILDE */
	   "\xc2\x99" => "\xe2\x84\xa2", /* TRADE MARK SIGN */
	   "\xc2\x9a" => "\xc5\xa1",     /* LATIN SMALL LETTER S WITH CARON */
	   "\xc2\x9b" => "\xe2\x80\xba", /* SINGLE RIGHT-POINTING ANGLE QUOTATION*/
	   "\xc2\x9c" => "\xc5\x93",     /* LATIN SMALL LIGATURE OE */
	   "\xc2\x9e" => "\xc5\xbe",     /* LATIN SMALL LETTER Z WITH CARON */
	   "\xc2\x9f" => "\xc5\xb8"      /* LATIN CAPITAL LETTER Y WITH DIAERESIS*/
	);
	
	return strtr(utf8_encode($str), $cp1252_map);
}


chaîne en entrée : ISO-8859-1 (donc probablement Windows-1252)
chaîne en sortie : ISO-8859-1 valide (les caractères provenant en fait de Windows-1252 sont transformés en entités HTML)


function purge_iso88591($str)
{
	$cp1252_map = array(
	   "\x80" => "&#8364;", /* EURO SIGN */
	   "\x82" => "&#8218;", /* SINGLE LOW-9 QUOTATION MARK */
	   "\x83" => "&#402;",     /* LATIN SMALL LETTER F WITH HOOK */
	   "\x84" => "&#8222;", /* DOUBLE LOW-9 QUOTATION MARK */
	   "\x85" => "&#8230;", /* HORIZONTAL ELLIPSIS */
	   "\x86" => "&#8224;", /* DAGGER */
	   "\x87" => "&#8225;", /* DOUBLE DAGGER */
	   "\x88" => "&#710;",     /* MODIFIER LETTER CIRCUMFLEX ACCENT */
	   "\x89" => "&#8240;", /* PER MILLE SIGN */
	   "\x8a" => "&#352;",     /* LATIN CAPITAL LETTER S WITH CARON */
	   "\x8b" => "&#8249;", /* SINGLE LEFT-POINTING ANGLE QUOTATION */
	   "\x8c" => "&#338;",     /* LATIN CAPITAL LIGATURE OE */
	   "\x8e" => "&#381;",     /* LATIN CAPITAL LETTER Z WITH CARON */
	   "\x91" => "&#8216;", /* LEFT SINGLE QUOTATION MARK */
	   "\x92" => "&#8217;", /* RIGHT SINGLE QUOTATION MARK */
	   "\x93" => "&#8220;", /* LEFT DOUBLE QUOTATION MARK */
	   "\x94" => "&#8221;", /* RIGHT DOUBLE QUOTATION MARK */
	   "\x95" => "&#8226;", /* BULLET */
	   "\x96" => "&#8211;", /* EN DASH */
	   "\x97" => "&#8212;", /* EM DASH */
	
	   "\x98" => "&#732;",     /* SMALL TILDE */
	   "\x99" => "&#8482;", /* TRADE MARK SIGN */
	   "\x9a" => "&#353;",     /* LATIN SMALL LETTER S WITH CARON */
	   "\x9b" => "&#8250;", /* SINGLE RIGHT-POINTING ANGLE QUOTATION*/
	   "\x9c" => "&#339;",     /* LATIN SMALL LIGATURE OE */
	   "\x9e" => "&#382;",     /* LATIN SMALL LETTER Z WITH CARON */
	   "\x9f" => "&#376;"      /* LATIN CAPITAL LETTER Y WITH DIAERESIS*/
	);
	
	return strtr($str, $cp1252_map);
}

Modifié par Bobe (23 Aug 2005 - 02:30)
Tes conseils me poussent à adopter plutôt l'ISO 8859-1, tant pis si la base de données doit contenir des chaînes encodées en HTML, il faut savoir mettre son perfectionnisme de côté ! Mes recherches touchent donc à leur fin grâce à toi Smiley smile .

Une dernière question sur un détail à éclaircir.

Quand un utilisateur fait une saisie, c'est en ISO-8859-1 (avec une variante pour Windows, mais pas pour MAC/Unix), n'est-ce pas ? Donc avec la fonction de "purge" de l'ISO-8859-1, on convertit les caractères invalides saisis, c'est logique.

Mais comment ça se passe lors d'une saisie sous MAC/Unix ? J'imagine qu'il y a l'utilisation des caractères de contrôles dont tu parlais précédemment, mais comment vont-ils être convertis en entités HTML ?

En bref, est-ce que les fonctions que tu m'as données sont compatibles pour toute plateforme ?

Merci.
84mickael a écrit :

Quand un utilisateur fait une saisie, c'est en ISO-8859-1 (avec une variante pour Windows, mais pas pour MAC/Unix), n'est-ce pas ? Donc avec la fonction de "purge" de l'ISO-8859-1, on convertit les caractères invalides saisis, c'est logique.


Si le formulaire est en méthode 'POST', les données seront envoyées dans le même encodage que celui de la page.
Sauf bien sùr que dans le cas où la page est en iso-8859-1, les données seront susceptibles de contenir des caractères provenant du charset Windows-1252 (par exemple le signe euro).
De plus, au moins dans le cas où la page est en iso-8859-1, la plupart des navigateurs envoient les caractères qui ne sont présents ni dans iso-8859-1 ni dans Windows-1252 sous forme d'entité HTML numérique (&#xxx;).

a écrit :

En bref, est-ce que les fonctions que tu m'as données sont compatibles pour toute plateforme ?


Oui.