Ver2felt: Falsch kodierten User-Input "retten"

Hallo Forum,

ich habe ein ziemlich vertracktes Problem in Javascript mit Zeichenkodierungen. Unsere Library behandelt alle Zeichen korrekt, sofern der richtige Zeichensatz gesetzt ist. Jetzt hat sich aber in den Tests mit Benutzern herausgestellt, dass diese die wildesten Kombinationen aus angegebener Kodierung der Webseite (per Meta-Tag) und tatsächlicher Kodierung der Datei produzieren können. Dies soll nun abgefangen werden und "verhindert" werden, bzw. gerettet werden.

Konkret:
Ich habe eine HTML-Datei, die die Skript-Library einbindet und mittels
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
vom DAU auf angeblich UTF-8 kodiert gesetzt wurde. Die HTML-Datei selber ist aber als "ANSI" (laut Texteditor) gespeichert und dementsprechend sind alle Strings falsch kodiert, werden aber im Editor richtig angezeigt.

Sobald ich den String irgendwie analysieren will, werden die ANSI-Zeichen in das Unicode-Zeichen \uFFFD umgewandelt (Replacement Character) und ich habe keine Möglichkeit mehr, an das "wirkliche" Zeichen zu kommen, um es z.B. einer ISO-8859-1-zu-UTF-8-Kodierung zu unterziehen.

Gibt es eine Möglichkeit, in Javascript diese Strings zu retten?

