Transcript
Page 1: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

Unicode et graphèmes clusters pour PHP

Page 2: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

Unicode : bases et concepts

Unicode : état de lřart

Patchwork\Utf8

Page 3: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

Peace

和平 ☮

Page 4: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

P U+0050LATIN CAPITAL LETTER P

U+0633ARABIC LETTER SEEN

和 U+548CCJK UNIFIED IDEOGRAPH-548C ☮ U+262E

PEACE SYMBOL

A chaque caractère son numéro, un nom et des propriétés (catégorie, script, etc.)

Page 5: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

Représentations binaires

Majuscules, minuscules, folding

Compositions, ligatures

Comparaison : normalisations et collations

Segmentation : caractères, mots, phrases et césures

Locales : conventions culturelles, translittérations

Identifiants et sécurité, confusables

Affichage : direction, largeur

Page 6: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

De point de codeà séquence dřoctets◦ UTF-8 : 1, 2, 3 ou 4 octets

◦ UTF-16 : 2 ou 4 octets

◦ UTF-32 : 4 octets

BOM U+FEFFByte Order Mark

UTF-32BE 00 00 FE FF

UTF-32LE FF FE 00 00

UTF-16BE FE FF

UTF-16LE FF FE

UTF-8 EF BB BF ()

á U+00E1LATIN SMALL LETTER A WITH ACUTE

UTF-16BE 00 E1

UTF-8 C3 A1

あ U+3042HIRAGANA LETTER A

UTF-16BE 30 42

UTF-8 E3 81 82

Page 7: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

Sur-ensemble dřASCII

Auto-synchronisé

Caractéristique

Octet 1 Octet 2 Octet 3 Octet 4

0xxxxxxx

110xxxxx 10xxxxxx

1110xxxx 10xxxxxx 10xxxxxx

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

Page 8: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

Concerne un peu plus de 1000 caractères

Folding Ŕ comparaison insensible à la casse◦ Comparer les chaînes en minuscules

◦ Une majuscule, deux minuscules : Σ ⇔ σ/ς

◦ Exception turque : I ⇔ i vs İ ⇔ i et I ⇔ ı

◦ Full folding : ß ⇔ ss

Page 9: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

ÅÅ U+00C5

LATIN CAPITAL LETTER A WITH RING ABOVE

A+◌̊ 0041, 030ALATIN CAPITAL LETTER A, COMBINING RING ABOVE

fif+i U+0066, U+0069

LATIN SMALL LETTER F, LATIN SMALL LETTER I

fi FB01LATIN SMALL LIGATURE FI

둑ᄃ+ᅮ+ᆨ

U+1103, U+116E, U+11A8HANGUL CHOSEONG TIKEUT, HANGUL JUNGSEONG U, HANGUL JONGSEONG KIYEOK

둑 U+B451HANGUL SYLLABE DUG

Comment tester lřégalité ? (=, ≠)

Page 10: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

Forme Composée, Décomposée, de Kompatiblité

ḋ+◌U+1E0B, U+0323LATIN SMALL LETTER D WITH DOT ABOVE,COMBINING DOT BELOW

d+◌+◌̇U+0064, U+0323, U+0307LATIN SMALL LETTER D,COMBINING DOT BELOW, COMBINING DOT ABOVE

ḍ+◌̇U+1E0D, U+0307LATIN SMALL LETTER D WITH DOT BELOW,COMBINING DOT ABOVE

fif+i U+0066, U+0069

LATIN SMALL LETTER F, LATIN SMALL LETTER I

fi U+FB01LATIN SMALL LIGATURE FI

NFD

NFC

NFKD, NFKC

NFD, NFC

Page 11: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

NFC

D é j à U+0044 U+00E9 U+006A U+00E0

NFD

D e ◌ j a ◌U+0044 U+0065 U+0301 U+006A U+0061 U+0300

Quel est le 2e caractère ? le 3e ?

Page 12: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

ICU : Java et C/C++◦ Licence X-like, soutenu par IBM, utilisé comme

implémentation de référence pour Unicode et +

Perl 6 Parrot : NFG◦ NFC + Graphèmes Clusters

JavaScript : Unicode (NFC)

Python : chaînes typées

PHP : iconv, mbstring, pcre, intl

Page 13: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

iconv_set_encoding('UTF-8')

◦ iconv($in_charset , $out_charset , $str)

◦ iconv_strlen($str)

◦ iconv_substr($str, $start, $length)

◦ iconv_strpos($haystack, $needle, $offset = 0)

◦ iconv_strrpos($haystack, $needle)

Manipulation de chaînes UTF-8 : fait !

NFC : DéjàNFD : De◌ ◌

Page 14: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

mb_internal_encoding('UTF-8')

◦ Équivalents dřiconv

◦ mb_strtolower/upper (), pas de folding

◦ mb_stripos(), folding simple

Manipulation de chaînes UTF-8 : fait ! (bis)

Manipulation de la casse : fait ! % folding

NFC : DéjàNFD : De◌ ja◌

Page 15: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

Avec le modificateur u : /./u

Donne accès aux propriétés Unicode◦ \x{00E9} ou simplement é ssi source UTF-8◦ \p{Greek}◦ \p{Mn}◦ \X ⇔ (?>\PM\pM*) pour PCRE < 8.32

