12 Stimmen

Wie säubere ich Benutzereingaben auf korrekte Inhaltskodierung, bevor ich sie speichere?

Ich habe eine Anwendung, in der Benutzer Text in Formulare eingeben.

Die Daten werden in einer MySQL-Datenbank gespeichert (collation: utf8_general_ci ) und dann als XML (Kodierung: UTF-8) ausgegeben.

Das Problem ist, dass die Leute dazu neigen, ihre Informationen aus anderen Quellen auszuschneiden und einzufügen, z. B. aus Microsoft Word-Dokumenten oder PDF-Dateien.

Dieser Eingabetext enthält oft Zeichen, die für die Ausgabekodierung nicht korrekt sind, wie z. B. "intelligente Anführungszeichen", die aus einem Dokument in Windows-1252-Kodierung

Dies führt natürlich zu Problemen bei der Umwandlung oder anderweitigen Bearbeitung der XML-Datei, da die Zeichen illegal sind.

Wie kann man also die Eingabe bereinigen?

Zuvor habe ich einige ziemlich brutale Methoden verwendet, z. B. die Skript "de-moronisieren" die aus einer langen Liste von Such- und Ersetzungsoperationen besteht.

Ist das immer noch die beste Methode? Gibt es eine andere Möglichkeit?

Kann ich einfach die accept-charset-Attribut in das Formular einfügen und den Browser dies für mich erledigen lassen?

Wenn ja, mit welchen Browsern ist dies möglich, und sind Probleme zu erwarten?

Wie kommt es außerdem, dass meine Datenbank diese Zeichen akzeptiert, die in UTF-8 reservierte Zeichen/Steuerzeichen sind?

Wie Sie sehen können, weiß ich genug über Kodierungen, um zu wissen, dass ich ein Problem habe, aber ich bin jetzt ein bisschen überfordert...

TIA

9voto

bobince Punkte 512550

Dieser Eingabetext enthält oft Zeichen, die für die Ausgabekodierung nicht korrekt sind, wie z. B. "intelligente Anführungszeichen", die aus einem Dokument in Windows-1252-Kodierung stammen

"Intelligente Anführungszeichen" (Bytes 147 und 148 in cp1252) sind vollkommen gültige Unicode-Zeichen, U+201C und U+201D. Ihre Anwendung sollte in der Lage sein, sie nahtlos zu verarbeiten; wenn nicht, machen Sie etwas falsch und höchstwahrscheinlich werden alle Nicht-ASCII-Zeichen fehlschlagen.

Unabhängig davon, ob die Zeichen von jemandem stammen, der sie eintippt, oder von jemandem, der sie aus Word einfügt, sollte der Browser UTF-8-kodierte Zeichen an Ihre Anwendung übermitteln, die die gleichen UTF-8-Bytes in der Datenbank speichern sollte.

Wenn der Browser nicht in UTF-8 sendet, ist es wahrscheinlich, dass Sie den Zeichensatz der HTML-Seite, die das Formular enthält, nicht eingestellt haben. Dies kann mit der Option:

Content-Type: text/html;charset=utf-8

HTTP-Header und/oder die:

<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />

Element in <head>.

Kann ich einfach das accept-charset-Attribut auf dem Formular setzen und den Browser dies für mich tun lassen?

Nein, accept-charset ist im Grunde nutzlos dank des IE, der es fälschlicherweise so interpretiert, dass es bedeutet "versuche diesen Zeichensatz zu verwenden, wenn der auf der Seite die gewünschten Zeichen nicht kodieren kann", anstatt "verwende immer diesen Zeichensatz". Das bedeutet, wenn Sie accept-charset verwenden, können Sie mit einer Mischung von Kodierungen enden, die auf einmal übermittelt werden, ohne dass Sie herausfinden können, welche die richtige ist. Toll!

Wie kommt es, dass meine Datenbank diese Zeichen akzeptiert, die in UTF-8 reserviert/kontrolliert sind?

In MySQL ist UTF-8 nur eine Sortierreihenfolge, die zum Vergleich und zur Ordnung verwendet wird. Es speichert die Daten immer noch als Bytes und kümmert sich nicht wirklich darum, ob sie keine gültigen UTF-8-Sequenzen sind.

Es ist auf jeden Fall eine gute Idee, eingehende UTF-8-Sequenzen in Ihrer Anwendung zu dekodieren und zu überprüfen, da "kurze Sequenzen", die in modernem Unicode ungültig sind, ein "<"-Zeichen verbergen können, das von älteren Browsern (zumindest IE6 vor SP2, Opera 7) noch erkannt wird.

ETA:

Ich habe also eine Zeichenkette mit Byte 146 eingegeben

Nein, Sie haben ein Unicode-Zeichen U+201B eingegeben. Der Browser arbeitet mit Unicode-Zeichen und nicht mit Bytes, und zwar bis zu dem Punkt, an dem er das serialisierte Formular an den Server übermitteln muss. Erst dann entscheidet er, wie er die Zeichen in Bytes umwandelt, und wenn die Seite als UTF-8 behandelt wird, wählt er immer UTF-8.

(Wenn es sich nicht um UTF-8 handelt, neigen die Browser dazu, auf eine nicht standardkonforme Weise zu schummeln: alle Zeichen, die nicht in die Kodierung passen, werden in HTML-Zeichenreferenzen wie ''' kodiert. Das ist falsch, weil man jetzt nicht mehr zwischen einem vom Browser umcodierten '&' und einem echten, vom Benutzer eingegebenen '&' unterscheiden kann, und es ist heimtückisch falsch, weil es, wenn man den Verweis dann als nicht umcodiertes HTML wiedergibt, so aussieht, als würde man es richtig machen, was in Wirklichkeit nur ein großes altes Sicherheitsloch ist).

Sie wurde in der Datenbank als 146

Wirklich, ein \x92 ' Byte, nicht ' \xC2\x92 ', ' \xE2\x80\x99 ' oder ''?

es kam heraus, als ich die (UTF-8-kodierte) XML-Datei als 146. Keine Beschwerden seitens des Browsers

Dann kam es nicht als ein einziges 146-Byte heraus. Ein Browser wird sich beschweren, wenn er einen bloßen ' \x92 ' in einer XML-Datei. (Nicht in einer HTML-Datei, in der ungültige UTF-8-Sequenzen als fehlende Zeichen angezeigt werden).

Ich vermute, dass es als ''-Zeichenreferenz ausgegeben wird, was wohlgeformt ist (obwohl das Zeichen U+0092 Teil des C1-Steuersatzes ist und daher nicht als etwas Nützliches dargestellt wird). Wenn dies der Fall ist, wird Ihre Formularseite nicht als UTF-8 erkannt, und Sie leiden unter dem oben beschriebenen Problem der automatischen Abschreibung durch den Browser bei der Übermittlung.

2voto

Brian Ferris Punkte 6742

Versuchen Sie es mit dem Perl Verschlüsseln Modul. Es unterstützt die Konvertierung zwischen einer Reihe von Zeichensätzen, darunter natürlich auch UTF-8. Ich habe gerade meine Perl-Installation überprüft und sie unterstützt auch "cp1252", was laut Wikipedia nur ein anderer Name für Windows-1252 ist. Sie können Ihre eigene Installation mit dem folgenden Einzeiler überprüfen:

perl -MEncode -e 'print map {"$_\n"} Encode->encodings(":all");'

1voto

bigiain Punkte 779

"Kann ich einfach das Attribut accept-charset auf dem Formular setzen und den Browser das für mich erledigen lassen?"

Nur, wenn Sie bereit sind, "dem Browser" zu vertrauen - das mag bei einigen Anwendungen sinnvoll sein, aber im Allgemeinen sind Sie damit sehr anfällig für Unfug (oder Schlimmeres).

(Siehe auch bobince's Warnungen über den IE...)

Iain

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X