]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - extlib/MIME/Type.php
c335f8d92d95008e0206791b8a7f9a270adfc414
[quix0rs-gnu-social.git] / extlib / MIME / Type.php
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4: */
3 // +----------------------------------------------------------------------+
4 // | PHP version 4                                                        |
5 // +----------------------------------------------------------------------+
6 // | Copyright (c) 1997-2002, 2008 The PHP Group                                |
7 // +----------------------------------------------------------------------+
8 // | This source file is subject to version 3.0 of the PHP license,       |
9 // | that is bundled with this package in the file LICENSE, and is        |
10 // | available at through the world-wide-web at                           |
11 // | http://www.php.net/license/3_0.txt.                                  |
12 // | If you did not receive a copy of the PHP license and are unable to   |
13 // | obtain it through the world-wide-web, please send a note to          |
14 // | license@php.net so we can mail you a copy immediately.               |
15 // +----------------------------------------------------------------------+
16 // | Authors: Ian Eure <ieure@php.net>                                    |
17 // +----------------------------------------------------------------------+
18 //
19 // $Id: Type.php,v 1.6 2009/01/16 11:49:45 cweiske Exp $
20
21 require_once 'PEAR.php';
22
23 $_fileCmd = &PEAR::getStaticProperty('MIME_Type', 'fileCmd');
24 $_fileCmd = 'file';
25
26 /**
27  * Class for working with MIME types
28  *
29  * @category MIME
30  * @package  MIME_Type
31  * @license  PHP License 3.0
32  * @version  1.2.0
33  * @link     http://pear.php.net/package/MIME_Type
34  * @author   Ian Eure <ieure@php.net>
35  */
36 class MIME_Type
37 {
38     /**
39      * The MIME media type
40      *
41      * @var string
42      */
43     var $media = '';
44
45     /**
46      * The MIME media sub-type
47      *
48      * @var string
49      */
50     var $subType = '';
51
52     /**
53      * Optional MIME parameters
54      *
55      * @var array
56      */
57     var $parameters = array();
58
59     /**
60      * List of valid media types.
61      * A media type is the string in front of the slash.
62      * The media type of "text/xml" would be "text".
63      *
64      * @var array
65      */
66     var $validMediaTypes = array(
67         'text',
68         'image',
69         'audio',
70         'video',
71         'application',
72         'multipart',
73         'message'
74     );
75
76
77     /**
78      * Constructor.
79      *
80      * If $type is set, if will be parsed and the appropriate class vars set.
81      * If not, you get an empty class.
82      * This is useful, but not quite as useful as parsing a type.
83      *
84      * @param string $type MIME type
85      *
86      * @return void
87      */
88     function MIME_Type($type = false)
89     {
90         if ($type) {
91             $this->parse($type);
92         }
93     }
94
95
96     /**
97      * Parse a mime-type and set the class variables.
98      *
99      * @param string $type MIME type to parse
100      *
101      * @return void
102      */
103     function parse($type)
104     {
105         $this->media      = $this->getMedia($type);
106         $this->subType    = $this->getSubType($type);
107         $this->parameters = array();
108         if (MIME_Type::hasParameters($type)) {
109             require_once 'MIME/Type/Parameter.php';
110             foreach (MIME_Type::getParameters($type) as $param) {
111                 $param = new MIME_Type_Parameter($param);
112                 $this->parameters[$param->name] = $param;
113             }
114         }
115     }
116
117
118     /**
119      * Does this type have any parameters?
120      *
121      * @param string $type MIME type to check
122      *
123      * @return boolean true if $type has parameters, false otherwise
124      * @static
125      */
126     function hasParameters($type)
127     {
128         if (strstr($type, ';')) {
129             return true;
130         }
131         return false;
132     }
133
134
135     /**
136      * Get a MIME type's parameters
137      *
138      * @param string $type MIME type to get parameters of
139      *
140      * @return array $type's parameters
141      * @static
142      */
143     function getParameters($type)
144     {
145         $params = array();
146         $tmp    = explode(';', $type);
147         for ($i = 1; $i < count($tmp); $i++) {
148             $params[] = trim($tmp[$i]);
149         }
150         return $params;
151     }
152
153
154     /**
155      * Strip parameters from a MIME type string.
156      *
157      * @param string $type MIME type string
158      *
159      * @return string MIME type with parameters removed
160      * @static
161      */
162     function stripParameters($type)
163     {
164         if (strstr($type, ';')) {
165             return substr($type, 0, strpos($type, ';'));
166         }
167         return $type;
168     }
169
170
171     /**
172      * Removes comments from a media type, subtype or parameter.
173      *
174      * @param string $string   String to strip comments from
175      * @param string &$comment Comment is stored in there.
176      *
177      * @return string   String without comments
178      * @static
179      */
180     function stripComments($string, &$comment)
181     {
182         if (strpos($string, '(') === false) {
183             return $string;
184         }
185
186         $inquote   = false;
187         $quoting   = false;
188         $incomment = 0;
189         $newstring = '';
190
191         for ($n = 0; $n < strlen($string); $n++) {
192             if ($quoting) {
193                 if ($incomment == 0) {
194                     $newstring .= $string[$n];
195                 } else if ($comment !== null) {
196                     $comment .= $string[$n];
197                 }
198                 $quoting = false;
199             } else if ($string[$n] == '\\') {
200                 $quoting = true;
201             } else if (!$inquote && $incomment > 0 && $string[$n] == ')') {
202                 $incomment--;
203                 if ($incomment == 0 && $comment !== null) {
204                     $comment .= ' ';
205                 }
206             } else if (!$inquote && $string[$n] == '(') {
207                 $incomment++;
208             } else if ($string[$n] == '"') {
209                 if ($inquote) {
210                     $inquote = false;
211                 } else {
212                     $inquote = true;
213                 }
214             } else if ($incomment == 0) {
215                 $newstring .= $string[$n];
216             } else if ($comment !== null) {
217                 $comment .= $string[$n];
218             }
219         }
220
221         if ($comment !== null) {
222             $comment = trim($comment);
223         }
224
225         return $newstring;
226     }
227
228
229     /**
230      * Get a MIME type's media
231      *
232      * @note 'media' refers to the portion before the first slash
233      *
234      * @param string $type MIME type to get media of
235      *
236      * @return string $type's media
237      * @static
238      */
239     function getMedia($type)
240     {
241         $tmp = explode('/', $type);
242         return strtolower(trim(MIME_Type::stripComments($tmp[0], $null)));
243     }
244
245
246     /**
247      * Get a MIME type's subtype
248      *
249      * @param string $type MIME type to get subtype of
250      *
251      * @return string $type's subtype, null if invalid mime type
252      * @static
253      */
254     function getSubType($type)
255     {
256         $tmp = explode('/', $type);
257         if (!isset($tmp[1])) {
258             return null;
259         }
260         $tmp = explode(';', $tmp[1]);
261         return strtolower(trim(MIME_Type::stripComments($tmp[0], $null)));
262     }
263
264
265     /**
266      * Create a textual MIME type from object values
267      *
268      * This function performs the opposite function of parse().
269      *
270      * @return string MIME type string
271      */
272     function get()
273     {
274         $type = strtolower($this->media . '/' . $this->subType);
275         if (count($this->parameters)) {
276             foreach ($this->parameters as $key => $null) {
277                 $type .= '; ' . $this->parameters[$key]->get();
278             }
279         }
280         return $type;
281     }
282
283
284     /**
285      * Is this type experimental?
286      *
287      * @note Experimental types are denoted by a leading 'x-' in the media or
288      *       subtype, e.g. text/x-vcard or x-world/x-vrml.
289      *
290      * @param string $type MIME type to check
291      *
292      * @return boolean true if $type is experimental, false otherwise
293      * @static
294      */
295     function isExperimental($type)
296     {
297         if (substr(MIME_Type::getMedia($type), 0, 2) == 'x-' ||
298             substr(MIME_Type::getSubType($type), 0, 2) == 'x-') {
299             return true;
300         }
301         return false;
302     }
303
304
305     /**
306      * Is this a vendor MIME type?
307      *
308      * @note Vendor types are denoted with a leading 'vnd. in the subtype.
309      *
310      * @param string $type MIME type to check
311      *
312      * @return boolean true if $type is a vendor type, false otherwise
313      * @static
314      */
315     function isVendor($type)
316     {
317         if (substr(MIME_Type::getSubType($type), 0, 4) == 'vnd.') {
318             return true;
319         }
320         return false;
321     }
322
323
324     /**
325      * Is this a wildcard type?
326      *
327      * @param string $type MIME type to check
328      *
329      * @return boolean true if $type is a wildcard, false otherwise
330      * @static
331      */
332     function isWildcard($type)
333     {
334         if ($type == '*/*' || MIME_Type::getSubtype($type) == '*') {
335             return true;
336         }
337         return false;
338     }
339
340
341     /**
342      * Perform a wildcard match on a MIME type
343      *
344      * Example:
345      * MIME_Type::wildcardMatch('image/*', 'image/png')
346      *
347      * @param string $card Wildcard to check against
348      * @param string $type MIME type to check
349      *
350      * @return boolean true if there was a match, false otherwise
351      * @static
352      */
353     function wildcardMatch($card, $type)
354     {
355         if (!MIME_Type::isWildcard($card)) {
356             return false;
357         }
358
359         if ($card == '*/*') {
360             return true;
361         }
362
363         if (MIME_Type::getMedia($card) == MIME_Type::getMedia($type)) {
364             return true;
365         }
366
367         return false;
368     }
369
370
371     /**
372      * Add a parameter to this type
373      *
374      * @param string $name    Attribute name
375      * @param string $value   Attribute value
376      * @param string $comment Comment for this parameter
377      *
378      * @return void
379      */
380     function addParameter($name, $value, $comment = false)
381     {
382         $tmp = new MIME_Type_Parameter();
383
384         $tmp->name               = $name;
385         $tmp->value              = $value;
386         $tmp->comment            = $comment;
387         $this->parameters[$name] = $tmp;
388     }
389
390
391     /**
392      * Remove a parameter from this type
393      *
394      * @param string $name Parameter name
395      *
396      * @return void
397      */
398     function removeParameter($name)
399     {
400         unset($this->parameters[$name]);
401     }
402
403
404     /**
405      * Autodetect a file's MIME-type
406      *
407      * This function may be called staticly.
408      *
409      * @internal Tries to use fileinfo extension at first. If that
410      *  does not work, mime_magic is used. If this is also not available
411      *  or does not succeed, "file" command is tried to be executed with
412      *  System_Command. When that fails, too, then we use our in-built
413      *  extension-to-mimetype-mapping list.
414      *
415      * @param string $file   Path to the file to get the type of
416      * @param bool   $params Append MIME parameters if true
417      *
418      * @return string $file's MIME-type on success, PEAR_Error otherwise
419      *
420      * @since 1.0.0beta1
421      * @static
422      */
423     function autoDetect($file, $params = false)
424     {
425         // Sanity checks
426         if (!file_exists($file)) {
427             return PEAR::raiseError("File \"$file\" doesn't exist");
428         }
429
430         if (!is_readable($file)) {
431             return PEAR::raiseError("File \"$file\" is not readable");
432         }
433
434         if (function_exists('finfo_file')) {
435             $finfo = finfo_open(FILEINFO_MIME);
436             $type  = finfo_file($finfo, $file);
437             finfo_close($finfo);
438             if ($type !== false && $type !== '') {
439                 return MIME_Type::_handleDetection($type, $params);
440             }
441         }
442
443         if (function_exists('mime_content_type')) {
444             $type = mime_content_type($file);
445             if ($type !== false && $type !== '') {
446                 return MIME_Type::_handleDetection($type, $params);
447             }
448         }
449
450         @include_once 'System/Command.php';
451         if (class_exists('System_Command')) {
452             return MIME_Type::_handleDetection(
453                 MIME_Type::_fileAutoDetect($file),
454                 $params
455             );
456         }
457
458         require_once 'MIME/Type/Extension.php';
459         $mte = new MIME_Type_Extension();
460         return $mte->getMIMEType($file);
461     }
462
463
464     /**
465      * Handles a detected MIME type and modifies it if necessary.
466      *
467      * @param string $type   MIME Type of a file
468      * @param bool   $params Append MIME parameters if true
469      *
470      * @return string $file's MIME-type on success, PEAR_Error otherwise
471      */
472     function _handleDetection($type, $params)
473     {
474         // _fileAutoDetect() may have returned an error.
475         if (PEAR::isError($type)) {
476             return $type;
477         }
478
479         // Don't return an empty string
480         if (!$type || !strlen($type)) {
481             return PEAR::raiseError("Sorry, couldn't determine file type.");
482         }
483
484         // Strip parameters if present & requested
485         if (MIME_Type::hasParameters($type) && !$params) {
486             $type = MIME_Type::stripParameters($type);
487         }
488
489         return $type;
490     }
491
492
493     /**
494      * Autodetect a file's MIME-type with 'file' and System_Command
495      *
496      * This function may be called staticly.
497      *
498      * @param string $file Path to the file to get the type of
499      *
500      * @return string $file's MIME-type
501      *
502      * @since 1.0.0beta1
503      * @static
504      */
505     function _fileAutoDetect($file)
506     {
507         $cmd = new System_Command();
508
509         // Make sure we have the 'file' command.
510         $fileCmd = PEAR::getStaticProperty('MIME_Type', 'fileCmd');
511         if (!$cmd->which($fileCmd)) {
512             unset($cmd);
513             return PEAR::raiseError("Can't find file command \"{$fileCmd}\"");
514         }
515
516         $cmd->pushCommand($fileCmd, "-bi " . escapeshellarg($file));
517         $res = $cmd->execute();
518         unset($cmd);
519
520         return $res;
521     }
522 }
523