Autor Zpráva
moskyt
Profil
Zdravím,

Mám v proměnné určitý text, který obsahuje výraz O'Dowd

Chci tímto výrazem nahradit jiný, který mám v databázi přes $zmena = mysql_query("update...

Problém je v tom, že kvůli tomu O' nahradit nejde. Nemohu ten znak vyescapovat, protože těch náhrad potřebuji udělat více, musel bych ručně všechny texty procházet a všechny znaky escapovat. Dá se to nějak řešit?

Předem díky za radu.
pcmanik
Profil
moskyt:
mysqli_real_escape_string
mckay
Profil
moskyt:
Podíval bych se pro jistotu ještě na bezpečnostní a praktický aspekt tohoto postupu.

Z praktického hlediska - takto budete ukládat do databáze jiný text než ve skutečnosti máte v proměnné. To povede k tomu, že v budoucnosti, když budete data získávat zpátky z databáze, budete muset text dát do původního stavu, v jakém byl, než jste ho z-escapoval funkcí, kterou Vám pcmanik poradil. Což samozřejmě, nejspíš i velice snadno, půjde, ale nabízí se otázka - proč? Ostatně, nebylo by lepší mít v databázi přesně ta data, která jste nějakým způsobem obdržel?

To už mě vede k bezpečnostní stránce celé věci. V prvé řadě bych asi na Vašem místě přestal používat dnes již zastaralé mysql_* prefixované funkce a přešel na doporučované, novější mysqli_* prefixované funkce. Problém se znaky apostrofu v textu, který ukládáte vzniká tam, kde se ve vašem update dotazu nahradí název proměnné jejím obsahem a apostrof naruší dotaz, který jste původně chtěl do databáze zastal a udělá z něj jiný, v tomto případě snad neproveditelný (tohoto využívá útok zvaný SQL injection, kterému se chcete v produkčním kódu vždy bránit).

Dle mého přesvědčení by bylo rozumnější tento problém vyřešit pomocí prepared statements a parametrizace dotazu, a to zhruba nějak následovně:

$text = "Blah blah blah O'Dowd"; // Text co chcete vložit do databáze pomocí UPDATE dotazu

// věnujte pozor otazníku, to je právě ten parametr dotazu, který musíte následně navázat
$preparedStatement = mysqli->prepare("UPDATE ... SET sloupec = ? WHERE ... "); 

// "s" znamená, že budete vkládat string (řetězec), $text je vaše proměnná obsahující text s potenciálně nebezpečnými znaky
$preparedStatement->bind_param("s", $text); 

// Zde nakonec dotaz provedete
$preparedStatement->execute(); 

Pointou tohoto kódu je, že se nadále nemusíte příliš starat o to, co Vám přijde nebo co se Vám vyskytuje v proměnných, které používáte v dotazu, vše se takto samo ošetří.

Vše o tom, jak pracovat s mysqli správně, se můžete dočíst zde.
Radek9
Profil
mckay:
budete muset text dát do původního stavu, v jakém byl, než jste ho z-escapoval funkcí, kterou Vám pcmanik poradil
To se ale ecapuje jen pro potřeby toho SQL dotazu (aby byl syntakticky správně) podobně, jako se escapují znaky ve stringu v programovacích jazycích. V DB je potom origiální text, nikoli escapovaný. Každopádně prepared statements jsou určitě lepší volba. Pro rozsáhlejší aplikace potom ORM, které tohle všechno řeší samo v pozadí.
mckay
Profil
Radek9:
Děkuji za upřesnění, moje chyba.

I v případě použití mysqli_real_escape_string(), bych rád však upozornil na problémy, které mohou nastat, pokud si správně nenastavíte kódování spojení (pro referenci viďte políčko "caution" v pcmanikem odkazované stránce). Zjednodušeně jde o to, že je třeba, abyste nastavil pomocí mysqli_set_charset("kodovani") takové kódování s jakým pracujete (v podstatě si ho musíte vynutit). Příklad, kde by to mohlo dělat problémy a vést k SQL injection je zmíněn a popsán např. ze začátku této přednášky (česky).

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: