This blog is NOFOLLOW Free!






Flash-ul lui Adobe și Windows-ul meu Mobile

TRACK TOP
Filed in Rant, Tech.
8 comments filed

Update: am corectat puțin articolul în urma dialogului avut mai jos prin comentarii. Pe scurt, am calmat tonul frustrat abordat inițial, făra a altera complet forma inițială. Nu mai există sentimentul inițial pe care l-am avut atunci când am scris rândurile de mai jos. Până la urmă cei ce se ocupă de partea de comunicare din partea companiei Adobe își iau salariul pe merit din moment ce își “pierd” timpul cu un blog de buzunar ca al meu. Cu toate acestea, aștept rezultatele. Momentan discuția de mai jos rămâne la stadiul de vorbărie, iar eu ca programator nu cred în vorbe ci în software funcțional. De altfel pot trăi fără jocuri Flash pe telefon. Nu intru în sevraj în absența lor. De fapt nu mă joc pe telefon. Afirmația dădea doar o notă de dramatism situației expuse. Experiența web folosind PocketIE, Opera Mobile plus versiunea mobilă a Firefox (codename: Fennec, momentan Alpha stage) lasă de dorit în continuare în unele situații bine determinate unde o mână de CSS + (X)HTML nu pot compensa absența Flash Player. Urarea de la sfârșit rămâne. Înafară de Windows, Flash (încă?) e jale sau nu este deloc.

Era destul de evident faptul că va urma o replică de-a subsemnatului la adresa nesimțirii celor de la Adobe legată de lipsa Flash Player pe iPad. De altfel, ideea a mai fost discutată și de către Cătălin Nicolescu, dar eu iau o abordare diferită a problemei. Doar nu o să mă apuc să fac ‘rant’ pe aceeași temă.

Replica mea către Adobe ar fi: păi bine mă ipocriților, de ce nu plăngeți de faptul că eu pe Windows Mobile n-am Flash Player? Știu că există Flash Lite, dar eu nu l-am văzut rulând pe HTC-ul meu, ce apropo, Ș.T.I.E. multitasking, ca să fac referire și la produsul Apple ce nu mă interesează, dar care a generat discuția. Dacă vă doare atât de mult experiența utilizatorilor a unui X-produs pe web datorita produsului vostru proprietar, de ce nu văd un CAB pus la download ca să pot vedea și eu cum merge fleșul în PocketIE sau Opera Mobile? Sau să mă joc jocuri în fleș?

Nu e nici o diferență între ceea ce face Apple și ceea ce face Adobe. Adobe sunt totuși mai ipocriți. Ca să mă citez: același căcat împachetat altfel. Îi urez Flash-ului ce i-am urat acum câțiva ani: o deschidere mai mare spre platforme diferite, sau o moarte rapidă și foarte dureroasă.


Firebug 1.5 + Firefox 3.5.7 + Ubuntu Hardy amd64

TRACK TOP
Filed in Linux, Programare, Rant.
2 comments filed

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 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.

Soluția de moment: downgrade la Firebug 1.4: http://getfirebug.com/releases/firebug/1.4/

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.

Dragă programatorule, dacă îți vine a copy-paste, fă refactor!

TRACK TOP
Filed in Programare, Rant.
4 comments filed

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 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.

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 … touche: “Ce-ai zis mă? Să copiezi?”. Exact ce ziceam mai sus … 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ă.

În concluzie vreo câteva idei, departe de a oferi o imagine completă:

  • 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.
  • o arhitectură bună, modulară, a aplicației, DRY (și preferabil KISS) 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.
  • dacă acea parte de ‘unknown’ 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ă.
  • 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.
  • refactor, OOP, clase, interfețe, ‘design pattern’ (exemplu: singleton) ar trebui să nu fie doar cuvinte într-un vocabular de specialitate.

Importanța unui PHP framework bine scris

TRACK TOP
Filed in PHP, Programare, Securitate.
No comments yet. Be the first to comment!

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ă de baza de date. Iar pentru chestii riscante, chiar o filtrare XSS cu HTML Purifier, o bibliotecă a cărui filtru XSS a fost creat să treacă de XSS (Cross Site Scripting) Cheat Sheet.

Știu, nu vreau să fac “carieră” din astfel de post-uri pe blog și nu prea cred că o să mă vedeți vreodată să trimit chestii către http://hackersblog.org/. 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 ‘junk’-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.

Povestea începe de la faptul că am avut o mică discuție cu necenzurat 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.

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.

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.

Momentan nu dăm poze, așteptăm să aplice patch-ul trimis :).

PHP sub Windows, Zend Server, WinCache și un cluster FastCGI cu Process Manager

TRACK TOP
Filed in PHP, Programare, Windows.
3 comments filed

La GeekMeet-ul din Octombrie de la Sibiu, Todi Pruteanu ne zicea printre altele despre WinCache - 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 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 ‘closed source’ de la Zend, ZendOptimizer+ alăruri de Zend Data Cache 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, ‘Zend Enabler for Apache’ 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.

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 ’round robin load balance’. Tehnic vorbind - se poate. Dincolo de un simplu FastCGI wrapper cum este spawn-fcgi, proiect de casă al lighttpd, a apărut o versiune nativă de Windows pe forurile respective. De curiozitate am luat sursa, 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 … #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.

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 ‘thread safety’, iar clusterul poate să facă uz de o arhitectură SMP, fără a apela la threading.

Acum poate apare întrebarea: de ce mai multe procese FastCGI pentru a procesa scripturile PHP? În primul rând practica ne invață că un ’segmentation fault’ 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 ‘environment variables’, ș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 întâmplător ș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 ‘tutorialele’ de PHP FastCGI sub Windows unde ‘php-cgi.exe -b 127.0.0.1:9000′ 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.

Bun, acum am pus bazele ideei despre cum ar trebui făcut un Process Manager. Una dintre probleme este acel ‘race condition’: 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 - primul, la cererea 1998 - al doilea, la cererea 1999 - al treilea, la cererea 2000 - 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 :). Ziceam și pe Twitter: De ce nu există un PHP - FastCGI Process Manager sub Windows? Pentru că nimeni nu și-a dat interesul să scrie unul. Posibilităti există!

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 - 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 chestie compatibilă PHP 5.3.x 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.

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 - 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.

