PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/horde-3.3.13/lib/Horde/MIME/Magic.php

#
PHP | 272 lines | 156 code | 27 blank | 89 comment | 40 complexity | 3be706f2e58f6abfc24e01d543598439 MD5 | raw file
Possible License(s): LGPL-2.0
  1. <?php
  2. require_once 'Horde/Util.php';
  3. /**
  4. * The MIME_Magic:: class provides an interface to determine a
  5. * MIME type for various content, if it provided with different
  6. * levels of information.
  7. *
  8. * $Horde: framework/MIME/MIME/Magic.php,v 1.52.8.18 2009/01/06 15:23:20 jan Exp $
  9. *
  10. * Copyright 1999-2009 The Horde Project (http://www.horde.org/)
  11. *
  12. * See the enclosed file COPYING for license information (LGPL). If you
  13. * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  14. *
  15. * @author Anil Madhavapeddy <anil@recoil.org>
  16. * @author Michael Slusarz <slusarz@horde.org>
  17. * @package Horde_MIME
  18. */
  19. class MIME_Magic {
  20. /**
  21. * Returns a copy of the MIME extension map.
  22. *
  23. * @access private
  24. *
  25. * @return array The MIME extension map.
  26. */
  27. function _getMimeExtensionMap()
  28. {
  29. static $mime_extension_map;
  30. if (!isset($mime_extension_map)) {
  31. require dirname(__FILE__) . '/mime.mapping.php';
  32. }
  33. return $mime_extension_map;
  34. }
  35. /**
  36. * Returns a copy of the MIME magic file.
  37. *
  38. * @access private
  39. *
  40. * @return array The MIME magic file.
  41. */
  42. function _getMimeMagicFile()
  43. {
  44. static $mime_magic;
  45. if (!isset($mime_magic)) {
  46. require dirname(__FILE__) . '/mime.magic.php';
  47. }
  48. return $mime_magic;
  49. }
  50. /**
  51. * Attempt to convert a file extension to a MIME type, based
  52. * on the global Horde and application specific config files.
  53. *
  54. * If we cannot map the file extension to a specific type, then
  55. * we fall back to a custom MIME handler 'x-extension/$ext', which
  56. * can be used as a normal MIME type internally throughout Horde.
  57. *
  58. * @param string $ext The file extension to be mapped to a MIME type.
  59. *
  60. * @return string The MIME type of the file extension.
  61. */
  62. function extToMIME($ext)
  63. {
  64. if (empty($ext)) {
  65. return 'application/octet-stream';
  66. } else {
  67. $ext = String::lower($ext);
  68. $map = MIME_Magic::_getMimeExtensionMap();
  69. $pos = 0;
  70. while (!isset($map[$ext]) && $pos !== false) {
  71. $pos = strpos($ext, '.');
  72. if ($pos !== false) {
  73. $ext = substr($ext, $pos + 1);
  74. }
  75. }
  76. if (isset($map[$ext])) {
  77. return $map[$ext];
  78. } else {
  79. return 'x-extension/' . $ext;
  80. }
  81. }
  82. }
  83. /**
  84. * Attempt to convert a filename to a MIME type, based on the global Horde
  85. * and application specific config files.
  86. *
  87. * @param string $filename The filename to be mapped to a MIME type.
  88. * @param boolean $unknown How should unknown extensions be handled? If
  89. * true, will return 'x-extension/*' types. If
  90. * false, will return 'application/octet-stream'.
  91. *
  92. * @return string The MIME type of the filename.
  93. */
  94. function filenameToMIME($filename, $unknown = true)
  95. {
  96. $pos = strlen($filename) + 1;
  97. $type = '';
  98. $map = MIME_Magic::_getMimeExtensionMap();
  99. for ($i = 0;
  100. $i <= $map['__MAXPERIOD__'] &&
  101. strrpos(substr($filename, 0, $pos - 1), '.') !== false;
  102. $i++) {
  103. $pos = strrpos(substr($filename, 0, $pos - 1), '.') + 1;
  104. }
  105. $type = MIME_Magic::extToMIME(substr($filename, $pos));
  106. if (empty($type) ||
  107. (!$unknown && (strpos($type, 'x-extension') !== false))) {
  108. return 'application/octet-stream';
  109. } else {
  110. return $type;
  111. }
  112. }
  113. /**
  114. * Attempt to convert a MIME type to a file extension, based
  115. * on the global Horde and application specific config files.
  116. *
  117. * If we cannot map the type to a file extension, we return false.
  118. *
  119. * @param string $type The MIME type to be mapped to a file extension.
  120. *
  121. * @return string The file extension of the MIME type.
  122. */
  123. function MIMEToExt($type)
  124. {
  125. if (empty($type)) {
  126. return false;
  127. }
  128. $key = array_search($type, MIME_Magic::_getMimeExtensionMap());
  129. if ($key === false) {
  130. list($major, $minor) = explode('/', $type);
  131. if ($major == 'x-extension') {
  132. return $minor;
  133. }
  134. if (strpos($minor, 'x-') === 0) {
  135. return substr($minor, 2);
  136. }
  137. return false;
  138. } else {
  139. return $key;
  140. }
  141. }
  142. /**
  143. * Uses variants of the UNIX "file" command to attempt to determine the
  144. * MIME type of an unknown file.
  145. *
  146. * @param string $path The path to the file to analyze.
  147. * @param string $magic_db Path to the mime magic database.
  148. *
  149. * @return string The MIME type of the file. Returns false if the file
  150. * type isn't recognized or an error happened.
  151. */
  152. function analyzeFile($path, $magic_db = null)
  153. {
  154. /* If the PHP Mimetype extension is available, use that. */
  155. if (Util::extensionExists('fileinfo')) {
  156. if (empty($magic_db)) {
  157. $res = @finfo_open(FILEINFO_MIME);
  158. } else {
  159. $res = @finfo_open(FILEINFO_MIME, $magic_db);
  160. }
  161. if ($res) {
  162. $type = finfo_file($res, $path);
  163. finfo_close($res);
  164. /* Remove any additional information. */
  165. foreach (array(';', ',', '\\0') as $separator) {
  166. $pos = strpos($type, $separator);
  167. if ($pos !== false) {
  168. $type = rtrim(substr($type, 0, $pos));
  169. }
  170. }
  171. if (preg_match('|^[a-z0-9]+/[.-a-z0-9]+$|i', $type)) {
  172. return $type;
  173. }
  174. }
  175. }
  176. if (Util::extensionExists('mime_magic')) {
  177. return trim(mime_content_type($path));
  178. } else {
  179. /* Use a built-in magic file. */
  180. $mime_magic = MIME_Magic::_getMimeMagicFile();
  181. if (!($fp = @fopen($path, 'rb'))) {
  182. return false;
  183. }
  184. while (list($offset, $odata) = each($mime_magic)) {
  185. while (list($length, $ldata) = each($odata)) {
  186. @fseek($fp, $offset, SEEK_SET);
  187. $lookup = @fread($fp, $length);
  188. if (!empty($ldata[$lookup])) {
  189. fclose($fp);
  190. return $ldata[$lookup];
  191. }
  192. }
  193. }
  194. fclose($fp);
  195. }
  196. return false;
  197. }
  198. /**
  199. * Uses variants of the UNIX "file" command to attempt to determine the
  200. * MIME type of an unknown byte stream.
  201. *
  202. * @param string $data The file data to analyze.
  203. * @param string $magic_db Path to the mime magic database.
  204. *
  205. * @return string The MIME type of the file. Returns false if the file
  206. * type isn't recognized or an error happened.
  207. */
  208. function analyzeData($data, $magic_db = null)
  209. {
  210. /* If the PHP Mimetype extension is available, use that. */
  211. if (Util::extensionExists('fileinfo')) {
  212. if (empty($magic_db)) {
  213. $res = @finfo_open(FILEINFO_MIME);
  214. } else {
  215. $res = @finfo_open(FILEINFO_MIME, $magic_db);
  216. }
  217. if (!$res) {
  218. return false;
  219. }
  220. $type = finfo_buffer($res, $data);
  221. finfo_close($res);
  222. /* Remove any additional information. */
  223. $pos = strpos($type, ';');
  224. if ($pos !== false) {
  225. $type = rtrim(substr($type, 0, $pos));
  226. }
  227. $pos = strpos($type, ',');
  228. if ($pos !== false) {
  229. $type = rtrim(substr($type, 0, $pos));
  230. }
  231. return $type;
  232. }
  233. /* Use a built-in magic file. */
  234. $mime_magic = MIME_Magic::_getMimeMagicFile();
  235. while (list($offset, $odata) = each($mime_magic)) {
  236. while (list($length, $ldata) = each($odata)) {
  237. $lookup = substr($data, $offset, $length);
  238. if (!empty($ldata[$lookup])) {
  239. return $ldata[$lookup];
  240. }
  241. }
  242. }
  243. return false;
  244. }
  245. }