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

<channel>
	<title>printf(&#34; SaltwaterC &#34;); &#187; Programare</title>
	<atom:link href="http://www.saltwaterc.net/category/programare/feed" rel="self" type="application/rss+xml" />
	<link>http://www.saltwaterc.net</link>
	<description>Developer blog</description>
	<lastBuildDate>Thu, 18 Feb 2010 12:43:20 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Firebug 1.5 + Firefox 3.5.7 + Ubuntu Hardy amd64</title>
		<link>http://www.saltwaterc.net/rant/firebug-15-firefox-357-ubuntu-hardy-amd64.html</link>
		<comments>http://www.saltwaterc.net/rant/firebug-15-firefox-357-ubuntu-hardy-amd64.html#comments</comments>
		<pubDate>Fri, 29 Jan 2010 08:34:57 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Programare]]></category>
		<category><![CDATA[Rant]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/rant/firebug-15-firefox-357-ubuntu-hardy-amd64.html</guid>
		<description><![CDATA[Firebug este o unealtă indispensabilă activităților de dezvoltare web pe care le execut. Din păcate, actualizările se lasă cu urmări câteodată. Precum zice în titlu, am încercat combinația nefericită de mai sus. Buba stă în Firebug: 64 bit Firefox on Linux crashes with Firebug 1.5.0. Am mers pe firul epic al poveștii de pe issue [...]]]></description>
			<content:encoded><![CDATA[<p>Firebug este o unealtă indispensabilă activităților de dezvoltare web pe care le execut. Din păcate, actualizările se lasă cu urmări câteodată. Precum zice în titlu, am încercat combinația nefericită de mai sus. Buba stă în Firebug: <a href="http://blog.getfirebug.com/2010/01/19/64-bit-firefox-on-linux-crashes-with-firebug-1-5-0/" title="64 bit Firefox on Linux crashes with Firebug 1.5.0" target="_blank">64 bit Firefox on Linux crashes with Firebug 1.5.0</a>. Am mers pe firul epic al poveștii de pe issue tracker și mi-am resetat preferințele. Crash-ul reapare atunci când se reactivează tab-ul Net sau Console. Din nefericire, echipa Firebug aruncă vina către Ubuntu, desi eu mi-am făcut propriul build personalizat de Firefox, deci problema cred că zace undeva prin ceva bibliotecă livrată cu Ubuntu din moment ce versiunea de Firefox îmi aparține.</p>
<p>Soluția de moment: downgrade la Firebug 1.4: <a href="http://getfirebug.com/releases/firebug/1.4/" title="Firebug 1.4" target="_blank">http://getfirebug.com/releases/firebug/1.4/ </a></p>
<p>PS: Firefox 3.6 sub Hardy amd64 este probabil cea mai instabilă versiune lansată vreodată. Am avut versiuni de Firefox Alpha sau Beta ce erau mai stabile de atât.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/rant/firebug-15-firefox-357-ubuntu-hardy-amd64.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Dragă programatorule, dacă îți vine a copy-paste, fă refactor!</title>
		<link>http://www.saltwaterc.net/rant/draga-programatorule-daca-iti-vine-a-copy-paste-fa-refactor.html</link>
		<comments>http://www.saltwaterc.net/rant/draga-programatorule-daca-iti-vine-a-copy-paste-fa-refactor.html#comments</comments>
		<pubDate>Fri, 22 Jan 2010 11:41:45 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programare]]></category>
		<category><![CDATA[Rant]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/rant/draga-programatorule-daca-iti-vine-a-copy-paste-fa-refactor.html</guid>
		<description><![CDATA[M-am săturat de cod prost scris ca de mere pădurețe. Nu mă refer la cod nefuncțional sau cu bug-uri. Mă refer la metodologia copy-paste la care se apelează intensiv din când în când. După care apucă-te și modifică ceva pentru a adăuga chestii noi. M-am săturat de gândire non-DRY datorită căreia apuc să modific în [...]]]></description>
			<content:encoded><![CDATA[<p>M-am săturat de cod prost scris ca de mere pădurețe. Nu mă refer la cod nefuncțional sau cu bug-uri. Mă refer la metodologia copy-paste la care se apelează intensiv din când în când. După care apucă-te și modifică ceva pentru a adăuga chestii noi. M-am săturat de gândire non-<a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself" title="DRY" target="_blank">DRY</a> datorită căreia apuc să modific în 5 locuri și 3 fișiere pentru a pune o chestie amărâtă care să arate la fel peste tot. În concluzie, pe lângă defularea de mai sus, m-am hotărât să mai dau niște idei.</p>
<p>Pe alocuri plângerile mele au avut succes. Acum două zile colegii de echipă mă ascultau în timp ce modificam niște chestii, iar involuntar am zis: iar de aici copiez dincolo &#8230; touche: &#8220;Ce-ai zis mă? Să copiezi?&#8221;. Exact ce ziceam mai sus &#8230; câteodată și mie îmi vine greu să nu scriu cod prost. Dar eforturile susținute = evoluție. În concluzie am luat linia aceea lungă (un apel înlănțuit de proceduri) și am pus-o într-o nouă metodă.</p>
<p>În concluzie vreo câteva idei, departe de a oferi o imagine completă:</p>
<ul>
<li>dacă îți vine să faci copy-paste, fie ele și 3 linii de cod sau una lungă, înseamnă ca ai nevoie de un mic refactor.</li>
<li>o arhitectură bună, modulară, a aplicației, DRY (și preferabil <a href="http://en.wikipedia.org/wiki/KISS_principle" title="Keep It Simple, Stupid" target="_blank">KISS</a>) compliant, duce la o mentenanță mai ușoară. Pentru a modifica ceva nu este nevoie să cauți toate instanțele aceleiași bucăți de cod.</li>
<li>dacă acea parte de &#8216;unknown&#8217; umbrește puterea de a-ți crea arhitectura înainte de a o implementa, atunci orice model repetitiv din cod stă bine într-o metodă separată.</li>
<li>caută să înțelegi framework-ul pe care îl folosești. De exemplu în dezvoltarea web folosind MVC, nu prea are ce căuta într-un controller o chestie ce ar sta bine într-un helper/bibliotecă, pentru că atunci când este nevoie să fie apelată bucata respectivă din alt controller, fără refactor, o să fie trist. Desigur, excepție fac acele controllere moștenite, dar și acolo este o linie fină între ce se poate moșteni și ce ar trebui să fie apelabil global.</li>
<li>refactor, OOP, clase, interfețe, &#8216;design pattern&#8217; (exemplu: singleton) ar trebui să nu fie doar cuvinte într-un vocabular de specialitate.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/rant/draga-programatorule-daca-iti-vine-a-copy-paste-fa-refactor.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Importanța unui PHP framework bine scris</title>
		<link>http://www.saltwaterc.net/programare/importanta-unui-framework-php-bine-scris.html</link>
		<comments>http://www.saltwaterc.net/programare/importanta-unui-framework-php-bine-scris.html#comments</comments>
		<pubDate>Mon, 11 Jan 2010 21:32:08 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programare]]></category>
		<category><![CDATA[Securitate]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/programare/importanta-unui-framework-php-bine-scris.html</guid>
		<description><![CDATA[Spuneam la GeekMeet-ul din octombrie (damn it, iarăși fac referință la el) în timpul prezentării mele, pentru cei absenți, o abordare de la OS până la coder în privința Web Security, despre importanța folosirii unui framework ce să facă în mod implicit filtrare XSS și SQL Injection (SQLi) a input-ului, în biblioteca ce se ocupă [...]]]></description>
			<content:encoded><![CDATA[<p>Spuneam la GeekMeet-ul din octombrie (damn it, iarăși fac referință la el) în timpul prezentării mele, pentru cei absenți, o abordare de la OS până la coder în privința Web Security, despre importanța folosirii unui framework ce să facă în mod implicit filtrare <a href="http://en.wikipedia.org/wiki/Cross-site_scripting" title="Cross-site scripting" target="_blank">XSS</a> și <a href="http://en.wikipedia.org/wiki/SQL_injection" title="SQL injection" target="_blank">SQL Injection</a> (SQLi) a input-ului, în biblioteca ce se ocupă de baza de date. Iar pentru chestii riscante, chiar o filtrare XSS cu <a href="http://htmlpurifier.org/" title="HTML Purifier - Standards-Compliant HTML Filtering" target="_blank">HTML Purifier</a>, o bibliotecă a cărui filtru XSS a fost creat să treacă de <a href="http://ha.ckers.org/xss.html" title="XSS (Cross Site Scripting) Cheat Sheet Esp: for filter evasion" target="_blank">XSS (Cross Site Scripting) Cheat Sheet</a>.</p>
<p>Știu, nu vreau să fac &#8220;carieră&#8221; din astfel de post-uri pe blog și nu prea cred că o să mă vedeți vreodată să trimit chestii către <a href="http://hackersblog.org/" title="hackersblog" target="_blank">http://hackersblog.org/</a>. Sunt preocupat de a proteja, de a-i învăța pe alții cum să se protejeze, și mai puțin de a demonstra vulernabilități. Sunt orientat către ce nu ar trebui să facă aplicația și mai puțin înspre a demonstra cum ajungi acolo. De altel aș prefera ca lumea să nu se ia de &#8216;junk&#8217;-ul de WordPress ce rulează pe blog, sunt prea ocupat pentru a scrie un engine sigur cu un număr echivalent de facilități. Mă rog, va urma un contra-exemplu pentru a susține cele din paragraful anterior.</p>
<p>Povestea începe de la faptul că am avut o mică discuție cu <a href="http://boem.me/" title="necenzurat" target="_blank">necenzurat</a> despre importanța folosirii unui framework, dar el o susținea pe a lui cu alea 10 kile de cod. Doar pentru ce îți trebuie un framework de 1.25 megi (dimensiunea minimă, maxim 1.49) pentru o aplicație banală? Pai în primul rând bune sunt cele de PHP5 folosind OOP și clase cu auto-load. Poți face multiple instalări folosind aceleași surse ale framework-ului exceptând aplicația în sine. Folosești ce încarci. A da, și ai filtrare implicită. De ce? Pentru că nimeni nu este perfect. Greșeli apar și în codul programatorilor ce au trecut de fazele tatonării. Vorbesc din experiența lucrului și mai mult din experiența lucrului în echipă. Dacă tu ca programator nu o dai de gard, se prea poate să dea altul.</p>
<p>Acu recunosc, am trișat puțin. M-am uitat puțin prin cele 10 kile de cod astfel încât buba a fost oarecum imediată. Dar nu imposibil de descoperit cu puțină răbdare și stil având în vedere regulile simple de URL rewrite, destul de evidente, și faptul că era vorba de un singur parametru vulnerabil. De fapt am reușit 3 in 1: XSS, blind SQLi și disclosure în același input.</p>
<p>A da, a folosi mysql_error() în producție este una dintre cele mai proaste idei. XSS-ul și disclosure-ul au fost posibile prin intermediul acestei funcții magice ce ar trebui folosite doar pentru dezvoltare, nu și pentru producție.</p>
<p>Momentan nu dăm poze, așteptăm să aplice patch-ul trimis <img src='http://www.saltwaterc.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/programare/importanta-unui-framework-php-bine-scris.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP sub Windows, Zend Server, WinCache și un cluster FastCGI cu Process Manager</title>
		<link>http://www.saltwaterc.net/windows/php-sub-windows-zend-server-wincache-%c8%99i-un-cluster-fastcgi-cu-process-manager.html</link>
		<comments>http://www.saltwaterc.net/windows/php-sub-windows-zend-server-wincache-%c8%99i-un-cluster-fastcgi-cu-process-manager.html#comments</comments>
		<pubDate>Wed, 06 Jan 2010 22:11:45 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programare]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/windows/php-sub-windows-zend-server-wincache-%c8%99i-un-cluster-fastcgi-cu-process-manager.html</guid>
		<description><![CDATA[La GeekMeet-ul din Octombrie de la Sibiu, Todi Pruteanu ne zicea printre altele despre WinCache &#8211; un accelerator de PHP dedicat platformei Windows. Nelămurirea mea legată de WinCache a fost următoarea: dacă Microsoft iși anunță colaborarea pentru a susține PHP sub Windows, atunci de ce nu au colaborat cu echipa APC (Alternative PHP Cache) din [...]]]></description>
			<content:encoded><![CDATA[<p>La GeekMeet-ul din Octombrie de la Sibiu, <a href="http://studentclub.ro/todi/" title="Deschis celor deschiși" target="_blank">Todi Pruteanu</a> ne zicea printre altele despre <a href="http://www.iis.net/expand/WinCacheForPHP" title="Windows Cache Extension for PHP" target="_blank">WinCache</a> &#8211; un accelerator de PHP dedicat platformei Windows. Nelămurirea mea legată de WinCache a fost următoarea: dacă Microsoft iși anunță colaborarea pentru a susține PHP sub Windows, atunci de ce nu au colaborat cu echipa <a href="http://pecl.php.net/package/APC" title="Alternative PHP Cache" target="_blank">APC</a> (Alternative PHP Cache) din moment ce acesta este proiectul de casă și va fi introdus în nucleul PHP începând cu versiunea 6? Întrebarea a rămas fără răspuns. Cu toate acestea, experimentând puțin, am găsit un loc pentru această extensie, deși am impresia că acceleratorul &#8216;closed source&#8217; de la Zend, <a href="http://files.zend.com/help/Zend-Server-Community-Edition/zendoptimizerplus.html" title="Zend Optimizer+" target="_blank">ZendOptimizer+</a> alăruri de <a href="http://files.zend.com/help/Zend-Server-Community-Edition/zenddatacache.html" title="Zend Data Cache" target="_blank">Zend Data Cache</a> ce oferă un API de caching compatibil cu APC poate să preia aceeași funcție. Poate pentru că echipa Zend a scris printre altele un modul de Apache, tot closed source, &#8216;Zend Enabler for Apache&#8217; ce oferă un FastCGI Process Manager pentru Windows suficient de deștept, dar care face o chestie: rularea de mai multe procese FastCGI care deservesc același server web. În plus, Zend Server oferă suport și pentru Microsoft IIS, deci backend-ul PHP nu este restricționat la Apache.</p>
<p>Paragraful anterior rezumă problema, dacă citim printre rânduri. Problema sub Windows este rularea mai multor procese FastCGI ce să servească pe același port, practic un cluster local cu &#8217;round robin load balance&#8217;. Tehnic vorbind &#8211; se poate. Dincolo de un simplu FastCGI wrapper cum este spawn-fcgi, proiect de casă al lighttpd, a apărut <a href="http://redmine.lighttpd.net/boards/2/topics/686" title="Spawn-FCGI Win32" target="_blank">o versiune nativă de Windows</a> pe forurile respective. De curiozitate am luat <a href="http://redmine.lighttpd.net/attachments/727/spawn-fcgi-win32.c" title="Spawn-FCGI Win32 Source" target="_blank">sursa</a>, am compilat-o cu MinGW (gcc -O2 -lws2_32 -o spawn-fcgi-win32.exe spawn-fcgi-win32.c) și am început să mă joc. Într-un mod așteptat, suportul pentru PHP FastCGI childs nu funcționează sub Windows, din motive tehnice. De fapt cercetând sursele PHP pentru cgi SAPI (php-src/sapi/cgi/cgi_main.c) partea cu child process este pusă între niște blocuri de preprocesare pentru compilator: #ifndef PHP_WIN32 &#8230; #endif ceea ce practic anulează FastCGI Process Manager-ul rudimentar implementat de către echipa de dezvoltare a PHP. Motivele sunt simple: spre deosebire de *NIX, sub Windows nu există conceptul de fork() al proceselor. Ba mai mult, sub *NIX există PHP-FPM(FastCGI Process Manager) ceea ce dă apă la moară și mai mult unei platforme non-Windows pentru PHP. Fanii nginx știu despre ce este vorba.</p>
<p>Vestea bună este faptul că acel spawn-fcgi-win32.exe știe să lanseze mai multe procese ce să servească pe același port TCP. Dă și idei despre cum ar trebui implementat un FastCGI Process Manager sub Windows pentru PHP. Ba mai mult, cum ziceam și în paragraful anterior,  acestea vor servi prin round robin load balance. Această arhitectură multiproces, deși nu se pretează stilului Windows ce este preponderent multithread, rezolvă problemele cu extensiile de PHP ce nu au implementat acel &#8216;thread safety&#8217;, iar clusterul poate să facă uz de o arhitectură SMP, fără a apela la threading.</p>
<p>Acum poate apare întrebarea: de ce mai multe procese FastCGI pentru a procesa scripturile PHP? În primul rând practica ne invață că un &#8217;segmentation fault&#8217; poate să apară oricând, iar în producție nu este faptul cel mai de dorit. Arhitecturile multiproces s-au dovedit a fi cele mai potrivite. Vezi cazul Google Chrome cu 1 proces per tab. În al doilea rând, un proces PHP ce servește cereri FastCGI are o limită de 500 de cereri după care acel proces se închide. Acea limită este codată în sursele PHP (tot în cgi_main.c). Acea limită se poate altera prin &#8216;environment variables&#8217;, și anume prin: PHP_FCGI_MAX_REQUESTS. Problema care se ivește: o limită mare poate duce la probleme de memorie ocupată abuziv (memory leaks). În concluzie, această limită este necesară. Prin design-ul serverului FastCGI al PHP, limita este obligatorie și finită deci este nevoie de un PHP FastCGI Process Manager. Apache are ceva extensii (mod_fastcgi si mod_fcgid, doar mod_fastcgi știe să folosească TCP binding) sau soluția Zend Server: Zend Enabler for Apache, IIS are propriul manager. Piața de web servere de Windows ce <em>întâmplător</em> știu de FastCGI nu se termină aici. Spre exemplu eu folosesc versiunea nativă a nginx sub Windows pentru simplul fapt că folosesc nginx și sub alte platforme. Am o târlă de motive pentru care nginx este trecut în preferințele subsemnatului ca web server excelent. Dar, în același timp, nu pot să mă iau după toate &#8216;tutorialele&#8217; de PHP FastCGI sub Windows unde &#8216;php-cgi.exe -b 127.0.0.1:9000&#8242; este suficient pentru a rula. Este suficient până la primul crash sau până la 500 de cereri. În plus, eu ca web developer poate că îmi doresc o soluție complet separată de web server.</p>
<p>Bun, acum am pus bazele ideei despre cum ar trebui făcut un Process Manager. Una dintre probleme este acel &#8216;race condition&#8217;: dacă toate procesele au aceeași viață, spre exemplu un cluster local de 4 cu limită implicită de 500, atunci acestea se vor termina în modul următor: la cererea 1997 &#8211; primul, la cererea 1998 &#8211; al doilea, la cererea 1999 &#8211; al treilea, la cererea 2000 &#8211; ultimul. Dacă process managerul nu se prinde de faptul că nu mai exista cineva care să proceseze ceva.php, atunci web serverul va servi clasica eroare 504 (Gateway Timeout) iar clienții conectați la webserver vor fi nemulțumiți. Acel php-cgi.exe nu oferă o metodă de identificare a faptului că rămâne fără cereri. Nu există în cod suport pentru IPC (Inter Process Communication) cu un manager. În concluzie, după bootstrap, un manager poate doar să monitorizeze clusterul. Nu susțin faptul că nu s-ar putea implementa. Ori, această monitorizare poate avea întârzieri, și pe un server încărcat aceasta nu este de dorit. În concluzie, printr-un algoritm, managerul ar putea mări artificial și temporar viața proceselor 2, 3 și 4 pentru a pune un interval de întârziere și a fi cineva acolo care să servească până monitorul se prinde de faptul că lipsește cineva. Altă idee ar mai fi modificarea pentru Windows a serverului FastCGI ca să suporte respawn (autospawn), înainte de a se închide, deși încă nu am investigat dacă această posibilitate este realizabilă din punct de vedere tehnic. Teoretic ar fi OK, cel puțin din câte mă prind citind despre varii funcții din Windows API. Ar rezolva problema existenței unui child care să servească, in concluzie managerul s-ar transforma în simplu monitor de procese după secvența de bootstrap unde lansează clusterul. Idei am, din păcate n-am mai pus mâna pe C decât ocazional în ultimii 5 ani. Din fericire mai pricep ce e prin codul altora <img src='http://www.saltwaterc.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Ziceam și pe <a href="http://twitter.com/SaltwaterC/status/7451025800" title="De ce nu există un PHP - FastCGI Process Manager sub Windows?" target="_blank">Twitter</a>: <span class="status-body"><span class="entry-content">De ce nu există un PHP &#8211; FastCGI Process Manager sub Windows? Pentru că nimeni nu și-a dat interesul să scrie unul. Posibilităti există!</span></span></p>
<p>Ceea ce ne aduce iarăși la WinCache. N-am început degeaba cu el. Unei platforme PHP îi stă bine și cu un opcode cache (PHP accelerator, whatever). Pe lângă PHP din Zend Server &#8211; ce vine cu multe jucării de la mama lui, Zend, cred că se poate pune un nginx. Problema acceleratorului și al Cache API-ului ar fi rezolvată. Ba ar fi compatibil codul cu un eventual APC folosit în producție, chiar dacă în teorie, având în vedere soluțiile multiple, se recomandă o bibliotecă abstractă cu drivere pentru varii extensii PHP. Bun, ar zice unii: dar APC ce are? Păi, ultima versiune pusă la dispoziție de unul dintre oamenii ce se ocupă de build-ul de PHP pentru Windows, precum și de dezvoltarea lui, a pus la dispoziție o <a href="http://downloads.php.net/pierre/" title="Windows PHP extensions" target="_blank">chestie compatibilă PHP 5.3.x</a> ce din păcate pusă în setup-ul multiproces expus mai devreme duce la crash. Practic din 4 procese, 3 crapă, unul rulează relativ stabil. Contravine ideii de multiproces. XCache deși este excelent, nu foloseste shared memory pentru data cache, deci practic acesta va fi împărțit într-un număr egal cu numărul de procese. Nu știu code cache-ul cum se comportă. WinCache știe doar code cache, dar face uz de shared memory și funcționează bine cu load balancer-ul. În concluzie, cel puțin pe termen scurt WinCache are un rol acolo. Mai mult, WinCache funcționează doar cu versiunile de PHP non-thread-safe, compilate cu Visual C++ 9, și teoretic cu IIS, practic Microsoft a mințit. Funcționează cu nginx fără probleme și de ce nu, cu alte servere.</p>
<p>Altă idee: un server web sub *NIX ar putea folosi un server FastCGI sub Windows. nginx poate să folosească backend-uri multiple, eventual cu load balance între mai multe mașini. Deși încă sunt de părere că PHP sub Windows cam suge datorită faptului că are multe lacune iar majoritatea bibliotecilor ce le integrează provin din *NIX, are un atu: suportul COM/.NET &#8211; ceea ce înseamnă că într-o arhitectură existentă se poate adăuga un server Windows cu PHP ce să poată beneficia de anumite SDK-uri comerciale ce se distribuie sub formă de COM.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/windows/php-sub-windows-zend-server-wincache-%c8%99i-un-cluster-fastcgi-cu-process-manager.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Agile OpenSpace la Cluj, Scrum și Software Craftsmanship &#8211; Code retreat</title>
		<link>http://www.saltwaterc.net/programare/agile-openspace-la-cluj-scrum-si-software-craftsmanship-code-retreat.html</link>
		<comments>http://www.saltwaterc.net/programare/agile-openspace-la-cluj-scrum-si-software-craftsmanship-code-retreat.html#comments</comments>
		<pubDate>Tue, 13 Oct 2009 23:06:04 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programare]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/fara-nume/agile-openspace-la-cluj-scrum-%c8%99i-software-craftsmanship-code-retreat.html</guid>
		<description><![CDATA[Vineri și sâmbătă subsemnatul și Ciprian și-au mișcat fundurile pătrățoase până la Cluj pentru o întâlnire informală anunțată de către AgileWorks Romania, ca urmare a efortului curent de a ne &#8216;agiliza&#8217;. Deși inițial s-ar fi anunțat mai multă lume, prezența clujeană a fost destul de restrânsă &#8211; ceea ce într-un fel a fost trist, din [...]]]></description>
			<content:encoded><![CDATA[<p>Vineri și sâmbătă subsemnatul și <a href="http://despremere.blogspot.com/" title="Despre mere, marketing și comunicare" target="_blank">Ciprian</a> și-au mișcat fundurile pătrățoase până la Cluj pentru o întâlnire informală anunțată de către <a href="http://groups.google.com/group/agileworks-romania" title=" AgileWorks Romania">AgileWorks Romania</a>, ca urmare a efortului curent de a ne &#8216;agiliza&#8217;. Deși inițial s-ar fi anunțat mai multă lume, prezența clujeană a fost destul de restrânsă &#8211; ceea ce într-un fel a fost trist, din moment ce au apărut și speak-eri de talie mondială ce în mod normal ar veni pe finanțe dese la o conferință. Noi i-am prins pe &#8216;moca&#8217;. Cei ce au ajuns totuși, în ordinea în care au stat la masă și s-au prezentat:</p>
<p>- <a href="http://www.mihaibrehar.ro/blog/" title="programare web, management, antreprenoriat" target="_blank">Mihai Brehar</a></p>
<p>- <a href="http://www.mozaicworks.com/" title="Think, Design, Work Smart" target="_blank">Maria Diaconu</a></p>
<p>- Aici ar trebui să am un nume, dar am un lapsus în schimb</p>
<p>- <a href="http://www.negrean.ro/" title=" IT, New Marketing &amp; Web Specialist" target="_blank">Ovidiu Negrean</a></p>
<p>- Ciprian Stăvar</p>
<p>- Ștefan Rusu (adică subsemnatu&#8217;)</p>
<p>- <a href="http://www.alexbolboaca.ro/silverstripe/" title="Science, Evolution, Software Development" target="_blank">Alex Bolboacă</a></p>
<p>- Paul Nagy</p>
<p>- <a href="http://www.noop.nl/welcome.html" title="Management, Development, Complexity, and Whimsicality" target="_blank">Jurgen Appelo</a></p>
<p>În fine, timpul a fost scurt, au fost ceva probleme cu locația, s-au propus mai multe teme, s-a vorbit în mare parte despre estimări. Am trecut repede la fapte, cu berea în față (am specificat: cadru informal) dar cu atenția spre Agile. Paul în special și restul au oferit câteva informații valoroase:</p>
<p>- estimările se pot face pe task-uri ce nu depind de alte task-uri. Un dezvoltator pricepe mai bine care-i treaba cu dependința.</p>
<p>- este mai ușor să măsori în unități relative comparat cu unități bine stabilite. Exercițiul a constat în faptul că l-a pus pe Mihai Brehar să estimeze distanța dintre ei. Răspuns: 1,5m. Următoarea chestie a fost: pune degetul unde crezi tu că este jumătatea distanței dintre noi. Ochiometric a fost bine, iar dacă treceam la măsurători precise, a doua estimare ar fi mai bună &#8211; de unde și povestea cu velocity points. Pe de altă parte acele velocity points sunt valabile pentru o echipă. Schimbi oameni din echipă &#8211; ai altă echipă. Ajungem la filosofia Agile &#8211; oameni, nu unelte, dar despre asta era vorba în primul rând, nu?</p>
<p>- pentru cei ce vor să estimeze task-urile în timp, Paul a fost ferm: &#8216;am o veste proastă pentru dezvoltatori &#8211; nu puteți&#8217;. Se leagă de povestea de mai sus.</p>
<p>-  au fost prezentate mai multe metode de estimare, pe lângă clasicele numere incrementate sau luate ca valori din șirul lui Fibonacci, Alex a prezentat un tabel ceva mai complicat (nu îl pot reproduce, am reținut doar chestia cu numerele la tricouri <img src='http://www.saltwaterc.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ), iar Paul a vorbit despre metoda cărților de poker.</p>
<p>- ca idee, este nevoie de date suficiente pentru a face calcule. Ideea este luată oarecum din teoria numerelor mari din statistică. Numerele mici dau statisticile peste cap cu variații mari când ai date puține &#8230; dar când ai date multe, situația se schimbă.</p>
<p>- încă o reprezentare grafică a fost o chestie ce arăta partea de &#8216;known&#8217; și partea de &#8216;unknown&#8217; ce înconjoară acea zonă. Se leagă de chestiile de mai sus. Scopul este de a trece mai repede de la &#8216;unknown&#8217; la &#8216;known&#8217; prin învățare &#8211; cu cât înveți mai repede, cu atât mai repede se produce tranziția &#8211; și prin feedback.</p>
<p>Pentru că discuția a rămas începută, am schimbat locația datorită micilor probleme pomenite mai sus. Mai multă bere (beer is priceless!) și discuții mai aprinse. Ca niște concluzii: Agile este o filosofie (nimic nou sub Soare aici) ca răspuns celor ce debitează pe această temă. Paul (din nou) a venit cu o completare la idee prin &#8216;Scrum este un framework&#8217;. Ba mai mult, este un framework minimal &#8211; dacă scoți din el, se duce naibii totul, dar mai departe pe el se poate construi și personaliza metodologia de lucru. De altfel, cred că Jurgen a spus aceasta, sper să nu atribui greșit citatul/adaptarea, cei ce &#8216;fac Scrum&#8217; au tot atâtea șanse de a &#8216;face Scrum&#8217; câte șanse are un programator de a instanția o clasă abstractă. Lucru ce vine în completarea ideii despre Scrum ca framework.</p>
<p>Altă discuție interesantă la bere ce merită menționată a fost motivul pentru care managerii nu trebuie să pună presiune pe dezvoltatori. Din nou Paul la balon &#8211; da a fost vedeta serii. Cercul vicios sună/arată cam așa: presiune de la manager catre dezvoltator -&gt; grabă + hack -&gt; cod prost -&gt; maitenance -&gt; mai puțini oameni activi. Ultimele 3 duc la frustrare, buguri care mai departe duc la și la mai multă presiune, iar frustrarea adaugă încă o doză de cod prost și bug-uri.</p>
<p>A doua zi a fost dedicată Code retreat-ului, deși a apărut prin zonă doar Mihai Brehar și mai târziu Ovidiu Negrean. Deși mă simțeam ca după o bătaie cu parul (motiv necunoscut), am luat parte la toate cele trei iterații ce s-au făcut pe problema jocului de <a href="http://groups.google.com/group/agileworks-romania/browse_thread/thread/a7cfa7190436b687" title="  AgileWorks - October 2009 - ClujNapoca  " target="_blank">poker</a>, problemă pentru care am apelat la PHP ca limbaj și Kohana ca framework pentru simplitatea de a încărca automat clase și a face rapid un prototip. Primele două au fost alături de Mihai unde am exersat varii tehnici (TDD, pair programming), ultima a fost cu Alex. Ultimele două iterații au fost bazate pe TDD. Ca rezumat:</p>
<p>- prima iterație = FAIL. Cică era de așteptat. După 45 minute de pair programming, codul a fost rulat o singură dată și a returnat un simplu 0 &#8211; ceea ce nu rezolva prima mână. S-a văzut importanța testelor și ca o paranteză la implementare &#8211; folosirea limbajului de business cerut de client (black și white pentru jucători, nu hand1 și hand2).</p>
<p>- a doua iterație, TDD based, nu doar că a fost cu succes, dar am avut și timp de refactoring plus 5 minute de relaxare. Alex a fost prin zonă cu o mână de ajutor deoarece nimeni nu știa cum să facă TDD.</p>
<p>- a treia iterație a mers tot pe mâna TDD, am folosit o abordare diferită a problemei (altă echipă). Inițial ne-am propus să rezolvăm problema full house, iar în final am rezolvat și careul deoarece soluțiile erau înrudite în contextul respectiv. De data aceasta am fost creativ și am folosit o metodă matematică ce nu presupune parcurgerea mâinilor, ci calcule. Problema s-a redus la una de rezolvare a unui sistem de clasa a VI-a:</p>
<p>{ 2X + 3Y = 4X + Y</p>
<p>{ 2X + 3Y = X+ 4Y</p>
<p>ce rapid ajunge la X = Y  pe ambele ecuații (două drepte suprapuse, ca reprezentare în plan x0y) de unde și concluzia că soluția este funcțională pentru cele două cazuri (full + careu), deoarece X = Y presupune &#8216;five of a kind&#8217; cum erau la acele jocuri obosite de poker ce se găseau prin varii baruri. E bună și matematica aceasta la ceva în programare și mi-am adus aminte de ce sunt bune unele modele: dacă sunt demonstrate corect și implementate corect, sunt &#8216;bug free&#8217; din punct de vedere logic. Excludem erorile de limbaj/runtime.</p>
<p>Pentru că puțini pricep cum se face TDD, iau ca exemplu un feature ce trebuie să returneze -1, 0 sau 1 &#8211; folosit și în tratarea cazurilor la jocul de poker (black, tie, white).</p>
<p>- se scrie primul test (am folosit assert($obj-&gt;method() == -1);, nu am apelat la PHPUnit)</p>
<p>- se implementează un mock în method (return -1;)</p>
<p>- se rulează testul =&gt; OK</p>
<p>- se scriu celelalte teste (assert($obj-&gt;method() == 0); și assert($obj-&gt;method() == 1);), se rulează și evident, eșuează</p>
<p>- se implementează codul funcțional propriu zis</p>
<p>- se rulează iar testele, iar dacă totul e OK, refactor și teste</p>
<p>Chiar aveam într-o metodă o eroare de logică, TDD a arătat rapid sursa problemei, iar debug-ul a durat 10 secunde. Avantajele sunt clare. Ca idee: TDD se potrivește doar pentru core functionality, nu pentru interfețe. Nu poți testa un capcha sau un CSS pe IE 6 prin TDD. Pentru aplicații ce folosesc baze de date, este nevoie de un mock. În rest, metoda își arată utilitatea. Noapte bună!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/programare/agile-openspace-la-cluj-scrum-si-software-craftsmanship-code-retreat.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Eclipse, Subclipse si relocarea unui repository SVN</title>
		<link>http://www.saltwaterc.net/rant/eclipse-subclipse-si-relocarea-unui-repository-svn.html</link>
		<comments>http://www.saltwaterc.net/rant/eclipse-subclipse-si-relocarea-unui-repository-svn.html#comments</comments>
		<pubDate>Thu, 09 Jul 2009 15:57:18 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programare]]></category>
		<category><![CDATA[Rant]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/rant/eclipse-subclipse-si-relocarea-unui-repository-svn.html</guid>
		<description><![CDATA[Se pare că interfața SVN pe care o are Subclipse activată în mod implicit, și anume JavaHL are un DNS resolving scris cu picioarele. Inițial am crezut că m-am tâmpit eu și nu am setat corect adresa serverului ce rezolva hostname-ul respectiv &#8230; dar adresa era corectă, deci relocare &#8211; din cuc &#8211; un alt [...]]]></description>
			<content:encoded><![CDATA[<p>Se pare că interfața SVN pe care o are Subclipse activată în mod implicit, și anume JavaHL are un DNS resolving scris cu picioarele. Inițial am crezut că m-am tâmpit eu și nu am setat corect adresa serverului ce rezolva hostname-ul respectiv &#8230; dar adresa era corectă, deci relocare &#8211; din cuc &#8211; un alt eventual checkout &#8211; din cuc. Din fericire există alternativă, și anume folosirea SVNKit pe post de interfață.</p>
<p>Window » Preferences » Team » SVN &#8211; iar Client se schimba din JavaHL în SVNKit. Voila &#8211; se rezolvă problemele.</p>
<p>Eroarea era ceva de genul:</p>
<blockquote><p>RA layer request failed<br />
svn: OPTIONS of &#8216;http://<em>hostname</em>/svn/<em>repository_path</em>/trunk&#8217;: Could not resolve hostname `<em>hostname</em>&#8216;: No such host is known (http://<em>hostname</em>)</p></blockquote>
<p>Acum totul este roz. Setup: Eclipse 3.4.1, Subclipse 1.6.2, Java 1.6.0_13.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/rant/eclipse-subclipse-si-relocarea-unui-repository-svn.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>urlencode()/rawurlencode() complet</title>
		<link>http://www.saltwaterc.net/programare/urlencode-rawurlencode-complet.html</link>
		<comments>http://www.saltwaterc.net/programare/urlencode-rawurlencode-complet.html#comments</comments>
		<pubDate>Thu, 11 Jun 2009 23:32:22 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programare]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/programare/urlencoderawurlencode-complet.html</guid>
		<description><![CDATA[Exceptând faptul ca Mr. Google bușește validarea blogului (deși W3 nu citește resursele externe = se validează), deasemenea exceptând faptul că WordPress mai trage câte o gherlă și refuză să pună conținut valid, este cunoscut faptul că am un oarecare fetiș cu standardele. În concluzie depun eforturi reale pentru a le respecta. Din păcate există [...]]]></description>
			<content:encoded><![CDATA[<p>Exceptând faptul ca Mr. Google bușește validarea blogului (deși W3 nu citește resursele externe = se validează), deasemenea exceptând faptul că WordPress mai trage câte o gherlă și refuză să pună conținut valid, este cunoscut faptul că am un oarecare fetiș cu standardele. În concluzie depun eforturi reale pentru a le respecta. Din păcate există situații rare în care caractere arbitrare din UTF-8 duc la invalidarea paginilor. Un exemplu bun este atunci când se compun link-uri ce conțin caractere non-ASCII. Soluția evidentă este URL encoding, dar din păcate funcția urlencode() din PHP, precum și rawurlencode() are boala de a omite caracterele menționate mai sus. Din moment ce dezvoltatorii PHP refuză introducerea unui flag pentru a putea face o codare completă a unui șir de caractere, există soluții ce pot fi aplicate la nivel de PHP. Soluția propusă de către subsemnatul depinde doar de componente din core (PCRE este parte a PHP core!).</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> url_encode_all<span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/./e'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;sprintf('<span style="color: #009933; font-weight: bold;">%%</span><span style="color: #009933; font-weight: bold;">%02X</span>', ord('<span style="color: #000099; font-weight: bold;">\\</span>0'))&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$text</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/programare/urlencode-rawurlencode-complet.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL, arbori, o singură tabelă, cheile străine si un exemplu în Kohana</title>
		<link>http://www.saltwaterc.net/programare/mysql-arbori-o-singura-tabela-cheile-straine-si-un-exemplu-in-kohana.html</link>
		<comments>http://www.saltwaterc.net/programare/mysql-arbori-o-singura-tabela-cheile-straine-si-un-exemplu-in-kohana.html#comments</comments>
		<pubDate>Wed, 27 May 2009 16:34:27 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programare]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/programare/mysql-arbori-o-singura-tabela-cheile-straine-si-un-exemplu-in-kohana.html</guid>
		<description><![CDATA[Aparent am o poveste de spus. Ei bine și de data aceasta aparențele nu înșeală. M-am lovit de suficiente ori de problema arborilor stocați în baze de date, în special atunci când este vorba de o structură de categorii. Cum nu sunt un mare fan al procedurilor stocate și al trigger-elor, sunt de părere că [...]]]></description>
			<content:encoded><![CDATA[<p>Aparent am o poveste de spus. Ei bine și de data aceasta aparențele nu înșeală. M-am lovit de suficiente ori de problema arborilor stocați în baze de date, în special atunci când este vorba de o structură de categorii. Cum nu sunt un mare fan al procedurilor stocate și al trigger-elor, sunt de părere că impunând o constrângere de cheie străina problema se rezolvă mult mai elegant atunci când vine vorba să se șteargă toată ierarhia. MyISAM nu știe el de chei străine deci aici vine în ajutor InnoDB. InnoDB știe de chei străine, dar cel mai probabil prin transformarea tabelei problema arborelui nu se rezolvă de la sine deoarece nu se pot impune constrângerile de cheie străina.</p>
<p>Ideea este următoarea: pentru a impune o cheie străina folosind MySQL și InnoDB este nevoie ca structura arborelui să fie corecta și aceasta să convină lui InnoDB. A doua parte este partea spinoasă. Cel mai probabil un arbore corect definit are un lucru esențial ce îi lipsește. Se dă următoarea structură de bază:</p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;"><span style="color: #990099; font-weight: bold;">CREATE</span> <span style="color: #990099; font-weight: bold;">TABLE</span> <span style="color: #008000;">`trees`</span> <span style="color: #FF00FF;">&#40;</span>
<span style="color: #008000;">`id`</span> <span style="color: #999900; font-weight: bold;">INT</span><span style="color: #FF00FF;">&#40;</span> <span style="color: #008080;">11</span> <span style="color: #FF00FF;">&#41;</span> <span style="color: #FF9900; font-weight: bold;">UNSIGNED</span> <span style="color: #CC0099; font-weight: bold;">NOT</span> <span style="color: #9900FF; font-weight: bold;">NULL</span> <span style="color: #FF9900; font-weight: bold;">AUTO_INCREMENT</span> <span style="color: #990099; font-weight: bold;">PRIMARY KEY</span> <span style="color: #000033;">,</span>
<span style="color: #008000;">`parent<span style="color: #008080; font-weight: bold;">_</span>id`</span> <span style="color: #999900; font-weight: bold;">INT</span><span style="color: #FF00FF;">&#40;</span> <span style="color: #008080;">11</span> <span style="color: #FF00FF;">&#41;</span> <span style="color: #FF9900; font-weight: bold;">UNSIGNED</span> <span style="color: #CC0099; font-weight: bold;">NOT</span> <span style="color: #9900FF; font-weight: bold;">NULL</span> <span style="color: #990099; font-weight: bold;">DEFAULT</span> <span style="color: #008000;">'1'</span><span style="color: #000033;">,</span>
<span style="color: #008000;">`data`</span> <span style="color: #999900; font-weight: bold;">VARCHAR</span><span style="color: #FF00FF;">&#40;</span> <span style="color: #008080;">255</span> <span style="color: #FF00FF;">&#41;</span> CHARACTER <span style="color: #990099; font-weight: bold;">SET</span> utf8 <span style="color: #CC0099; font-weight: bold;">COLLATE</span> utf8_unicode_ci <span style="color: #CC0099; font-weight: bold;">NOT</span> <span style="color: #9900FF; font-weight: bold;">NULL</span> <span style="color: #000033;">,</span>
<span style="color: #990099; font-weight: bold;">INDEX</span> <span style="color: #FF00FF;">&#40;</span> <span style="color: #008000;">`parent<span style="color: #008080; font-weight: bold;">_</span>id`</span> <span style="color: #FF00FF;">&#41;</span>
<span style="color: #FF00FF;">&#41;</span> <span style="color: #990099; font-weight: bold;">ENGINE</span> <span style="color: #CC0099;">=</span> <span style="color: #990099; font-weight: bold;">InnoDB</span> CHARACTER <span style="color: #990099; font-weight: bold;">SET</span> utf8 <span style="color: #CC0099; font-weight: bold;">COLLATE</span> utf8_unicode_ci</pre></div></div>

<p>Precum se observă schema de date este corectă iar aparent nu pot apărea probleme. Se dă chiar următorul arbore:</p>
<pre>
1, 0, a
2, 0, b
3, 1, c
4, 1, d
5, 3, e
6, 2, f</pre>
<p>Deși (aparent) la prima vedere structural este corect, dacă se rulează interogarea ce ar trebui sa pună constrângerea:</p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;"><span style="color: #990099; font-weight: bold;">ALTER</span> <span style="color: #990099; font-weight: bold;">TABLE</span> <span style="color: #008000;">`trees`</span> <span style="color: #990099; font-weight: bold;">ADD</span> <span style="color: #990099; font-weight: bold;">FOREIGN KEY</span> <span style="color: #FF00FF;">&#40;</span> <span style="color: #008000;">`parent<span style="color: #008080; font-weight: bold;">_</span>id`</span> <span style="color: #FF00FF;">&#41;</span> <span style="color: #990099; font-weight: bold;">REFERENCES</span> <span style="color: #008000;">`trees`</span> <span style="color: #FF00FF;">&#40;</span>
<span style="color: #008000;">`id`</span>
<span style="color: #FF00FF;">&#41;</span> <span style="color: #990099; font-weight: bold;">ON</span> <span style="color: #990099; font-weight: bold;">DELETE</span> <span style="color: #990099; font-weight: bold;">CASCADE</span> <span style="color: #000033;">;</span></pre></div></div>

<p>o să dea o eroare de MySQL de toată frumusețea, ceva gen:</p>
<pre>#1452 - Cannot add or update a child row: a foreign key constraint fails
([...]`, CONSTRAINT `[...]` FOREIGN KEY (`parent_id`)
REFERENCES `trees` (`id`) ON DELETE CASCADE)</pre>
<p>Cei cu privirea mai ageră poate că s-au prins de soluție. Nu întâmplător i-am dat valoare implicită 1 lui parent_id, ba chiar mai mult, exemplul dat de mine nu este UN arbore, ci mai mulți arbori stocați în aceeași tabelă. Am dat acest exemplu pentru că am întâlnit de suficiente ori în practică asemenea implementări ce mai încolo îmi dădeau bătăi de cap. Ba chiar am moștenit o astfel de baza de date pentru un proiect. Ceea ce confirmă zicala care spune faptul că web developerii sug la SQL &#8211; iar cum sunt și eu în breasla lor mă auto-includ. Dar din când în când, mai există și momente de deșteptare.</p>
<p>Soluția sună cam asa: se face backup la date. Cheile primare nu se salvează, coloana parent_id ce va deveni cheie străina se incrementează cu o unitate dacă este vorba de o implementare precum cea din exemplul meu, dacă nu, atunci se adaptează. Se golește tabela. Se aplică iarăși codul de mai sus pentru crearea cheii străine (ALTER TABLE bla, bla, bla). În mod deloc surprinzător, aceasta va funcționa fără probleme. Nu va mai da eroarea #1452. Dar, pentru a continua, este imperativ ca această înregistrare să se găsească în tabelă:</p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;"><span style="color: #990099; font-weight: bold;">INSERT</span> <span style="color: #990099; font-weight: bold;">INTO</span> <span style="color: #008000;">`trees`</span> <span style="color: #FF00FF;">&#40;</span>
<span style="color: #008000;">`id`</span> <span style="color: #000033;">,</span>
<span style="color: #008000;">`parent<span style="color: #008080; font-weight: bold;">_</span>id`</span> <span style="color: #000033;">,</span>
<span style="color: #008000;">`data`</span>
<span style="color: #FF00FF;">&#41;</span>
<span style="color: #990099; font-weight: bold;">VALUES</span> <span style="color: #FF00FF;">&#40;</span>
<span style="color: #008000;">'1'</span><span style="color: #000033;">,</span> <span style="color: #008000;">'1'</span><span style="color: #000033;">,</span> <span style="color: #008000;">'root'</span>
<span style="color: #FF00FF;">&#41;</span><span style="color: #000033;">;</span></pre></div></div>

<p>&#8216;root&#8217; nu e musai să fie &#8216;root&#8217;. Poate fi și &#8216;rădăcină&#8217;, dar cum personal scriu mai rar soft pentru România, prefer denumirile în Engleză. Aceasta trebuie să fie rădăcina arborelui. O înregistrare de genul (0, 0, &#8216;root&#8217;) este invalidă, deci nu va putea fi folosită pentru a valida implementarea originală. De aici se pot insera mai departe înregistrările, fără bătăi de cap atâta timp cât se păstrează integritatea relației cheie primară &#8211; cheie străină. De altfel, această înregistrare NU trebuie ștearsă. Dacă se șterge, se va șterge automat tot arborele. Este evident &#8230; dacă tai un copac de la rădăcina, cade cu totul. Dacă tai doar o creangă, restul copacului nu este afectat. În concluzie, dacă datele sunt manipulate corect, nu pot apărea probleme. Mai departe se poate insera noul arbore:</p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;"><span style="color: #990099; font-weight: bold;">INSERT</span> <span style="color: #990099; font-weight: bold;">INTO</span> <span style="color: #008000;">`trees`</span> <span style="color: #FF00FF;">&#40;</span>
<span style="color: #008000;">`parent<span style="color: #008080; font-weight: bold;">_</span>id`</span> <span style="color: #000033;">,</span>
<span style="color: #008000;">`data`</span>
<span style="color: #FF00FF;">&#41;</span>
<span style="color: #990099; font-weight: bold;">VALUES</span> <span style="color: #FF00FF;">&#40;</span>
<span style="color: #008080;">1</span><span style="color: #000033;">,</span> <span style="color: #008000;">'a'</span>
<span style="color: #FF00FF;">&#41;</span><span style="color: #000033;">,</span> <span style="color: #FF00FF;">&#40;</span>
<span style="color: #008080;">1</span><span style="color: #000033;">,</span> <span style="color: #008000;">'b'</span>
<span style="color: #FF00FF;">&#41;</span><span style="color: #000033;">,</span> <span style="color: #FF00FF;">&#40;</span>
<span style="color: #008080;">2</span><span style="color: #000033;">,</span> <span style="color: #008000;">'c'</span>
<span style="color: #FF00FF;">&#41;</span><span style="color: #000033;">,</span> <span style="color: #FF00FF;">&#40;</span>
<span style="color: #008080;">2</span><span style="color: #000033;">,</span> <span style="color: #008000;">'d'</span><span style="color: #000033;">,</span>
<span style="color: #FF00FF;">&#41;</span><span style="color: #000033;">,</span> <span style="color: #FF00FF;">&#40;</span>
<span style="color: #008080;">4</span><span style="color: #000033;">,</span> <span style="color: #008000;">'e'</span>
<span style="color: #FF00FF;">&#41;</span><span style="color: #000033;">,</span> <span style="color: #FF00FF;">&#40;</span>
<span style="color: #008080;">3</span><span style="color: #000033;">,</span> <span style="color: #008000;">'f'</span>
<span style="color: #FF00FF;">&#41;</span><span style="color: #000033;">;</span></pre></div></div>

<p>Se va obține rezultatul dorit inițial. Iar constrângerea își face magia: spre exemplu dacă se șterge (2, 1, &#8216;a&#8217;), atunci automat se vor șterge și (4, 2, &#8216;c&#8217;), (5, 2, &#8216;d&#8217;) și (6, 4, &#8216;e&#8217;) pentru că ierarhic au ca părinte pe (2, 1, &#8216;a&#8217;).</p>
<p>Pentru că tot m-a prins microbul MVC, mai bine zis Kohana, o să dau ca exemplu un model ce tratează din punctul de vedere al aplicației problema de mai sus. Din moment ce în mod implicit Kohana este destul de restrictiv cu manipularea variabilelor, altfel spus chestii ce în mod normal PHP le tratează ca &#8216;Notice&#8217; în Kohana pot da in &#8216;Runtime Error&#8217;, metodele sunt puțin mai stufoase în sensul că verifică integritatea înainte de a acționa. Exemple asupra a ceea ce am spus mai sus: nu se poate șterge sau actualiza o înregistrare ce este deja ștearsă. În mod normal aceste operații returnează 0, fie ca e vorba de &#8216;affected rows&#8217; sau de &#8216;deleted rows&#8217;. Cel puțin așa se întâmplă în mod implicit în ambele situații descrise, nu am cercetat dacă este configurabil acest comportament și nici nu am de gând. Kohana prin strictețe impune modele sănătoase de programare ce nu și le însușește orice cocalar ce pune mâna pe PHP pentru faptul că variabilele încep cu $ și a auzit că poate să se simtă și el h4&#215;0r pentru că poate programa ceva. Deci să îi dau bâte cu modelul:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Tree_Model <span style="color: #000000; font-weight: bold;">extends</span> Model <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">NULL</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		parent<span style="color: #339933;">::</span>__construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> add_child<span style="color: #009900;">&#40;</span><span style="color: #000088;">$parent_id</span><span style="color: #339933;">,</span> <span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$check_record</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>db<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>where<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$parent_id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>get<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'trees'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$check_record</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>count<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>db<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>from<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'trees'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>set<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'parent_id'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #000088;">$parent_id</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'data'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>insert<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #b1b100;">else</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> update_child<span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #339933;">,</span> <span style="color: #000088;">$parent_id</span><span style="color: #339933;">,</span> <span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$check_record1</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>db<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>where<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>get<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'trees'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$check_record2</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>db<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>where<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$parent_id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>get<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'trees'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$check_record1</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>count<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> <span style="color: #cc66cc;">1</span> AND <span style="color: #000088;">$check_record2</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>count<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>db<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>from<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'trees'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>set<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'parent_id'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #000088;">$parent_id</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'data'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>where<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>update<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #b1b100;">else</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> delete_child<span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$check_record</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>db<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>where<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>get<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'trees'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$check_record</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>count<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> <span style="color: #cc66cc;">1</span> AND <span style="color: #000088;">$id</span> <span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>db<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>from<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'trees'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>where<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>delete<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #b1b100;">else</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>PS: clasa este portabilă și pentru alte baze de date având în vedere faptul că am folosit &#8216;Database Query Builder&#8217;. Mergea si cu ORM, dar prefer o abordare puțin mai directa a problemei. În ORM nu mă mai simt stăpân pe situație. Pentru cârcotași: având în vedere că aceste tipuri de structuri de date nu prea sunt dedicate modificărilor dese, impactul de performanță datorat numărului mărit de interogări pentru a verifică integritatea este minim și merită efortul pentru a face o abordare corectă în loc să se apeleze la reguli mai puțin stricte și a depinde de erorile eventuale returnate de către baza de date (FK constraint error).</p>
<p>Nota: nu pot corecta comportamentul cretin al WordPress pentru a afisa corect apostrof si ghilimele.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/programare/mysql-arbori-o-singura-tabela-cheile-straine-si-un-exemplu-in-kohana.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lista Județelor, Municipiilor, Orașelor și a Comunelor/Satelor din România</title>
		<link>http://www.saltwaterc.net/programare/lista-judetelor-municipiilor-oraselor-si-a-comunelor-satelor-din-romania.html</link>
		<comments>http://www.saltwaterc.net/programare/lista-judetelor-municipiilor-oraselor-si-a-comunelor-satelor-din-romania.html#comments</comments>
		<pubDate>Sat, 23 May 2009 00:41:55 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programare]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/programare/lista-jude%c8%9belor-municipiilor-ora%c8%99elor-%c8%99i-a-comunelorsatelor-din-romania.html</guid>
		<description><![CDATA[Pe post de introducere: în primul rând o să îmi cer scuze din start pentru că nu am mai scris cu diacritice de un secol, deci anumite chestii s-ar putea să sune ciudat &#8211; cel puțin până ma obișnuiesc. Dacă tot am &#8216;Romanian Programmers&#8217; dat de Sfântul Windows 7, am zis să beneficiez puțin (ca [...]]]></description>
			<content:encoded><![CDATA[<p>Pe post de introducere: în primul rând o să îmi cer scuze din start pentru că nu am mai scris cu diacritice de un secol, deci anumite chestii s-ar putea să sune ciudat &#8211; cel puțin până ma obișnuiesc. Dacă tot am &#8216;Romanian Programmers&#8217; dat de Sfântul Windows 7, am zis să beneficiez puțin (ca porcul) pentru a-mi îndrepta această bubă în ceea ce privește scrierea propriilor articole.</p>
<p>Iar acum să trec la articolul pe bune. Ieri și astăzi am răscolit Internet-ul după o chestie ce să imi ofere lista pomenită în titlu. M-au ajuns din urmă zilele în care sunt pus în fața faptului de a dezvolta o asemenea aplicație ce necesită o astfel de listă/astfel de liste. Fie am găsit liste incomplete &#8211; mai bine zis un document xls de la Institutul Național de Statistică ce datează de pe vremea lui Pazvante (sau recensământul din 2002, fiecare citește ce vrea) sau lista disponibilă pe Wikipedia ce nu mă coafează din moment ce am observat inadvertențe, fie <a href="http://www.mihaitha.net/2009/03/07/judetele-si-orasele-din-romania/" title="Judetele si orasele din Romania" target="_blank">nu sunt structurate</a> în sensul că orice sat e trecut la orașe. Deși nu am întâlnit o chestie ce să le mulțumească pe toate și anume o listă ce cuprinde și diacritice, lista de față este (relativ) completă.</p>
<p>Am scris un mic script ce a cules listele pomenite mai sus. Le pun la download ca fișier serializat, urmând ca fiecare sa îl convertească în formatul pe care și-l dorește: XML, JSON, SQL, etc. Mai pun și un script obosit ce ia conținutul fișierului și îl trântește în HTML  (cu var_dump() &#8211; nu m-am obosit să fac artă).</p>
<p>Download: <a href="http://saltwaterc.net/wp-download/lista-judete-municipii-orase-comune-sate-romania/lista_localitati.zip">lista_localitati.zip</a> <a href="http://saltwaterc.net/wp-download/lista-judete-municipii-orase-comune-sate-romania/process_ro_list_output.zip">process_ro_list_output.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/programare/lista-judetelor-municipiilor-oraselor-si-a-comunelor-satelor-din-romania.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Instalarea Apache 2.2 + PHP 5.2 + MySQL 5.1 sub Windows</title>
		<link>http://www.saltwaterc.net/windows/instalarea-apache-22-php-52-mysql-51-sub-windows.html</link>
		<comments>http://www.saltwaterc.net/windows/instalarea-apache-22-php-52-mysql-51-sub-windows.html#comments</comments>
		<pubDate>Wed, 29 Apr 2009 19:24:00 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programare]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/tech/instalarea-apache-22-php-52-mysql-51-sub-windows.html</guid>
		<description><![CDATA[Ultima actualizare: 19 Aprilie 2009
Introducere
Desi exista o droaie de pachete de astea ce le contin pe toate si au o gramada de arome, pe zi ce trece ajung la concluzia ca un developer serios nu se incurca cu mizerii si isi seteaza singur mediul de dezvoltare a aplicatiilor web. Ma rog, nu toate sunt mizerii, [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Ultima actualizare:</strong> 19 Aprilie 2009</p>
<h2>Introducere</h2>
<p>Desi exista o droaie de pachete de astea ce le contin pe toate si au o gramada de arome, pe zi ce trece ajung la concluzia ca un developer serios nu se incurca cu mizerii si isi seteaza singur mediul de dezvoltare a aplicatiilor web. Ma rog, nu toate sunt mizerii, dar majoritatea fie sunt prea stufoase, fie inutile sau inutilizabile fara lucru manual &#8211; deci mai bine faci lucru manual din start. Asta in cazul in care nu vrei sa ramai o mimoza pentru tot restul vietii care transpira cand vine vorba sa adauge module noi mediului respectiv, sau pur si simplu sa se blocheze in parametrii de configurare relativ simpli. Nu sustin faptul ca este usor. De altfel patrunderea in tainele configurarii fine necesita timp si multa documentatie citita. Dar macar vreo cateva chestii de baza ar trebui cunoscute. Iar chestiile de baza pornesc cu instalarea.</p>
<p>Propozitie cheie: daca iti este lene sa iti configurezi acest mediu (lucru ce nu se intampla zilnic, iar experienta acumulata este benefica) atunci oare nu iti este lene sa te apuci sa programezi catusi de cat mai mult decat aplicatii gen &#8220;hello world&#8221;? Pentru a implementa solutii de o complexitate relativ mare ce necesita varii module este nevoie de mult mai multa munca pentru documentare decat pentru a configura un mediu de dezvoltare. In plus, din moment ce nu iti cunosti bine mediul in care ruleaza aplicatiile tale, cum poti avea nesimtirea sa sustii ca ai idee foarte bine ce face propria aplicatie? De unde vei sti ca va functiona corect si este portabila pe alta masina? Intrebarile acestea sunt multe, si nu, nu am de gand sa le transform in intrebari retorice. Raspunsurile sunt mai mult sau mai putin evidente.</p>
<p>O sa structurez acest articol in cativa pasi destul de simplu de urmat. Este ca in cazul in care se construieste o casa: se pleaca de la fundatie, si se termina treaba cu acoperisul. Deci ordinea va respecta logica si bunul simt, cu notiunea ca desi o sa incep cu <strong>Apache</strong>, <strong>MySQL </strong>deasemenea poate fi primul pas deoarece baza de date si serverul web nu sunt interdependente. <strong>PHP </strong>se integreaza cu Apache, deci regulile anterior mentionate indica faptul ca va fi instalat dupa el &#8211; aceasta pentru a nu fi nevoit sa faci instalarea PHP de doua ori.<span id="more-533"></span></p>
<h2>Pasul 1: Instalarea Apache 2.2</h2>
<p>In principiu primul pas ar fi verificarea faptului ca nici un alt proces nu asculta pe portul 80 ce in mod uzual este folosit de catre Apache. In mare chestii precum Skype ar trebui inchise inainte de instalare, pentru ca Skype are prostul obicei de a asculta pe porturile tipice HTTP si HTTPS (adica 80 si 443) printre altele. Pentru o solutie generalizata, utilitarul netstat ar trebui sa ofere solutia: Start &gt; Run &gt; cmd.exe iar in chestia aia neagra aka terminal (chestie pe care multi nu o pricep, in concluzie o urasc) se ruleaza urmatoarea linie:</p>
<p><em>netstat -a -p TCP</em></p>
<p>ce va returna toate porturile TCP ce sunt active. Daca apare o chestie ce se termina cu :80 in coloana &#8220;Local Address&#8221; este necesara oprirea aplicatiei ce ocupa acel port. Exemplu de situatie in care instalarea <u><em><strong>nu</strong></em></u> va fi cu succes:</p>
<p align="center"> <a href="http://saltwaterc.net/wp-content/uploads/netstat-tcp-image.png" title="netstat si porturile TCP"><img src="http://saltwaterc.net/wp-content/uploads/netstat-tcp-image.png" alt="netstat si porturile TCP" /></a></p>
<p>Desi in trecut installer-ul oferit de Apache Foundation era destul de trist, sau buildul avea lacune (cea mai notabila: absenta suportului pentru SSL &#8211; deci nu se puteau folosi conexiuni criptate prin HTTPS), in prezent situatia s-a schimbat in bine. Nu mai este nevoie de build-uri 3rd party cu tutoriale complicate de instalare. Acest tutorial nu se vrea unul complicat, de unde si prezenta pozelor. <strong>Click pe ele</strong> pentru a le vedea mai mari. Desigur, anumite categorii de cititori se auto-exclud prin definitie. Desi suportul pentru criptare nu este obligatoriu pentru dezvoltare, este recomandat a-l avea la indemana in eventualitatea de a testa aplicatia cum se comporta in acest context &#8211; de altfel foarte recomandat daca se compun cai absolute din aplicatia PHP ce depind de context HTTP/HTTPS.</p>
<p>Pagina proiectului este: <a href="http://httpd.apache.org/download.cgi" title="Apache HTTP Server" target="_blank">http://httpd.apache.org/download.cgi </a></p>
<p>Ultima versiune la ora actuala este 2.2.11, deci pe parcursul acestui tutorial voi folosi aceasta versiune. De <a href="http://apache.iasi.roedu.net/httpd/binaries/win32/apache_2.2.11-win32-x86-openssl-0.9.8i.msi" title="Apache 2.2.11 - Windows + OpenSSL 0.9.8i" target="_blank">aici</a> se poate lua aceasta versiune folosind un mirror de Romania. Daca serverul este cazut, sau fisierul devine indisponibil, se poate oricand cauta o alternativa urmarind link-ul dat mai sus. In principiu dupa ce download-ul e gata, se executa pachetul ce tocmai a poposit pe disk:</p>
<p><em>apache_2.2.11-win32-x86-openssl-0.9.8i.msi </em></p>
<p>De aici instalarea e relativ banala pana la configurarea <strong>Server Information</strong>:</p>
<p align="center"><a href="http://saltwaterc.net/wp-content/uploads/apache2-server-information-image.png" title="Apache 2 Server Information"><img src="http://saltwaterc.net/wp-content/uploads/apache2-server-information-image.png" alt="Apache 2 Server Information" /></a></p>
<p>In principiu pentru o masina de dezvoltare aceste chestii nu sunt relevante, deci poti lasa datele implicite. Pentru un server &#8220;de productie&#8221; in primul rand n-as recomanda Windows pentru Apache2+PHP si in al doilea rand nu cred ca acesta este locul potrivit pentru a trata acest subiect. Deci ma limitez la dezvoltatori. Bifa pentru &#8220;All Users&#8221; este puternic recomandata, precum si instalarea ca serviciu. In cazul instalarii ca serviciu, serverul va porni impreuna cu sistemul de operare.</p>
<p>La urmatorul pas, <strong>Setup Type</strong>, se alege &#8220;Custom&#8221;. Installer-ul vrea sa faca treaba pentru tine, dar asta nu inseamna ca o va face neaparat asa cum trebuie, sau cum e recomandat. Mai departe, optiunile din lista de chestii ce se pot instala pot fi lasate asa cum sunt. Documentatia este optionala deoarece se poate gasi online. Eu o instalez pentru ca spre deosebire de PHP si MySQL, nu se distribuie o arhiva CHM pe site-ul oficial cu aceasta documentatie. Restul chestiilor sunt recomandate. &#8220;Build Headers and Libraries&#8221; este necesar doar celor ce fac sporturi extreme, deci nu este cazul de fata.</p>
<p>Aici mai este totusi o chestie de facut. Instalarea acestei stive WAMPP (Windows Apache MySQ PHP Platform) &#8211; pun sub acest nume pentru a nu se confunda cu proiectul WAMP ce le impacheteaza pe toate, se poate face imprastiat pe disk, dar ca recomandari acestea ar trebui sa fie tinute in acelasi director, caile de pe disk sa nu contina spatii si sa fie cat mai scurte. In concluzie click pe &#8220;Apache HTTP Server 2.2.11&#8243;, iar in partea stanga jos e un buton &#8220;Change&#8221;:</p>
<p align="center"> <a href="http://saltwaterc.net/wp-content/uploads/apache2-custom-setup-image.png" title="Apache 2 Custom Setup"><img src="http://saltwaterc.net/wp-content/uploads/apache2-custom-setup-image.png" alt="Apache 2 Custom Setup" /></a></p>
<p>Calea propusa de catre subsemnatul este:</p>
<p><em>C:\wampp\apache</em></p>
<p>Nu este obligatorie, este doar o recomandare. Dar folosind aceasta denumire, este suficient de clar ce fel de stiva este instalata.</p>
<p align="center"> <a href="http://saltwaterc.net/wp-content/uploads/apache2-custom-setup-path-image.png" title="Apache 2 Custom Setup - Calea catre WAMPP"><img src="http://saltwaterc.net/wp-content/uploads/apache2-custom-setup-path-image.png" alt="Apache 2 Custom Setup - Calea catre WAMPP" /></a></p>
<p>Se termina restul instalarii ce practic se rezuma la next, install, etc. La sfarsit ar trebui ca serviciul sa porneasca automat, iar jos langa ceas sa fie un panel de control pentru Apache 2.2. Pentru a valida instalarea, cu Web browserul preferat se viziteaza adresa: <a href="http://localhost" title="localhost" target="_blank" rel="noindex,nofollow">http://localhost/</a> iar daca totul e OK, ar trebui sa apara mesajul &#8220;It Works!&#8221;. Cam atat de la Apache.</p>
<h2>Pasul 2: Instalarea PHP 5.2</h2>
<p>Trecem la PHP 5.2.6 &#8211; ramura stabila 5.2 a PHP. Nu am ales o versiune mai noua (5.2.8 sau 5.2.9-2) pentru simplul motiv ca PHP 5.2.6 are un setup complet, in timp ce versiunile mai noi au o mana de module lipsa. Este drept ca se pot pune cele de la 5.2.6, dar este o munca ce nu va fi pe gustul cuiva ce acum incepe incet-incet sa puna gramada un mediu de dezvoltare. In plus, intre aceste versiuni nu au fost modificari majore. Ca o mica paranteza, PHP 5.3.0 va aduce modificari majore, dar momentan este disponibil doar ca versiune de test. De altfel, idea este sa avem un suport cat mai larg pentru dezvoltarea unei aplicatii. Exceptand cazurile in care nu exista alternative, limitarea la tehnologii vechi nu este de dorit. Oricum, in cazul branch-ului 5.2, de anul trecut si pana in prezent, nu s-a miscat mare lucru. S-a centrat atentia pe 5.3 si pe 6. Deci alegerea 5.2.6 este oarecum justificata.</p>
<p>Pentru ca versiunea este totusi una mai veche, link-ul de download este <a href="http://museum.php.net/php5/php-5.2.6-win32-installer.msi" title="PHP 5.2.6">acesta</a>. Dupa ce ati obtinut fisierul, executata-l. Da, este vorba despre:</p>
<p><em>php-5.2.6-win32-installer.msi</em></p>
<p>In continuare, treaba va merge ca pentru majoritatea installer-elor de Windows. Doar la Destination Folder este nevoie de o mica modificare:</p>
<p align="center"><a href="http://saltwaterc.net/wp-content/uploads/php5-destination-folder-image.png" title="PHP 5 Destination Folder"><img src="http://saltwaterc.net/wp-content/uploads/php5-destination-folder-image.png" alt="PHP 5 Destination Folder" /></a></p>
<p>si anume faptul ca am folosit calea propusa/recomandata:</p>
<p><em>C:\wampp\php</em></p>
<p>pentru a pastra o structura consistenta.</p>
<p>Urmatorul pas este important, nu pentru ca vreau sa ii acord eu importanta, ci pentru ca aici se va alege optiunea de configurare ce va integra PHP cu serverul HTTP. Se alege &#8220;Apache 2.2.x Module&#8221; nu pentru ca spun eu ci pentru faptul ca versiunea de Apache instalata in acest tutorial este 2.2 (d&#8217;oh) si pentru ca alte metode de integrare cu Apache fie sunt lente, fie sunt ceva mai dificile, deci vor fi prezentate intr-un articol viitor.</p>
<p align="center"><a href="http://saltwaterc.net/wp-content/uploads/php5-web-server-setup-image.png" title="PHP 5 Web Server Setup"><img src="http://saltwaterc.net/wp-content/uploads/php5-web-server-setup-image.png" alt="PHP 5 Web Server Setup" /></a></p>
<p>Pasul urmator presupune oferirea directorului unde se afla fisierul de configurare al Apache 2.2. Installer-ul este suficient de destept astfel incat sa stie sa puna ceea ce trebuie acolo, atata timp cat nu sunt probleme intre scaun si tastatura. Am ales calea precum zice imaginea urmatoare:</p>
<p align="center"><a href="http://saltwaterc.net/wp-content/uploads/php5-apache-configuration-directory-image.png" title="PHP 5 Apache Configuration Directory"><img src="http://saltwaterc.net/wp-content/uploads/php5-apache-configuration-directory-image.png" alt="PHP 5 Apache Configuration Directory" /></a></p>
<p>si anume:</p>
<p><em>C:\wampp\apache\conf\</em></p>
<p>ce respecta conventia anterior facuta.</p>
<p>Pasul urmator presupune alegerea componentelor PHP ce vor fi instalate. Ceea ce propune installer-ul este un setup minim, destul de inutil de altfel. Pentru a beneficia de intreaga putere a PHP este nevoie si de extensiile sale. Astfel, in sectiunea &#8220;Program&#8221; aleg si &#8220;Script Executable&#8221;, dar fara inregistrarea extensiei .php pentru a fi executata de catre PHP pe motiv ca atunci cand dau dublu click pe un .php prefer sa se deschida scriptul intr-un editor, in loc sa il ruleze. Oricum, daca este parte a unei aplicatii Web, atunci rularea de catre interpretor va fi inutila din start.</p>
<p>Sectiunea &#8220;Extensions&#8221; este partea stringenta. De altfel motivul pentru care am ales PHP 5.2.6. Le poti instala pe toate, dar se va incarca mediul in mod inutil. Alta solutie ar fi sa fie incarcate pe masura ce un proiect avanseaza, dar refacerea configuratiei aduce ceva batai de cap si necesita o cunoastere destul de buna a extensiilor. O lista recomandata de catre subsemnatul include: bzip2, bz2_filter, Crack, Curl, domxml, EXIF, Fileinfo, GD2, Gettext, GMP, pecl_http, mcrypt_filter, Multi-Byte String, Mcrypt, Ming, MySQL, MySQLi, OpenSSL, PDO &#8211; iar din sectiunea PDO &#8211; MySQL si SQLite, mai departe, phar, rar, Sockets, Standard PHP Library &#8211; Types Addon, SQLite, ssh2, Tidy, timezonedb, XML-RPC, XSL, zip, zip_filter. Lista este departe de a fi completa si inafara de MySQL si SQLite, alte engine-uri pentru baze de date au fost lasate pe afara, desi exista suport pentru ele. Deasemenea am lasat pe afara extensiile ce ofera suport pentru diverse protocoale, printre care si cele tipice pentru e-mail. La nevoie se pot include. Multe dintre ele se prea poate sa fie inutile pentru proiecte relativ simple.</p>
<p>Sectiunea &#8220;Extras&#8221; contine doar documentatie, dar nu isi are rostul. Online se gaseste documentatie actualizata, fie direct pe site, fie disponibila ca download. Deci o sa o las ca &#8220;debifata&#8221;.</p>
<p align="center"><a href="http://saltwaterc.net/wp-content/uploads/php5-chose-install-items-image.png" title="PHP 5 Chose Install Items"><img src="http://saltwaterc.net/wp-content/uploads/php5-chose-install-items-image.png" alt="PHP 5 Chose Install Items" /></a></p>
<p>Dupa terminarea instalarii, o sa ai un Apache 2.2 integrat cu PHP 5.2. Mai este nevoie totusi de o modificare:</p>
<p><em>C:\wampp\apache\conf\httpd.conf</em></p>
<p>contine optiunile de configurare ale Apache. Ce n-a facut installer-ul PHP si trebuie corectat de mana este activarea index.php ca fisier de index. Se cauta urmatorul bloc de configurare:</p>
<p><em>&lt;IfModule dir_module&gt;<br />
DirectoryIndex index.html<br />
&lt;/IfModule&gt;</em></p>
<p>Acesta se schimba in</p>
<p><em>&lt;IfModule dir_module&gt;<br />
DirectoryIndex index.php index.html index.htm<br />
&lt;/IfModule&gt;</em></p>
<p>Am adaugat din burta index.htm pentru ca unii folosesc si aceasta extensie pentru fisiere HTML. Restart la Apache. Daca ai lasat optiunile implicite, atunci ai langa ceas acel Apache Monitor ce are butoane pentru Start, Stop, Restart &#8211; deci nu este nevoie sa se sape prin managerul de servicii al Windows.</p>
<p><strong>Actualizare:</strong> NU apela la butonul <strong>Restart</strong> dupa instalarea PHP! Am constatat cu stupoare ca aplicand tutorialul meu, desi C:\wampp\php e in %PATH%, doar <strong>Stop</strong>+<strong>Restart</strong> il aduc pe calea cea buna. Detalii despre %PATH% mai jos.</p>
<p align="center"><a href="http://saltwaterc.net/wp-content/uploads/apache2-service-monitor-restart-image.png" title="Apache 2 Service Monitor Restart"><img src="http://saltwaterc.net/wp-content/uploads/apache2-service-monitor-restart-image.png" alt="Apache 2 Service Monitor Restart" /></a></p>
<p>In directorul:</p>
<p><em>C:\wampp\apache\htdocs</em></p>
<p>se gaseste directory root-ul aplicatiilor Web ce vor fi servite de catre configuratie. Pentru teste, index.html se va redenumi in index.php iar continutul lui va fi schimbat in:</p>
<p><em>&lt;?php</em></p>
<p><em>phpinfo();</em></p>
<p>dupa care se va accesa din nou adresa: <a href="http://localhost/" title="localhost" target="_blank" rel="noindex,nofollow">http://localhost/</a>. Ar trebui sa apara informatiile despre PHP si mediul in care ruleaza + informatii despre extensii si configurare.</p>
<p>Ponturi:</p>
<ol>
<li>pentru reconfigurarea PHP este suficienta rularea installer-ului din nou, urmata de apelarea cu incredere la butonul &#8220;Change&#8221;. Este recomandat ca extensiile instalate de catre installer sa nu fie scoase din setup direct din fisierul de configurare, desi aceasta este posibil. Reconfigurarea este posibila si fara installer, dar nu este de dorit pentru toata lumea.</li>
<li>daca apari erori la pornirea Apache (<em>C:\wampp\apache\logs\error.log</em> &#8211; contine log-ul de erori) atunci trebuie verificat daca installer-ul PHP si-a pus propria cale in %PATH%. Pentru mai multe detalii apelati la: <a href="http://en.wikipedia.org/wiki/Environment_variable" title="Environment Variable" target="_blank">Environment Variable</a>. %PATH% face parte din aceasta categorie si se poate modifica:</li>
</ol>
<ul>
<li>Windows XP: Properties la My Computer -&gt; Advanced -&gt; Environment Variables</li>
<li>Windows Vista/Windows 7: Properties la My Computer, e un link &#8220;Change Settings&#8221; pe acolo, ce va deschide un panou asemanator cu cel din Windows XP. De aici procedura e identica, si anume</li>
</ul>
<blockquote><p> In sectiunea System Variables, exista variabila cu numele Path. Se verifica daca contine calea C:\wampp\php. Daca nu, se adauga acolo. Separatorul de astfel de cai este &#8220;;&#8221; (fara ghilimele!!!) deci atentie la sintaxa.</p>
<p align="center"><a href="http://saltwaterc.net/wp-content/uploads/windows-environment-variables-path-image.png" title="Windows Environment Variables"><img src="http://saltwaterc.net/wp-content/uploads/windows-environment-variables-path-image.png" alt="Windows Environment Variables" /></a></p>
<p><strong>Note</strong>:</p>
<p>(1) Nu constituie erori de pornire acele &#8220;PHP Notice&#8221;. Erorile sunt explicite si arata faptul ca anumite biblioteci dinamice nu se pot incarca pentru ca Apache nu le gaseste. Acele biblioteci (dll-uri) ce nu sunt gasite de catre Apache se pot copia intr-un director de sistem gen <em>C:\Windows</em> sau <em>C:\Windows\system32</em> dar aceasta nu este o optiune prea desteapta. Deasemenea se pot copia si in directorul bin al Apache, dar din nou nu este o optiune desteapta. In fond si la urma urmei exista doua categorii de utilizatori de Windows: cei ce il utilizeaza corect &#8211; desi este mai dificil, scuteste utilizatorul de multe probleme clasice pe termen indelungat &#8211; si utilizatorii ce il fac praf suficient de repede datorita administrarii extrem de proaste. Nu exista cale de mijloc.</p>
<p>(2) In cazul Windows XP o sa apara &#8220;Warnings&#8221; in legatura cu bibliotecile suplimentare necesare anumitor extensii (gen libmysql.dll pentru MySQL si MySQLi). Solutii: a) Reboot la OS dupa instalarea Apache+PHP. Sub anumite versiuni de Windows (exemplu: XP, la Vista nu am remarcat datorita problemei descrise mai jos) Apache nu baga in seama un %PATH% modificat &#8211; deci este nevoie de un reboot pentru a-l aduce pe calea cea buna. Avand in vedere faptul ca anumite chestii din PHP depind de un environment variable, chestia de mai sus este bine sa fie retinuta. b) copierea dll-urilor cu pricina ce se gasesc in directorul PHP si sunt cerute de catre extensii din directorul bin al Apache. Desi, aceasta optiune este una destul de trista. As zice din barda.</p></blockquote>
<p><strong>Windows Vista:</strong> intamplator astazi m-am lovit de instalarea stivei prezentare in acest articol sub Windows Vista. Din moment ce subsemnatul si Vista suntem certati (pe buna dreptate) detaliul de mai sus mi-a scapat. Pana in prezent, integrarea de fata functioneaza doar sub Windows XP si Windows 7 (Beta si RC). Windows Vista are nevoie de un parametru suplimentar atunci cand se configureaza integrarea dintre Apache 2.2 si PHP 5.2, in rest codul PHP apare in browser in loc sa fie interpretat intr-un mod foarte retard. Problema se mai intalneste si la unele pachete de acestea all-in-one. Sectiunea aceasta ce in mod standard se gaseste la sfarsitul fisierului httpd.conf dupa rularea installer-ului PHP:</p>
<p><em>#BEGIN PHP INSTALLER EDITS &#8211; REMOVE ONLY ON UNINSTALL<br />
PHPIniDir &#8220;C:/wampp/php/&#8221;<br />
LoadModule php5_module &#8220;C:/wampp/php/php5apache2_2.dll&#8221;<br />
#END PHP INSTALLER EDITS &#8211; REMOVE ONLY ON UNINSTALL </em></p>
<p>trebuie sa mai contina inca o chestie, deci sa arate astfel pentru Windows Vista:</p>
<p><em>#BEGIN PHP INSTALLER EDITS &#8211; REMOVE ONLY ON UNINSTALL<br />
PHPIniDir &#8220;C:/wampp/php/&#8221;<br />
LoadModule php5_module &#8220;C:/wampp/php/php5apache2_2.dll&#8221;<br />
<strong>AddType application/x-httpd-php .php</strong><br />
#END PHP INSTALLER EDITS &#8211; REMOVE ONLY ON UNINSTALL</em></p>
<h2>Pasul 3: Instalarea MySQL 5.1</h2>
<p>In principiu inainte de instalare ar trebui verificat daca nu ruleaza nimic pe portul 3306, adica portul implicit pe care asculta serverul MySQL. Daca nu mai exista o alta instalare de MySQL, atunci slabe sanse. Pentru identificarea precisa, se va folosi metoda prezentata la instalarea Apache.</p>
<p>MySQL 5.1.34 este ultima versiune stabila disponibila la momentul redactarii acestui articol, deci il vom folosi pe acesta. Desi mai exista MySQL 5.0 ca branch stabil, folosit destul de mult in productie (de altfel mai exista si 4.1 prin productie, dar il urasc cu pasiune din motive obiective) totusi am mers pe ultima chestie lansata. Are vreo cateva chestii noi ce in buna parte tin de viteza si de extensibilitate.</p>
<p>Spre deosebire de Apache 2.2 si PHP 5.2, pe pagina oficiala a MySQL exista atat build-uri de 32-bit, cat si build-uri de 64-bit. Primele doua se distribuie oficial doar ca binare de 32-bit. In principiu se recomanda build-ul ce se potriveste cel mai bine platformei, 64-bit in cazul subsemnatului, cu notiunea ca pot apela si la unul de 32-bit. Link-ul de download pentru build-ul pe 32 este <a href="http://dev.mysql.com/downloads/mysql/5.1.html#win32" title="MySQL 5.1 32-bit" target="_blank">acesta</a>, in timp ce pentru cel de 64 este <a href="http://dev.mysql.com/downloads/mysql/5.1.html#winx64" title="MySQL 5.1 64-bit" target="_blank">acesta</a>. De acolo se alege &#8220;Windows MSI Installer&#8221; iar din dreapta link-ul de &#8220;Download&#8221;. In cazul in care mirror-ul ales automat pentru &#8220;Download&#8221;este invalid sau are probleme, se poate alege si &#8220;Pick a mirror&#8221; de unde se alege unul mai apropiat de casa.</p>
<p>Eu am plecat la drum cu:</p>
<p><em>mysql-5.1.34-winx64.msi</em></p>
<p>iar utilizatorii unui Windows 32-bit este obligatoriu sa plece la drum cu:</p>
<p><em>mysql-5.1.34-win32.msi</em></p>
<p>In rest, instalarea este relativ identica.</p>
<p>In pasul in care installer-ul intreaba de  &#8220;Setup Type&#8221;, se alege &#8220;Custom&#8221;. Se va debifa documentatia deoarece este disponibila online. Optional se poate lasa. Eu prefer sa downloadez ultimele arhive cu documentatie ce sunt la zi. In rest, nu mai este nevoie de nimic deoarece optiunile sunt multumitoare. Ce mai trebuie schimbata este calea de instalare, ce va folosi modelul prezentat mai sus in cazul Apache si PHP.</p>
<p><strong>Later Edit:</strong> mi-a scapat un mic aspect ce nu l-am mentionat data trecuta, si anume faptul ca serverul se poate instala intr-o locatie iar data storage-ul in alta. Acestea sunt imaginile actualizate:</p>
<p align="center"> <a href="http://saltwaterc.net/wp-content/uploads/mysql5-server-install-path-image.png" title="MySQL 5 Server Path"><img src="http://saltwaterc.net/wp-content/uploads/mysql5-server-install-path-image.png" alt="MySQL 5 Server Path" /></a></p>
<p align="center"> <a href="http://saltwaterc.net/wp-content/uploads/mysql5-server-datafiles-path-image.png" title="MySQL 5 Datafiles Path"><img src="http://saltwaterc.net/wp-content/uploads/mysql5-server-datafiles-path-image.png" alt="MySQL 5 Datafiles Path" /></a></p>
<p align="center"> <a href="http://saltwaterc.net/wp-content/uploads/mysql5-server-install-path-image1.png" title="MySQL 5 Install Paths"><img src="http://saltwaterc.net/wp-content/uploads/mysql5-server-install-path-image1.png" alt="MySQL 5 Install Paths" /></a></p>
<p>Se continua instalarea. La aparitia acelor chestii despre MySQL Enterprise, se da &#8220;Next&#8221; pana in sfarsit se ajunge la ultimul pas:</p>
<p align="center"><a href="http://saltwaterc.net/wp-content/uploads/mysql5-wizard-completed-image.png" title="MySQL 5 Wizard Completed"><img src="http://saltwaterc.net/wp-content/uploads/mysql5-wizard-completed-image.png" alt="MySQL 5 Wizard Completed" /></a></p>
<p>Bifa aia e importanta, dupa ea se va porni procesul de configurare al serverului MySQL si pe aici unii s-ar putea sa isi prinda urechile.Se continua clasicul click-Next pana configuratorul intreaba despre tipul configurarii:</p>
<p align="center"><a href="http://saltwaterc.net/wp-content/uploads/mysql5-server-instance-configuration-image.png" title="MySQL 5 Server Instance Configuration"><img src="http://saltwaterc.net/wp-content/uploads/mysql5-server-instance-configuration-image.png" alt="MySQL 5 Server Instance Configuration" /></a></p>
<p>Urmatoarea alegere este atat de evidenta, incat nu voi pune o poza ce sa o arate. Se va alege &#8220;Developer Machine&#8221; la server type. Urmatorul pas cere modul de utilizare a bazei de date. Cel implicit, &#8220;Multifunctional Database&#8221; este potrivit pentru acest tip de instalare. La urmatorul pas despre &#8220;InnoDB Tablespace Settings&#8221; se lasa optiunile implicite. Presupun ca pe C:\ exista suficient spatiu.</p>
<p>Urmatorul pas presupune setarea numarului de conexiuni concurente. De regula, desi in procesul de dezvoltare sunt rare situatiile in care optiunea implicita, &#8220;Decision Support (DSS)/OLAP&#8221; ce presupune un numar maxim 20 conexiuni concurente s-ar putea sa fie suficient, subsemnatul foloseste optiunea &#8220;Manual Setting&#8221; si pune numarul la 50.</p>
<p align="center"><a href="http://saltwaterc.net/wp-content/uploads/mysql5-server-instance-configuration-concurent-connections-image.png" title="MySQL 5 Server Instance Configuration Concurent Connections"><img src="http://saltwaterc.net/wp-content/uploads/mysql5-server-instance-configuration-concurent-connections-image.png" alt="MySQL 5 Server Instance Configuration Concurent Connections" /></a></p>
<p>Mai departe, la setarile de retea, &#8220;Enable TCP/IP Networking&#8221; este obligatoriu. Nu este necesara activarea unei exceptii in firewall daca baza de date nu va fi folosita inafara masinii. Eu deschid o gaura in firewall pentru acest port pentru ca se intampla sa accesez o baza de date din exterior. Exista alternativa la TCP/IP si anume &#8220;named pipes&#8221;, dar aceasta va fi lasata deoparte pe moment. Se justifica alegerea pentru masinile ce ruleaza baze de date impreuna cu aplicatii ce le folosesc, in rest, configurarea este putin mai dificila. Web-ul este gandit ca modular, deci in practica, exceptand o parte a Web hosturilor shared (sau cei ce au bani doar de un VPS/masina dedicata), serverul MySQL va rula pe o masina dedicata, in concluzie TCP/IP va fi singura cale de a comunica cu bazele de date. &#8220;Enable Strict Mode&#8221; este recomandat de catre installer si de catre subsemnatul.</p>
<p align="center"><a href="http://saltwaterc.net/wp-content/uploads/mysql5-server-instance-configuration-networking-options-image.png" title="MySQL 5 Server Instance Configuration Networking Options"><img src="http://saltwaterc.net/wp-content/uploads/mysql5-server-instance-configuration-networking-options-image.png" alt="MySQL 5 Server Instance Configuration Networking Options" /></a></p>
<p>Urmatorul pas este unul foarte important. O greseala in alegere aici se poate propaga mai departe in optiunile implicite si mai departe in probleme mari. Totul ar fi bine si frumos daca ar exista un singur set de caractere, dar din pacate nu este asa. Iar daca intentionezi sa dezvolti o aplicatie ce va primi altceva inafara de caractere latine si uzuale, este cazul sa pui bifa pe &#8220;Best Support For Multilingualism&#8221;. Se pot face hack-uri la nivel de cod PHP pentru a putea fi folosit setul de caractere implicit, dar aceasta inseamna ca toate sirurile de caractere ce se indreapta catre baza de date sa treaca prin acel filtru, iar o mica neatentie poate sa duca la ore de debugging inutil. In concluzie, mai bine se lucreaza direct cu UTF8.</p>
<p align="center"><a href="http://saltwaterc.net/wp-content/uploads/mysql5-server-instance-configuration-default-charset-image.png" title="MySQL 5 Server Instance Configuration Default Charset"><img src="http://saltwaterc.net/wp-content/uploads/mysql5-server-instance-configuration-default-charset-image.png" alt="MySQL 5 Server Instance Configuration Default Charset" /></a></p>
<p>Mai departe urmeaza setarile serviciului. Da, este recomandat ca MySQL sa fie instalat deasemenea ca serviciu. Bifa pentru lansare automata iarasi e recomandata. Deasemenea recomand adaugarea directorului bin al MySQL in %PATH%. Trebuie doar o bifa. Eu pun numele serviciului MySQL5.1 pentru ca am un fetis cu consistenta, iar Apache se pune Apache2.2 fara ca sa ma intrebe &#8211; deci pastrez ideea. Nu e obligatoriu.</p>
<p align="center"><a href="http://saltwaterc.net/wp-content/uploads/mysql5-server-instance-configuration-windows-options-image.png" title="MySQL 5 Server Instance Configuration Windows Options"><img src="http://saltwaterc.net/wp-content/uploads/mysql5-server-instance-configuration-windows-options-image.png" alt="MySQL 5 Server Instance Configuration Windows Options" /></a></p>
<p>Pasul urmator presupune setarile de securitate. Sub nici o forma nu este recomandata crearea unui &#8220;Anonymous Account&#8221;. Se recomanda crearea unei parole suficient de puternice pentru utilizatorul root ce este un superuser pentru MySQL. A nu se confunda cu root din *nix &#8211; utilizatorii MySQL nu sunt utilizatori de sistem. Serverul are propriul sistem de management al utilizatorilor. Deasemenea nu se recomanda activarea accesului remote pentru root.</p>
<p align="center"><a href="http://saltwaterc.net/wp-content/uploads/mysql5-server-instance-configuration-security-options-image.png" title="MySQL 5 Server Instance Configuration Security Options"><img src="http://saltwaterc.net/wp-content/uploads/mysql5-server-instance-configuration-security-options-image.png" alt="MySQL 5 Server Instance Configuration Security Options" /></a></p>
<p>Se continua setup-ul si gata si cu MySQL.</p>
<h2>Bonus: instalarea phpMyAdmin 3.1</h2>
<p><a href="http://www.phpmyadmin.net/home_page/" title="phpMyAdmin" target="_blank"><strong>phpMyAdmin</strong></a> este un frontend MySQL popular si destul de bun la ceea ce face. Desi initial nu l-am prea suportat, pe servere la distanta se poate dovedi un aliat puternic. In concluzie este o aditie buna si pentru dezvoltarea locala, desi exista si alte optiuni, recomandate de altfel sa fie la indemana: <a href="http://dev.mysql.com/downloads/gui-tools/5.0.html" title="MySQL GUI Tools" target="_blank">MySQL Query Browser, MySQL Administrator</a> si <a href="http://dev.mysql.com/workbench/" title="MySQL Workbench" target="_blank">MySQL Workbench</a> &#8211; scule facute de cei de la MySQL AB &#8211; adica Sun &#8211; adica Oracle &#8211; daca este sa pastrez istoricul cumparaturilor. Mai exista si <a href="http://www.webyog.com/en/downloads.php" title="SQLyog" target="_blank">SQLyog</a>, un frontend ce imbina elemente de Query Browser si de Administrator. Unii prefera in locul lui <a href="http://www.heidisql.com/download.php" title="HeidiSQL" target="_blank">HeidiSQL</a> &#8211; desi acesta din urma stie mai putine.</p>
<p>De <a href="http://www.phpmyadmin.net/home_page/downloads.php" title="phpMyAdmin Download" target="_blank">aici</a> am luat ultima versiune stabila, si anume 3.1.5. Instalarea este relativ mai complicata decat in cazul chestiilor de mai sus pentru ca este aplicatie PHP si nu am apelat la metoda cea mai usoara, dar am apelat la cea mai comoda pe termen lung. Am downloadat:</p>
<p><em>phpMyAdmin-3.1.5-all-languages.zip</em></p>
<p>A urmat extragerea arhivei si redenumirea directorului <em>phpMyAdmin-3.1.5-all-languages</em> din interiorul ei in <em>phpmyadmin</em>. L-am mutat in <em>C:\wampp\</em>. Acesta trebuie sa contina fisierele phpMyAdmin. Daca contine alt director, atunci acela trebuie redenumit in phpmyadmin si mutat in WAMPP. Configurarea phpMyAdmin presupune copierea fisierului <em>config.sample.inc.php</em> in <em>config.inc.php</em> si modificarea lui. Modificari necesare:</p>
<ul>
<li>definirea <em>$cfg['blowfish_secret']</em> cu un sir de caractere arbitrar. Preferabil sa fie cat mai de neinteles. <strong>ATENTIE: </strong>pentru a nu invalida sintaxa config.inc.php trebuie sa se foloseasca apostrof nu ghilimele pentru a defini sirul blowfish_secret. Conform documentatiei phpMyAdmin acesta are o dimensiune maxima <em>aparenta</em> de 46 caractere. Un generator bun poate fi algoritmul sha1, desi setul de caractere este mai redus decat in cazul in care se foloseste un generator ce sa includa varii caractere speciale. Pentru sha1 apeleaza cu incredere la: <a href="http://www.shell-tools.net/index.php?op=hash_sha" title="SHA1 Hash Generator" target="_blank">http://www.shell-tools.net/index.php?op=hash_sha </a></li>
<li>schimbarea <em>$cfg['Servers'][$i]['extension']</em> din <em>mysql</em> in <em>mysqli</em>. MySQLi aka MySQL Improved &gt; MySQL.</li>
</ul>
<p>Mai are si alte optiuni, dar nu sunt necesare si nu trebuie schimbate. <a href="http://www.phpmyadmin.net/documentation/" title="phpMyAdmin Documentation" target="_blank">Documentatia phpMyAdmin</a> le explica pe indelete.</p>
<p>Urmeaza integrarea cu Apache. Desi directorul s-ar fi putut pune pur si simplu in interiorul <em>C:\wampp\htdocs</em> s-ar putea sa incurce pe acolo, sau sa fie sters din greseala. Deci apelarea la un alias este o optiune mult mai recomandata. Mai intai voi prezenta pasii, dupa care voi oferi detalii pentru doi dintre ei. Aici sunt pasii:</p>
<ol>
<li>crearea unui fisier text gol in <em>C:\wampp\apache\conf\extra</em>. Acesta se va numi <em>httpd-phpmyadmin.conf</em> pentru a pastra conventia de nume ce o are Apache pentru fisierele de configurare. Fisierul se va gasi ca download la sfarsitul articolului, alaturi de toate celalte resurse.</li>
<li>acest fisier va trebui inclus in config-ul cel mare, si anume <em>C:\wampp\apache\conf\httpd.conf</em>. Se include fisierul anterior creat, chiar dupa lucrurile configurate automat de catre installer-ul PHP (scrie in comentariu, liniile ce incep cu # sunt considerate comentarii). Locul acesta se gaseste la sfarsitul fisierului.</li>
<li>restart la Apache.</li>
<li>vizitarea adresei <a href="http://localhost/phpmyadmin" title="phpMyAdmin" target="_blank" rel="noindex,nofollow">http://localhost/phpmyadmin</a> pentru validare.</li>
</ol>
<p>Continutul lui <em>httpd-phpmyadmin.conf</em>:</p>
<blockquote><p><em>Alias /phpmyadmin &#8220;C:/wampp/phpmyadmin&#8221;</em></p>
<p><em>&lt;Directory &#8220;C:/wampp/phpmyadmin&#8221;&gt;<br />
Options Indexes FollowSymLinks<br />
AllowOverride None<br />
Order deny,allow<br />
Allow from all<br />
DirectoryIndex index.php</em></p>
<p><em>&lt;IfModule mod_php4.c&gt;<br />
AddType application/x-httpd-php .php</em></p>
<p><em>php_flag magic_quotes_gpc Off<br />
php_flag track_vars On<br />
php_flag register_globals Off<br />
php_value include_path .<br />
&lt;/IfModule&gt;</em></p>
<p><em>&lt;IfModule mod_php5.c&gt;<br />
AddType application/x-httpd-php .php</em></p>
<p><em>php_flag magic_quotes_gpc Off<br />
php_flag track_vars On<br />
php_flag register_globals Off<br />
php_value include_path .<br />
&lt;/IfModule&gt;<br />
&lt;/Directory&gt;</em></p></blockquote>
<p><strong>ATENTIE:</strong>  datorita modului retard prin care WordPress inlocuieste ghilimelele cu niste chestii ce seamana cu ele dar sunt inclinate (practic alte caractere), metoda copy-paste a textului de mai sus nu se preteaza fara o curatare a mizeriilor. Se recomanda download-ul fisierului de la sfarsitul articolului.</p>
<p>Includerea fisierului de mai sus in <em>httpd.conf</em> prespune adaugarea la sfarsitul <em>httpd.conf</em> a:</p>
<blockquote><p><em># Include the phpMyAdmin configuration file<br />
Include conf/extra/httpd-phpmyadmin.conf</em></p></blockquote>
<p>In principiu cam in aceasta consta o instalare de phpMyAdmin. Fisierul de configurare pentru Apache este inspirat de cel din <a href="http://www.debian.org/" title="Debian" target="_blank">Debian</a>, desi are vreo cateva chestii noi in el, si vreo cateva chestii scoase. Atentie: nu incerca chestii gen &#8220;I know better&#8221;, mai ales daca iti vine vreo idee creata sa scoti linia cu &#8220;Allow from all&#8221;. Apache va refuza sa serveasca directorul.Warning-ul din footer, si anume: &#8220;Your PHP MySQL library version 5.0.51a differs from your MySQL server version 5.1.34. This may cause unpredictable behavior.&#8221; se poate ignora. Inca n-am intalnit probleme folosint clientul de MySQL 5.0, si nu, nu am avut timp sau chef sa caut sau sa imi compilez unul pentru MySQL 5.1.Va urma.</p>
<p>Niste imagini pe post de dovezi (in cazul 3.1.5 arata la fel, nu am actualizat si imaginea):</p>
<p align="center"><a href="http://saltwaterc.net/wp-content/uploads/phpmyadmin3-login-window-image.png" title="phpMyAdmin 3 Login Window"><img src="http://saltwaterc.net/wp-content/uploads/phpmyadmin3-login-window-image.thumbnail.png" alt="phpMyAdmin 3 Login Window" /></a><a href="http://saltwaterc.net/wp-content/uploads/phpmyadmin3-logged-in-image.png" title="phpMyAdmin 3 Logged In"><img src="http://saltwaterc.net/wp-content/uploads/phpmyadmin3-logged-in-image.thumbnail.png" alt="phpMyAdmin 3 Logged In" /></a></p>
<h2>Download:</h2>
<p><a href="http://saltwaterc.net/wp-download/wampp/apache_2.2.11-win32-x86-openssl-0.9.8i.msi.zip" title="Apache 2.2.11" target="_blank">apache_2.2.11-win32-x86-openssl-0.9.8i.msi</a> &#8211; installer-ul Apache</p>
<p><a href="http://saltwaterc.net/wp-download/wampp/php-5.2.6-win32-installer.msi.zip" title="PHP 5.2.6" target="_blank">php-5.2.6-win32-installer.msi</a> &#8211; installer-ul PHP</p>
<p><a href="http://saltwaterc.net/wp-download/wampp/mysql-5.1.34-winx64.msi.zip" title="MySQL 5.1 64-bit" target="_blank">mysql-5.1.34-winx64.msi</a> &#8211; installer-ul 64-bit al MySQL</p>
<p><a href="http://saltwaterc.net/wp-download/wampp/mysql-5.1.34-win32.msi.zip" title="MySQL 5.1 32-bit" target="_blank">mysql-5.1.34-win32.msi</a> &#8211; installer-ul 32-bit al MySQL</p>
<p><a href="http://saltwaterc.net/wp-download/wampp/phpMyAdmin-3.1.5-all-languages.zip" title="phpMyAdmin 3.1.5" target="_blank">phpMyAdmin-3.1.5-all-languages.zip</a> &#8211; release-ul de phpMyAdmin</p>
<p><a href="http://saltwaterc.net/wp-download/wampp/httpd-phpmyadmin.zip" title="phpMyAdmin Apache Configuration" target="_blank">httpd-phpmyadmin.conf</a> &#8211; fisierul de configurare al phpMyAdmin ce il foloseste Apache.</p>
<p><a href="http://saltwaterc.net/wp-download/wampp/WAMPP-images.zip" title="WAMPP Images" target="_blank">WAMPP-images.zip</a> &#8211; imaginile folosite pe parcursul articolului</p>
<p>Recomand totusi sursele oficiale pentru fisierele de mai sus. Le-am pus pentru comoditatea unora cu speranta sa nu fie abuzate, in caz contrar, vor fi scoase de la download, sau voi bana pe cei ce le abuzeaza. Inclin totusi catre a doua varianta.</p>
<h2>Documentatie online:</h2>
<p>Apache &#8211; <a href="http://httpd.apache.org/docs/2.2/" title="Apache 2.2 Documentation" target="_blank">http://httpd.apache.org/docs/2.2/</a></p>
<p>PHP &#8211; <a href="http://www.php.net/manual/en/" title="PHP Documentation" target="_blank">http://www.php.net/manual/en/</a></p>
<p>MySQL &#8211; <a href="http://dev.mysql.com/doc/refman/5.1/en/" title="MySQL 5.1 Documentation" target="_blank">http://dev.mysql.com/doc/refman/5.1/en/</a></p>
<h2>Manuale:</h2>
<p>PHP &#8211; <a href="http://www.php.net/download-docs.php" title="PHP Manuals" target="_blank">http://www.php.net/download-docs.php</a></p>
<p>MySQL -  <a href="http://dev.mysql.com/doc/" title="MySQL Manuals" target="_blank">http://dev.mysql.com/doc/</a></p>
<p>Recomand versiunile CHM ale manualelor.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/windows/instalarea-apache-22-php-52-mysql-51-sub-windows.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Write in C</title>
		<link>http://www.saltwaterc.net/programare/write-in-c.html</link>
		<comments>http://www.saltwaterc.net/programare/write-in-c.html#comments</comments>
		<pubDate>Wed, 18 Feb 2009 09:27:00 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programare]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/videos/write-in-c.html</guid>
		<description><![CDATA[If you can see this, then you might need a Flash Player upgrade or you need to install Flash Player if it&#8217;s missing. Get Flash Player from Adobe.&#187; Powered by XHTML Video Embed
Via Misu   &#8230;
]]></description>
			<content:encoded><![CDATA[<p align="center"><object type="application/x-shockwave-flash" style="width:448px;height:386px" data="http://www.youtube.com/v/XHosLhPEN3k&amp;hl=en&amp;fs=1"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="quality" value="best" /><param name="wmode" value="transparent" /><param name="movie" value="http://www.youtube.com/v/XHosLhPEN3k&amp;hl=en&amp;fs=1" /><param name="pluginspage" value="http://www.macromedia.com/go/getflashplayer" />If you can see this, then you might need a Flash Player upgrade or you need to install Flash Player if it&#8217;s missing. Get <a href="http://get.adobe.com/flashplayer/" target="_blank">Flash Player</a> from Adobe.</object><br/><span style='display:block;text-align:left;font-size:xx-small'><a href='http://saltwaterc.net/xhtml-video-embed' target='_blank' title='XHTML Video Embed - Delivers valid XHTML flash content into your WordPress blog'>&raquo; Powered by XHTML Video Embed</a></span></p>
<p>Via Misu <img src='http://www.saltwaterc.net/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' />  &#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/programare/write-in-c.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Geek jokes</title>
		<link>http://www.saltwaterc.net/tech/geek-jokes.html</link>
		<comments>http://www.saltwaterc.net/tech/geek-jokes.html#comments</comments>
		<pubDate>Wed, 04 Feb 2009 11:35:39 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programare]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/tech/geek-jokes.html</guid>
		<description><![CDATA[http://www.kailashnadh.name/docs/geek_jokes/
Cred ca este una dintre cele mai tari colectii de geek jokes &#8230; evident &#8230; nu le poate pricepe oricine &#8230;
]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.kailashnadh.name/docs/geek_jokes/" title="Geek Jokes" target="_blank">http://www.kailashnadh.name/docs/geek_jokes/</a></p>
<p>Cred ca este una dintre cele mai tari colectii de geek jokes &#8230; evident &#8230; nu le poate pricepe oricine &#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/tech/geek-jokes.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pretentii pentru tari bananiere</title>
		<link>http://www.saltwaterc.net/windows/pretentii-pentru-tari-bananiere.html</link>
		<comments>http://www.saltwaterc.net/windows/pretentii-pentru-tari-bananiere.html#comments</comments>
		<pubDate>Tue, 02 Sep 2008 13:29:52 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programare]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/pics/pretentii-pentru-tari-bananiere.html</guid>
		<description><![CDATA[
Bagand niste clice pe blogu&#8217; lu&#8217; necenzurat am dat de imaginea din figura alaturata. Desi imi vine greu sa cred, daca imaginea este pe bune, atunci nu primeaza la categoria penibil prin cerinta in sine, desi intre noi fie vorba, echipa ReactOS se chinuie de ani de zile sa scoata ceva decent si inca mai [...]]]></description>
			<content:encoded><![CDATA[<div style="float: left; margin-right: +10px;"><a title="Stupidity, C++, and the OS" href="http://saltwaterc.net/wp-content/uploads/stupidity.png"><img src="http://saltwaterc.net/wp-content/uploads/stupidity.thumbnail.png" alt="Stupidity, C++, and the OS" /></a></div>
<p>Bagand niste clice pe <a title="necenzurat`s Pandemonium" href="http://blog.w2.ro/" target="_blank">blogu&#8217; lu&#8217; necenzurat</a> am dat de imaginea din figura alaturata. Desi imi vine greu sa cred, <strong>daca imaginea este pe bune</strong>, atunci nu primeaza la categoria penibil prin cerinta in sine, desi intre noi fie vorba, echipa ReactOS se chinuie de ani de zile sa scoata ceva decent si inca mai au de lucru (mult), in timp ce nenea asta cu pretentii pentru oameni locuitori in tara bananiera asteapta ca pentru un buget de 20-100$ sa se aleaga cu un &#8216;Windows&#8217; numa bun pentru vanzare. Failing at failing sau prostie<sup>2</sup>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/windows/pretentii-pentru-tari-bananiere.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Hug a developer</title>
		<link>http://www.saltwaterc.net/programare/hug-a-developer.html</link>
		<comments>http://www.saltwaterc.net/programare/hug-a-developer.html#comments</comments>
		<pubDate>Tue, 02 Sep 2008 12:28:29 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programare]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/videos/hug-a-developer.html</guid>
		<description><![CDATA[Prins in febra programarii fiind, am cautat varii metode de a face embed prin intermediul XHTML Video Embed (da, propriul produs si sunt destul de mandru de cum mi-a iesit) &#8211; dar Blip TV si XVE nu se pupa (si basta). Nu se pupa din vina lor ca eu l-as adauga cu toata placerea. Atat [...]]]></description>
			<content:encoded><![CDATA[<p>Prins in febra programarii fiind, am cautat varii metode de a face embed prin intermediul <a href="http://wordpress.org/extend/plugins/xhtml-video-embed/" title="XHTML Video Embed - WordPress plug-in" target="_blank">XHTML Video Embed</a> (da, propriul produs si sunt destul de mandru de cum mi-a iesit) &#8211; dar Blip TV si XVE nu se pupa (si basta). Nu se pupa din vina lor ca eu l-as adauga cu toata placerea. Atat de tare a fost febra, incat am uitat sa il mai caut si prin alta parte (a se citi YouTube). Pentru toti cei ce se simt si se recunosc &#8230;</p>
<p align="center"><object type="application/x-shockwave-flash" style="width:448px;height:386px" data="http://www.youtube.com/v/SE7gzecA43U&amp;hl=en&amp;fs=1"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="quality" value="best" /><param name="wmode" value="transparent" /><param name="movie" value="http://www.youtube.com/v/SE7gzecA43U&amp;hl=en&amp;fs=1" /><param name="pluginspage" value="http://www.macromedia.com/go/getflashplayer" />If you can see this, then you might need a Flash Player upgrade or you need to install Flash Player if it&#8217;s missing. Get <a href="http://get.adobe.com/flashplayer/" target="_blank">Flash Player</a> from Adobe.</object><br/><span style='display:block;text-align:left;font-size:xx-small'><a href='http://saltwaterc.net/xhtml-video-embed' target='_blank' title='XHTML Video Embed - Delivers valid XHTML flash content into your WordPress blog'>&raquo; Powered by XHTML Video Embed</a></span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/programare/hug-a-developer.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Determinarea corecta a MIME Type in PHP 5</title>
		<link>http://www.saltwaterc.net/linux/determinarea-corecta-a-mime-type-in-php-5.html</link>
		<comments>http://www.saltwaterc.net/linux/determinarea-corecta-a-mime-type-in-php-5.html#comments</comments>
		<pubDate>Tue, 19 Aug 2008 11:46:07 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Programare]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/tech/linux/determinarea-corecta-a-mime-type-in-php-5.html</guid>
		<description><![CDATA[Din start mentionez ca acest mic tutorial este dedicat fisierelor ce au ca directie un host *nix, iar functionalitatea implicita este satisfacuta pentru Ubuntu/Debian. Se poate aplica cu modificarile de rigoare si sub alte distributii. O sa il structurez pe pasi pentru o aplicare mai usoara. Nu am incercat pentru PHP 4, desi majoritatea pasilor [...]]]></description>
			<content:encoded><![CDATA[<p>Din start mentionez ca acest mic tutorial este dedicat fisierelor ce au ca directie un host *nix, iar functionalitatea implicita este satisfacuta pentru Ubuntu/Debian. Se poate aplica cu modificarile de rigoare si sub alte distributii. O sa il structurez pe pasi pentru o aplicare mai usoara. Nu am incercat pentru PHP 4, desi majoritatea pasilor s-ar putea sa fie valabili.</p>
<p><strong>Introducere</strong></p>
<p>Determinarea MIME Type-ului corect pentru un fisier este o problema esentiala. Nu o sa explic si de ce &#8230; daca nu stii de ce, atunci tutorialul acesta iti depaseste nivelul cunostintelor. Atunci cand se face upload la un fisier printr-un form, sau se doreste import-ul unui fisier, se poate intampla ca extensia fisierului sa nu reflecte realitatea sau ca aceasta sa lipseasca cu desavarsire, fapt ce va duce la varii probleme. Array-ul $_FILES ce ia valori in functie de continutul unui form ce are specificat in mod explicit enctype=&#8221;multipart/form-data&#8221; se prea poate sa nu contina valoarea corecta a mime type-ului pentru $_FILES['file_input_name']['type'] deoarece detectia mime-ului cade pe spinarea browserului iar in majoritatea cazurilor acesta se foloseste de extensia fisierului deci va esua in cazurile descrise mai sus. Este nevoie ca informatia sa fie interpretata citind headerele fisierului si folosindu-ne de mime magic.</p>
<p><strong>PECL si fileinfo</strong></p>
<p>Nu o sa imi pierd timpul sa explic ce e PECL. Google este de mare ajutor. Din pacate in repository-urile Ubuntu/Debian, extensia fileinfo nu este disponibila in mod implicit. Din fericire este disponibila prin intermediul PECL. Acum incepe treaba sa fie paroasa.</p>
<p>In primul rand, este nevoie de una bucata compilator. Exista un pachet ce le face pe toate, deci:</p>
<blockquote><p>sudo apt-get install build-essential</p></blockquote>
<p>Bun. Avem compilator, avem PECL (presupun, daca n-ai HTTP server si PHP &#8211; citesti degeaba). Pentru build-ul fileinfo mai este nevoie de pachete de development, deci:</p>
<blockquote><p>sudo apt-get install libmagic-dev php5-dev</p></blockquote>
<p>ce va instala headerele de development pentru libmagic, phpize si alte chestii. Faceti acum, sau regretati mai tarziu. Acum este timpul sa compilam extensia fileinfo folosind pecl:</p>
<blockquote><p>sudo pecl install fileinfo</p></blockquote>
<p>Daca maraie vreo eroare la configure, instalati pachetul de development aferent (pentru cei somnorosi, are sufixul -dev). Daca maraie vreo eroare la compile, imi pare rau, nu va pot ajuta. Pe masina de devel a functionat fara probleme. Daca nu maraie nici o eroare, ar trebui sa indice faptul ca extensia a fost instalata cu succes. Ar trebui sa fie ceva de genul:</p>
<blockquote><p>Build process completed successfully<br />
Installing &#8216;/usr/lib/php5/20060613+lfs/fileinfo.so&#8217;<br />
install ok: channel://<a href="http://pear.php.net/Fileinfo-1.0.4" class="linkification-ext" title="Linkification: http://pear.php.net/Fileinfo-1.0.4">pear.php.net/Fileinfo-1.0.4</a></p></blockquote>
<p>Daca ati ajuns pana aici, mai este putin si usor. Extensiile instalate prin intermediul PECL nu sunt incarcate in mod automat, spre deosebire de cele instalate din repository-urile Ubuntu/Debian folosind apt-get sau alternativa (cu mici exceptii, spre exemplu mcrypt.so trebuie incarcat in mod explicit &#8211; nenea maintainer a fost cascat). Pentru a mentine ideea si spiritul Debian, incarcarea modulului se va face folosind directorul de fisiere alternative de configurare pentru PHP. Tastati urmatoarele chestii intr-un terminal (da stiu, copy-paste e mai comod):</p>
<blockquote><p>cd /etc/php5/conf.d/; sudo touch fileinfo.ini; sudo nano fileinfo.ini</p></blockquote>
<p>Bagati urmatoarea linie in acel fisier:</p>
<blockquote><p>extension=fileinfo.so</p></blockquote>
<p>dupa care salvati cu Ctrl+O. Inchideti editorul text folosind Ctrl+X. Nu, nu sunt vim maniac, sa nu aud de el. Acum este timpul sa se dea restart la HTTP server pentru a incarca noua configuratie. Ar trebui sa fie valabil si pentru cei cu GCI/FastCGI (eventual alt HTTP server gen lighttpd), desi subsemnatul e de ala cu Apache 2+PHP5 handler, deci in cazul meu (si al majoritatii):</p>
<blockquote><p>sudo /etc/init.d/apache2  reload</p></blockquote>
<p>ce va duce la un graceful restart (aka restart fara downtime) urmat de incarcarea noilor fisiere de configurare. Daca totul e ok, noul modul de PHP ar trebui sa fie incarcat. phpinfo(); ar trebui sa indice acest fapt, atat in lista de fisiere de configurare alternative (cele din /etc/php5/conf.d) cat si prin faptul ca ar trebui sa indice pe undeva in mod explicit faptul ca fileinfo este incarcata.</p>
<p><strong>Utilizarea fileinfo pentru a afla MIME Type</strong></p>
<p>Acum sa trecem la lucruri grele. fileinfo contine niste functii smechere asemanatoare cu fopen. Pentru ubergeeks exista modul orientat obiect de lucru cu ele (<a href="http://www.php.net/finfo_open" title="finfo_open manual" target="_blank">php.net/finfo_open</a> explica), dar subsemnatul se multumeste cu trei apeluri procedurale din moment ce nu exista nici un avantaj real in cazul de fata pentru a defini un obiect si a-l distruge dupa ce se afla mime-ul. Pentru cei dornici sa isi implementeze o clasa proprie &#8230; este alta poveste. Eu mi-am facut o functie custom ce am inclus-o in API-ul central ce primeste ca parametru calea fisierului si imi returneaza mime-ul in caz de succes sau un cod de eroare pentru debug in caz de esuare. Miezul problemei sta in:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$finfo</span><span style="color: #339933;">=</span><span style="color: #990000;">finfo_open</span><span style="color: #009900;">&#40;</span>FILEINFO_MIME<span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;/usr/share/misc/magic&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$finfo</span><span style="color: #009900;">&#41;</span>
	<span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Can't open the fileinfo database.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$mime</span><span style="color: #339933;">=</span><span style="color: #990000;">finfo_file</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$finfo</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fileName</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">finfo_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$finfo</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Si cam atat. Succes si spor la treaba.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/linux/determinarea-corecta-a-mime-type-in-php-5.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Design Coding</title>
		<link>http://www.saltwaterc.net/programare/design-coding.html</link>
		<comments>http://www.saltwaterc.net/programare/design-coding.html#comments</comments>
		<pubDate>Fri, 18 Jul 2008 07:38:23 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programare]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/videos/design-coding.html</guid>
		<description><![CDATA[This is how you do it &#8230; G-yeah &#8230;
If you can see this, then you might need a Flash Player upgrade or you need to install Flash Player if it&#8217;s missing. Get Flash Player from Adobe.&#187; Powered by XHTML Video Embed
]]></description>
			<content:encoded><![CDATA[<p>This is how you do it &#8230; G-yeah &#8230;</p>
<p align="center"><object type="application/x-shockwave-flash" style="width:448px;height:386px" data="http://www.youtube.com/v/a0qMe7Z3EYg&amp;hl=en&amp;fs=1"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="quality" value="best" /><param name="wmode" value="transparent" /><param name="movie" value="http://www.youtube.com/v/a0qMe7Z3EYg&amp;hl=en&amp;fs=1" /><param name="pluginspage" value="http://www.macromedia.com/go/getflashplayer" />If you can see this, then you might need a Flash Player upgrade or you need to install Flash Player if it&#8217;s missing. Get <a href="http://get.adobe.com/flashplayer/" target="_blank">Flash Player</a> from Adobe.</object><br/><span style='display:block;text-align:left;font-size:xx-small'><a href='http://saltwaterc.net/xhtml-video-embed' target='_blank' title='XHTML Video Embed - Delivers valid XHTML flash content into your WordPress blog'>&raquo; Powered by XHTML Video Embed</a></span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/programare/design-coding.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FLV Player in Flash</title>
		<link>http://www.saltwaterc.net/programare/flv-player-in-flash.html</link>
		<comments>http://www.saltwaterc.net/programare/flv-player-in-flash.html#comments</comments>
		<pubDate>Sun, 15 Jun 2008 09:27:34 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programare]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/programare/flv-player-in-flash.html</guid>
		<description><![CDATA[Am cautat suficient de mult solutii pentru aceasta problema. Pana la urma JW FLV MEDIA PLAYER s-a dovedit a fi solutia potrivita, chiar daca are o licenta restrictiva. Prin licenta restrictiva se intelege faptul ca desi este Open Source, nu este Free Software, in sensul ca pentru uz comercial se percep taxe. Cu notificarile de [...]]]></description>
			<content:encoded><![CDATA[<p>Am cautat suficient de mult solutii pentru aceasta problema. Pana la urma <a href="http://www.jeroenwijering.com/?item=JW_FLV_Player" title="JW FLV MEDIA PLAYER" target="_blank">JW FLV MEDIA PLAYER</a> s-a dovedit a fi solutia potrivita, chiar daca are o licenta restrictiva. Prin licenta restrictiva se intelege faptul ca desi este Open Source, nu este Free Software, in sensul ca pentru uz comercial se percep taxe. Cu notificarile de rigoare, l-am introdus in XVE, desi nu sunt fericit asupra acestui aspect, plug-in-ul subsemnatului fiind free pentru uz comercial (libertatea nu presupune comercializarea lui ci doar utilizarea lui). Solutia a aparut dupa un Google Search &#8230; Se numeste (sec) FLV Player, este disponibil la adresa aceasta: <a href="http://flv-player.net/" title="FLV Player" target="_blank">http://flv-player.net/</a> &#8211; iar functiile sunt echivalente, chiar daca unele lipsesc. Cele ce lipsesc, nu sunt resimtite de marea majoritate a celor ce ar avea nevoie de o astfel de integrare. In curand va aparea pe ecranele XHTML Video Embed.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/programare/flv-player-in-flash.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>XHTML Video Embed v0.3</title>
		<link>http://www.saltwaterc.net/programare/xhtml-video-embed-v03.html</link>
		<comments>http://www.saltwaterc.net/programare/xhtml-video-embed-v03.html#comments</comments>
		<pubDate>Sun, 08 Jun 2008 12:37:06 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programare]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/programare/xhtml-video-embed-v03.html</guid>
		<description><![CDATA[XHTML Video Embed a ajuns la versiunea 0.3. Dupa doua luni in care mai mult taras-grapis am scris si implementat noi chestii, mi-am rupt un weekend din timpul subsemnatului si am finalizat aceasta versiune. Aduce in plus:

suport pentru Jumpcut.
suport pentru a face override la dimensiunile unificate folosind parametri speciali in structura tag-ului.
localizare in engleza si [...]]]></description>
			<content:encoded><![CDATA[<p>XHTML Video Embed a ajuns la versiunea 0.3. Dupa doua luni in care mai mult taras-grapis am scris si implementat noi chestii, mi-am rupt un weekend din timpul subsemnatului si am finalizat aceasta versiune. Aduce in plus:</p>
<ul>
<li>suport pentru Jumpcut.</li>
<li>suport pentru a face override la dimensiunile unificate folosind parametri speciali in structura tag-ului.</li>
<li>localizare in engleza si romana. Pentru alte limbi o sa am nevoie de voluntari.</li>
<li>suport pentru videoclipurile high definition de pe YouTube.</li>
<li>introducerea suportului pentru FLV embedding ce a aparut in branch-ul 0.2.4.x dupa ce dezvoltarea acestei versiuni a inceput.</li>
<li>design complet nou al aplicatiei. Nu, nu ma refer la interfata ci la modul in care lucreaza. Partea publica a plug-in-ului a fost puternic optimizata deoarece modelul de dezvoltare din v0.1.x/v0.2.x incepuse sa puna probleme. Desi admin-panel-ul poate fi mai lent decat cel din versiunile anterioare, acesta este generat complet dinamic, deci adaugarea unui serviciu nou presupune foarte putin lucru.</li>
<li>securizare mai buna a anumitor componente.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/programare/xhtml-video-embed-v03.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ID-uri numerice curate in PHP</title>
		<link>http://www.saltwaterc.net/programare/id-uri-numerice-curate-in-php.html</link>
		<comments>http://www.saltwaterc.net/programare/id-uri-numerice-curate-in-php.html#comments</comments>
		<pubDate>Tue, 25 Mar 2008 22:15:44 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programare]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/programare/id-uri-numerice-curate-in-php.html</guid>
		<description><![CDATA[Adesea m-am lovit de problema sanitizarii variabilelor care provin din input, si nu zic asta facand referire la PHP, ci la programare in general. Din moment ce am avut boala sa studiez catusi de cat bazele securitatii, mi-a ramas in cap un principiu foarte bine formulat: &#8220;all user input is evil!&#8221;. Adevarat grait. Deci am [...]]]></description>
			<content:encoded><![CDATA[<p>Adesea m-am lovit de problema sanitizarii variabilelor care provin din input, si nu zic asta facand referire la PHP, ci la programare in general. Din moment ce am avut boala sa studiez catusi de cat bazele securitatii, mi-a ramas in cap un principiu foarte bine formulat: &#8220;all user input is evil!&#8221;. Adevarat grait. Deci am inceput sa gandesc aplicatiile dupa metoda user proof. In primul rand cand testez ceva nou, nu testez dupa cum ar trebui sa fie utilizata aplicatia in mod corect, ci cum NU ar trebui sa fie folosita, si ce sa se intample in acele cazuri. In primul rand pentru ca o aplicatie nu este o chestie democratica unde userul face ce vrea el si adesea face prost. Deasemenea intervine si cealata extrema. Unde nu este prostie &#8211; este viclenie &#8211; deci se poate trezi cate un h4&#215;0r de asta cu mai mult timp liber la dispozitie sa te caute la oo (a se citi: securizare).</p>
<p>Problema ID-urilor numerice in PHP desi este una destul de banala, rezolvarea este multipla. De-alungul timpului am testat mai multe chestii, dar doar recent am ajuns la o forma finala care sa ma multumeasca deplin. De ce ID-uri numerice? Pentru ca este foarte usor de lucrat cu ele cand se interactioneaza cu o baza de date. Orice tabela care trebuie sa stocheze in mod unic niste chestii, are o cheie primara. Pana acum cea mai desteapta chestie in materie de chei primare este cheia intreaga care se seteaza cu auto-increment &#8211; ceea ce asigura complet unicitatea datelor. Recomandarea ar fi ca auto incrementul sa inceapa de la 0 (chestia asta o sa se lege de ce o sa zic mai jos). Bonus ar fi faptul ca fiecare tabela de acest gen ar trebui sa aiba cheia primara indexata pentru a reduce considerabil timpul de cautare al ei.</p>
<p>Adesea aceste chei primare din baza de date sunt trimise prin intermediul requesturilor de tip GET, deci se vor regasi in componenta URL-ului. Problema se pune atunci cand pe langa acel ID numeric, utilizatorul (in mod intentionat) introduce si altceva pe langa acel ID. Treaba poate sa se imputa de la XSS (Cross Site Scripting) &#8211; atunci cand acea cheie se regaseste in pagina, sau la atacuri de tip <a href="http://en.wikipedia.org/wiki/SQL_injection" title="SQL injection" target="_blank">SQL injection</a> (mai grav).</p>
<p>Desi exista functii native in suportul de MySQL pentru PHP, acestea sunt destul de triste la ID-uri numerice, deci am preferat propria metoda:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> clean_id<span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
<span style="color: #000088;">$id</span><span style="color: #339933;">=</span><span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;@[^0-9]@&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #000088;">$id</span><span style="color: #339933;">=</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">return</span> <span style="color: #000088;">$id</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Chestia asta de mai sus face vreo doua chestii &#8230; prima este aceea ca da strip la tot inputul care nu e numeric. A doua verifica ce a mai ramas, iar daca are valoarea 0 (orice 0 din PHP), atunci returneaza un 0 numeric. Este important acest zero numeric &#8230; ziceam ceva mai sus de el &#8230; acest zero numeric are grija ca interogarea sa nu dea de o chestie gen &lt;&lt;WHERE id=&#8221;&gt;&gt; si sa bubuie o eroare de SQL (care in anumite cazuri &#8230; ar putea la randul ei sa divulge alte chestii).</p>
<p><strong>Actualizare:</strong></p>
<p>Datorita observatiei lui <em>AgLiAn</em> am ajuns la concluzia ca functia mea initiala nu rezolva o problema: interger overflow, chestie ce mai departe se traduce in interpretarea ca float de catre PHP &#8211; si de unde pot aparea alte probleme. Si pentru ca am mentionat pe undeva mai sus de auto-increment (si acest obicei nu o sa se transforme peste noapte pana la proba contrara ce demonstreaza un obicei prost), functia clean_id(); devine:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> clean_id<span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
<span style="color: #b1b100;">return</span> <span style="color: #990000;">abs</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">intval</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/programare/id-uri-numerice-curate-in-php.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>iif() in PHP</title>
		<link>http://www.saltwaterc.net/programare/iif-in-php.html</link>
		<comments>http://www.saltwaterc.net/programare/iif-in-php.html#comments</comments>
		<pubDate>Tue, 26 Feb 2008 12:52:28 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programare]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/programare/iif-in-php.html</guid>
		<description><![CDATA[Se intampla ca anumite constructii pretentioase sa aiba nevoie de o selectie &#8230; Problema care se pune este sa se scrie cat mai putin cod pentru rezolvarea problemei respective. Deci exista operatiile ternare care pot fi facute si de catre o functie. In mod normal ar fi o chestie gen:

if &#40;$expression==true&#41;
	$var=&#34;value&#34;;
else
	$var=&#34;other_value&#34;;

Am gasit o abordare diferita [...]]]></description>
			<content:encoded><![CDATA[<p>Se intampla ca anumite constructii pretentioase sa aiba nevoie de o selectie &#8230; Problema care se pune este sa se scrie cat mai putin cod pentru rezolvarea problemei respective. Deci exista operatiile ternare care pot fi facute si de catre o functie. In mod normal ar fi o chestie gen:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$expression</span><span style="color: #339933;">==</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span>
	<span style="color: #000088;">$var</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;value&quot;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">else</span>
	<span style="color: #000088;">$var</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;other_value&quot;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Am gasit o abordare diferita a problemei operatiilor ternare (chestie care o folosesc de o buna bucata de timp), si anume operatia ternara:</p>
<php lang="php">$var=($expression==true) ? &#8220;value&#8221; : &#8220;other_value&#8221;;<br />
care poate fi concatenata intr-un string, sau utilizata intr-o variabila. Problema este ca imi cam rup degetele cu aceasta scriere (nu prea folosesc ? si : cand codez PHP), deci am gasit o implementare de <a href="http://en.wikipedia.org/wiki/IIf" title="iif()" target="_blank">iif()</a> in PHP. De fapt doua. Prima abordare se bazeaza chiar pe translatarea operatiei ternare:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> iif<span style="color: #009900;">&#40;</span><span style="color: #000088;">$expression</span><span style="color: #339933;">,</span> <span style="color: #000088;">$returntrue</span><span style="color: #339933;">,</span> <span style="color: #000088;">$returnfalse</span><span style="color: #339933;">=</span><span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
<span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$expression</span> ? <span style="color: #000088;">$returntrue</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$returnfalse</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Desi este o abordare destul de interesanta, are mici probleme, si anume faptul ca se evalueaza toate argumentele inainte de executie, iar daca $returntrue si $returnfalse sunt rezultate ale altor functii, se itampla sa apara rezultate neasteptate in practica deoarece operatorul ? poate sa scurtcircuiteze evaluarea.</p>
<p>A doua abordare, aia pe care o folosesc, este urmatoarea:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> iif<span style="color: #009900;">&#40;</span><span style="color: #000088;">$expression</span><span style="color: #339933;">,</span> <span style="color: #000088;">$returntrue</span><span style="color: #339933;">,</span> <span style="color: #000088;">$returnfalse</span><span style="color: #339933;">=</span><span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$expression</span><span style="color: #009900;">&#41;</span>
	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$returntrue</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">else</span>
	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$returnfalse</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Dupa niste RTFM am ajuns la concluzia ca tot a doua abordare este mai buna, chiar daca este mai putin eleganta, si se obtine cod ceva mai scurt si mai putin alambicat, mai ales cand vine vorba de interogari SQL cu grad mare de nesimtire.</php>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/programare/iif-in-php.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>301 redirect fara .htaccess si mod_rewrite</title>
		<link>http://www.saltwaterc.net/programare/301-redirect-fara-htaccess-si-mod_rewrite.html</link>
		<comments>http://www.saltwaterc.net/programare/301-redirect-fara-htaccess-si-mod_rewrite.html#comments</comments>
		<pubDate>Wed, 20 Feb 2008 14:50:40 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programare]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/programare/301-redirect-fara-htaccess-si-mod_rewrite.html</guid>
		<description><![CDATA[Arata cam asa (in PHP, pentru alte limbaje nu ma ostenesc):

if &#40; &#40; !preg_match &#40; &#34;@www@i&#34;, $_SERVER&#91;'HTTP_HOST'&#93; &#41; &#41; &#38;amp;&#38;amp; &#40; preg_match &#40; &#34;@example\.com@i&#34;, $_SERVER&#91;'HTTP_HOST'&#93; &#41; &#41; &#41;
&#123;
$_urlHead = &#40; isset&#40; $_SERVER&#91;'HTTPS'&#93; &#41; &#38;amp;&#38;amp; strtolower &#40; $_SERVER&#91;'HTTPS'&#93; &#41; == 'on' &#41; ? &#34;https://www.&#34; : &#34;http://www.&#34;;
$_redirURL=$_urlHead . $_SERVER&#91;'HTTP_HOST'&#93; . $_SERVER&#91;'REQUEST_URI'&#93;;
header &#40; &#34;HTTP/1.1 301 Moved Permanently&#34; &#41;;
header [...]]]></description>
			<content:encoded><![CDATA[<p>Arata cam asa (in PHP, pentru alte limbaje nu ma ostenesc):</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #990000;">preg_match</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;@www@i&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_HOST'</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;&amp;</span>amp<span style="color: #339933;">;</span> <span style="color: #009900;">&#40;</span> <span style="color: #990000;">preg_match</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;@example\.com@i&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_HOST'</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
<span style="color: #000088;">$_urlHead</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span> <span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTPS'</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;&amp;</span>amp<span style="color: #339933;">;</span> <span style="color: #990000;">strtolower</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTPS'</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'on'</span> <span style="color: #009900;">&#41;</span> ? <span style="color: #0000ff;">&quot;https://www.&quot;</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;http://www.&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$_redirURL</span><span style="color: #339933;">=</span><span style="color: #000088;">$_urlHead</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_HOST'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'REQUEST_URI'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">header</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;HTTP/1.1 301 Moved Permanently&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">header</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;Location: <span style="color: #006699; font-weight: bold;">$_redirURL</span>&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Initial eram ceva mai recalcitrant in ceea ce priveste manaritul prin .htaccess, dar chiar si fara a fi, mai exista cate un server de pe vremea lui Nae ce nu vrea sa te lase nene sa il stresezi cu astfel de directive.</p>
<p><strong>Explicatii:</strong> if-ul asta smecher verifica daca exista www in HTTP_HOST care se modeleaza in functie de request. Adica daca folosesc saltwaterc.net atunci HTTP_HOST=saltwaterc.net, daca folosesc www.saltwaterc.net atunci HTTP_HOST=www.saltwaterc.net, iar daca scot din buzunar un port magic si serverul asculta sa zicem pe 8080 deci requestul se face pe saltwaterc.net:8080 atunci evident, nu mai tre sa zic care este HTTP_HOST-ul pentru ca este clar. A doua verificare se face in functie de un nume de domeniu, si anume ala pe care se va hosta scriptul. Nu este necesara, dar este utila pentru serverele de development care cel mai adesea sunt hostate local si nu prezinta www. Redirectionarea se face compunand &#8220;manual&#8221; URL-ul de redirect si trebuie avut grija ca acel www sa fie acolo. REQUEST_URI-ul are grija sa tina minte ce s-a bagat in bara de adresa dupa HTTP_HOST, deci redirectionarea se face la sigur. Smecheria aia cu HTTPS are grija ca in cazul in care se folosesc conexiuni criptate, redirectionarea sa fie facuta corect tot catre o conexiune criptata.</p>
<p><strong>Unde trebuie adaugat:</strong> inainte de a se face orice fel de output cand se executa scriptul. Daca s-a trimis output catre browser, nu se mai poate drege busuiocul deoarece e o limitare a protocolului HTTP de a nu mai putea trimite headere dupa output.</p>
<p><strong>Solutia inversa &#8211; www to no-www:</strong> avand in vedere cele zise mai sus, este de-a dreptul triviala &#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span> <span style="color: #990000;">preg_match</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;@www@i&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_HOST'</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
<span style="color: #000088;">$_urlHead</span><span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span> <span style="color: #990000;">isset</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTPS'</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;&amp;</span>amp<span style="color: #339933;">;</span> <span style="color: #990000;">strtolower</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTPS'</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'on'</span> <span style="color: #009900;">&#41;</span> ? <span style="color: #0000ff;">&quot;https://&quot;</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;http://&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$_redirURL</span><span style="color: #339933;">=</span><span style="color: #000088;">$_urlHead</span> <span style="color: #339933;">.</span> <span style="color: #990000;">preg_replace</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;@www\.@i&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_HOST'</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'REQUEST_URI'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;HTTP/1.1 301 Moved Permanently&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Location: <span style="color: #006699; font-weight: bold;">$_redirURL</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Se observa cu usurinta ca dispare particula dedicata platformei de development &#8230; nu mai este nevoie de asa ceva din motivul pomenit mai sus.</p>
<p>PS: de mod_rewrite nu e nevoie pentru a face un 301, dar e nevoie pentru smecherii cu CNAME si alte avioane. Adica ce ziceam mai sus, dar pe alta limba. Am scos aberatiile scrise pe acilea prin articol a.k.a. de pe vremea cand eram mic si prost.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/programare/301-redirect-fara-htaccess-si-mod_rewrite.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>XHTML Video Embed</title>
		<link>http://www.saltwaterc.net/programare/xhtml-video-embed.html</link>
		<comments>http://www.saltwaterc.net/programare/xhtml-video-embed.html#comments</comments>
		<pubDate>Sun, 03 Feb 2008 17:35:53 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programare]]></category>

		<guid isPermaLink="false">http://saltwaterc.net/programare/xhtml-video-embed.html</guid>
		<description><![CDATA[Mai trantesc un post in aceasta categorie pentru a anunta poporul ca am comis-o si la capitolul pluginuri WordPress. Idei aveam si inca mai am, intentii aveam si inca mai am, la capitolul timp stau mai prost. Am trantit acest plugin din motive deja pomenite: absenta unor solutii care sa ma multumeasca, deci in loc [...]]]></description>
			<content:encoded><![CDATA[<p>Mai trantesc un post in aceasta categorie pentru a anunta poporul ca am comis-o si la capitolul pluginuri WordPress. Idei aveam si inca mai am, intentii aveam si inca mai am, la capitolul timp stau mai prost. Am trantit acest plugin din motive deja pomenite: absenta unor solutii care sa ma multumeasca, deci in loc sa ma plang, am luat atitudine si am rezolvat problema. Oricum, deschid un drum cu acest proiect, si sper ca voi mai gasi timp si pentru altele la fel de utile pe care le am in plan.</p>
<p>PS: din moment ce acest weekend l-am dedicat programarii (da, inca nu mi-a trecut boala complet, deci nici vorba de iesit/iesit la bere/etc.) in seara aceasta o sa pun si o versiune noua de WLMP custom &#8211; update-uri la pachetele continute si diverse imbunatatiri.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.net/programare/xhtml-video-embed.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