Vérifier la validité UTF-8 de $str :

preg_match('//u', $str)

Manipulation de chaînes UTF-8 : fait ! (ter) Manipulation des propriétés Unicode : fait !

NFC : DéjàNFD : De◌ ◌

Page 16: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

Normalizer

Gestion des graphèmes clusters

Collator, NumberFormatter, Locale, MessageFormatter, IntlDateFormatter, Spoofchecker, Transliterator, Fonctions IDN, Uconverter (PHP5.5)

Page 17: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

use Normalizer as n;

n::isNormalized($str, $form = n::NFC)

n::normalize($str, $form = n::NFC)

n::NFC, n::NFD, n::NFKC, n::NFKC, n::NONE

Tester lřégalité de chaînes : fait !

NFC : DéjàNFD : De◌ ◌

Page 18: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

grapheme_extract ŕ Extrait un groupe de graphèmes d'une chaîne UTF-8

grapheme_stripos grapheme_stristr grapheme_strlen grapheme_strpos grapheme_strripos grapheme_strrpos grapheme_strstr grapheme_substr

Manipulation par graphème cluster : fait !◦ Encore un peu jeune, attention aux bugs◦ https://bugs.php.net/55562, 61860 et 62759

NFC : DéjàNFD : De◌ ◌

Page 19: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

Chaînes UTF-8 : iconv, mbstring, pcre Casse : mbstring Normalisation : intl Graphèmes : intl et pcre

function toAscii($s){

if (preg_match("/[\x80-\xFF]/", $s)){

$s = Normalizer::normalize($s, Normalizer::NFKD);$s = preg_replace('/\p{Mn}+/u', '', $s);

$s = iconv('UTF-8', 'ASCII//TRANSLIT', $s);}

return $s;}

Quid :◦ Case folding ? Complexité ? Disponibilité ?

Page 20: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

Unicode et graphèmes clusters pour PHP

Page 21: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

Portabilité PHP, optimisé pour UTF-8

◦ Iconv : 99%

◦ Mbstring : les 45% nécessaires

◦ Intl : Normalizer et grapheme_*()

◦ utf8_en/decode() - Windows-1252 enhanced

Page 22: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF

0x NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI

1x DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US

2x SP ! " # $ % & ' ( ) * + , - . /

3x 0 1 2 3 4 5 6 7 8 9 : ; < = > ?

4x @ A B C D E F G H I J K L M N O

5x P Q R S T U V W X Y Z [ \ ] ^ _

6x ` a b c d e f g h i j k l m n o

7x p q r s t u v w x y z { | } ~ DEL

8x € ‚ ƒ „ … † ※ ˆ ‰ Š ‹ Œ Ţ

9x Ř ř Ŗ ŗ • Ŕ ŕ ˜ ™ š › œ ţ Ÿ

AxNBS

P¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯

Bx ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿

Cx À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï

Dx Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß

Ex à á â ã ä å æ ç è é ê ë ì í î ï

Fx ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ

HTML5 : se substitue à ISO-8859-1

Page 23: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

Patchwork\Utf8

mbstring

iconv

grapheme_*

Normalizer

pcre

xml

Page 24: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

Les fonctions PHP, version UTF-8

◦ Limité au sous-ensemble qui le nécessite

◦ Préfixe u:: pour déclarer lřintention dans le code

Page 25: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

strlen - chr - ord

substr - str_split

strpos - strrpos - strstr - strrchr - stripos - strripos - stristr - strrichr

strtolower - strtoupper - ucfirst - lcfirst - ucwords

trim - ltrim - rtrim

strtr - str_ireplace - substr_replace - str_replace déjà compatible

strcmp - strnatcmp - strcasecmp - strnatcasecmp - strncasecmp - strncmp

strspn - strcspn - strpbrk - substr_compare - substr_count - str_word_count -count_chars

number_format - wordwrap - str_pad - strrev - str_shuffle

utf8_encode - utf8_decode Ŕ Windows-1252 enhanced

Manque la famille printf

Ajoute isUtf8 - toAscii - strtocasefold - strtonatfold et nombreux workaround

NFC : DéjàNFD : De◌ ja◌

Page 26: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

Quelques extras, workarounds et bootstrapping

Couvert par de nombreux tests unitaires

Licences Apache-2.0 et GPL-2.0

Page 27: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

https://github.com/FSX/php-utf8

Mediawiki, PhpBB, Drupal, etc.

Différences majeures◦ Gestion des graphème clusters

◦ API déjà documentée : cf. documentation PHP

◦ Bootstrapping via autoload possible

◦ Testable et comparable en même temps

Page 28: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

Editeur de code en mode UTF-8 sans BOM

Vérifiez la validité UTF-8 de vos entrées

Mais ne supprimez pas les caractères erronés◦ java\xFFscript:alert("XSS")◦ preg_match('//u', $v) or $v = u::utf8_encode($v);

Normalisez vos entrées UTF-8 : NFC on demand

require 'bootup.utf8.php';

use Patchwork\Utf8 as u;

Page 29: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

NFC repousse les graphèmes clusters

Pour manipuler des données (cf. MySQL),pas les identifiants.

A utiliser avec discernement

Page 31: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

Page 32: Patchwork UTF-8 : portabilité unicode et graphèmes clusters

PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8

14Mo4Mo2Mo

-


Recommended