UTF-8-überprüfung in PHP ohne Verwendung von preg_match()
Muss ich überprüfen einige Benutzereingaben, die in UTF-8 codiert. Viele haben empfohlen, mit dem folgenden code:
preg_match('/\A(
[\x09\x0A\x0D\x20-\x7E]
| [\xC2-\xDF][\x80-\xBF]
| \xE0[\xA0-\xBF][\x80-\xBF]
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}
| \xED[\x80-\x9F][\x80-\xBF]
| \xF0[\x90-\xBF][\x80-\xBF]{2}
| [\xF1-\xF3][\x80-\xBF]{3}
| \xF4[\x80-\x8F][\x80-\xBF]{2}
)*\z/x', $string);
Es ist ein regulärer Ausdruck genommen http://www.w3.org/International/questions/qa-forms-utf-8 . Alles war ok, bis ich entdeckte einen bug in PHP, der scheint, gewesen herum mindestens seit 2006. Preg_match() bewirkt, dass ein seg-fault, wenn der $string ist zu lang. Es scheint keine Abhilfe. Sie können den bug submission hier: http://bugs.php.net/bug.php?id=36463
Nun, um zu vermeiden, mit preg_match ich habe eine Funktion, die genau die gleiche Sache wie der reguläre Ausdruck oben. Ich weiß nicht, ob diese Frage hier angebracht, auf Stack Overflow, aber ich würde gerne wissen, ob die Funktion, die ich gemacht habe richtig ist. Hier ist es:
BEARBEITEN [13.01.2010]:
Wenn jemand interessiert ist, es wurden einige Fehler in der vorherigen version, die ich gepostet habe. Unten ist die endgültige version der Funktion.
function check_UTF8_string(&$string) {
$len = mb_strlen($string, "ISO-8859-1");
$ok = 1;
for ($i = 0; $i < $len; $i++) {
$o = ord(mb_substr($string, $i, 1, "ISO-8859-1"));
if ($o == 9 || $o == 10 || $o == 13 || ($o >= 32 && $o <= 126)) {
}
elseif ($o >= 194 && $o <= 223) {
$i++;
$o2 = ord(mb_substr($string, $i, 1, "ISO-8859-1"));
if (!($o2 >= 128 && $o2 <= 191)) {
$ok = 0;
break;
}
}
elseif ($o == 224) {
$o2 = ord(mb_substr($string, $i + 1, 1, "ISO-8859-1"));
$o3 = ord(mb_substr($string, $i + 2, 1, "ISO-8859-1"));
$i += 2;
if (!($o2 >= 160 && $o2 <= 191) || !($o3 >= 128 && $o3 <= 191)) {
$ok = 0;
break;
}
}
elseif (($o >= 225 && $o <= 236) || $o == 238 || $o == 239) {
$o2 = ord(mb_substr($string, $i + 1, 1, "ISO-8859-1"));
$o3 = ord(mb_substr($string, $i + 2, 1, "ISO-8859-1"));
$i += 2;
if (!($o2 >= 128 && $o2 <= 191) || !($o3 >= 128 && $o3 <= 191)) {
$ok = 0;
break;
}
}
elseif ($o == 237) {
$o2 = ord(mb_substr($string, $i + 1, 1, "ISO-8859-1"));
$o3 = ord(mb_substr($string, $i + 2, 1, "ISO-8859-1"));
$i += 2;
if (!($o2 >= 128 && $o2 <= 159) || !($o3 >= 128 && $o3 <= 191)) {
$ok = 0;
break;
}
}
elseif ($o == 240) {
$o2 = ord(mb_substr($string, $i + 1, 1, "ISO-8859-1"));
$o3 = ord(mb_substr($string, $i + 2, 1, "ISO-8859-1"));
$o4 = ord(mb_substr($string, $i + 3, 1, "ISO-8859-1"));
$i += 3;
if (!($o2 >= 144 && $o2 <= 191) ||
!($o3 >= 128 && $o3 <= 191) ||
!($o4 >= 128 && $o4 <= 191)) {
$ok = 0;
break;
}
}
elseif ($o >= 241 && $o <= 243) {
$o2 = ord(mb_substr($string, $i + 1, 1, "ISO-8859-1"));
$o3 = ord(mb_substr($string, $i + 2, 1, "ISO-8859-1"));
$o4 = ord(mb_substr($string, $i + 3, 1, "ISO-8859-1"));
$i += 3;
if (!($o2 >= 128 && $o2 <= 191) ||
!($o3 >= 128 && $o3 <= 191) ||
!($o4 >= 128 && $o4 <= 191)) {
$ok = 0;
break;
}
}
elseif ($o == 244) {
$o2 = ord(mb_substr($string, $i + 1, 1, "ISO-8859-1"));
$o3 = ord(mb_substr($string, $i + 2, 1, "ISO-8859-1"));
$o4 = ord(mb_substr($string, $i + 3, 1, "ISO-8859-1"));
$i += 5;
if (!($o2 >= 128 && $o2 <= 143) ||
!($o3 >= 128 && $o3 <= 191) ||
!($o4 >= 128 && $o4 <= 191)) {
$ok = 0;
break;
}
}
else {
$ok = 0;
break;
}
}
return $ok;
}
Ja, es ist sehr lang. Ich hoffe ich hab das richtig verstanden wie Sie, dass der reguläre Ausdruck funktioniert. Hoffe auch, dass es helfen wird, die andere.
Vielen Dank im Voraus!
- Warum schauen so viele spezielle Werte? Es kann viel einfacher sein.
- Ich habe versucht, genau zu prüfen, was der reguläre Ausdruck vom W3C überprüft.
- Was planen Sie zu tun, wenn die Zeichenfolge keine gültige UTF-8? Besser, verstümmelt Daten als gar keine Daten richtig?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie immer mit der Multibyte-String-Funktionen:
Wenn Sie wollen, es zu benutzen eine Menge und vielleicht ändern Sie es irgendwann:
1.) Zuerst legen Sie die Codierung, die Sie verwenden möchten in Ihre config-Datei
2) Überprüfen Sie die String -
Oder, wenn Sie nicht Vorhaben, ihn zu ändern, können Sie immer legen Sie einfach die Codierung direkt in der Funktion:
Gegeben, dass es noch keine expliziten isUtf8 () - Funktion in PHP, hier ist, wie UTF-8 kann genau überprüft in PHP je nach PHP-version.
Einfachste und am meisten rückwärts kompatibel Weg, um richtig validieren von UTF-8 ist immer noch über den regulären Ausdruck mit der Funktion wie:
Beachten Sie die zwei entscheidenden Unterschiede zu dem regulären Ausdruck angeboten von W3C. Es verwendet nur einmal Teilmuster und hat ein '+' Quantifizierer nach dem ersten Charakter-Klasse. Das problem der PCRE-Absturz weiterhin, aber das meiste ist durch die Verwendung von sich wiederholenden capturing subpattern. Durch drehen der Muster um ein nur einmal Muster und die Erfassung mehrerer single-byte-Zeichen in einzelnen Teilmuster, es soll verhindern, dass PCRE aus schnell ausgeführten out-of-stack (und verursacht einen segmentation Fault). Es sei denn, du bist Validierung von strings mit viel mehr-Byte-Zeichen (in der Größenordnung von tausenden), dieser reguläre Ausdruck sollte servieren Ihnen gut.
Eine andere gute alternative ist mit
mb_check_encoding()
wenn Sie die mbstring-Erweiterung zur Verfügung. Validieren von UTF-8 kann getan werden, so einfach wie:Beachten Sie jedoch, dass, wenn Sie mit der PHP-version vor 5.4.0, diese Funktion hat einige Fehler in der Validierung:
Als das internet listet auch zahlreiche andere Möglichkeiten zum validieren von UTF-8 sind, werde ich einige von Ihnen hier. Beachten Sie, dass sollte Folgendes vermieden werden in den meisten Fällen.
Verwendung von
mb_detect_encoding()
ist manchmal gesehen zu validieren UTF-8. Wenn Sie mindestens die PHP-version 5.4.0, es funktioniert tatsächlich mit der strenge der parameter über:Es ist sehr wichtig zu verstehen, dass dies nicht funktioniert, vor 5.4.0. Es ist sehr fehlerhaft, die vor dieser version, da es nur Prüfungen für ungültig Sequenzen, erlaubt aber den überlangen Sequenzen und ungültigen code Punkte. Darüber hinaus sollten Sie nie verwenden es für diesen Zweck, ohne die strenge parameter auf true gesetzt ist (ist es eigentlich nicht tun, Validierung ohne den strict-parameter).
Eine raffinierte Möglichkeit zu überprüfen UTF-8 ist, durch die Verwendung von " u " - flag in der PCRE. Aber schlecht dokumentiert ist, es auch überprüft die Zeichenkette. Ein Beispiel könnte sein:
Jede Zeichenfolge sollte mit einem leeren pattern, aber dadurch der Gebrauch der 'u' - flag passt nur auf gültige UTF-8-strings. Allerdings, wenn Sie mit mindestens 5.5.10. Die Validierung ist fehlerhaft wie folgt:
Mit dem " u " - flag Verhalten hat aber auch einen Vorteil: Es ist das Schnellste der hier besprochenen Methoden. Wenn du Geschwindigkeit brauchst, und Sie sind mit der neuesten und größten PHP-version, diese Validierung Methode könnte für Sie sein.
Einer zusätzlichen Validierung für UTF-8 ist über
json_encode()
, die erwartet input-strings werden in UTF-8. Es funktioniert nicht, vor 5.5.0, aber nach, dass, ungültige Sequenzen false zurück, anstatt eine Zeichenfolge. Zum Beispiel:Ich würde nicht empfehlen, auf auf dieses Verhalten verlassen, um die Letzte, allerdings. Frühere PHP-Versionen einfach produzierten eine Fehlermeldung für ungültige Sequenzen, so gibt es keine Garantie, dass das aktuelle Verhalten ist endgültig.
Sollten Sie in der Lage sein zu verwenden iconv auf Gültigkeit überprüfen. Einfach versuchen, und konvertieren Sie Sie in UTF-16 und sehen, wenn Sie eine Fehlermeldung erhalten.
Haben Sie versucht,
ereg()
statt preg_match? Vielleicht das man nicht haben, die Fehler, und Sie brauchen nicht eine potenziell buggy Abhilfe.if (function_exists('ereg'))
und verwenden preg_match benutzt.Hier ist eine string-Funktion-basierte Lösung:
http://www.php.net/manual/en/function.mb-detect-encoding.php#85294