Martin Hein: mysqldump erzeugt \"

Hallo Forum,

ich lasse per Cronjob auf dem Webserver täglich meine DB
dumpen. Der dadurch erzeugte dump sieht anders aus, als
der dump, den ich über phpmyadmin (phpMyAdmin 2.7.0-pl2)
erzeuge. Der den ich über phpmyadmin erzeuge funktioniert.

Konkrete Frage:

In dem über die Kommandozeile erzeugten Dump werden
doppelte Anführungszeichen mit '' maskiert. In
meinem über phpmyadmin erzeugten Dump werden die
Anführungszeichen ncht maskiert.

Wie sorg ich dafür, dass der über die Kommandzeile
erzeugte Dump so aussieht, wie der den ich über phpmyadmin
erzeuge ?

danke für Tipps und

beste Gruesse,
maritn

  1. Moin!

    Wie sorg ich dafür, dass der über die Kommandzeile
    erzeugte Dump so aussieht, wie der den ich über phpmyadmin
    erzeuge ?

    Indem du es richtig machst.

    Wir wissen ja aber noch nicht mal, was du überhaupt machst. Wie sollen wir da Fehler entdecken?

    - Sven Rautenberg

    --
    "Love your nation - respect the others."
    1. Hallo,

      Wir wissen ja aber noch nicht mal, was du überhaupt machst. Wie sollen wir da Fehler entdecken?

      ich eben auch nicht.

      ich gehe davon aus, das, wenn ich einen Dump mit phpmyadmin erzeuge,
      dass die Funktion mysqldump auf der Kommandozeile anstösst. Mit welchen Parametern verrät phpmyadmin nicht.

      hintere dem Dump, der per Cronjob erzeugt wird, wird wahrscheinlich auch ein Aufruf der Funktion mysqldump stecken. Aber auch das weiss
      ich nicht, weil den Cronjob der T-Systems eingerichtet hat.

      Daher meine Frage (falls das nicht ganz klar war):

      Mit welchem Parameter / welchen Parametern muss ich die Funktion mysqldump aufrufen, damit im Dump " nicht durch \ maskiert
      werden ?

      In der Doku habe ich dazu nicht's gefunden.

      beste gruesse,
      martin

      1. Hello Martin,

        Mit welchem Parameter / welchen Parametern muss ich die Funktion mysqldump aufrufen, damit im Dump " nicht durch \ maskiert
        werden ?

        In der Doku habe ich dazu nicht's gefunden.

        Das Insert-Statement in der erzeugten SQL-Datei muss auch genauso aussehen, wie dasjenige, das Du beim urprünglichen Eintragen des Datensatzes benutzt hast (hättest benutzen sollen).

        INSERT INTO adresse
        VALUES (
          1,
          5,
          '2007-12-07 01:35:54',
          '0000-00-00 00:00:00',
          'unknown',
          'superuser@pc14',
          'Thomas',
          'Schmieder',
          'Mühlenstraße 19',
          '37444',
          'Sankt Andreasberg',
          NULL,
          'Hier soll die "Bemerkung" eingetragen werden\r\nUnd zwar mit 'Häkchen'\r\n',NULL);

        In der letzten Zeile steht ddas Datenfeld mit den Häkchen und Zeilenumbrüchen.
        Welche da maskiert werden müssen, sagt dir das Manual unter
        http://dev.mysql.com/doc/refman/5.1/en/mysql-real-escape-string.html

        Es sind selbstverständlich genau dieselben, die auch PHP ersetzen lassen würde mit seiner gleichnamigen Funktion, indem es nämlich diejenige von MySQL dafür aufruft.

        Characters encoded are

        00h     NUL (ASCII 0)
          0Ah     “\n”
          0Dh     “\r”
          5Ch     “\”
          27h     “'”
          22h     “"”
          1Ah     ^Z   Control-Z (see Section 8.1, “Literal Values”)
                       Dieses Zeichen wurde auf Konsolen zum Beenden der Eingabe verwendet

        Alle anderen Bytecodes sind _für__die__SLQ-Text-Schnittstelle_ unschädlich und müssen daher auch nicht ersetzt werden. In der Datenbank steht dann wieder nur der bereinigte Bytecode. Das ist unter Anderem dafür wichtig, dass man beim Holen von Daten aus der Datenbank keinerlei Rückersetzungen mehr durchführen muss. Man muss die erhaltenen Daten dann nur noch für den Ausgabe-Kontext aufbereiten, also z.B. für HTML fit machen.

        Schau Dir mal in Deinem phpMyAdmin ein generiertes Insert-Statement, dass welche von den Aufgeführten Zeichen enthält, an. Soweit ich mich erinnere, zeigt er das ja an.

        Und wenn  das die Escapes nicht enthält, ist am phpMyAdmin etwas kaputt. Dass man sowas einstellen können müsste, wäre mir nicht einleuchtend. Dit Telebumm macht hier jedenfalls mMn keinen Fehler bei der Erzeugung des Dumps.

        Harzliche Grüße vom Berg
        http://bergpost.annerschbarrich.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau
        Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

        1. Hallo Tom,

          ertsmal vielen Dank für Deine Hilfe!

          es kann schon sehr gut angehen, dass in der Anwendung bei der
          Kommunikation zwischen PHP und MySQL etwas grundsätzlich im
          Argen liegt. Das zu ändern steht ganz weit oben auf meiner
          ToDo-Liste. Ich verstehe aber immernoch nicht genau, was da
          passiert.

          1. Zur Zeit generiere ich ein SQL-Statement, dass Inhalte in die
               DB schreibt in etwa so:

          $content = $_POST['content'];
          if (!get_magic_quotes_gpc())
          $content = addslashes($content);
          $sql_stament = '
          UPDATE table
          SET content = "'.$content.'"';

          ... ich erzwinge m.E. also Slashes.

          1. Wenn ich mir $sql_stament auch der Seite ausgeben lasse, sieht
               das so aus:

          UPDATE table SET
          content = "<div class="cross_image">
          <h1>TEST</h1>";

          ... und habe den Eindruck 1) funktioniert.

          1. Wenn ich dann in meinem phpmyadmin dann content als SQL
               exportiere, sieht das so aus:

          INSERT INTO tabke VALUES ('<div class="cross_image">\r\n<h1>TEST</h1>');

          ... und da sind die Slashes verschwunden.

          Es funktioniert alles so. Deshalb schmeiss ich es nicht über den
          Haufen, bevor mir klar ist, was genau passiert und was ich daran
          ändern muss. Dazu kommt, dass ich da auf einer MySQL<4.1 arbeite,
          was ich eh für einen Misstand halte, der im nächsten Jahr
          abgestellt werden sollte. Bis dahin will ich tiefer in das Thema
          Zeichensätze einsteigen, weil auch das unsauber gelöst ist.

          beste gruesse,
          martin

          1. Moin!

            1. Zur Zeit generiere ich ein SQL-Statement, dass Inhalte in die
                 DB schreibt in etwa so:

            $content = $_POST['content'];
            if (!get_magic_quotes_gpc())
            $content = addslashes($content);
            $sql_stament = '
            UPDATE table
            SET content = "'.$content.'"';

            ... ich erzwinge m.E. also Slashes.

            Diese Vorgehensweise ist unsauber. Die einzige korrekte Funktion zum Escapen für MySQL ist mysql_real_escape_string(). Oder lieber (und wenn verfügbar) mysqli_real_escape_string() (wobei die objektorientierte Nutzung auch die kürzere Schreibweise $x->escape_string() erlaubt).

            Mit anderen Worten: Deine Logik müßte im Prinzip komplett umgedreht werden: Wenn magic_quotes_gpc aktiviert ist (eine schlechte Sache), ist stripslashes() auf die Eingabedaten anzuwenden, ansonsten passiert nichts.

            Und dann wird der String zur Verwendung im SQL-Query mit mysql_real_escape_string() entschärft.

            1. Wenn ich mir $sql_stament auch der Seite ausgeben lasse, sieht
                 das so aus:

            UPDATE table SET
            content = "<div class="cross_image">
            <h1>TEST</h1>";

            ... und habe den Eindruck 1) funktioniert.

            Ja, an der optischen Erscheinungsweise dieses Schrittes wird sich nichts ändern, wenn du die Änderungen unter 1) einarbeitest - nicht in diesem konkreten Spezialfall jedenfalls.

            1. Wenn ich dann in meinem phpmyadmin dann content als SQL
                 exportiere, sieht das so aus:

            INSERT INTO tabke VALUES ('<div class="cross_image">\r\n<h1>TEST</h1>');

            ... und da sind die Slashes verschwunden.

            Das ist vollkommen normal, das muß so sein. Escaping ist für einen Verarbeitungsschritt zuständig, damit Nutzdaten von Steuerdaten getrennt werden können. Am Ende bleiben - und das ist die Absicht dahinter - nur wieder die originalen Nutzdaten übrig.

            Dasselbe hast du ja auch, wenn du einen String mit Anführungszeichen definierst:

              
            $str = "Hallo \"Welt\"";  
            
            

            Die doppelten Anführungszeichen außenrum sind "Steuerdaten", sie steuern, wo PHP Anfang und Ende des Strings erkennt. Die Anführungszeichen innen sind Nutzdaten, und du mußt den Backslash davor schreiben, damit diese sich von den Steuerdaten unterscheiden - die Variable enthält aber nach dieser Programmzeile nur wieder die original gemeinten Anführungszeichen ohne Backslashes.

            - Sven Rautenberg

            --
            "Love your nation - respect the others."
            1. echo $begrüßung;

              INSERT INTO tabke VALUES ('<div class="cross_image">\r\n<h1>TEST</h1>');

              Ergänzung zu dem von Sven gesagten: Die \ vor den " sind in diesem Fall nicht notwendig. Im Gegensatz zum vorher ausgeführten UPDATE-Stetement ist der Wert nun in ' eingefasst, so dass darin " unmaskiert vorkommen dürfen. Es schadet aber auch nicht, wenn die " maskiert wären. mysql_escape_string() (und Konsorten) behandelt generell beide Formen, also ' und ", weil es ja nicht wissen kann, mit welchen Zeichen der String eingefasst ist.

              Das MySQL-Handbuch-Kapitel Language Structure klärt über die für MySQL zu verwendenden schreibweisen auf. "Literal Values" beschäftigt sich mit allen Werten, "Schema Object Names" mit den Bezeichnern für Datenbank-, Tabellen- und Feldnamen.

              echo "$verabschiedung $name";

            2. Hallo Sven,

              Diese Vorgehensweise ist unsauber. Die einzige korrekte Funktion zum Escapen für MySQL ist mysql_real_escape_string(). Oder lieber (und wenn verfügbar) mysqli_real_escape_string() (wobei die objektorientierte Nutzung auch die kürzere Schreibweise $x->escape_string() erlaubt).

              1. ok, wird beherzigt: Jedes in die DB schreiben von Daten!=int
                   soll sauber für mysql 'real' escaped werden.

              Mit anderen Worten: Deine Logik müßte im Prinzip komplett umgedreht werden: Wenn magic_quotes_gpc aktiviert ist (eine schlechte Sache), ist stripslashes() auf die Eingabedaten anzuwenden, ansonsten passiert nichts.

              1. falls das Browser auf die Idee kommt, selbst zu maskieren,
                   sollte man das besser rückgängig machen (stripslashes()).
                   Frage: Kann ich stripslashes() pauschal über die Werte
                   laufen lassen, ohne vorher magic_quotes_gpc abzufragen.

              Für mein Verständnis:
              ---------------------

              Wird jetzt durch diese Vorgehensweise etwas anderes in der
              DB stehen, als jetzt ?

              Oder anders herum:

              Sorgt "mysql_real_escape_string()" dafür, dass jetzt in meiner
              DB z.B. " steht ?

              und:

              Muss ich entsprehend beim auslesen der Daten, (die dann ja
              dargestellt werden sollen) den Schritt auch wieder umgekehrt
              ausführen (so etwas wie unescape?)

              danke und

              beste gruesse,
              martin

              1. Hello Martin,

                1. falls das Browser auf die Idee kommt, selbst zu maskieren,
                     sollte man das besser rückgängig machen (stripslashes()).
                     Frage: Kann ich stripslashes() pauschal über die Werte
                     laufen lassen, ohne vorher magic_quotes_gpc abzufragen.

                Der Browser darf hier nichts maskieren. Er darf nur das für HTTP übliche Transfer-Encoding anwenden und das muss er im HTTP-heasder auch bekannt geben, damit der Server weiß, wie er aus den für die Übertragung codierten Daten wieder Rohdaten zaubern kann.

                Die PHP-Schnittstelle sorgt dann ihrerseits dafür, dass die von Server zur Verfügung gestellten Environment-Daten im Programm in vorbehandelter Form auftauchen. URLs werden urldecoded, URLs werden geparsed und am eingestellten Trennzeichen in Parameter zerlegt, Post- und Getparameter werden ggf. in Arrays umgeschrieben und in die Variablen (Arrays) geschrieben. Punkte in den Bezeichnnern werden zu Unterstrichen (Beispiel: $_POST['imagebutton_X'], $_POST['imagebutton_Y']) und die Maskierung mit "Magic Quotes" wird durchgeführt. Ich hoffe, sich habe hier nix vergessen.

                Wird jetzt durch diese Vorgehensweise etwas anderes in der
                DB stehen, als jetzt ?

                Das hatte ich schon ausführlich beschrieben
                https://forum.selfhtml.org/?t=163209&m=1062714

                Harzliche Grüße vom Berg
                http://bergpost.annerschbarrich.de

                Tom

                --
                Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                Nur selber lernen macht schlau
                Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

              2. echo $begrüßung;

                1. ok, wird beherzigt: Jedes in die DB schreiben von Daten!=int
                     soll sauber für mysql 'real' escaped werden.

                Es schadet nicht, wenn auch Zahlenwerte in Hochkomma oder Anführungszeichen eingeschlossen werden. Ein SQL-Statement ist immer Text, egal, ob die Zahl nun als 42, '42' oder "42" notiert ist. In allen Fällen muss sie in eine Zahl umgewandelt werden, wenn sie in einem Zahlen-Feldtyp zu liegen kommen soll. Wenn vom Client eine Zahl (z.B. ein ID-Wert) erwartet wird, dann ist es keine gravierende Mehrbelastung, sie wie alle anderen Werte zu quotieren und zu maskieren. Alternativ kann sie in PHP mit intval() garantiert in einen Integer-Wert gewandelt werden. Zur Not kommt da eben 0 raus, wenn keine Zahl erkannt werden konnte.

                1. falls das Browser auf die Idee kommt, selbst zu maskieren,

                Der Browser ist brav. PHP ist hier das Übel, bzw. dessen Feature "Magic Quotes".

                sollte man das besser rückgängig machen (stripslashes()).
                   Frage: Kann ich stripslashes() pauschal über die Werte
                   laufen lassen, ohne vorher magic_quotes_gpc abzufragen.

                Das ist nicht wirklich empfehlenswert. Pauschal ist zwar gut, aber nur gemäß Example#2, wenn dies einmalig am Script-Anfang erfolgt: http://de2.php.net/manual/en/security.magicquotes.disabling.php

                Wird jetzt durch diese Vorgehensweise etwas anderes in der DB stehen, als jetzt ?
                Sorgt "mysql_real_escape_string()" dafür, dass jetzt in meiner DB z.B. " steht ?

                Nein. Die Maskierung erfolgt nur, weil Werte und Befehlsbestandteile in einem gemeinsamen Text (dem SQL-Statement) stehen sollen. Es ist dabei erforderlich zwischen " bzw. ' als Begrenzungszeichen und als Teil eines Wertes zu unterscheiden. Der SQl-Parser demaskiert die Werte, bevor sie in ein Feld eingetragen werden. MySQL speichert also die Roh-Form der Werte.

                Muss ich entsprehend beim auslesen der Daten, (die dann ja
                dargestellt werden sollen) den Schritt auch wieder umgekehrt
                ausführen (so etwas wie unescape?)

                Der Weg von MySQL zum Client ist anders. Hier kommen die Daten direkt und ohne in einen Text eingebettet zu sein. Du bekommst also bei einem SELECT die Rohform der Werte zurück.

                echo "$verabschiedung $name";

                1. Hallo Jungs,

                  ich glaube, jetzt hab ich's verstanden:

                  1. Wenn "magic_quotes_gpc" -> stripslashes auf Daten aus "Post".
                  2. Daten aus Post mit "mysql_real_escape_string()" escapen.
                  3. Dann in die DB schreiben.

                  Beim Auslesen der Daten muss ich keine Veränderung vornehmen.

                  besten Dank und

                  viel gruesse,
                  martin

                  1. Hello,

                    ich glaube, jetzt hab ich's verstanden:

                    1. Wenn "magic_quotes_gpc" -> stripslashes auf Daten aus "Post".
                    2. Daten aus Post mit "mysql_real_escape_string()" escapen.
                    3. Dann in die DB schreiben.

                    Beim Auslesen der Daten muss ich keine Veränderung vornehmen.

                    So stimmt es.

                    1. kann man mit einre rekursiven Funktion gleich am Anfang tun,
                       oder eben, wenn man darf, spätenstens noch in der .htaccess (Modulversion)
                       oder der lokalen php-ini (CGI-Version) ausschalten

                    2. lässt sich auch wunderbar auf ein Array anwenden, dass nachher zum DS
                       für values() zusammengebaut hat. Man muss nur die Zieltypen NULL und FALSE
                       aussparen.

                    Am besten gleich in einem 'Rutsch' mit einer kleinen eigenen Funktion auf das
                       Array der an die Datenbank zu übergebenden Werte anwenden (geht mit array_map() )

                    ##-----------------------------------------------------------------------------
                       # mysql real escape string with quotes
                       ##-----------------------------------------------------------------------------
                       function mysql_resq($value, $connection, $quote="'")
                       {
                         return $quote . mysql_real_escape_string($value, $connection) . $quote;
                       }
                       #-----------------------------------------------------------------------------

                    und anschließend die Spalten, die mitt NULL oder FALSE belegt werden sollen
                       wieder gezielt überschreiben im Array. Die kennt man ja, weil ihre Werte i.d.R.
                       nicht dierekt aus Dialogfeldern des Formulars, sondern aus Auswertungen (Bedingungen)
                       im Script stammen, die z.B. durch Controls des Formulars (SELECT, RADIO, CKECKBOX)
                       gefüttert werden...

                    3. Nur kontextbezogene Behandlungen sind notwendig.
                       Für die Anzeige im HTML-Kontext eben htmlspecialchars()

                    Harzliche Grüße vom Berg
                    http://bergpost.annerschbarrich.de

                    Tom

                    --
                    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                    Nur selber lernen macht schlau
                    Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

      2. Moin!

        ich gehe davon aus, das, wenn ich einen Dump mit phpmyadmin erzeuge,
        dass die Funktion mysqldump auf der Kommandozeile anstösst. Mit welchen Parametern verrät phpmyadmin nicht.

        Diese Annahme ist FALSCH! PHPMyAdmin nutzt eigenen Code zur Erstellung eines Dumps - und entsprechend auch zum Wiedereinspielen.

        hintere dem Dump, der per Cronjob erzeugt wird, wird wahrscheinlich auch ein Aufruf der Funktion mysqldump stecken. Aber auch das weiss ich nicht, weil den Cronjob der T-Systems eingerichtet hat.

        Diese Information ist ja aber doch wichtig. Bisher hat es sich nämlich so angehört, als ob du selbst den Dump eingerichtet hast und ihn leicht ändern könntest.

        Mit welchem Parameter / welchen Parametern muss ich die Funktion mysqldump aufrufen, damit im Dump " nicht durch \ maskiert werden ?

        Wozu willst du das wissen, wenn du den Dump nicht ändern kannst? Wenn T-Systems den Dump eingerichtet hat, dann sag denen, dass ihr Dumpformat bitte kompatibel mit PHPMyAdmin werden soll - dann regeln die das passend. Entweder, indem sie den Dump ändern, oder indem sie PHPMyAdmin aktualisieren (könnte ja sein, dass du eine uralte Version nutzt, die da ein Problem hat).

        In der Doku habe ich dazu nicht's gefunden.

        Die Doku sagt, dass es für mysqldump einen Parameter gibt, der das Escaping der Datenfelder regelt. Einfach nur nach "escape" suchen, es gibt nur eine Fundstelle im Dokument, mit Verweis auf "LOAD DATA INFILE".

        - Sven Rautenberg

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

          Diese Annahme ist FALSCH! PHPMyAdmin nutzt eigenen Code zur Erstellung eines Dumps - und entsprechend auch zum Wiedereinspielen.

          Danke für die Info !

          Diese Information ist ja aber doch wichtig. Bisher hat es sich
          nämlich so angehört, als ob du selbst den Dump eingerichtet hast »» und ihn leicht ändern könntest.

          Wozu willst du das wissen, wenn du den Dump nicht ändern kannst?
          Wenn T-Systems den Dump eingerichtet hat, dann sag denen, dass
          ihr Dumpformat bitte kompatibel mit PHPMyAdmin werden soll - dann
          regeln die das passend. Entweder, indem sie den Dump ändern, oder »» indem sie PHPMyAdmin aktualisieren (könnte ja sein, dass du eine »» uralte Version nutzt, die da ein Problem hat).

          Ich will wissen, ob es generell geht, weil T-Systems das bisher
          nicht hinbekommen hat und ich einem "geht nicht" ganz gerne
          irgendwie begegne.

          beste gruesse,
          martin