Actualizare de Virtualbox. Acum ce? Management de procese? Reboot!

TRACK TOP
Filed in Linux, Virtualizare, Windows.
No comments yet. Be the first to comment!

Băieții aceștia faini de la Sun Microsystems au ‘ghiara’ pe VirtualBox de la băieții de la Innotek. Vremuri istorice tulburi cu un produs mediocru. Între timp Sun-ul a băgat camionul de dolari în proiect și a început să se distingă din mulțime printr-un backend foarte puternic. Pe subsemnatul l-a convins să renunțe la VMware Server pentru acele ’server consolidation deployment’ ce mai apărea prin rețelele locale pe unde operez. Tot istoric vorbind, pentru Windows se distribuiau două pachete, unul pentru x86 și unul pentru x86-64. În prezent se distribuie unul singur ce se instalează în funcție de contextul platformei.

Bun. La partea cu instalarea îmi doream să ajung. Mai bine zis la partea cu actualizarea. De regulă pe un Ubuntu Server ce mai rulează servicii mici/medii VirtualBox are bunul simț să ruleze în background ca daemon printr-un simplu init script. În concluzie actualizările le fac atunci când îmi mai aduc aminte să deschid interfața grafică. Sub Windows în schimb este o jucărie unde mai testez ultimele apariții în domeniul OS. Dar aici mă lovesc suficient de des de acea fereastră ce mă anunță faptul că a apărut o nouă versiune. Click - download  - next, next, next … gata. În teorie era gata. În practică 3.0.12, adică ultima versiune, refuză să adauge orice fel de HDD virtual nou și am o mică bănuială despre imposibilitatea de a adăuga noi mașini virtuale.

Mă apuc să lucrez în calculator să văd ce se întâmplă (doctore). Cretinătatea aceea de installer nu a închis VBoxSVC înainte de instalare. Adică acel serviciu ad-hoc din arhitectura VirtualBox ce se ocupă de mașinile virtuale atâta timp cât rulează cel puțin una. În mod normal stă închis acel proces. Ridicolul merge mai departe. Acel proces, VBoxSVC dă un ‘lock’ exclusiv pe fișierele de configurare astfel încât să nu apară chestia aceea numită ‘race condition’ în geek language. Iar acel proces nu mai vrea să moară. Task Manager-ul e inutil ca de obicei la omorât procese încăpățânate. Am scos artileria grea: Advanced Process Termination (APT). Pe lângă o duzină de metode de kill, știe două metode de kernel kill și încă două de crash kill. Kernel kill pe Windows 7 x64 nu are suport. Nu mi-am spart capul cu hack-ul de OS. Din păcate metodele din user mode au dat greș. Windows încă e copil mic și udă patul atunci când vine vorba de procese încăpățânate. Sistemele UNIX-like (ex: Linux, FreeBSD) rămân în situația penibilă de mai sus atunci când un proces rămâne blocat în ‘IO wait state & friends’. Soluția este evidentă: reboot. Dar m-am cam săturat să rămân cu procese blocate pentru ca Windows e rebut la management-ul lor din ‘user mode’. Iar VirtualBox e rebut la actualizare și nu își știe închide serviciul înainte de un nou ‘deploy’. În mod curios, procesul blocat nu apare în APT. Dar APT are o jucărie numită ‘Custom PID’ pentru a da kill după kill.

Agile OpenSpace la Cluj, Scrum și Software Craftsmanship - Code retreat

TRACK TOP
Filed in Programare.
No comments yet. Be the first to comment!

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 ‘agiliza’. Deși inițial s-ar fi anunțat mai multă lume, prezența clujeană a fost destul de restrânsă - 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 ‘moca’. Cei ce au ajuns totuși, în ordinea în care au stat la masă și s-au prezentat:

- Mihai Brehar

- Maria Diaconu

- Aici ar trebui să am un nume, dar am un lapsus în schimb

- Ovidiu Negrean

- Ciprian Stăvar

- Ștefan Rusu (adică subsemnatu’)

- Alex Bolboacă

- Paul Nagy

- Jurgen Appelo

Î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:

- 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.

- 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ă - de unde și povestea cu velocity points. Pe de altă parte acele velocity points sunt valabile pentru o echipă. Schimbi oameni din echipă - ai altă echipă. Ajungem la filosofia Agile - oameni, nu unelte, dar despre asta era vorba în primul rând, nu?

- pentru cei ce vor să estimeze task-urile în timp, Paul a fost ferm: ‘am o veste proastă pentru dezvoltatori - nu puteți’. Se leagă de povestea de mai sus.

-  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 :)), iar Paul a vorbit despre metoda cărților de poker.

- 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 … dar când ai date multe, situația se schimbă.

- încă o reprezentare grafică a fost o chestie ce arăta partea de ‘known’ și partea de ‘unknown’ ce înconjoară acea zonă. Se leagă de chestiile de mai sus. Scopul este de a trece mai repede de la ‘unknown’ la ‘known’ prin învățare - cu cât înveți mai repede, cu atât mai repede se produce tranziția - și prin feedback.

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 ‘Scrum este un framework’. Ba mai mult, este un framework minimal - 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 ‘fac Scrum’ au tot atâtea șanse de a ‘face Scrum’ câte șanse are un programator de a instanția o clasă abstractă. Lucru ce vine în completarea ideii despre Scrum ca framework.

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 - da a fost vedeta serii. Cercul vicios sună/arată cam așa: presiune de la manager catre dezvoltator -> grabă + hack -> cod prost -> maitenance -> 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.

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 poker, 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:

- 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 - ceea ce nu rezolva prima mână. S-a văzut importanța testelor și ca o paranteză la implementare - folosirea limbajului de business cerut de client (black și white pentru jucători, nu hand1 și hand2).

- 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.

- 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:

