Riconoscimento del MIME Type attraverso il Magic number

MarcoGrazia

Utente Attivo
15 Dic 2009
852
20
28
63
Udine
www.stilisticamente.com
Ciao, quella che presento qui è una semplice routine in grado di lggere il Magic number di un file e quindi stabilirne il tipo MIME.
Chiaramente non è risolutiva ne vuole esserlo, ma l'ho testata con alcuni dei file che gestisce e mi pare ben funzionante.
In pratica la utilizzo per il controllo remoto dell'invio di alcuni tipi di file attraverso la LAN che gestisco.
La routine la metto qui ed è abbastanza autoesplicativa, almeno spero.
PHP:
function minimime($fname) {
    $fh = fopen($fname, 'rb');    //    Legge il file passato alla funzione come binario
   
    //    Se il file handle non è false, continua nella lettura.
    if ($fh) {
        $bytes6 = fread($fh, 6);    //    legge 6 caratteri
        fseek($fh, 0);    //    torna a puntare il primo carattere del file ( il carattere 0 )
        $bytes8 = fread($fh, 8);    //    legge 8 caratteri per usi futuri.
        fclose($fh);     //    Chiude il file in lettura.
       
        //    Se sono stati letti dei byte prosegue, se no esce a false.
        if ($bytes6 === false) return false;
        //    IMG
        if (substr($bytes6, 0, 3) == "\xff\xd8\xff") return 'image/jpeg';            //    Immagini JPG
        if (substr($bytes6, 0, 2) == "\x42\x4D") return 'image/x-windows-bmp';        //    Immagini BMP
        if ($bytes6    == "\x89PNG\x0d\x0a" || $bytes6    == "\x89\x50\x4E\x47\x0D\x0A") return 'image/png';        //    Immagini PNG
        if ($bytes6    == "\x47\x49\x46\x38\x37\x61" || $bytes6 == "\x47\x49\x46\x38\x39\x61") return 'image/gif';        //    Immagini GIF di ogni tipo previsto
        if ($bytes6    == "GIF87a" || $bytes6 == "GIF89a") return 'image/gif';        //    Stessa cosa di cui sopra, ma utilizzando i caratteri esadecimali.
        if (substr($bytes6, 0, 4) == "\x49\x49\x2A\x00" || substr($bytes6, 0, 4) =="\x4D\x4D\x00\x2A") return 'image/tiff';        //    Immagini TIFF ( generalmente per i FAX )
        //    PDF
        if ($bytes6 == "%PDF" || substr($bytes6, 0, 4) == "\x25\x50\x44\x46") return 'application/pdf';        //    PDF
        //    ZIP, RAR file or 7z
        if (substr($bytes6, 0, 2) == "PK" || substr($bytes6, 0, 2) == "\x50\x4B") return 'application/zip';        //    ZIP File
        if ($bytes6 == "\x52\x61\x72\x21\x1A\x07") return 'application/x-rar-compressed';                        //    RAR File
        if ($bytes6 == "\x75\x73\x74\x61\x72") return 'application/x-tar';                                        //    Archivi TAR
        if (substr($bytes6, 0, 2) == "7z" || $bytes6 == "\x37\x7A\xBC\xAF\x27\x1C") return 'application/x-7z-compressed';        //    7Z file
        //    ELSE
        return 'application/octet-stream';    //    Generic file    Generico se non è tra questi.
    }
    return false;  //  Esce in errore
}    //    minimime()
L'embrione l'ho trovato su un sito cercando un metodo semplice per gestire il mime type di un file caricato, ma poi l'ho ampliata e modificata al meglio che potevo, è abbastanza veloce.
Il funzionamento è semplice: passato il nome di un file, che si deve trovare nel percorso del file system dove gira l'applicazione, questo viene aperto in lettura di tipo binario.
Se non ci sono errori di sorta continua con la lettura dei primi 6 caratteri del file, apltrimenti esce con un false.
C'è anche una variabile che legge i primi 8 caratteri del file, ma per ora non è usata, quindi chiude il file, e prosegue con l'interpretazione dei caratteri letti.
Il magic number, dovrebbe essere interpretato proprio nei primi 6 caratteri di ogni file, ma è una pia illusione, in realtà può essere anche utilizzato nei primi due caratteri come nei file ZIP, che riportano solo PK, le iniziale del loro inventore: Phill Katz.
Comunque interpretato il file, viene ritornato il suo mime type e quindi la routine esce.

Qui sotto si vede un suo semplice utilizzo, chiamandola con un file in lettura, ho pure passato un mio vecchio CUD :D e l'ha letto perfettamente interpretandolo come PDF.
PHP:
echo minimime('CUD_01856613_2014_0.pdf') . '<br>';       //    Torna application/pdf
echo minimime('administrator.png') . '<br>';            //    Torna image/png
echo minimime('AtomSetup.exe') . '<br>';                //    Torna un application/octet-stream dato che il file exe non è contemplato.
echo minimime('error-404.jpg') . '<br>';                //    Torna image/jpeg
La routine non verifica DLL e file EXE perché non mi serve farlo, però posso solo aggiungere al riguardo che nel caso voleste ampliarla in tal senso, dovrete verificare il tipo di sistema operativo in uso, perché nel tempo i modelli sono cambiati e bisogna verificare se si tratta di DOS executable, DOS stub, Windows in modalità Portable Executable, ELF, insomma un casino :D

Per chi si vuole divertire a modificarla e ad ampliarla qui un piccolo elenco di magic number: https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files
E qui un elenco di mime type: https://www.sitepoint.com/mime-types-complete-list/
 

Discussioni simili