Kalle_B: Problem mit Umlauten in URL- Parametern

Hallöle,

für eine aufzurufende Seite gebe ich die Seitenüberschrift als URL- Parameter mit, sie enthält Umlaute:
<a href='index.php?zp=p591&amp;ort_id=9669,9671,9674,9219,9216&amp;titel=Was ist los im Weschnitztal?&amp;utitel=F&uuml;rth, Rimbach, M&ouml;rlenbach, Birkenau, Weinheim'>hier</a>

Konzentrieren wir uns mal auf den utitel. In der Adresszeile der aufgerufenen Seite sieht der so aus:
&utitel=F%FCrth,%20Rimbach,%20M%F6rlenbach,%20Birkenau,%20Weinheim

Die Seite liest den utitel so ein:
$utitel = urldecode($_POST['utitel']);

Das bedeutet wohl, dass aus dem ursprünglichen &uuml; nun ein ü geworden ist, problematisch für die Anzeige auf einer UTF-8 codierten Seite. Es sieht so aus:
F�rth, Rimbach, M�rlenbach, Birkenau, Weinheim

Deshalb muss ich für die Ausgabe also wieder codieren:
$utitel = htmlentities( $utitel, ENT_QUOTES, 'UTF-8' );

Doch die Anzeige bleibt
F�rth, Rimbach, M�rlenbach, Birkenau, Weinheim

Wo ist mein Denkfehler?

