Text formatieren

lisali

Erfahrenes Mitglied
Hallo,

ich benutze diese Funktion, um Werte in die Datenbank zu speichern:

PHP:
<?php 
  //This stops SQL Injection in POST vars 
  foreach ($_POST as $key => $value) { 
    $_POST[$key] = mysql_real_escape_string($value); 
  } 

  //This stops SQL Injection in GET vars 
  foreach ($_GET as $key => $value) { 
    $_GET[$key] = mysql_real_escape_string($value); 
  } 
?>

Wenn ich jetzt z.B. einen Text schreibe, wo ich mehrere Absätze mache, wird es so in die Datenbank geschrieben:
tetas\r\nasd\r\nsfd\r\nfds\r\nsfd

Jetzt möchte ich gerne das ganze wieder ausgeben, aber mit Zeilenumbrüchen statt den \r und \n's, aber irgendwie klappt das nicht... ich hab schon die html decode Funktion, nl2br, usw. probiert.
 
Kannst du kurz posten, wie du die Ausgabe umgesetzt hast? Die Funktion nl2br macht eigentlich genau das, was du möchtest. Unabhängig davon ist es nicht unbedingt von Vorteil, die beiden globalen Arrays komplett (blind) zu escapen. Unter Umständen ist dies sowie schon der Fall, wenn deine Server Einstellung Magic Quotes auf "on" steht. Wenn beispielsweise eine Fehler auftritt und die Werte nicht in die DB gespeichert sondern erneut im Formular ausgegeben würden, kann es zu unschönen Effekten kommen.

Grüße BN
 
Ich habe testweise folgendes benutzt:

$text = nl2br( $row['text'] );

Du meinst, wenn in der php.ini Magic Quotes auf on ist?

Ja, ich habe die Funktion eigentlich übernommen, um mir die Schreibarbeit zu sparen. Hast du dafür einen besseren Ratschlag? Welche Eingaben sollte ich denn nicht mit der Funktion versehen?
 
Um zu prüfen, ob die Server Einstellung Magic Quotes auf "on" gesetzt ist, kannst du dich der Funktion get_magic_quotes_gpc bedienen. Ich handhabe es so, dass ich den Wert einmalig in einer zentralen Konfiguration abfrage und in einer Konstante speichere:
PHP:
define ('MAGIC_QUOTES_ON',  function_exists ('get_magic_quotes_gpc') && get_magic_quotes_gpc ());

Da meines Wissens ab PHP6 Magic Quotes entfernt wird, ist es wichtig zu prüfen, ob die Funktion get_magic_quotes_gpc überhaupt zur Verfügung steht. Daher zunächst die Prüfung function_exists und anschließend das Abfragen der Funktion...

Ich empfehle dir, nur die Werte mittels mysql_real_escape_string zu escapen, die
a) unmittelbar in die DB gespeichert werden sollen und
b) Zeichenketten beinhalten (erwartest du einen Integer würde ich casten bzw. Fehleingaben entsprechend abfangen)

Beispiel:
PHP:
// in deiner zentralen Konfigurations-Datei
define ('MAGIC_QUOTES_ON', function_exists ('get_magic_quotes_gpc') && get_magic_quotes_gpc ());


// in einer zentralen Funktions-Bibliothek
/**
 * Escaping von Zeichenketten unter Berücksichtigung 
 * der Server Einstellung Magic Quotes
 *
 * Ist die Einstellung Magic Quotes "on" gesetzt, wird das durch den Server
 * vorgenommene Escaping entfernt (stripslahes). Doppel Escaping ist somit
 * ausgeschlossen.
 *
 * @param string $param
 * @return string
 */
function dbQuote ($param)
{
  if (MAGIC_QUOTES_ON)
  {
	$param = stripslashes ($param);
  }
  
  return mysql_real_escape_string ($param);
}


// dein Script
mysql_query ("
  UPDATE	tabelle
  SET		firstname = '" . dbQuote ($_POST ['firstname']) . "',
			name = '" . dbQuote ($_POST ['name']) . "',
			street = '" . dbQuote ($_POST ['street']) . "',
			nr = '" . (int) $_POST ['nr'] . "'
  WHERE		user_id = '" . (int) $_POST ['user_id'] . "'
");

Ich persönlich bevorzuge es, zunächst die vom Server erzeugten Escapings zu entfernen und mich anschließend selbst um das Escaping zu kümmern. Damit stelle ich sicher, dass Eingaben nur dort escaped werden, wo es tatsächlich notwendig ist. Aber das ist hier und jetzt nicht das Thema :).

Deine Ausgabe $text = nl2br( $row['text'] ); führt deshalb nicht zum Ergebnis, da deine Zeilenumbrüche doppelt escaped in der Db liegen. Anstelle von \n steht in der DB \\n. Mit meiner obigen Methodik tritt dieses Verhalten nicht mehr auf.

Grüße BN
 
Ah, ich verstehe! Vielen Dank. Tut mir Leid, dass ich jetzt erst antworte, aber ich hatte mich vorerst mit anderen Dingen beschäftigt.

Ich habe mir das irgendwie viel komplizierter vorgestellt als es ist. Also merke ich mir jetzt wohl einfach das bei Benutzereingaben, ich die Funktion anwenden sollte und bei Zahlen-Angaben immer mit int caste?

Oh .. und eine Frage: Ist es nicht ratsam immer "trim" anzuwenden bei Texten? Ich meine, ich habe vorhin darüber nachgedacht, dass es doch total sinnvoll wäre, wenn das sogar eine Standardfunktion für Benutzereingaben wäre, weil die Leerzeichen vor und nach einem Text total sinnlos sind, egal in welchem Kontext. Oder beachte ich da bestimmte Sachen nicht?

