Escapování

Školení, která pořádám

Článek vyšel v rámci PHP okénka na serveru Root.cz.

V PHP jsou tři základní escapovací funkce, které se používají v různých situacích: addslashes, htmlspecialchars a urlencode.

Funkce addslashes se používá většinou při ukládání dat do databáze. Funkce doplní zpětné lomítko před apostrof, uvozovky a zpětné lomítko, takže text obsahující tyto znaky obalený apostrofy nebo uvozovkami může být bez obav použit v SQL dotazu. Při ukládání proměnných zvenku tuto funkci používejte pouze v případě, že není zapnutá direktiva magic_quotes_gpc, jinak dojde k dvojitému escapování. Některé databáze (např. MySQL) si vystačí s touto funkcí i při ukládání binárních dat, jiné pro escapování těchto dat potřebují použít vlastní funkci – např. SQLite používá funkci sqlite_escape_string.

Funkce htmlspecialchars se používá při vypisování textu, ve kterém nechceme interpretovat HTML značky – řídící znaky <>"& se převedou na odpovídající HTML entity – tedy např. < na &lt;. Použití této funkce by mělo být samozřejmostí při vypisování neošetřeného textu a při používání proměnných v hodnotách atributů HTML značek, např. value.

<?php
// špatně - proměnná může obsahovat speciální HTML znaky
echo "<input name='search' value='$_GET[search]' />\n";

// špatně - proměnná může obsahovat apostrof
echo "<input name='search' value='" . htmlspecialchars($_GET["search"]) . "' />\n";

// správně - případné uvozovky jsou spolu s ostatními speciálními znaky defaultně escapovány
echo "<input name=\"search\" value=\"" . htmlspecialchars($_GET["search"]) . "\" />\n";

// správně - escapován bude i apostrof
echo "<input name='search' value='" . htmlspecialchars($_GET["search"], ENT_QUOTES) . "' />\n";
?>

Funkci htmlspecialchars je zvykem používat na výstupu, i když by ji z výkonnostních důvodů bylo někdy lepší použít např. už při ukládání dat do databáze. Nedělá se to ze dvou důvodů – jednak by kvůli větší délce escapovaného textu mohl být řetězec zkrácen přesto, že uživatel maximální délku nepřekročil, a jednak by někdo do databáze mohl nestandardním způsobem vložit neošetřená data, která by při výpisu způsobila paseku. Zkrácení řetězce může mít závažné důsledky, pokud k němu dojde uprostřed HTML entity – v extrémním případě to může vést až k nezobrazení celé stránky.

Funkce urlencode se používá při ošetřování řetězce předávaného v URL. Funkce nahradí všechny nealfanumerické znaky kromě -_. jejich URL reprezentací – tedy znakem % následovaným dvojicí hexadecimálních číslic (mezera se převede na +). Pokud tedy chceme vytvořit přehled nejčastěji hledaných výrazů, měli bychom to udělat nějak takhle:

<?php
$result = mysql_query("SELECT search, pocet FROM searches ORDER BY pocet DESC LIMIT 10");
while ($row = mysql_fetch_assoc($result)) {
    echo "<li><a href='?search=" . urlencode($row["search"]) . "'>" . htmlspecialchars($row["search"]) . "</a> ($row[pocet])</li>\n";
}
mysql_free_result($result);
?>

Kromě těchto základní escapovacích funkcí v PHP samozřejmě existují další, např. quotemeta nebo preg_quote. Vždycky jde o to zamyslet se nad tím, jestli v daném kontextu náhodou nejsou některé znaky speciální a pokud ano, tak je správně ošetřit. Podle mého názoru je správné escapování jedna z vlastností, které odlišují kvalitní webové aplikace od těch ostatních.

Jakub Vrána, Výuka, 27.4.2005, diskuse: 66 (nové: 0)

Diskuse

DFly:

a take rawUrlEncode()

Kuba:

