Gina: Leerzeichen

Hallo,
bin neu hier und hoffe ich mache nichts falsch.

ich habe folgendes Problem:

ich will in einem php-script mit einer Javascriptfunktion
einen String wieder in ein Formularfeld schreiben, den ich aus einer Datenbank geholt habe.

das funktioniert auch wenn im String keine Leerzeichen vorkommen.
Sind Leerzeichen im String,wird garnichts in das Formularfeld geschrieben.

was ist hier falsch?

die php zeilen:

eingabe ins formular:

echo"<input id='song'  name='song' class='mytextinput' value='".htmlentities($_POST['song'],ENT_QUOTES)."'/>";

abspeichrn in Datenbank:

$sql = "UPDATE titel SET song = '".mysql_real_escape_string($_POST['song'])."' WHERE tid ='".$_POST['tid']."';";

link anklicken und in Formularfeld schreiben:
echo "<td><a href='#' onclick=javascript:updatesong('".$dsatz['song']."','".$dsatz['tid']."');>
".$dsatz['song']."</a></td>";

die javascript-funktion:

function updatesong(song,tid)
{
 document.eingabe.song.value= song;
 document.eingabe.tid.value = tid;
}

  1. das funktioniert auch wenn im String keine Leerzeichen vorkommen.
    Sind Leerzeichen im String,wird garnichts in das Formularfeld geschrieben.

    D.h. das JS wird nicht ausgeführt? Was sagt die Fehlerkonsole?

    die php zeilen:

    sind für ein JS Problem uninteressant.

    Struppi.

    1. das funktioniert auch wenn im String keine Leerzeichen vorkommen.
      Sind Leerzeichen im String,wird garnichts in das Formularfeld geschrieben.

      D.h. das JS wird nicht ausgeführt? Was sagt die Fehlerkonsole?

      die php zeilen:

      sind für ein JS Problem uninteressant.

      Struppi.

      Die Fehlerkonsole sagt: unterminated string literal

      1. Bitte zitiere so, dass man sieht worauf due Antwortest, Danke!

        Struppi.

        Die Fehlerkonsole sagt: unterminated string literal

        dann ist klar warum das Skript nicht ausgeführt wird.

        Struppi.

  2. Hi,

    ich will in einem php-script mit einer Javascriptfunktion einen String wieder in ein Formularfeld schreiben, den ich aus einer Datenbank geholt habe.

    du solltest dein Problem schrittweise angehen, d.h. immer einen Schritt nach dem anderen ananlysieren und prüfen, ob in diesem Schritt das herauskommt, was du erwartest. Das nur als algemeiner Rat, denn du hast hier einen Themenkomplex, der PHP, die Datenbank und Javascript enthält.

    das funktioniert auch wenn im String keine Leerzeichen vorkommen.

    Deutet stark auf ein Problem mit Anführungszeichen hin, dazu passt auch die Fehlermeldung, die du in deinem nächsten Posting wiedergibst.

    echo"<input id='song'  name='song' class='mytextinput' value='".htmlentities($_POST['song'],ENT_QUOTES)."'/>";

    Hier sieht's korrekt aus, aber betrachte lieber den clientseitigen Quellcode, so wie er im Browser ankommt. Der ist für JS relevant, und außerdem ist er leichter zu überblicken.

    $sql = "UPDATE titel SET song = '".mysql_real_escape_string($_POST['song'])."' WHERE tid ='".$_POST['tid']."';";

    sieht für mich auch korrekt aus, auch wenn ich nicht gerade der Datenbank-Experte bin.

    echo "<td><a href='#' onclick=javascript:updatesong('".$dsatz['song']."','".$dsatz['tid']."');>".$dsatz['song']."</a></td>";

    Aber hier knallt's. Schau dir diese Zeile mal wirklich im Browser-Quelltext an, dann siehst du sofort, was du vergessen hast. Abgesehen davon, dass das Label "javascript:" in einem Javascript-Eventhandler unsinnig ist.

    So long,
     Martin

    --
    Lieber Blödeleien als blöde Laien.
  3. abspeichrn in Datenbank:

    $sql = "UPDATE titel SET song = '".mysql_real_escape_string($_POST['song'])."' WHERE tid ='".$_POST['tid']."';";

    Ach, noch ein P.S., du weißt das du hier eine grosse Sicherheitslücke hast?

    Struppi.

  4. Liebe Gina,

    echo "<td><a href='#' onclick=javascript:updatesong('".$dsatz['song']."','".$dsatz['tid']."');>
    ".$dsatz['song']."</a></td>";

    wie bereits angemerkt wurde, ist hier ein größeres syntaktisches Problem enthalten. Diese Zeile generiert einen HTML-Code in etwa dieser Form:

    <td><a href='#' onclick=javascript:updatesong('irgend was', 'irgend was anderes');>sonst irgend was</a></td>

    Mit dem Syntaxhighlighting sollte Dir nun klar werden, dass Du den ganzen Krempel (sprich "Wert des onclick-Attributes") in Anführungszeichen setzen solltest, so wie das grundsätzlich immer erfolgen sollte. Und verwende bitte im HTMl-Quelltext nach Möglichkeit _doppelte_ Anführungszeichen. Das hat den Vorteil, dass Du innerhalb solcher doppelten Anführungszeichen einfache (gerade in Deiner JavaScript-Syntax!) benutzen kannst, um somit beides auseinander zu halten. Vergleiche:

    <a href="#" onclick="updatesong('wert 1', 'wert 2');">klick</a>

    Liebe Grüße,

    Felix Riesterer.

    --
    ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
  5. echo "<td><a href='#' onclick=javascript:updatesong('".$dsatz['song']."','".$dsatz['tid']."');>
    ".$dsatz['song']."</a></td>";

    Es mag auf den ersten Blick kürzer scheinen, HTML-Code in PHP unterzubringen und mit echo auszugeben, aber der Vorteil von PHP ist gerade, umgekehrt PHP-Code in HTML unterzubringen. Das heißt, du startest mit diesem HTML:

    <td><a href="#" onclick="updatesong('X', 'Y')">Z</a></td>

    X, Y und Z mal als Platzhalter. Dort montierst du nun die Variablen hinein. Sinnvollerweise maskierst du gleich eventuelle Anführungszeichen in deren Werten.

    Allerdings scheint X dasselbe wie Z zu sein, daher brauchst du dieselbe Information nicht zweimal im HTML unterbringen, sondern kannst im JavaScript auf den Textknoten im a-Element zugreifen. Dabei kommt dann heraus:

    <td><a href="#" onclick="updatesong(this.firstChild.nodeValue, '<?php echo htmlspcialchars($dsatz['tid'], ENT_QUOTES); ?>')"><?php echo htmlspcialchars($dsatz['song'], ENT_QUOTES); ?></a></td>

    Ein weiterer Schritt wäre, HTML- und JavaScript-Code zu trennen und dieses Event-Handling mit JavaScript anzustoßen. Vermutlich hast du viele td-Elemente mit Links. Es würde ausreichen, einem übergeordneten Element einen click-Handler zu geben, der alle a-Elemente überwacht. Da du eine Tabelle hast, könnte das übergeordnete Element ein tr- oder das table-Element sein. Dem verpasst du eine ID, um es einfacher in JavaScript ansprechen zu können.

    // Nach dem Laden des Dokuments führe aus:  
    window.onload = function () {  
       // Vergebe click-Handler an das Element mit der ID tabelle:  
       document.getElementById("tabelle").onclick = handleSongClicks;  
    };  
    function handleSongClicks (e) {  
       if (!e) e = window.event;  
       // Prüfe Zielelement  
       var zielElement = e.target || e.srcElement;  
       if (e.nodeName != "A") return;  
       // Falls ein a-Element angeklickt wurde, fülle Formularfelder:  
       document.eingabe.song.value = this.firstChild.nodeValue;  
       document.eingabe.tid.value = this.title;  
    }
    

    Siehe https://redaktion.selfhtml.org/selfhtml-preview/javascript/einbindung.html

    Die "tid" habe ich jetzt mal im title-Attribut untergebracht, der HTML-Code müsste also einfach lauten:

    <td><a href="#" title="<?php echo htmlspcialchars($dsatz['tid'], ENT_QUOTES); ?>"><?php echo htmlspcialchars($dsatz['song'], ENT_QUOTES); ?></a></td>

    Mathias

  6. Moin!

    ich will in einem php-script mit einer Javascriptfunktion
    einen String wieder in ein Formularfeld schreiben, den ich aus einer Datenbank geholt habe.

    das funktioniert auch wenn im String keine Leerzeichen vorkommen.
    Sind Leerzeichen im String,wird garnichts in das Formularfeld geschrieben.

    was ist hier falsch?

    Das kontextgerechte Escaping fehlt bei dir teilweise, und verursacht deine Probleme. Rede von Glück, dass du selbst drauf gestoßen bist, und nicht irgendein böser Angreifer.

    die php zeilen:
    echo"<input id='song'  name='song' class='mytextinput' value='".htmlentities($_POST['song'],ENT_QUOTES)."'/>";

    Hier ist Escaping vorhanden, der Kontext ist "Baue eine Variable in einen HTML-String ein". htmlentities() ist dafür im Prinzip auch nutzbar - vernünftiger wäre es, einfach nur htmlspecialchars() zu verwenden, denn Entities sind in den allermeisten Fällen nicht notwendig.

    abspeichrn in Datenbank:

    $sql = "UPDATE titel SET song = '".mysql_real_escape_string($_POST['song'])."' WHERE tid ='".$_POST['tid']."';";

    Hier ist Escaping teilweise vorhanden. Der Kontext ist "Baue eine Variable in einen SQL-String ein", und für $_POST['song'] wird das gemacht - für $_POST['tid'] NICHT! BÖSE FALLE!

    link anklicken und in Formularfeld schreiben:
    echo "<td><a href='#' onclick=javascript:updatesong('".$dsatz['song']."','".$dsatz['tid']."');>
    ".$dsatz['song']."</a></td>";

    Hier wird es jetzt richtig komplex, denn es gibt im Onclick-Attribut einen verschachtelten Kontext: "Baue eine Variable in einen Javascript-String ein, und das Ergebnis dann in HTML."

    Du wirst die Anführungsstriche, die den Attributwert begrenzen, vermutlich schon deshalb weggelassen haben, weil diese zwei Kontexte dir reichlich Fehler beschert haben.

    Deshalb mal schrittweise:

    1. Frage: Wenn ein Javascript-String mit einfachen Anführungszeichen oder doppelten Anführungszeichen begrenzt wird, wie ist dann mit diesen Zeichen zu verfahren, wenn sie innerhalb des Strings auch noch mal vorkommen?

    Antwort: Escapen mit einem Backslash. jsvar = "Hallo, \"Welt\"!": oder jsvar = 'Hallo, \'Welt\'!';

    So einen Backslash liefert dir in PHP die Funktion addslashes().

    Folglich wäre der erste Schritt in PHP: Baue eine Variable in einen Javascript-String ein.

    $onclickatt = "updatesong('".addslashes($dsatz['song'])."','".addslashes($dsatz['tid'])."');";

    2. Frage: Wie kommt der Javascript-String jetzt in den HTML-Kontext des Attributs? Klar, mit htmlspecialchars().

    Also:

    echo "<a href=\"#\" onclick=\"".htmlspecialchars($onclickatt)."\">".htmlspecialchars($dsatz['song'])."</a>";  
    
    

    Beachte: Die Variablen werden immer escaped, wenn sie in einem anderen Sinnzusammenhang benutzt werden. Wenn sie aus der Datenbank kommen, sind sie nur "reiner Text". Solchen reinen Text kann man aber nicht problemlos als Javascript-String benutzen, weil ja genau die Anführungszeichen enthalten sein könnten, die den String auch begrenzen sollen. Deshalb Escaping für den Javascript-Kontext.

    Dann der Einbau in HTML: Auch hier können Zeichen, die in "reinem Text" keine Probleme machen, für Ärger sorgen, vornehmlich <, >, & und ". Genau diese Zeichen werden deshalb von htmlspecialchars() entschärft. Noch bevor irgendein Javascript ausgeführt wird, werden die Entschärfungen durch Entities vom Browser wieder dekodiert, so dass das "richtige" Javascript im Attribut steht.

    Ich hoffe, ich habe in der Kürze der Zeit keinen Denkfehler eingebaut. Der wichtigste Punkt ist jedenfalls das doppelte Escaping des Javascripts im onclick-Attribut. Hier wird gerne übersehen, dass der "reine Text" eben nicht nur einen Kontext wechselt, sondern gleich zwei.

    Wie du an den anderen Antworten siehst: Bis jetzt hat das noch niemand moniert, obwohl fehlendes Escaping schon mal angesprochen wurde, und die Antworter zu den hilfreichen Fachleuten dieses Forums gehören. Nichts für Ungut, Jungs. ;)

    - Sven Rautenberg

    --
    "Love your nation - respect the others."
    1. Wie du an den anderen Antworten siehst: Bis jetzt hat das noch niemand moniert

      Über einen dreifachen Kontextwechsel muss man sich nur Gedanken machen, wenn man beliebige Zeichenketten ("reiner Text") in JavaScript-Code in HTML-Attributwerten in PHP-Strings unterbringen will. Solche Hirnwichserei sollte und kann man problemlos vermeiden - von Anfang an.

      Mathias

      1. Über einen dreifachen Kontextwechsel muss man sich nur Gedanken machen, wenn man beliebige Zeichenketten ("reiner Text") in JavaScript-Code in HTML-Attributwerten in PHP-Strings unterbringen will.

        Insofern gälte es, solche Problemstellungen gegen den Strich zu bürsten. Sobald man um die Problematik von "kontextgerechtem Escaping" weiß, gilt es aus ihr hinaus anstatt in sie hinein zu kommen. D.h. die Benutzung von Programmiertechniken, die Escaping unnötig machen oder es einem völlig abnehmen und strukturell überhaupt kein Nicht-Escaping zulassen:

        • Vernünftige Template-Engines statt HTML-in-PHP-Gebastel
        • Datenbankabstraktion mit Prepared Statements statt SQL-Code selbst zusammenbauen
        • Unobtrusive JavaScript statt JavaScript-Code in HTML und PHP-generiertem JavaScript

        Mathias