[ Webhosting profitux.cz ] [ Pohádky Online ] [ Golfový trenažér pro nácvik odpalů ]
v6ak [ programování, bezpečnost, web, php, java, ... ] (Vít Šesták)
Buzz - v6ak Twitter - v6ak

štítky

Co je špatného na magic_quotes_gpc?

Docela často vidím používání direktivy magic_quotes_gpc a spolehání se na ní. Podle mého názoru vede často ke špatně napsaným skriptům, proti SQL injekci nemusí vždy pomoci, může pomoci k HTML injekci (a tím k XSS), nemusí to být kratší a může způsobit pěkný zmatek. Proč? To můžu ukázat a vysvětlit. Zde.

Abych byl optimista, přidám například i informace, jak je možné většinou tuto věc vypnout. I na freehostingu!

3 mýty o magic_quotes_gpc a jejich vyvrácení

Mám-li zapnuté magic_quotes_gpc, nemusím se o žádné escapování starat.
Musíte! SQL není obvykle jediný výstup, kde je potřeba escapovat! Co třeba takové HTML, URL, případně command-line a další?
To je právě jedna z věcí, co mi na magic_quotes_gpc vadí - když uvidíte něco jako:
"INSERT INTO atable VALUES( NULL, '".$_GET['user']."', '".$_GET['text']."' )"
Pak můžete mít pocit, že můžete napsat třeba:
echo $row->user_name
Což ale není pravda!
Mimochodem, může nastat reálný problém se znakovou sadou.
Tak dobře, ale o escapování v SQL se starat nemusím.
To taky není úplně pravda. Co když bude uživatelský vstup pocházet odjinud? (A to není jen tak vymyšlené.)
Navíc není bezpečné vytvořit dotaz takto:
'SELECT * FROM my_table WHERE id='.$_GET['id']
Útočník totiž může stále normálně použít středník a za ním klasické příkazy. Pokud by mu chyběly apstrofy pro řetězec, může použít 0xHEXA zápis. Správně by mělo dojít k jedné z těhto věcí:
  • ověření pomocí ctype_digit
  • konverzi na číselný typ pomocí intval nebo (int)
  • uzavření vstupu do apostrofů
