You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

235 lines
7.2 KiB

<?php
/**
* Copyright 1999-2017 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
*
* @category Horde
* @copyright 1999-2017 Horde LLC
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
* @package Mime
*/
/**
* Utilities to determine MIME content-types of unknown content.
*
* @author Anil Madhavapeddy <anil@recoil.org>
* @author Michael Slusarz <slusarz@horde.org>
* @category Horde
* @copyright 1999-2017 Horde LLC
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
* @package Mime
*/
class Horde_Mime_Magic
{
/**
* The MIME extension map.
*
* @var array
*/
protected static $_map = null;
/**
* Returns a copy of the MIME extension map.
*
* @return array The MIME extension map.
*/
protected static function _getMimeExtensionMap()
{
if (is_null(self::$_map)) {
require __DIR__ . '/mime.mapping.php';
self::$_map = $mime_extension_map;
}
return self::$_map;
}
/**
* Attempt to convert a file extension to a MIME type, based
* on the global Horde and application specific config files.
*
* If we cannot map the file extension to a specific type, then
* we fall back to a custom MIME handler 'x-extension/$ext', which
* can be used as a normal MIME type internally throughout Horde.
*
* @param string $ext The file extension to be mapped to a MIME type.
*
* @return string The MIME type of the file extension.
*/
public static function extToMime($ext)
{
if (empty($ext)) {
return 'application/octet-stream';
}
$ext = Horde_String::lower($ext);
$map = self::_getMimeExtensionMap();
$pos = 0;
while (!isset($map[$ext])) {
if (($pos = strpos($ext, '.')) === false) {
break;
}
$ext = substr($ext, $pos + 1);
}
return isset($map[$ext])
? $map[$ext]
: 'x-extension/' . $ext;
}
/**
* Attempt to convert a filename to a MIME type, based on the global Horde
* and application specific config files.
*
* @param string $filename The filename to be mapped to a MIME type.
* @param boolean $unknown How should unknown extensions be handled? If
* true, will return 'x-extension/*' types. If
* false, will return 'application/octet-stream'.
*
* @return string The MIME type of the filename.
*/
public static function filenameToMime($filename, $unknown = true)
{
$pos = strlen($filename) + 1;
$type = '';
$map = self::_getMimeExtensionMap();
for ($i = 0; $i <= $map['__MAXPERIOD__']; ++$i) {
$npos = strrpos(substr($filename, 0, $pos - 1), '.');
if ($npos === false) {
break;
}
$pos = $npos + 1;
}
$type = ($pos === false) ? '' : self::extToMime(substr($filename, $pos));
return (empty($type) || (!$unknown && (strpos($type, 'x-extension') !== false)))
? 'application/octet-stream'
: $type;
}
/**
* Attempt to convert a MIME type to a file extension, based
* on the global Horde and application specific config files.
*
* If we cannot map the type to a file extension, we return false.
*
* @param string $type The MIME type to be mapped to a file extension.
*
* @return string The file extension of the MIME type.
*/
public static function mimeToExt($type)
{
if (empty($type)) {
return false;
}
if (($key = array_search($type, self::_getMimeExtensionMap())) === false) {
list($major, $minor) = explode('/', $type);
if ($major == 'x-extension') {
return $minor;
}
if (strpos($minor, 'x-') === 0) {
return substr($minor, 2);
}
return false;
}
return $key;
}
/**
* Attempt to determine the MIME type of an unknown file.
*
* @param string $path The path to the file to analyze.
* @param string $magic_db Path to the mime magic database.
* @param array $opts Additional options:
* - nostrip: (boolean) Don't strip parameter information from MIME
* type string.
* DEFAULT: false
*
* @return mixed The MIME type of the file. Returns false if the file
* type can not be determined.
*/
public static function analyzeFile($path, $magic_db = null,
$opts = array())
{
if (Horde_Util::extensionExists('fileinfo')) {
$res = empty($magic_db)
? finfo_open(FILEINFO_MIME)
: finfo_open(FILEINFO_MIME, $magic_db);
if ($res) {
$type = trim(finfo_file($res, $path));
finfo_close($res);
/* Remove any additional information. */
if (empty($opts['nostrip'])) {
foreach (array(';', ',', '\\0') as $separator) {
if (($pos = strpos($type, $separator)) !== false) {
$type = rtrim(substr($type, 0, $pos));
}
}
if (preg_match('|^[a-z0-9]+/[.-a-z0-9]+$|i', $type)) {
return $type;
}
} else {
return $type;
}
}
}
return false;
}
/**
* Attempt to determine the MIME type of an unknown byte stream.
*
* @param string $data The file data to analyze.
* @param string $magic_db Path to the mime magic database.
* @param array $opts Additional options:
* - nostrip: (boolean) Don't strip parameter information from MIME
* type string.
* DEFAULT: false
*
* @return mixed The MIME type of the file. Returns false if the file
* type can not be determined.
*/
public static function analyzeData($data, $magic_db = null,
$opts = array())
{
/* If the PHP Mimetype extension is available, use that. */
if (Horde_Util::extensionExists('fileinfo')) {
$res = empty($magic_db)
? @finfo_open(FILEINFO_MIME)
: @finfo_open(FILEINFO_MIME, $magic_db);
if (!$res) {
return false;
}
$type = trim(finfo_buffer($res, $data));
finfo_close($res);
/* Remove any additional information. */
if (empty($opts['nostrip'])) {
if (($pos = strpos($type, ';')) !== false) {
$type = rtrim(substr($type, 0, $pos));
}
if (($pos = strpos($type, ',')) !== false) {
$type = rtrim(substr($type, 0, $pos));
}
}
return $type;
}
return false;
}
}