{ 2X + 3Y = 4X + Y

{ 2X + 3Y = X+ 4Y

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 ‘five of a kind’ 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 ‘bug free’ din punct de vedere logic. Excludem erorile de limbaj/runtime.

Pentru că puțini pricep cum se face TDD, iau ca exemplu un feature ce trebuie să returneze -1, 0 sau 1 - folosit și în tratarea cazurilor la jocul de poker (black, tie, white).

- se scrie primul test (am folosit assert($obj->method() == -1);, nu am apelat la PHPUnit)

- se implementează un mock în method (return -1;)

- se rulează testul => OK

- se scriu celelalte teste (assert($obj->method() == 0); și assert($obj->method() == 1);), se rulează și evident, eșuează

- se implementează codul funcțional propriu zis

- se rulează iar testele, iar dacă totul e OK, refactor și teste

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ă!

MSI P35 Neo2 FR și update de BIOS

TRACK TOP
Filed in Rant, Tech.
No comments yet. Be the first to comment!

Ăștia de la MSI fac niște plăci de bază execelente atâta timp cât nu trag nimic la măsea. Din păcate, plăcile precum cea pomenită în titlu au un mod de-a dreptul cretin de a face update la BIOS.

Metode oficiale:

- Iei una bucată startup disk (floppy de ăla), pui imaginea ROM și aplicația de actualizate pe o partiție FAT, butezi în DOS și flash-uiești BIOS-ul. FAIL. N-am chef de floppy - nici n-am mai folosit vreunul de ani buni.

- Pentru cei fără partiții FAT (aka majoritatea în secolul 21), iei una bucată startup disk de Windows 98 sau Windows ME (WTF?!) plus una bucată floppy disk pe care se alfă aplicația de actualizare și imaginea ROM. Butezi de pe startup, actualizezi de pe al doilea disk. FAIL. Double FAIL.

Metode semi-oficiale (nesuportate de MSI):

- Îți faci cont pe forumurile MSI. Este trist pentru că nici măcar nu poți citi thread-urile de update făra cont. Trist și inutil. Există vreo două aplicații ce crează stick-uri USB pentru boot. Una dintre aplicațiile menționate știe chiar live update. Partea jenibilă: îți trebuie o placă MSI în sistem ca să poți face un stick boot-abil. WTF? FAIL.

Metoda subsemnatului:

- În primul rând n-am Windows pe mașina cu pricina și nici nu cred că o să am vreodată. Este strict pentru dezvoltare și altceva înafară de Ubuntu nu a văzut de la geneză și până în prezent. Floppy nu am de gând să îmi pun pentru un f%t%t de BIOS update. Și nici nu am de gând să caut două disk-uri. În plus sunt destul de fragile. Ca să fac un stick boot-abil trebuie să rulez pe o mașina cu placă de bază MSI ceea ce este inutil și enervant. N-o să pun Windows doar pentru că așa vrea dezvoltatorul aplicației respective. Da, actualizările MSI sunt Windows-centric. Aș fi dat multe pentru acel ASUS EZ Flash 2 cu inerfață grafică, accesibil din BIOS. Deși ASUS Update de Windows suge. Vineri a făcut praf un P5B Deluxe - a șters chip-ul, dar a ‘uitat’ să-l mai scrie. După care a refuzat orice interacțiune. Dar măcar suportul din hardware e impecabil. În concluzie a trebuit să fiu inventiv.

Pas 1 : Se ia una bucată UNetbootin. Are atât versiune de Windows cât și versiune de Linux. Pentru Ubuntu se găsește repository PPA, deci instalarea a fost după metoda standard după ce s-a adăugat noul repo în config.

Pas 2: Se ia una bucată stick USB formatat FAT32 și se infige în portul cu pricina. Se lansează UNetbootin. Pentru că pe net se găsesc doar tutoriale complicate despre cum se instalează FreeDOS pe USB, am ales UNetbootin. Are interfața cu dificultate apropiată de nivelul de percepție al unui retard.

Pas 3: se alege ca distribuție FreeDOS din primul drop down (da, nu știe doar Linux) - și versiunea 1.0 (singura disponibilă). Jos se alege drive-ul USB pe care să-l scrie (în cazul în care detectează mai multe) - OK. Ar trebui să downloadeze FreeDOS de pe Web și să-l pună pe stick.

Pas 4: Se desface arhiva în care se gasește imaginea ROM și aplicația de actualizare. Se pun pe stick-ul USB menționat anterior. Reboot.

Pas 5: Se scormonește prin BIOS pentru a putea face USB boot. Opțional se poate sări peste BIOS. F11 în timpul POST ar trebui să arate meniul în care se alege BOOT device-ul. Așa e la P35 Neo2 FR. La altele e Esc în timpul POST.

Pas 6: Se alege opțiunea 3 din meniul FreeDOS. Nu e un meniu standard (pentru cei familiarizați cu FreeDOS) precum cel din imaginea ISO. Opțiunea 3 e un live edition cu highmem suport, blah, blah, blah, yada, yada, yada. Se încarcă FreeDOS, după care se tastează în shell B:. Da, mi-a luat ceva să mă prind de faptul că B: este de fapt drive-ul USB propriu zis. În A: se montează live filesystem-ul FreeDOS.

Pas 7: Se rulează aplicația de actualizare ce primește ca argument fișierul de update. În cazul subsemnatului:

B:\> Afud408.exe A7345IMS.1A0

Se așteaptă până își termină toate mizeriile. Reboot. Ar fi bine ca sistemul să nu crape în timpul update-ului. Exclus OC și alte mizerii. Nu strică un UPS.

După reboot BIOS-ul o să dea un checksum bad la CMOS și e normal pentru că imaginea ROM e diferită. F1 pentru a intra în setup. Se va vedea faptul că s-a instalat ultima versiune și se pot pune vechile opțiuni. Succes.

Problema mail() din Zend Server Community Edition - Debian Repository

TRACK TOP
Filed in Linux, Rant.
No comments yet. Be the first to comment!

Din plictiseală sau datorită faptului că în mod repetitiv m-am tot lovit de Zend Server CE printre plimbările mele pe Web, m-am decis să renunț la versiunea implicită ce vine în reopository-ul sistemului de operare de pe mașina de dezvoltare (Ubuntu Hardy) și să pun în schimb Zend Server. Zis și făcut. Țac, țac, țac - zgomot de taste - instalarea a mers ca unsă.

Din păcate, ocazional, dezvolt și aplicații ce au nevoie de acces la funcția mail(), funcție ce altceva înafară de FALSE aka FAIL nu știa să returneze. Verific Postfix-ul - rula de zor. Deci nu era bubă de MTA. NU, nu suport Sendmail. Iau o porție de copypasta de pe php.net, pun totul întrun fișier php, rulez în shell - surpriză:

sh: -t: not found

Mă scarpin cu o mână în cap și cu cealaltă în dos. Ceva îmi pute - și nu era de la a doua mână. Încep să sap pentru a afla ce pește prăjt au făcut cei de la Zend cu php.ini de încearcă să ruleze aplicația ‘-t’. Crăp un output de phpinfo() in Firefox și mă luminez:

sendmail_path Local Value: -t -i Master Value: -t -i

Erm, WTF Zend? Casc vinovatul (/usr/local/zend/etc/php.ini) și caut linia cu pricina ce bine mersi era comentată. Cică în mod implicit ar trebui să fie ’sendmail -t -i’, dar se pare că opțiunea nu este hardcodată ca atare. Soluția e la mintea cocoșului:

sendmail_path = sendmail -t -i

Restart la Apache2. Merge? Merge. Shell-ul este fericit deasemenea.

Vulnerabilitate în WordPress e pleonasm

TRACK TOP
Filed in WordPress.
3 comments filed

Cu riscul de a supăra vreo câțiva spălați pe creier ce suferă de ‘fanboyism’, WordPress încă suge pe partea de securitate. Da, s-au făcut progrese, da, timpul de răspuns al echipei de dezvoltare este scăzut (vezi cazul 2.8.4), da, am eu mania unor reguli stricte (prea stricte în opinia neavizată a unora), da, am boala bug report. În fine, prin Iunie am încercat lupta împotriva morilor de vânt din punctul de vedere al posibilitaților de a lansa vectori de atac CSRF prin intermediul WordPress - folosind cont fără opțiunea de ‘unfiltered HTML’. Și da, aș fi contribuit cu un patch - deși problema nu este ușoară. Ca o paranteză, în cazul WordPress măcar am reușit să creez puțină vâlvă - alții precum cei de la SMF (Simple Machine Forums) nici în ziua de astăzi nu au răspuns la mail privind această problemă a CSRF-ului.

Sunt conștient de faptul că la nivel de WordPress problemele sunt minore sau inexistente datorită acelui sistem de token signature (wp_nonce), dar cumulat cu plug-in-uri defecte sau potențiale vulnerabilități pot duce la un efect de domino. Chiar descoperisem un plug-in vulnerabil la acest tip de atac, dar a fost patch-uit înainte să apuc să dau mail dezvoltatorului. Știu că unii pot atribui poveștii de mai sus valențe beletristice legate de droburi de sare, dar eu sunt dintre cei ce s-au mai fript cu WordPress - din fericire nu pe blogul personal. De fapt mulți dezvoltatori de plug-in-uri nu au o cultură a securității, și ca să nu fiu ipocrit, chiar și plug-in-ul subsemnatului are o problemă minoră ce ar putea fi exploatată printr-ul XSS+AJAX - deși e foarte dificil, dar nu mai este menținut din Ianuarie (va urma o rescriere completă). Iar o platformă atât de eterogenă are punctul cel mai slab localizat în codul cel mai slab - ce adesea va fi primul atacat având în vedere că acest aspect este o regulă în (in)securitate, iar caracterul deschis al platformei și plug-in-urile aferente elimină orice urmă de ’security through obscurity’.

Pe de altă parte, la anumite probleme răspunsul a fost destul de prompt. În aceeași zi cu povestirea cu CSRF-ul de mai sus am dat un mail echipei de securitate cu niște XSS vectors localizați. S-a scris despre asta, deși detaliile sunt vagi. Problema raportată se manifestă doar pe IE 6, unele și pe IE 7, dar echipa WordPress nu s-a obosit să dea detalii. Atacurile se puteau lansa prin proprietăți CSS nefiltrate. Browserele decente nu suferă de această problema, dar judecând după cota de piață a IE 6 & 7 - lucrurile nu sunt roz. Din păcate vulnerabilitatea se regăsește în toate versiunile anterioare lui 2.8.2, deci în cazul în care un blog arbitrar are posibilitatea de user registration și contribuție - este recomandat minim WP 2.8.2. Problema e însăși acea kses, menținută de către dezvoltatorii WordPress. Oficial proiectul kses e mort - nu a mai avut suport de prin 2006. Iar kses nu a fost concepută ca o bibliotecă sigură până la paranoia. Spre exemplu HTML Purifier bifează cu succes toate test case-urile ce se găsesc in cheat sheet-ul celor de la ha.ckers.org dar nu observ nici un efort în adoptarea acestuia. Au fost făcute plug-in-uri în acest sens - dar această funcționalitate ar trebui să fie ‘core level’. Filtrul WordPress a fost testat parțial de către subsemnatul - iar rezultatul îl vedeți mai sus. Nu am testat event handlers pe JavaScript pentru ca sunt 90 si ceva, iar un test case corect ar fi preferabil sa il codez, nu sa il fac de mana din motive de dimensiuni.

Din păcate, etic ar fi fost să se menționeze și cine și-a pierdut timpul pentru a le testa aplicația și raporta vulnerabilitatea. Da, nu am fost creditat. Nu este prima oară când se întâmplă, dar în cazul WordPress este deranjant pentru că dialogul nu a mers fin precum în cazul altora. Am ales metoda mail - pentru că din nou, așa e etic, spre deosebire de acțiunea de a pune totul pe grok.org ca sa panichez lumea - ce oricum pune botul la F.U.D. mai mult decât trebuie.

Știu că a vorbi este ușor și in principiu este degeaba. Cum am spus în repetate rânduri, oricine poate să își dea cu părerea - dar nu orice părere conteaza. Cam din perioada amintită mai sus tot ameninț lumea cu un blog engine implementat pe un M.V.C. framework iar motivele sunt evidente. Nu contest cantitatea de timp investită in WordPress, numărul de plug-in-uri disponibile (ce în timp devin enervante pe partea de maintenance), dar prea multă entropie și mentalitate îmbâcsită s-a strâns acolo. Dar pentru a face ceva - evident, este nevoie de timp, motiv pentru care WordPress înca se bucură de acest status quo pe care îl are având în vedere că am facut un numar consistent de deploy-uri la viața mea (iar pe unele le mențin).

Eclipse, Subclipse si relocarea unui repository SVN

TRACK TOP
Filed in Programare, Rant.
No comments yet. Be the first to comment!

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 … dar adresa era corectă, deci relocare - din cuc - un alt eventual checkout - din cuc. Din fericire există alternativă, și anume folosirea SVNKit pe post de interfață.

Window » Preferences » Team » SVN - iar Client se schimba din JavaHL în SVNKit. Voila - se rezolvă problemele.

Eroarea era ceva de genul:

RA layer request failed
svn: OPTIONS of ‘http://hostname/svn/repository_path/trunk’: Could not resolve hostname `hostname‘: No such host is known (http://hostname)

Acum totul este roz. Setup: Eclipse 3.4.1, Subclipse 1.6.2, Java 1.6.0_13.

BuyBox.ro - si live deployment-ul

TRACK TOP
Filed in Rant, Securitate.
2 comments filed

Deshid o nouă categorie cu acest post și anume o să îmi dau cu părerea și despre securitate. Știu că oricine poate să-și dea cu părerea, dar pe barba mea că nu e cazul de fața. Nu îmi stă în fire să îmi dau cu părerea dacă nu e nimic de zis.

Nu știu cum se face, dar în țărișoara noastră eCommerce + securitate sunt două concepte ce par a fi mutual exclusive, altfel spus sunt disjuncte. Cel puțin cam așa se întâmplă în ultima vreme. Dacă tot faceți update la site sau a dat tanti Tanța cu mătura pe tastatură, măcar puneți în puii mei o pagină de offline, sau băgați erorile în log, în loc să le băgați in browser.

Fatal error: require() [function.require]: Failed opening required ‘admin/encriptare.php’ (include_path=’.') in /[…]/index.php on line 13

Știu că este doar un simplu path disclosure, dar e un semn bun faptul că serverul acela nu prea e configurat pentru “producție”.

urlencode()/rawurlencode() complet

TRACK TOP
Filed in Programare.
No comments yet. Be the first to comment!

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!).

function url_encode_all($text)
    {
        return preg_replace(‘/./e’, "sprintf(’%%%02X’, ord(’\\0′))", $text);
    }

MySQL, arbori, o singură tabelă, cheile străine si un exemplu în Kohana

TRACK TOP
Filed in Programare.
No comments yet. Be the first to comment!

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.

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ă:

CREATE TABLE `trees` (
`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`parent_id` INT( 11 ) UNSIGNED NOT NULL DEFAULT ‘1′,
`data` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
INDEX ( `parent_id` )
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci

Precum se observă schema de date este corectă iar aparent nu pot apărea probleme. Se dă chiar următorul arbore:

1, 0, a
2, 0, b
3, 1, c
4, 1, d
5, 3, e
6, 2, f

Deși (aparent) la prima vedere structural este corect, dacă se rulează interogarea ce ar trebui sa pună constrângerea:

ALTER TABLE `trees` ADD FOREIGN KEY ( `parent_id` ) REFERENCES `trees` (
`id`
) ON DELETE CASCADE ;

o să dea o eroare de MySQL de toată frumusețea, ceva gen:

#1452 - Cannot add or update a child row: a foreign key constraint fails
([...]`, CONSTRAINT `[...]` FOREIGN KEY (`parent_id`)
REFERENCES `trees` (`id`) ON DELETE CASCADE)

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 - 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.

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ă:

INSERT INTO `trees` (
`id` ,
`parent_id` ,
`data`
)
VALUES (
‘1′, ‘1′, ‘root’
);

‘root’ nu e musai să fie ‘root’. Poate fi și ‘rădăcină’, 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, ‘root’) 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ă - cheie străină. De altfel, această înregistrare NU trebuie ștearsă. Dacă se șterge, se va șterge automat tot arborele. Este evident … 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:

INSERT INTO `trees` (
`parent_id` ,
`data`
)
VALUES (
1, ‘a’
), (
1, ‘b’
), (
2, ‘c’
), (
2, ‘d’,
), (
4, ‘e’
), (
3, ‘f’
);

Se va obține rezultatul dorit inițial. Iar constrângerea își face magia: spre exemplu dacă se șterge (2, 1, ‘a’), atunci automat se vor șterge și (4, 2, ‘c’), (5, 2, ‘d’) și (6, 4, ‘e’) pentru că ierarhic au ca părinte pe (2, 1, ‘a’).

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 ‘Notice’ în Kohana pot da in ‘Runtime Error’, 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 ‘affected rows’ sau de ‘deleted rows’. 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×0r pentru că poate programa ceva. Deci să îi dau bâte cu modelul:

class Tree_Model extends Model {

    public function __construct($id = NULL)
    {
        parent::__construct($id);
    }

    public function add_child($parent_id, $data)
    {
        $check_record = $this->db->where(‘id’, $parent_id)->get(‘trees’);

        if($check_record->count() > 0)
        {
            return $this->db->from(‘trees’)->set(array(‘parent_id’ => $parent_id, ‘data’ => $data))->insert();
        }
        else
        {
            return false;
        }
    }

    public function update_child($id, $parent_id, $data)
    {
        $check_record1 = $this->db->where(‘id’, $id)->get(‘trees’);
        $check_record2 = $this->db->where(‘id’, $parent_id)->get(‘trees’);

        if($check_record1->count() === 1 AND $check_record2->count() > 0)
        {
            return $this->db->from(‘trees’)->set(array(‘parent_id’ => $parent_id, ‘data’ => $data))->where(‘id’, $id)->update();
        }
        else
        {
            return false;
        }
    }

    public function delete_child($id)
    {
        $check_record = $this->db->where(‘id’, $id)->get(‘trees’);

        if($check_record->count() === 1 AND $id > 1)
        {
            return $this->db->from(‘trees’)->where(‘id’, $id)->delete();
        }
        else
        {
            return false;
        }
    }

}

PS: clasa este portabilă și pentru alte baze de date având în vedere faptul că am folosit ‘Database Query Builder’. 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).

