MimeType evaluation

#1
Guten Morgen.
Seit längerem nun steh ich vor dem Problem einer sauberen MimeType-Überprüfung in PHP. Das Problem dabei ist nicht die fehlende Funktionalität in PHP, sondern verschiedene unglückliche Parameter.

Zum einen fehlt auf der von mir zu gebrauchenden Serverinstallation (Windows) das sogenannte "magic"-File.
Somit fällt die Funktion
PHP:
mime_content_type()
weg, da gemäss Manual die MimeTypes per magic.mime eruiert werden.
Code:
Returns the MIME content type for a file as determined by using information from the magic.mime file.
Weiter gäbe es ja die in PHP6 standardmässig gebrauchte Klasse Fileinfo und die dementsprechenden fifo-funktionen welche allerdings auf meiner
PHP-Installation nicht zur Verfügung steht.
Womit diese Option auch wegfällt.

Nun weitere sichere (und in PHP integrierte) Möglichkeiten gibt es m.E. nicht, oder seh ich das falsch? Die meisten weiteren Contributions im Netz drehen sich nur um die Analysation der file-extension.
Zu erwähnen wäre vielleicht, dass ich keine system() / exec() absetzten kann & auch nicht will.

Also hab ich mich drangemacht selbst eine kleine Lösung zu schreiben, mit welcher ich allerdings nicht ganz zufrieden bin.

Prinzipiell ist es nur eine weitere Integration des magic.mime, aber seht selbst.

PHP:
<?php

    $file = 'yourfile.ext';
    $handle = fopen ($file, "r");
    $buffer = fgets($handle); //just the first line (no loop is needed)
    fclose ($handle);
    
    $matches = array();
    preg_match_all('/[A-Za-z0-9,.-\/]+/', $buffer, $matches);

// show $matches

?>
für eine .exe kriege ich zum Beispiel ein $matches-Array wie das folgende

Code:
array(1) {
  [0]=>
  array(10) {
    [0]=>
    string(2) "MZ"
    [1]=>
    string(1) "L"
    [2]=>
    string(4) "This"
    [3]=>
    string(7) "program"
    [4]=>
    string(6) "cannot"
    [5]=>
    string(2) "be"
    [6]=>
    string(3) "run"
    [7]=>
    string(2) "in"
    [8]=>
    string(3) "DOS"
    [9]=>
    string(5) "mode."
  }
}
Das erste Element ist nun das Entscheidende. Im magic-File nun nach MZ gesucht findet man das folgende

Code:
sheeep@foobar:~$ cat /etc/apache2/magic | grep MZ
0        string            MZ                application/x-dosexec
0        string    MZ
0        string    MZ
0        string    MZ
0        string    MZ
0        string    MZ        application/octet-stream
Eine exe als octet-stream zu deklarieren ist richtig, also dürfte die Evaluation stimmen. (Auch für weitere Dateien getestet)

magic beinhaltet teilweise auch byte-Überprüfungen wie die folgende:
Code:
>43    byte        0x14        application/ichitaro4
Meines Erachtens lässt sich dies mit PHP nicht überprüfen, oder irre ich mich da?

Auch gibt es Dateien (zB ein normales Textfile), welches mit dieser Methode nicht analysiert werden kann, da es bereits einen text/plain header besitzt und mir somit die wirkliche erste Zeile ausgibt. (Welche mit Sicherheit matcht :))

Zum anderen ist das magic-file 935 Zeilen schwer, was einen nicht zu übergehenden Aufwand für die Integration bedeuten würde ;)

Nun, kennt ihr weitere Möglichkeiten einen MimeType eines Files sicher zu finden? Oder sollte ich mich an dieser Lösung austoben?
(Bzw: auf PHP6 warten ;))

PS: Mein Code ist nur ein POC, RegEx ist nicht ausgereift und keine Überprüfungen gemacht, sollte aber für die Idee reichen.
 
