Saboteur: Kodierungsprobleme...

Hallo Leute,

ich bin verzweifelt, ich kann keine vernünftige Lösung meines Problems finden, nur Workarounds..

Ich arbeite jetzt mit dem folgenden Modell:
die Daten zwischen dem Server und Client werden mit Hilfe von JSON ausgetauscht. Auf der Serverseite wird JSON mit PHP-Funktion json_encode() erzeugt, auf der Clientseite mit einem Javascriptobjekt, das unter http://www.devpro.it/JSON/files/JSON-js.html zu finden ist. Die ganze Seite wird aus mehreren Gründen im UTF-8 Kontext dargestellt. Als Framework benutze ich jQuery.

Die Formulardaten bekomme ich mit der Funktion:

  
function processForm(objectID, action) {  
 var data = new Object;  
 $('#'+objectID).find('input').each(function() {  
  if (this.type != 'button') {  
   if (this.type == 'checkbox') {  
    data[this.name] = this.checked;  
   } else data[this.name] = this.value;  
  }  
 });  
 $('#'+objectID).find('select').each(function() {  
  data[this.name] = this.value;  
 });  
 $('#'+objectID).find('textarea').each(function() {  
  data[this.name] = this.value;  
 });  
 data['object'] = objectID;  
 data['action'] = action;  
  
 for (var property in data) {  
  if (typeof(data[property]) == 'string') {  
   data[property] = utf8_encode(data[property]);  
  }  
 }  
  
 var requestData = new Object;  
 requestData['json'] = JSON.encode(data);  
 requestData['location'] = 'form';  
  
 postData(requestData)  
}  

Und jetzt kommt das Problem. Falls ich diese Funktion ohne utf8_encode im IE verwende (das war die ursprüngliche Variante)

  
for (var property in data) {  
 if (typeof(data[property]) == 'string') {  
  data[property] = utf8_encode(data[property]);  
 }  
}  

und nicht typische Zeichen, wie Umlaute und kyrillische Buchstaben im Formular eingebe wird das JSON-Objekt auf der Serverseite nicht geparst. Funktion json_decode interpretiert es, als ungültiges JSON. Merkwürdigerweise funktioniert alles im Firefox einwandfrei.

Wenn ich versuche die Formulardaten einzukodieren (aus meiner Sicht ist es nicht logisch, da die Seite schon im UTF-8 Kontext dargestellt wird und daher müssen alle Eingaben auch einkodiert sein), funktioniert es im IE mit machen Zeichen, wie "ü" gut und mit anderen, wie "Ü" wieder nicht. Im Firefox wird JSON in allen Fällen interpretiert, aber die Rückwerte werden unlesbar.

Ein paar Beispiele, die tatsächliche Zeichen werden mit Charcodes ersetzt, da ser automatische Filter von selfhtml sie leider nicht durchläßt.

  
1) Firefox mit utf8_encode.  
  
Eingabe: üüüü  
JSON: {reason":"üüüü"}  
Rückwert: üüüü  
  
Eingabe: ÜÜÜÜ  
JSON:{"reason":"Ã Ã Ã Ã "}  
Rückgabe: Ã Ã Ã Ã   
  
2) IE mit utf_encode.  
  
Eingabe: üüüü  
JSON:  
{"reason":"üüüü"}  
Rückgabe: üüüü  
  
Eingabe: ÜÜÜÜ  
JSON:{"reason":"Ã Ã Ã Ã "}  
Rückgabe: JSON wird nicht interpretiert  
  
3) Firefox ohne utf8_encode.  
  
Funktioniert alles.  
  
4) IE ohne utf8_encode.  
  
Falls man untypische Zeichen eingibt, wird JSON nicht interpretiert.  

Die funktion utf8_encode für Javascript wurde aus selfhtml.org entnommen. Ich teste meine Anwendung nur mit den letzten Versionen von Firefox 3 und Explorer 7.

