/** * 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 <var>null</var>. * * @param string $filename The file path whose type to determine. * @param string $default The default value. * @return string|false */ public function getMimeType($filename, $default = null) { $reader = new HausDesign_Io_FileReader($filename); $parentOffset = 0; foreach (preg_split('/^/m', $this->_magic) as $line) { $chunks = array(); if (!preg_match("/^(?P<Dependant>>?)(?P<Byte>\\d+)\\s+(?P<MatchType" . ">\\S+)\\s+(?P<MatchData>\\S+)(?:\\s+(?P<MIMEType>[a-" . "z]+\\/[a-z-0-9]+)?(?:\\s+(?P<Description>.?+))?)?\$/", $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) $data = $reader->readInt64BE(); break; case 'beshort': // big-endian 16-bit integer $data = $reader->readUInt16BE(); break; case 'belong': // big-endian 32-bit integer // break intentionally omitted // big-endian 32-bit integer // break intentionally omitted 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 // break intentionally omitted // little-endian 32-bit integer // break intentionally omitted 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 rtrim($chunks['Description'], "\n"); } } } return $default; }