<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Nekuřácké kupé - Jakub Bouček &#187; PHP</title>
	<atom:link href="http://www.jakub-boucek.cz/blog/rubrika/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jakub-boucek.cz/blog</link>
	<description></description>
	<lastBuildDate>Wed, 25 Jan 2012 23:20:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Čárové kódy na webových stránkách</title>
		<link>http://www.jakub-boucek.cz/blog/carove-kody-na-webovych-strankach/</link>
		<comments>http://www.jakub-boucek.cz/blog/carove-kody-na-webovych-strankach/#comments</comments>
		<pubDate>Wed, 25 Jan 2012 23:11:24 +0000</pubDate>
		<dc:creator>Jakub Bouček</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Návody a FAQ]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.jakub-boucek.cz/blog/?p=1018</guid>
		<description><![CDATA[Čárové kódy známe všichni, jsou to ty podivné čárky a čísly na krabici mléka, sušenkách i kondomech. Pokud ale vyvíjíte webové aplikace, může se dříve nebo později dostavit požadavek vložit čárový kód i do stránky určené k tisku (například faktura). Samotné vygenerování kódu není takový problém, existují k tomuto účelu desítky různých on-line generátorů i [...]]]></description>
			<content:encoded><![CDATA[<p><a title="Čárový kód na Wikipedii" href="http://cs.wikipedia.org/wiki/%C4%8C%C3%A1rov%C3%BD_k%C3%B3d">Čárové kódy</a> známe všichni, jsou to ty podivné čárky a čísly na krabici mléka, sušenkách i kondomech.</p>
<div class="ilust right "><img class="alignright size-full wp-image-1026" title="codebar_0" src="http://www.jakub-boucek.cz/blog/wp-content/uploads/2012/01/codebar_01.jpg" alt="" width="259" height="117" /></div>
<p>Pokud ale vyvíjíte webové aplikace, může se dříve nebo později dostavit požadavek vložit čárový kód i do stránky určené k tisku (například faktura). Samotné vygenerování kódu není takový problém, existují k tomuto účelu desítky různých <a title="Odkazy na on-line generátory čárových kódů" href="http://cs.wikipedia.org/wiki/%C4%8C%C3%A1rov%C3%BD_k%C3%B3d#Extern.C3.AD_odkazy">on-line generátorů</a> i <a title="Oblíbený PHP genrátor" href="http://www.barcodephp.com/en">off-line generátorů</a>. Tyto generátory pomocí parametrů v URL vygenerují obrázek, který se klasicky pomocí <code>&lt;img&gt;</code> vloží do stránky.</p>
<p>Samotný problém ale bývá s vložením kódu do stránky tak, aby se zobrazil i na počítači bez internetu (např. při uložení dokumentu na flešku) a aby při tisku nedocházelo k rozostření hran, které jsou způsobeny rozdílem DPI mezi obrazovkou a tiskárnou.</p>
<p><span id="more-1018"></span></p>
<h2>Kvalita tisku</h2>
<p>Problém s kvalitou tisku obrázků řešil nedávno na svém <a title="Fakturoid - Kvalitnější tisk obrázků na fakturách" href="http://blog.fakturoid.cz/2011/08/30/tisk-obrazku-na-fakture/">blogu i Fakturoid</a>. Řešení je vcelku jednoduché, stačí obrázek vygenerovat třeba ve dvojnásobných rozměrech a ten na stránce stlačit na původní rozměry pomocí <code>&lt;img width="..." height="..." &gt;</code>.</p>
<p>Prohlížeč potom na obrazovce zobrazí kód takřka stejně jako předtím, ale při tisku, který má mnohem drobnější rozlišení, se takový obrázek vykreslí se všemi detaily, tedy včetně ostrých hran čar.</p>
<p>Příklad můžete vidět na tomto čárovém kódu:</p>
<div id="attachment_1023" class="wp-caption aligncenter" style="width: 353px"><img class="size-full wp-image-1023" title="codebar_1_343px" src="http://www.jakub-boucek.cz/blog/wp-content/uploads/2012/01/codebar_1_343px.png" alt="" width="343" height="50" /><p class="wp-caption-text">Tento čárový kód je zobrazen na obrazovce v poměru 1:1, ale při tisku je jeho kvalita špatná, pro mnoho čteček nepoužitelná.</p></div>
<p>Stejný kód generovaný ve větším rozlišení:</p>
<div id="attachment_1035" class="wp-caption aligncenter" style="width: 351px"><img class="size-full wp-image-1035" title="codebar_1_1364px" src="http://www.jakub-boucek.cz/blog/wp-content/uploads/2012/01/codebar_1_1364px.png" alt="" width="341" height="50" /><p class="wp-caption-text">Tento čárový kód je zobrazen na obrazovce v poměru 1:4. Při tisku je ale zobrazen prvotřídně.</p></div>
<blockquote><p>Pozn.: Některé prohlížeče při tisku nevyhlazují obrázky a proto se mohou oba výše uvedené čárové kódy vytisknout zcela stejně.</p></blockquote>
<p>Aby kód dobře vypadal dobře na obrazovce, je vhodné striktně dodržovat poměr 1:2 nebo 1:4, protože jinak se bude obrázek přepočítávat přes pixely a bude vypadat ošklivě a rozmazaně (na tisk to má ale minimální vliv).</p>
<div id="attachment_1035" class="wp-caption aligncenter" style="width: 460px"><img class="size-full wp-image-1035" title="codebar_1_1364px" src="http://www.jakub-boucek.cz/blog/wp-content/uploads/2012/01/codebar_1_343px.png" alt="" width="450" height="40" /><p class="wp-caption-text">Nehezký efekt při úpravě velikosti obrázku v jiném poměru než 1:2 či 1:4</p></div>
<p>Pokud už budete takto násilně upravovat velikost čárového kódu, můžete rovnou generovat obrázek o výšce 1px a velikost pak podle potřeby upravit ve stránce obdobným způsoben. U obrázků čárového kódu bez dalších prvků (např. popisku) lze libovolně měnit poměr obrázku, aniž by to mělo na kvalitu jeho zobrazení vliv.</p>
<h2>Tisk bez internetu</h2>
<p>Klasické vložení pomocí tagu <code>&lt;img src="http://domena.tld/obrazek.png"&gt;</code> má několik nedostatků:</p>
<ol>
<li>Bez připojení k internetu se nic nezobrazí,</li>
<li>Není součástí dokumentu (což například u faktury představuje problém),</li>
<li>Obrázek se generuje při každém zobrazení faktury znovu,</li>
<li>Rozměry obrázku nejsou předem známé, protože ty se definují až při samotném generování podle množství dat.</li>
</ol>
<p>Všechny uvedené problémy může vyřešit <a title="Zdroják - Datová URL pomohou s malými soubory" href="http://zdrojak.root.cz/clanky/datova-url-pomohou-s-malymi-soubory/">datové URL</a>, tedy obrázek zakódovaný přímo ve zdrojovém kódu stránky. Jeho vytvoření lze v PHP zajistit pomocí funkce <code>base64_encode()</code> a výsledek vypadá následovně:</p>
<pre>&lt;img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABVQAAAABCAIAAAC+HbKQ
AAAACXBIWXMAAAsSAAALEgHS3X78AAAAlUlEQVRIie2XUQrAIAxD1/sf2v0K25MUW61gPiWm0UZR
a609O2Bmv+O9n55DPhWO4oHqEpRaUWtcqansw4xP0vGua0ZzxgMhKkuKTlROlLnZfPJWLZMVzqai
SRyvJvEr9MLLOZ1/MznmZ+eEcHvx5d931FhHqUWokEnFW7VeEFbe1Rl1T3kHZnv2/hMVTWUu6UTt
QzZeWZgLDmfubaMAAAAASUVORK5CYII=" /&gt;</pre>
<div id="attachment_1035" class="wp-caption aligncenter" style="width: 351px"><img class="size-full wp-image-1035" title="codebar_1_1364px" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABVQAAAABCAIAAAC+HbKQAAAACXBIWXMAAAsSAAALEgHS3X78AAAAlUlEQVRIie2XUQrAIAxD1/sf2v0K25MUW61gPiWm0UZRa609O2Bmv+O9n55DPhWO4oHqEpRaUWtcqansw4xP0vGua0ZzxgMhKkuKTlROlLnZfPJWLZMVzqaiSRyvJvEr9MLLOZ1/MznmZ+eEcHvx5d931FhHqUWokEnFW7VeEFbe1Rl1T3kHZnv2/hMVTWUu6UTtQzZeWZgLDmfubaMAAAAASUVORK5CYII=" alt="" width="341" height="50" /><p class="wp-caption-text">Čárový kód vykreslený pomocí datového URL</p></div>
<p>Je třeba ale zvážit, jaké bude primární použití takové faktury. Určitá omezení proto mohou dosáhnout na uživatele, kteří budou mít na svých počítačích starší Internet Explorer. Ten si s datovými URL moc nerozumí. Je proto vhodné toto nasazovat pouze v prostředí, kde lze ovlivnit volbu prohlížeče, například pro účely firemního intranetu. Mimo toto kontrolované prostředí lze datová URL využívat za předpokladu, že čárové kódy na dokumentu jsou pouhým doplňkem a netvoří nezbytnou součást takového dokladu.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jakub-boucek.cz/blog/carove-kody-na-webovych-strankach/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PHP &#8211; proč si napsat vlastní Framework/CMS/e-shop</title>
		<link>http://www.jakub-boucek.cz/blog/php-proc-si-napsat-vlastni-framework-cms-eshop/</link>
		<comments>http://www.jakub-boucek.cz/blog/php-proc-si-napsat-vlastni-framework-cms-eshop/#comments</comments>
		<pubDate>Sat, 09 Apr 2011 04:53:05 +0000</pubDate>
		<dc:creator>Jakub Bouček</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Zamyšlení]]></category>

		<guid isPermaLink="false">http://www.jakub-boucek.cz/blog/?p=831</guid>
		<description><![CDATA[Pokud jste četli nadpis jako „Proč si nepsat vlastní…“, pak si jej přečtěte znovu a pozorněji. Opravdu se zabývám tím, pro by si každý programátor měl napsat svůj vlastní Framework, CMS a nebo e-shop. Jakmile se student programovacího jazyka dostane dostatečně daleko od prvního „Hello world“, přijde první nabídka na vybudování nějakého rozsáhlejšího systému &#8211; [...]]]></description>
			<content:encoded><![CDATA[<p>Pokud jste četli nadpis jako „Proč si <strong>ne</strong>psat vlastní…“, pak si jej přečtěte znovu a pozorněji. Opravdu se zabývám tím, pro by si každý programátor měl napsat svůj vlastní Framework, CMS a nebo e-shop.</p>
<p>Jakmile se student programovacího jazyka dostane dostatečně daleko od prvního „Hello world“, přijde první nabídka na vybudování nějakého rozsáhlejšího systému &#8211; například e-shopu. Mladý programátor je už otrkaný, ví že stále dokola řeší opakující se problémy a tuší, že by měly vyřešit nějak centrálně &#8211; a tehdy poprvé stojí před vnitřním dilematem: <strong>Použít hotový a léty prověřený systém, nebo si vytvořit svůj vlastní?</strong></p>
<p>Já tvrdím:<br />
<strong>Každý, kdo si někdy položil tuto otázku, by si měl napsat svůj vlastní systém.</strong><br />
<span id="more-831"></span><br />
Jedině tak na vlastní kůži pozná, co je za tím práce a kolik pastí je třeba překonat &#8211; přičichne si k nejhrubšímu meritu problému a otevře si tím svoje oči. Naučí se na věci pohlížet z různých stran, bude lépe předvídat možné budoucí požadavky a rozpoznávat potenciální problémy ještě dříve, než se projeví. <strong>Bude o věcech přemýšlet.</strong></p>
<blockquote><p><strong>Je to jako s auty: Řidič se po své první autonehodě stává mnohem lepším řidičem.</strong> Dokud totiž neuslyší mačkání plechů, má tendenci podceňovat nebezpečí, neumí bleskurychle odhadnout, co je důležité (lidský život nad hmotnou škodou) a v krizových situacích má tendence k zbrklým činům. Zvláštní skupinou jsou tzv. sváteční řidiči, kteří v zájmu opatrnosti zásadně nepřekračují rychlost 30 km/h &#8211; jejich rčení „za celý život ani škrábnutí“ jsou pověstná.</p></blockquote>
<p><strong>A tehdy student sám pochopí, že stejně objevuje Ameriku.</strong> Jeho systém nedělá nic víc, než mnoho OpenSource projektů &#8211; kromě toho, že se mu navíc podařilo obohatit svůj systém o množství chyb, nedostatků, pastí a „až jednou bude čas, tak to dodělám“ věcí. Kromě toho si během prací jeho duše rozdělila systém na části, které má rád a ty, které odbývá v rámci nucených prací, stejně tak znalosti a zkušenosti dokážou plně pokrýt jen některé bloky, jiné naopak fungují někde na pomezí teorie nepravděpodobnosti.</p>
<p>To je ten správný čas připustit si, že <strong>svět už má Nette/Wordpress/Magento</strong>. Ne dříve ne později. Dříve byste nedokázali vnímat problematiku do hloubky a naopak později by se vám mohlo stát, že vám váš vlastní systém vezme svobodu a budete zajati molochem, který už nemůžete hodit přes palubu, protože by vás stáhl s sebou.</p>
<p>Zkuste o tom přemýšlet.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jakub-boucek.cz/blog/php-proc-si-napsat-vlastni-framework-cms-eshop/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Subdomény a komerční hostingy</title>
		<link>http://www.jakub-boucek.cz/blog/subdomeny-a-komercni-hostingy/</link>
		<comments>http://www.jakub-boucek.cz/blog/subdomeny-a-komercni-hostingy/#comments</comments>
		<pubDate>Thu, 16 Apr 2009 00:42:30 +0000</pubDate>
		<dc:creator>Jakub Bouček</dc:creator>
				<category><![CDATA[Bezpečnost]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Návody a FAQ]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Zamyšlení]]></category>

		<guid isPermaLink="false">http://www.jakub-boucek.cz/blog/?p=339</guid>
		<description><![CDATA[Pokud vlastníte doménu (doménové jméno), jistě víte, že můžete využívat i tzv. subdomény (či poddomény), tedy dalších jmen, které rozšiřují původní doménové jméno. Například, pokud vlastníme doménu koldasoft.cz, můžeme zcela volně využívat odvozených domén jako třeba www.koldasoft.cz, či reference.koldasoft.cz a nebo cerberus.koldasoft.cz. Možnosti využití jsou široké. Více o doménové problematice najdete na Wikipedii. V tomto [...]]]></description>
			<content:encoded><![CDATA[<p>Pokud vlastníte doménu (doménové jméno), jistě víte, že můžete využívat i tzv. subdomény (či poddomény), tedy dalších jmen, které rozšiřují původní doménové jméno. Například, pokud vlastníme doménu <a href="http://koldasoft.cz/">koldasoft.cz</a>, můžeme zcela volně využívat odvozených domén jako třeba <a href="http://www.koldasoft.cz/">www.koldasoft.cz</a>, či <a href="http://reference.koldasoft.cz/">reference.koldasoft.cz</a> a nebo <a href="http://cerberus.koldasoft.cz/">cerberus.koldasoft.cz</a>. Možnosti využití jsou široké. Více o doménové problematice najdete <a href="http://cs.wikipedia.org/wiki/Internetov%C3%A1_dom%C3%A9na">na Wikipedii</a>.</p>
<p>V tomto článku bych se rád zamyslel nad realizací hostingu pro takovéto subdomény na webovém serveru. Zejména jejich správu a rozložení v souborové struktuře z pohledu správce webu.<span id="more-339"></span></p>
<p>U drtivé většiny hostingů se provádí nahrávání stránek na server hostingu pomocí FTP nebo jiné podobné technologie (SCP, SVN-put, atd.). Po přihlášení server klientovi zpřístupní adresář serveru, ze kterého webový server bude načítat stránky. Zde však již mezi poskytovateli hostingu vzniká základní rozdíly:</p>
<ul>
<li>Některé hostingy zobrazují obsah na webu obsah <strong>rootu FTP</strong>. Dělají to najčastěji amatérské servery typu one-man-show s minimálními zkušenostmi. Ze zkušenosti takový hosting považuji za méně kvalitní a podpory bývá nepřístupná individuálním požadavkům. Takový server často používá nestandardní nastavení.</li>
<li>Někde se stránky musí nahrát do adresáře <strong>public_html</strong>. Toto se vyskytuje zřídka, především u velkých podniků, které hostingové služby mají jako okrajovou činnost a menší společnosti většinou s mizernou podporou. Toto je defaultní nastavení distribuce serveru a vykazuje tak snahu zprovoznit hosting co nejrychleji a s minimálními náklady -  servery jsou nedotažené, ovládání těžkopádné. Takový hosting s velikou pravděpodobností nebude schopen a ochoten naslouchat Vašim individuálním požadavkům, protože je nastaven na velmi prostý automatický systém, který neumožňuje velké zásahy.</li>
<li>Jinde se po přihlášení do FTP zobrazí několik různých adresářů, z nichž právě jeden je určen obsah webu. Taková konfigurace je většinou propracovaná a umožňuje široké možnosti nastavení serveru na míru. Tuto konfiguraci používají vyspělé hostingové společnosti.<br />
Adresáře přístupné přes FTP mívají pak různé významy. Jeden z nich představuje adresář s daty webové aplikace, druhý umožňuje nahrávat soukromé soubory, které nebudou z webové aplikace přímo přístupné (zabezpečení) a další mohou obsahovat například logy, nebo jiné konfigurační nástroje.</li>
</ul>
<h2>Subdomény</h2>
<p>Výrazně složitější situace je v případě řízení subdomén. I zde se přístup hostingů rozděluje na několik základních typů:</p>
<ul>
<li>Snad nejhorší řešení, které jsem kdy viděl, má webhosting na Forpsi. Na serveru poddomény nejsou vůbec řešeny, pouze při přístupu na libovolnou poddoménu je volán určitý PHP skript, který sám musí rozlišit, o jakou poddoménu jde a volat tak nějaký podskript. Otřesné.
<p><div class="wp-caption aligncenter" style="width: 531px"><img src="/data/blog/subdomeny_01.png" alt="PHP skcript pro zpracování domény" width="521" height="386" /><p class="wp-caption-text">PHP script pro zpracování domény. Zdroj: kb.forpsi.com</p></div></li>
<li>Nastavení domény administrátorem na žádost. Je to sice krkolomné, ale na nízkorozpočtových a nebo velmi individuálních serverech je to velmi časté řešení. Pokud je správce vstřícný a rozumný, v praktickém provozu může být tato varianta zcela uspokojivá.</li>
<li>Dalším nevhodným způsobem vytváření sudomén je, když jakýkoliv podadresář v adresáři s obsahem webu se automaticky stává subdoménou. Na takových serverech není možné provozovat jakoukoliv aplikaci, která pracuje s citlivějšími daty &#8211; pokud nejsou jen v databázi. Jde o to, že takový hosting jen brání vytvoření přehledné souborové a adresářové struktury. Jednak proto, že adresáře poddomén překáží a za druhé, že obsah umístěný v adresáři je přístupný i přes subdoménu. Navíc jsou pak velmi obtížně použitelné nástroje, jako je SVN a pod.<br />
Toto řešení je překvapivě často používané na serverech, což nechápu, protože je považuju v praxi za nepoužitelné.</li>
<li>Poněkud lepší řešení je ukládání do adresáře „<strong>subdomains</strong>“, který je ovšem opět umístěn v adresáři s obsahem webu. Většina nevýhod uvedených v předchozím bodu odpadá. Přesto pro profesionální nasazení není ani takovýto systém rozhodně vhodný.</li>
<li>Jediný opravdu praktický a plnohodnotně využitelný způsob souborovým řízení poddomén je jejich umístění na stejnou úroveň.
<div class="wp-caption aligncenter" style="width: 161px"><img src="/data/blog/subdomeny_02.png" alt="Strukura FTP" width="151" height="145" /><p class="wp-caption-text">Strukura FTP</p></div>
<p>Na obrázku je jedna z nejlepších struktur adresářů na běžném hostingu. Soubory pro <em>hlavní</em> doménu jsou v adresáři <strong>/web/www/</strong> a další poddomény jsou v adresářích na stejné úrovni, tedy <strong>/web/subdomena/</strong>, ap. I když to může znít komplikovaně, ve skutečnosti je to velmi příjemné řešení.<br />
Toto řešení používají opravdoví profesinálové, na českém poli zejména: <a href="http://tojeono.cz/">Tojeono.cz</a>, <a href="http://ebola.cz/">Ebola.cz</a>, <a href="http://ceskyhosting.cz/">Ceskyhosting.cz</a> a dokonce i <a href="http://pipni.cz/">Pipni.cz</a>.</li>
</ul>
<p>Vyzývám tímto všechny hostingové společnosti, aby si tato slova szaly k srdci a trochu se zamysleli dříve, než vpustí klienty na své servery.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jakub-boucek.cz/blog/subdomeny-a-komercni-hostingy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP: magická funkce __toString() nemůže vyhazovat výjimky</title>
		<link>http://www.jakub-boucek.cz/blog/php-magicka-funkce-tostring-nemuze-vyhazovat-vyjimky/</link>
		<comments>http://www.jakub-boucek.cz/blog/php-magicka-funkce-tostring-nemuze-vyhazovat-vyjimky/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 22:19:32 +0000</pubDate>
		<dc:creator>Jakub Bouček</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.jakub-boucek.cz/blog/?p=175</guid>
		<description><![CDATA[Věděli jste to? Bohužel o tomto faktu dokumentace dosti nepříjemně mlčí a tak jsem jednoho dne narazil.]]></description>
			<content:encoded><![CDATA[<p>Věděli jste to?</p>
<p>Bohužel o tomto faktu dokumentace dosti nepříjemně mlčí a tak jsem jednoho dne narazil.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jakub-boucek.cz/blog/php-magicka-funkce-tostring-nemuze-vyhazovat-vyjimky/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Problém s přílohami ve SquirrelMail 1.4.13</title>
		<link>http://www.jakub-boucek.cz/blog/problem-s-prilohami-ve-squirrelmail/</link>
		<comments>http://www.jakub-boucek.cz/blog/problem-s-prilohami-ve-squirrelmail/#comments</comments>
		<pubDate>Sat, 14 Jun 2008 23:20:42 +0000</pubDate>
		<dc:creator>Jakub Bouček</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[Návody a FAQ]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.jakub-boucek.cz/blog/?p=52</guid>
		<description><![CDATA[V týdnu jsem dostal hlášení od Koldy, že jednomu z našich klientů nejdou odesílat přílohy. Pozastavil jsem se nad podivností této chyby a odkazoval jsem ho na nastavení jeho e-mailového klienta &#8211; myslel jsem totiž, že se k serveru připojuje pomocí POP3 a SMTP serveru, jako drtivá většina našich klientů. Jednalo se však o chybu [...]]]></description>
			<content:encoded><![CDATA[<p>V týdnu jsem dostal hlášení od <a href="http://kolda.bloguje.cz/">Koldy</a>, že jednomu z našich klientů nejdou odesílat přílohy. Pozastavil jsem se nad podivností této chyby a odkazoval jsem ho na nastavení jeho e-mailového klienta &#8211; myslel jsem totiž, že se k serveru připojuje pomocí POP3 a SMTP serveru, jako drtivá většina našich klientů. Jednalo se však o chybu na našem webovém rozhraní SquirrelMailu, které bylo klientům poskytnuto jako alternativa a po několik měsíců nebylo nikým využíváno.</p>
<p>Google, ani letmý pohled do dostupné dokumentace mi nenapověděl.</p>
<p>Při pokusu o uložení se vracela chyba <code>Nelze přesunout/zkopírovat soubor. Soubor není přiložen</code> (v originále <code>Could not move/copy file. File not attached</code>).</p>
<p>Prošel jsem celou konfiguraci, zkontroloval všechna nastavení, ale vše se zdálo být v pořádku. Teprve až podrobným zkoumáním kódu, který zpracovává soubory  tvořící přílohy mailu jsem vyvolal podrobné chybové hlášení PHP:</p>
<pre><strong>Warning</strong>:  move_uploaded_file(../attach/DynUVxB1G8peSN2zHNJWLs7s2lXvJN5K) [function.move-uploaded-file]: failed to open stream: No such file or directory in <strong>/web/webxyz.cz/mail/src/compose.php</strong> on line <strong>1389</strong>
<strong>Warning</strong>:  move_uploaded_file() [function.move-uploaded-file]: Unable to move '/web/_temp/upload/phpAA80.tmp' to '../attach/DynUVxB1G8peSN2zHNJWLs7s2lXvJN5K' in <strong><strong>/web/webxyz.cz/</strong></strong><strong>mail/src/compose.php</strong> on line <strong>1389
</strong></pre>
<p>A byl problém na světě. Ve standardní distribuci nejsou připraveny některé adresáře nezbytné pro plnou funkčnost projektu a je třeba je ručně vytvořit. Konkrétně adresář <code>/attach</code> v rootu projektu.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jakub-boucek.cz/blog/problem-s-prilohami-ve-squirrelmail/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Jak jsem si zaškodil</title>
		<link>http://www.jakub-boucek.cz/blog/jak-jsem-si-zaskodil/</link>
		<comments>http://www.jakub-boucek.cz/blog/jak-jsem-si-zaskodil/#comments</comments>
		<pubDate>Tue, 30 Oct 2007 03:08:00 +0000</pubDate>
		<dc:creator>Jakub Bouček</dc:creator>
				<category><![CDATA[Bezpečnost]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Pracovní vztahy]]></category>
		<category><![CDATA[Remcání]]></category>
		<category><![CDATA[Společnost]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Mým klientům a partnerům umožňuji využívat některé služby poskytované z mého účtu na hostingu. Jednou z takových služeb je umístění některých doplňků stránek (videa, fotky, ap.) na rychlejší hosting, než je zbytek webu. Velikou výhodu spatřuji v tom, že tyto služby mohu monitorovat a spravovat jednotně.Příkladem takové slžby je třeba vložené video do prezentace Plzeňských [...]]]></description>
			<content:encoded><![CDATA[<p>Mým klientům a partnerům umožňuji využívat některé služby poskytované z mého účtu na hostingu. Jednou z takových služeb je umístění některých doplňků stránek (videa, fotky, ap.) na rychlejší hosting, než je zbytek webu. Velikou výhodu spatřuji v tom, že tyto služby mohu monitorovat a spravovat jednotně.Příkladem takové slžby je třeba vložené video do prezentace Plzeňských ohýnků.Po delší době jsem se zašel podívat na statistiky návštěvnosti a nestačil jsem se divit. Služby byly neúměrně zneužívané více erotickými weby.<br />
<span id="more-34"></span></p>
<p>V první chvíli jsem zcela nechápal, jak je možné, že za poslední dva měsíce bylo staženo přes <strong>3 GB dat</strong>, zatímco běžně se přenos pohyboval v řádů desítek MB.</p>
<div class="ilust"><img src="http://boucek.info/data/bloguje_jak_jsem_skodil_00.png" alt="Ilustrace: statistika za měsíc říjen 2007 v grafu" /></div>
<p>Až pohled níž, do seznamu stránek, které služby využívají, mi podal vysvětlující informace. Doslova stovky adres, které sprostě zneužívaly v několika posledních měsících mnou poskytované služby k účelům, se kterými nesouhlasím – dokonce jsou přímo <strong>v rozporu s podmínkami</strong> hostingu, na němž služby provozuji (v ilustraci níže jsou nežádoucí adresy označeny červeně).</p>
<div class="ilust"><img src="http://boucek.info/data/bloguje_jak_jsem_skodil_01.png" alt="Ilustrace: seznam připojení služeb za měsíc říjen 2007 v tabulce" /></div>
<p>Abych byl upřímný, před časem jsem s pardubickou rádoby erotickou agenturou spolupracoval na internetových projektech a v rámci spolupráce jsem <strong>umožnil použití</strong> mnou spravovaného přehrávače video-sekvencí. Již tehdy jsem zdůrazňoval, že si <strong>výslovně nepřeji</strong>, aby byl nasazován pro jiné použití, než jak jsem jej tehdy nastavil a zprovoznil. Přehrávač byl tehdy použit pro uvítací, erotiky zcela prostou, nahrávku.</p>
<p>Krátce po té jsem ukončil s agenturou spolupráci – o důvodech bych se zde nerad blíže zmiňoval. Náhodou jsem sice zaznamenal, že se přehrávač objevil i na sousedních stránkách <span class="bad_link">agentury</span>, <strong>přestože tam neměl co dělat</strong>, ale blíže jsem se tím nezabýval.</p>
<p>Jenomže přehrávač, jak jsem dnes zjistil, byl použitý na mnoha stránkách věnovaných erotice a byly skrz něj přehrávány pornografické záběry.</p>
<h3>Jak se zbavit pijavice</h3>
<p>Přemýšlel jsem, jak problém efektivně odstranit.</p>
<p>První nejjednodušší variantou bylo prosté smazání přehrávače z místa, odkud je stahován. Tím bych však poškodil asi desítku klientů a další desítky soukromých projektů – včetně tohoto blogu – bych citelně ochromil. Musel bych pak ručně obejít všechny stránky, kde je přehrávač umístěn a opravit je.</p>
<p>Další nevýhody tohoto řešení:</p>
<ul>
<li>Uživatelé by byli zmateni a nedostatečně informováni,</li>
<li>poškodil bych své slušné klienty, kteří za nic nemohou,</li>
<li>viníci by nebyli dostatečně potrestáni,</li>
<li>snadno by se mohl problém opakovat</li>
<li>a hlavně, <strong>to prostě nebylo dost cool!</strong></li>
</ul>
<p>Vzpomněl jsem si, jak podobný problém řeší server <a href="http://blog.cz/">blog.cz</a>. Pokud je jejich obrázek vložen do cizí stránky, <strong>nezobrazí se</strong>. Namísto toho se však zobrazí nápis, že tohle se prostě nesmí.</p>
<p>V mém případě jsem však neměl situaci tak jednoduchou. <strong>Jediné, čím jsem mohl manipulovat byl přehrávač</strong> – flashová aplikace, která se stahovala z mých stránek. Nemohl jsem však již ovlivnit jeho <strong>nastavení</strong>, které bylo vepsáno přímo ve stránce, ke které jsem neměl přístup. Také jsem nemohl ovlivnit <strong>přehrávaná videa</strong>, protože tato jsou stahována z jiných serverů.</p>
<p><strong>Neumím ani pracovat</strong> s Flashem, takže podvrhnout přehrávač nepřipadalo v úvahu.</p>
<p>Začal jsem tedy zkoumat způsob vložení přehrávače do stránky a hledal jsem, zda by se v některém místě nedala najít slabina, kterou mohu využít. Byla tam. Vzhledem k tomu, že, přehrávač je získáván protokolem HTTP z adresy <code>//fotky.boucek.info/player/flvplayer.swf</code>, lze přikázat prohlížeči, aby se <strong>přesměroval na jinou adresu</strong>.</p>
<p>Všiml jsem si, že existují dvě metody, jak v HTML definovat parametry, ze kterých přehrávač čte cestu k přehrávanému videu:</p>
<div class="code"><code>&lt;<strong>embed</strong> <strong>src</strong>="http://fotky.boucek.info/player/flvplayer.swf?file=<span style="color: red;">http://cesta/k/videu.flv</span>"<br />
<strong>width</strong>="320" <strong>height</strong>="260"<br />
<strong>type</strong>="application/x-shockwave-flash" /&gt;</code></div>
<p>a nebo:</p>
<div class="code"><code>&lt;<strong>embed</strong> <strong>src</strong>="http://fotky.boucek.info/player/flvplayer.swf"<br />
<strong>width</strong>="320" <strong>height</strong>="260"<br />
<strong>type</strong>="application/x-shockwave-flash"<br />
<strong>flashvars</strong>="file=<span style="color: red;">http://cesta/k/videu.flv</span>" /&gt;</code></div>
<p>Bohužel všechny kradené prohlížeče jsou do stránek vkládány pomocí druhé varianty, tedy pomocí atributu <code>flashvars</code>. To je problém, protože pomocí přesměrování lze ovlivnit pouze parametry předané přímo v adrese přehrávače.</p>
<p>V zoufalství jsem zkusil ještě zkombinovat obě varianty a do kódu umístit cestu k videu oběma metodama a sledovat, která bude mít větší prioritu. Přehrávač totiž může pochopitelně v jednom okamžiku přehrávat <strong>pouze jedno video</strong>, proto si musí vybrat jedno z nich.</p>
<p>Naštěstí přehrávač dává přednost <strong>parametrům uvedeným přímo v adrese přehrávače</strong>, takže vhodným přesměrováním lze snadno změnit chování přehrávače.</p>
<p>Tím byla odstraněna poslední překážka a mohl jsem začít škodit :-)</p>
<h3>Jdeme škodit</h3>
<p>Ujasnil jsem si body, které <strong>musí akce splňovat</strong>:</p>
<ul>
<li>Musí zasáhnout pouze nežádoucí kopie přehrávače,</li>
<li>ostatní musí zůstat bez změny funkce,</li>
<li>musí být funkční ve všech prohlížečích,</li>
<li>přesměrování musí jít ovlivňovat velmi rychle, být flexibilní – to pro případ, že by změna přeci jen zasáhla přehrávače na stránkách klientů.</li>
</ul>
<p>Před začátkem programování jsem si připravil video, které budu prohlížeči podstrkovat. Volil jsem ostré viditelné a kontrastní barvy – červenou a bílou. Na konci videa jsem si neodpustil emotivní vyštěknutí :-)</p>
<div class="ilust"><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="100" height="100" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="src" value="http://fotky.boucek.info/player/flvplayer.swf" /><embed type="application/x-shockwave-flash" width="100" height="100" src="http://fotky.boucek.info/player/flvplayer.swf"></embed></object></div>
<p>Časově nejnáročnějším úkolem bylo naprogramování kódu, který bude dělat přesně to, co se po něm chce.</p>
<p>Sepsal jsem klíčová slova, kterými jsem odlišoval žádoucí a nežádoucí kopie. Tato slova se mohla vyskytovat <strong>v adrese</strong>, kterou byl přehrávač volán, nebo <strong>v adrese stránky</strong>, do které byl stahován (tzv. referer). Klíčová slova jsou tato:</p>
<ul>
<li>papaya-agency.com,</li>
<li>q3.cz,</li>
<li>ceskeholky.cz,</li>
<li>sex,</li>
<li>erotic,</li>
<li>porno.</li>
</ul>
<p>Dále bylo třeba zajistit, aby nedocházelo k <strong>nekonečnému přesměrovávání</strong>. To by se mohlo stát, protože když si prohlížeč zavolá přehrávač, dostane příkaz, aby se přesměroval na novou adresu. <strong>Prohlížeč musí poslechnout</strong>, tak volá přehrávač z nové adresy. Jenže obě adresy jsou <strong>skoro stejné</strong>, jen ta druhá je doplněná o cestu k nastrčenému videu, tudíž by prohlížeč dostával stále příkaz k přesměrování. Proto jsem nastrčenému videu dal neobvyklý název: „robber.fvl“ [zloděj, lupič] a zajistil, že pokud se volá přehrávač, který v adrese <strong>obsahuje slovo</strong> „robber“, nebude dále přesměrovávat.</p>
<p>Jak takové přesměrování praktikovat na serveru? Protože server soubor s příponou <code>*.flv</code> nijak nezpracovává, ale pouze posílá, je třeba pomocí <a href="http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html">Rewrite</a>, nebo jiné funkce serveru přepsat volanou adresu na nějaký PHP soubor. K tomu postačuje řádek ve tvaru: <code>RewriteRule ^.+$ index.php [L]</code>.</p>
<p>O zbytek už se postará PHP:</p>
<div class="code"><code><br />
<span style="color: #000000;"><br />
<span style="color: #0000bb;"><br />
&lt;?php<br />
</span><br />
<span style="color: #ff8000;"><br />
//Get base name of GET address</p>
<p></span><br />
<span style="color: #0000bb;"><br />
$uri_orig<br />
</span><br />
<span style="color: #007700;"><br />
=<br />
</span><br />
<span style="color: #0000bb;"><br />
$_SERVER<br />
</span><br />
<span style="color: #007700;"><br />
[<br />
</span><br />
<span style="color: #dd0000;"><br />
"REQUEST_URI"<br />
</span><br />
<span style="color: #007700;"><br />
];</p>
<p></span><br />
<span style="color: #0000bb;"><br />
$uri_bases<br />
</span><br />
<span style="color: #007700;"><br />
= array();</p>
<p></span><br />
<span style="color: #0000bb;"><br />
preg_match<br />
</span><br />
<span style="color: #007700;"><br />
(<br />
</span><br />
<span style="color: #dd0000;"><br />
'/^[^?]*/'<br />
</span><br />
<span style="color: #007700;">,<br />
</span><br />
<span style="color: #0000bb;"><br />
$uri_orig<br />
</span><br />
<span style="color: #007700;">,<br />
</span><br />
<span style="color: #0000bb;"><br />
$uri_bases<br />
</span><br />
<span style="color: #007700;"><br />
);</p>
<p></span><br />
<span style="color: #0000bb;"><br />
$uri_base<br />
</span><br />
<span style="color: #007700;"><br />
=<br />
</span><br />
<span style="color: #0000bb;"><br />
basename<br />
</span><br />
<span style="color: #007700;"><br />
(<br />
</span><br />
<span style="color: #0000bb;"><br />
$uri_bases<br />
</span><br />
<span style="color: #007700;"><br />
[<br />
</span><br />
<span style="color: #0000bb;"><br />
0<br />
</span><br />
<span style="color: #007700;"><br />
]);</p>
<p></span><br />
<span style="color: #ff8000;"><br />
//Verify base path and fix it to default if need</p>
<p></span><br />
<span style="color: #007700;"><br />
if (!<br />
</span><br />
<span style="color: #0000bb;"><br />
file_exists<br />
</span><br />
<span style="color: #007700;"><br />
(<br />
</span><br />
<span style="color: #dd0000;"><br />
"./$uri_base"<br />
</span><br />
<span style="color: #007700;"><br />
) ||<br />
</span><br />
<span style="color: #0000bb;"><br />
preg_match<br />
</span><br />
<span style="color: #007700;"><br />
(<br />
</span><br />
<span style="color: #dd0000;"><br />
'/\.php$/'<br />
</span><br />
<span style="color: #007700;">,<br />
</span><br />
<span style="color: #0000bb;"><br />
$uri_orig<br />
</span><br />
<span style="color: #007700;"><br />
))</p>
<p></span><br />
<span style="color: #0000bb;"><br />
$uri_base<br />
</span><br />
<span style="color: #007700;"><br />
=<br />
</span><br />
<span style="color: #dd0000;"><br />
"flvplayer.swf"<br />
</span><br />
<span style="color: #007700;"><br />
;</p>
<p></span></p>
<div class="hide_for_more"><span style="color: #ff8000;"><br />
//Get referer URL</p>
<p></span><br />
<span style="color: #0000bb;"><br />
$uri_ref<br />
</span><br />
<span style="color: #007700;"><br />
=<br />
</span><br />
<span style="color: #dd0000;"><br />
""<br />
</span><br />
<span style="color: #007700;"><br />
;<br />
if (isset(<br />
</span><br />
<span style="color: #0000bb;"><br />
$_SERVER<br />
</span><br />
<span style="color: #007700;"><br />
[<br />
</span><br />
<span style="color: #dd0000;"><br />
'HTTP_REFERER'<br />
</span><br />
<span style="color: #007700;"><br />
]))</p>
<p></span><br />
<span style="color: #0000bb;"><br />
$uri_ref<br />
</span><br />
<span style="color: #007700;"><br />
=<br />
</span><br />
<span style="color: #0000bb;"><br />
$_SERVER<br />
</span><br />
<span style="color: #007700;"><br />
[<br />
</span><br />
<span style="color: #dd0000;"><br />
'HTTP_REFERER'<br />
</span><br />
<span style="color: #007700;"><br />
];</p>
<p></span><br />
<span style="color: #ff8000;"><br />
//Set block_it flag to default</p>
<p></span><br />
<span style="color: #0000bb;"><br />
$block_it<br />
</span><br />
<span style="color: #007700;"><br />
=<br />
</span><br />
<span style="color: #0000bb;"><br />
false<br />
</span><br />
<span style="color: #007700;"><br />
;</p>
<p></span><br />
<span style="color: #ff8000;"><br />
//Find referer in blacklist</p>
<p></span><br />
<span style="color: #0000bb;"><br />
$uri_ref_blacklist<br />
</span><br />
<span style="color: #007700;"><br />
= array(<br />
</span><br />
<span style="color: #dd0000;"><br />
'/papaya-agency\.com/'<br />
</span><br />
<span style="color: #007700;">,<br />
</span><br />
<span style="color: #dd0000;"><br />
'/q3\.cz/'<br />
</span><br />
<span style="color: #007700;">,<br />
</span><br />
<span style="color: #dd0000;"><br />
'/ceskeholky\.cz/'<br />
</span><br />
<span style="color: #007700;">,<br />
</span><br />
<span style="color: #dd0000;"><br />
'/sex/'<br />
</span><br />
<span style="color: #007700;">,<br />
</span><br />
<span style="color: #dd0000;"><br />
'/erotic/'<br />
</span><br />
<span style="color: #007700;">,<br />
</span><br />
<span style="color: #dd0000;"><br />
'/porno/'<br />
</span><br />
<span style="color: #007700;"><br />
);<br />
foreach(<br />
</span><br />
<span style="color: #0000bb;"><br />
$uri_ref_blacklist<br />
</span><br />
<span style="color: #007700;"><br />
as<br />
</span><br />
<span style="color: #0000bb;"><br />
$uri_ref_bad<br />
</span><br />
<span style="color: #007700;"><br />
)</p>
<p></span><br />
<span style="color: #0000bb;"><br />
$block_it<br />
</span><br />
<span style="color: #007700;"><br />
=<br />
</span><br />
<span style="color: #0000bb;"><br />
$block_it<br />
</span><br />
<span style="color: #007700;"><br />
||<br />
</span><br />
<span style="color: #0000bb;"><br />
preg_match<br />
</span><br />
<span style="color: #007700;"><br />
(<br />
</span><br />
<span style="color: #0000bb;"><br />
$uri_ref_bad<br />
</span><br />
<span style="color: #007700;">,<br />
</span><br />
<span style="color: #0000bb;"><br />
$uri_ref<br />
</span><br />
<span style="color: #007700;"><br />
) ||<br />
</span><br />
<span style="color: #0000bb;"><br />
preg_match<br />
</span><br />
<span style="color: #007700;"><br />
(<br />
</span><br />
<span style="color: #0000bb;"><br />
$uri_ref_bad<br />
</span><br />
<span style="color: #007700;">,<br />
</span><br />
<span style="color: #0000bb;"><br />
$uri_orig<br />
</span><br />
<span style="color: #007700;"><br />
);</p>
<p></span><br />
<span style="color: #ff8000;"><br />
//Disable if already fixed</p>
<p></span><br />
<span style="color: #0000bb;"><br />
$block_it<br />
</span><br />
<span style="color: #007700;"><br />
=<br />
</span><br />
<span style="color: #0000bb;"><br />
$block_it<br />
</span><br />
<span style="color: #007700;"><br />
&amp;&amp; (!<br />
</span><br />
<span style="color: #0000bb;"><br />
preg_match<br />
</span><br />
<span style="color: #007700;"><br />
(<br />
</span><br />
<span style="color: #dd0000;"><br />
'/robber/'<br />
</span><br />
<span style="color: #007700;">,<br />
</span><br />
<span style="color: #0000bb;"><br />
$uri_orig<br />
</span><br />
<span style="color: #007700;"><br />
));</p>
<p></span><br />
<span style="color: #ff8000;"><br />
//Pokud se má blokovat</p>
<p></span><br />
<span style="color: #007700;"><br />
if(<br />
</span><br />
<span style="color: #0000bb;"><br />
$block_it<br />
</span><br />
<span style="color: #007700;"><br />
) {</p>
<p></span><br />
<span style="color: #ff8000;"><br />
//...blokuj</p>
<p></span><br />
<span style="color: #0000bb;"><br />
header<br />
</span><br />
<span style="color: #007700;"><br />
(<br />
</span><br />
<span style="color: #dd0000;"><br />
"HTTP/1.1 307 Temporary Redirect"<br />
</span><br />
<span style="color: #007700;"><br />
);</p>
<p></span><br />
<span style="color: #0000bb;"><br />
header<br />
</span><br />
<span style="color: #007700;"><br />
(<br />
</span><br />
<span style="color: #dd0000;"><br />
"Location: http://fotky.boucek.info/player/$uri_base?image=http://fotky.boucek.info/robber.gif&amp;file=http://fotky.boucek.info/robber.flv"<br />
</span><br />
<span style="color: #007700;"><br />
);<br />
} else {</p>
<p></span><br />
<span style="color: #ff8000;"><br />
//...když ne, tak pošli původní soubor, kterej byl žádanej</p>
<p></span><br />
<span style="color: #007700;"><br />
if (<br />
</span><br />
<span style="color: #0000bb;"><br />
preg_match<br />
</span><br />
<span style="color: #007700;"><br />
(<br />
</span><br />
<span style="color: #dd0000;"><br />
'/\.swf$/'<br />
</span><br />
<span style="color: #007700;">,<br />
</span><br />
<span style="color: #0000bb;"><br />
$uri_base<br />
</span><br />
<span style="color: #007700;"><br />
))</p>
<p></span><br />
<span style="color: #0000bb;"><br />
header<br />
</span><br />
<span style="color: #007700;"><br />
(<br />
</span><br />
<span style="color: #dd0000;"><br />
'Content-Type: application/x-shockwave-flash'<br />
</span><br />
<span style="color: #007700;"><br />
);</p>
<p></span><br />
<span style="color: #0000bb;"><br />
header<br />
</span><br />
<span style="color: #007700;"><br />
(<br />
</span><br />
<span style="color: #dd0000;"><br />
'Content-Length: '<br />
</span><br />
<span style="color: #007700;">.<br />
</span><br />
<span style="color: #0000bb;"><br />
filesize<br />
</span><br />
<span style="color: #007700;"><br />
(<br />
</span><br />
<span style="color: #dd0000;"><br />
"./$uri_base"<br />
</span><br />
<span style="color: #007700;"><br />
));</p>
<p></span><br />
<span style="color: #0000bb;"><br />
readfile<br />
</span><br />
<span style="color: #007700;"><br />
(<br />
</span><br />
<span style="color: #dd0000;"><br />
"./$uri_base"<br />
</span><br />
<span style="color: #007700;"><br />
);<br />
}<br />
</span></div>
<p><button onclick="delStyleRule(style_rule_id);this.parentNode.removeChild(this);">Zobrazit celý kód</button></p>
<p>?&gt;</p>
<p></span></code></div>
<p>A stránky jsou rázem ozdobené:</p>
<div class="ilust"><img src="http://boucek.info/data/bloguje_jak_jsem_skodil_02.png" alt="Ilustrace: Náhled na stránku obsazenou červenobílým obdélníkem" /></div>
<div class="ilust"><img src="http://boucek.info/data/bloguje_jak_jsem_skodil_03.jpg" alt="Ilustrace: Náhled na stránku obsazenou červenobílým obdélníkem" /></div>
<p><script type="text/javascript"><!--
    addEvent(window, 'load', init_me);
    var style_rule_id;</p>
<p>    function init_me() {
      style_rule_id = addStyleRule('.hide_for_more', 'display: none;');</p>
<p>      var nodesInContent = document.getElementById('content').getElementsByTagName('*');
      for (var i = 0; i < nodesInContent.length; i++) { 
        var elem = nodesInContent[i];
        if(elem.className == "bad_link") {
          var url = elem.firstChild.nodeValue.replace(/ /g, '');
          var newElem = document.createElement('a');
          newElem.appendChild(document.createTextNode(url));
          newElem.setAttribute('href', 'http://' + url);
          if(elem.getAttribute('title'))
            newElem.setAttribute('title', 'Přejít na stránky: ' + elem.getAttribute('title'));
          elem.parentNode.replaceChild(newElem, elem);
        }
      }
    }</p>
<p>    /** 
    *  Priradi urcite udalosti objektu zadanou obsluznou funkci. Rozhodne 
    *  automaticky, zda pouzit attachEvent, nebo addEventListener. Resi problem 
    *  s pouzitim this uvnitr obsluzne funkce. 
    *  @param obj Objekt, u nehoz chceme udalost obsluhovat. 
    *  @param event Udalost, jiz hodlame obslouzit - ve formatu click, load apod. 
    *               (nikoliv onclick, onload). 
    *  @param funct Nazev obsluzne funkce. 
    */  
    function addEvent(obj, event, funct) {  
      if (obj.attachEvent) { //IE  
        obj['e' + event + funct] = funct;  
        obj['x' + event + funct] = function() {  
          obj['e' + event + funct](window.event);  
        }  
        obj.attachEvent('on' + event, obj['x' + event + funct]);  
      } else // other browser  
        obj.addEventListener(event, funct, false);  
    }   </p>
<p>    /** 
     *  Odstrani zadanou obsluznou funkci registrovanou u objektu. 
     *  @param obj Objekt, u nehoz chceme obsluznou funkci odstrani. 
     *  @param event Udalost, jiz doposud funkce obsluhovala - ve formatu click, 
     *               load apod. (nikoliv onclick, onload). 
     *  @param funct Nazev obsluzne funkce, jiz planujeme odstranit. 
     */  
    function removeEvent(obj, event, funct) {  
      if (obj.detachEvent) { // IE  
        obj.detachEvent('on' + event, obj[event + funct]);  
        obj['x' + event + funct] = null;  
      } else // other browser  
        obj.removeEventListener(event, funct, false );  
    }</p>
<p>  function addStyleRule(selector, value) {
      var stylesht = document.styleSheets[0];
      var styleshts_lngt = (stylesht.cssRules?stylesht.cssRules.length:stylesht.rules.length);
      if (stylesht.insertRule) {
        stylesht.insertRule(selector + ' {' + value + '}', styleshts_lngt);
        return styleshts_lngt;
      } else if (stylesht.addRule) {
        stylesht.addRule(selector, value, styleshts_lngt);
        return styleshts_lngt;
      } 
      return false;
    }</p>
<p>    function delStyleRule(rule_id) {
      var stylesht = document.styleSheets[0];
      if (stylesht.deleteRule) {
        stylesht.deleteRule(rule_id);
      } else if (stylesht.removeRule) {
        stylesht.removeRule(rule_id);
      } else {
        return false;
      }
      return true;
    }
  // -->
// --&gt;
// --&gt;
// --&gt;</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.jakub-boucek.cz/blog/jak-jsem-si-zaskodil/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