Zuletzt bearbeitet:
#2
Was genau hast du denn vor? Wenn es z.B. darum geht bei einem Upload den MIME Type zu ermitteln, dann steht dir dafür in $_FILES das Element "type" zur Verfügung.
 
#3
Was genau hast du denn vor? Wenn es z.B. darum geht bei einem Upload den MIME Type zu ermitteln, dann steht dir dafür in $_FILES das Element "type" zur Verfügung.
Nun ja, grundsätzlich nicht nur für Uploads. Wenn ich schon Klassen schreiben müssen Sie auch konsistent sein =)

Even if: Einige Tests sagen mir; $_FILES['filename_here']['type'] prüft nicht sehr genau.

Code:
sheeep@foobar:~$ touch foo.exe
ergibt folgenden Output

Code:
array(1) {
 ["foo"]=>
  array(5) {
    ["name"]=>
    string(7) "foo.exe"
    ["type"]=>
    string(31) "a[I]pplication/x-ms-dos-executable[/I]"
    ["tmp_name"]=>
    string(14) "/tmp/php8T9EJZ"
    ["error"]=>
    int(0)
    ["size"]=>
    int(0)
  }
}
Darauf allerdings kann ich nicht gehen. Ein leeres File dürfte keinen Type application/x-ms-dos-executable haben. Oder doch?

Weiter im Text.
Code:
sheeep@foobar:~$ echo "this is me" > test.txt
Code:
["type"]=>     string(10) "text/plain"
Dann aber.
Code:
sheeep@foobar:~$ mv test.txt test.pdf
Code:
["type"]=>     string(15) "application/pdf"
Meiner Meinung nach dürfte die Upload-Routine von PHP nur auf die Extension des Files schliessen, was wiederum nicht wirklich hilfreich ist. (Jedenfalls genügt es meinen Ansprüchen nicht. =))
 
#4
Meiner Meinung nach dürfte die Upload-Routine von PHP nur auf die Extension des Files schliessen, was wiederum nicht wirklich hilfreich ist.
Nicht PHP legt den MimeType fest, sondern der Browser, deshalb gibt es auch immer wieder Probleme mit der MimeType überprüfung, da z.B. IE6, IE7 und FF unterschiedliche MimeTypes für ein und das selbe File übergeben.
 
#5
Nicht PHP legt den MimeType fest, sondern der Browser, deshalb gibt es auch immer wieder Probleme mit der MimeType überprüfung, da z.B. IE6, IE7 und FF unterschiedliche MimeTypes für ein und das selbe File übergeben.
you're right.

Code:
[URL="http://www.php.net/manual/en/reserved.variables.files.php"]$_FILES['userfile']['type'][/URL]

The mime type of the file, if the browser provided this
information. An example would be [I]"image/gif"[/I]. 
This mime type is however not checked on the PHP side 
and therefore don't take its value for granted.
Einen Grund mehr, dieser Information keine Beachtung zu schenken.
 
#7
http://de2.php.net/manual/de/book.fileinfo.php

finfo ftw :) das ist recht zuverlässig und leider erst aber der php5.3 direkt eingebaut. wird zeit, dass das bei debian mal standard wird.
Danke, leider schrieb ich in der Threadbeschreibung
Weiter gäbe es ja die in PHP6 standardmässig gebrauchte Klasse Fileinfo und die dementsprechenden fifo-funktionen welche allerdings auf meiner
PHP-Installation nicht zur Verfügung steht.
Womit diese Option auch wegfällt.
Aber hast schon recht, 5.3 les ich gerade ;)
 
#11
Gibt es eigentlich auch unter Windows eine zuverlässige Methode den Mimetype zu bestimmen?
PECL - FileInfo
Allows retrieval of information regarding a vast majority of file types. This information may include dimensions, quality, length etc.

Additionally it can also be used to retrieve the mime type for a particular
file and for text files proper language encoding.
Und falls bereits installiert: http://ch.php.net/fileinfo

(halt eben wie bereits im Thread erwähnt ;))
 
Oben