MfG Kalle

  1. habe nun diverse Kombinationen ausprobiert und den Verdacht, dass htmlentities nicht so funktionert, wie auf Seite http://de2.php.net/html_entities versprochen:

    "Wandelt alle geeigneten Zeichen in entsprechende HTML-Codes um"

    Umlaute sind wohl keine geeigneten Zeichen?

    Kalle

    1. habe den Verdacht, dass htmlentities nicht so funktionert, wie auf Seite http://de2.php.net/html_entities versprochen:

      "Wandelt alle geeigneten Zeichen in entsprechende HTML-Codes um"

      So ist es, wenn ich dieses tue:
      $utitel = str_replace( 'ü', '&uuml;', $utitel );

      wird angezeigt:
      Fürth, Rimbach, M�rlenbach, Birkenau, Weinheim

      Komisch, sogar die Beispiele zu htmlentities suggerieren, dass Umlaute gewandelt werden.

      Kalle

      1. echo $begrüßung;

        habe den Verdacht, dass htmlentities nicht so funktionert, wie auf Seite http://de2.php.net/html_entities versprochen:
        "Wandelt alle geeigneten Zeichen in entsprechende HTML-Codes um"

        Ich habe eher den Verdacht, dass du dir nicht im Klaren bist, wann du welche Kodierung vorliegen hast, und diverse Kodierungen bei dir bunt gemischt auftreten. Versuch erst einmal darüber Klarheit zu bekommen.

        echo "$verabschiedung $name";

  2. Moin!

    &utitel=F%FCrth,%20Rimbach,%20M%F6rlenbach,%20Birkenau,%20Weinheim

    Die Seite liest den utitel so ein:
    $utitel = urldecode($_POST['utitel']);

    Mich wundert, dass du da urldecode() einsetzt. Diesen Schritt erledigt PHP schon.

    Relevant ist dann, was übergeben wurde. Und das sind ganz eindeutig (%FC sagt es) Umlaute in ISO-8859-1-Codierung, nicht UTF-8.

    Das bedeutet wohl, dass aus dem ursprünglichen &uuml; nun ein ü geworden ist, problematisch für die Anzeige auf einer UTF-8 codierten Seite. Es sieht so aus:
    F�rth, Rimbach, M�rlenbach, Birkenau, Weinheim

    Was ja kein Wunder ist.

    URL-Codierung des UTF-8-Strings wäre ratsam.

    Deshalb muss ich für die Ausgabe also wieder codieren:
    $utitel = htmlentities( $utitel, ENT_QUOTES, 'UTF-8' );

    Du mußt IMMER codieren. Und zwar entsprechend des Kontextes der Ausgabesituation. Oft auch mehrfach.

    Ich habe allerdings das Gefühl, dass du nicht alle deine Schritte hier angegeben hast, oder du hast dich mißverständlich ausgedrückt. Kannst du da nochmal Klarheit schaffen für den Weg, den dein Umlautstring nimmt?

    - Sven Rautenberg

    --
    "Love your nation - respect the others."
    1. Moin, Sven!

      die Seite http://remso.de/weschnitztal.htm ist UTF-8 kodiert und leitet nur weiter, weil die gewünschte cryptische Eingabe keinem User zuzumuten ist. Zum Test habe ich die Weiterleitung von 0 auf 5 sec gesetzt.

      Trotz UTF-8 wird das Wort F%FCrth übergeben, also ISO-8859-1, das hat mich irritiert. Firefox ignoriert die Zeile
      <meta http-equiv="content-type"     content="text/html;charset=UTF-8">
      Wie kann ich per HTML- Datei sagen, dass ich UTF-8 möchte?

      Das aufgerufene PHP- Folgeprogramm enthält u.a. diese Zeilen:

      @mysql_query( "SET NAMES 'utf8'", $conn_id );
      ...
      $utitel = $_POST['utitel'];
      ...
      header('content-type: text/html; charset=utf-8');
      ...
      $_ue   = array( 'ä', 'ö', 'ü', 'ß', 'Ä', 'Ö', 'Ü', '€' );
      $_uuml = array( '&auml;', '&ouml;', '&uuml;', '&szlig;', '&Auml;', '&Ouml;', '&Uuml;', '&euro;' );
      echo str_replace( $_ue, $_uuml, $arr['utitel'] );

      so funktioniert's im Firefox (F%FCrth) und IE (Fürth), aber kompatibel sieht das nicht aus.

      LG Kalle

      1. echo $begrüßung;

        die Seite http://remso.de/weschnitztal.htm ist UTF-8 kodiert und leitet nur weiter, [...]

        Die Seite hat zwar ein Meta-Element mit einem Content-Type inklusive charset-Angabe, der UTF-8 sagt. Doch der Server sendet einen ebensolchen HTTP-Header, in dem er ISO-8859-1 angibt. Diese Angabe hat Vorrang vor dem Meta-Element. Korrigieren kannst du das in der Server-Konfiguration oder indem du einen eigenen HTTP-Header für den Content-Type sendest. Zum Prüfen der Header eignet sich die Firefox-Extension livehttpheaders.

        Das aufgerufene PHP- Folgeprogramm enthält u.a. diese Zeilen:
        header('content-type: text/html; charset=utf-8');

        Dann ignoriert der Server diese Zeile anscheinend bzw. lässt ein Überschreiben nicht zu.

        echo "$verabschiedung $name";

      2. Moin!

        die Seite http://remso.de/weschnitztal.htm ist UTF-8 kodiert

        Nein, ist sie nicht.

        Weder sagt der Server, dass sie das ist, noch stehen dort, wo Umlaute sind, UTF-8-Bytes drin.

        Das ist alles reines ISO-8859-1.

        Abgesehen davon ist interessant, dass die Meta-Weiterleitung mit den Entities falsch weiterleitet, der Link ohne Entities korrekt.

        Und dass keine von beiden URLs korrekt url-encodiert ist! Leerzeichen haben in URLs nix verloren.

        Trotz UTF-8 wird das Wort F%FCrth übergeben, also ISO-8859-1, das hat mich irritiert. Firefox ignoriert die Zeile
        <meta http-equiv="content-type"     content="text/html;charset=UTF-8">
        Wie kann ich per HTML- Datei sagen, dass ich UTF-8 möchte?

        Gar nicht, wenn der Server was anderes sagt.

        Das aufgerufene PHP- Folgeprogramm

        Dann ist es zu spät.

        URLs sind leider, was die Auszeichnung des verwendeten Encodings angeht, ganz schlecht aufgestellt. Jede Webseite kann per Meta-Element und HTTP-Header das verwendete Encoding mitteilen - URLs können das nicht.

        Der einzige Teil einer URL, bei dem das Encoding festgelegt ist, ist der Domainteil. Das DNS-System schert sich nur um einen kleinen Teil von ASCII, nämlich a-z, 0-9 und '-' - und wenn Sonderzeichen ins Spiel kommen (Stichwort "Umlautdomains"), ist festgelegt, dass Unicode als Encoding-Basis verwendet wird, und nach einem festen Schema wird daraus wieder DNS-kompatibles ASCII gemacht.

        Der Rest der URL ist frei definierbar, bzw. genauer gesagt: Es ist Serversache. Und damit Vereinbarungssache. Deshalb sind Sonderzeichen in URLs nach Möglichkeit zu vermeiden - mindestens im Pfad und Dateinamen. Denn hier spielt ziemlich viel Zeugs rein, welches zu unerwarteten Unverträglichkeiten führen kann. Ich will nicht zu sehr ins Detail gehen, aber angenommen, eine Datei heißt "tüll.php" - welches Encoding wird für das Ü genommen? Hängt davon ab, was das Dateisystem des erstellenden Rechners nimmt. Was passiert mit dem Ü beim FTP-Transfer auf den Produktivserver? Wie interpretiert der Server das Ü in der URL? Paßt diese Interpretation zum Encoding des Dateisystems? Und so weiter...

        Lediglich als URL-Parameter hat man das Problem eines eventuell dahinterliegenden unverträglichen Dateisystems nicht, das ist alles komplett Sache des HTTP-Servers bzw. des auswertenden Programms. Trotzdem muß man hier einmal festlegen, welches Encoding denn nun tatsächlich verwendet werden soll. Und dieses Encoding muß dann auch konsequent urlencoded maskiert sein! UTF-8-Umlaute bestehen dann also zwingend aus zwei %-Sequenzen, die die zwei UTF-8-Bytes dieser Zeichen darstellen. Nur dann besteht keinerlei Mißverständnismöglichkeit, weil der Server die volle Kontrolle über seine Bytes behält.

        Das URL-Encoding hat für JEDE ausgegebene URL zu erfolgen. Darüber hinaus hat ggf. auch noch ein HTML-Encoding zu erfolgen, sollte die URL im HTML-Kontext ausgegeben werden.

        Beispiel:
        gewünschte URL: index.php?titel=Ä&utitel=ä (als UTF-8)
        URL-Encoding:   index.php?titel=%C3%84&utitel=%C3%84
        HTML-Encoding:  index.php?titel=%C3%84&amp;utitel=%C3%84

        - Sven Rautenberg

        --
        "Love your nation - respect the others."
  3. @@Kalle_B:

    <a href='index.php?zp=p591&amp;ort_id=9669,9671,9674,9219,9216&amp;titel=Was ist los im Weschnitztal?&amp;utitel=F&uuml;rth, Rimbach, M&ouml;rlenbach, Birkenau, Weinheim'>hier</a>

    Leerzeichen haben in einem URI nichts zu suchen, Umlaute auch nicht. [RFC3986] (Ja, bei dir sind Umlaute im Wert des 'href'-Attributs vorhanden, da der Browser ja aus '&uml;' 'ü' macht.)

    Du hast Glück, dass dein Browser das korrigiert und aus ' ' '%20', aus 'ü' '%FC' und aus 'ö' '%F6' macht ...

    &utitel=F%FCrth,%20Rimbach,%20M%F6rlenbach,%20Birkenau,%20Weinheim

    ... oder auch nicht. Die Frage ist, ob das so richtig ist, oder ob dein Server das nicht lieber UTF-8-codiert hätte; das 'ü' also nicht als '%FC', sondern als '%C3%BC'; das 'ö' nicht als '%F6', sondern als '%C3%B6'.

    Außerdem darf IIRC im Query kein '?' vorkommen. Das muss also auch als '%3F' escapet werden.

    Funktioniert es so?
    <a href='index.php?zp=p591&amp;ort_id=9669,9671,9674,9219,9216&amp;titel=Was%20ist%20los%20im%20Weschnitztal%3F&amp;utitel=F%C3%BCrth,%20Rimbach,%20M%C3%B6rlenbach,%20Birkenau,%20Weinheim'>hier</a>

    BTW, Hier klicken ist kein Link-Text.

    Deshalb muss ich für die Ausgabe also wieder codieren:
    $utitel = htmlentities( $utitel, ENT_QUOTES, 'UTF-8' );

    Nein, musst du nicht. Im generierten HTML soll ja 'ü' stehen, nicht '&uml;'. [QA-ESCAPES]

    Wo ist mein Denkfehler?

    Du verwechselst den Kontext. URI vs. HTML.

    Live long and prosper,
    Gunnar

    --
    Flughafen in Tempelhof
    findet jeder Hempel doof.