2012-04-28 10 views
1

Je veux correspondre à un sous ensemble de unicode/UTF-8 caractères, (en jaune ici http://solomon.ie/unicode/), de mes recherches je suis venu avec ceci:preg_match unicode analyse syntaxique

// ensure it's valid unicode/get rid of invalid UTF8 chars 
$text = iconv("UTF-8","UTF-8//IGNORE",$text); 

// and just allow a basic english...ish.. chars through - no controls, chinese etc 
$match_list = "\x{09}\x{0a}\x{0d}\x{20}-\x{7e}"; // basic ascii chars plus CR,LF and TAB 
$match_list .= "\x{a1}-\x{ff}"; // extended latin 1 chars excluding control chars 
$match_list .= "\x{20ac}"; // euro symbol 

if (preg_match("/[^$match_list]/u", $text)) 
    $error_text_array[] = "<b>INVALID UNICODE characters</b>"; 

test semble montrer fonctionne comme prévu, mais en tant que débutant à uniocde, je serais reconnaissant si quelqu'un ici peut détecter les vulnérabilités que j'ai oubliées. Puis-je confirmer que les plages hexadécimales correspondent aux points de code Unicode, par opposition à la valeur hexadécimale réelle (par exemple, x20ac au lieu de xe282ac pour le symbole Euro est correct)? Puis-je mélanger des caractères littéraux et des valeurs hexadécimales comme preg_match ("/ [^ 0-9 \ x {20ac}]/u", $ text)?

Merci, Kevin

Note, j'ai essayé cette question avant, mais il était fermé - « mieux adapté à codereview.stackexchange.com », mais pas là une réponse si l'espoir qu'il est correct d'essayer à nouveau dans une grande format plus concis.

Répondre

2

J'ai créé un wrapper pour tester votre code et je pense qu'il est sécurisé dans le filtrage des caractères que vous attendiez, mais votre code provoquera E_NOTICE quand il trouve des caractères UTF-8 invalides. Donc je pense que vous devriez ajouter @ au début de la ligne iconv pour supprimer les notifications.

Pour la deuxième question, vous pouvez mélanger les caractères littéraux et les valeurs hexadécimales. Vous pouvez aussi essayer par vous-même aussi. :)

<?php 
function generatechar($char) 
{ 
    $char = str_pad(dechex($char), 4, '0', STR_PAD_LEFT); 
    $unicodeChar = '\u'.$char; 
    return json_decode('"'.$unicodeChar.'"'); 
} 
function test($text) 
{ 
    // ensure it's valid unicode/get rid of invalid UTF8 chars 
    @$text = iconv("UTF-8","UTF-8//IGNORE",$text); //Add @ to surpress warning 
    // and just allow a basic english...ish.. chars through - no controls, chinese etc 
    $match_list = "\x{09}\x{0a}\x{0d}\x{20}-\x{7e}"; // basic ascii chars plus CR,LF and TAB 
    $match_list .= "\x{a1}-\x{ff}"; // extended latin 1 chars excluding control chars 
    $match_list .= "\x{20ac}"; // euro symbol 

    if (preg_match("/[^$match_list]+/u", $text) ) 
     return false; 

    if(strlen($text) == 0) 
     return false; //For testing purpose! 
    return true; 
} 

for($n=0;$n<65536;$n++) 
{ 
    $c = generatechar($n); 
    if(test($c)) 
     echo $n.':'.$c."\n"; 
} 
+0

chalet16 - merci beaucoup pour cela. Je vais jouer avec votre code de test quand je serai de retour au bureau lundi. J'ai mélangé les caractères selon mon exemple et cela semble fonctionner, mais je vérifiais juste pour être sûr :) Encore merci beaucoup pour vos efforts, Kevin – KevInSol

+0

Salut, je dois essayer ça maintenant, ça marche plutôt comme prévu sauf que j'ai l'air de retourner vrai pour u + d800 à u + dfff. Je ne vois pas où je vais me tromper. Aussi, je remarque que vous avez ajouté le + métachar à mon expression rationnelle - est-ce nécessaire lorsque vous essayez de faire correspondre le caractère ant dans une liste? – KevInSol

+0

Je viens de voir que u + d800 à u + dfff sont la paire de substitution - mais cela semble être utilisé en UTF-16, pas 8? Et l'iconv aurait dû les dépouiller? – KevInSol