Jen malá poznámka ke zvýrazňovači php kódu - nevím proč není kód vypisován neproporcionálním fontem. Rozlišit znakové sekvence "' a '" je takhle dost netriviální (já to dělám tak, že označuju znak po znaku myší :o)

ikona Jakub Vrána OpenID:

Proporcionální písmo se mi lépe čte a vejde se ho na stejné místo víc. Lepší rozlišování "' od '" to nepřeváží.

Kuba:

No, já nevím, ale u všech kódů je to tak nějak zvykem...

wyvern:

tak proc tu neudelat nejaky vtipni tlacitko, kterym si budu moct prepnout mezi proporcialni a neproporcialnim..? klidne by na to stacil nejakej jednoduchej javascript...

Jakub:

Tiez to tak robim:)

assimilate:

K uvedeným příkladů, a varianta

<?php echo '<input name="search"
value="'
,htmlspecialchars( $_GET['search'] ),'" />'; ?>

Správně? Špatně?

Martin Sirovy:

Take to pisu takto + pouzivam pokud je to v parametru ENT_QUOTES, tak by me take zajimalo jestli je to ok. Dalsi vec jestli pokud pouzivam apostrofy je nutne psat & jako entitu &amp; nebo staci jen &. Doufam, ze se dockame odpovedi. BTW musim pochavalit autora, nacerpal jsem z tohoto webu hodne uzitecnych tipu .]

ikona Jakub Vrána OpenID:

ENT_QUOTES je nutné používat uvnitř hodnoty atributů uzavřené do apostrofů. & je nutné psát jako &amp; vždy.

Martin Sirovy:

Ok, děkuji za odpověď. Tento to kod je tedy v poradku: <?php echo '<input name="search"
value="'
,htmlspecialchars( $_GET['search'] ),'" />'; ?>

kozotoč:

<?php echo'<input name="search"
value="'
.htmlspecialchars($_GET['search']).'" />'?>

je i o pár ns rychlejší, protože se nemusí řešit případné escapování a desubstituce proměnných mezi dvojitými uvozovkami. pozor, stringy odděluje tečka (afaik).

Megaloman:

Tečka je operátor, který stringy neodděluje, ale spojuje, u konstruktu echo lze tečky nahradit čárkami, což je teprve operátor, který odděluje stringy.

Ovšem v tomto případě na tom nezáleží, protože výsledný výstup bude tak jako tak stejný...

ikona Jakub Vrána OpenID:

Je to vžitý omyl. Konstantní řetězec je stejně rychlý v apostrofech jako v uvozovkách.

kozotoč:

Mýlíš se. V příkladu je sice použit konstantní řetězec, ale obsahuje \ a tokeny za ním musí PHP na rozdíl od apostrofového řetězce parsovat. Výrok, že s použitím apostrofů je syntaktická analýza ''o pár nanosekund rychlejší'' je tedy pravdivý. Nehledě na optickou „ošklivost” takového řetězce a potenciální si přidělávání problémů, že to někde zapomenu escapovat a budu muset složitě pátrat kde.

ikona Jakub Vrána OpenID:

Apostrofový řetězec přeci také může obsahovat zpětné lomítko. Nejlepší asi bude to změřit:
<?php
for ($i=0; $i < 1e6; $i++) "abc\"def"; // 0.630249977112
for ($i=0; $i < 1e6; $i++) 'abc"def'; // 0.63881611824
?>
Jedná se o samostatné spuštění jednotlivých variant a medián ze tří pokusů.

ikona v6ak:

Myslím si sice, že pro výkonovou optimalizaci je málo podstatné, zda používám apostrofy nebo uvozovky, myslím, že používáš špatnou metodu testování (bavím se o php4 a vyšším, ne o php3). Kód se parsuje na začátku asi do nějakého vykonávacího stromu (zde bych použil Composite, ale nevím, jak to je v php). Přitom se IMHO parsují i řetězce a při vykonávání pak není poznat rozdíl mezi řetězci s jinou syntaxí. Pokud chceš porovnávat dobu parsování, pak je potřeba použít jiný prostředek, třeba eval, tady by bylo jeho použití IMHO namístě (i když T9 mi nabízí f*ck :-D ). Momentálně nemůžu otestovat, nemám po ruce php, jen javascript, C  a Brainfuck.

