Wenn-ich-sie-wäre: Modrewrite PHP to Images (Achtung Anfänger)

Hallo,

vorweg ich habe heute zum ersten mal mit PHP gearbeitet und bin richtig stolz, das ich es geschafft habe aus GET Parametern ein Bild zu zaubern.

Nun sieht die URL des jeweiligen Bildes nicht besonders schön aus:
example.com/unterverzeichnis/image-gen.php?parameter1=wenn-ich&parameter2=sie-waere

Ziel ist es die URL so zu haben:
example.com/unterverzeichnis/wenn-ich.sie-ware.png
oder
example.com/unterverzeichnis/wenn-ich.png (Hier wird dann nur das wenn ich im Bild angezeigt.

Der PUNKT soll also als Trennung zwischen den beiden GET Parametern trennen. Ich habe mich daher versucht schlau zu machen. Nach meinen Informationen ist nun das APACHE Modul : Modrewrite die richtige Wahl?

Es wird wohl über die .htacces im jeweiligen Verzeichnis gesteuert. Ich habe mich auch versucht durch den Syntax zu arbeiten, und mein Lösungsansatz war:

RewriteEngine on  
RewriteRule ([A-Za-z]+).png$ image-gen.php?parameter1=$1 [QSA,L]  
RewriteRule ([A-Za-z]+).([A-Za-z]+).png$ image-gen.php?parameter1=$1&parameter2=$2 [QSA,L]

Soweit so gut, die erste RewriteRule Zeile funktioniert auch, bei dem zweiten RewriteRule klappt es leider garnicht. Irgendwie verstehe ich diesen Syntax nicht!? Oder was mache ich falsch?

  1. Moin,

    RewriteEngine on

    RewriteRule ([A-Za-z]+).png$ image-gen.php?parameter1=$1 [QSA,L]
    RewriteRule ([A-Za-z]+).([A-Za-z]+).png$ image-gen.php?parameter1=$1&parameter2=$2 [QSA,L]

      
    Das sieht schon nicht schlecht aus. Beachte, dass der Punkt, anders als vielleicht von dir angenommen, in diesem Zustand keinen Punkt darstellt, sondern ein beliebiges Zeichen. Das ist so bei regulären Ausdrücken, und kann auch [hier nachgelesen](http://www.modrewrite.de/mod-rewrite/syntax/) werden.  
      
    
    > bei dem zweiten RewriteRule klappt es leider garnicht.  
      
    Das ist recht wenig Information. Was klappt nicht? Werden die Parameter nicht richtig übergeben? Oder wird gar nichts übergeben?  
      
    Grüße Marco
    
    1. Moin,

      Das ist recht wenig Information. Was klappt nicht? Werden die Parameter nicht richtig übergeben? Oder wird gar nichts übergeben?

      Ich habe das mal auf meinem Server nachvollzogen. Im Verzeichnis test/mod_rewrite liegt eine .htaccess-Datei mit den Rules.

      Bei mir ist es so, dass immer die erste Regel greift. Das ist kein Wunder, denn diese Regel ist so allgemein, dass sie auch auf die Regeln der zweiten Regel mit zutrifft. Die Lösung:

      RewriteEngine on
      RewriteRule ^([A-Za-z]+).png$ image-gen.php?parameter1=$1 [QSA,L]
      RewriteRule ^([A-Za-z]+).([A-Za-z]+).png$ image-gen.php?parameter1=$1&parameter2=$2 [QSA,L]

      Die ^-Zeichen stehen bei regulären Ausdrücken für den Anfang einer Zeile (oder in dem Fall für den Anfang eines Ausdrucks). Die Punkte habe ich mit einem \ maskiert, damit sie wirklich Punkte und keine beliebigen Zeichen darstellen. Mit dieser Methode funktionieren beide Links, obwohl keine PNG-Dateien im Verzeichnis existieren:

      http://misterunknown.de/test/mod_rewrite/test.png
      http://misterunknown.de/test/mod_rewrite/test.wald.png

      Die entsprechende PHP-Datei gibt die übergebenen $_GET-Parameter per
        print_r($_GET);
      aus.

      Grüße Marco

      1. RewriteEngine on
        RewriteRule ^([A-Za-z]+).png$ image-gen.php?parameter1=$1 [QSA,L]
        RewriteRule ^([A-Za-z]+).([A-Za-z]+).png$ image-gen.php?parameter1=$1&parameter2=$2 [QSA,L]

        Vielen Dank Marco, das war es. Wieder etwas gelernt.

      2. Tach!

        http://misterunknown.de/test/mod_rewrite/test.png
        http://misterunknown.de/test/mod_rewrite/test.wald.png

        Da sieht man übrigens ein schönes, wenn auch harmloses Beispiel für missachteten Kontextwechsel. Unter "Inhalt der .htaccess-Datei" steht nicht etwa

        ?parameter1=$1&parameter2=$2

        sondern

        ?parameter1=$1¶meter2=$2

        Weil das & nicht ordnungsgemäß als & maskiert worden ist, interpretieren es zumindest einige Prowser als Entity ¶ auch wenn das abschließende ; fehlt.

        Wenn man Einfluss auf die Serverkonfiguration hat (sprich: geht nicht mehr im Script), kann man sich für PHP

        arg_separator.input = ";&"

        konfigurieren. Dann kann der Browser immer noch & als sein Default-Trennzeichen verwenden und man selbst das Semikolon, woraufhin sich solche Überraschungen mit einigen Zeichenfolgen, die man grad mal auch gar nicht getestet hat, ersparen.

        P.S. Der Fehler ist noch während meines Schreibens korrigiert worden.

        dedlfix.

        1. Moin,

          Wenn man Einfluss auf die Serverkonfiguration hat (sprich: geht nicht mehr im Script), kann man sich für PHP
            arg_separator.input = ";&"
          konfigurieren. Dann kann der Browser immer noch & als sein Default-Trennzeichen verwenden und man selbst das Semikolon, woraufhin sich solche Überraschungen mit einigen Zeichenfolgen, die man grad mal auch gar nicht getestet hat, ersparen.

          Sehr schön, das wusste ich noch nicht. Danke.

          P.S. Der Fehler ist noch während meines Schreibens korrigiert worden.

          Ja, der Validator hatte mich darauf aufmerksam gemacht. Ich habe es kurzerhand mit str_replace() gelöst.

          Grüße Marco

          1. Tach!

            Ja, der Validator hatte mich darauf aufmerksam gemacht. Ich habe es kurzerhand mit str_replace() gelöst.

            htmlspecialchars() wäre dir richtige Funktion dazu gewesen. Du fügst ja etwas in den HTML-Kontext ein.

            dedlfix.

            1. Moin,

              htmlspecialchars() wäre dir richtige Funktion dazu gewesen.

              Stimmt. Ich hatte irgendsowas im Hinterkopf, aber es wollte mir nicht einfallen. Dazu hätte ich auch mal noch eine Frage:
              Was ist eigentlich der Unterschied zwischen htmlspecialchars() und htmlentities()? Bei php.net steht nur, dass htmlentities() wirklich alle Zeichen umwandelt. Aber welche sind das? Und warum werden die von htmlspecialchars() weggelassen?

              Grüße Marco

              1. Tach!

                Was ist eigentlich der Unterschied zwischen htmlspecialchars() und htmlentities()? Bei php.net steht nur, dass htmlentities() wirklich alle Zeichen umwandelt. Aber welche sind das? Und warum werden die von htmlspecialchars() weggelassen?

                Es sind nicht alle, aber trotzdem zu viele. Der deutsche Text schreibt

                "... allerdings wandelt htmlentities() wirklich alle Zeichen, die eine HTML-Code-Entsprechung haben, ..."

                Die englische Original-Passage dazu ist:

                "...except with htmlentities(), all characters which have HTML character entity equivalents..."

                Das "wirklich" ist da verwirrend und meiner Meinung nach falsch übersetzt. Die Auflösung jedenfalls, welche Zeichen "eine HTML-Code-Entsprechung" im Sinne PHPs haben (sprich: wenn es ein Entity dazu gibt, also beileibe nicht sämtliche Zeichen außerhalb ASCIIs), liefert die Funktion get_html_translation_table().

                htmlspecialchars() behandelt nur die "wirklich" notwendigen Zeichen, die da wären &, <, > und je nach Parametern " und '. Diese müssen berücksichtigt werden. Das heißt nicht, dass sie unter allen Umständen umgeschrieben werden müssen. Man muss das auch wieder kontextbezogen betrachten. Ein " zum Beispiel muss nur als &quot; notiert werden, wenn es Teil des Wertes eines Attributes ist. Im laufenden Fließtext ist es nicht notwendig, aber auch nicht schädlich.

                Die anderen Zeichen in ihre Entity- oder NCR-Form zu bringen ist nur eine Notlösung, wenn man nicht auf UTF-8 umsteigen kann. Denn dann kann man sie direkt notieren. Sich mit ISO-8859-1 und Entitys/NCRs für die Zeichen außerhalb dieser Kodierung rumzuschlagen ist generell keine kluge Idee. Wenn solche Zeichen im Browser eingegeben werden und der sie nicht in die angegebenen Kodierung bringen kann, dann gehen sie verloren oder sind in ihrer Ersatzschreibweise nicht von "normalen" Zeichen zu unterscheiden.

                Gibt man zum Beispiel 中 zusammen mit einem wörtlich gemeinten &amp; ein, so senden einige Browser das - wenn sie zu ISO-8859-1 gezwungen werden - als &#20013; und &amp;. Wie unterscheidest du nun die Ersatzschreibweise &#20013; von dem wirklich so eingegebenen &amp;? Das Beispiel mag etwas konstruiert erscheinen, aber einerseits ist das Problem auch bei einem einfachen & nicht einfacher lösbar und andererseits hast du ja selbst gesehen, wie schnell aus einem & gefolgt von para ein Entity erkannt wird.

                dedlfix.

                1. Moin,

                  htmlspecialchars() behandelt nur die "wirklich" notwendigen Zeichen, die da wären &, <, > und je nach Parametern " und '. Diese müssen berücksichtigt werden. Das heißt nicht, dass sie unter allen Umständen umgeschrieben werden müssen.

                  Ok, das ergibt Sinn.

                  Gibt man zum Beispiel 中 zusammen mit einem wörtlich gemeinten &amp; ein, so senden einige Browser das - wenn sie zu ISO-8859-1 gezwungen werden - als &#20013; und &amp;. Wie unterscheidest du nun die Ersatzschreibweise &#20013; von dem wirklich so eingegebenen &amp;? Das Beispiel mag etwas konstruiert erscheinen, aber einerseits ist das Problem auch bei einem einfachen & nicht einfacher lösbar und andererseits hast du ja selbst gesehen, wie schnell aus einem & gefolgt von para ein Entity erkannt wird.

                  Ja, das geht schneller als man denkt. Ich habe mir mal eine Art CMS für eine Seite geschrieben, in der ich genau das Problem hatte: Beim Anzeigen in der Textbox mussten Zeichen umgewandelt werden, genau wie beim Schreiben in die Datenbank. Das ist nervig und ist nur kompliziert zu machen.

                  Mittlerweile versuche ich nur noch UTF-8 zu nutzen, bzw. nach und nach umzustellen.

                  Grüße Marco