Nota: nu pot corecta comportamentul cretin al WordPress pentru a afisa corect apostrof si ghilimele.

Lista Județelor, Municipiilor, Orașelor și a Comunelor/Satelor din România

TRACK TOP
Filed in Programare.
1 comment filed

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 - cel puțin până ma obișnuiesc. Dacă tot am ‘Romanian Programmers’ 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.

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 - 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 nu sunt structurate î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ă.

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() - nu m-am obosit să fac artă).

Download: lista_localitati.zip process_ro_list_output.zip

Instalarea Apache 2.2 + PHP 5.2 + MySQL 5.1 sub Windows

TRACK TOP
Filed in Programare, Windows.
3 comments filed

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, dar majoritatea fie sunt prea stufoase, fie inutile sau inutilizabile fara lucru manual - 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.

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 “hello world”? 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.

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 Apache, MySQL deasemenea poate fi primul pas deoarece baza de date si serverul web nu sunt interdependente. PHP se integreaza cu Apache, deci regulile anterior mentionate indica faptul ca va fi instalat dupa el - aceasta pentru a nu fi nevoit sa faci instalarea PHP de doua ori. Read the remainder of this entry »

Gnome History

TRACK TOP
Filed in Linux.
No comments yet. Be the first to comment!

Acesta este inca unul dintre acele posturi despre intalnitele “OS annoyances“. Desi primele 3 rezultate din Google Search-ul de mai sus fac referire la Windows OS, de data aceasta Gnome in implementarea Debian/Ubuntu iese la rampa. Posibil si sub alte distributii pentru ca imi miroase a problema din upstream in loc sa fie o problema a Debian+derivatii.