IMHO však budou apostrofy nepatrně rychlejší, nemusí očekávat $. Ale to záleží na algoritmu.

ikona Jakub Vrána OpenID:

Výrok, že syntaktická analýza je o pár ns rychlejší, je pravdivý, původní komentář ale ne - celkový běh je rychlejší s uvozovkami.

Pokud se totiž bavíme o výkonnosti, je doba parsování zanedbatelná, protože při použití akcelerátoru se parsuje jen jednou, zato vykonává se opakovaně.

ikona David Grudl:

Když se oba řetězce přeloží na stejný opcode, tak nemůže být v běhu rozdíl. BTW akcelerátory se používají naprosto sporadicky.

ikona Jakub Vrána OpenID:

Jaká je příčina rozdílu, netuším - prostě jsem to změřil. Máš pravdu, že se to přeloží na stejný opcode.

Akcelerátory se u projektů, kterým přestává stačit jeden server, používají zcela běžně. Na sdíleném webhostingu samozřejmě méně.

ikona David Grudl:

Ještě k větě "při použití akcelerátoru se parsuje jen jednou, zato vykonává se opakovaně" - asi trošku slovíčkařím, ale pokud se nepletu, přítomnost akcelerátoru na serveru (např. Zend Optimizeru nebo ionCube loaderu) neznamená použití opcode cache. Třeba Zend Optimizer se dá najít na řadě sdílených webhostingů, akceleruje vykonávání skriptů, ale jako opcode cache začne fungovat až po zakoupení encoderu ($960 je stále dost ;)

ps. Jednou jsem změnil jedno písmenko v názvu nepoužívané proměnné třídy a výkon se zhoršil o 5 %. Je to magie!

ikona Jakub Vrána OpenID:

Otázka je, čemu říkáme akcelerátor. Já tak říkám třeba eAcceleratoru, u kterého je ukládání zkompilovaného kódu pro další použití hlavním úkolem.

A ano, pouhá přítomnost akcelerátoru na serveru ukládání kompilace nezajistí. Např. v situaci, kdy je na serveru APC a není zapnuté apc.enabled :-).

ikona v6ak:

No pokud kde o běh, tak jsem to pochopil jako že to je cca nastejno. A taky nechápu, proč by se to mělo lišit, když ve stromu to bude nejspíš vypadat naprosto identicky. Pokud máš nějaký důvod, sem s ním!
OT: Ta moje T9 je tak deformovaná, že když jsem psal 'sem', napsala 'PDO' :-D

kozotoč:

Páni, ty máš rychlou mašinu. Udělal jsem taky test - z toho, co máš jako příklad v článku.
<?php
$_GET
['search']="a\"b'c\\d\ne";
$t1=microtime(true);
for(
$i=0;$i<1e6;$i++)$a="<input name=\"search\" value=\"" . htmlspecialchars($_GET["search"]) . "\" />";
$t2=microtime(true);
for(
$i=0;$i<1e6;$i++)$a='<input name="search" value="' . htmlspecialchars($_GET["search"]) . '" />';
$t3=microtime(true);
die((
$t2-$t1).' s vs '.($t3-$t2));
?>

Vyhodilo mi to:

2.0504870414734 vs 1.9555149078369

kozotoč:

zkoušel jsem to několikrát (i na začátku jsem inicializoval $a, ($a='';) aby se neřeklo, že se v prvním cyklu musela poprvé vytvořit) a konstantně je případ s apostrofy více než o 1/10 sekundy (tj o více než 100 nanosekund na jeden výskyt) rychlejší.

ještě odpověď na "Apostrofový řetězec přeci také může obsahovat zpětné lomítko": ano, ale zde syntaktický analyzátor PHPka nemusí odskočit na tu část jeho kódu, která by zjišťovala, co vlastně že za ním může být.

