PageRenderTime 41ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Zend/Validate/File/MimeType.php

https://bitbucket.org/Ebozavrik/test-application
PHP | 440 lines | 220 code | 50 blank | 170 comment | 39 complexity | 50f37b2691e0adf82af0999e4be35220 MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Validate
  17. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id: MimeType.php 24593 2012-01-05 20:35:02Z matthew $
  20. */
  21. /**
  22. * @see Zend_Validate_Abstract
  23. */
  24. require_once 'Zend/Validate/Abstract.php';
  25. /**
  26. * Validator for the mime type of a file
  27. *
  28. * @category Zend
  29. * @package Zend_Validate
  30. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  31. * @license http://framework.zend.com/license/new-bsd New BSD License
  32. */
  33. class Zend_Validate_File_MimeType extends Zend_Validate_Abstract
  34. {
  35. /**#@+
  36. * @const Error type constants
  37. */
  38. const FALSE_TYPE = 'fileMimeTypeFalse';
  39. const NOT_DETECTED = 'fileMimeTypeNotDetected';
  40. const NOT_READABLE = 'fileMimeTypeNotReadable';
  41. /**#@-*/
  42. /**
  43. * @var array Error message templates
  44. */
  45. protected $_messageTemplates = array(
  46. self::FALSE_TYPE => "File '%value%' has a false mimetype of '%type%'",
  47. self::NOT_DETECTED => "The mimetype of file '%value%' could not be detected",
  48. self::NOT_READABLE => "File '%value%' is not readable or does not exist",
  49. );
  50. /**
  51. * @var array
  52. */
  53. protected $_messageVariables = array(
  54. 'type' => '_type'
  55. );
  56. /**
  57. * @var string
  58. */
  59. protected $_type;
  60. /**
  61. * Mimetypes
  62. *
  63. * If null, there is no mimetype
  64. *
  65. * @var string|null
  66. */
  67. protected $_mimetype;
  68. /**
  69. * Magicfile to use
  70. *
  71. * @var string|null
  72. */
  73. protected $_magicfile;
  74. /**
  75. * Finfo object to use
  76. *
  77. * @var resource
  78. */
  79. protected $_finfo;
  80. /**
  81. * If no $_ENV['MAGIC'] is set, try and autodiscover it based on common locations
  82. * @var array
  83. */
  84. protected $_magicFiles = array(
  85. '/usr/share/misc/magic',
  86. '/usr/share/misc/magic.mime',
  87. '/usr/share/misc/magic.mgc',
  88. '/usr/share/mime/magic',
  89. '/usr/share/mime/magic.mime',
  90. '/usr/share/mime/magic.mgc',
  91. '/usr/share/file/magic',
  92. '/usr/share/file/magic.mime',
  93. '/usr/share/file/magic.mgc',
  94. );
  95. /**
  96. * Indicates whether use of $_magicFiles should be attempted.
  97. * @var boolean
  98. */
  99. protected $_tryCommonMagicFiles = true;
  100. /**
  101. * Option to allow header check
  102. *
  103. * @var boolean
  104. */
  105. protected $_headerCheck = false;
  106. /**
  107. * Sets validator options
  108. *
  109. * Mimetype to accept
  110. *
  111. * @param string|array $mimetype MimeType
  112. *
  113. * @return void
  114. */
  115. public function __construct ($mimetype)
  116. {
  117. if ($mimetype instanceof Zend_Config) {
  118. $mimetype = $mimetype->toArray();
  119. } elseif (is_string($mimetype)) {
  120. $mimetype = explode(',', $mimetype);
  121. } elseif (!is_array($mimetype)) {
  122. require_once 'Zend/Validate/Exception.php';
  123. throw new Zend_Validate_Exception( "Invalid options to validator provided" );
  124. }
  125. if (isset( $mimetype['magicfile'] )) {
  126. $this->setMagicFile($mimetype['magicfile']);
  127. unset( $mimetype['magicfile'] );
  128. }
  129. if (isset( $mimetype['headerCheck'] )) {
  130. $this->enableHeaderCheck($mimetype['headerCheck']);
  131. unset( $mimetype['headerCheck'] );
  132. }
  133. $this->setMimeType($mimetype);
  134. }
  135. /**
  136. * Returns the actual set magicfile
  137. *
  138. * @return string
  139. */
  140. public function getMagicFile ()
  141. {
  142. if (null === $this->_magicfile) {
  143. if (!empty( $_ENV['MAGIC'] )) {
  144. $this->setMagicFile($_ENV['MAGIC']);
  145. } elseif (
  146. !( @ini_get("safe_mode") == 'On' || @ini_get("safe_mode") === 1 )
  147. && $this->shouldTryCommonMagicFiles() // @see ZF-11784
  148. ) {
  149. require_once 'Zend/Validate/Exception.php';
  150. foreach ($this->_magicFiles as $file) {
  151. // supressing errors which are thrown due to openbase_dir restrictions
  152. try {
  153. $this->setMagicFile($file);
  154. if ($this->_magicfile !== null) {
  155. break;
  156. }
  157. } catch (Zend_Validate_Exception $e) {
  158. // Intentionally, catch and fall through
  159. }
  160. }
  161. }
  162. if ($this->_magicfile === null) {
  163. $this->_magicfile = false;
  164. }
  165. }
  166. return $this->_magicfile;
  167. }
  168. /**
  169. * Sets the magicfile to use
  170. * if null, the MAGIC constant from php is used
  171. * if the MAGIC file is errorous, no file will be set
  172. *
  173. * @param string $file
  174. *
  175. * @throws Zend_Validate_Exception When finfo can not read the magicfile
  176. * @return Zend_Validate_File_MimeType Provides fluid interface
  177. */
  178. public function setMagicFile ($file)
  179. {
  180. if (empty( $file )) {
  181. $this->_magicfile = null;
  182. } else if (!( class_exists('finfo', false) )) {
  183. $this->_magicfile = null;
  184. require_once 'Zend/Validate/Exception.php';
  185. throw new Zend_Validate_Exception( 'Magicfile can not be set. There is no finfo extension installed' );
  186. } else if (!is_file($file) || !is_readable($file)) {
  187. require_once 'Zend/Validate/Exception.php';
  188. throw new Zend_Validate_Exception( 'The given magicfile can not be read' );
  189. } else {
  190. $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME;
  191. $this->_finfo = @finfo_open($const, $file);
  192. if (empty( $this->_finfo )) {
  193. $this->_finfo = null;
  194. require_once 'Zend/Validate/Exception.php';
  195. throw new Zend_Validate_Exception( 'The given magicfile is not accepted by finfo' );
  196. } else {
  197. $this->_magicfile = $file;
  198. }
  199. }
  200. return $this;
  201. }
  202. /**
  203. * Enables or disables attempts to try the common magic file locations
  204. * specified by Zend_Validate_File_MimeType::_magicFiles
  205. *
  206. * @param boolean $flag
  207. *
  208. * @return Zend_Validate_File_MimeType Provides fluent interface
  209. * @see http://framework.zend.com/issues/browse/ZF-11784
  210. */
  211. public function setTryCommonMagicFilesFlag ($flag = true)
  212. {
  213. $this->_tryCommonMagicFiles = (boolean)$flag;
  214. return $this;
  215. }
  216. /**
  217. * Accessor for Zend_Validate_File_MimeType::_magicFiles
  218. *
  219. * @return boolean
  220. * @see http://framework.zend.com/issues/browse/ZF-11784
  221. */
  222. public function shouldTryCommonMagicFiles ()
  223. {
  224. return $this->_tryCommonMagicFiles;
  225. }
  226. /**
  227. * Returns the Header Check option
  228. *
  229. * @return boolean
  230. */
  231. public function getHeaderCheck ()
  232. {
  233. return $this->_headerCheck;
  234. }
  235. /**
  236. * Defines if the http header should be used
  237. * Note that this is unsave and therefor the default value is false
  238. *
  239. * @param boolean $checkHeader
  240. *
  241. * @return Zend_Validate_File_MimeType Provides fluid interface
  242. */
  243. public function enableHeaderCheck ($headerCheck = true)
  244. {
  245. $this->_headerCheck = (boolean)$headerCheck;
  246. return $this;
  247. }
  248. /**
  249. * Returns the set mimetypes
  250. *
  251. * @param boolean $asArray Returns the values as array, when false an concated string is returned
  252. *
  253. * @return string|array
  254. */
  255. public function getMimeType ($asArray = false)
  256. {
  257. $asArray = (bool)$asArray;
  258. $mimetype = (string)$this->_mimetype;
  259. if ($asArray) {
  260. $mimetype = explode(',', $mimetype);
  261. }
  262. return $mimetype;
  263. }
  264. /**
  265. * Sets the mimetypes
  266. *
  267. * @param string|array $mimetype The mimetypes to validate
  268. *
  269. * @return Zend_Validate_File_Extension Provides a fluent interface
  270. */
  271. public function setMimeType ($mimetype)
  272. {
  273. $this->_mimetype = null;
  274. $this->addMimeType($mimetype);
  275. return $this;
  276. }
  277. /**
  278. * Adds the mimetypes
  279. *
  280. * @param string|array $mimetype The mimetypes to add for validation
  281. *
  282. * @return Zend_Validate_File_Extension Provides a fluent interface
  283. */
  284. public function addMimeType ($mimetype)
  285. {
  286. $mimetypes = $this->getMimeType(true);
  287. if (is_string($mimetype)) {
  288. $mimetype = explode(',', $mimetype);
  289. } elseif (!is_array($mimetype)) {
  290. require_once 'Zend/Validate/Exception.php';
  291. throw new Zend_Validate_Exception( "Invalid options to validator provided" );
  292. }
  293. if (isset( $mimetype['magicfile'] )) {
  294. unset( $mimetype['magicfile'] );
  295. }
  296. foreach ($mimetype as $content) {
  297. if (empty( $content ) || !is_string($content)) {
  298. continue;
  299. }
  300. $mimetypes[] = trim($content);
  301. }
  302. $mimetypes = array_unique($mimetypes);
  303. // Sanity check to ensure no empty values
  304. foreach ($mimetypes as $key => $mt) {
  305. if (empty( $mt )) {
  306. unset( $mimetypes[$key] );
  307. }
  308. }
  309. $this->_mimetype = implode(',', $mimetypes);
  310. return $this;
  311. }
  312. /**
  313. * Defined by Zend_Validate_Interface
  314. *
  315. * Returns true if the mimetype of the file matches the given ones. Also parts
  316. * of mimetypes can be checked. If you give for example "image" all image
  317. * mime types will be accepted like "image/gif", "image/jpeg" and so on.
  318. *
  319. * @param string $value Real file to check for mimetype
  320. * @param array $file File data from Zend_File_Transfer
  321. *
  322. * @return boolean
  323. */
  324. public function isValid ($value, $file = null)
  325. {
  326. if ($file === null) {
  327. $file = array(
  328. 'type' => null,
  329. 'name' => $value
  330. );
  331. }
  332. // Is file readable ?
  333. require_once 'Zend/Loader.php';
  334. if (!Zend_Loader::isReadable($value)) {
  335. return $this->_throw($file, self::NOT_READABLE);
  336. }
  337. $mimefile = $this->getMagicFile();
  338. if (class_exists('finfo', false)) {
  339. $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME;
  340. if (!empty( $mimefile ) && empty( $this->_finfo )) {
  341. $this->_finfo = @finfo_open($const, $mimefile);
  342. }
  343. if (empty( $this->_finfo )) {
  344. $this->_finfo = @finfo_open($const);
  345. }
  346. $this->_type = null;
  347. if (!empty( $this->_finfo )) {
  348. $this->_type = finfo_file($this->_finfo, $value);
  349. }
  350. }
  351. if (empty( $this->_type ) &&
  352. ( function_exists('mime_content_type') && ini_get('mime_magic.magicfile') )
  353. ) {
  354. $this->_type = mime_content_type($value);
  355. }
  356. if (empty( $this->_type ) && $this->_headerCheck) {
  357. $this->_type = $file['type'];
  358. }
  359. if (empty( $this->_type )) {
  360. return $this->_throw($file, self::NOT_DETECTED);
  361. }
  362. $mimetype = $this->getMimeType(true);
  363. if (in_array($this->_type, $mimetype)) {
  364. return true;
  365. }
  366. $types = explode('/', $this->_type);
  367. $types = array_merge($types, explode('-', $this->_type));
  368. $types = array_merge($types, explode(';', $this->_type));
  369. foreach ($mimetype as $mime) {
  370. if (in_array($mime, $types)) {
  371. return true;
  372. }
  373. }
  374. return $this->_throw($file, self::FALSE_TYPE);
  375. }
  376. /**
  377. * Throws an error of the given type
  378. *
  379. * @param string $file
  380. * @param string $errorType
  381. *
  382. * @return false
  383. */
  384. protected function _throw ($file, $errorType)
  385. {
  386. $this->_value = $file['name'];
  387. $this->_error($errorType);
  388. return false;
  389. }
  390. }