<?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"
	>

<channel>
	<title>Programista PHP</title>
	<atom:link href="http://blog.karpowicz.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.karpowicz.net</link>
	<description>Radek Karpowicz</description>
	<pubDate>Wed, 06 Aug 2008 08:11:37 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>Poolcamp i 3camp</title>
		<link>http://blog.karpowicz.net/poolcamp-i-3camp/</link>
		<comments>http://blog.karpowicz.net/poolcamp-i-3camp/#comments</comments>
		<pubDate>Tue, 17 Jun 2008 23:40:00 +0000</pubDate>
		<dc:creator>Radek</dc:creator>
		
		<category><![CDATA[poolcamp]]></category>

		<guid isPermaLink="false">http://blog.karpowicz.net/?p=33</guid>
		<description><![CDATA[
Jak widać na powyższym zdjęciu Internetowa społeczność również jest w stanie się spotkać i przy tym świetnie bawić. Pogoda była piękna, atmosfera zlotu rewelacyjna. Pomijając fakt, że na 3 czy 4 rozgrywki bilarda wygrałem może 1, naprawdę warto było tam być i grać w U7!
Poolcamp poprzedził trójmiejski odpowiednik poznańskiego barcampa - 3camp, na którym to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.karpowicz.net/wp-content/uploads/2008/06/poolcamp5.jpg" rel="lightbox"><img src="http://blog.karpowicz.net/wp-content/uploads/2008/06/poolcamp5.jpg" alt="poolcamp" title="poolcamp 5" /></a></p>
<p>Jak widać na powyższym zdjęciu Internetowa społeczność również jest w stanie się spotkać i przy tym świetnie bawić. Pogoda była piękna, atmosfera zlotu rewelacyjna. Pomijając fakt, że na 3 czy 4 rozgrywki bilarda wygrałem może 1, naprawdę warto było tam być i grać w U7!</p>
<p>Poolcamp poprzedził trójmiejski odpowiednik poznańskiego barcampa - <a href='http://3camp.pl'>3camp</a>, na którym to byliśmy również w licznym gronie. 3camp opuściliśmy zaraz po przerwie z tego względu, iż mieliśmy zarezerwowane stoły w U7. Odnośnie prezentacji uczucia mam mieszane, szczerze mówiąc jeszcze wiele brakuje naszym pomorskim kolegą w porównania z poziomem obecnym na barcampie.</p>
<p><strong>Galeria</strong>: <a href="http://janusz.kaliszczak.pl/images/blog/2008.06.17-3camp-poolcamp/">http://janusz.kaliszczak.pl/images/blog/2008.06.17-3camp-poolcamp/</a> oraz <a href="http://www.flickr.com/photos/harnir/sets/72157605672618713/">http://www.flickr.com/photos/harnir/sets/72157605672618713/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.karpowicz.net/poolcamp-i-3camp/feed/</wfw:commentRss>
		</item>
		<item>
		<title>AP mode, AdHoc Wifi - atheros madwifi</title>
		<link>http://blog.karpowicz.net/ap-mode-adhoc-wifi-atheros-madwifi/</link>
		<comments>http://blog.karpowicz.net/ap-mode-adhoc-wifi-atheros-madwifi/#comments</comments>
		<pubDate>Wed, 28 May 2008 19:05:17 +0000</pubDate>
		<dc:creator>Radek</dc:creator>
		
		<category><![CDATA[debian]]></category>

		<category><![CDATA[wifi]]></category>

		<category><![CDATA[atheros]]></category>

		<guid isPermaLink="false">http://blog.karpowicz.net/?p=28</guid>
		<description><![CDATA[Konfiguracja karty na chipsecie Atherosa aby pracowała w trybie AP nie jest specjalnie skomplikowana, lecz sprzężenie ze sobą udostępnienia sieci przez drugi interfejs, spięcie ich w mostek oraz ustawienia polityki bezpieczeństwa to złożone zadanie.
Wiele podręcznikowych przykładów, które znalazłem w sieci nie działało bądź działało nie tak jakbym sobie tego życzył.
Poniżej przedstawiam schemat sieci (made in [...]]]></description>
			<content:encoded><![CDATA[<p class="akap">Konfiguracja karty na chipsecie Atherosa aby pracowała w trybie AP nie jest specjalnie skomplikowana, lecz sprzężenie ze sobą udostępnienia sieci przez drugi interfejs, spięcie ich w mostek oraz ustawienia polityki bezpieczeństwa to złożone zadanie.<br />
Wiele podręcznikowych przykładów, które znalazłem w sieci nie działało bądź działało nie tak jakbym sobie tego życzył.</p>
<p>Poniżej przedstawiam schemat sieci (made in Gimp), na której to bazie będziemy konfigurować bezprzewodowy punkt dostępu do Internetu.</p>
<p><center><a href="http://blog.karpowicz.net/wp-content/uploads/2008/05/hostap.png" rel="lightbox[groupname]"><img src="http://blog.karpowicz.net/wp-content/uploads/2008/05/hostap-300x246.png" alt="" title="WiFi Network" width="300" height="246" class="aligncenter size-medium wp-image-30" /></a></center><br />
<span id="more-28"></span></p>
<p class="akap">Komputer, który zostanie podpięty do sieci Internet przez interfejs <strong>eth0</strong> pełnił będzie rolę stacji udostępniającej połączenie na interfejsie <strong>ath0</strong> a więc zarazem posłuży jako punkt dostępowy AP dla reszty maszyn w sieci.<br />
Na komputerze udostępniającym połączenie niezbędne jest zainstalowanie pakietu <em>madwifi</em> oraz <em>wpasupplicant</em>. Pakiet z WPA jest nam potrzebny do zabezpieczenia AP przed niepożądanymi stacjami roboczymi, które ewentualnie będą chciały skorzystać z naszego dostępu do Internetu.</p>
<p class="akap">AP do szyfrowania transmisji wykorzystywać będzie WPA. Tak więc kolejnym krokiem będzie zainstalowanie oraz skonfigurowanie <strong>Hostapd</strong>, który będzie pełnił rolę daemona obsługującego autentykację oraz pracującego jako AP.<br />
Konfiguracja dla Hostapd:</p>
<pre>interface=<strong>ath0</strong>
bridge=<strong>br0</strong>
driver=<strong>madwifi</strong>
# show verbose output
logger_syslog=-1
logger_syslog_level=2
logger_stdout=-1
logger_stdout_level=2
debug=4
dump_file=/tmp/hostapd.dump
ctrl_interface=/var/run/hostapd
ctrl_interface_group=0
ssid=<strong>domowy_ap</strong>
eapol_key_index_workaround=0
eap_server=0
wpa=1
#wpa_psk_file=/etc/hostapd/wpa_psk
wpa_key_mgmt=<strong>WPA-PSK</strong>
wpa_pairwise=TKIP
wpa_passphrase=<strong>tajneHaslo
</strong></pre>
<p>Z czego należy zauważyć, iż hasło podawane jest w formie jawnej. Jeżeli nam to nie odpowiada, możemy odkomentować linię <em>wpa_psk_file</em> i tym samym zdefiniować ścieżkę do pliku z kluczem wygenerowanym przez <em>wpa_passphrase</em>.</p>
<p>Rozpoczęcie udostępniania połączenia Internetowego sprowadza się do następujących czynności:
<ul>
<li>Uruchomienia skryptu <em>start_ap.sh</em> (którego kod znajduje się niżej)</li>
<li>Wystartowania Hostapd (hostapd /etc/hostapd/hostapd.conf)</li>
</ul>
<p>Ze względu, iż w konfiguracji Hostapd ustawiliśmy tryb debug na 4 (verbose mode) na konsoli zostaną wyświetlone wszystkie informacje odnośnie błędów, inicjalizacji połączeń itd:</p>
<p><code>Configuration file: /etc/hostapd/hostapd.conf<br />
Configure bridge br0 for EAPOL traffic.<br />
madwifi_set_privacy: enabled=0<br />
BSS count 1, BSSID mask ff:ff:ff:ff:ff:ff (0 bits)<br />
madwifi_sta_deauth: addr=ff:ff:ff:ff:ff:ff reason_code=3<br />
madwifi_set_privacy: enabled=0<br />
madwifi_del_key: addr=00:00:00:00:00:00 key_idx=0<br />
madwifi_del_key: addr=00:00:00:00:00:00 key_idx=1<br />
madwifi_del_key: addr=00:00:00:00:00:00 key_idx=2<br />
madwifi_del_key: addr=00:00:00:00:00:00 key_idx=3<br />
Using interface ath0 with hwaddr 11:11:11:11:11:11 and ssid 'domowy_ap'<br />
.........................................................</code></p>
<p>Wyłączenie Hostapd odbywa się poprzez standardowy hotkey CTRL+C natomiast interfejsy sieciowe przywracamy do pierwotnego stanu przez uruchomienie <em>stop_ap.sh</em>. Skrypty start_ap i stop_ap stworzyłem na własne potrzeby z tego względu, iż ciągłe uruchamiane tych samych poleceń było strasznie uciążliwe i spowalniało cały proces.</p>
<p>Opis interfejsów umieszczonych we wpisie:<br />
<strong>ath0</strong> - bezprzewodowa karta sieciowa pracująca w trybie AP<br />
<strong>eth0</strong> - karta Ethernet łączącą komputer z Internetem<br />
<strong>br0</strong> - mostek sieciowy między ath0 i eth0<br />
<strong>192.168.0.111</strong> - komputer z interfejsem bezprzewodowym, który udostępnia połączenie<br />
<strong>192.168.0.1</strong> - bramka sieciowa (gateway)</p>
<p>Systemem operacyjnym, na którym uruchamiałem Hostapd jest Debian. Bezprzewodowa karta sieciowa to Atheros AR5BMB5.</p>
<p class="info"><strong>start_ap.sh</strong> - podnosi interfejs wifi, ładuje drivery, ustawia kartę w tryb Access Pointa, tworzy mostek oraz dodaje domyślną bramę.</p>
<pre>
#!/bin/sh

# unload madwifi
madwifi-unload

# load madwifi
modprobe ath_pci
modprobe wlan_scan_sta
modprobe ath_rate_sample
modprobe wlan
modprobe ath_hal

# set up wifi interface
ifconfig <strong>wifi0</strong> up

# set card into AP mode
wlanconfig <strong>ath0</strong> destroy
wlanconfig <strong>ath0</strong> create wlandev <strong>wifi0</strong> wlanmode ap

ifconfig <strong>ath0</strong> 0.0.0.0
ifconfig <strong>eth0</strong> 0.0.0.0

# create bridge
brctl addbr br0
brctl addif br0 <strong>eth0</strong>
brctl addif br0 <strong>ath0</strong>
ifconfig br0 <strong>192.168.0.111</strong> up

# add default gateway
route add default gw <strong>192.168.0.1</strong></pre>
<p class="info"><strong>stop_ap.sh</strong> - skrypt zatrzymujący AP. Usuwa drivery madwifi z pamięci, kładzie interfejsy oraz restartuje sieć.</p>
<pre>#!/bin/sh

# unload madwifi
madwifi-unload

# down interfaces
ifconfig <strong>eth0</strong> down
ifconfig br0 down

# delete bridge
brctl delif <strong>ath0</strong>
brctl delif <strong>eth0</strong>
brctl delbr br0

/etc/init.d/networking stop
/etc/init.d/networking start
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.karpowicz.net/ap-mode-adhoc-wifi-atheros-madwifi/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Triggery w MySQL</title>
		<link>http://blog.karpowicz.net/triggery-w-mysql/</link>
		<comments>http://blog.karpowicz.net/triggery-w-mysql/#comments</comments>
		<pubDate>Fri, 07 Mar 2008 21:22:56 +0000</pubDate>
		<dc:creator>Radek</dc:creator>
		
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://blog.karpowicz.net/triggery-w-mysql/</guid>
		<description><![CDATA[Momentami dochodzi do sytuacji, w których modyfikacja kodu aplikacji jest ostatecznością. Wtedy to rozwiązania pośrednie nie naruszające struktury systemu stają się niezwykle użyteczne.
Tak też było w tym przypadku, nie chciałem modyfikować istniejącego kodu PHP i zmian dokonałem na poziomie MySQL deklarując wyzwalacze (ang. triggers).

Definicja triggera w MySQL wygląda następująco:
CREATE
&#160; &#160; TRIGGER&#160;trigger_name trigger_time trigger_event
&#160; &#160; ON&#160;tbl_name [...]]]></description>
			<content:encoded><![CDATA[<p class="akap">Momentami dochodzi do sytuacji, w których modyfikacja kodu aplikacji jest ostatecznością. Wtedy to rozwiązania pośrednie nie naruszające struktury systemu stają się niezwykle użyteczne.<br />
Tak też było w tym przypadku, nie chciałem modyfikować istniejącego kodu PHP i zmian dokonałem na poziomie MySQL deklarując wyzwalacze (ang. triggers).</p>
<p><span id="more-22"></span><br />
Definicja triggera w MySQL wygląda następująco:</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">CREATE</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">TRIGGER</span><span style="color: Gray;">&nbsp;</span><span style="color: #00008b;">trigger_name</span><span style="color: Gray;"> </span><span style="color: Blue;">trigger_time</span><span style="color: Gray;"> </span><span style="color: Blue;">trigger_event</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">ON</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">tbl_name</span><span style="color: Gray;"> </span><span style="color: Green;">FOR</span><span style="color: Gray;"> </span><span style="color: Green;">EACH</span><span style="color: Gray;"> </span><span style="color: Green;">ROW</span><span style="color: Gray;"> </span><span style="color: Blue;">trigger_stmt</span></li></ol></div>
<p><em>Trigger_event</em> to zdarzenie, po którym następuje wywołanie określonego bloku instrukcji. Możliwe opcje to:</p>
<ul>
<li>INSERT - dodanie rekordu do tabeli</li>
<li>UPDATE - uaktualnienie rekordu</li>
<li>DELETE - usunięcie rekordu</li>
</ul>
<p>Z czego triggery mogą być wywoływane przed danym zdarzeniem - <em>BEFORE</em> lub po wystąpieniu danego zdarzenia - <em>AFTER</em>.</p>
<p>Rozważmy następujący scenariusz:</p>
<p class="akap">Istnieje tabela przechowująca dane dotyczące książek, jest to system wykorzystywany w bibliotece XYZ. Dostęp do systemu ma wielu użytkowników za pośrednictwem panelu administracyjnego. Możliwe jest dodawanie, usuwanie oraz modyfikacja pozycji książkowych. Aplikacja tworzona była dość dawno i z tego też względu zapomniano o zaimplementowaniu potrzebnych dzisiaj funkcjonalności.<br />
Pewnego dnia bibliotekarka chcąc dodać nową książkę do bazy danych, zauważyła iż ktoś z użytkowników popełnił błąd podczas edycji ostatnio dodanych pozycji i usunął jedną z książek. Chcąc powiadomić użytkownika o błędzie uświadomiła sobie, że nie jest w stanie się dowiedzieć, który z kilkunastu bywalców biblioteki dokonał błędnej modyfikacji, kiedy oraz jaka książka została usunięta. Wezwano więc informatyka aby zaimplementował mechanizm pozwalający na śledzenie historii zmian dokonywanych przez osoby z poziomu panelu administracyjnego.<br />
System był przestarzały, tym samym w kodzie źródłowym istniały rozwiązania już nie tak popularne jak niegdyś. Programista stwierdził, iż szybciej będzie jeżeli skorzysta z udogodnień oferowanych przez MySQL w postaci triggerów, niżeli miałby tracić czas na analizę kodu źródłowego i jego modyfikację.</p>
<p>Struktura tabeli zawierającej pozycje książkowe przedstawia się następująco:</p>
<pre>
+---------------+------------------+------+-----+---------+----------------+
| Field         | Type             | Null | Key | Default | Extra          |
+---------------+------------------+------+-----+---------+----------------+
| id_book       | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| b_title       | varchar(45)      | NO   |     | NULL    |                |
| b_description | varchar(255)     | NO   |     | NULL    |                |
| b_datetime    | datetime         | YES  |     | NULL    |                |
+---------------+------------------+------+-----+---------+----------------+
</pre>
<p>Aby możliwe, było prowadzenie historii zmian potrzebna jest dodatkowa tabela, do której będą zapisywane logi.</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">CREATE</span><span style="color: Gray;"> </span><span style="color: Green;">TABLE</span><span style="color: Gray;"> </span><span style="color: #8b0000;">`</span><span style="color: Blue;">test</span><span style="color: #8b0000;">`</span><span style="color: Gray;">.</span><span style="color: #8b0000;">`</span><span style="color: Blue;">bibl_logs</span><span style="color: #8b0000;">`</span><span style="color: Gray;"> </span><span style="color: Olive;">(</span></li>
<li><span style="color: Gray;">&nbsp; </span><span style="color: #8b0000;">`</span><span style="color: Blue;">id_log</span><span style="color: #8b0000;">`</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">INTEGER</span><span style="color: Gray;"> </span><span style="color: Blue;">UNSIGNED</span><span style="color: Gray;"> </span><span style="color: Green;">NOT</span><span style="color: Gray;"> </span><span style="color: Green;">NULL</span><span style="color: Gray;"> </span><span style="color: Blue;">AUTO_INCREMENT</span><span style="color: Gray;">,</span></li>
<li><span style="color: Gray;">&nbsp; </span><span style="color: #8b0000;">`</span><span style="color: Blue;">l_bookt</span><span style="color: #8b0000;">`</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">VARCHAR</span><span style="color: Olive;">(</span><span style="color: Maroon;">255</span><span style="color: Olive;">)</span><span style="color: Gray;">,</span></li>
<li><span style="color: Gray;">&nbsp; </span><span style="color: #8b0000;">`</span><span style="color: Blue;">l_datetime</span><span style="color: #8b0000;">`</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">DATETIME</span><span style="color: Gray;"> </span><span style="color: Green;">NOT</span><span style="color: Gray;"> </span><span style="color: Green;">NULL</span><span style="color: Gray;">,</span></li>
<li><span style="color: Gray;">&nbsp; </span><span style="color: Green;">PRIMARY</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">KEY</span><span style="color: Gray;"> </span><span style="color: Olive;">(</span><span style="color: #8b0000;">`</span><span style="color: Blue;">id_log</span><span style="color: #8b0000;">`</span><span style="color: Olive;">)</span></li>
<li><span style="color: Olive;">)</span></li></ol></div>
<pre>
+------------+------------------+------+-----+---------+----------------+
| Field      | Type             | Null | Key | Default | Extra          |
+------------+------------------+------+-----+---------+----------------+
| id_log     | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| l_bookt    | varchar(255)     | YES  |     | NULL    |                |
| l_datetime | datetime         | YES  |     | NULL    |                |
+------------+------------------+------+-----+---------+----------------+
</pre>
<p>Teraz można przejść do deklaracji wyzwalacza dla tabeli <em>bibl_books</em>. Podczas usuwania rekordu z tabeli zawierającej książki automatycznie dodawany będzie wpis w tabeli z logami - historia zmian.</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">CREATE</span><span style="color: Gray;"> </span><span style="color: Green;">TRIGGER</span><span style="color: Gray;"> </span><span style="color: Blue;">histlog</span><span style="color: Gray;"> </span><span style="color: Green;">BEFORE</span><span style="color: Gray;"> </span><span style="color: Green;">DELETE</span><span style="color: Gray;"> </span><span style="color: Green;">ON</span><span style="color: Gray;"> </span><span style="color: Blue;">bibl_books</span></li>
<li><span style="color: Green;">FOR</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">EACH</span><span style="color: Gray;"> </span><span style="color: Green;">ROW</span></li>
<li><span style="color: Green;">INSERT</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">INTO</span><span style="color: Gray;"> </span><span style="color: Blue;">bibl_logs</span><span style="color: Gray;"> </span><span style="color: Olive;">(</span><span style="color: Blue;">id_log</span><span style="color: Gray;">, </span><span style="color: Blue;">l_bookt</span><span style="color: Gray;">, </span><span style="color: Blue;">l_datetime</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Green;">VALUES</span><span style="color: Gray;"> </span><span style="color: Olive;">(</span><span style="color: #8b0000;">''</span><span style="color: Gray;">, </span><span style="color: Green;">OLD</span><span style="color: Gray;">.</span><span style="color: Blue;">b_title</span><span style="color: Gray;">, </span><span style="color: Blue;">NOW</span><span style="color: Olive;">())</span><span style="color: Gray;">;</span></li></ol></div>
<p>W ten sposób wpisy usuwane z tabeli <em>bibl_books</em> będą lądować w tabeli <em>bibl_logs</em>.</p>
<p class="akap">
Wyzwalacze w wielu sytuacjach mogą stać się bardzo przydatne, momentami zaoszczędzają nam konieczności ingerencji w kod źródłowy aplikacji aby uzyskać pożądane efekty. Możliwa jest także deklaracja zmiennych oraz przypisywanie do nich wartości w trigerrach:
</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">BEGIN</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">DECLARE</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">counter</span><span style="color: Gray;"> = </span><span style="color: Green;">INTEGER</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">SELECT</span><span style="color: Gray;">&nbsp;</span><span style="color: #00008b;">count</span><span style="color: Olive;">(</span><span style="color: Blue;">id_book</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Green;">INTO</span><span style="color: Gray;"> </span><span style="color: Blue;">counter</span><span style="color: Gray;"> </span><span style="color: Green;">FROM</span><span style="color: Gray;"> </span><span style="color: Blue;">bibl_books</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">IF</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">counter</span><span style="color: Gray;"> &gt; </span><span style="color: Maroon;">0</span><span style="color: Gray;"> </span><span style="color: Green;">THEN</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/* kod SQL */</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">END</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">IF</span><span style="color: Gray;">;</span></li>
<li><span style="color: Green;">END</span><span style="color: Gray;">;</span></li></ol></div>
<p>Więcej informacji na temat trigerrów można znaleźć na poniższych stronach:</p>
<p><a href="http://www.quest-pipelines.com/newsletter-v8/0207_D.htm" rel="nofollow">http://www.quest-pipelines.com/newsletter-v8/0207_D.htm</a><br />
<a href="http://forge.mysql.com/wiki/Triggers" rel="nofollow">http://forge.mysql.com/wiki/Triggers</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.karpowicz.net/triggery-w-mysql/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Tshark - zrzut pakietów z danymi</title>
		<link>http://blog.karpowicz.net/tshark-zrzucone-pakiety-danych/</link>
		<comments>http://blog.karpowicz.net/tshark-zrzucone-pakiety-danych/#comments</comments>
		<pubDate>Fri, 07 Mar 2008 19:14:45 +0000</pubDate>
		<dc:creator>Radek</dc:creator>
		
		<category><![CDATA[debian]]></category>

		<category><![CDATA[python]]></category>

		<category><![CDATA[sniffer]]></category>

		<category><![CDATA[tshark]]></category>

		<guid isPermaLink="false">http://blog.karpowicz.net/tshark-zrzucone-pakiety-danych/</guid>
		<description><![CDATA[
Tshark jest to analizator ruchu sieciowego, pozwala na przechwytywanie pakietów krążących w lokalnej sieci. Jest to wersja Wiresharka pozbawiona wygodnego GUI.

W ostatnim czasie potrzebowałem wydobyć interesujące mnie informacje ze zrzuconych danych pakietowych do plików wygenerowanych przez tsharka. Ze względu na fakt, iż nie były to czyste dane lecz też nagłówki protokołów sieciowych oraz ramki musiałem [...]]]></description>
			<content:encoded><![CDATA[<p class="info">
<a href="http://www.wireshark.org/docs/man-pages/tshark.html" rel="nofollow">Tshark</a> jest to analizator ruchu sieciowego, pozwala na przechwytywanie pakietów krążących w lokalnej sieci. Jest to wersja Wiresharka pozbawiona wygodnego GUI.
</p>
<p class="akap">W ostatnim czasie potrzebowałem wydobyć interesujące mnie informacje ze zrzuconych danych pakietowych do plików wygenerowanych przez tsharka. Ze względu na fakt, iż nie były to czyste dane lecz też nagłówki protokołów sieciowych oraz ramki musiałem te dane odpowiednio wyłuskać.<br />
Napisałem do tego celu skrypt w pythonie, który interesujące mnie pakiety wydobył z pliku i zapisał na wyjściu. Widać po kodzie, że pisany był w pewien sposób pod protokół gadu-gadu.</p>
<p><span id="more-20"></span><br />
Poniżej przedstawiam przykładowy fragment danych przechwyconych przez tsharka.</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">Transmission</span><span style="color: Gray;"> </span><span style="color: Blue;">Control</span><span style="color: Gray;"> </span><span style="color: Blue;">Protocol</span><span style="color: Gray;">, </span><span style="color: Blue;">Src</span><span style="color: Gray;"> </span><span style="color: Blue;">Port</span><span style="color: Gray;">: </span><span style="color: Maroon;">6348</span><span style="color: Gray;"> </span><span style="color: Olive;">(</span><span style="color: Maroon;">6348</span><span style="color: Olive;">)</span><span style="color: Gray;">, </span><span style="color: Blue;">Dst</span><span style="color: Gray;"> </span><span style="color: Blue;">Port</span><span style="color: Gray;">: </span><span style="color: Maroon;">3</span><span style="color: Blue;">Com</span><span style="color: Gray;">-</span><span style="color: Blue;">nsd</span><span style="color: Gray;"> </span><span style="color: Olive;">(</span><span style="color: Maroon;">1742</span><span style="color: Olive;">)</span><span style="color: Gray;">, </span><span style="color: Blue;">Seq</span><span style="color: Gray;">: </span><span style="color: Maroon;">96</span><span style="color: Gray;">, </span><span style="color: Blue;">Ack</span><span style="color: Gray;">: </span><span style="color: Maroon;">28</span><span style="color: Gray;">, </span><span style="color: Blue;">Len</span><span style="color: Gray;">: </span><span style="color: Maroon;">35</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">Source</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">port</span><span style="color: Gray;">: </span><span style="color: Maroon;">6348</span><span style="color: Gray;"> </span><span style="color: Olive;">(</span><span style="color: Maroon;">6348</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">Destination</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">port</span><span style="color: Gray;">: </span><span style="color: Maroon;">3</span><span style="color: Blue;">Com</span><span style="color: Gray;">-</span><span style="color: Blue;">nsd</span><span style="color: Gray;"> </span><span style="color: Olive;">(</span><span style="color: Maroon;">1742</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">Sequence</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">number</span><span style="color: Gray;">: </span><span style="color: Maroon;">96</span><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">(</span><span style="color: Blue;">relative</span><span style="color: Gray;"> </span><span style="color: Blue;">sequence</span><span style="color: Gray;"> </span><span style="color: Blue;">number</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">[</span><span style="color: Blue;">Next</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">sequence</span><span style="color: Gray;"> </span><span style="color: Blue;">number</span><span style="color: Gray;">: </span><span style="color: Maroon;">131</span><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">(</span><span style="color: Blue;">relative</span><span style="color: Gray;"> </span><span style="color: Blue;">sequence</span><span style="color: Gray;"> </span><span style="color: Blue;">number</span><span style="color: Olive;">)]</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">Acknowledgement</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">number</span><span style="color: Gray;">: </span><span style="color: Maroon;">28</span><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">(</span><span style="color: Blue;">relative</span><span style="color: Gray;"> </span><span style="color: Blue;">ack</span><span style="color: Gray;"> </span><span style="color: Blue;">number</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">Header</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">length</span><span style="color: Gray;">: </span><span style="color: Maroon;">20</span><span style="color: Gray;"> </span><span style="color: Blue;">bytes</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">Flags</span><span style="color: Gray;">: </span><span style="color: Maroon;">0</span><span style="color: Blue;">x18</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Blue;">PSH</span><span style="color: Gray;">, </span><span style="color: Blue;">ACK</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Maroon;">0.</span><span style="color: Gray;">.. .... = </span><span style="color: Blue;">Congestion</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">Window</span><span style="color: Gray;"> </span><span style="color: Blue;">Reduced</span><span style="color: Gray;"> </span><span style="color: Olive;">(</span><span style="color: Blue;">CWR</span><span style="color: Olive;">)</span><span style="color: Gray;">: </span><span style="color: Blue;">Not</span><span style="color: Gray;"> </span><span style="color: Blue;">set</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Maroon;">.0</span><span style="color: Gray;">.. .... = </span><span style="color: Blue;">ECN</span><span style="color: Gray;">-</span><span style="color: Blue;">Echo</span><span style="color: Gray;">: </span><span style="color: Blue;">Not</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">set</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; .</span><span style="color: Maroon;">.0</span><span style="color: Gray;">. .... = </span><span style="color: Blue;">Urgent</span><span style="color: Gray;">: </span><span style="color: Blue;">Not</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">set</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; ..</span><span style="color: Maroon;">.1</span><span style="color: Gray;"> .... = </span><span style="color: Blue;">Acknowledgment</span><span style="color: Gray;">: </span><span style="color: Blue;">Set</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; .... </span><span style="color: Maroon;">1.</span><span style="color: Gray;">.. = </span><span style="color: Blue;">Push</span><span style="color: Gray;">: </span><span style="color: Blue;">Set</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; .... </span><span style="color: Maroon;">.0</span><span style="color: Gray;">.. = </span><span style="color: Blue;">Reset</span><span style="color: Gray;">: </span><span style="color: Blue;">Not</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">set</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; .... .</span><span style="color: Maroon;">.0</span><span style="color: Gray;">. = </span><span style="color: Blue;">Syn</span><span style="color: Gray;">: </span><span style="color: Blue;">Not</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">set</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; .... ..</span><span style="color: Maroon;">.0</span><span style="color: Gray;"> = </span><span style="color: Blue;">Fin</span><span style="color: Gray;">: </span><span style="color: Blue;">Not</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">set</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">Window</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">size</span><span style="color: Gray;">: </span><span style="color: Maroon;">65250</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">Checksum</span><span style="color: Gray;">: </span><span style="color: Maroon;">0</span><span style="color: Blue;">x14eb</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">[</span><span style="color: Blue;">correct</span><span style="color: Olive;">]</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">[</span><span style="color: Blue;">Good</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">Checksum</span><span style="color: Gray;">: </span><span style="color: Green;">True</span><span style="color: Olive;">]</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">[</span><span style="color: Blue;">Bad</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">Checksum</span><span style="color: Gray;">: </span><span style="color: Green;">False</span><span style="color: Olive;">]</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">[</span><span style="color: Blue;">SEQ</span><span style="color: Gray;">/</span><span style="color: Blue;">ACK</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">analysis</span><span style="color: Olive;">]</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">[</span><span style="color: Blue;">TCP</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">Analysis</span><span style="color: Gray;"> </span><span style="color: Blue;">Flags</span><span style="color: Olive;">]</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">[</span><span style="color: Blue;">This</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">frame</span><span style="color: Gray;"> </span><span style="color: Green;">is</span><span style="color: Gray;"> </span><span style="color: Blue;">a</span><span style="color: Gray;"> </span><span style="color: Olive;">(</span><span style="color: Blue;">suspected</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Blue;">out</span><span style="color: Gray;">-</span><span style="color: Blue;">of</span><span style="color: Gray;">-</span><span style="color: Blue;">order</span><span style="color: Gray;"> </span><span style="color: Blue;">segment</span><span style="color: Olive;">]</span></li>
<li><span style="color: Blue;">Data</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Maroon;">35</span><span style="color: Gray;"> </span><span style="color: Blue;">bytes</span><span style="color: Olive;">)</span></li></ol></div>
<pre class="code">
<strong>radek@:~/#</strong> ./extract.py
extract.py &lt;dumped_file&gt; &lt;protocol&gt; &lt;out_file&gt;
</pre>
<p>Analogicznie do powyższego schematu na wejściu do skryptu podajemy nazwę pliku ze zrzuconymi pakietami, protokół który nas interesuje oraz plik wyjściowy.</p>
<p>Protokołem może być dla przykładu <em>gadugadu</em> lub też numer portu. Przykładowo:</p>
<pre class="code">
<strong>radek@:~/#</strong> ./extract.py dumped.dmp gadugadu out.dmp
</pre>
<p>Skrypt do pobrania poniżej.</p>
<p class="download">
<a href="http://blog.karpowicz.net/wp-content/uploads/2008/03/extract.py">extract.py</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.karpowicz.net/tshark-zrzucone-pakiety-danych/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Profilowanie aplikacji PHP - Xdebug</title>
		<link>http://blog.karpowicz.net/profilowanie-aplikacji-php-xdebug/</link>
		<comments>http://blog.karpowicz.net/profilowanie-aplikacji-php-xdebug/#comments</comments>
		<pubDate>Fri, 08 Feb 2008 19:13:22 +0000</pubDate>
		<dc:creator>Radek</dc:creator>
		
		<category><![CDATA[php 5]]></category>

		<category><![CDATA[optymalizacja]]></category>

		<category><![CDATA[php]]></category>

		<category><![CDATA[profilowanie]]></category>

		<category><![CDATA[xdebug]]></category>

		<guid isPermaLink="false">http://blog.karpowicz.net/profilowanie-aplikacji-php-xdebug/</guid>
		<description><![CDATA[W trakcie procesu projektowania aplikacji nie jesteśmy w stanie dokładnie wyliczyć oraz przewidzieć czasu wykonywania się poszczególnych jej elementów. Możliwe jest to dopiero podczas etapu wdrażania i testowania systemu przy pomocy narzędzi zintegorwanych z platformą (CI, CakePHP etc.) na której rozbudowujemy projekt o ile z takowej korzystamy, czy też dzięki wykorzystaniu narzędzi zewnętrznych.

CodeIgniter posiada wbudowany [...]]]></description>
			<content:encoded><![CDATA[<p class="akap">W trakcie procesu projektowania aplikacji nie jesteśmy w stanie dokładnie wyliczyć oraz przewidzieć czasu wykonywania się poszczególnych jej elementów. Możliwe jest to dopiero podczas etapu wdrażania i testowania systemu przy pomocy narzędzi zintegorwanych z platformą (CI, CakePHP etc.) na której rozbudowujemy projekt o ile z takowej korzystamy, czy też dzięki wykorzystaniu narzędzi zewnętrznych.</p>
<p><span id="more-15"></span></p>
<p class="info">CodeIgniter posiada wbudowany profiler oraz benchmark, dzięki któremu możemy zmierzyć czas wykonywania się danego kontrolera, czy też poszczególnych bloków kodu. <a href="http://codeigniter.com/user_guide/general/profiling.html" rel="nofollow">http://codeigniter.com/user_guide/general/profiling.html</a></p>
<p>Miłośników systemu Windows zapewne uszczęśliwi fakt dostępności łatwego i wygodnego IDE dla PHP, które posiada wbudowany profiler, mowa tutaj o <a href="http://www.nusphere.com/products/php_profiler.htm">PhpED</a> od <em>NuSphere</em>. Wersja podstawowa kosztuje 119$ i oczywiście pozbawiona jest <em>Advanced PHP profiler</em>, natomiast wersja profesjonalna z udogodnieniami, których brak w wersji podstawowej warta jest 299$ (<a href="http://www.nusphere.com/products/phped_verscomp.htm" rel="nofollow">porówanie wersji</a>).<br />
Wydatek nie duży w przypadku, gdy zakupujemy program do firmy, natomiast zbyt wysoki dla przeciętnego Kowalskiego, który dojeżdża do pracy rowerem. Również zwolennik Open Source nie wyda swoich ciężko zarobionych pieniędzy na <em>Software</em>, nie ze względu na jego wysoki koszt ale na sam fakt, że w świecie wolnego oprogramowania za programy po prostu się nie płaci.</p>
<h4>Instalacja Xdebug</h4>
<p class="akap">Wykorzystamy do tego celu <a href="http://xdebug.org/" rel="nofollow">Xdebug</a>, narzędzie do debugowania i profilowania aplikacji stworzonych w <abbr title="Hypertext Preprocessor" lang="en">PHP</abbr>, które występuje w postaci modułu dla tegoż właśnie języka programowania. Instalacji rozszerzenia można dokonać na kilka różnych sposobów, wszystkie dokładnie opisane zostały w dokumentacji projektu. Osobiście preferuję instalację ze źródeł, najnowsze można pobrać poprzez <abbr title="Concurrent Versions System" lang="en">CVS</abbr></p>
<pre>
<strong>radek</strong>@:~ cvs -d :pserver:srmread@cvs.xdebug.org:/repository login
CVS password: srmread
<strong>radek</strong>@:~ cvs -d :pserver:srmread@cvs.xdebug.org:/repository co xdebug
<strong>radek</strong>@:~ cd xdebug
<strong>radek</strong>@:~ phpize &#038;&#038; ./configure &#038;&#038; make clean &#038;&#038; make
<strong>radek</strong>@:~ cp modules/xdebug.so /folder/dla/modulu/</pre>
<p>Gdy skopiujemy już gotowy moduł do wybranego folderu możemy przystąpić do konfiguracji. Domyślnie plik konfiguracyjny PHP pod Apache2 znajduje się w <em>/etc/php5/apache2/php.ini</em> dodajemy do niego następujące wpisy:</p>
<pre>
zend_extension=/folder/dla/modulu/xdebug.so

; General
xdebug.default_enable=on
xdebug.extended_info=1

; Profiling
xdebug.profiler_enable=1
xdebug.profiler_output_dir=/tmp/xdebug_profiler
xdebug.profiler_output_name=cachegrind.out.%p
</pre>
<p>Wyniki profilowania w postaci plików wyjściowych będą zapisywane w folderze <em>/tmp/xdebug_profiler/</em> Upewnijmy się, czy taki folder aby na pewno istnieje i posiada prawa do zapisu (chmod 777). To tyle z procesu instalacji, możemy teraz zrestartować demona Apache i sprawdzić czy profilowanie działa.</p>
<p>Możemy tego dokonać poprzez wyświetlenie dowolnego pliku php na naszym lokalnym serwerze i sprawdzeniu czy analiza z uruchomienia została zapisana w <em>/tmp/xdebug_profiler</em>.</p>
<pre>
<strong>radek</strong>@:/ ls /tmp/xdebug_profiler/
-rw-r&#8211;r&#8211;  1 www-data www-data 1,8K 2008-02-03 14:24 cachegrind.out.7144
</pre>
<h4>Wyniki Profilowania</h4>
<p class="akap">Dzięki Xdebug jesteśmy w stanie wyłapać błędy w naszej aplikacji w postaci niezoptymalizowanego kodu, który jest przyczyną spadku wydajności. Obserwując wygenerowane wyniki w <a href="http://kcachegrind.sourceforge.net/" rel="nofollow">KCachegrind</a> lub <a href="http://sourceforge.net/projects/wincachegrind" rel="nofollow">WinCacheGrind</a> możemy w prosty sposób zlokalizować te warstwy aplikacji, które wykonują się najdłużej czy też te, które najczęściej były wywoływane. Mamy także możliwość poruszania się po wygenerowanym grafie (KCachegrind), który przedstawia strukturę odwołań.</p>
<p class="photo"><img src='http://blog.karpowicz.net/wp-content/uploads/2008/02/zrzut.png' alt='KCachegrind' /><br />
KCachegrind</p>
<p class="photo"><img src='http://blog.karpowicz.net/wp-content/uploads/2008/02/zrzut1.png' alt='WinCacheGrind' /><br />
WinCacheGrind</p>
<p>Z powyższego zestawienia wynika, że trzema najdłużej wykonującymi się metodami w projekcie są kolejno:</p>
<ol>
<li>konstruktor klasy <em>Welcome</em> - 1,7ms</li>
<li>konstruktor klasy <em>Controller</em> - 1,7ms</li>
<li>metoda <em>_ci_initialize</em> klasy <em>Controller</em> - 1,7ms</li>
</ol>
<p>Tuż za nimi plasuje się z numerem czwartym metoda <em>_run_hook</em> z klasy <em>CI_hooks</em> z czasem 1,4ms.</p>
<p class="akap">Zlokalizowanie miejsca występowania anomalii zapewnia nam możliwość jej zlikwidowania oraz przywrócenia aplikacji właściwego stanu wydajności. Należy przy tym pamiętać o zagnieżdżonych odwołaniach do zewnętrznych modułów czy też implementacjach np. zapytań sql, przy których może okazać się konieczna ich optymalizacja aby uzyskać interesujące nas efekty optymalizacji. Profilowanie aplikacji jest rzeczą bardzo ważną, zależy od tego późniejsze funkcjonowanie naszego systemu, który powinien być niezawodny i przede wszystkim szybki.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.karpowicz.net/profilowanie-aplikacji-php-xdebug/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Introspekcja w PHP 5 (ang. Reflection)</title>
		<link>http://blog.karpowicz.net/introspekcja-w-php-5-ang-reflection/</link>
		<comments>http://blog.karpowicz.net/introspekcja-w-php-5-ang-reflection/#comments</comments>
		<pubDate>Wed, 23 Jan 2008 14:27:00 +0000</pubDate>
		<dc:creator>Radek</dc:creator>
		
		<category><![CDATA[php 5]]></category>

		<category><![CDATA[code]]></category>

		<category><![CDATA[php]]></category>

		<category><![CDATA[reflection]]></category>

		<guid isPermaLink="false">http://blog.karpowicz.net/index.php/introspekcja-w-php-5-ang-reflection/</guid>
		<description><![CDATA[PHP wraz z wersją oznaczoną numerem 5 oddało nam do dyspozycji zestaw bardzo ciekawy udogodnień, ułatwiających rozwiązywanie nietypowych problemów. Jedno z nich, które w dalszej części opiszę jest związane z inżynierią wsteczną (ang. reverse engineering).

Mowa tutaj o Introspekcji (ang. Reflection), a właściwie to interfejsie funkcji API pozwalający nam na pobieranie kompletnych informacji odnośnie:

klas (ang. classes)
interfejsów [...]]]></description>
			<content:encoded><![CDATA[<p class="akap">PHP wraz z wersją oznaczoną numerem 5 oddało nam do dyspozycji zestaw bardzo ciekawy udogodnień, ułatwiających rozwiązywanie nietypowych problemów. Jedno z nich, które w dalszej części opiszę jest związane z inżynierią wsteczną (ang. reverse engineering).</p>
<p><span id="more-13"></span><br />
Mowa tutaj o <em>Introspekcji</em> (ang. <a href="http://php.net/manual/en/language.oop5.reflection.php" title="PHP Manual - Reflection" rel="nofollow">Reflection</a>), a właściwie to interfejsie funkcji <abbr title="Application Programming Interface" lang="en">API</abbr> pozwalający nam na pobieranie kompletnych informacji odnośnie:</p>
<ul>
<li>klas (ang. classes)</li>
<li>interfejsów (ang. interfaces)</li>
<li>metod (ang. methods)</li>
</ul>
<p>To nie wszystko, automatycznie otrzymujemy także dostęp do dokumentacji tychże klas/funkcji/interfejsów (ang. doc comments). Poniżej podaję wybrane metody obiektów (nie wszystkie), które posłużą w dalszej pracy.</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">class</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">ReflectionClass</span><span style="color: Gray;"> </span><span style="color: Green;">implements</span><span style="color: Gray;"> </span><span style="color: Blue;">Reflector</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">public</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">string</span><span style="color: Gray;"> </span><span style="color: Blue;">getDocComment</span><span style="color: Olive;">()</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">public</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">ReflectionMethod</span><span style="color: Gray;"> </span><span style="color: Blue;">getMethod</span><span style="color: Olive;">(</span><span style="color: Blue;">string</span><span style="color: Gray;"> </span><span style="color: Blue;">name</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">public</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">ReflectionMethod</span><span style="color: Olive;">[]</span><span style="color: Gray;"> </span><span style="color: Blue;">getMethods</span><span style="color: Olive;">()</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">public</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">ReflectionClass</span><span style="color: Gray;"> </span><span style="color: Blue;">getParentClass</span><span style="color: Olive;">()</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">public</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">bool</span><span style="color: Gray;"> </span><span style="color: Blue;">isSubclassOf</span><span style="color: Olive;">(</span><span style="color: Blue;">ReflectionClass</span><span style="color: Gray;"> </span><span style="color: Green;">class</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">public</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">bool</span><span style="color: Gray;"> </span><span style="color: Blue;">implementsInterface</span><span style="color: Olive;">(</span><span style="color: Blue;">string</span><span style="color: Gray;"> </span><span style="color: Blue;">name</span><span style="color: Olive;">)</span></li>
<li><span style="color: Olive;">}</span></li>
</ol></div>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">class</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">ReflectionMethod</span><span style="color: Gray;"> </span><span style="color: Green;">extends</span><span style="color: Gray;"> </span><span style="color: Blue;">ReflectionFunction</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">public</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">bool</span><span style="color: Gray;"> </span><span style="color: Blue;">isPublic</span><span style="color: Olive;">()</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">public</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">bool</span><span style="color: Gray;"> </span><span style="color: Blue;">isPrivate</span><span style="color: Olive;">()</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">public</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">bool</span><span style="color: Gray;"> </span><span style="color: Blue;">isProtected</span><span style="color: Olive;">()</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">public</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">string</span><span style="color: Gray;"> </span><span style="color: Blue;">getName</span><span style="color: Olive;">()</span></li>
<li><span style="color: Olive;">}</span></li>

<li><span style="color: Gray;">?&gt;</span></li></ol></div>
<p>Przepuśćmy, że istnieje taki scenariusz:</p>
<p>Zbudowaliśmy system, działający pod obsługą PHP 5, naszym celem jest poszerzenie jego funkcjonalności o interfejs, którym pozwoli nam na dołączanie zewnętrznych rozszerzeń naszej aplikacji (ang. Plugins). Wtyczki w tym wypadku to pliki php zaprojektowane w odpowiedni sposób, tak aby implementowały odpowiednie metody i posiadały sprecyzowane wartości. Przeanalizujmy po kolei kroki, które musimy wykonać:</p>
<ol>
<li>wczytanie plików *.php z wybranej lokalizacji tj. folderu z wtyczkami</li>
<li>iteracja na każdym pliku</li>
<li>weryfikacja pliku jako w pełni funkcjonalnego rozszerzenia</li>
</ol>
<ul class="level2">
<li>istnienie klasy o nazwie równej nazwie pliku (bez rozszerzenia)</li>
<li>klasa dziedziczy po obiekcie <em>Plugins</em></li>
<li>zaimplementowane są następujące metody: <em>load(), unload(), display()</em></li>
<li>powyższe metody nie są ani chronione ani prywatne - muszą być publiczne</li>
<li>w dokumentacji klasy zawarta jest informacja o autorze oraz wersji</li>
</ul>
<p>Jeżeli powyższe kroki zostaną wykonane a warunki spełnione oraz plugin przejdzie pomyślnie proces weryfikacji, możemy załadować go do systemu. Wczytywanie plików z lokalizacji oraz iteracji po każdym z nich nie będę opisywał ze względu na łatwość implementacji oraz dostępność podobnych rozwiązań, podam jedynie przykładowy kod:</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #00008b;">$dir</span><span style="color: Gray;"> = </span><span style="color: #8b0000;">'</span><span style="color: Red;">plugins/</span><span style="color: #8b0000;">'</span><span style="color: Gray;">;</span></li>
<li><span style="color: #00008b;">$iterator</span><span style="color: Gray;"> = </span><span style="color: Green;">new</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">RecursiveIteratorIterator</span><span style="color: Olive;">(</span><span style="color: Green;">new</span><span style="color: Gray;"> </span><span style="color: Blue;">RecursiveDirectoryIterator</span><span style="color: Olive;">(</span><span style="color: #00008b;">$dir</span><span style="color: Olive;">)</span><span style="color: Gray;">,</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">RecursiveIteratorIterator</span><span style="color: Gray;">::</span><span style="color: Blue;">SELF_FIRST</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; </span></li>
<li><span style="color: Green;">foreach</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: #00008b;">$iterator</span><span style="color: Gray;"> </span><span style="color: Green;">as</span><span style="color: Gray;"> </span><span style="color: #00008b;">$file</span><span style="color: Olive;">)</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">echo</span><span style="color: Gray;">&nbsp;</span><span style="color: #00008b;">$file</span><span style="color: Gray;">-&gt;</span><span style="color: Blue;">getFilename</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li>
</ol></div>
<p>Blok kodu umieszczony w <em>foreach</em> będzie sercem naszej implementacji, to w nim będą następować operacje na obiektach zaimplementowanych przez wtyczki.</p>
<h4>Reverse Engineering</h4>
<p class="akap">Wykorzystamy do tego celu wspomniany wcześniej obiekt <em>ReflectionClass</em> oraz <em>ReflectionMethod</em>, fragment kodu, który sprawdza czy podany plik spełnia wszystkie wcześniej wymienione warunki aby być poprawnym rozszerzeniem.</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">include</span><span style="color: Olive;">(</span><span style="color: #00008b;">$file</span><span style="color: Gray;">-&gt;</span><span style="color: Blue;">getPathname</span><span style="color: Olive;">())</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;"> * Nazwa pliku bez rozszerzenia jako nazwa klasy</span></li>
<li><span style="color: #ffa500;"> */</span></li>
<li><span style="color: #00008b;">$class</span><span style="color: Gray;"> = </span><span style="color: Blue;">substr</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: #00008b;">$file</span><span style="color: Gray;">-&gt;</span><span style="color: Blue;">getFilename</span><span style="color: Olive;">()</span><span style="color: Gray;">, -</span><span style="color: Maroon;">4</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;"> * Tablica z wymaganymi metodami</span></li>
<li><span style="color: #ffa500;"> */</span></li>
<li><span style="color: #00008b;">$aMethods</span><span style="color: Gray;"> = </span><span style="color: Green;">array</span><span style="color: Olive;">(</span><span style="color: #8b0000;">'</span><span style="color: Red;">load</span><span style="color: #8b0000;">'</span><span style="color: Gray;">, </span><span style="color: #8b0000;">'</span><span style="color: Red;">unload</span><span style="color: #8b0000;">'</span><span style="color: Gray;">, </span><span style="color: #8b0000;">'</span><span style="color: Red;">display</span><span style="color: #8b0000;">'</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;"> * Zmienna określająca czy klasa jest poprawną wtyczką, jeżeli</span></li>
<li><span style="color: #ffa500;"> * tak to po przejściu poniższego bloku instrukcji powinna ona</span></li>
<li><span style="color: #ffa500;"> * przybrać wartość TRUE.</span></li>
<li><span style="color: #ffa500;"> */</span></li>
<li><span style="color: #00008b;">$is_valid</span><span style="color: Gray;"> = </span><span style="color: Green;">false</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">try</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: #00008b;">$refl</span><span style="color: Gray;"> = </span><span style="color: Green;">new</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">ReflectionClass</span><span style="color: Olive;">(</span><span style="color: #00008b;">$class</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; * Nie wystąpił wyjątek a więc oznacza to, że w pliku istnieje klasa</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; * o poprawnej nazwie. Warunek nr 1 spełniony.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; */</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: #00008b;">$class_parent</span><span style="color: Gray;"> = </span><span style="color: #00008b;">$refl</span><span style="color: Gray;">-&gt;</span><span style="color: Blue;">getParentClass</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; * Sprawdzamy czy załadowana klasa dziedziczy po klasie 'Plugins'.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; * Jeżeli tak, warunek nr 2 spełniony.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; */</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: #00008b;">$class_parent</span><span style="color: Gray;">-&gt;</span><span style="color: Blue;">getName</span><span style="color: Olive;">()</span><span style="color: Gray;"> == </span><span style="color: #8b0000;">'</span><span style="color: Red;">Plugins</span><span style="color: #8b0000;">'</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #00008b;">$class_methods</span><span style="color: Gray;"> = </span><span style="color: #00008b;">$refl</span><span style="color: Gray;">-&gt;</span><span style="color: Blue;">getMethods</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * Jeżeli licznik nie osiągnie wartości 3 - tylu funkcji oczekujemy,</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * oznacza to, że klasa nie posiada podstawowych i wymaganych</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * metod - load(), unload(), display() wymaganych aby spełnić</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * warunek nr 3.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; */</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #00008b;">$counter</span><span style="color: Gray;"> = </span><span style="color: Maroon;">0</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">foreach</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: #00008b;">$class_methods</span><span style="color: Gray;"> </span><span style="color: Green;">as</span><span style="color: Gray;"> </span><span style="color: #00008b;">$refobj</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #00008b;">$method</span><span style="color: Gray;"> = </span><span style="color: Green;">new</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">ReflectionMethod</span><span style="color: Olive;">(</span><span style="color: #00008b;">$class</span><span style="color: Gray;">, </span><span style="color: #00008b;">$refobj</span><span style="color: Gray;">-&gt;</span><span style="color: Blue;">name</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * Pomijamy metody będące konstruktorami oraz destruktor.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; */</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: #00008b;">$class</span><span style="color: Gray;"> == </span><span style="color: #00008b;">$refobj</span><span style="color: Gray;">-&gt;</span><span style="color: Blue;">name</span><span style="color: Gray;"> || </span><span style="color: #00008b;">$class</span><span style="color: Gray;"> == </span><span style="color: #8b0000;">'</span><span style="color: Red;">__construct</span><span style="color: #8b0000;">'</span><span style="color: Gray;"> ||</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; </span><span style="color: #00008b;">$class</span><span style="color: Gray;"> == </span><span style="color: #8b0000;">'</span><span style="color: Red;">__destruct</span><span style="color: #8b0000;">'</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">continue</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * Nie interesują nas także metody prywatne, czy też chronione</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * do których nie możemy się odwołać spoza klasy. Jedynie</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * metody publiczne.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; */</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Gray;"> !</span><span style="color: #00008b;">$method</span><span style="color: Gray;">-&gt;</span><span style="color: Blue;">isPublic</span><span style="color: Olive;">()</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">continue</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * Sprawdzamy czy nazwa funkcji znajduje się w tablicy</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * z wymaganymi metodami. Jeżeli tak, zwiększamy licznik.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; */</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: Blue;">in_array</span><span style="color: Olive;">(</span><span style="color: #00008b;">$refobj</span><span style="color: Gray;">-&gt;</span><span style="color: Blue;">name</span><span style="color: Gray;">, </span><span style="color: #00008b;">$aMethods</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #00008b;">$counter</span><span style="color: Gray;">++;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: #00008b;">$counter</span><span style="color: Gray;"> == </span><span style="color: Maroon;">3</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * Teraz pozostało jedynie sprawdzenie czy dokumentacja dla</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * klasy zawiera wymagane elementy - autora oraz wersję.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; */</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #00008b;">$doc</span><span style="color: Gray;"> = </span><span style="color: #00008b;">$refl</span><span style="color: Gray;">-&gt;</span><span style="color: Blue;">getDocComment</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * W tym momencie skończyła się praca na obiektach, trzeba</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * cofnąć się do źródeł cywilizacji i użyć wyrażeń regularnych.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; */</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #00008b;">$pattern</span><span style="color: Gray;"> = </span><span style="color: #8b0000;">'</span><span style="color: Red;">/(?:@author|@version)(?:[\t|\s]+)([^*|@]+)?/im</span><span style="color: #8b0000;">'</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">preg_match_all</span><span style="color: Olive;">(</span><span style="color: #00008b;">$pattern</span><span style="color: Gray;">, </span><span style="color: #00008b;">$doc</span><span style="color: Gray;">, </span><span style="color: #00008b;">$result</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * Sprawdzamy czy w ogóle cokolwiek zostało dopasowane do</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * wzorca - autor i wersja, jeżeli nie opis jest błędny.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; */</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: Blue;">count</span><span style="color: Olive;">(</span><span style="color: #00008b;">$result</span><span style="color: Olive;">)</span><span style="color: Gray;"> &gt; </span><span style="color: Maroon;">0</span><span style="color: Gray;"> &amp;&amp; </span><span style="color: Green;">isset</span><span style="color: Olive;">(</span><span style="color: #00008b;">$result</span><span style="color: Olive;">[</span><span style="color: Maroon;">0</span><span style="color: Olive;">][</span><span style="color: Maroon;">0</span><span style="color: Olive;">])</span><span style="color: Gray;"> &amp;&amp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; </span><span style="color: Green;">isset</span><span style="color: Olive;">(</span><span style="color: #00008b;">$result</span><span style="color: Olive;">[</span><span style="color: Maroon;">0</span><span style="color: Olive;">][</span><span style="color: Maroon;">1</span><span style="color: Olive;">]</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: Blue;">strtolower</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: Blue;">substr</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: #00008b;">$result</span><span style="color: Olive;">[</span><span style="color: Maroon;">0</span><span style="color: Olive;">][</span><span style="color: Maroon;">0</span><span style="color: Olive;">]</span><span style="color: Gray;">, </span><span style="color: Maroon;">0</span><span style="color: Gray;">, </span><span style="color: Maroon;">7</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;"> ==</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; </span><span style="color: #8b0000;">'</span><span style="color: Red;">@author</span><span style="color: #8b0000;">'</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #00008b;">$doc_author</span><span style="color: Gray;"> = </span><span style="color: #00008b;">$result</span><span style="color: Olive;">[</span><span style="color: Maroon;">1</span><span style="color: Olive;">][</span><span style="color: Maroon;">0</span><span style="color: Olive;">]</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #00008b;">$doc_version</span><span style="color: Gray;"> = </span><span style="color: #00008b;">$result</span><span style="color: Olive;">[</span><span style="color: Maroon;">1</span><span style="color: Olive;">][</span><span style="color: Maroon;">1</span><span style="color: Olive;">]</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">else</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #00008b;">$doc_author</span><span style="color: Gray;"> = </span><span style="color: #00008b;">$result</span><span style="color: Olive;">[</span><span style="color: Maroon;">1</span><span style="color: Olive;">][</span><span style="color: Maroon;">1</span><span style="color: Olive;">]</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #00008b;">$doc_version</span><span style="color: Gray;"> = </span><span style="color: #00008b;">$result</span><span style="color: Olive;">[</span><span style="color: Maroon;">1</span><span style="color: Olive;">][</span><span style="color: Maroon;">0</span><span style="color: Olive;">]</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * Sprawdzamy czy autor oraz wersja nie są pustymi</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * polami.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; */</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: #00008b;">$doc_author</span><span style="color: Gray;"> &amp;&amp; </span><span style="color: #00008b;">$doc_version</span><span style="color: Gray;">&nbsp; </span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * Wszystko jest w jak najlepszym porządku.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * Zebrane dane są gotowe do użycia.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; */</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #00008b;">$is_valid</span><span style="color: Gray;"> = </span><span style="color: Green;">true</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">else</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * Informacje o autorze lub wersji okazały</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * się niepoprawne.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; */</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; } </span><span style="color: Green;">else</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * Klasa nie posiada 3 podstawowych metod, więc nie jest</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * prawidłowym rozszerzeniem.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; */</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; } </span><span style="color: Green;">else</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * Klasa mimo, iż jest poprawnie nazwana nie dziedziczy po klasie</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * 'Plugins'. Przechodzimy więc do kolejnej iteracji.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; */</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">continue</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">} </span><span style="color: Green;">catch</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Blue;">Exception</span><span style="color: Gray;"> </span><span style="color: #00008b;">$e</span><span style="color: Olive;">)</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp;&nbsp; * Plugin nie posiada poprawnie nazwanej klasy, więc przechodzimy</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp;&nbsp; * do kolejnej iteracji tj. kolejnego pliku. Możliwe jest także,</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp;&nbsp; * iż któraś z pozostałych instrukcji w bloku try{} spowodowała błąd.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp;&nbsp; */</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">continue</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: #00008b;">$is_valid</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * Plik jest poprawnym rozszerzeniem naszego interfejsu.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; *</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * $file-&gt;getPathName() - nazwa pliku, wraz ze ścieżką</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * $class - nazwa klasy</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * $doc&nbsp;&nbsp; - opis klasy (całość komentarza, nie obrobiona)</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * $doc_author&nbsp; - autor plugin-u</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * $doc_version - wersja plugin-u</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; */</span></li>
<li><span style="color: Olive;">}</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">else</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * Plik nie jest poprawny i nie może zostać wykorzystany</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; * jako plugin.</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; */</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">?&gt;</span></li></ol></div>
<p class="akap">Mam nadzieję, że powyższy praktyczny przykład rzucił więcej światła na problem związany z wykorzystaniem jednej z technologi oferowanych przez PHP 5. Kod był pisany od ręki mimo to mam nadzieję, że ustrzegłem się od jakichkolwiek uchybień i błędów.</p>
<p class="akap">Czy podczas czytania tego tekstu były rzeczy dla Ciebie nie zrozumiałe, zdające się być niepoprawne, masz jakiekolwiek zastrzeżenia? Zostaw informację w komentarzach lub skontaktuj się ze mną poprzez e-mail.</p>
<h4>Pozostałe metody (nie dotyczy użycia <em>Introspekcji</em>)</h4>
<p class="akap">Wykorzystanie <em>Reflection API</em> nie jest jedyną metodą na uzyskanie informacji z pliku odnośnie zawartych w nim klas, funkcji, metod danych klas czy też zmiennych. Można tego dokonać również przy użyciu standardowych metod, mam na myśli tutaj kwestie możliwe do wykonania także przy użyciu PHP 4.</p>
<p>Nie jestem tego w stanie lepiej przedstawić niż podając konkrety.</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Gray;">@</span><span style="color: Green;">include</span><span style="color: Olive;">(</span><span style="color: #00008b;">$file</span><span style="color: Gray;">-&gt;</span><span style="color: Blue;">getPathname</span><span style="color: Olive;">())</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: #00008b;">$class</span><span style="color: Gray;">&nbsp;&nbsp; = </span><span style="color: #00008b;">$file</span><span style="color: Gray;">-&gt;</span><span style="color: Blue;">getFilename</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: #00008b;">$oClass</span><span style="color: Gray;"> = </span><span style="color: Green;">new</span><span style="color: Gray;">&nbsp;</span><span style="color: #00008b;">$class</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;"> * Sprawdzenie czy $class jest podklasą danej klasy.</span></li>
<li><span style="color: #ffa500;"> * W ten sposób można sprawdzić, czy klasa rozszerza</span></li>
<li><span style="color: #ffa500;"> * obiekt 'Plugins'.</span></li>
<li><span style="color: #ffa500;"> */</span></li>
<li><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: Blue;">is_subclass_of</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: #00008b;">$oClass</span><span style="color: Gray;">, </span><span style="color: #8b0000;">'</span><span style="color: Red;">Plugins</span><span style="color: #8b0000;">'</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span><span style="color: Gray;"> </span><span style="color: #ffa500;">/* extends */</span><span style="color: Gray;"> </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;"> * Metody klasy pobieramy za pomocą funkcji.</span></li>
<li><span style="color: #ffa500;"> */</span></li>
<li><span style="color: Blue;">get_class_methods</span><span style="color: Olive;">(</span><span style="color: #00008b;">$class</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
</ol></div>
<p>No dobrze, wszystko zdaję się działać? Mamy już nazwę klasy, wiemy czy dziedziczy ona po klasie &#8216;Plugins&#8217;, jesteśmy również w posiadaniu tablicy z metodami danego obiektu. Pozostało nam sprawdzenie czy posiada zadane 3 metody i czy są one publiczne&#8230; i tutaj zaczynają się schody. Trzeba to zrobić trochę na około używając wyrażeń regularnych.<br />
Zrobiłem to według kilku punktów:</p>
<ol>
<li>Usuwam z pliku wszystkie komentarze, aby wyeliminować ewentualne funkcje, klasy, które są ukryte w komentarzach a mogłyby zostać błędnie rozpoznane i załadowane w dalszej części.</li>
<li>Następnie gdy już usunąłem 3 typy komentarzy (// # /**/) mogę dopasować funkcje do wzorca</li>
<li>Sprawdzam również czy po nazwie obiektu następuje słowo &#8220;extends&#8221; i pobieram nazwę klasy, po której dziedziczy</li>
</ol>
<p>Poniżej niezbędna lista wzorców:</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;"> * Komentarze</span></li>
<li><span style="color: #ffa500;"> */</span></li>
<li><span style="color: #00008b;">$content</span><span style="color: Gray;"> = </span><span style="color: Blue;">preg_replace</span><span style="color: Olive;">(</span><span style="color: #8b0000;">'</span><span style="color: Red;">@/\*.*?\*/@ims</span><span style="color: #8b0000;">'</span><span style="color: Gray;">, </span><span style="color: #8b0000;">''</span><span style="color: Gray;">, </span><span style="color: #00008b;">$content</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">/* comment */</span></li>
<li><span style="color: #00008b;">$content</span><span style="color: Gray;"> = </span><span style="color: Blue;">preg_replace</span><span style="color: Olive;">(</span><span style="color: #8b0000;">'</span><span style="color: Red;">@^[\s|\t]+#.*?$@ims</span><span style="color: #8b0000;">'</span><span style="color: Gray;">, </span><span style="color: #8b0000;">''</span><span style="color: Gray;">, </span><span style="color: #00008b;">$content</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;"># comment</span></li>
<li><span style="color: #00008b;">$content</span><span style="color: Gray;"> = </span><span style="color: Blue;">preg_replace</span><span style="color: Olive;">(</span><span style="color: #8b0000;">'</span><span style="color: Red;">@^[\s|\t]+//.*?$@ims</span><span style="color: #8b0000;">'</span><span style="color: Gray;">, </span><span style="color: #8b0000;">''</span><span style="color: Gray;">, </span><span style="color: #00008b;">$content</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">// comment</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;"> * Pobieramy całą zawartość klasy - do znacznika 'class' (druga klasa) lub</span></li>
<li><span style="color: #ffa500;"> * końca pliku '?&gt;'.</span></li>
<li><span style="color: #ffa500;"> */</span></li>
<li><span style="color: Blue;">preg_match_all</span><span style="color: Olive;">(</span></li>
<li><span style="color: #8b0000;">'</span><span style="color: Red;">@^[\s|\t]+class[\s|\t]+([A-Z0-9_]+)([^{]+)?.*?(?:class|\?\&gt;)@ism</span><span style="color: #8b0000;">'</span></li>
<li><span style="color: Gray;">, </span><span style="color: #00008b;">$content</span><span style="color: Gray;">, </span><span style="color: #00008b;">$aresult</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;"> * Sprawdzamy czy klasa dziedziczy po 'plugins'.</span></li>
<li><span style="color: #ffa500;"> */</span></li>
<li><span style="color: Blue;">preg_match</span><span style="color: Olive;">(</span><span style="color: #8b0000;">'</span><span style="color: Red;">@extends[\s|\t]+plugins@ism</span><span style="color: #8b0000;">'</span><span style="color: Gray;">, </span><span style="color: #00008b;">$aresult</span><span style="color: Olive;">[</span><span style="color: Maroon;">2</span><span style="color: Olive;">][</span><span style="color: Maroon;">0</span><span style="color: Olive;">]</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;"> * Pobieramy nazwy metod - jedynie te publiczne lub nieokreślone (PHP 4)</span></li>
<li><span style="color: #ffa500;"> */</span></li>
<li><span style="color: Blue;">preg_match_all</span><span style="color: Olive;">(</span></li>
<li><span style="color: #8b0000;">'</span><span style="color: Red;">@^[\s|\t]+(?:function|public[\s\t]+function)[\s|\t]+([A-Z0-9_]+)@ims</span><span style="color: #8b0000;">'</span><span style="color: Gray;">,</span></li>
<li><span style="color: #00008b;">$aresult</span><span style="color: Olive;">[</span><span style="color: Maroon;">0</span><span style="color: Olive;">][</span><span style="color: Maroon;">0</span><span style="color: Olive;">]</span><span style="color: Gray;">, </span><span style="color: #00008b;">$amethods</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
</ol></div>
<p class="akap">Metoda nie wykorzystująca <em>Introspekcji</em> jest czasochłonna, przede wszystkim dlatego, iż dużo jest manipulacji z obrabianiem zawartości pliku. Problem mogą sprawić także niedociągnięcia we wzorcach wykorzystywanych jak widać na każdym kroku. Stanowczo polecam migrację z PHP 4 do 5. Projektując i tworząc aplikacje liczy się wydajność i łatwość rozbudowy, tak więc to od Ciebie zależy czy kod, który stworzyłeś będzie czytelny i łatwy w rozbudowie dla potencjalnych następców. Jeżeli zdecydowałeś się wykorzystać drugą metodę związaną z wyrażeniami regularnymi, radzę dodać komentarze do wzorców - odpowiednio opisane będą łatwe do zrozumienia nawet dla laika.</p>
<p class="info">Przedstawiony tekst nie wyczerpuje całego tematu związanego z Introspekcją, po więcej informacji odsyłam pod adres <a href="http://php.net/manual/en/language.oop5.reflection.php">http://php.net/manual/en/language.oop5.reflection.php</a> do manuala PHP.</p>
<p>Życzę przyjemnej i owocnej pracy.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.karpowicz.net/introspekcja-w-php-5-ang-reflection/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Dysk twardy w (nie)bezpiczeństwie</title>
		<link>http://blog.karpowicz.net/dysk-twardy-w-niebezpiczenstwie/</link>
		<comments>http://blog.karpowicz.net/dysk-twardy-w-niebezpiczenstwie/#comments</comments>
		<pubDate>Sun, 20 Jan 2008 20:22:08 +0000</pubDate>
		<dc:creator>Radek</dc:creator>
		
		<category><![CDATA[hardware]]></category>

		<category><![CDATA[opowiadanie]]></category>

		<guid isPermaLink="false">http://blog.karpowicz.net/index.php/dysk-twardy-w-niebezpiczenstwie/</guid>
		<description><![CDATA[Dysk twardy w (nie)bezpiczeństwie, czyli chaker atakuje - ukryj prolog

Przeglądałem jak co dzień działy RSS lokalnej gazety w poszukiwaniu ciekawych publikacji i natknąłem się na coś co zwróciło moją uwagę:
&#8220;Linux mordercą laptopów?&#8221;
Pod tematem wpisu ubranym w ironię kryła się złowieszcza prawda o systemie sygnowanym logiem morderczego pingwina, jego mrocznej przeszłości owianej mgłą tajemnicy, zamiarach wobec [...]]]></description>
			<content:encoded><![CDATA[<p class="prologhdr"><strong>Dysk twardy w (nie)bezpiczeństwie, czyli chaker atakuje</strong> - <a href="javascript:;" onclick="$('prolog_2').style.display='none';">ukryj prolog</a></p>
<div class="prologon" id="prolog_2">
<p class="akap">Przeglądałem jak co dzień działy <abbr title="Really Simple Syndication" lang="en">RSS</abbr> lokalnej gazety w poszukiwaniu ciekawych publikacji i natknąłem się na coś co zwróciło moją uwagę:</p>
<p><a HREF="http://bytowisko.pl/?p=1002" TARGET="_blank"><strong>&#8220;Linux mordercą laptopów?&#8221;</strong></a></p>
<p class="akap">Pod tematem wpisu ubranym w ironię kryła się złowieszcza prawda o systemie sygnowanym logiem morderczego pingwina, jego mrocznej przeszłości owianej mgłą tajemnicy, zamiarach wobec nadludzkiej rasy laptopów jako ich największego wroga&#8230;.<br />
Cokolwiek przeszło przez moją neuronową strukturę oplatającą mózgowie, nie była to myśl dotycząca tematu publikacji. Ów temat który mimo, iż miałem przed oczyma, poruszający się ruchem wahadłowym z lekko zachwianą amplitudą (zapewne przyczyną nierównomiernych odchyleń były drgania klawiszy mej maszyny do pisania) nie był źródłem wygenerowania tej myśli.<br />
Przyszła sama, nie wiadomo skąd, z pomieszczenia obok? kartki bezwładnie miotającej się na wietrze, która przed sekundą przykleiła się do mego okna aby zniknąć tak szybko jak się pojawiła? okno od zachodu&#8230; zaraz, zaraz&#8230; przecież dzisiaj nie ma wiatru&#8230; no tak - nie minęło ćwierć sekundy a ujrzałem przylegający do szyby drugi element, nie była to jednak kartka lecz rozradowana twarz d(o)ręczyciela poczty, a jakżeby inaczej w końcu dziś mamy niedziele wieczór&#8230;</p>
<p>- Nowego posta przyniesłem - <em>usłyszałem zza drzwi, głos typowego wieśniaka&#8230; </em><br />
- Dzienkujem - <em>odrzekłem z politowaniem</em></p>
<p>Ciekaw byłem niezmiernie zawartości koperty, trzasnąłem drzwiami tak błyskawicznie jak je otworzyłem przerywając mężczyźnie na rowerze w połowie zdania, usiadłem wygodnie w swym skórzanym fotelu, wyciągając nogi daleko przed siebie, otworzyłem kopertę i zamaszystym ruchem wyciągnąłem z niej całą zawartość, były to arkusze szarego papieru datowane na&#8230; cztery miesiące w tył, była to treść najnowszego wpisu z mojego bloga. Nie było by w tym nic dziwnego gdyby nie fakt, że ów wpis chroniony był hasłem nie do złamania (5 znaków, jedynie wielkie litery). Dało mi to do myślenia, otrzymałem list od chakera, który dysponował komputerem o niespotykanej dotąd mocy obliczeniowej, złamał on zabezpieczenia i przejął poufną treść z mojego bloga. Jako, że najprawdopodobniej krąży ona już w sieci za magicznym dotknięciem różdżki wujka Gógla, którego zapewne udział w owym incydencie był nie mniejszy, nie pozostało mi nic innego jak opublikowanie wpisu, mimo iż plany były zupełnie inne&#8230;</p>
<p class="error">&#8220;Tajne przez Poufne&#8221; czyli treść właściwa publikacji:</p>
</div>
<p>Wszystko zaczęło się od <a HREF="http://bytowisko.pl/?p=1002" TARGET="_blank">&#8220;Mordercy Laptopów&#8221;</a>, jak niespodziewana lawina pociągnął za sobą kolejne linki&#8230; wyszukiwane frazy&#8230; opinie ekspertów&#8230; Gdy już zebrałem wymagane dane, przystąpiłem do analizy.</p>
<p class="info">Możliwe jest iż przy niewłaściwych ustawieniach <em>Zaawansowanego Zarządzania Energią</em> dla dysku twardego, jest on w stanie zużyć się w czasie wielokrotnie krótszym, niżeli przy poprawnych ustawieniach.</p>
<p>Pobrałem pakiet potrzebny do zdiagnozowania problemu, właściwie to zrobiło to za mnie <abbr title="GUI for apt-get (Advanced Packaging Tool)" lang="en">Aptitude</abbr>.</p>
<pre><strong>root@~ /</strong> aptitude search smartmontools
p   smartmontools     - control and monitor storage systems using S.M.A.R.T.
<strong>root@~ /</strong> aptitude install smartmontools</pre>
<p>Narzędziem zawartym w wyżej pobranej i zainstalowanej paczce, potrzebnym do diagnostyki jest <em>smartctl</em>, korzystamy z niego w następujący sposób:</p>
<pre><strong>root@~ /</strong> smartctl -d ata -a /dev/sda | grep Load_Cycle_Count</pre>
<p><strong>ATA</strong> - typ naszego dysku może być również <abbr title="Small Computer Systems Interface" lang="en">SCSI</abbr>, SAT (skrót od <abbr title="Serial Advanced Technology Attachment" lang="en">SATA</abbr>)<br />
<strong>/dev/sda</strong> - lokalizacja naszego urządzenia</p>
<p>Wartość, której szukamy to <em>Load_Cycle_Count</em></p>
<p class="info">193 Load_Cycle_Count        0&#215;0032   099   099   000    Old_age   Always       -       <strong>17541</strong></p>
<p>Jak widać z powyższego wpisu wartość <em>Load_Cycle_Count</em> dla mojego dysku twardego wynosi 17541 - dużo? Raczej nie, biorąc pod uwagę fakt, że laptop na baterii pracuje sporadycznie no i przede wszystkim jest nowy, nabyłem go zaledwie 4 miesiące temu.<br />
Liczba cykli wzrasta u mnie wolno, tak więc nie przejmuję się tym problem, w końcu dysk nie ma nawet kiedy przełączyć się w tryb oszczędzania energii, więc nie ma czynnika, który mógłby powodować diametralny wzrost tej wartości.<br />
Jednakże ten problem jest poważny mimo, że na taki nie wygląda, przykładem może być wpis <a HREF="http://tumbleweed.org.za/2007/10/23/a-serious-warning-to-linux-laptop-users/" TARGET="_blank" rel="nofollow">Stefano Rivers&#8217;a</a> u którego to owa magiczna wartość sięgnęła rzędu <strong>160 000</strong> w zaledwie <strong>trzy miesiące</strong> - imponujące nieprawdaż?</p>
<p>Jeżeli poniższe symptomy występują u Ciebie powinieneś zacząć się martwić i przeciwdziałać temu problemowi zanim stanie się na tyle poważny, że jego likwidacja nie przyniesie żadnych korzyści, ze względu na spóźnioną reakcję.</p>
<p CLASS="info">Symptoms of this bug are:<br />
* frequent HD clicks &#8212; more than one per 3 minutes while idle, louder than the typical access sounds. Often more than twice per minute.<br />
* Rapidly Increasing Load_Cycle_Count as displayed in the final number in &#8220;sudo smartctl -a /dev/hda | grep Load_Cycle_Count&#8221; (where /dev/hda is replaced with your own hard disk device)<br />
* Early hard disk failure &#8212; some disks are cut down to less than a year of actual uptime.The problem seems to be caused by:<br />
* Hardware defaults to aggressive power management, causing heads to park.<br />
* Disk is touched often, causing heads to unpark.<br />
* Most laptop drives handle up to 600,000 such cycles.Reasonable Limits / Criteria for a fix:<br />
* There should be fewer than ~15 load cycles per hour, except during heavy usage while on battery.
</p>
<p>No i oczywiście tymczasowe obejście problemu:</p>
<pre>hdparm -B 254</pre>
<p><em>-B   set Advanced Power Management setting (1-255)</em></p>
<p>bug: <a HREF="https://bugs.launchpad.net/ubuntu/+source/acpi-support/+bug/59695" TARGET="_blank"> https://bugs.launchpad.net/ubuntu/+source/acpi-support/+bug/59695 </a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.karpowicz.net/dysk-twardy-w-niebezpiczenstwie/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Wine + FlashFXP 3.2.0</title>
		<link>http://blog.karpowicz.net/wine-flashfxp-320/</link>
		<comments>http://blog.karpowicz.net/wine-flashfxp-320/#comments</comments>
		<pubDate>Fri, 18 Jan 2008 00:34:48 +0000</pubDate>
		<dc:creator>Radek</dc:creator>
		
		<category><![CDATA[debian]]></category>

		<category><![CDATA[ftp]]></category>

		<category><![CDATA[opowiadanie]]></category>

		<category><![CDATA[wine]]></category>

		<guid isPermaLink="false">http://blog.karpowicz.net/wine-flashfxp-320/</guid>
		<description><![CDATA[Łajn i patrol stumilowego szlaku - ukryj prolog

Przemierzając bezkresną przestrzeń najmroczniejszej z krain, tak mroczną, iż jej nazwa nie jest w stanie oddać całego ogromu oraz potęgi zamieszkujących ją Websajtów, tej samej krainy, w której od lat toczy się wojna między Ortami i Graficzanami a dzieci w wieku 12 lat konstruują własne układy elektroniczne w [...]]]></description>
			<content:encoded><![CDATA[<p class="prologhdr"><strong>Łajn i patrol stumilowego szlaku</strong> - <a href="javascript:;" onclick="$('prolog_1').style.display='none';">ukryj prolog</a></p>
<div class="prologon" id="prolog_1">
<p class="akap">Przemierzając bezkresną przestrzeń najmroczniejszej z krain, tak mroczną, iż jej nazwa nie jest w stanie oddać całego ogromu oraz potęgi zamieszkujących ją <abbr title="Hybrydy ksiąg" lang="pl"><em>Websajtów</em></abbr>, tej samej krainy, w której od lat toczy się wojna między <em>Ortami</em> i <em>Graficzanami</em> a dzieci w wieku 12 lat konstruują własne układy elektroniczne w oparciu o najnowocześniejsze standardy zwane <em>ifrejmami</em>, wielokrotnie narażałem swoje życie.</p>
<p class="akap">Niebezpieczna wyprawa po krainie <em>Łebdwa</em>, zakończyła się niepowodzeniem. Nie odnalazłem żadnego godnego zastępcy dla mojego byłego współpracownika FlashFXP, jak się później okazało spiskującej przeciwko mnie i pracującego dla <abbr title="Majkrosoft Kompani" lang="en">M$</abbr>. Jedynym rozsądnym, aczkolwiek bardzo niebezpiecznym wyjściem jakie mi pozostało było przeprogramowanie Flash-a w taki sposób aby znów był lojalny wobec mojej nowej organizacji współpracującej ze światem Wolnego Oprogramowania, mowa tutaj o &#8220;Dejbian Indastri&#8221;. Sprawa była o tyle trudna, że musiałem odnaleźć osobę, która tego dokona&#8230;</p>
</p>
<p class="akap">Nazywał się Łajn, był profesorem zamieszkującym blok HQ bazy Wolnego Oprogramowania i jako jedyny ze znanych mi ożywicieli był niezależny od M$. Wielokrotnie słyszałem opinie potwierdzające jego zdolności w zakresie układów wszczepialnych, był jedynym, któremu udało się uciec z koloni M$. Przeprogramował umieszczony w płacie skroniowym nadajnik w taki sposób aby symulować jego poprawne działanie a nie odczuwać wpływu fali przez niego emitowanych.</p>
<p>Odnalezienie Łajna było wyzwaniem trudnym, jak nie co najmniej graniczącym z cudem, ukrywał się ze względu na swoją przeszłość, która pragnęła jego śmierci. Posłałem po niego swojego najlepszego tropiciela Pinga, misja była prosta. W przypadku odnalezienia profesora, wraca. Gdyby jednak z powodu nieoczekiwanego zwrotu akcji, któremuś z nich cokolwiek się stało wiedziałbym o tym. Ping ma przy sobie nadajnik, który emituje fale o długości 64m w odstępach 0,3ms więc gdy opóźnienie wzrośnie, co w krainie <em>Telepsy</em> jest czymś graniczącym z cudem, bądź nadajnik przestanie odpowiadać na wysyłane sygnały będę wiedział, że misja zakończyła się niepowodzeniem.<br />
Zająłem miejsce przed odbiornikiem, włączyłem. Nasłuchiwałem rytmicznie wybijanego dźwięku z drewnianego pudła przykrytego kratą, imitującego głośnik, przypominało to stukot kropel wody uderzających w blaszany element, dźwięk był pusty. Im dłużej się wsłuchiwałem, tym bardziej moja podświadomość płatała mi figle, nieprzerwany stukot wydobywający się z urządzenia składał się w słowa, Tejli&#8230; Łejli&#8230; - słyszałem nieustannie w głowie. Byłem rozbity, popadłem w dziwny stan euforii, podśmiewałem się delikatnie, nie byłem w stanie zapanować nad natłokiem myśli wdzierających się do mojej głowy&#8230;</p>
<p>- Zaraz&#8230; Chwila&#8230; Coś tu nie gra&#8230;</p>
<p>Odbiornik przestał emitować dźwięk, podziałało to mnie niewiarygodnie, poderwałem się. Podbiegłem do urządzenia, cisza&#8230;</p>
<p>- To nie może&#8230; to nie może być prawda&#8230;</p>
<p>W jednym momencie natłok myśli przygniótł mnie do ziemi, oddech miałem płytki, nieustanne poczucie, że się duszę krążyło nade mną tak posępnie jakby pragnąc mojej śmierci, trwałem w tym stanie do momentu gdy nagle rozległo się pukanie&#8230; było to pukanie do drzwi. Tocząc wewnętrzny bój z nieistniejącymi wrogami doczołgałem się do drzwi, opierając ręce na zimnej, metalowej powierzchni powoli podążałem do prostokątnego prześwitu znajdującego się w górnej partii drzwi.</p>
<p>- Kto tam? Czego chcesz?<br />
- To ja, Ping&#8230; wpuść mnie.</p>
<p>Serce zaczęło bić szybciej, litry krwi przetaczające się przez moje ciało zwiększyły swoją prędkość, w jednym momencie zrobiło mi się gorąco, tętno wzrosło&#8230; Niepewną, drżącą dłoń położyłem na zasuwie drzwi, powoli przesuwając w swoją stronę kawał ciężkiego metalu&#8230; im więcej światła przedzierało się do pomieszczenia tym bardziej stawałem się niespokojny. Drzwi uległy&#8230; do pomieszczenia wszedł Ping, z wyrazem twarzy nie zapowiadającym dobrych wieści&#8230;</p>
<p>- Ni&#8230; Nie&#8230; udało mi się go uratować, otoczyli nas&#8230; nie byłem w stanie&#8230; wybacz&#8230;<br />
- Nadejdzie czas, czas triumfu Wolnego Oprogramowania, czas w którym M$ zapłaci za swoje wszystkie zbrodnie. Pomścimy śmierć Łajna&#8230;</p>
<p>Powaga sytuacji jeszcze do mnie nie dotarła, starałem się zachować spokój, smutek wymalowany na mojej twarzy, zdawał się pogłębiać&#8230; Mimo to głos miałem pewny, musiałem ze względu na wcześniej wypowiedzianą obietnicę&#8230; chodź tyle mogłem zrobić.<br />
Wskrzeszę FlashFXP, przeprogramuję go sam, nie mam wyjścia&#8230; zrobię to.
</p>
<p class="error">&#8220;Przebudzenie&#8221;, czyli treść właściwa publikacji:</p>
</div>
<p>Na pierwszy rzut oka wszystko działało, FlashFXP uruchamiał się bezproblemowo, działały zakładki, okna&#8230; jednakże po chwili dostrzegłem, że realizacja połączenia z serwerem jest niemożliwa - FlashFXP nadzwyczajnie w świecie zawieszał się. Wina leżała po stronie obsługi kontrolki listy, która była odpowiedzialna za wyświetlanie plików zawartych na serwerze.</p>
<p>Znalazłem informacje na temat tego błędu w bugtrack-u <em>Wine</em>:</p>
<p CLASS="info"><a TARGET="_blank" TITLE="Bug with FlashFXP still exists" HREF="http://bugs.winehq.org/show_bug.cgi?id=5131">http://bugs.winehq.org/show_bug.cgi?id=5131 </a><br />
&#8220;The issue is caused by a message loop between the app and the<br />
comctl32 listview code, when the listview is virtual (LVS_OWNERDATA).&#8221;</p>
<p>Błąd istnieje w <strong>comctl32/listview.c</strong> pobrałem patcha i zastosowałem go wedle zaleceń:</p>
<p CLASS="info"><a TITLE="Patch" HREF="http://bugs.winehq.org/attachment.cgi?id=5518">http://bugs.winehq.org/attachment.cgi?id=5518</a></p>
<p>Poprawiłem błędny kod <strong>listview.c</strong> oraz skompilowałem <em>Wine</em> raz jeszcze:</p>
<pre>
patch dlls/comctl32/listview.c &lt; patch
./configure
make &amp;&amp; make install</pre>
<p>Po tych zabiegach wszystko działa bezproblemowo z <em>Wine</em> w wersji: 0.9.49</p>
<p><font SIZE="0"><em>Korzystanie z komercyjnego oprogramowania trochę się kłóci z ideologią open-source propagowaną wraz z Linuksem, ale co zrobić gdy czasami nie można znaleźć alternatywy a ja osobiście lepszego klienta FTP jak do tej pory nie widziałem. Jeżeli posiadasz alternatywę, która według Ciebie mnie zainteresuje, pozostaw informację w komentarzach.</em></font></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.karpowicz.net/wine-flashfxp-320/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