Chápu, že se toto může zpracovávat různě (jinak do syntaktického stromu, jinak při Just-In-Time compilaci), ale i tak platí, že uvozovková notace s escapovanýma uvozovkama je celkově o pár ns pomalejší, opticky ošklivější a náchylnější k bugům vzniklým zapomenutím zpětného lomítka.

ikona Jakub Vrána OpenID:

Syntaktický analyzátor funguje nějak takhle:
<?php
$state
= "INIT";
for (
$i=0; $i < strlen($s); $i++) {
    $state = $states[$state][$s{$i}];
}
?>
Složitost je tedy lineární vzhledem k délce kódu. To je taky jediný důvod, proč je apostrofová varianta v tomto případě rychlejší – má méně znaků.

"Odskok na jinou část kódu", o kterém mluvíš, je zadarmo, protože prozkoumání tabulky pro zpětné lomítko zabere stejně času jako prozkoumání tabulky pro apostrof.

kozotoč:

Jakube, prosim tě: přestaň už mlžit a uznej taky jednou svou chybu, že používání textových literálů s apostrofovou notací je celkově (z pohledu rychlosti, optického vzhledu v kódu, náchylnosti k vytovření syntaktické chyby) výhodnější než používání literálů uvozovkových. Vážím si tvé práce, ale tadytímhle „maloJardováním” ztrácíš kredit.

ikona Jakub Vrána OpenID:

Nemlžím a proti apostrofům nic nemám. Nemám ovšem nic ani proti uvozovkám, takže jestli po mě chceš slyšet odsouzení uvozovek, tak se ho nedočkáš. Žádné chyby si nejsem vědom. Chyby vidím v tomto vlákně dvě:

http://php.vrana.cz/escapovani.php#d-4733 (špatný závěr)
http://php.vrana.cz/escapovani.php#d-6982 (špatná metodika)

Autorem těchto příspěvků ovšem nejsem já.

kozotoč:

mno, ale reagovat bych přecijenom mohl.

http://php.vrana.cz/escapovani.php#d-6970 (špatná metodika)

Karel:

Hele, už toho fakt nech a jdi programovat v apostrofech ;-)
Konstantní řetězce (tedy ty, kde není žádná proměnná), které jsou ve dvojitých uvozovkách, se nijak nedesubstituují a jejich zpracování není nijak handicapované oproti apostrofovým. (v tom ses mýlil)

Pokud jsou v jedné notaci řetězce oproti té druhé zpětná lomítka navíc (tj. zbytečně), pak zabere jistý (ale naprosto zanedbatelný) čas zabere jejich první zpracování ve fázi 'parse' (což Jakub připustil) a ve fázi 'execute' se použije stejný bytecode (stejně "rychle"), nezávisle na tom, v jakých uvozovkách řetězec byl. (což je pokud to dobře chápu Jakubova první reakce na tebe v této diskuzi)

ikona David Grudl:

Čas věnovaný této diskusi byl větší, než kolik by se ušetřilo předěláním všech uvozovek ve všech PHP aplikacích :-)

ikona Jakub Vrána OpenID:

Nemůžeš přeci porovnávat dobu běhu kódu na začátku skriptu a na jeho konci… Zkoušel jsi varianty prohodit (tedy nejdřív vyzkoušet apostrofy, potom uvozovky)?

Když chceš porovnat dva kusy kódu, musíš to dělat za stejných podmínek – tedy vytvořit dva skripty obsahující pouze testovaný kód a potom je za stejných podmínek spustit.

Já jsem to udělal a výsledky jsou tyto:
<?php
for($i=0;$i<1e6;$i++)$a="<input name=\"search\" value=\"" . htmlspecialchars($_GET["search"]) . "\" />"; // 1.4262650013
for($i=0;$i<1e6;$i++)$a='<input name="search" value="' . htmlspecialchars($_GET["search"]) . '" />'; // 1.4782140255
?>
Jedná se o samostatné spuštění jednotlivých variant a medián ze tří pokusů.