Wo kann das Problem sein?

  1. echo $begrüßung;

    ich bin verzweifelt, ich kann keine vernünftige Lösung meines Problems finden, nur Workarounds..

    Dann liegt es wohl tiefer als du annimst.

    Die ganze Seite wird aus mehreren Gründen im UTF-8 Kontext dargestellt.

    UTF-8 ist schon mal nicht verkehrt, wenn man AJAX macht. Allerdings ist UTF-8 kein Kontext sondern eine Kodierung wie beispielsweise ISO-8859-1 oder ASCII. Wenn UTF-8 wirklich durchgängig und korrekt deklariert verwendet wird, sollte es damit auch kein Problem geben.

    Du musst dir an jeder Stelle im Klaren sein, welche Kodierung vorliegt. Das betrifft die Verarbeitung in den Systemen selbst und die Kommunikation zwischen zweien. Wenn Unklarheiten bestehen, sollte man denen auf soweit auf den Grund gehen, dass man sich die Bytes möglichst direkt ansieht, ohne dass irgend ein System bei der Darstellung (fehl-)interpretierenderweise das Kontrollausgabeergebnis verfälscht.

    Und jetzt kommt das Problem.

    Das ganze System ist ja schon recht komplex geworden. Versuch doch mal, die Komplexität zu verringern und von vorn im Kleinen anzufangen, und mit so wenig wie möglich Code das Problem nachzustellen, bzw. das System so aufzusetzen, dass das Problem gar nicht erst auftritt.

    Wenn ich versuche die Formulardaten einzukodieren (aus meiner Sicht ist es nicht logisch, da die Seite schon im UTF-8 Kontext dargestellt wird und daher müssen alle Eingaben auch einkodiert sein),

    Eine Kodierung ist immer vorhanden, die Frage ist nur: welche? "Einkodieren" gibt es nicht, höchstes Umkodieren von einer Kodierung in eine andere (im Fehlerfall möglicherweise auch nur eine, dafür vielleicht doppelt angewendet).

    Ein paar Beispiele, die tatsächliche Zeichen werden mit Charcodes ersetzt, da ser automatische Filter von selfhtml sie leider nicht durchläßt.

    Eingabe: üüüü
    JSON: {reason":"üüüü"}
    Rückwert: üüüü

    195-188 oder C3-BC in Hex ist ein ü. Soweit so gut.

    Eingabe: ÜÜÜÜ
    JSON:{"reason":"Ã Ã Ã Ã "}
    Rückgabe: Ã Ã Ã Ã 

    195-32 oder C3-20 in Hex ist keine gültige UTF-8-Sequenz.

    Falls man untypische Zeichen eingibt, wird JSON nicht interpretiert.

    Mit untypisch meinst du vermutlich Zeichen außerhalb von ASCII.

    Die funktion utf8_encode für Javascript wurde aus selfhtml.org entnommen. Ich teste meine Anwendung nur mit den letzten Versionen von Firefox 3 und Explorer 7.

    Schon seit einigen Jahren und damit auch frühere Versionen kommen im Allgemeinen mit der Zeichenkodierung gut zurecht, wenn sie denn ordentlich ausgezeichnet ist.

    Wo kann das Problem sein?

    Wenn du den Weg des kleinstmöglichen Nachbauens nicht gehen willst, dann solltest du zumindest einige der üblichen Tools und Hilfsmittel verwenden, um Klarheit in das jetzige Verhalten zu bringen.

    Übliche Verdächtige sind

    • die Content-Type-Header der HTTP-Kommunikation, für deren Überwachung sich die livehttpheaders-Erweiterung im Firefox gut eignet. Für den IE wird es sowas sicher auch geben. Wenn du es aber das System einmal korrekt aufgesetzt hast, sollte es keine Unterschiede zwischen den Browsern mehr geben.
    • unter PHP bin2hex(), um sich Bytewerte auszugeben. (echo chunk_split(bin2hex($delinquent), 2, ' '); zur übersichtlicheren Darstellung)
    • Hexeditoren oder Hexdumps für Werte in Dateien (auch in Quellcode).

    Versuche auch eine Kommunikation ohne AJAX und JSON, dann JSON-kodiert, dann AJAX dazu. Jeweils immer mit den gleichen Beispieldaten, die auch mal Zeichen außerhalb von ISO-8859-1 enthalten.

    echo "$verabschiedung $name";

  2. Moin!

    ich bin verzweifelt, ich kann keine vernünftige Lösung meines Problems finden, nur Workarounds..

    Du mischst ein wenig zuviel alle möglichen Dinge durcheinander. Daran wird die meiste Verwirrung liegen. Ich sehe jQuery (das ist nicht schlecht), eine separate JSON-Funktion, irgendwelches UTF-8-Geskripte eines uralten SELFHTML-Artikels (das du unangenehmerweise nicht verlinkt hast) - insgesamt eine Mischung von Skripten, vermengt mit gewissen Wissenslücken über das Encoding an sich.

    die Daten zwischen dem Server und Client werden mit Hilfe von JSON ausgetauscht. Auf der Serverseite wird JSON mit PHP-Funktion json_encode() erzeugt, auf der Clientseite mit einem Javascriptobjekt, das unter http://www.devpro.it/JSON/files/JSON-js.html zu finden ist. Die ganze Seite wird aus mehreren Gründen im UTF-8 Kontext dargestellt. Als Framework benutze ich jQuery.

    Worum gehts genau? jQuery bietet eine Vielzahl von Erweiterungen für so ziemlich jeden Einsatzzweck - das AJAX-Absenden eines Formulars gehört mit zu den einfachsten Übungen, die man sich hinzuaddieren kann.

    AJAX arbeitet übrigens immer mit UTF-8. Wobei die Strings in Javascript grundsätzlich unicode-enthaltende Strings sind, das Ajax-Objekt wandelt diese beim Senden zum Server automatisch in UTF-8-Bytes um.

    Umgekehrt wird die Encoding-Angabe des Servers zwar respektiert, aber mit UTF-8 an dieser Stelle ist man ebenfalls auf der sicheren Seite.

    Insofern kann ich aus meiner Erfahrung heraus nicht sehen, wozu du eine UTF-8-Codierfunktion in Javascript benötigst.

    Der Nutzen einer JSON-Dekodierfunktion könnte sich angesichts eventueller Risiken noch stellen - allerdings bietet sich auch hier für jQuery ein passendes Plugin an, sofern du das schlichte eval() vermeiden möchtest - wobei eval() für JSON besser ist, als sein Ruf, bzw. Alternativen hierzu kaum etwas gewinnen, solange man nichts gegen AJAX-Hijacking tut (siehe [linkhttp://www.fortify.com/advisory.jsp]).

    Ein paar Beispiele, die tatsächliche Zeichen werden mit Charcodes ersetzt, da ser automatische Filter von selfhtml sie leider nicht durchläßt.

    Das Forum hier erlaubt sämtliche erlaubten Unicode-Zeichen. Wenn dein Posting mit den Originalzeichen nicht durchgeht, dann liegt das daran, dass du ungültige Unicode-Zeichen verwenden wolltest. Und das wiederum deutet für meine Begriffe recht eindeutig auf das Problem: Falsche Unicode-Produktion.

    Die funktion utf8_encode für Javascript wurde aus selfhtml.org entnommen. Ich teste meine Anwendung nur mit den letzten Versionen von Firefox 3 und Explorer 7.

    Wie oben erwähnt: Ein Link zu der von dir gefundenen Funktion wäre nett. Falls du den Artikel um [linkhttp://aktuell.de.selfhtml.org/artikel/javascript/utf8b64/utf8.htm#a4] herum meinst: Vergiß ihn. Das Teil ist sieben Jahre alt, und es stecken einige Verständnisfehler drin, beispielsweise die (mittlerweile, weil es UTF-8-fähige Editoren gibt) unkorrekte Idee, Editoren müßten UTF-8-Zeichen immer als zwei (oder mehr) seltsame Hieroglyphen anzeigen.

    Der Artikel steht sozusagen auf der Abschußliste - ich schicke ihn nur deshalb noch nicht in den Ruhestand, weil ich ihn hier nochmal verlinkt habe.

    - Sven Rautenberg

    --
    "Love your nation - respect the others."
    1. Danke für die Antwort! Ich habe schon das Problem gelöst. Ich habe nach dem Problem in dem Quellcode gesucht, da ich 100% sicher war, dass die Datenbank auf UTF-8 eingestellt ist. Leider war das nicht der Fall, die Daten waren in latin1 Kodierung, was ein Teil des Problems war.

      Worum gehts genau? jQuery bietet eine Vielzahl von Erweiterungen für so ziemlich jeden Einsatzzweck - das AJAX-Absenden eines Formulars gehört mit zu den einfachsten Übungen, die man sich hinzuaddieren kann.

      Alles ist nicht so einfach. ) Ich kann keine AJAX-Funktioinen aus JQuery benutzen, da sie sich auf HTTPRequestObject oder auf ActiveX-Object basieren. IE7 hat Probleme mit HTTPRequestObject und die Anwendung wird in dem Netzwerk benutzt, wo ActiveX aus Sicherheitsgründen ausgeschaltet ist. Ich verwende einen hidden iframe, um alle AJAX-Funktionen zu realisieren.

      Wenn du eine jQuery-Erweiterung kennst, die sowas realisiert, sage mir bitte  Bescheid.

      Ich habe auch die richtigen Header im iFrame gesetzt, so dass die Kodierung der Serverantwort richtig interpretiert wurde. Der falsche Header war der zweite Teil des Problems.

      Der Nutzen einer JSON-Dekodierfunktion könnte sich angesichts eventueller Risiken noch stellen - allerdings bietet sich auch hier für jQuery ein passendes Plugin an, sofern du das schlichte eval() vermeiden möchtest - wobei eval() für JSON besser ist, als sein Ruf, bzw. Alternativen hierzu kaum etwas gewinnen, solange man nichts gegen AJAX-Hijacking tut (siehe [linkhttp://www.fortify.com/advisory.jsp]).

      »»

      Danke für einen Tipp!!!

      Wie oben erwähnt: Ein Link zu der von dir gefundenen Funktion wäre nett. Falls du den Artikel um [linkhttp://aktuell.de.selfhtml.org/artikel/javascript/utf8b64/utf8.htm#a4] herum meinst: Vergiß ihn. Das Teil ist sieben Jahre alt, und es stecken einige Verständnisfehler drin, beispielsweise die (mittlerweile, weil es UTF-8-fähige Editoren gibt) unkorrekte Idee, Editoren müßten UTF-8-Zeichen immer als zwei (oder mehr) seltsame Hieroglyphen anzeigen.

      Genau diesen Artikel meinte ich. Ich verwende jetzt gar keine utf8_encode Funktion in JavaScript. Das war wirklich unnötig.

      MfG,
      Serge.