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.
Introducere
Determinarea MIME Type-ului corect pentru un fisier este o problema esentiala. Nu o sa explic si de ce … 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=”multipart/form-data” 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.
PECL si fileinfo
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.
In primul rand, este nevoie de una bucata compilator. Exista un pachet ce le face pe toate, deci:
sudo apt-get install build-essential
Bun. Avem compilator, avem PECL (presupun, daca n-ai HTTP server si PHP – citesti degeaba). Pentru build-ul fileinfo mai este nevoie de pachete de development, deci:
sudo apt-get install libmagic-dev php5-dev
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:
sudo pecl install fileinfo
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:
Build process completed successfully
Installing ‘/usr/lib/php5/20060613+lfs/fileinfo.so’
install ok: channel://pear.php.net/Fileinfo-1.0.4
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 – 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):
cd /etc/php5/conf.d/; sudo touch fileinfo.ini; sudo nano fileinfo.ini
Bagati urmatoarea linie in acel fisier:
extension=fileinfo.so
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):
sudo /etc/init.d/apache2 reload
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.
Utilizarea fileinfo pentru a afla MIME Type
Acum sa trecem la lucruri grele. fileinfo contine niste functii smechere asemanatoare cu fopen. Pentru ubergeeks exista modul orientat obiect de lucru cu ele (php.net/finfo_open 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 … 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:
$finfo=finfo_open(FILEINFO_MIME, "/usr/share/misc/magic");
if(!$finfo)
die("Can't open the fileinfo database.");
$mime=finfo_file($finfo, $fileName);
finfo_close($finfo);
Si cam atat. Succes si spor la treaba.