From 6ebd1e56eeccb933badb5fbb9524ecf6d9847299 Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Sat, 25 Oct 2014 21:15:56 +0200 Subject: [PATCH] Removed fileinfo dependency Recent changes in thumbnail generators revealed that finfo module cannot be relied on - I found a GIF file that started with usual "GIF87a", and yet finfo reported its mime type to be "application/octet-stream". This change removes reliance on finfo module and implements detecting common file types supported by szurubooru in manual fashion. This might, of course, introduce some bugs that weren't present when using finfo. However, this change was made exactly because of such bug - while previously such edge cases were impossible to fix, now they can be dealt with accordingly in our own code. Also from what I saw on the Internet, getting fileinfo to work on Windows is a lot of trouble, so this change is welcome from that angle, too. --- INSTALL.md | 3 -- src/Helpers/MimeHelper.php | 72 +++++++++++++++++++++++++------------- 2 files changed, 47 insertions(+), 28 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 115384da..0f2b21c7 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -8,7 +8,6 @@ In order to run szurubooru, you need to have installed following software: - mod_mime_magic (recommended) - PHP 5.6.0 - pdo_sqlite - - fileinfo - imagick or gd - composer (PHP package manager) - npm (node.js package manager) @@ -58,11 +57,9 @@ your setup): ;Linux extension=pdo_sqlite.so - ;Linux has php_fileinfo enabled by default ;Windows extension=php_pdo_sqlite.dll - extension=php_fileinfo.dll In order to draw thumbnails, szurubooru needs either imagick or gd2: diff --git a/src/Helpers/MimeHelper.php b/src/Helpers/MimeHelper.php index 2cdc0fe8..92666d99 100644 --- a/src/Helpers/MimeHelper.php +++ b/src/Helpers/MimeHelper.php @@ -5,14 +5,17 @@ class MimeHelper { public static function getMimeTypeFromFile($path) { - $finfo = new \finfo(FILEINFO_MIME); - return self::stripCharset($finfo->file($path)); + $fh = fopen($path, 'rb'); + if (!$fh) + throw new \Exception('Cannot open ' . $path . ' for reading'); + $bytes = fread($fh, 16); + fclose($fh); + return self::getMimeTypeFrom16Bytes($bytes); } public static function getMimeTypeFromBuffer($buffer) { - $finfo = new \finfo(FILEINFO_MIME); - return self::stripCharset($finfo->buffer($buffer)); + return self::getMimeTypeFrom16Bytes(substr($buffer, 0, 16)); } public static function isFlash($mime) @@ -38,36 +41,55 @@ class MimeHelper 'image/jpeg' => 'JPG', 'image/png' => 'PNG', 'image/gif' => 'GIF', - 'video/3gpp' => '3GP', - 'video/annodex' => 'AXV', - 'video/dl' => 'DL', - 'video/dv' => 'dif DV', - 'video/fli' => 'FLI', - 'video/gl' => 'GL', - 'video/mpeg' => 'mpeg mpg MPE', - 'video/MP2T' => 'TS', - 'video/mp4' => 'MP4', - 'video/quicktime' => 'qt MOV', - 'video/ogg' => 'OGV', 'video/webm' => 'WEBM', - 'video/vnd.mpegurl' => 'MXU', + 'video/mp4' => 'MP4', + 'video/mpeg' => 'MPEG MPG MPE', 'video/x-flv' => 'FLV', - 'video/x-mng' => 'MNG', - 'video/x-ms-asf' => 'asf ASX', - 'video/x-ms-wm' => 'WM', - 'video/x-ms-wmv' => 'WMV', - 'video/x-ms-wmx' => 'WMX', - 'video/x-ms-wvx' => 'WVX', - 'video/x-msvideo' => 'AVI', 'video/x-matroska' => 'MKV', + 'video/3gpp' => '3GP', + 'video/quicktime' => 'QT MOV', 'text/plain' => 'TXT', ]; $key = strtolower(trim($mime)); return isset($map[$key]) ? $map[$key] : null; } - private static function stripCharset($mime) + private static function getMimeTypeFrom16Bytes($bytes) { - return preg_replace('/;\s*charset.*$/', '', $mime); + if ($bytes === false) + return false; + + if (strncmp($bytes, 'CWS', 3) === 0 or strncmp($bytes, 'FWS', 3) === 0 or strncmp($bytes, 'ZWS', 3) === 0) + return 'application/x-shockwave-flash'; + + if (strncmp($bytes, "\xff\xd8\xff", 3) === 0) + return 'image/jpeg'; + + if (strncmp($bytes, "\x89PNG\x0d\x0a", 6) === 0) + return 'image/png'; + + if (strncmp($bytes, 'GIF87a', 6) === 0 or strncmp($bytes, 'GIF89a', 6) === 0) + return 'image/gif'; + + if (strncmp($bytes, "\x1a\x45\xdf\xa3", 4) === 0) + return 'video/webm'; + + if (strncmp(substr($bytes, 4), 'ftypisom', 8) === 0 or strncmp(substr($bytes, 4), 'ftypmp42', 8) === 0) + return 'video/mp4'; + + if (strncmp($bytes, "\x46\x4c\x56\x01", 4) === 0) + return 'video/x-flv'; + + if (strncmp($bytes, "\x1a\x45\xdf\xa3\x93\x42\x82\x88\x6d\x61\x74\x72\x6f\x73\x6b\x61", 16) === 0) + return 'video/x-matroska'; + + if (strncmp($bytes, "\x00\x00\x00\x14\x66\x74\x79\x70\x33\x67\x70", 12) === 0 or + strncmp($bytes, "\x00\x00\x00\x20\x66\x74\x79\x70\x33\x67\x70", 12) === 0) + return 'video/3gpp'; + + if (strncmp(substr($bytes, 4), 'ftypqt ', 8) === 0) + return 'video/quicktime'; + + return 'application/octet-stream'; } }