kozotoč:

Vyhodnocení uvozovkového literálu, který za zpětným lomítkem může mimo několika znaků (jako \t \n) mít (krom jiného) jedno, nebo dvě, nebo tři oktalová číslice nebo x a dvě hexadecimální číslice, není to samé jako apostrofový literál, kde se kontroluje jen apostrof pro ukončení.

Btw. udělal jsem přesně ten samý test, stejnou metodou, jakou popisuješ, a pro uvozovkový literál mi to vyhazuje 3.8289790153503 a pro apostrofový 3.7983191013336 sekund.

Přiznej už prosimtě, konečně, že ses zmýlil - není to žádná ostuda.

ikona Jakub Vrána OpenID:

Už jsem to vysvětloval v příspěvku http://php.vrana.cz/escapovani.php#d-6985. Syntaktickému analyzátoru je úplně jedno, kolik znaků má v daném kontextu nějaký význam. Prostě načte znak a změní stav podle tohoto načteného znaku. Čas změny stavu je konstantní a tedy nezávislý na počtu významových znaků.

Výsledky se mohou lišit, to připouštím. Mě se ale shodují na třech různých počítačích, dvou různých operačních systémech (Windows XP, Linux) a dvou verzích PHP (5.2.6, 5.1.6). A zaráží mě, že tobě vyšly úplně jiné časy než v testu http://php.vrana.cz/escapovani.php#d-6982.

A jak už jsem psal, chyby v tomto vlákně vidím dvě, ani jednu ode mě.

kozotoč:

Můj výrok v prvním ze dvou příspěvků, které označuješ jako chybné, ("...o pár nanosekund rychlejší...") je pravdivý, protože v tomto případě zpracovávají čtyři uzovovky přes \ navíc (přestože by nemusely).
To, čím argumentuju já, má 3 body, druhý z nich je optický vzhled dané notace a třetí je náchylnost k syntaktickým chybám a zdržení a řešení toho "kde jsem zapomněl zpětné lomítko nebo kde mi přebývá uvozovka". V 2/3 a 3/3 je na tom uvozovková notace hůř a tedy celkově (to, co mám na mysli) je na tom uvozovková notace hůř než apostrofová.
(Po žádném odzusování (ani tvém osobním názoru na obě notace) jsem netoužil.)
p.s. ad druhá chyba v threadu.. někam se "ztratil" tvůj post, který ji kritizuje (???)

ikona Jakub Vrána OpenID:

Jak prokázaly tři měření na různých počítačích, operačních systémech a verzích PHP, tak výrok pravdivý není.

Největší tvůj omyl spočívá v názoru, že uvozovkový literál se nutně musí zpracovat pomaleji, protože může přejít do více stavů než apostrofový. Dokud nepochopíš, že na počtu možných stavů nezáleží a záleží jen na délce vstupu, tak je jasné, že se se mnou budeš hádat.

To, že samotná syntaktická analýza je rychlejší (ale výhradně kvůli kratšímu vstupu), jsem nikde nerozporoval a naopak jsem tento fakt podpořil v příspěvku http://php.vrana.cz/escapovani.php#d-6973.

O tom, že apostrofy jsou v tomto případě pěknější a méně náchylné k chybám, jsem se taky nikde nepřel.

Post se nikam neztratil, je na http://php.vrana.cz/escapovani.php#d-6984.

kozotoč:

//muj test dle http://php.vrana.cz/escapovani.php#d-6982 (prvni polovina pro kazdou variantu zvlast, 1. fetch nemeren, zprumerovane)
2.1177170276642 " 2.0763738155365 ' // localhost, WinXP
1.02556681633 " 1.10180020332 ' // flyweb.cz, linux
1.06299996376 " 1.04999709129 ' // flyweb.cz jiny server, linux
1.87020397186 " 1.90944814682 ' // pipni.cz, 2x Xeon 3.20 GHz HT, predpokladam linux (tady bylo zajimave, ze tam byly velke vykyvy - i treba 0.5 s)

