1 -- byte number to begin checking from. ">" indicates a dependency * upon the previous non-">" line * o 2 -- type of data to match. Can be one of following * - byte (single character) * - short (machine-order 16-bit integer) * - long (machine-order 32-bit integer) * - string (arbitrary-length string) * - date (long integer date (seconds since Unix epoch/1970)) * - beshort (big-endian 16-bit integer) * - belong (big-endian 32-bit integer) * - bedate (big-endian 32-bit integer date) * - leshort (little-endian 16-bit integer) * - lelong (little-endian 32-bit integer) * - ledate (little-endian 32-bit integer date) * o 3 -- contents of data to match * o 4 -- file description/MIME type if matched * o 5 -- optional MIME encoding if matched and if above was a MIME type * * @package php-reader * @author Sven Vollbehr * @copyright Copyright (c) 2006-2008 PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev: 73 $ */ final class Magic { /** @var string */ private $_magic; /** * Reads the magic information from given magic file. * * @param string $filename The path to the magic file. */ public function __construct($filename) { $reader = new Reader($filename); $this->_magic = $reader->read($reader->getSize()); } /** * Returns the recognized MIME type/description of the given file. The type * is determined by the content using magic bytes characteristic for the * particular file type. * * If the type could not be found, the function returns the default value, or * false. * * @param string $filename The file path whose type to determine. * @param string $default The default value. * @return string|false */ public function getType($filename, $default = false) { $reader = new Reader($filename); $parentOffset = 0; foreach (preg_split("/^/m", $this->_magic) as $line) { $chunks = array(); if (!preg_match("/^(?P>?)(?P\d+)\s+(?P\S+)" . "\s+(?P\S+)(?:\s+(?P[a-z]+\/[a-z-" . "0-9]+)?(?:\s+(?P.+))?)?$/", $line, $chunks)) continue; if ($chunks["Dependant"]) { $reader->setOffset($parentOffset); $reader->skip($chunks["Byte"]); } else $reader->setOffset($parentOffset = $chunks["Byte"]); $matchType = strtolower($chunks["MatchType"]); $matchData = preg_replace (array("/\\\\ /", "/\\\\\\\\/", "/\\\\([0-7]{1,3})/e", "/\\\\x([0-9A-Fa-f]{1,2})/e", "/0x([0-9A-Fa-f]+)/e"), array(" ", "\\\\", "pack(\"H*\", base_convert(\"$1\", 8, 16));", "pack(\"H*\", \"$1\");", "hexdec(\"$1\");"), $chunks["MatchData"]); switch ($matchType) { case "byte": // single character $data = $reader->readInt8(); break; case "short": // machine-order 16-bit integer $data = $reader->readInt16(); break; case "long": // machine-order 32-bit integer $data = $reader->readInt32(); break; case "string": // arbitrary-length string $data = $reader->readString8(strlen($matchData)); break; case "date": // long integer date (seconds since Unix epoch/1970) $data = $reader->readInt64BE(); break; case "beshort": // big-endian 16-bit integer $data = $reader->readUInt16BE(); break; case "belong": // big-endian 32-bit integer case "bedate": // big-endian 32-bit integer date $data = $reader->readUInt32BE(); break; case "leshort": // little-endian 16-bit integer $data = $reader->readUInt16LE(); break; case "lelong": // little-endian 32-bit integer case "ledate": // little-endian 32-bit integer date $data = $reader->readUInt32LE(); break; default: $data = null; break; } if (strcmp($data, $matchData) == 0) { if (!empty($chunks["MIMEType"])) return $chunks["MIMEType"]; if (!empty($chunks["Description"])) return $chunks["Description"]; } } return $default; } }