Christian Seiler: Neuer Artikel: Kontextwechsel erkennen und behandeln

Liebe Forumsgemeinde,

Ich habe den Artikel Kontextwechsel erkennen und behandeln, der schließlich auch von zahlreichem Feedback aus dem Forum gelebt hat, nun veröffentlicht. Einen Teaser dazu findet ihr im Weblog. Ich möchte noch einmal dedlfix für seine Arbeit daran danken sowie dem Forum für die Unterstützung.

Viele Grüße,
Christian

  1. Hi!

    Ich möchte noch einmal dedlfix für seine Arbeit daran danken sowie dem Forum für die Unterstützung.

    Und ich möchte das mal zum Anlass nehmen, meinerseits dir und auch den anderen Mitgliedern von SELFHTML für ihre Arbeit danken. Man macht das viel zu selten (also das Danken).

    Lo!

  2. Liebe Forumsgemeinde,

    Ich habe den Artikel Kontextwechsel erkennen und behandeln, der schließlich auch von zahlreichem Feedback aus dem Forum gelebt hat, nun veröffentlicht. Einen Teaser dazu findet ihr im Weblog. Ich möchte noch einmal dedlfix für seine Arbeit daran danken sowie dem Forum für die Unterstützung.

    zitat, Abschnitt URL
    7) Eine URL-Dekodierfunktion wird höchstwahrscheinlich alle %XX-Sequenzen inklusive %20 richtig dekodieren, auch wenn der Kontext eigentlich ein + vorschreibt. Insofern könnte man generell zu rawurlencode() greifen. Doch warum sollte man sich ohne Not und wider besseren Wissens eine Restunsicherheit ins Programm einbauen?

    Meine Notiz.
    Beim Dekodieren ist darauf zu achten, dass "+" zu " " gewandelt werden, bevor die %xx kovertiert werden.
    Ich habe schon input-decoder gesehem, die das verkehrt hatten.
    Bei rawurlencode hat man solche Probleme nicht.

    mfg Beat

    --
    ><o(((°>           ><o(((°>
       <°)))o><                     ><o(((°>o
    Der Valigator leibt diese Fische
    1. Hi!

      Beim Dekodieren ist darauf zu achten, dass "+" zu " " gewandelt werden, bevor die %xx kovertiert werden.
      Ich habe schon input-decoder gesehem, die das verkehrt hatten.
      Bei rawurlencode hat man solche Probleme nicht.

      Das ist ein quasi ein Zwickmühlenproblem. Der Standard sagt +, aber es wird immer einige kaputte Programme geben, die den Standard nicht richtig interpretieren. Soll man deswegen empfehlen, den Standard generell zu missachten, selbst wenn man vom Problem nicht betroffen ist. Ich denke, wer dieses Problem hat, weil er Fremdsysteme mit Daten beschicken muss, sollte das im Einzelfall entscheiden, ob er auch im Querystring zu rawurlencode() greift.

      Übrigens, wenn du aufmerksam liest, wird dir eine Stelle auffallen, wo ich diese Unterscheidung nicht mache. Das aber auch nur aus dem Grund, weil Javascript das Leerzeichen in seinen diesbezüglichen Funktionen generell zu %20 kodiert und ich keine Lust hatte, da noch eine Extrawurst zu kochen.

      Lo!

      1. Übrigens, wenn du aufmerksam liest, wird dir eine Stelle auffallen, wo ich diese Unterscheidung nicht mache. Das aber auch nur aus dem Grund, weil Javascript das Leerzeichen in seinen diesbezüglichen Funktionen generell zu %20 kodiert und ich keine Lust hatte, da noch eine Extrawurst zu kochen.

        Ja der Himmel hängt voller Extrawürste.

        Mich beschäftigt derzeit folgendes Problem.
        Ich schreibe an einem Perl-Modul, das das Frontend für einen Formmailer darstellt. Das Modul soll ein anderes Modul einbinden, das dann den SMTP Versand durchführt.

        In welche Zuständigkeit fällt die Kontextgerechte Behandlung der Mail.
        Muss ich die Headerbehandlung durchführen, oder ist das in der Zuständigkeit des SMTP Moduls?

        Wenn ich eine Mail via Sendmail versende, dann wird von mir erwartet, dass ich die Headerbehandlung selber durchführe.

        In diesem Beispiel wäre das nicht schlimm, wenn die Behandlung mehrfach durchgeführt wird, denn das Resultat bleibt sich dasselbe. Aber es zeigt ein Grundproblem: Wie erfahre ich, ob eine Kontextbehandlung durchgeführt wurde? Und wie legt man bei einem modularen Design genau fest, wo Kodierungen durchzuführen sind?

        mfg Beat

        --
        ><o(((°>           ><o(((°>
           <°)))o><                     ><o(((°>o
        Der Valigator leibt diese Fische
        1. Hi!

          Ich schreibe an einem Perl-Modul, das das Frontend für einen Formmailer darstellt. Das Modul soll ein anderes Modul einbinden, das dann den SMTP Versand durchführt. In welche Zuständigkeit fällt die Kontextgerechte Behandlung der Mail.
          Muss ich die Headerbehandlung durchführen, oder ist das in der Zuständigkeit des SMTP Moduls?

          Das kommt darauf an, wie die Schnittstelle aussieht. Wenn man es richtig macht (zumindest würde ich das so machen), setzt man vor das SMTP-Modul noch ein Mail-Modul, das die Einzelteile der Mail (Empfänger, Subjekt, Inhalt, weitere Headerangaben, Angaben zur Zeichenkodierung) entgegennimmt, daraus etwas erstellt, das mit dem SMTP-Modul versendet werden kann. Da sich das SMTP-Modul nur um den Versand kümmert, wäre das Mail-Modul dasjenige, das die Teile kontextgerecht zusammenbaut.

          Wenn ich eine Mail via Sendmail versende, dann wird von mir erwartet, dass ich die Headerbehandlung selber durchführe.

          Dazu kann ich nichts sagen, da fehlt mir das Wissen.

          In diesem Beispiel wäre das nicht schlimm, wenn die Behandlung mehrfach durchgeführt wird, denn das Resultat bleibt sich dasselbe.

          Das kommt sicher darauf an, was du genau anstellst.

          Aber es zeigt ein Grundproblem: Wie erfahre ich, ob eine Kontextbehandlung durchgeführt wurde?

          Im Prinzip gar nicht. Du kannst eine Information nicht entschlüsseln, wenn du nicht weißt, ob das Resultat richtig ist. Es kann zwar gültig nach bestimmten Regeln aussehen. Wenn es aber nach der Intention des Autors nach anderen Regeln aussehen soll ... ohne den Autor zu fragen oder eine Prüfsumme nach bekanntem Algorhitmus prüfen zu können, geht es nicht mit absoluter Gewissheit.

          Und wie legt man bei einem modularen Design genau fest, wo Kodierungen durchzuführen sind?

          So spät wie möglich (Kodierungen im Sinne eines Kontextes; Zeichenkodierungen sind ja immer vorhanden). Nach Möglichkeit sollte im Rohformat gearbeitet werden. Wenn für einen Empfänger jedoch ein bestimmtes Übertragungsprotokoll verwendet wird, sollte das für dieses Protokoll zuständige Modul die Rohdaten entgegennehmen und für die kontextgerechte Aufbereitung sorgen. Beim Empfänger wird (oder sollte) es ein Gegenmodul geben, das wieder die Rohdaten herstellt.

          Es gibt da ja das EVA-Prinzip: Trennung des Codes nach Eingabe, Verarbeitung und Ausgabe. Die Verarbeitung arbeitet mit Daten im Rohformat. Diese bekommte es im Rohformat und gibt sie im Rohformat weiter. Eingabe und Ausgabe sorgen für die kontextgerechte Interpretation beziehungsweise Behandlung.

          Lo!

  3. hi,

    Ich habe den Artikel Kontextwechsel erkennen und behandeln, der schließlich auch von zahlreichem Feedback aus dem Forum gelebt hat, nun veröffentlicht. Einen Teaser dazu findet ihr im Weblog. Ich möchte noch einmal dedlfix für seine Arbeit daran danken sowie dem Forum für die Unterstützung.

    Danke auch!

    Dedlfix, Du hättest den Abschnitt "HTML in der Datenbank" evntl. ein bischen ausführlicher abhandeln können. Ich persönlich stufe die Verwendung von &htmlentities; ohnehin als deprecated ein und bevorzuge eine konsistente Codierung.

    Wenn bspw. in einem utf-8-kodierten Suchformular der Suchbegriff "Hühner" eingegeben wurde und in der Tabelle "H&uuml;hner" steht, kannste lange suchen. Konsistenz heißt hier, gleiche Kodierung (Character Setting). Oder eine entsprechende Umwandlung, was freilich nicht immer möglich und überdies etwas CPU-intensiver ist.

    Ansonsten schön, dass es mal wieder einen neuen Artikel gibt.

    Viele Grüße,
    Horst Haselhuhn

    --
    Eine Kuh macht muh, viele Kühe machen Mühe.
    1. Hi!

      Wenn bspw. in einem utf-8-kodierten Suchformular der Suchbegriff "Hühner" eingegeben wurde und in der Tabelle "H&uuml;hner" steht, kannste lange suchen. Konsistenz heißt hier, gleiche Kodierung (Character Setting). Oder eine entsprechende Umwandlung, was freilich nicht immer möglich und überdies etwas CPU-intensiver ist.

      H&uuml;hner haben im Gegensatz zu Hühnern in der Datenbank normalerweise nichts zu suchen, weil sie nicht nur das von dir angesprochene Suchproblem haben. Es mit einem htmlentities() zu beseitigen, ist wie den Teufel mit dem Belzebub auszutreiben. Konsistenz ist das eine und Minus × Minus ergibt auch Plus. Aber &uuml; sind 6 Zeichen und nicht nur eins wie beim ü, das fällt einem dann auch bei anderen Stringfunktionen auf die Füße. Die Devise sollte nicht nur "Konsistenz" lauten sondern "Rohformat". Das beinhaltet Konsistenz _und_ einfache Verarbeitung.

      Kodierung ist nochmal ein komplexes Thema für sich. Das habe ich absichtlich in dem Artikel ausgeklammert.

      Lo!

  4. Im Abschnitt "Zahlen im (My)SQL-Statement"

    Kann der Ausdruck:
    [code=php]
    $sql = sprintf('SELECT feldliste FROM tabelle WHERE feld=%s', intval($zahl));
    [/code]
    für integer Werte durch:
    [code=php]
    $sql = sprintf('SELECT feldliste FROM tabelle WHERE feld=%d', $zahl);
    [/code]
    vereinfacht werden.
    Das gleiche gilt für "floats" mit entsprechender Formatanweisung "%f"

    1. Hallo

      Im Abschnitt "Zahlen im (My)SQL-Statement"

      Kann der Ausdruck:
      [code=sql]
      $sql = sprintf('SELECT feldliste FROM tabelle WHERE feld=%s', intval($zahl));
      [/code]
      für integer Werte durch:
      [code=sql]
      $sql = sprintf('SELECT feldliste FROM tabelle WHERE feld=%d', $zahl);
      [/code]
      vereinfacht werden.

      Für die $zahl, die gesichert innerhalb des Skripts erstellt wird, mag diese Vereinfachung stimmen, aber wenn $zahl aus einer Eingabe (z.B. per POST oder GET übergeben) stammt, darf man ihr nicht trauen und dann ist genau die Behandlung, wie sie dedlfix angibt, richtig. Da eine Integerzahl, die mit intval behandelt wird, eine Integerzahl bleibt und Variablen anderen Typs in ein Integer umgewandelt werden (im Zweifel zu 0) sollte der immer gleichen Schreibweise wegen, intval grundsätzlich drin bleiben.

      Das gleiche gilt für "floats" mit entsprechender Formatanweisung "%f"

      Ja, das tut es.

      Tschö, Auge

      --
      Verschiedene Glocken läuteten in der Stadt, und jede von ihnen vertrat eine ganz persönliche Meinung darüber, wann es Mitternacht war.
      Terry Pratchett, "Wachen! Wachen!"
      Veranstaltungsdatenbank Vdb 0.3
      1. Hi Auge!

        Für die $zahl, die gesichert innerhalb des Skripts erstellt wird, mag diese Vereinfachung stimmen, aber wenn $zahl aus einer Eingabe (z.B. per POST oder GET übergeben) stammt, darf man ihr nicht trauen und dann ist genau die Behandlung, wie sie dedlfix angibt, richtig.

        einLaser spielt aber auf die implizite Umwandlung an, die mit den Formatanweisungen %d und %f automatisch gemacht werden.

        MfG H☼psel

        --
        "It's amazing I won. I was running against peace, prosperity, and incumbency."
        George W. Bush speaking to Swedish Prime Minister unaware a live television camera was still rolling, June 14, 2001
        Selfcode: ie:% fl:( br:> va:) ls:& fo:) rl:? n4:& ss:| de:] js:| ch:? sh:( mo:) zu:)
    2. Hallo,

      Kann der Ausdruck:

      $sql = sprintf('SELECT feldliste FROM tabelle WHERE feld=%s', intval($zahl));

      
      > für integer Werte durch:  
      > ~~~
        
      
      > $sql = sprintf('SELECT feldliste FROM tabelle WHERE feld=%d', $zahl);  
      > 
      
      

      vereinfacht werden.

      Du hast prinzipiell Recht. Aber: Auf Tastaturen hierzulande sind 's' und 'd' so dicht nebeneinander, dass es leicht fällt, da mal einen Fehler zu machen, der dann zu einer Lücke wird. Wenn man sich dagegen angewöhnt, explizit intval() zu nutzen, ist man vor einem derartigen Fehler geschützt. Zudem sieht man beim Drüberlesen schneller, dass der Code an der Stelle sicher ist.

      Anders ausgedrückt: Ich würde %d ohne intval() niemandem ankreiden, aber wenn ich etwas empfehlen soll, dann besser %s oder %d (wäre in dem Fall egal) mit inval().

      Viele Grüße,
      Christian

      --
      Mein "Weblog" [RSS]
      Using XSLT to create JSON output (Saxon-B 9.0 for Java)
      »I don't believe you can call yourself a web developer until you've built an app that uses hyperlinks for deletion and have all your data deleted by a search bot.«
                  -- Kommentar bei TDWTF
      1. Wenn man zu Tippfehlern mit gleichzeitigem Überlesen neigt, sollte man wohl besser die Parameter binden.) Eigentlich sollte man das IMMER tun.)

      2. Hi,

        Kann der Ausdruck:

        $sql = sprintf('SELECT feldliste FROM tabelle WHERE feld=%s', intval($zahl));

        
        > > für integer Werte durch:  
        > > ~~~
          
        
        > > $sql = sprintf('SELECT feldliste FROM tabelle WHERE feld=%d', $zahl);  
        > > 
        
        

        vereinfacht werden.

        Du hast prinzipiell Recht. Aber: Auf Tastaturen hierzulande sind 's' und 'd' so dicht nebeneinander, dass es leicht fällt, da mal einen Fehler zu machen, der dann zu einer Lücke wird. Wenn man sich dagegen angewöhnt, explizit intval() zu nutzen, ist man vor einem derartigen Fehler geschützt. Zudem sieht man beim Drüberlesen schneller, dass der Code an der Stelle sicher ist.

        beide Vorgehen haben auf 32-Bit-Systemen das Problem eines zu geringen Wertebereichs. Daher würde ich an dieser Stelle

          
        $sql = sprintf("SELECT feldliste FROM tabelle WHERE feld='%s'", mysql_real_escape_string($zahl));  
        
        

        favorisieren.

        Gruß,
        Andreas.

        1. Hi,

          beide Vorgehen haben auf 32-Bit-Systemen das Problem eines zu geringen Wertebereichs. Daher würde ich an dieser Stelle

          $sql = sprintf("SELECT feldliste FROM tabelle WHERE feld='%s'", mysql_real_escape_string($zahl));

          
          > favorisieren.  
            
          noch was: durch die Umwandlung nach Integer handelt man sich möglicherweise Probleme bei Fehleingaben ein. Steht in $zahl z.B. "1foo", wird das durch intval() nach 1 umgewandelt, wodurch alle Datensätze, wo feld 1 entspricht, zurückgegeben werden, was für den gemeinen Nutzer nicht unbedingt nachvollziehbar ist. Eine zusätzliche Prüfung wäre hier nötig.  
            
          Gruß,  
          Andreas.
          
          1. Hi!

            beide Vorgehen haben auf 32-Bit-Systemen das Problem eines zu geringen Wertebereichs.

            Haben? Können haben, müssen aber nicht. Außerdem kommt es auch noch auf den Feldtyp im DBMS an. Wer INT verwendet hat dieses Problem nicht. Wer BIGINT (oder allgemein: Zahlen jenseits der 32 Bit) verwendet, muss sowieso erhöhte Aufmerksamkeit walten lassen, nicht nur an dieser Stelle.

            Daher würde ich an dieser Stelle
            $sql = sprintf("SELECT feldliste FROM tabelle WHERE feld='%s'", mysql_real_escape_string($zahl));
            favorisieren.

            Ja, wenn es notwendig ist, aber pauschal findet das nicht meine Unterstützung. (Meine Devise: Nachdenken vor Nachmachen. - "Das hab ich schon immer so gemacht" ist nicht immer der beste Ratgeber.)

            noch was: durch die Umwandlung nach Integer handelt man sich möglicherweise Probleme bei Fehleingaben ein. Steht in $zahl z.B. "1foo", wird das durch intval() nach 1 umgewandelt, wodurch alle Datensätze, wo feld 1 entspricht, zurückgegeben werden, was für den gemeinen Nutzer nicht unbedingt nachvollziehbar ist. Eine zusätzliche Prüfung wäre hier nötig.

            Das hat nicht direkt was mit dem Kontext zu tun, sondern ist Aufgabe einer fachlichen Prüfung. Ebenso wie Berechtigungsprüfungen sind Wertebereichsprüfungen gemäß fachlicher Anforderungen notwendig, die im Vorfeld erledigt werden müssen/sollten. Die kontextgerechte Behandlung ist dann noch der letzte notwendige Schritt, bevor die Daten auf Reisen gehen. Wenn jemand die fachliche Prüfung mit der Behandlung für den Kontextwechsel verbindet und das im Einzelfall "rechtfertigen" kann - bitte schön. Eine pauschale Empfehlung will ich nicht geben, weil die fachlichen Anforderungen unterschiedlich sein können und werden.

            Lo!

            1. Hi dedlfix,

              beide Vorgehen haben auf 32-Bit-Systemen das Problem eines zu geringen Wertebereichs.

              Haben? Können haben, müssen aber nicht. Außerdem kommt es auch noch auf den Feldtyp im DBMS an.

              Natürlich müssen sie das nicht. Aber es kann ja nicht schaden, dem Problem, ungeachtet dessen, dass es in der Praxis nicht auftreten sollte, generell aus dem Weg zu gehen. Oder zumindest darauf aufmerksam zu machen, dass das Problem existieren kann.

              Wer INT verwendet hat dieses Problem nicht.

              Doch - das Problem kann bereits bei UNSIGNED INT auftreten, zumindest unter MySQL und mit der hier vorgeschlagenen Nutzung von %d als sprintf()-Platzhalter bzw. intval().

              Daher würde ich an dieser Stelle
              $sql = sprintf("SELECT feldliste FROM tabelle WHERE feld='%s'", mysql_real_escape_string($zahl));
              favorisieren.

              Ja, wenn es notwendig ist, aber pauschal findet das nicht meine Unterstützung. (Meine Devise: Nachdenken vor Nachmachen. - "Das hab ich schon immer so gemacht" ist nicht immer der beste Ratgeber.)

              Wo siehst du denn hier eine Pauschalität? Ich habe doch zwei Argumente genannt - sind die deiner Meinung nach beide so abwegig? Oder anders gefragt: welchen Vorteil versprichst du dir von der integer-Variante, oder welchen Nachteil siehst du in der String-Version?

              noch was: durch die Umwandlung nach Integer handelt man sich möglicherweise Probleme bei Fehleingaben ein. Steht in $zahl z.B. "1foo", wird das durch intval() nach 1 umgewandelt, wodurch alle Datensätze, wo feld 1 entspricht, zurückgegeben werden, was für den gemeinen Nutzer nicht unbedingt nachvollziehbar ist. Eine zusätzliche Prüfung wäre hier nötig.

              Das hat nicht direkt was mit dem Kontext zu tun, sondern ist Aufgabe einer fachlichen Prüfung. Ebenso wie Berechtigungsprüfungen sind Wertebereichsprüfungen gemäß fachlicher Anforderungen notwendig, die im Vorfeld erledigt werden müssen/sollten.

              das Problem ist, dass eine Nutzereingabe durch intval() ggf. verändert wird. Wenn man auf eine fachliche Prüfung verzichten kann, bzw. es keine fachliche Prüfung gibt, z.B. im Falle von Suchanfragen, ist das eher hinderlich. Daher ist es meiner Meinung nach falsch, Nutzereingaben pauschal in Zahlenwerte zu konvertieren, auch dann, wenn man Zahlenwerte erwartet.

              Gruß,
              Andreas.

              1. Hi!

                Aber es kann ja nicht schaden, dem Problem, ungeachtet dessen, dass es in der Praxis nicht auftreten sollte, generell aus dem Weg zu gehen. Oder zumindest darauf aufmerksam zu machen, dass das Problem existieren kann.

                Es gibt noch jede Menge anderer Probleme beim Programmieren zu beachten, auch solche, die mit dem Nichtbeachten von Wertebereichen zu tun haben. All diese Probleme kann man unmöglich aufzählen, weswegen ich mich nur auf solche beschränken will, die unmittelbar mit dem Kontextwechsel zu tun haben. Wenn ich das Problem mit den überlaufenden Integerwerten erwähnen wollte, müsste ich der Vollständigkeit halber alle MySQL-Integer-Typen ansprechen (also auch die kleiner als INT) und daraufhin eine generelle Lösung erstellen. Wie auch immer, die überlaufenden Zahlen erzeugen kein Kontextwechselproblem. Die (String-)Alternative zu intval() ist bereits erwähnt. Ich werde noch zwei Beispiele hinzufügen, ein mit dem Typecast per %d und eins für die Stringvariante.

                Wo siehst du denn hier eine Pauschalität? Ich habe doch zwei Argumente genannt - sind die deiner Meinung nach beide so abwegig? Oder anders gefragt: welchen Vorteil versprichst du dir von der integer-Variante, oder welchen Nachteil siehst du in der String-Version?

                Die String-Variante ist in deinem Beispiel da, um ein möglicherweise auftretendes Wertebereichsproblem zu umgehen. Dazu muss sie einen Umweg über einen anderen Variablentyp gehen. Dabei ist nicht offensichtlich, warum hier ein String verwendet wird, obwohl doch Zahlen verarbeitet werden sollen. Aus diesem Grunde will ich sie nicht als primäre Lösung darstellen. Auch deshalb nicht, weil andere DBMS anders denken, wenn sie Strings statt Zahlen erhalten.

                Das Augenmerk dieses Abschnitts soll sein, den richtigen Kontext zu erkennen, was bei Zahlen gelegentlich mit einem mysql_real_escape_string() auf unquotierte Werte falsch gemacht wird.

                das Problem ist, dass eine Nutzereingabe durch intval() ggf. verändert wird. Wenn man auf eine fachliche Prüfung verzichten kann, bzw. es keine fachliche Prüfung gibt, z.B. im Falle von Suchanfragen, ist das eher hinderlich. Daher ist es meiner Meinung nach falsch, Nutzereingaben pauschal in Zahlenwerte zu konvertieren, auch dann, wenn man Zahlenwerte erwartet.

                Dieses Argument scheint mir nicht nachvollziehbar. Suchanfragen in Zahlenfeldern werden kein sinnvolles Ergebnis bringen, wenn man sie mit Nicht-Zahlen-Strings vergleicht. Wenn jemand einen falschen Wert eingibt, kann er nicht erwarten, ein richtiges Ergebnis zu erhalten. Insofern sehe ich es als gerechtfertigt, Eingaben in Zahlenwerte zwangszukonvertieren, wenn diese für die Weiterverarbeitung benötigt werden. Außerdem geht es hier nicht um pauschale Umwandlung für sämtliche Datentypen (wie man deinen Satz interpretieren kann), sondern um eine solche im Falle von Zahlen.

                Lo!

                1. Hi,

                  Aber es kann ja nicht schaden, dem Problem, ungeachtet dessen, dass es in der Praxis nicht auftreten sollte, generell aus dem Weg zu gehen. Oder zumindest darauf aufmerksam zu machen, dass das Problem existieren kann.

                  Es gibt noch jede Menge anderer Probleme beim Programmieren zu beachten, auch solche, die mit dem Nichtbeachten von Wertebereichen zu tun haben. All diese Probleme kann man unmöglich aufzählen, weswegen ich mich nur auf solche beschränken will, die unmittelbar mit dem Kontextwechsel zu tun haben.

                  hier liegt wohl ein Missverständnis vor. Meine Antworten bezogen sich anfangs auf die Postings von einLaser und Christian, daher habe ich auch diese zitiert. Meiner Meinung nach musst du in dieser Hinsicht gar nichts an deinem Artikel ändern.

                  das Problem ist, dass eine Nutzereingabe durch intval() ggf. verändert wird. Wenn man auf eine fachliche Prüfung verzichten kann, bzw. es keine fachliche Prüfung gibt, z.B. im Falle von Suchanfragen, ist das eher hinderlich. Daher ist es meiner Meinung nach falsch, Nutzereingaben pauschal in Zahlenwerte zu konvertieren, auch dann, wenn man Zahlenwerte erwartet.
                  Dieses Argument scheint mir nicht nachvollziehbar. Suchanfragen in Zahlenfeldern werden kein sinnvolles Ergebnis bringen, wenn man sie mit Nicht-Zahlen-Strings vergleicht.

                  wenn man sie erst nach integer castet aber schon. Daher hatte ich das Beispiel "1foo" angebracht - sucht man nach diesem String in einem INTEGER-Feld, findet man nichts, was korrekt wäre. Wendet man erst intval() an, wird aus "1foo" eine 1 und plötzlich findet man etwas, was falsch wäre. Um diesen Fehler zu umgehen, müsste man hier also prüfen, ob tatsächlich eine Zahl übergeben wurde, was aber unnötig oder gar hinderlich ist, wenn wir bei dem Beispiel "Suchanfrage" bleiben und eine Suche z.B. über mehrere Felder, mit möglicherweise unterschiedlichen Datentypen, erlaubt ist.

                  Außerdem geht es hier nicht um pauschale Umwandlung für sämtliche Datentypen (wie man deinen Satz interpretieren kann), sondern um eine solche im Falle von Zahlen.

                  ja, ich hätte lieber schreiben sollen "Daher ist es meiner Meinung nach falsch, Nutzereingaben pauschal in Zahlenwerte zu konvertieren wenn man Zahlenwerte erwartet.". Suchanfragen müssen sich ja nicht zwangsläufig auf ein Feld/einen Datentyp beschränken.

                  Das hat aber alles mit deinen Kontextwechseln nichts zu tun, sondern war nur als allgemeiner Zusatz zu einLasers und Christians Anmerkung gedacht, eben _nicht_ pauschal nach int zu casten.

                  Gruß,
                  Andreas.

                  1. Hi!

                    Wie auch immer, für jedes Argument kann es in einer konkreten Situation ein Pro geben und in einer anderen ein Kontra. Es gibt nicht "die" Lösung für alle Probleme. Ein Typecast ist eine Variante, einen kontextgerechten Wert zu erzwingen. Eine andere habe ich ebenfalls beschrieben (explizites Beispiel ist geplant). Der Rest ist das Problem des Programmierers, das jeder für sich selbst und unter Berücksichtigung des konkreten Falls mit den für ihn optimalen Mitteln lösen muss. Eine Empfehlung in die eine oder andere Richtung ist für den einen richtig und den anderen falsch, sehe ich also nicht als zielführend an. Eine Wertung der beiden Lösungen werde ich nicht vornehmen. Das eins oben und eins darunter stehen muss, lässt sich nicht vermeiden. Da sich jedoch die Stringlösung nicht von der allgemeinen Stringbehandlung unterscheidet, lasse ich den Typecast in diesem Abschnitt an erster Stelle stehen (und füge %d hinzu), um ihn als eine Alternative zur Standardbehandlung zu verdeutlichen.

                    Lo!

  5. Hi.

    Ich weiss nicht, ob Bemerkungen zu dem Artikel noch offene Ohren des Autors vorfinden, oder ob es dazu zu spaet ist. Aber eine Sache hat mich irritiert.

    Die erste und oberste Frage, die sich einem Leser stellen duerfte, wenn er diesen Artikel liest, ist wohl: "Was ist ein Kontextwechsel?". Antwort zunaechst - klar -: der Wechsel des Kontextes.
    Bleibt die Frage: "Was ist ein Kontext?" Und diese Frage beantwortet der Artikel *nicht*.

    Der zentrale Begriff "Kontext" (ebenso "Kontextwechsel") wird in dem Artikel in durchaus verschiedenen Variationen gebraucht, erklaert wird er nirgendwo. Ich hielte es fuer nicht so leicht, im Hinblick darauf eine Definition des Begriffes hinzuschreiben, die dem in irgendeiner Form gerecht wird. Also frag ich mal nach, stellvertretend fuer die generische Leserin: "Was ist denn ein Kontext?"

    Viele Gruesse,
    der Bademeister

    1. Hi!

      Ich weiss nicht, ob Bemerkungen zu dem Artikel noch offene Ohren des Autors vorfinden, oder ob es dazu zu spaet ist.

      Offene Ohren finden sie schon, aber die Argumente müssen mich überzeugen.

      Die erste und oberste Frage, die sich einem Leser stellen duerfte, wenn er diesen Artikel liest, ist wohl: "Was ist ein Kontextwechsel?". Antwort zunaechst - klar -: der Wechsel des Kontextes.
      Bleibt die Frage: "Was ist ein Kontext?" Und diese Frage beantwortet der Artikel *nicht*.

      Wenn du nochmal aufmerksam die Abschnitte "Einleitung" und "Programmcode und Daten" liest, bleibst du dann bei deiner Meinung? ;-)

      Wenn man die Bedeutung von Wort X nicht kennt, so war es früher durchaus üblich, in einem Nachschlagewerk nachzusehen. Ich kann nicht alles haarklein erläutern. Jedoch denke ich, durch die Einleitung und den nachfolgenden Abschnitt deutlich gemacht zu haben, was das Problem ist und besonders der Teil zwischen dem zweiten und dritten Beispiel-Kasten sollte die Begriffe Kontext und Kontextwechsel erläutern.

      Wenn du bereits im Vorwort den dort verwendeten Begriff Kontextwechsel erläutert sehen willst, müsste ich da schon mit der Einleitung beginnen und dann beißt sich irgendwie die Katze in den eigenen Schwanz.

      Lo!

      1. Hi dedlfix,

        Offene Ohren finden sie schon, aber die Argumente müssen mich überzeugen.

        Ich gebe zu, mit wirklichen Argumenten habe ich auch gespart. Dann werde ich mir nun auch die Zeit nehmen, das nachzuholen.

        Vorneweg eine Anmerkung: Der eine oder andere mag das Folgende als ziemlich pedantisch ansehen. Sei's drum - ich tu das nicht. Ich finde den Artikel inhaltlich gut, er zeigt im wesentlichen die meisten kritischen Situation im Hinblick auf Zeichenmaskierung gut auf und ist daher eine gute Uebersicht fuer halbwegs fortgeschrittene (was immer das heisst) PHP-Programmierer. Er ist aber formal sehr unpraezise, so dass ich glaube, dass Anfaenger, die kein Grundverstaendnis fuer die Problematik mitbringen, bei der Lektuere des Artikels grosse Schwierigkeiten haben werden, dieses Verstaendnis zu erlangen. Nicht zuletzt schreibe ich das im Hinblick auf diesen Thread, indem ein Anfaenger zwar die formale Funktionsweise verschiedener Escape-Funktionen kannte, aber keinerlei Verstaendnis fuer ihren Einsatzzweck hatte.

        ---------------------------------------------------------------------

        Bleibt die Frage: "Was ist ein Kontext?" Und diese Frage beantwortet der Artikel *nicht*.

        Wenn du nochmal aufmerksam die Abschnitte "Einleitung" und "Programmcode und Daten" liest, bleibst du dann bei deiner Meinung? ;-)

        Ja. Ich versuche im folgenden mal zu verstehen, was ein Kontext ist.

        [...] und besonders der Teil zwischen dem zweiten und dritten Beispiel-Kasten sollte die Begriffe Kontext und Kontextwechsel erläutern.

        Dem hier angesprochenen Abschnitt entnehme ich, dass ein Kontext (z.B.) ein Teil eines PHP-Programmcodes ist. Etwa ein Teil, der aus einem Stringliteral besteht, oder ein Teil, der aus "Code" besteht. Auszug:

        Das Anführungszeichen hat bereits die Bedeutung des Kontextwechsels zwischen Code und Daten.

        Ok, das nehme ich erstmal so hin. Aber spaetestens in dem Abschnitt ueber "geschachtelte" Kontextwechsel wird manches damit etwas problematisch:

        Um den String jedoch beispielsweise in einem SQL-basierenden Datenbanksystem abzulegen, muss er in ein SQL-Statement eingebettet werden [...]

        Nein, das ist *falsch*! Um den String in einem SQL-basierenden Datenbanksystem abzulegen, muss ein (ggf.) *anderer* String, naemlich sein SQL-Literal, in ein SQL-Statement eingebettet werden. Warum Du Dich hartnaeckig weigerst, von Literalen zu sprechen, kann ich nicht nachvollziehen, denn darin steckt des Pudels ganzer Kern.

          
        
        > $sql = "SELECT feldliste FROM tabelle WHERE feld='$variable'";  
        
        

        In diesem Beispiel kommen zwei geschachtelte Kontextwechsel vor

        Kann ich (im Hinblick auf obige Erklaerung von "Kontextwechsel") nicht nachvollziehen. Hier steht PHP-Code mit einem einzigen Kontextwechsel: "Code zu Daten". Und wenn es doch zwei sind, wo ist der zweite Kontextwechsel (echte Frage!)? Ist er da, wo das spaetere SQL-Statement anfaengt (also am Beginn des PHP-Strings) oder da, wo die "Daten" desselben anfangen, also beim ersten "'". Ich wuerde letzteres vermuten, aber spaeter schreibst Du etwas von "SQL-Kontext". Was ist das? Das ist nicht konsistent mit den obigen Kontexten "Code" und "Daten" innerhalb von PHP-Skripten. Viel eher wuerde ich wiederum Code- und Daten-Kontext (innerhalb von SQL-Statements) erwarten, als einen SQL-Kontext.

        Wenn ich nun weiterlese, stolpere ich u.a. ueber folgende Saetze.

        Im Browser angezeigt hat dieser bereits den HTML-Kontext interpretiert.

        Ein Kontext ist Quelltext?

        Der Kontext, in dem dieser Code steht, ist PHP.

        Ein Kontext ist eine Sprache?

        AJAX ist eine Technik, die im Browser aus dem Kontext JavaScript heraus ausgeführt wird.

        Ok, ein Kontext ist u.U. eine Sprache (s.o.). Aber was um Himmels Willen bedeutet es, dass daraus eine Technik ausgefuehrt wird?

        Notiert man die beiden Kontexte (HTML und JavaScript) in einzelne Anweisungen [...]

        Was???

        Mein Fazit: Ich weiss nicht, was ein Kontext ist. Aus all diesem ein Grundverstaendnis fuer das Thema zu erlangen, wuerde mir ausgesprochen schwer fallen.

        Wenn man die Bedeutung von Wort X nicht kennt, so war es früher durchaus üblich, in einem Nachschlagewerk nachzusehen.

        Wenn ein Fach(!)artikel einen Fach(!)begriff benutzt, dann war es frueher wie heute ueblich, dass er eine Definition oder einen Verweis auf eine Quelle einer Definition liefert. Der Grund ist der, dass ein (nicht fachspezifisches) Nachschlagewerk diese im allgemeinen nicht parat hat.

        Ich meine das uebrigens ernst - ich *weiss nicht*, was "Kontext" (in diesem Kontext ;-)) bedeutet. Und ich weiss auch nicht, warum dieser Begriff so eine zentrale Rolle spielt. Wenn man in den jeweils angesprochenen Beispielen mal hinschreiben wuerde, was wirklich passiert, d.h. die Begriffe Maskierung und Literal exzessiv und *praezise* benutzte, dann braeuchte man den Begriff Kontext wahrscheinlich ueberhaupt nicht. Dass er hier im Forum ein Modewort ist, aendert daran nichts. Und wenn er doch so wesentlich gebraucht wird, dann muss die Frage gestattet sein, was er bedeutet.

        So, jetzt hab ich ganz schoen ausgeholt - dafuer jetzt noch was anderes: Ich habe selber aus dem Aritkel was lernen koennen, und zwar im Hinblick auf die Unterschiede der Notwendigkeit von Maskierungen von JavaScript-Code in <script>-Elementen und in Eventhandlern. Dafuer also "Vielen Dank" an Dich von einem Leser. :-)

        Viele Gruesse,
        der Bademeister

        1. Hi!

          Ich gebe zu, mit wirklichen Argumenten habe ich auch gespart. Dann werde ich mir nun auch die Zeit nehmen, das nachzuholen.

          Danke. Damit kann ich doch wenigstens was anfangen.

          Ich finde den Artikel inhaltlich gut, [...] Er ist aber formal sehr unpraezise, so dass ich glaube, dass Anfaenger, die kein Grundverstaendnis fuer die Problematik mitbringen, bei der Lektuere des Artikels grosse Schwierigkeiten haben werden, dieses Verstaendnis zu erlangen. Nicht zuletzt schreibe ich das im Hinblick auf diesen Thread, indem ein Anfaenger zwar die formale Funktionsweise verschiedener Escape-Funktionen kannte, aber keinerlei Verstaendnis fuer ihren Einsatzzweck hatte.

          Es wird immer jemanden geben, der auch bei der besten Formulierung Verständnisprobleme hat. Besonders, wenn derjenige sich auf etwas eingeschossen hat und schwer von seinem Standpunkt wegzubringen ist beziehungsweise von seinem Denkfehler zu überzeugen ist.

          Bleibt die Frage: "Was ist ein Kontext?" Und diese Frage beantwortet der Artikel *nicht*.
          [...]
          [...]

          Als Idee habe ich, die Kontexte nicht nur im Fließtext nochmal einer genauen Begutachtung zu unterziehen sondern sie in den Beispielen auch mit dem (dezenten) Einsatz von (Hintergrund-)Farbe (inklusive Legende) zu verdeutlichen.

          Mitunter braucht man auch zeitlichen Abstand, um sein eigenes Geschriebsel kritisch betrachten zu können.

          Um den String jedoch beispielsweise in einem SQL-basierenden Datenbanksystem abzulegen, muss er in ein SQL-Statement eingebettet werden [...]
          Nein, das ist *falsch*! Um den String in einem SQL-basierenden Datenbanksystem abzulegen, muss ein (ggf.) *anderer* String, naemlich sein SQL-Literal, in ein SQL-Statement eingebettet werden. Warum Du Dich hartnaeckig weigerst, von Literalen zu sprechen, kann ich nicht nachvollziehen, denn darin steckt des Pudels ganzer Kern.

          Soweit ich mich erinnere, wurde der Begriff Literal jetzt zum ersten Mal und von dir thematisiert. Aus der bisherigen Nichtverwendung eine noch dazu hartnäckige Weigerung herauszulesen, finde ich schon etwas gewagt. Ob die Verwendung des Begriffs "Literal" zum Verständnis beiträgt, werde ich betrachten. Man kann aber auch durch Übergenauigkeit mehr verwirren als aufklären. Der erwähnte Satz sollte erst einmal zeigen, dass der Transport des Wertes wieder in einem anderen Kontext erfolgt, und dass dabei ebenfalls die bekannte Mischung aus Code und Daten zu berücksichtigen ist. Erst jetzt käme das Literal (die Darstellung des Wertes in SQL-gerechter Notation) zum Einsatz, als eine Lösung des Problems. Der nachfolgende Satz sollte beschreiben, was dabei zu beachten ist - allerdings ohne dass er das "Literal" zu verwendet hat. Generell werde ich nochmal prüfen, inwieweit ich es noch verständlicher und betonender einarbeiten kann, wie Werte unbeschadet eine Einbettung / einen Kontextwechsel überstehen.

          Das Problem "ich habe einen Wert und will den eigentlich nur transportieren" als das was man eigentlich will, und dass der Kontextwechsel "nur" eine in Abhängigkeit dazu zu beachtenden Notwendigkeit ist, hatte ich in meiner ersten Version so nicht berücksichtigt. Darauf hatte mich Sven Rautenberg aufmerksam gemacht, aber sich dann leider nicht mehr an der weiteren Diskussion beteiligt.

          Die Idee mit dem Literal hat was. Die Problematik lässt sich damit zusammenfassen: "Ich haben einen Wert. Den muss ich zum Zwecke des Transports in einen anderen Kontext einbauen. Dazu darf nicht der Wert selbst eingefügt werden sondern sein Literal. Neues Problem: Wie bilde ich das Literal des Wertes?" - Hmm, das sieht nach einem generellen Umformulieren aus ... Ich denke darüber nach.

          [einige Beispiele]

          Werde ich mir genauer anschauen, auch wenn ich jetzt hier nicht im einzelnen darauf eingehe.

          Mein Fazit: Ich weiss nicht, was ein Kontext ist. Aus all diesem ein Grundverstaendnis fuer das Thema zu erlangen, wuerde mir ausgesprochen schwer fallen.

          Das Problem ist, du weißt es bereits und stellst dich vielleicht grad etwas bockig, um deinen Standpunkt zu verteidigen. :-) Die meisten, die es nicht wissen oder verstehen, geben kein Feedback oder können keine zielgerichtete Kritik formulieren.

          Ich meine das uebrigens ernst - ich *weiss nicht*, was "Kontext" (in diesem Kontext ;-)) bedeutet. Und ich weiss auch nicht, warum dieser Begriff so eine zentrale Rolle spielt. Wenn man in den jeweils angesprochenen Beispielen mal hinschreiben wuerde, was wirklich passiert, d.h. die Begriffe Maskierung und Literal exzessiv und *praezise* benutzte, dann braeuchte man den Begriff Kontext wahrscheinlich ueberhaupt nicht.

          Es ist immer schon, wenn es einen Begriff für etwas gibt oder man einen dafür findet. Das erleichtert das Beschreiben und auch das Verständnis, wenn man nicht immer darum herum formulieren muss. Natürlich muss zum einen die Definition klar sein und zum anderen die Verwendung dann auch richtig sein, damit es nicht zu Missverständnissen kommt.

          Eine Verdeutlichungsidee habe ich ja oben schon genannt.

          So, jetzt hab ich ganz schoen ausgeholt

          Gib's mir! :-) Aber im Ernst: Danke für die Kritik. Wenn dir oder jemand anderem noch etwas einfällt, immer her damit. Sicher werde ich nicht alles berücksichtigen können, aber als Anregung werde ich es aufnehmen.

          Lo!