ikona David Grudl:

Jak na tom může být obecně uvozovková notace hůř k náchylnosti k chybám a optické čitelnosti? Co když potřebuješ do řetežce zapisovat apostrofy? Co když potřebuješ zapsat znak tabulátoru nebo oddělovače řádků?

ikona Jakub Vrána OpenID:

Já myslím, že to nebylo myšleno obecně, ale jen pro tento konkrétní případ.

kozotoč:

ano, pokud potřebuju vypsat tabulátor, nový řádek, tak samozřejmě použiju uvozovky.

myslel jsem ale případ v tomto článku, např. u použité části řetězce

"<input name=\"search\" value=\""

není opravdu důvod používat uvozovkovou notaci - asi se shodneme na tom, že

'<input name="search" value="'

je lepší. Zejména tam, kde uvozovka v uvozovkami uvozeném řetězci začíná nebo končí, nebo tam, kde se v něm vyskytují vedle sebe mnoho " a \, tam mohou (subjektivně, vjemově) nastávat "zmatky".

ikona Jakub Vrána OpenID:

S tím se dá souhlasit. Důvod použití uvozovek v tomto příkladě je ten, že na konci se používá \n, takže na konci je vhodnější mít uvozovky – z důvodu konzistence jsou i na začátku.

kozotoč:

