1<?php 2/* vim: set expandtab tabstop=4 shiftwidth=4: */ 3// +----------------------------------------------------------------------+ 4// | PHP version 4 | 5// +----------------------------------------------------------------------+ 6// | Copyright (c) 1997-2002 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.2 2004/08/07 22:19:04 ieure Exp $ 20 21require_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 * @version 1.0.0 30 * @package MIME_Type 31 * @author Ian Eure <ieure@php.net> 32 */ 33class MIME_Type { 34 /** 35 * The MIME media type 36 * 37 * @var string 38 */ 39 var $media = ''; 40 41 /** 42 * The MIME media sub-type 43 * 44 * @var string 45 */ 46 var $subType = ''; 47 48 /** 49 * Optional MIME parameters 50 * 51 * @var array 52 */ 53 var $parameters = array(); 54 55 /** 56 * List of valid media types 57 * 58 * @var array 59 */ 60 var $validMediaTypes = array( 61 'text', 62 'image', 63 'audio', 64 'video', 65 'application', 66 'multipart', 67 'message' 68 ); 69 70 71 /** 72 * Constructor. 73 * 74 * If $type is set, if will be parsed and the appropriate class vars set. If not, 75 * you get an empty class. This is useful, but not quite as useful as parsing a 76 * type. 77 * 78 * @param string $type MIME type 79 * @return void 80 */ 81 function MIME_Type($type = false) 82 { 83 if ($type) { 84 $this->parse($type); 85 } 86 } 87 88 89 /** 90 * Parse a mime-type 91 * 92 * @param $type string MIME type to parse 93 * @return void 94 */ 95 function parse($type) 96 { 97 $this->media = $this->getMedia($type); 98 $this->subType = $this->getSubType($type); 99 if (MIME_Type::hasParameters($type)) { 100 require_once 'MIME/Type/Parameter.php'; 101 foreach (MIME_Type::getParameters($type) as $param) { 102 $param = &new MIME_Type_Parameter($param); 103 $this->parameters[$param->name] = $param; 104 } 105 } 106 } 107 108 109 /** 110 * Does this type have any parameters? 111 * 112 * @param $type string MIME type to check 113 * @return boolean true if $type has parameters, false otherwise 114 * @static 115 */ 116 function hasParameters($type) 117 { 118 if (strstr($type, ';')) { 119 return true; 120 } 121 return false; 122 } 123 124 125 /** 126 * Get a MIME type's parameters 127 * 128 * @param $type string MIME type to get parameters of 129 * @return array $type's parameters 130 * @static 131 */ 132 function getParameters($type) 133 { 134 $params = array(); 135 $tmp = explode(';', $type); 136 for ($i = 1; $i < count($tmp); $i++) { 137 $params[] = trim($tmp[$i]); 138 } 139 return $params; 140 } 141 142 143 /** 144 * Strip paramaters from a MIME type string 145 * 146 * @param string $type MIME type string 147 * @return string MIME type with parameters removed 148 * @static 149 */ 150 function stripParameters($type) 151 { 152 if (strstr($type, ';')) { 153 return substr($type, 0, strpos($type, ';')); 154 } 155 return $type; 156 } 157 158 159 /** 160 * Get a MIME type's media 161 * 162 * @note 'media' refers to the portion before the first slash 163 * @param $type string MIME type to get media of 164 * @return string $type's media 165 * @static 166 */ 167 function getMedia($type) 168 { 169 $tmp = explode('/', $type); 170 return strtolower($tmp[0]); 171 } 172 173 174 /** 175 * Get a MIME type's subtype 176 * 177 * @param $type string MIME type to get subtype of 178 * @return string $type's subtype 179 * @static 180 */ 181 function getSubType($type) 182 { 183 $tmp = explode('/', $type); 184 $tmp = explode(';', $tmp[1]); 185 return strtolower(trim($tmp[0])); 186 } 187 188 189 /** 190 * Create a textual MIME type from object values 191 * 192 * This function performs the opposite function of parse(). 193 * 194 * @return string MIME type string 195 */ 196 function get() 197 { 198 $type = strtolower($this->media.'/'.$this->subType); 199 if (count($this->parameters)) { 200 foreach ($this->parameters as $key => $null) { 201 $type .= '; '.$this->parameters[$key]->get(); 202 } 203 } 204 return $type; 205 } 206 207 208 /** 209 * Is this type experimental? 210 * 211 * @note Experimental types are denoted by a leading 'x-' in the media or 212 * subtype, e.g. text/x-vcard or x-world/x-vrml. 213 * @param string $type MIME type to check 214 * @return boolean true if $type is experimental, false otherwise 215 * @static 216 */ 217 function isExperimental($type) 218 { 219 if (substr(MIME_Type::getMedia($type), 0, 2) == 'x-' || 220 substr(MIME_Type::getSubType($type), 0, 2) == 'x-') { 221 return true; 222 } 223 return false; 224 } 225 226 227 /** 228 * Is this a vendor MIME type? 229 * 230 * @note Vendor types are denoted with a leading 'vnd. in the subtype. 231 * @param string $type MIME type to check 232 * @return boolean true if $type is a vendor type, false otherwise 233 * @static 234 */ 235 function isVendor($type) 236 { 237 if (substr(MIME_Type::getSubType($type), 0, 4) == 'vnd.') { 238 return true; 239 } 240 return false; 241 } 242 243 244 /** 245 * Is this a wildcard type? 246 * 247 * @param string $type MIME type to check 248 * @return boolean true if $type is a wildcard, false otherwise 249 * @static 250 */ 251 function isWildcard($type) 252 { 253 if ($type == '*/*' || MIME_Type::getSubtype($type) == '*') { 254 return true; 255 } 256 return false; 257 } 258 259 260 /** 261 * Perform a wildcard match on a MIME type 262 * 263 * Example: 264 * MIME_Type::wildcardMatch('image/*', 'image/png') 265 * 266 * @param string $card Wildcard to check against 267 * @param string $type MIME type to check 268 * @return boolean true if there was a match, false otherwise 269 */ 270 function wildcardMatch($card, $type) 271 { 272 if (!MIME_Type::isWildcard($card)) { 273 return false; 274 } 275 276 if ($card == '*/*') { 277 return true; 278 } 279 280 if (MIME_Type::getMedia($card) == 281 MIME_Type::getMedia($type)) { 282 return true; 283 } 284 return false; 285 } 286 287 288 /** 289 * Add a parameter to this type 290 * 291 * @param string $name Attribute name 292 * @param string $value Attribute value 293 * @param string $comment Comment for this parameter 294 * @return void 295 */ 296 function addParameter($name, $value, $comment = false) 297 { 298 $tmp = &new MIME_Type_Parameter; 299 $tmp->name = $name; 300 $tmp->value = $value; 301 $tmp->comment = $comment; 302 $this->parameters[$name] = $tmp; 303 } 304 305 306 /** 307 * Remove a parameter from this type 308 * 309 * @param string $name Parameter name 310 * @return void 311 */ 312 function removeParameter($name) 313 { 314 unset ($this->parameters[$name]); 315 } 316 317 318 /** 319 * Autodetect a file's MIME-type 320 * 321 * This function may be called staticly. 322 * 323 * @param string $file Path to the file to get the type of 324 * @param bool $params Append MIME parameters if true 325 * @return string $file's MIME-type on success, PEAR_Error otherwise 326 * @since 1.0.0beta1 327 * @static 328 */ 329 function autoDetect($file, $params = false) 330 { 331 @include_once 'System/Command.php'; 332 if (function_exists('mime_content_type')) { 333 $type = mime_content_type($file); 334 } else if (class_exists('System_Command')) { 335 $type = MIME_Type::_fileAutoDetect($file); 336 } else { 337 return PEAR::raiseError("Sorry, can't autodetect; you need the mime_magic extension or System_Command and 'file' installed to use this function."); 338 } 339 340 // _fileAutoDetect() may have returned an error. 341 if (PEAR::isError($type)) { 342 return $type; 343 } 344 345 // Don't return an empty string 346 if (!$type || !strlen($type)) { 347 return PEAR::raiseError("Sorry, couldn't determine file type."); 348 } 349 350 // Strip parameters if present & requested 351 if (MIME_Type::hasParameters($type) && !$params) { 352 $type = MIME_Type::stripParameters($type); 353 } 354 355 return $type; 356 } 357 358 /** 359 * Autodetect a file's MIME-type with 'file' and System_Command 360 * 361 * This function may be called staticly. 362 * 363 * @param string $file Path to the file to get the type of 364 * @return string $file's MIME-type 365 * @since 1.0.0beta1 366 * @static 367 */ 368 function _fileAutoDetect($file) 369 { 370 // Sanity checks 371 if (!file_exists($file)) { 372 return PEAR::raiseError("File \"$file\" doesn't exist"); 373 } 374 375 if (!is_readable($file)) { 376 return PEAR::raiseError("File \"$file\" is not readable"); 377 } 378 379 $cmd = new System_Command; 380 381 382 // Make sure we have the 'file' command. 383 $fileCmd = PEAR::getStaticProperty('MIME_Type', 'fileCmd'); 384 if (!$cmd->which($fileCmd)) { 385 unset($cmd); 386 return PEAR::raiseError("Can't find file command \"{$fileCmd}\""); 387 } 388 389 $cmd->pushCommand($fileCmd, "-bi '{$file}'"); 390 $res = $cmd->execute(); 391 unset($cmd); 392 393 return $res; 394 } 395}