Elgg  Version master
MimeTypeDetector.php
Go to the documentation of this file.
1 <?php
2 namespace Elgg\Filesystem;
3 
8 
9  const DEFAULT_TYPE = 'application/octet-stream';
10 
14  public $strategies = [
15  [__CLASS__, 'tryFinfo'],
16  [__CLASS__, 'tryMimeContentType'],
17  [__CLASS__, 'tryFile'],
18  [__CLASS__, 'tryGetimagesize'],
19  ];
20 
24  public $use_extension = true;
25 
29  public $extensions = [
30  'txt' => 'text/plain',
31  'htm' => 'text/html',
32  'html' => 'text/html',
33  'php' => 'text/html',
34  'css' => 'text/css',
35  'js' => 'text/javascript',
36  'mjs' => 'text/javascript',
37  'json' => 'application/json',
38  'xml' => 'application/xml',
39  'swf' => 'application/x-shockwave-flash',
40  'flv' => 'video/x-flv',
41 
42  // images
43  'png' => 'image/png',
44  'jpe' => 'image/jpeg',
45  'jpeg' => 'image/jpeg',
46  'jpg' => 'image/jpeg',
47  'gif' => 'image/gif',
48  'bmp' => 'image/bmp',
49  'ico' => 'image/vnd.microsoft.icon',
50  'tiff' => 'image/tiff',
51  'tif' => 'image/tiff',
52  'svg' => 'image/svg+xml',
53  'svgz' => 'image/svg+xml',
54  'webp' => 'image/webp',
55 
56  // archives
57  'zip' => 'application/zip',
58  'rar' => 'application/x-rar-compressed',
59  'exe' => 'application/x-msdownload',
60  'msi' => 'application/x-msdownload',
61  'cab' => 'application/vnd.ms-cab-compressed',
62 
63  // audio/video
64  'mp3' => 'audio/mpeg',
65  'qt' => 'video/quicktime',
66  'mov' => 'video/quicktime',
67 
68  // adobe
69  'pdf' => 'application/pdf',
70  'psd' => 'image/vnd.adobe.photoshop',
71  'ai' => 'application/postscript',
72  'eps' => 'application/postscript',
73  'ps' => 'application/postscript',
74 
75  // open office
76  'odt' => 'application/vnd.oasis.opendocument.text',
77  'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
78 
79  // office
80  'doc' => 'application/msword',
81  'rtf' => 'application/rtf',
82  'xls' => 'application/vnd.ms-excel',
83  'ppt' => 'application/vnd.ms-powerpoint',
84  'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
85  'docm' => 'application/vnd.ms-word.document.macroEnabled.12',
86  'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
87  'dotm' => 'application/vnd.ms-word.template.macroEnabled.12',
88  'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
89  'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
90  'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
91  'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',
92  'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
93  'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
94  'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
95  'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
96  'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
97  'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
98  'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
99  'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
100  'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
101  'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
102  'sldm' => 'application/vnd.ms-powerpoint.slide.macroEnabled.12',
103  'one' => 'application/msonenote',
104  'onetoc2' => 'application/msonenote',
105  'onetmp' => 'application/msonenote',
106  'onepkg' => 'application/msonenote',
107  'thmx' => 'application/vnd.ms-officetheme',
108  ];
109 
118  public function getType($file, $default = self::DEFAULT_TYPE) {
119  // Check only existing files
120  if (!is_file($file) || !is_readable($file)) {
121  return $default;
122  }
123 
124  $ext = pathinfo($file, PATHINFO_EXTENSION);
125 
126  $type = $this->tryStrategies($file);
127 
128  if ($type) {
129  return $this->fixDetectionErrors($type, $ext);
130  }
131 
132  if ($this->use_extension && isset($this->extensions[$ext])) {
133  return $this->extensions[$ext];
134  }
135 
136  return $default;
137  }
138 
146  public function tryStrategies($file) {
147  foreach ($this->strategies as $strategy) {
148  $type = call_user_func($strategy, $file);
149  if (!empty($type)) {
150  return $type;
151  }
152  }
153 
154  return '';
155  }
156 
165  public function fixDetectionErrors($type, $extension) {
166  if ($type === 'application/zip') {
167  // hack for Microsoft zipped formats
168  switch ($extension) {
169  case 'docx':
170  return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
171  case 'xlsx':
172  return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
173  case 'pptx':
174  return 'application/vnd.openxmlformats-officedocument.presentationml.presentation';
175  }
176  }
177 
178  // check for bad ppt detection
179  if ($type === 'application/vnd.ms-office' && $extension === 'ppt') {
180  return 'application/vnd.ms-powerpoint';
181  }
182 
183  // bad css/js detection
184  if ($type === 'text/plain' && in_array($extension, ['css', 'js', 'mjs'])) {
185  return $this->extensions[$extension];
186  }
187 
188  // try extension detection as a fallback for octet-stream
189  if ($type === 'application/octet-stream' && $this->use_extension && isset($this->extensions[$extension])) {
190  return $this->extensions[$extension];
191  }
192 
193  return $type;
194  }
195 
203  public static function tryFinfo($file) {
204  if (!function_exists('finfo_open')) {
205  return '';
206  }
207 
208  $finfo = finfo_open(FILEINFO_MIME);
209  $type = finfo_file($finfo, $file);
210  finfo_close($finfo);
211  // Mimetype can come in text/plain; charset=us-ascii form
212  if (strpos($type, ';')) {
213  list($type,) = explode(';', $type);
214  }
215 
216  return $type;
217  }
218 
226  public static function tryMimeContentType($file) {
227  return function_exists('mime_content_type') ? mime_content_type($file) : '';
228  }
229 
237  public static function tryFile($file) {
238  if (DIRECTORY_SEPARATOR !== '/' || !function_exists('exec')) {
239  return '';
240  }
241 
242  $type = @exec('file -b --mime-type ' . escapeshellarg($file));
243  return $type ?: '';
244  }
245 
253  public static function tryGetimagesize($file) {
254  $data = @getimagesize($file);
255  return empty($data['mime']) ? '' : $data['mime'];
256  }
257 }
$default
Definition: checkbox.php:30
static tryGetimagesize($file)
Detect MIME type.
list extensions
Definition: conf.py:31
tryStrategies($file)
Detect MIME type using various strategies.
static tryFinfo($file)
Detect MIME type using finfo_open.
$type
Definition: delete.php:21
if(!$entity instanceof\ElggUser) $data
Definition: attributes.php:13
getType($file, $default=self::DEFAULT_TYPE)
Sniff the MIME type.
fixDetectionErrors($type, $extension)
Fix common type detection errors.
static tryMimeContentType($file)
Detect MIME type using mime_content_type.
Detect the MIME type of a file.
static tryFile($file)
Detect MIME type using file(1)
$extension
Definition: default.php:25