M-am trezit inca de dimineata cu gand rau impotriva Gnome History. Din pacate gandul meu a fost mai slab decat implementarea incapatanata a celor ce au gandit Gnome-ul din acest punct de vedere si n-au pus pe undeva o optiune pentru dezactivarea acestei functii, optiune ce sa fie demna de ‘Captain Obvious’, altfel spus, la mintea cocosului. Daca in trecut istoricul se tinea in fisierul ~/.recently-used iar un simplu:

chmod -c 400 ~/.recently-used

era suficient pentru a opri atrocitatea, in prezent (de la Gutsy si pana in prezent daca nu ma insel) lucrurile sunt sensibil mai diferite. Numele fisierului s-a schimbat intre timp in .recently-used.xbel. Nu aceasta ar fi problema esentiala daca metodele clasice ar functiona. Am incercat schimbarea ACL-urilor precum am pus mai sus: ceva le restaureaza. Am pus symlink catre /dev/null … ceva sterge link-ul si restaureaza fisierul. L-am creat de sub root si l-am lasat asa … ceva ii restaureaza ACL-urile si le pune iarasi pe contul meu. Parca era un film de acela prost cu Greuceanu ce omoara balauri alimentati cu baterii Duracell ce tot primesc resurect. Din fericire acesta a fost balaur pe 2 biti (4 capete). Cine stie bancul cu balaurul pe 8 biti, pricepe.