Zapnuté magic_quotes_gpc zabrání XSS.
Určitě ne! HTML injekci to určitě samo nezabrání - není jak. A to ani když umísťujete vstup do html paramertu (tím mám namysli např. '<a href="'.$row->url.'">). Zpětné lomítko přece nemá v html žádný speciální význam, ne?.
Skript lze (při porušení standardu) zapsat i bez uvozovek okolo type nebo bez type.
K XSS je více cest než jen HTML injekce. Například URL typu javascript:alert(%22XSS%22). Nevím, za je toto validní, ale určitě to ve většně prohlížečích funguje.

Co to dělá?

Je-li direkiva magic_quotes_gpc zapnuta, pak budou všechny vstupní proměnné _GET, _POST, s_COOKIE (a možná i některé další, zvášť pokud zapnete register_globals) escapovány pomocí addslashes. Nevím přesně, jak to je u polí, ale prý s tím je trošku problém. Tato direktiva má vliv i na několik funkcí, myslím že k nim patří i parse_str.

Příklad - jeden úkol, tři řešení

Pro názornost udělám příklad: máme v (My)SQL jednoduchu tabulku s jedním sloupcem. Máme za úkol vytvořit v PHP vyhledávací stránku. Stačit bude (v tomto příkladu) pouze vyhledávání pomocí LIKE (podmínka: sloupec LIKE %to, co uživatel zadal%). Stránka bude zaznámenávat hledané výrazy pomocí knihovny. Může se to hodit nejen pro statistiky, ale třeba i pro „našeptávač“. (Zde na to bude "použita" prázdná funkce, což pro tento příklad stačí.) Bezpečnost a správná funkčnost je samozřejmostí. Ukážeme si hned tři řešení:

Zde je ta tabulka i s nějakými záznamy v SQL pro MySQL (použil jsem mírně upravený export):

CREATE TABLE atable ( title varchar(255) character set utf8 collate utf8_czech_ci NOT NULL default '' ) ENGINE=MyISAM DEFAULT CHARSET=latin1; INSERT INTO atable VALUES ('asdfasdfadfas'); INSERT INTO atable VALUES ('123456a'); INSERT INTO atable VALUES ('sdfsd''asdas');

Potom tu mám soubor vypínající magic_quotes_gpc (varianta skriptu vyžadující magic_quotes_gpc bude v jiném adresáři a bude to mít zapnuto.)

soubor .htaccess
php_flag magic_quotes_gpc Off

Pro první dva příkady tu mám i nastavení (pro třetí bude zvlášť) :

soubor cfg.php
<?php define('DEBUG', true); //má se ladit? //zde si doplňte svoje údaje, snad to nemusím vysvětlovat... define('CFG_MYSQL_SERVER', '...'); define('CFG_MYSQL_USER', '...'); define('CFG_MYSQL_PASS', '...'); define('CFG_X_DB', '...');

Dále tu mám „knihovnu“ pro záznam hledaných výrazů.

soubor v6Autocomplete.php
<?php function v6AutcompleteAdd($searchId, $searchExpression){}//pro budoucnost

A ze společných souborů to je vše.

Klasické řešení bez použití magic_quotes_gpc

Myslím že tu není snad nic k nepochopení. Komentovat mimo kód to snad nemusím.

soubor no.php
<?php require_once './cfg.php'; require_once './lib/v6Autocomplete.php'; define('SEARCH_ID', 5); header('content-type:text/html; chatset=utf-8'); ?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title><?php if(!empty($_GET['search'])) echo htmlspecialchars($_GET['search'].' - hledání', ENT_COMPAT, 'utf-8') ?></title> </head> <body> <form action="<?php echo htmlspecialchars(basename($_SERVER['PHP_SELF']), ENT_COMPAT, 'utf-8'); ?>" method="get"> Hledaný výraz: <input type="text" name="search" value="<?php empty($_GET['search']) or print(htmlspecialchars($_GET['search'], ENT_COMPAT, 'utf-8')); ?>"> <button type="submit">Hledat</button> </form> <?php if(!empty($_GET['search'])){ do{// emulace try/catch if(!$dbh=@mysql_connect(CFG_MYSQL_SERVER, CFG_MYSQL_USER, CFG_MYSQL_PASS)){ $e=(object)array( 'func'=>'mysql_connect', 'err'=>@mysql_error(), 'code'=>@mysql_errno() ); break; }; if(!@mysql_select_db(CFG_X_DB, $dbh)){ $e=(object)array( 'func'=>'mysql_select_db', 'err'=>@mysql_error(), 'code'=>@mysql_errno() ); break; }; if(!@mysql_query('SET CHARACTER SET utf8')){ $e=(object)array( 'func'=>'mysql_query', 'err'=>@mysql_error(), 'code'=>@mysql_errno() ); break; }; if(!$q=@mysql_query( 'SELECT title FROM atable WHERE
title LIKE \''.mysql_real_escape_string('%'.$_GET['search'].'%', $dbh).'\';'
,$dbh)){ $e=(object)array( 'func'=>'mysql_query', 'err'=>@mysql_error(), 'code'=>@mysql_errno() ); break; }; echo '<ul>'; while($row=mysql_fetch_object($q)){ echo '<li>'.htmlspecialchars($row->title, ENT_COMPAT, 'utf-8').'</li>'; }; echo '</ul>'; v6AutcompleteAdd(SEARCH_ID, $_GET['search']); }while(false);if(isset($e)){//catch($e) echo 'Chyba. Zkuste později.'; if(DEBUG){ echo '<div style="white-space:pre">'. htmlspecialchars(print_r($e, true), ENT_COMPAT, 'utf-8').'</div>'; unset($err); }; }; // pokus se o to i v případě chyby @mysql_free_result($q); @mysql_close($dbh); unset($q, $dbh, $row); }else{ echo 'Zatím nehledáte'; } ?> </body> </html>

Klasické řešení s magic_quotes_gpc

Na toto si vytvořím nový adresář, kam to umístím, a dám do něj i .htaccess zajišťující zapnutí magic_quotes_gpc:

soubor mq_gpc/.htaccess
php_flag magic_quotes_gpc On
soubor mq_gpc/index.php
<?php require_once '../cfg.php'; require_once '../lib/v6Autocomplete.php'; define('SEARCH_ID', 5); header('content-type:text/html; chatset=utf-8'); ?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title><?php if(!empty($_GET['search'])) echo htmlspecialchars(stripslashes($_GET['search']).' - hledání', ENT_COMPAT, 'utf-8'); ?></title> </head> <body> <form action="<?php echo htmlspecialchars(basename($_SERVER['PHP_SELF']), ENT_COMPAT, 'utf-8'); ?>" method="get"> Hledaný výraz: <input type="text" name="search" value="<?php empty($_GET['search']) or print(htmlspecialchars(stripslashes($_GET['search']), ENT_COMPAT, 'utf-8')); ?>"> <button type="submit">Hledat</button> </form> <?php if(!empty($_GET['search'])){ do{// emulace try/catch if(!$dbh=@mysql_connect(CFG_MYSQL_SERVER, CFG_MYSQL_USER, CFG_MYSQL_PASS)){ $e=(object)array( 'func'=>'mysql_connect', 'err'=>@mysql_error(), 'code'=>@mysql_errno() ); break; }; if(!@mysql_select_db(CFG_X_DB, $dbh)){ $e=(object)array( 'func'=>'mysql_select_db', 'err'=>@mysql_error(), 'code'=>@mysql_errno() ); break; }; if(!@mysql_query('SET CHARACTER SET utf8')){ $e=(object)array( 'func'=>'mysql_query', 'err'=>@mysql_error(), 'code'=>@mysql_errno() ); break; }; if(!$q=@mysql_query( 'SELECT title FROM atable WHERE title LIKE \'%'.$_GET['search'].'%\';' ,$dbh)){ $e=(object)array( 'func'=>'mysql_query', 'err'=>@mysql_error(), 'code'=>@mysql_errno() ); break; }; echo '<ul>'; while($row=mysql_fetch_object($q)){ echo '<li>'.htmlspecialchars($row->title, ENT_COMPAT, 'utf-8').'</li>'; }; echo '</ul>';
v6AutcompleteAdd(SEARCH_ID, stripSlashes($_GET['search']));
}while(false);if(isset($e)){//catch($e) echo 'Chyba. Zkuste později.'; if(DEBUG){ echo '<div style="white-space:pre">'. htmlspecialchars(print_r($e, true), ENT_COMPAT, 'utf-8').'</div>'; unset($err); }; }; // pokus se o to i v případě chyby @mysql_free_result($q); @mysql_close($dbh); unset($q, $dbh, $row); }else{ echo 'Zatím nehledáte'; } ?> </body> </html>

Délka kódu

Zde si však komentář už dovolím. Začnu déklou kódu - to je častý argument zastánců magic_quotes_gpc, ne? Kolik se na magic_quotes_gpc ušetřilo kódu a kolik bylo nutno napsat navíc? Ušetřil jsem tím pár znaků na jednom řádku. Zato mi však přibylo mnoho stripslashes. Takže magic_quotes_gpc mi prodloužilo kód. Jasně, jde jen o jeden konkrétní případ, ale když v předchozím případě místo mysql_real_escape_string použiju addslashes, aby to bylo ekvivalentní použití magic_quotes_gpc, tak na místech, kde šetřím, ušetřím o dva znaky méně než na místech, kde musím psát něco navíc. Takže se to v délce kódu nevyplatí i při padesátiprocentním použití escapování pro SQL.

Logika

Všimněte si v kódu použití stripSlashes před voláním fukce v6AutcompleteAdd. To je ten hlavní problém magic_quotes_gpc: volám funkci - mám jí předat parametry escapované pomocí addslashes (zde od magic_quotes_gpc), nebo v původním tvaru? Funkce nemůže poznat, zda argument byl z proměnných postižených magic_quotes_gpc, nebo ne. Pokud bych vkládal data z DB do požadavku nebo bych chtěl udělat třeba AJAXové vyhledávání a posílat data v těle požadavku jako JSON, pak by asi bylo vše jinak. (Jasně, pro vyhledávání se více hodí metoda GET, ale i tak to není uměle vyrobený problém! Určitě by se našel přirozený příklad, který by to ukazoval.)

Ale rozebereme, zda by v tom případě měla funkce dostávat argumenty čisté, nebo všechny řetězce escapované od magic_quotes_gpc: Kdyby funkce dostávala argumenty čisté, pak by se programování ve funkcích lišilo o programování mimo funkce, což by mohlo dělat zmatek a tím vytvářet bezpečnostní problémy. Zvlášť při přesunutí části kódu do funkce. Nebo by snad funkce měla dostávat všechny řetězcové argumenty escapované od magic_quotes_gpc/addslashes? Úplně všechny? Ale mnoho by toho bylo děláno zbytečně! A bylo by to další zesložitění a prodloužení! Nebo by se mělo escapovat jen něco? V tom by byl už úplný zmatek. A podle čeho by se to vybíralo? Vždyť funkce má i abstrakční význam - nestarám se o to, jak funkce funguje, ale o to, jak ji používat. A co když změním technlogii? A to taky není nereálné - podívejte se na další příklad, tam by už SQL escapování bylo úplně zbytečné. V tom případě by bylo nutno v zájmu zpětné kompatibility požadovat escapování addslashes napořád!

Bezpečnost: A co kódování?

Navíc u magic_quotes_gpc a addslashes jsem neviděl ani slůvko o použitém kódování. Asi nejspíš budou používat nečeské iso-8859-1. Tuším způsob, jak by šlo docílit SQL injekce kvůli rozdílné znakové sadě, například iso-8859-2 vs. utf-8, ale asi i iso-88592 vs. windows-1250 a další. (O problému se sedmibitovýmí znakovými sadami se nezmiňuji, o těch ví "každé malé dítě".) Někdy to prozkoumám a možná o tom později něco napíšu.

Naproti tomu funkce mysql_real_escape_string bere kódování ze spojení s databází, takže tento problém nevzniká. To je taky důvod, proč jsem radši použil mysql_real_escape_string místo addslashes.

Dosazování pomocí parametrů a placeholderů

Toto není možná nejčastější způsob prgramování (zvlášť mezi méně pokročilými), ale není špatný. Neescapuji. Jen říkám, kam co dosadit a výstup je escapován automaticky, je-li to potřeba. Pro některé tu budou hned dvě nové věci - PDO (pro databáze) a DOM (pro kód webové stránky). Myslím, že více z vás se bude líbit více PDO než ukecaný DOMDocument. Ale nikdo vás nenutí používat obě věci zároveň, PDO a DOMDocument nejsou nijak svázané, jen mají podobnou koncepci řešení escapování. Nezavrhujte proto tento přístup k esapování jen kvůli ukecanosti DOMDocumentu. Tento přístup lze dobře kombinovat s klasickým přístupem bez magic_quotes_gpc.

Díky novým třídám (hlavně PDO) tu mám pár odlišností od předchozích dvou příkladů:

Tady máme nastavení skriptu:

soubor disp.PDO.cfg.php
<?php define('DEBUG', true); /*pro pgSQL* define('CFG_PDO_DSN_PREFIX', 'pgsql'); define('CFG_PDO_DSN', 'host=127.0.0.1;dbname=v6ak'); define('CFG_PDO_USER', 'v6ak'); define('CFG_PDO_PASS', 's'); /*pro MySQL*/ define('CFG_PDO_DSN_PREFIX', 'mysql'); define('CFG_PDO_DSN', 'host=127.0.0.1;dbname=mqdb'); define('CFG_PDO_USER', 'root'); define('CFG_PDO_PASS', ''); /**/

A teď už jen samotný soubor:

soubor disp.PDO.cfg.php
<?php require_once 'PDO.cfg.php'; require_once './lib/v6Autocomplete.php'; define('SEARCH_ID', 5); $page=new DOMDocument(); //<html> $page->appendChild($html=$page->createElement('html')); //<head> $html->appendChild($head=$page->createElement('head')); // meta s kódováním $head->appendChild($charsetMeta=$page->createElement('meta')); $charsetMeta->setAttribute('http-equiv', 'content-type'); $charsetMeta->setAttribute('content', 'text/html; charset=utf-8'); //tag title $head->appendChild($title=$page->createElement('title')); if(!empty($_GET['search'])){ $title->appendChild($page->createTextNode($_GET['search'].' - hledání')); }; //</head> //<body> $html->appendChild($body=$page->createElement('body')); //formulář $body->appendChild($form=$page->createElement('form')); $form->setAttribute('action', basename($_SERVER['PHP_SELF'])); $form->setAttribute('method', 'get'); $form->appendChild($page->createTextNode('Hledaný výraz: ')); $form->appendChild($searchInput=$page->createElement('input')); $searchInput->setAttribute('type', 'text'); $searchInput->setAttribute('name', 'search'); if(!empty($_GET['search'])) $searchInput->setAttribute('value', $_GET['search']); //dole: v PHP<5.2.0 bych musel použít $submitButton->appendChild($page->createTextNode('Hledat')) $form->appendChild($page->createTextNode(' '));// V ostatních verzích se vytvořila mezera zalomením, tak ji sem taky přidám $form->appendChild($submitButton=$page->createElement('button', 'Hledat')); $submitButton->setAttribute('type', 'submit'); //hledání if(!empty($_GET['search'])){ try{ $dbh=new PDO(CFG_PDO_DSN_PREFIX.':'.CFG_PDO_DSN, CFG_PDO_USER, CFG_PDO_PASS); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);//házej výjimky $qarr=array( 'mysql'=>'SET CHARACTER SET utf8', 'pgsql'=>'SET CLIENT_ENCODING TO utf8;' ); if(array_key_exists(CFG_PDO_DSN_PREFIX, $qarr)) $dbh->exec($qarr[CFG_PDO_DSN_PREFIX]); else throw new Exception('Neznámá DB => nemohu nasavit kódování. Známé DB:'."\n\t * ".implode("\n\t * ", array_keys($qarr))); unset($qarr); // Kdyby to bylo delší, tak bych možná místo otazníků použil :neco, ale toto tady stačí $q=$dbh->prepare( 'SELECT title FROM atable WHERE title LIKE ?;' ); $q->execute(array('%'.$_GET['search'].'%')); $body->appendChild($resultsUl=$page->createElement('ul')); while($row=$q->fetchObject()){ $resultsUl->appendChild($page->createElement('li', $row->title)); }; v6AutcompleteAdd(SEARCH_ID, $_GET['search']); }catch(Exception $e){ $body->appendChild($page->createTextNode('Chyba. Zkuste později.')); if(DEBUG){ $body->appendChild($err=$page->createElement('div', print_r($e, true))); $err->setAttribute('style', 'white-space:pre'); unset($err); }; }; //pokus se o to i v případě chyby unset($q, $dbh, $row, $resultsUl);// destruktry se (pokud se nemýlím) postarají o uvolnění. }else{ $body->appendChild($page->createTextNode('Zatím nehledáte')); } //</body> header('content-type:text/html; chatset=utf-8'); // k DOCTYPE: lépe to zatím neumím echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">'.$page->saveHTML();

Všimněte si, že tu nikde nebyla použita escapovací funkce (htmlspecialchars, mysql_real_escape_string, ...) ani funkce k ní opačná (stripslashes, ...). Přesto je problém escapování vyřešen! Data, která je jindy potřeba escapovat jsou totiž oddělena od ostatních výstupů tak, že je možné zjistit, jak se to má seskládat, aniž by bylo potřeba escapování. (Samozřejmě, v objektu DOMDocument k escapování dochází, ale o to se nestará uživatel objektu, ale jeho autor. Uživatel obektu jen oddělí data.) Tímto způsobem lze eleganně vyřešit escapování a přitom se nedostat do takových zmatků, jaké jsou spojeny s magic_quotes_gpc.

Srovnání jednotlivých způsobů řešení

Délka kódu

Klasické řešení bez magic_quotes_gpc je na tom jako vždy lépe, než klasické řešení s magic_quotes_gpc. V dosazování pomocí parametrů se díky PDO zkrátil kód, ale kvůli DOMDocument se zase prodloužil. Opakuji, že PDO a DOMDocument nejsou nijak svázané. Takže můžete používat třeba jen PDO.

Logika

Nejlogičtější mi přijde Dosazování, přesně to zařadit je však kvůli větším rozdílům obtížné. Nicméně u klasického řešení je určitě logičtější verze bez magic_quotes_gpc. (Vizte kritiku logiky přímo u magic_quotes_gpc.)

Přehlednost

Zde je objektivní zařazení Dosazování asi úpnlě nemožné, to ať si posoudí každý sám. V klasickém řešení je u verze s magic_quotes_gpc kód "ušpiněn" mnoha stripslashes a verze bez magic_quotes_gpc mi přijde přehlednější.

Bezpečnost

Zde bude klasické řešení bez magic_quotes_gpc asi stejně bezpečné jako Dosazování. U magic_quotes_gpc by mohl být závažný problém se znakovou sadou, ale to musím ještě ověřit. Navíc jsem četl o nějakém problému při práci s poli u magic_quotes_gpc. Ten jsem nepotvrdil, ale může to být verzí php.

Rychlost

Porovnání klasických řešení je snadné: verze s magic_quotes_gpc escapuje něco zbytečně a pak ještě dochází k "odescapování", což jsou úkony, které musí verze s magic_quotes_gpc dělat navíc, takže je patrně pomalejší.

PDO u dosazování by mohlo být rychlejší, protože nemusí escapovat, asi to bude řešeno tak, že uvede délku řetězce (v bajtech, ne ve znacích). Navíc DB server má trošku ušetřenou práci s analýzou. Podmínkou však je, aby použitý databázový driver placeholdery použil a neemuloval.

U DOMDocumentu to však bude jinak: výstupem má být HTML, kde je nutné escapování, protože u HTML jiná možnost není. DOMDocument musí escapovat všechno a všechno generovat, což by u klasického řešení nebyl nutné. Navíc jsu zde odeslána data až nakonec, což zpozdí jejich odeslání klientovi a zpraování u klienta. Ideální by bylo, kdyby existoval binární DOM soubor, který by šel posílat postupně, čímž by se odstranily snad všechny nedostatky a naopak by tu přibyly klady jako rychlejší zpracování u klienta, menší velikost apod. To však je asi zatím jen sen.

Vypnutí magic_quotes_gpc

Jak jsem slíbil (a málem na to úplně zapoměl) a naznačil, ukážu způsob, jaklze magic_quotes_gpc vypnout. Jsou zde minimálně tyto možnosti:

Apache znamená, že tato možnost je pro kombinaci php+apache (to je obvyklá kombinace), admin znamená, že je nutno mít přístup přímo ke konfiguračním souborům aplikace (nemusí vyžadovat rootovská práva), což na webhostingu asi mít nebudete. Pro webhosting bude tedy asi nutné použít soubor .htaccess. Není 100% jisté, že to bude s Apache+php fungovat, protože použití souboru .htaccess je možné omezit nebo zakázat. Jak jste mohli vidět, mělo by stačit:

  1. Vytvořit/otevřít soubor .htaccess v adresáři, který chcete ovlivnit
  2. Napsat do něj něco jako:
    php_flag magic_quotes_gpc Off
    Případně například:
    # ted vypnu v tomto adresari a vsech jeho podadresarich magic_quotes_gpc! Super! Melo by to vsak jit prekricet jinym souborem v nejakem podadresari. php_flag magic_quotes_gpc Off

Řešení problému přímo v php

Escapování podle get_magic_quotes_gpc()

Viděl jsem různé funkce, které se snažily zjistit stav magic_quotes_gpc a podle toho vrátily původní/escapovanou/"odescapovanou" hodnotu, ale je tu jeden problém: není možné zjistit, zda je daný text z _GET, _POST nebo _COOKIE a mohl být zasažen direktivou magic_quotes_gpc, nebo zda je odjinud a direktivou magic_quotes_gpc zasažen být nemohl. Takže tyto funkce nemohou dost dobře fungovat. (Když je voláte z funkcí, tak původ řetězce nevíte ani vy...)

Mimochodem, četl jsem něco o změně v php 6, která by toto měla udělat ještě neschůdnějším.

Navrácení do původního stavu na začátku skriptu

Toto už je schůdnější varianta. Na začátku se provede skript, který zasažené proměnné vrátí do normálního stavu. Ideální je využití array_walk_recursive (narozdíl od array_walk pracuje i s různou hloubkou polí) a funkce s parametrem volaným odkazem, která parametr upraví pomocí stripslashes.

Závěr

Možná jste si všimli, že v celkovém srovnání bylo klasické řešení s magic_quotes_gpc vždy za klasické řešení bez magic_quotes_gpc. Má tedy smysl uvažovat o klasickém řešení s magic_quotes_gpc?

Mám-li něco doporučit, pak bych pro databáze viděl PDO, případně klasické řešení bez magic_quotes_gpc, nebude-li PDO k dispozici (např. u PHP 4) a pro generování HTML bych asi použil klasické řešení. Už jsem si ale vyžkoušel DOM v kombinaci s XSLT (pak může být DOM trošku méně ukecaný) a taky to nebylo špatné, to bych však doporučil spíše tam, kde budou například potřeba šablony - v tomto je XSLT mocný nástroj.

Diskuzi ke článku naleznete zde.

Linkování

Líbí se Vám tato stránka? Zalinkujte ji!

Chcete sledovat novinky? Pokud si právě prohlížíte článek a hledáte RSS pro celý web, pak jste trošku jinde. Možná hledáte poslední změny.

Validní HTML 4.01 StrictValidní CSS 2.0Validní hlavní RSS kanálPHP 5Apache
referer: UA:CCBot/2.0 (http://commoncrawl.org/faq/) time:0.54099000 1475008622
web
mail
comment