Tento článek je poněkud netradiční, podívám se v něm nikoli na nejlepší projekty Zend’s PHP 5 Coding Contest, ale na projekty s vyloženě špatně napsaným kódem, které ovšem také usilovaly o přízeň poroty a odborné veřejnosti. Cílem článku není pohanět cizí práci, ale poukázat na to, čeho byste se měli ve svých projektech založených na PHP 5 jednoznačně vyvarovat.

Do Zend’s PHP 5 Coding Contest se přihlásila stovka autorů se svými aplikacemi. Na deset nejlepších z těchto skriptů jsem vás upozornil v předchozích článcích a chtěl jsem tím v nejlepším skončit. Tento článek doplňuji na přání redakce Intervalu, podle níž i popis chyb má svůj smysl.

AtomReader – špatný parser Atom 0.3 feedu

Dokument Atom 0.3 je odnož XML, na jeho parsování se tedy nabízí nová SimpleXML a DOM rozšíření PHP 5. AtomReader je knihovna Svena Kutznera, která tuto jednoduchou operaci parsování Atom 0.3 feedu provádí, a to pomocí funkcí simplexml_load_file a dom_import_simplexml, dostupných nově v PHP 5. (V PHP 4 se používalo typicky xml_parser_create a xml_parse, čemuž předcházelo curl_exec, případně file_get_contents, pokud neexistovala curl extension.)

Sven Kutzner nicméně celou věc odflákl. Zda daný feed existuje, nejdříve testuje pomocí @fopen($uri, "r"), což je poněkud zbytečné a problematické (allow_url_fopen off), a následně používá v kódu zmatené a zcela nadbytečné konstrukce typu:

if ( $fp = @fopen($uri, „r“) ){
   fclose($fp);
   $this->xmlValid = true;
   try {
      if(!$this->sxml = @simplexml_load_file($uri))
      throw new Exception(‚parse error‘);
   }
   catch (Exception $e){
      $this->xmlValid = false;
   }
   $this->uriValid = true;
   return true;
} else {
   $this->uriValid = false;
   return false;
}

V celé aplikaci dále chybí zpracování výjimek, zcela neošetřené je $_GET['url'], nepočítá totiž s get_magic_quotes_gpc() a s urldecode(), takže na některých PHP konfiguracích nebude fungovat. Občas jsou používány standardní PHP tagy typu <?php a občas pro změnu zastaralé short-open tags typu <?= (místo <?php echo) či <? (místo <?php). Výstupní dokument nemá přiřazen žádný DOCTYPE ani žádné kódování, ačkoli by zde mělo být UTF-8, defaultní kódování pro SimpleXML a DOM (nebo by se alespoň při výstupu měla použít funkce utf8_decode a výstup ponechat v iso-8859-1), a vůbec není řešena cache Atom feedu.

Představa, že AtomReader nasadím na svém webu, kde budu chtít zobrazovat Atom feed z webu jiného, a s každou jednotlivou návštěvou se přes fopen() bude zjišťovat stav (200) a potom natahovat celý feed přes simplexml_load_file a následně zpracovávat přes DOM, to je noční můra pro každý webhosting. Ono to sice chvíli fungovat nějak bude, ale extrémně pomalu a nespolehlivě.

Navíc k těmto formálním nedostatkům je nutno poukázat i na chybnou koncepci – dnes je nesmyslné napsat jen (špatný) parser Atom 0.3 feedu, v situaci, kdy existují (a převažují) formáty RSS 0.91, RSS 1.0 (RDF) a RSS 2.0. Není přeci problém napsat parser, který bude podporovat veškeré tyto formáty, bude implementovat cache výsledků i mnohem lepší zpracování chyb, a navíc bude přenášet řádově méně dat. Takový parser potom bude již skutečně použitelný, AtomReader použitelný není.

LinkFinder – nefunkční management záložek a RSS čtečka

Program LinkFinder, který napsal Andrew Embler, by měl být podle jeho slov cosi jako del.icio.us pro jednotlivce, tedy PHP 5 aplikace pro správu záložek, včetně „aktivních“ záložek ve formátu RSS (inspirace Firefoxem?).

Abych aplikaci zprovoznil, musel jsem si v php.ini nastavit short_open_tag = On, až potom se LinkFinder rozběhl, nicméně jeho úvodní stránka při pokusu o vytvoření mého uživatelského účtu skončila na této chybě:

Warning: Cannot modify header information – headers already sent by (output started at \home\www\interval\linkfinder\classes\validate.php:74) in \home\www\interval\linkfinder\classes\user.php on line 22

Problém spočíval v souboru validate.php, jehož konec vypadal takto (v souboru user.php je potom nastavení login cookie setcookie("LF_Authenticate", $userHash, time() + 1296000);, kterému ovšem nesmí předcházet žádný výstup, tedy ani mezery či CRLF):

@65: }
@66:
@67: ?>
@68:
@69:
@70:
@71:
@72:
@73:
@74:

Vše jsem opravil a aplikace začala pracovat. Kliknul jsem tedy na Add URL, zkusil přidat http://hulan.info a dostal jsem tento výstup:

hulan.info –ş RedakÄŤnĂ­ systĂ©m F-ART:CMS — srdce vĂ­ce neĹľ tisĂ­ce webĹŻ!