Metode exista, si sunt doua la numar. Prima desi functioneaza, este trista pentru ca are prostul obicei de a genera erori GTK in shell:

rm ~/.recently-used.xbel ; mkdir ~/.recently-used.xbel

Se pare ca e o piatra prea tare de rumegat pentru implementarea incapatanata prezentata mai sus.

Dar are dezavantajul erorilor din shell. Fericitii (ca mine) ce folosesc ext3 pe post de filesystem (nu cunosc utilitare echivalente pentru reiser, xfs, jfs - nu dati cu pietre) pot apela la o smecherie ce marcheaza fisierul ca immutable iar la incercarea de a face ceva, o sa se loveasca de un raspuns mai incapatanat de la Sfantul Kernel:

sudo chattr +i ~/.recently-used.xbel

Chestia asta il va opri pe mucos sa mai salveze istoricul, ba mai mult, scuteste shell-ul de erori neinteresante.

Deepest Sender

TRACK TOP
Filed in WordPress.
No comments yet. Be the first to comment!

Se pare ca m-am cam saturat sa ma chinui a posta articole din interfata web a WordPress deci am inceput sa cercetez optiuni alternative. In concluzie m-am dat pe client relativ dedicat cu mentiunea ca ofera totusi ceva mai multe optiuni. In principiu mare branza nu a fost, desi trebuia sa respecte o singura chestie: sa fie extensie de Firefox. Din moment ce browserul tinde sa fie al doilea sistem de operare la mine pe masina de pe care tastez, am presupus ca exista. Precum titlul o demonstreaza, exista si se numeste Deepest Sender. In caz ca inca iti este lipita de creier intrebarea: dar bine, totusi de ce o extensie de Firefox? - raspunsul este simplu: pentru ca nu scrie nicaieri faptul ca stau mereu sub Windows OS, deci printe altele o chestie dependenta de platforma limiteaza din spatiul de miscare. Da, stiu, geeky. Chiar daca nu ofera acces la absolut toate jucariile din interfata de administrare a WordPress, stie totusi sa faca vreo cateva chestii interesante:

  • conturi multiple (nu e musai sa scriu doar pe blogul personal … de fapt stai, nu scriu doar pe blogul personal);
  • editor rich text cu posibilitate de a vedea sursa HTML generata si un preview al formatarii;
  • cica ar sti sa stea si sub forma de sidebar desi nu m-a prins acest trend pentru browser;
  • drag-and-fleosc;
  • baga de seama ca ii dai muzica sa roada daca ai FoxyTunes pe aproape
  • baga de seama ca tastezi balarii si incearca sa te corecteze - aka spellchecking
  • daca pusca Firefoxu’ (se intampla si de astea) atunci o sa incerce sa recupereze cat poate, atata timp cat Firefox-ul nu a puscat cu tot cu disk-ul pe care se afla instalat
  • salvarea de drafts, desi nu poate importa draft-urile salvate folosind interfata web a WordPress
  • posibilitatea de a modifica ultimele 15 post-uri de pe blog. Este o limitare ce toate engine-urile suportate inafara de LiveJournal o au. Da, Deepest Sender suporta si alte chestii pe langa WordPress.
  • mod offline, posibilitatea de a salva si incarca fisiere XML in care se stocheaza articolul;
  • asta e adaugata de la mine din burta (oricum nu duc lipsa) - editor rich text ce stie sa colaboreze cu persoana care tasteaza articolul in loc sa lucreze impotriva lui cum face de multe ori TinyMCE aka editorul JavaScript ce vine in mod implicit cu WordPress.
  • inca una de la mine - adaugarea de imagini ofera si posibilitatea de a alinia chestiile mult mai usor decat TinyMCE si ofera posibilitatea de a da float la o imagine, chestie ce intr-un WordPress chel lipseste cu desavarsire, deci e nevoie sa se intervina in codul HTML.

