dedlfix: Character Encoding - UTF-8 - multibyte String-Funktionen

Beitrag lesen

Hi!

Da ich eigentlich gerne generell und durchgehend UTF-8 codiert arbeiten wollte, müsste ich ja (u.a.) bei den String-Funktionen die jeweiligen mb_xxx Funktionen verwenden und anstelle der PCRE-Funktionen die mb_ereg_xxx Funktionen. Soweit richtig?

Die erste Frage ist, ob du tatsächlich Stringfunktionen in PHP benötigst. Mitunter lassen sich die Anwendungen so gestalten, dass PHP nur Durchreicher ist, womit das Problem der nur eingeschränkt vorhandenen Multibyte-Kodierungen erst einmal keins mehr ist.

Anscheinend ist dies aber keine Alternative für dich, so dass es die vorhandenen Möglichkeiten auszuloten gilt. Die ereg-Funktionen sind kein Ersatz für PCRE. Das ist aber auch nicht nötig, denn PCRE kann auch in einem UTF-8-Modus arbeiten. Dazu gibt es einen Modifier. Ansonsten gibt es einige wenige Funktionen, die auch auf andere Kodierungen Rücksicht nehmen können, wenn man es ihnen per Zusatzparameter mitteilt (htmlentities() beispielsweise, aber diese Funktion will man nicht verwenden, wenn man UTF-8 haben kann. htmlspecialchars() benötigt für ISO-8859-x und UTF-8 keine charset-Angabe, der Default-Modus ISO-8859-1 ist für diese Kodierungen problemlos und unterschiedslos verwendbar).

Mein erstes Problem besteht jetzt schonmal darin, dass mir nicht klar ist, in welcher Kodierung denn nun bspw. ein Request (URI + Query String) auf dem Server überhaupt ankommt, wovon das abhängig ist und wie ich das feststellen kann?

Feststellen, in welcher Kodierung Daten vorliegen, kann man prinzipbedingt nicht. Man kann es höchstens erraten, solange nur wenige Kodierungen eine Rolle spielen. Man kann eine ankommende Bytefolge darauf testen, ob sie die UTF-8-Spielregeln einhält, sprich: ob die Sequenzen der Bytes größer als 0x7f regelgerecht sind. Aber da jegliche Bytefolge auch gültiges ISO-8859-1 sein kann, ist eine eindeutige Erkennung schon daran zum Scheitern verurteilt. Lediglich am interpretierten Inhalt kann man erkennen, ob etwas Sinnvolles rauskommt oder nicht. - Alle Funktionen, die dir eine Zeichenkodierungserkennung versprechen, kochen auch nur mit Wasser und liefern nicht in jedem Fall ein fehlerfreies Ergebnis.

Es ist auch nicht möglich, einem Client die zu verwendende Kodierung vorzuschreiben. Das geht schon deshalb nicht, weil ein Client auch ohne den Server zu kennen, eine Anforderung absenden können muss. Weiterhin gibt es keine Regel, in welcher Kodierung er zu senden hat und auch keinen Header oder dergleichen, in dem der Client dem Server die verwendete Kodierung mitteilt.

Dies stellt aber in der Praxis nicht unbedingt ein Problem dar. Initiale Requests kommen oft mit den ASCII-Zeichen aus. Formulardaten werden vom Client in der Regel in der Kodierung abgesendet, die die das Formular enthaltene Seite deklariert hat. Das accept-charset-Attribut eines Formulars trifft hingegen in der Praxis nicht selten auf taube Ohren.

Kommen die Daten in der URL an, so besteht die Möglichkeit, dass sie ein Mensch eingetippt hat und der Request ein initialier ist. Der Browser verwendet dann seine Default-Einstellung, ohne das dem Server mitteilen zu können. Du kannst nur versuchen, ob die Daten gültiges UTF-8 sind, und wenn nicht, sie von ISO-8859-1 nach UTF-8 umzukodieren und dann zu versuchen, ein Ergebnis für diesen Request zu finden.

Für die UTF-8-"Erkennung" gibt es einige Funktionen in den Userkommentaren bei den üblichen verdächtigen Funktionen (suche bei utf8_decode, utf8_encode, mb_detect_encoding). Sie können aber lediglich die formale Richtigkeit von UTF-8-Sequenzen ermitteln, nicht aber, ob tatsächlich eine UTF-8-Kodierung vom Autor beabsichtig war oder ob die Bytesequenz nur zufällig gültiges UTF-8 ergibt.

Übrigens, den Request allein im Hinblick auf UTF-8-Fähigkeit zu beachten, ist oft noch nicht ausreichend. Auch das Speichern der Daten verlangt eine Betrachtung und damit die dafür verwendeten Medien (Dateien oder Datenbanken). Du kannst ja mal aufzählen, welche Stellen dir im Webumfeld einfallen, an denen eine Zeichenkodierung eine Rolle spielt und eingestellt werden kann. Wir™ schauen dann mal, ob du alle kennst. (Das Nachschlagen im hiesigen Archiv ist nicht nur nicht verboten, sondern ausdrücklich erwünscht :-)

Ein Aufruf von mb_internal_encoding() gibt mir ISO-8859-1 als interne Kodierung aus.
Diese müsste ich, wenn ich durchgehend mit UTF-8 arbeiten will, dann entsprechend umstellen?

Diese Frage konnte das PHP-Handbuch nicht klären?

Stellt sich für mich aber gleich die nächste Frage: Lohnt sich der "Aufwand/ Aufstand" (bei PHP < 6), oder wäre es ggf. sinnvoller/ einfacher, vorhandene Strings in UTF-8 in ISO-8859-1 umzukodieren, diese intern dann "normal" zu verarbeiten und vor einer Ausgabe ggf. wieder in UTF-8 zu kodieren?
Wenn ja, wie stelle ich das so an, dass ich keine Datenverluste/ -verfremdungen erleide und worauf muss ich ggf. achten?

Diese Anforderung kann mit dem Ansinnen, alles nach ISO-8859-1 umzukodieren, nicht erfüllt werden. Mit der ISO-8859-Familie sind jeweils nur 256 Zeichen darstellbar. Mit Unicode hingegen können derzeit 1.114.112 Zeichen repräsentiert werden. Eine verlustfreie Umkodierung kann nur dann stattfinden, wenn nur die 256 ISO-8859-x-Zeichen verwendet werden.

Ob sich der Aufwand lohnt, musst du selbst entscheiden, denn nur du kennst die Anforderungen deines Projekts.

Lo!