johny7: mysql real escape wandelt nicht in utf8 um

Moin allerseits,

Wenn ich Sonderzeichen in der URL habe und die Variablen durch mysql_real_escape_string() schicke, werden trotzdem nicht-UTF Zeichen in die Datenbank geschrieben. Ich dachte,die Eingaben werden automatisch in UTF8 umgewandelt...
Wenn ich Text per POST schicke, funktioniert das mit mysql_real_escape. Aber wenn ich zum Beispiel ?user=Halöle aufrufe, dann wird der UMlaut in der Datenbank nicht richtig gespeichert.

Ich habe das jetzt so gelöst, dass alle Daten, die per URL kommen und Sonderzeichen enthalten können anschließend noch utf8_encode() durchlaufen.
Aber ist das so alles korrekt oder habe ich irgendwo ein Konzeptionsfehler?

Grüße, JN

--
ie:{ fl:( br:^ va:| ls:[ fo:| rl:? n4:? ss:| de:] js:| ch:? sh:( mo:| zu:)
http://www.johny7.de
  1. Hi!

    Wenn ich Sonderzeichen in der URL habe und die Variablen durch mysql_real_escape_string() schicke, werden trotzdem nicht-UTF Zeichen in die Datenbank geschrieben. Ich dachte,die Eingaben werden automatisch in UTF8 umgewandelt...

    Nein. Diese Funktion beachtet nur eine mit mysql_set_charset() eingestellte Kodierung beim Interpretieren der übergebenen Daten. Allerdings sind alle behandelten Zeichen im ASCII-Bereich und damit ist die eingestellte Kodierung (im Falle von ISO-8859-x und UTF-8) nicht mehr wichtig.

    Eine Zeichenumkodierung findet potentiell nur auf dem MySQL-Server selbst statt, die mysql(i)_*-Funktionen machen in der Hinsicht nichts. Welche Kodierung der Server zu erwarten hat, kann man ihm mit der erwähnten Funktion mysql(i)_set_charset() oder einem SET-NAMES-Statement mitteilen.

    Wenn ich Text per POST schicke, funktioniert das mit mysql_real_escape. Aber wenn ich zum Beispiel ?user=Halöle aufrufe, dann wird der UMlaut in der Datenbank nicht richtig gespeichert.

    Das ist ein anderes Problem und hat nichts mit dem DBMS zu tun, sondern mit der Kommunikation zwischen Browser und Webserver. Wenn ein Formular abgesendet wird, orientiert sich der Browser bei der Kodierung der Zeichen an der Kodierung der Seite, in der das Formular enthalten war. Mit dem Attribut accept-charset des form-Elements kann man gezielt festlegen, welche Kodierung man wünscht, aber das behandeln nicht alle Browser wie vorgesehen.

    Wenn Daten in die URL direkt eingegeben werden, hat der Browser keinen Anhaltspunkt, welche Kodierung er verwenden soll. Er hat keine Response vorliegen, die irgendeinen Bezug zu der Eingabe hat, an der er sich orientieren könnte. Er kann auch nicht vorab den Server befragen, welche Kodierung er zu dieser URL gern hätte, denn die Eingabe gehört schließlich zur URL und eine andere Zeichenkodierung ergibt eine andere URL. Es gibt auch keinen Standard, der da was regelt. Das heißt, du musst theoretisch mit allen Zeichenkodierungen rechnen.

    Ich habe das jetzt so gelöst, dass alle Daten, die per URL kommen und Sonderzeichen enthalten können anschließend noch utf8_encode() durchlaufen.
    Aber ist das so alles korrekt oder habe ich irgendwo ein Konzeptionsfehler?

    Nein, das ist in einigen Fällen korrekt, aber nicht für alle Browser und alle Konfigurationen. Es ist auch nicht zweifelsfrei möglich, aus einem String die Kodierung abzuleiten. Lediglich einige Indizien kann man mit einer Restfehlerquote auswerten.

    • Enthält der String Bytes oberhalb von 0x7F und ergeben diese gültige UTF-8-Sequenzen, so liegt vermutlich UTF-8 vor.
    • Ergeben diese Bytes keine gültigen UTF-8-Sequenzen, liegt anzunehmenderweise ISO-8859 vor. Bei einem Publikum vorzugsweise aus dem westlichen Kulturkreis wird das dann ISO-8859-1 und seltener -15 sein. Auch Windows-1252 kommt in Frage, was eine Erweiterung von ISO-8859-1 darstellt. Da Latin1 im MySQL-Server aber effektiv Windows-1252 ist, spielt der Unterschied keine Rolle.
    • Bei Zeichen unterhalb von 0x80 ist es ASCII und damit sowohl gültiges UTF-8 als auch ISO-8859-1/Win-1252.

    Lo!

    1. Hi!

      Achja, ich hab da mal angefangen das Zusammenspiel in puncto Zeichenkodierungen aller Komponenten im Webumfeld zu beleuchten: http://wiki.selfhtml.org/wiki/Themen:Zeichencodierung

      Lo!

    2. Moin allerseits,

      [...] Ich dachte,die Eingaben werden automatisch in UTF8 umgewandelt...

      Nein. Diese Funktion beachtet nur eine mit mysql_set_charset() eingestellte Kodierung beim Interpretieren der übergebenen Daten. Allerdings sind alle behandelten Zeichen im ASCII-Bereich und damit ist die eingestellte Kodierung (im Falle von ISO-8859-x und UTF-8) nicht mehr wichtig.

      Eine Zeichenumkodierung findet potentiell nur auf dem MySQL-Server selbst statt, die mysql(i)_*-Funktionen machen in der Hinsicht nichts. Welche Kodierung der Server zu erwarten hat, kann man ihm mit der erwähnten Funktion mysql(i)_set_charset() oder einem SET-NAMES-Statement mitteilen.

      Aha. Ja, SET NAMES ist vorhanden...

      Wenn ich Text per POST schicke, funktioniert das mit mysql_real_escape.

      Das ist ein anderes Problem und hat nichts mit dem DBMS zu tun, sondern mit der Kommunikation zwischen Browser und Webserver. Wenn ein Formular abgesendet wird, orientiert sich der Browser bei der Kodierung der Zeichen an der Kodierung der Seite, in der das Formular enthalten war. Mit dem Attribut accept-charset des form-Elements kann man gezielt festlegen, welche Kodierung man wünscht, aber das behandeln nicht alle Browser wie vorgesehen.

      Alles klar.

      Wenn Daten in die URL direkt eingegeben werden, hat der Browser keinen Anhaltspunkt, welche Kodierung er verwenden soll. Er hat keine Response vorliegen, die irgendeinen Bezug zu der Eingabe hat, an der er sich orientieren könnte. Er kann auch nicht vorab den Server befragen, welche Kodierung er zu dieser URL gern hätte, denn die Eingabe gehört schließlich zur URL und eine andere Zeichenkodierung ergibt eine andere URL. Es gibt auch keinen Standard, der da was regelt. Das heißt, du musst theoretisch mit allen Zeichenkodierungen rechnen.

      Das heißt, alle URL-Angaben werden erstmal als ASCII interpretiert?

      Nein, das ist in einigen Fällen korrekt, aber nicht für alle Browser und alle Konfigurationen. Es ist auch nicht zweifelsfrei möglich, aus einem String die Kodierung abzuleiten.

      Diese URL kommt von einer anderen Website, die die gegebene Website aufruft. Ich kann auf der anderen Seite einstellen, wie die URL aus zu sehen hat. Kann ich das gleich so einstellen, dass eine utf8-Kodierung vorliegt?

      Grüße, JN

      --
      ie:{ fl:( br:^ va:| ls:[ fo:| rl:? n4:? ss:| de:] js:| ch:? sh:( mo:| zu:)
      http://www.johny7.de
      1. Hi,

        Das heißt, alle URL-Angaben werden erstmal als ASCII interpretiert?

        Nein.
        Aktuelle Browser sind idR. so eingestellt, dass sie nicht korrekt kodierte URLs (Verlinkungen, Direkteingaben) als UTF-8 kodieren, bevor sie den Request absenden.

        Diese URL kommt von einer anderen Website, die die gegebene Website aufruft. Ich kann auf der anderen Seite einstellen, wie die URL aus zu sehen hat. Kann ich das gleich so einstellen, dass eine utf8-Kodierung vorliegt?

        Natürlich.
        Verwende die richtige Zeichenkodierung, und kümmere dich um die URL-gerechte Kodierung.

        MfG ChrisB

        --
        RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
        1. Hi!

          Das heißt, alle URL-Angaben werden erstmal als ASCII interpretiert?
          Nein.
          Aktuelle Browser sind idR. so eingestellt, dass sie nicht korrekt kodierte URLs (Verlinkungen, Direkteingaben) als UTF-8 kodieren, bevor sie den Request absenden.

          Mein aktueller Firefox hat diese Default-Einstellungen:

          network.standard-url.encode-query-utf8 = false
          network.standard-url.encode-utf8 = true

          Das heißt, dass der Query-String schonmal nicht UTF-8-kodiert ist. Was es stattdesen ist, lässt sich zumindest nicht mit Einstellungen, die "encod" im Namen haben festlegen. Anscheinend auch nicht mit "charset"-Angaben.

          Lo!