In fine, nu sunt toate numai lapte si miere:

  • are suficienta grija sa nu stie nimic altceva inafara de sintaxa de baza pentru a insera un link. Fara target, fara title … trist. Din fericire exista tab-ul ‘Source’ dar nu tine de cald precum echivalentul din TinyMCE.
  • din pacate are mai putine optiuni de formatare, desi majoritatea sunt suficiente pentru un bloagar de asta fara nevoi speciale;
  • faptul ca stie sa vada ultimele chestii postate pe blog este o chestie buna, dar limita de 15 articole este totusi un impediment. Nu stiu sigur daca este o problema cu serverul XML-PRC al WordPress sau pur si simplu o limitare a Deepest Sender.
  • ar fi fost un fel de “coolness, I has it” sa poti modifica ad-labam ora la care postezi articolul asa cum interfata web stie sa o faca. Deasemenea, nu am cercetat daca e limitare de client sau de protocol.
  • ar fi recomandat sa se nu se inchida clientul atata timp cat se tasteaza un articol. Desi la o deschidere ulterioara stie sa reia procesul de unde a ramas, formatarea articolului a devenit complet cretina si arata de parca a facut-o un copil beat. In rest a fost ochei … chiar mai ochei si mai ascultator decat TinyMCE. Pe deasupra disparuse si posibilitatea de a alege o categorie (o_O), desi la a doua deschidere in timp ce tastam articolul s-a comportat aproape impecabil: a uitat categoria ce o alesesem initial, in rest nu a mai pus probleme.

In conlcluzie, se pare ca o sa ramana o vreme instalat pe la mine prin browser. Flock stiu ca avea o chestie de aceasta, dar il folosesc mai rar datorita suportului slab pentru Firebug, desi e doar un Firefox 3 modificat.

Download

Later Edit: mai are un `annoyance` - si anume faptul ca refuza cu desavarsire sa se pupe cu codul XHTML valid - asta daca nu e potrivit cu mana. S-a observat abia dupa postarea articolului.

Saltwater’s Video Downloader merge in offline

TRACK TOP
Filed in Tech.
24 comments filed

Versiune in romana mai pe lung …

De ce? Degeaba. Sau de trefla. Sau ca sa nu ma bata la cap AIMR-ul, desi aplicatia acceseaza doar continut public, iar daca e o problema, e problema companiilor care hosteaza acele fisiere. Cu un Firefox+tab-ul Net al Firebug este banala obtinerea continutului media ce ajunge in browser, si nu e singura metoda, dar e relativ simpla, mai simpla decat scormonitul prin cache. In fine, precum unii au observat, desi Trilulilu si YouTube inca sunt functionale (celelalte nu, desi site-ul a fost in mod intentionat in offline), problemele de mentenanta si de singura gaura de securitate (ce a fost exploatata, dar a dus la crash-ul aplicatiei, deci consecintele au fost minore) mi-au cam ajuns. De altfel personal NU am nevoie de o asemenea aplicatie, doar am avut ambitia sa fiu al doilea ce a scris un Trilulilu Downloader (lansat publicului in August, 2007) dupa ce primul devenise un proiect defunct, iar chestia aceasta i-a adus ceva popularitate. YouTube, Google Video, Metacafe au fost ambitii minore. Bine, mai putin Google Video ce m-a pus la lucru vreo doua zile. Deci nu mai plangeti dupa aplicatie, nu mai este, nici nu o sa mai fie. Sunt prea ocupat cu treburi mult mai serioase. Multumesc celor ce mi-au utilizat munca, dar pentru orice exista un sfarsit.

Short English version …

As you can see, the Video Downloader is dead. It’s my decision based on certain facts. Pulling down the Downloader might have been a constraint, but currently this is not the case. Please look down for alternatives, and thank you for using my application.

Write in C

TRACK TOP
Filed in Programare.
3 comments filed

If you can see this, then you might need a Flash Player upgrade or you need to install Flash Player if it's missing. Get Flash Player from Adobe.
» Powered by XHTML Video Embed

Via Misu :D

2YAWM Celebration @ PureSound.FM

TRACK TOP
Filed in Fara nume.
No comments yet. Be the first to comment!

 2YAWM Celebration

Nu cred ca este cel mai mare secret faptul ca simpatizez acest post de radio online, ba mai mult, am contribuit la promovare, continut (leak-uri pe Web au mai fost), energie … Si pentru ca timpul tine sa ne reaminteasca faptul ca trece atat de repede, uite ca se serbeaza aniversarea de doi anisori. Chiar daca nu sunt un adept al sarbatoriri timpului, nu puteam sa refuz invitatia de a participa si la acest eveniment, deci fanii muzici EDM (PureSound.FM mai trece si dincolo de Trance) au la dispozitie un eveniment intins pe durata a 4 zile, 4 zile in care isi pot incanta urechile cu seturile DJ-ilor ce au confirmat prezenta pe afis.

Pentru ca in acesti doi ani de la lansare, subsemnatul a avut foarte multe de invatat de la rezidentii PureSound.FM (printre care m-am numarat pentru o perioada de timp destul de mare), contributia mea de data aceasta va fi dincolul de nivelul invatacel sau experiment, venind in intampinare cu un stil matur, dar pus alaturi din pura placere fara constrangerile timpului ce au dus la scaderea calitatii propriului show si in final la amanarea lui din dorinta de a face o treaba catre perfectionism sau a renunta la ea. Deci traiesc cu speranta mea ca voi reusi integrarea unei idei, unui concept, si oricine este invitat sa se alature daca poate sa simta cu adevarat muzica Trance.

Atasez si afisul ce afiseaza planificarea DJ-ilor in functie de zile si orele la care acestia pot fi ascultati (timpul este exprimat in GMT aka ora Marii Britanii) …

Read the remainder of this entry »

Geek jokes

TRACK TOP
Filed in Programare, Tech.
No comments yet. Be the first to comment!

http://www.kailashnadh.name/docs/geek_jokes/

Cred ca este una dintre cele mai tari colectii de geek jokes … evident … nu le poate pricepe oricine …

E bine sa ai backup

TRACK TOP
Filed in Fara nume.
No comments yet. Be the first to comment!

Sa lasam pixelii sa vorbeasca …

If you can see this, then you might need a Flash Player upgrade or you need to install Flash Player if it's missing. Get Flash Player from Adobe.
» Powered by XHTML Video Embed

Pentru toti devii PHP

TRACK TOP
Filed in PHP.
5 comments filed

PHP

Am primit acesta (evident) de la un alt PHP dev …

Bizoni in trafic

TRACK TOP
Filed in Rant.
1 comment filed

O campanie la care subscriu. Fazele din oras cu soferi care intra fara sa se uite*, se uita dar tot se baga ca taranii**, etc. nu le comentez. In principiu astia ajung la tamponari (de cele mai multe ori cu o tanti in portiera). Nu sunt asul soselelor … si eu fac gafe, dar pana acum nu gafe monumentale ce atenteaza la viata. Subscriu impotriva bizonilor ce atenteaza la viata. In ultima luna am fost mai plimbaret (eu sunt driver de oras mai mult) si m-am dat peste 1000km, dintre care majoritatea pe drumuri de 100-200km inafara Sibiului. Pana acum:

- m-am trezit cu masina fata in fata pe contrasens de 4 ori … Prima oara am iesit cu doua roti inafara carosabilului. Era curba deosebit de periculoasa, destul de stransa, emotii multe … si pe urmatoarea la scurta distanta de prima am luat-o tot asa pe dinafara pentru ca riscam sa o scap pe contrasens daca reintram cu toate rotile pe carosabil. Bizonul a taiat-o ca i-a fost greu sa reduca viteza la 50-60 - cam cu atata se negociaza virajul ala - asa ca s-a bagat pe contrasens pentru a nu o tranti in glisiera. A doua oara viraj in urcare, dupa care urmeaza o linie dreapta, destul de lunga … ies din curba si ma trezesc cu bizon pe contrasens ce depasea … frane + tras dreapta pe cat posibil … bine ca pe DN1 sunt zone unde marginea drumului e aproape cat o banda de circulatie … am putut sa ma bag pe acolo. A treia si a patra oara depasiri pe linie dreapta din sens opus, cu spatiu insuficient … fie am tras dreapta si eu si cel depasit ca sa aiba loc bizonul sa treaca printre noi, fie am franat eu hotarat ca sa aiba bizonul loc de intrat.

- inteleg faptul ca am masina mica, dar asta nu inseamna ca*** scrie la mine pe hayon: depaseste-ma cu orice pret, chiar daca momentul ales este prost. Daca am 80 la ora si peste 150-200m urmeaza curba deosebit de periculoasa si in coborare … poate ca stiu de ce nu ii dau gaz … Ei bine, sambata soferii patriei au incercat de 3 ori sa ma bage in glisiera metalica. In legislatie scrie clar faptul de a nu mari viteza cand sunt depasit, nu scrie sa ma implant in frane pentru ca bizonul ce trece nu are loc, vede ca vine cineva din sens opus sau are in fata viraj dur fara vizibilitate si se baga la loc, fara sa se mai uite in oglinda sa vada daca a trecut sau nu de mine.Toti 3 profesionisti in acte, dar cretini in rest. Unul era cu transport de marfa, celalalt cu transport copii, iar unul cara alta masina pe platforma. Deci da.

- combinatia dintre cele doua … nene caruia sa ii fac loc pentru a nu ajunge in cel de pe contrasens atunci cand depaseste … riscul e mare sa ma ia si pe mine odata cu ei … de vreo cateva ori …

- ca pieton sa nu mai povestesc cate am vazut, cat ca nu sunt genul de pieton stil oaie ce sare pe trecere si nu se asigura in prealabil …

If you can see this, then you might need a Flash Player upgrade or you need to install Flash Player if it's missing. Get Flash Player from Adobe.
» Powered by XHTML Video Embed

Coleg de suferinta: neo.

* daca e parcat un bou in intersectie, are scuza, si eu ies din parcare aproximativ pe neveu in fiecare zi pentru ca altii isi trantesc masina ca boii fix pe partea unde ar trebui sa te asiguri daca vine cineva din dreapta, cred ca o sa comand un set Bazooka de la parchez.ca.

** adica trebuie sa ma implant in frane ca sa fiu sigur ca il ratez … desi el ramane fara permis, tot trebuie sa imi repar masina, ceea ce suge prin definitie

*** exceptand cazurile de avarie unde o las moale … prefer sa ajung cu o ora mai tarziu decat cu masina pe platforma (sau deloc)