p.s. v tomhle vláknu vidím chyby ode mně a pak od jedno člověka, který je neumí přiznat. a to mně mrzí :-(

ikona Jakub Vrána OpenID:

Ale já opravdu nevidím žádnou chybu, které bych se dopustil. Můžeš mi ji prosím ukázat?

kozotoč:

Je to v prvních našich vzájemných komentářích na začátku tohoto threadu. Spočívá ve vzájemném nepochopení obecného versus konkrétního použití apostrofů/uvozovek, resp. sémantická chyba v odpovídání na něco jiného než vytyčená otázka/komentář/problém. Já chybu přiznal, ty jako lektor tohoto jazyka a člověk, který mu „perfektně rozumí” nemusíš, protože bys ztratil tvář. (Ta fráze v uvozovkách jsou tvoje slova z http://php.vrana.cz/php-cli.php . Pro mě perfektně = dokonale (počeštění z angličtiny), bez nejmenší chybičky, což implikuje i znalost všech jeho syntaktických elementů, metod, rozšíření, funkcí (viz. např. zde http://php.vrana.cz/kodovani-hlavicek-e-mailu.php#d-3684) apod. Já osobně bych si v životě nedovolil něco takového vypustit z huby, ale ty budeš něco víc.)

ikona Jakub Vrána OpenID:

Samozřejmě také dělám chyby a nemám problém je přiznat. V této diskusi ale opravdu žádné své nevidím. Odkaž mi prosím na příspěvek, kde jsem se chyby dopustil. Obecné „vzájemných komentářích na začátku tohoto threadu“ mě vede k příspěvku http://php.vrana.cz/escapovani.php#d-4733, kde vidím pravdivý výrok „je i o pár ns rychlejší“ zdůvodněný nepravdivým tvrzením „nemusí se řešit případné escapování a desubstituce proměnných“. V další diskusi se zabývám tímto nepravdivým výrokem.

pojízdná kočka:

Inu, Jakube, on má kozotoč pravdu v tom, že buď nějakému jazyku rozumíš dokonale (a pak si můžeš dovolit to napsat), nebo [v něm] děláš chyby (a nemáš problém je přiznat). Nic moc mezi tím.

(p.s. tvůj komentář je o 2 dny starší než ty ve stejné úrovni pod ním, přesto je před nima. čím to?)

ikona Jakub Vrána OpenID:

Ještě ty tady... I když člověk něčemu perfektně rozumí, tak v tom může udělat chybu. A já ji nemám problém přiznat. Jistě bys našel něco, na čem bys mě nachytal, ale v této diskusi to opravdu nevidím.

Příspěvky jsou zdánlivě nesprávně seřazeny proto, že spodní dva mají hloubku 10 a 11 a můj má hloubku 11. Takže jsou seřazeny správně, ale aby se nerozpadl design, tak je maximální zobrazovaná hloubka 10. Tento příspěvek má hloubku 13 a to by prosím už opravdu stačilo.

pojízdná kočka:

Já bych přecejen něco chybného od tebe viděla:
kozotoč ti na začátku tohoto threadu vytknul v 3. řádku (počítáno bez komentářů) 2 zpětná lomítka, která jsou tam zbytečně (oproti apostrofové notaci). Později v diskuzi, když jsi to chtěl demonstrovat na příkladu, jsi tam použil jen jednu uvozovku. Byť se jedná o jeden jediný znak, toto je podle mě špatná metodika (možná záměrně?) a manipulace.

ikona Jakub Vrána OpenID:

Zpětná lomítka jsem použil proto, aby byl kód konzistentní - aby v půlce řádku nebyly apostrofy a v půlce uvozovky. Nepovažuji to ale za nic důležitého, jindy bych to možná napsal jinak.

Na příkladu jsem chtěl ukázat, že zpětné lomítko se vyhodnotí už při kompilaci a při spuštění se provádí stejný bajtkód. Nezáleží na tom, kolik tam těch zpětných lomítek je.

pojízdná kočka:

Myslím, že nemáš tak docela pravdu - víc lomítek => víc času pro PHP kompilátor, který stráví na jejich převádění. Já vím, že v tomto případě jde o nanosekundy, ale nota bene to je přesně to, čím argumentoval kozotoč na začátku tohoto threadu.

pojízdná kočka:

"buď nějakému jazyku rozumíš dokonale (…) nebo [v něm] děláš chyby"

Jakub Vrána: "I když člověk něčemu perfektně rozumí, tak v tom může udělat chybu."

Jakube, netvrdil jsi, že mu rozumíš, ale že mu rozumíš dokonale.
Tady jsi použil manipulace patří mezi logické klamy. Tento logický klam, kterého ses dopustil, se nazývá podsunutý argument. (https://cs.wikipedia.org/wiki/Argumenta%C4%….28straw_man.29 )

ikona Jakub Vrána OpenID:

Z jednoduchého min(30, 3*$hloubka) jsem výpočet změnil na 10 * log(3 + $hloubka) - 10, což by mělo strukturu diskuse zachovat a přitom design nezdeformovat.

kozotoč:

oprava: v tom, že jde o nanosekundy, by se dalo souhlasit, v tom, že se desubstituce zabírá u dvojitých uvozovek extra čas, pravdu neměl.

Karel:

Tohle se mi přestává líbit. Jakubovy stránky jsou výborný zdroj pro začínající i pokročilé PHPčkaře; neměli bychom zacházet k osobním útokům a dělat z toho flamewars mimo dané téma.

kozotoč:

O.K. – mír. Pochopil jsem a uznávám 1/3 toho, co jsem vytknul: že použití uvozovek bez zbytečných vnořených uvozovek je přinejmenším stejně rychlé jako apostrofové řešení.

kriplozoik:

speciální případ je, když necháme uživatele zadat něco, co pak vyhledáváme v databázi přes LIKE (procento, podtržítko) nebo REGEXP (hafo dalších znaků, viz též funkce quotemeta).

ikona v6ak:

Jak jsme už psali, kód je v php4+ nejdříve celý parsován a pak celý vykonáván, takže takovéto měření nemá smysl, teoreticky by mělo vyjít oboje stejně. Jediná možnost by byla použít eval nebo podobný trik, kterým bychom změřili dobu parsování. Ale možná bychom museli zvýšit počet průběhů, abychom odstranili vedlejší vlivy. Nejlépe spustit php v reálném čase. Na to je ideální minimální Linux nezatížený GUI a zbytečnými službami. PHP bych spouštěl z příkazového řádku, ne z apache.
Pak by asi byl vidět rozdíl mezi uvozovkama a apostrofama.

ikona Jakub Vrána OpenID:

Tento druh měření má smysl při použití akcelerátoru - tehdy se kód parsuje (a kompiluje) jen jednou a zpracovává se opakovaně. Souhlasím, že by měření mělo podle mých znalostí teoreticky vyjít stejně, ale nevychází - na různých platformách, operačních systémech i verzích PHP. Příčinu neznám.

Všechny testy samozřejmě spouštím z příkazového řádku.

ikona v6ak:

V php3 se kód postupně parsuje a vykonává. V php4+ bez akcelerátoru se nejdřív celý zparsuje a pak celý vykoná. Je to parsování na jedno použití. (Použití neznamená průběh.) Akcelerátor by uschoval výsledek parsování pro další použití. Nevím, jak akcelerátory pracují s evalem, spíš na to kašlou.
Já jsem chtěl měřit právě dobu parsování, protože právě tam by měl být rozdíl, takže akcelerátor, pokud by si poradil s evalem, by tu byl na škodu.

cpbbt:

Tak to jsem blázen. Poslední dvě možnosti pracují naprosto identicky. Moc tomu nerozumím.

Michal:

URL escapuji pomoci urlencode(). Ale kdy použít rawurlencode(). Rozdíl je v escapovaní mezery ale fakt nevím kdy by se mohla funkce rawurlencode hodit?

Ogara:

Tak to vypada, ze fce magic_quotes_gpc uz je mrtva, ma nejakou nahradu nebo neni zadna potreba? :)

v6ak:

Čistě terminologicky, magic_quotes_gpc není funkce, ale konfigurační direktiva.

Dnes to vypadá, že magic_quotes_gpc je snad již naštěstí mrtvá. Kdysi jsem se nad tím dost rozčiloval, je to nesystémové řešení. Programátor pak musel rozlišovat, odkud ta hodnota vlastně přišla (zkuste si pak v aplikaci udělat trošku abstrakce...) a celé to vedlo spíše ke zmatku.

Když bychom měli z nějakého důvodu používat staré API, tak addslashes nebo o něco lépe mysql_real_escape_string. Pokud ale půjde o novou aplikaci, použil bych spíše PDO, Nette Database, Nette Database Table, Dibi (nicméně vývoj byl přesunut směřem k Nette Database), nebo další takové knihovny, které nabízejí pohodlnější řešení.

ikona Jakub Vrána OpenID:

magic_quotes_gpc=1 se dá nahradit pomocí filter.default=magic_quotes, ale nedoporučoval bych to. Jde o to, že data se ošetřují v nevhodný okamžik ještě před tím, než se rozhodne o tom, zda se vůbec budou posílat do databáze. Navíc je lepší zvolit lepší abstrakci (např. vázání proměnných) a data ručně vůbec neošetřovat.

Pro zpětnou kompatibilitu lze použít opak skriptu na http://php.vrana.cz/vypnuti-magic_quotes_gpc.php.

pitr03:

Zdravím... Narazil jsem na problém, jak pomocí FPutS() uložit text v azbuce do TXT souboru, tak aby se dal znovu přečíst. Asi to s problematikou escapování úplně nesouvisí, ale uvítal bych radu. Díky...

ikona Jakub Vrána OpenID:

Důležité je použít správné kódování. Pokud se skripty posílají s hlavičkou Content-Type: text/html; charset=utf-8 a kódování UTF-8 se používá i na všech ostatních místech, tak všechno obvykle funguje správně.

Romana:

Pokud funkce addslashes pridava zpetne lomitko, nemela by se jmenovat addbackshashes. Dekuji za zpracovni pripominky. Szalayova romana.szalayova@seznam.cz

Vložit komentář

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL:

avatar © 2005-2017 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.