Grüße

  1. Sobald ich den String irgendwie analysieren will, werden die ANSI-Zeichen in das Unicode-Zeichen \uFFFD umgewandelt (Replacement Character)

    Das verstehe ich nicht. an welcher Stelle passiert das? Warum verhinderst du es nihct dort.

    Gibt es eine Möglichkeit, in Javascript diese Strings zu retten?

    Wenn das Zeichen dort gar nicht mehr vorhanden ist, ist das unmöglich.

    Struppi.

    1. Sobald ich den String irgendwie analysieren will, werden die ANSI-Zeichen in das Unicode-Zeichen \uFFFD umgewandelt (Replacement Character)

      Das verstehe ich nicht. an welcher Stelle passiert das? Warum verhinderst du es nihct dort.

      An der Stelle, wo der User meine Funktion aufruft. Ich kann die Eingabe verwerfen und/oder eine Warnung ausgeben, aber die Anforderung lautet dass man es dem DAU so einfach wie möglich machen muss und weil der Editor doch die Zeichen richtig anzeigt, muss das die Library auch können.

      Gruß

      1. Sobald ich den String irgendwie analysieren will, werden die ANSI-Zeichen in das Unicode-Zeichen \uFFFD umgewandelt (Replacement Character)

        Das verstehe ich nicht. an welcher Stelle passiert das? Warum verhinderst du es nihct dort.

        An der Stelle, wo der User meine Funktion aufruft. Ich kann die Eingabe verwerfen und/oder eine Warnung ausgeben, aber die Anforderung lautet dass man es dem DAU so einfach wie möglich machen muss und weil der Editor doch die Zeichen richtig anzeigt, muss das die Library auch können.

        Das verstehe ich jetzt noch weniger, d.h. du wandelst alle ANSI Sonderzeichen in ein Unicodezeichen um und fragst jetzt wie du deine eigene Umwandlung rückängig machen kannst?????

        Struppi.

        1. Das verstehe ich jetzt noch weniger, d.h. du wandelst alle ANSI Sonderzeichen in ein Unicodezeichen um und fragst jetzt wie du deine eigene Umwandlung rückängig machen kannst?????

          Nein, ich mache gar nichts. Javascript wandelt alle Strings automatisch in Unicode um und interpretiert eigentlich alle Kodierungen korrekt. Wenn aber der Fall ist, dass die Kodierung der HTML-Seite falsch angegeben ist, interpretiert Javascript die Eingaben natürlich auch falsch.

          Hierfür benötige ich einen Workaround.

          Gruß

          1. Das verstehe ich jetzt noch weniger, d.h. du wandelst alle ANSI Sonderzeichen in ein Unicodezeichen um und fragst jetzt wie du deine eigene Umwandlung rückängig machen kannst?????

            Nein, ich mache gar nichts. Javascript wandelt alle Strings automatisch in Unicode um und interpretiert eigentlich alle Kodierungen korrekt. Wenn aber der Fall ist, dass die Kodierung der HTML-Seite falsch angegeben ist, interpretiert Javascript die Eingaben natürlich auch falsch.

            Mir ist nach wie vor nicht klar an welcher Stelle die Zeichen umgewandelt werden und an welcher Stelle du Hilfe benötigst. Wenn die Zeichen in ein Formular eingegeben werden, werden sie auch so 1:1 übertragen, d.h. du kannst serverseitig dieses Problem lösen. Was JS an dieser Stelle soll ist mir nicht klar.

            Struppi.

            1. Mir ist nach wie vor nicht klar an welcher Stelle die Zeichen umgewandelt werden und an welcher Stelle du Hilfe benötigst. Wenn die Zeichen in ein Formular eingegeben werden, werden sie auch so 1:1 übertragen, d.h. du kannst serverseitig dieses Problem lösen. Was JS an dieser Stelle soll ist mir nicht klar.

              Aaaalso. Ich habe eine Library, die der User sich herunterlädt und danach entweder lokal oder auf einem Webserver diese Library in seine selbstgeschriebene und von mir nicht kontrollierbare HTML-Seite einbindet.

              Eine Funktion der Library hat auch mit der Übergabe von Strings zu tun, die dann angezeigt werden. Dabei kann es passieren, dass der User eine falsche Kodierung in seiner Datei angibt (über Meta-Tags oder bei XHTML über den XML-Tag), die bei ihm aber richtig "aussieht" weil der Editor z.B. die Datei als ANSI speichert, aber der Tag im Header UTF-8 angibt. Javascript interpretiert nun den String so, wie die Datei angeblich kodiert sein soll laut Header-Tag und nicht, wie sie wirklich kodiert ist.

              Es gibt keine serverseitigen Interaktionen, der User kann die Lib auch komplett offline (nach Download ;) ) benutzen. Mit PHP wüsste ich wie ich das dekodieren oder umwandeln kann, aber da werden auch keine ungültigen Zeichen durch \uFFFD ersetzt.

              1. Eine Funktion der Library hat auch mit der Übergabe von Strings zu tun, die dann angezeigt werden. Dabei kann es passieren, dass der User eine falsche Kodierung in seiner Datei angibt (über Meta-Tags oder bei XHTML über den XML-Tag), die bei ihm aber richtig "aussieht" weil der Editor z.B. die Datei als ANSI speichert, aber der Tag im Header UTF-8 angibt. Javascript interpretiert nun den String so, wie die Datei angeblich kodiert sein soll laut Header-Tag und nicht, wie sie wirklich kodiert ist.

                Ich verstehe worauf du hinaus willst, aber ich verstehe nicht, wie der User es schafft eine falsche Kodierung richtig anzeigen zu lassen. Wenn er die falsche Kodierung nutzt, dann werden auch in JS die falschen Zeichen angezeigt.

                Was meinst du mit interpretiert? Inwiefern muss JS den String interpretieren? Und welche Probleme trene dabei konkret auf?

                Struppi.

                1. Ich verstehe worauf du hinaus willst, aber ich verstehe nicht, wie der User es schafft eine falsche Kodierung richtig anzeigen zu lassen. Wenn er die falsche Kodierung nutzt, dann werden auch in JS die falschen Zeichen angezeigt.

                  Das ist genau das Problem. In Javascript werden die Zeichen falsch angezeigt, da der Browser oder seine JS-Engine oder was auch immer die Datei so interpretiert, wie es im Header angegeben ist (z.B. "utf-8"). Der Benutzer kann die Datei aber (bspw. in Windows Notepad) unabhängig von den HTML-Angaben als ANSI speichern. Das ist natürlich falsch, aber für ihn nicht transparent, sofern er sich nicht vorher schon ausreichend mit Zeichenkodierungen befasst hat. Die meisten User denken leider, der HTML-Meta-Tag würde ausreichen.

                  Was meinst du mit interpretiert? Inwiefern muss JS den String interpretieren? Und welche Probleme trene dabei konkret auf?

                  Na, zunächst ist der String in der Datei ja nur eine Bytefolge. Da die Datei angeblich (wie gesagt, Angabe im HTML-Meta-Tag) UTF-8-kodiert sein soll, versucht er diese auch als UTF-8 zu interpretieren. Jetzt kommt ein ä (z.B. Latin-1-kodiert) als ein Byte mit dem Wert 228 daher. In UTF-8 müssen jetzt zwei weitere Bytes (Wert > 128) folgen, weil ab 224 in UTF-8 die 3-Byte-Unicode-Zeichen kommen. Da aber dahinter etwas anderes, womöglich ein x (ANSI- und UTF-8-Wert 120) folgt, ist dieses Zeichen ungültig und wird leider sofort durch den Unicode-Codepoint \uFFFD (Replacement Character) ausgetauscht, wodurch die Information um welches Byte es sich handelte, verloren gehen.

                  1. So langsam versteh' ich das Problem.

                    Na, zunächst ist der String in der Datei ja nur eine Bytefolge. Da die Datei angeblich (wie gesagt, Angabe im HTML-Meta-Tag) UTF-8-kodiert sein soll, versucht er diese auch als UTF-8 zu interpretieren.

                    Was mir noch nicht klar ist, was du mit interpretieren meinst. Wenn es nur darum geht die Zeichen anzuzeigen, kannst beim einbinden schon eine charset Angabe machen.

                    Also wenn du auf einer utf-8 Seite JS in Ansi einbindest, dann z.b. so:
                    <script src="ansi.js" charset="iso-8859-1"></script>

                    oder umgekehrt, wenn du utf-8 JS in eine mit ISO Kodierte Seite einbindest, dann eben so:
                    <script src="utf8.js" charset="utf-8"></script>

                    Dann werden zumindest die Sonderzeichen richtig angezeigt.

                    Ob dann aber alle String Funktionen ordnungsgemäß funktionieren, hab ich nicht ausprobiert.

                    Das Problem ist aber, dass dein Szenario so klingt, als ob alles passieren kann. Also jegliche denkbare Kombination der Zeichensätze. Und das 100% zu abzudecken dürfte unmmgöich sein.

                    Struppi.

              2. Hi,

                Dabei kann es passieren, dass der User eine falsche Kodierung in seiner Datei angibt (über Meta-Tags oder bei XHTML über den XML-Tag), die bei ihm aber richtig "aussieht" weil der Editor z.B. die Datei als ANSI speichert, aber der Tag im Header UTF-8 angibt.

                “He fuck it up - *he* fix it!”

                Ernsthaft, gegen sowas hilft ausreichende Dokumentation, statt irgendeiner „Magie“, die extrem grobe Fehler, die viel weitreichendere Folgen haben können, als sie den Wirkungsbereich deines Scriptes betreffen, irgendwie automatisch und still und leise zu beheben versucht.

                MfG ChrisB

                --
                RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
              3. Wenn die Kodierung des Dokuments falsch angegeben ist und sich darin ein Methodenaufruf mit einem JavaScript-String befindet, hast du in deinem JavaScript keine Möglichkeit, sie zu fixen. Das passiert alles weit vorher bzw. auf einer Ebene darunter.

                Das Beste, was du in dem Fall machen kannst, ist dem Benutzer eine Warnmeldung geben, dass er doch bitte die Kodierung korrekt angeben kann, damit dein Script vernünftig arbeiten kann. Feststellen, dass er einen Fehler gemacht hat, kannst du ja anhand der Replacement Characters.

                Mathias

                1. Das Beste, was du in dem Fall machen kannst, ist dem Benutzer eine Warnmeldung geben, dass er doch bitte die Kodierung korrekt angeben kann, damit dein Script vernünftig arbeiten kann. Feststellen, dass er einen Fehler gemacht hat, kannst du ja anhand der Replacement Characters.

                  Mathias

                  Ja, das mache ich jetzt auch. Scheint leider echt nicht anders zu gehen. :-(

                  Gruß

  2. Gibt es eine Möglichkeit, in Javascript diese Strings zu retten?

    Warum rettest du es nicht im File selbst?

    btw: Unterscheide zwischen "Umkodieren" und "Kodierung ändern" - im zweiteren Fall hast du ziemlich sicher defekte Zeichen.

    1. Warum rettest du es nicht im File selbst?

      Weil ich keine Kontrolle über das File habe, das der User erstellt. Da der User ein DAU ist, kann die Kodierung falsch sein.

      btw: Unterscheide zwischen "Umkodieren" und "Kodierung ändern" - im zweiteren Fall hast du ziemlich sicher defekte Zeichen.

      Auch wenn ich das \uFFFD "umkodiere" (genau das will ich ja tun) bleibt es ein ungültiges Zeichen. ;)

      1. Warum rettest du es nicht im File selbst?

        Weil ich keine Kontrolle über das File habe, das der User erstellt. Da der User ein DAU ist, kann die Kodierung falsch sein.

        Fehlertolerante JavaScript-Bibliotheken für DAUs schreiben ist letztlich unmöglich. Du kannst höchstens bei Fehlbenutzung abbrechen und auf den Fehler hinweisen. Etwa einen alert anzeigen, auf eine FAQ/Hilfeseite weiterleiten und weitere Tipps geben.

        Mathias

  3. Hi!

    ich habe ein ziemlich vertracktes Problem in Javascript mit Zeichenkodierungen.

    Javascript interessiert sich nicht für Zeichenkodierungen. Es läuft üblicherweise im Browser und es ist seine Aufgabe die Ressourcen passend zu interpretieren.

    Unsere Library behandelt alle Zeichen korrekt, sofern der richtige Zeichensatz gesetzt ist.

    Anzunehmenderweise in den zuständigen HTTP-Headerzeilen der vom Browser zu lesenden Ressource.

    Jetzt hat sich aber in den Tests mit Benutzern herausgestellt, dass diese die wildesten Kombinationen aus angegebener Kodierung der Webseite (per Meta-Tag) und tatsächlicher Kodierung der Datei produzieren können. Dies soll nun abgefangen werden und "verhindert" werden, bzw. gerettet werden.

    Wo auch immer die Ressource herkommt, der Browser muss sie zunächst lesen. Dabei gibt es eingebaute Mechanismen, die zuerst die Zeichenkodierung aus den offiziellen Angaben zu entnehmen versuchen und anschließend raten. Außerdem kann man oft noch händisch die Kodierung wählen. Wenn du allerdings aufgrund von Mechanismen beim "Einlesen" (wie auch immer das stattfindet) gar nicht händisch umstellenkannst, ist alles zu spät.

    Gibt es eine Möglichkeit, in Javascript diese Strings zu retten?

    Serverseitige Verarbeitung steht nicht zur Verfügung? Die könnte die Bytes einzeln lesen und wie auch immer interpretieren, was Javascript von Haus aus nicht kann.

    Lo!

    1. Wo auch immer die Ressource herkommt, der Browser muss sie zunächst lesen. Dabei gibt es eingebaute Mechanismen, die zuerst die Zeichenkodierung aus den offiziellen Angaben zu entnehmen versuchen und anschließend raten. Außerdem kann man oft noch händisch die Kodierung wählen. Wenn du allerdings aufgrund von Mechanismen beim "Einlesen" (wie auch immer das stattfindet) gar nicht händisch umstellenkannst, ist alles zu spät.

      Das befürchte ich leider auch. Dann muss der User halt die Kodierung korrigieren und ich kann ihn nur durch eine Fehlermeldung darauf hinweisen.

      Serverseitige Verarbeitung steht nicht zur Verfügung? Die könnte die Bytes einzeln lesen und wie auch immer interpretieren, was Javascript von Haus aus nicht kann.

      Nein, die Library läuft vollkommen autark im Browser. Kein AJAX o.ä.

      1. Hi!

        Serverseitige Verarbeitung steht nicht zur Verfügung? Die könnte die Bytes einzeln lesen und wie auch immer interpretieren, was Javascript von Haus aus nicht kann.
        Nein, die Library läuft vollkommen autark im Browser. Kein AJAX o.ä.

        Ajax wäre auch nicht die Lösung, denn das muss auch durch den Browser, bevor es bei Javascript ankommt, sondern ein normaler Upload zu einem Server, der zumindest ein paar Anzeichen von falscher Kodierung prüfen kann. Denn prinzipiell ist es nicht möglich, aus allen Texten zweifelsfrei die Kodierung zu erraten.

        Lo!