Edit: Vielleicht kann ich gleich eine generelle Frage zu dem Escapen stellen. Müsste ich denn das selbe Schema bei einem SELECT anwenden oder nur bei einem INSERT und UPDATE?
 
Zuletzt bearbeitet:
Hi lisali,

ich kommentiere dich der Einfachheit und hoffe dass es für dich ok ist.

Also merke ich mir jetzt wohl einfach das bei Benutzereingaben, ich die Funktion anwenden sollte und bei Zahlen-Angaben immer mit int caste?
Es ist nicht immer sinnvoll, einfach blind zu casten. Unter Umständen muss der Benutzer auch über seine Fehleingabe informiert werden. Wichtig ist beim Speichern in die DB nur, dass dort keine Injections auftreten können. Und dafür sind Quoting und Casting gute Mittel.
Oh .. und eine Frage: Ist es nicht ratsam immer "trim" anzuwenden bei Texten? Ich meine, ich habe vorhin darüber nachgedacht, dass es doch total sinnvoll wäre, wenn das sogar eine Standardfunktion für Benutzereingaben wäre, weil die Leerzeichen vor und nach einem Text total sinnlos sind, egal in welchem Kontext. Oder beachte ich da bestimmte Sachen nicht?
Das musst du selbst abschätzen. Sofern du Eingaben mit führenden oder anhängenden Leerzeichen erwartest, kannst du entsprechend darauf reagieren. In der Regel macht es wahrscheinlich Sinn, Zeichenketten mit trim zu behandeln. Weiterhin kann es sinnvoll sein, aus einzeiligen User-Input (type=text; z.B. Vorname, Nachname, etc.) Zeilenumbrüche zu entfernen. Manche User kopieren gern mal Dinge in Eingabefelder und nicht selten sind darunter dann auch Umbrüche.
Edit: Vielleicht kann ich gleich eine generelle Frage zu dem Escapen stellen. Müsste ich denn das selbe Schema bei einem SELECT anwenden oder nur bei einem INSERT und UPDATE?
Jede Eingabe von Benutzern muss escaped werden. Wenn deine Benutzer zum Beispiel eine Suche ausführen können, solltest du der Eingabe niemals vertrauen und auf jeden Fall quoten oder casten. Um deine Frage eindeutig zu beantworten - ja auch bei SELECT.

Grüße BN
 
Klar, das ist für mich total okay. :)

Kannst du mir ein Beispiel dafür nennen, wo ein Cast weniger sinnvoll ist? Jetzt bei den Zahlen z.B.

Gut, danke. Dann werde ich wohl trim in meine Formatierungsfunktion mit einbauen.

Aber warum eigentlich bei einem Select, wenn es doch eigentlich schon "sicher" ist, weil es bereits in der Datenbank "safe" gespeichert wurde?

Und übrigens werden bei mir Umlaute komischerweiße nur an bestimmten Stellen (bei einem AJAX-Request) nicht zu ä oder ü, usw, sondern zu einem ganz komischen Zeichen. Liegt es daran, dass diese Extra-Ajax-Datei keinen <meta> trägt mit der Angabe der ISO... ?

Dankeschön!
 
Wenn du beispielsweise eine Mengenangabe größer als "0" erwartest und der Benutzer gibt anstelle einer Zahl "bla" ein, dann ist ein stumpfer CAST nicht sinnvoll. Denn eine Menge "0" ((int) $bla) geht zwar in die DB rein, hilft dir aber nicht weiter.

Bei einem Select sind zwar die Daten aus der DB kommend "safe" aber wenn der Benutzer die Suchbedingung beeinflussen kann (bei Suchen üblich), ist genau seine Eingabe nicht "safe".

schlecht:
Code:
SELECT * FROM user WHERE username LIKE '" . $_POST ['searchterm'] . '"

besser:
Code:
SELECT * FROM user WHERE username LIKE '" . mysql_real_escape_string ($_POST ['searchterm']) . '"
(Anstelle mysql_real_escape_string kannst du natürlich auch eine andere Funktion verwenden)

Wenn Umlaute über AJAX (eigentlich auch generell) nicht korrekt ankommen, deutet das auf ein Zeichensatzproblem hin. Es ist durchaus ratsam, während der Server-Kommunikation folgenden Header zu setzen:
Code:
// html-Ausgabe
header ("Content-Type: text/html; charset=utf-8");

// JSON / TEXT-Plain
header ("Content-Type: text/plain; charset=utf-8");

Die Angabe im Charset ist dabei entscheidend, um die Zeichensatzprobleme zu beseitigen. (UTF-8 muss bei dir nicht zutreffen.) Der Content-Type regelt die Art der Ausgabe und somit die Art, wie der empfangende Browser die Daten verwertet (ausgibt).

Grüße BN
 
Ah, verstehe. Also, wenn eigentlich ein String sowohl als auch eine Zahl angegeben werden darf, caste ich eher nicht.

Okay, stimmt.. das mit dem Suchen habe ich nicht bedacht. Dankeschön!

Also, da bin ich selbst noch irgendwie unser welches charset ich nehmen soll und ich habe jetzt einfach in meiner Hauptdatei <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de"> definiert und in der CSS @charset "ISO-8859-1";

Was wäre denn das optimalste, damit es keine Probleme mit Umlauten oder sonstigen gibt? Vielleicht auch bezogen auf die Funktion, die du mir gegeben hast zum Escapen.
 
Ich würde dir an sich gern UTF-8 ans Herz legen, aber UTF-8 hat im Zusammenhang mit PHP Tücken, die man kennen muss. ISO-8859 geht völlig in Ordnung. In der DB sollten die Textfelder dann latin1 codiert werden.

Grüße BN
 
Zurück