Jinak řečeno, opět aplikace vyvíjená jen pro ISO-8859-1 (web je v UTF-8, tedy včetně title), která není schopná z hlaviček nebo z XML/HTML dokumentu poznat kódování!

Další „zajímavé“ parametry (chyby!) aplikace jsou všudypřítomné – používání neDOM metod, jako je InnerHTML a writeln() v JavaScriptu, či ukládání bookmarků do proprietárního formátu v SQLite databázi, což se v době, kdy máme pro bookmarky formát XBEL, jeví jako velice neefektivní pro spolupráci s jinými systémy.

Také jsem se podíval na RSS agregátor této aplikace, ta je řešená na první pohled zajímavě a moderně, přes DOM (DomDocument::loadXML, getElementsByTagName()), ale opět zde neexistuje jakékoli ošetření chybových stavů, neexistuje cache RSS feedů a chybí podpora Atom feedu.

FileBrowser – nebezpečný webový manažer souborů

Program FileBrowser napsal Filipe Silva a charakterizoval ho jako komplexního správce souborů. Celá jeho miniaplikace spočívá v tom, že si v config/config.php ručně nadefinujete cestu na adresář, ve kterém je aplikace instalována, a také URL tohoto adresáře (nevím proč, obojí se dá zjistit, proměnná __FILE__ a $_SERVER['HTTP_HOST'] s $_SERVER['REQUEST_URI']), a FileBrowser potom dokáže smazat jakýkoli soubor, ke kterému má tento PHP skript práva ve filesystému, umí uploadovat nový soubor a zvládá i přechod do podřízených adresářů.

Prostě takové primitivní webové FTP, ovšem bez jakéhokoli zabezpečení – pokud si na web nenahrajete .htaccess s požadavkem na HTTP autentizaci, pomocí FileBrowseru vám vymaže či zmodifikuje váš web během pár sekund kdokoli.

Celý systémek je navíc napsán jako shluk šesti PHP souborů, ve kterých nejsou žádné definované funkce, natož objekty, nepoužívá žádné rozšíření PHP (natož moderní rozšíření PHP 5), má neošetřené vstupy a výstupy. Pohled na prezentační stránku věci pak odhalí DOCTYPE HTML 4.01 Transitional a extrémní používání tabulek, elementů font a dalších nesmyslů.

FileBrowser je prostě typický představitel „takyaplikace“, která dělá jinak velice kvalitnímu PHP 5 a jeho programátorům špatné jméno a podporuje rozšířený omyl, že v PHP může programovat každý. Každý v něm může cosi dělat, to ano, ale programováním bych to rozhodně nenazýval…

GetGallery – podivná fotogalerie

Aplikace GetGallery má být dle Gustava Nilssona fotogalerie používající nových rysů PHP 5. Čekal jsem tedy něco pokrokového, validního, dobře napsaného, nicméně těchto 150 kB kódu neumí nic víc, než přes absolutně nezabezpečený soubor admin.php nahrát na server „tar.gz“ archiv, ten rozbalit, nahrát jeho obsah do zvoleného adresáře a pomocí GD2 vygenerovat náhledy. Případně existující soubory smazat (opět bez jakéhokoli zabezpečení).

Naprosto zmatená je koncepce aplikace, používá totiž zcela nesmyslně XML rozšíření – do XML si naformátuje seznam souborů a adresářů a toto celé poté uloží do proprietárního formátu SQLite databáze. Něco tak podivného se jen tak nevidí. Autor se prostě dočetl v zadání Zend’s PHP 5 Coding Contest, že by měl použít XML a SQLite, tak je použil a vůbec ho nenapadlo, že prostý skript o dvaceti řádcích, který přečte soubory v adresáři a zobrazí je, bez nároku na přítomnost XML a SQLite a provádění řady nadbytečného kódu, bude dělat naprosto to samé.

Prezentační část jeho aplikace je věc, která si sice hraje na XHTML, ale používá kód HTML 4.01 Transitional (nicméně, jsou zde použity šablony, to je plus).

GetGallery je odstrašující příklad 1 000 řádků kódu, který by bylo možno napsat na 100 řádcích a pracoval by navíc mnohem efektivněji.

PyroFTPD – FTP démon bez dokumentace

Program PyroFTPD je FTP server (démon) napsaný v PHP, jehož autorem je solidox, a co se týče PHP kódu, je to nejlepší ze špatných aplikací prezentovaných v tomto článku. PyroFTPD umí autorizaci uživatelů přes XML soubory, přes definici uživatelů v SQLite databázi i přes textový konfigurační soubor. Pro svůj běh požaduje podporu pro Posix, Sockety a SimpleXML.

Problém zde není ani tak v kódu či v koncepci této aplikace, jako spíše v naprosto nedostatečné dokumentaci a upozornění na bezpečnostní problémy (například jak zabezpečit pyrousers.xml). Pokud uživatel nasadí tento skript „v dobré víře“ na svůj server, může se brzo dočkat toho, že se na jeho FTP server nebude připojovat jenom on.

Řadě programátorů se dokumentaci psát nechce, přitom dokumentace je stejně důležitá část aplikace jako aplikační kód samotný.

Mezi programátorské chyby bych nedodatečnou dokumentaci a upozornění na zabezpečení aplikace rozhodně zařadil, zvláště ve světě internetu, a proto je nutno PyroFTPD skutečně nutno chápat jako velice špatnou aplikaci.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět