[PHP] Sprawdzanie typu (MIME) pliku

Witajcie po bardzo długiej przerwie. W wyniku kilku spraw nie mogłem znaleźć weny i czasu na naskrobanie czegoś na bloga. Nadszedł czas troszkę to nadrobić - zacznę, mam nadzieję, konkretnie.

Dziś na warsztat pójdzie sprawdzanie typu pliku na podstawie jego MIME. Jak dobrze wiadomo, sprawdzanie po rozszerzeniu jest niepewną i ryzykowną formą - rozszerzenie można zmienić, a nieraz (wskutek takiej czy innej konfiguracji serwera) można wykonać plik zamaskowany rozszerzeniem .jpg jako normalny plik PHP. Potencjalnych skutków chyba nie trzeba opisywać ;) Przechodząc do rzeczy:

1) Korzystając z klasy Fileinfo
To rozszerzenie PHP powstało właśnie do tego celu i jest aktualnie najlepszą metodą na osiągnięcie naszego celu. Poniżej krótki i treściwy przykład działania klasy.

<?php 
$file1 = 'image.png'; // Faktyczny obrazek w PNG
$file2 = 'kod.png'; // Plik PHP ze zmienionym rozszerzeniem

$finfo = new finfo(FILEINFO_MIME);

echo $finfo->file($file1, FILEINFO_MIME_TYPE); // Wyświetli: image/png
echo $finfo->file($file2, FILEINFO_MIME_TYPE); // Wyświetli: text/x-php

W tym miejscu już doskonale widać przewagę tego rozwiązania nad sprawdzaniem rozszerzenia pliku - oszust został zdemaskowany.

2)  Poprzez funkcję mime_content_type
Uwaga, ten sposób jest gorszy! Wspomniana funkcja została zdeprecjonowana, więc nie powinno się jej używać. Jednakże dosyć często zachodzi sytuacja, w której na serwerze nie jest dostępna pierwsza metoda (klasa fileinfo), a możemy użyć owej funkcji - dlatego o niej wspominam.

<?php
echo mime_content_type('php.gif'); // Wyświetli: image/gif

3) Sprawdzanie typu pliku po jego zawartości Każdy typ pliku zawiera na swoim początku zestaw charakterystycznych dla niego kilku bajtów. Sprawdzając je, możemy określić typ pliku - należy jednak wspomnieć, że to właśnie z tej metody korzystają powyższe rozwiązania, więc zabawę z ręczną jej implementacją możemy rozpocząć gdy jesteśmy zdesperowani i nie mamy żadnej z powyższych możliwości.

Poniżej krótki przykład, pobranie trzech pierwszych bajtów pliku, skonwertowanie ich do postaci heksadecymalnej i porównanie ich z bajtami charakterystycznymi dla pliku MP3

<?php
$file = fopen('plik.mp3', 'r');
$bytes = bin2hex(fread($file, 3));

if($bytes == '494433') {
    // Sprawdzany plik jest plkiem MP3
}
else {
    // Inny plik
}

fclose($file);

Dużą listę takich charakterystycznych bajtów możecie znaleźć tutaj, można też skorzystać z serwisu FileExt.com.

Mam nadzieję, że komuś przydał się ten wpis. Dziękuję za uwagę :)

Komentarze wyłączone

Możliwość komentowania na blogu została wyłączona. Zapraszam do kontaktu na Twitterze, Facebooku lub poprzez formularz, o ten tutaj. Do usłyszenia!