Size.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  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-2009 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id$
  20. */
  21. /**
  22. * @see Zend_Validate_Abstract
  23. */
  24. require_once 'Zend/Validate/Abstract.php';
  25. /**
  26. * Validator for the maximum size of a file up to a max of 2GB
  27. *
  28. * @category Zend
  29. * @package Zend_Validate
  30. * @copyright Copyright (c) 2005-2009 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_Size extends Zend_Validate_Abstract
  34. {
  35. /**#@+
  36. * @const string Error constants
  37. */
  38. const TOO_BIG = 'fileSizeTooBig';
  39. const TOO_SMALL = 'fileSizeTooSmall';
  40. const NOT_FOUND = 'fileSizeNotFound';
  41. /**#@-*/
  42. /**
  43. * @var array Error message templates
  44. */
  45. protected $_messageTemplates = array(
  46. self::TOO_BIG => "Maximum allowed size for file '%value%' is '%max%' but '%size%' detected",
  47. self::TOO_SMALL => "Minimum expected size for file '%value%' is '%min%' but '%size%' detected",
  48. self::NOT_FOUND => "The file '%value%' could not be found"
  49. );
  50. /**
  51. * @var array Error message template variables
  52. */
  53. protected $_messageVariables = array(
  54. 'min' => '_min',
  55. 'max' => '_max',
  56. 'size' => '_size',
  57. );
  58. /**
  59. * Minimum filesize
  60. * @var integer
  61. */
  62. protected $_min;
  63. /**
  64. * Maximum filesize
  65. *
  66. * If null, there is no maximum filesize
  67. *
  68. * @var integer|null
  69. */
  70. protected $_max;
  71. /**
  72. * Detected size
  73. *
  74. * @var integer
  75. */
  76. protected $_size;
  77. /**
  78. * Use bytestring ?
  79. *
  80. * @var boolean
  81. */
  82. protected $_useByteString = true;
  83. /**
  84. * Sets validator options
  85. *
  86. * If $options is a integer, it will be used as maximum filesize
  87. * As Array is accepts the following keys:
  88. * 'min': Minimum filesize
  89. * 'max': Maximum filesize
  90. * 'bytestring': Use bytestring or real size for messages
  91. *
  92. * @param integer|array $options Options for the adapter
  93. */
  94. public function __construct($options)
  95. {
  96. if ($options instanceof Zend_Config) {
  97. $options = $options->toArray();
  98. } elseif (is_string($options) || is_numeric($options)) {
  99. $options = array('max' => $options);
  100. } elseif (!is_array($options)) {
  101. require_once 'Zend/Validate/Exception.php';
  102. throw new Zend_Validate_Exception ('Invalid options to validator provided');
  103. }
  104. if (1 < func_num_args()) {
  105. // @todo: Preperation for 2.0... needs to be cleared with the dev-team
  106. // trigger_error('Multiple constructor options are deprecated in favor of a single options array', E_USER_NOTICE);
  107. $argv = func_get_args();
  108. array_shift($argv);
  109. $options['max'] = array_shift($argv);
  110. if (!empty($argv)) {
  111. $options['bytestring'] = array_shift($argv);
  112. }
  113. }
  114. if (isset($options['bytestring'])) {
  115. $this->setUseByteString($options['bytestring']);
  116. }
  117. if (isset($options['min'])) {
  118. $this->setMin($options['min']);
  119. }
  120. if (isset($options['max'])) {
  121. $this->setMax($options['max']);
  122. }
  123. }
  124. /**
  125. * Returns the minimum filesize
  126. *
  127. * @param boolean $byteString Use bytestring ?
  128. * @return integer
  129. */
  130. public function setUseByteString($byteString = true)
  131. {
  132. $this->_useByteString = (bool) $byteString;
  133. return $this;
  134. }
  135. /**
  136. * Will bytestring be used?
  137. *
  138. * @return boolean
  139. */
  140. public function useByteString()
  141. {
  142. return $this->_useByteString;
  143. }
  144. /**
  145. * Returns the minimum filesize
  146. *
  147. * @param bool $raw Whether or not to force return of the raw value (defaults off)
  148. * @return integer|string
  149. */
  150. public function getMin($raw = false)
  151. {
  152. $min = $this->_min;
  153. if (!$raw && $this->useByteString()) {
  154. $min = $this->_toByteString($min);
  155. }
  156. return $min;
  157. }
  158. /**
  159. * Sets the minimum filesize
  160. *
  161. * @param integer $min The minimum filesize
  162. * @throws Zend_Validate_Exception When min is greater than max
  163. * @return Zend_Validate_File_Size Provides a fluent interface
  164. */
  165. public function setMin($min)
  166. {
  167. if (!is_string($min) and !is_numeric($min)) {
  168. require_once 'Zend/Validate/Exception.php';
  169. throw new Zend_Validate_Exception ('Invalid options to validator provided');
  170. }
  171. $min = (integer) $this->_fromByteString($min);
  172. $max = $this->getMax(true);
  173. if (($max !== null) && ($min > $max)) {
  174. require_once 'Zend/Validate/Exception.php';
  175. throw new Zend_Validate_Exception("The minimum must be less than or equal to the maximum filesize, but $min >"
  176. . " $max");
  177. }
  178. $this->_min = $min;
  179. return $this;
  180. }
  181. /**
  182. * Returns the maximum filesize
  183. *
  184. * @param bool $raw Whether or not to force return of the raw value (defaults off)
  185. * @return integer|string
  186. */
  187. public function getMax($raw = false)
  188. {
  189. $max = $this->_max;
  190. if (!$raw && $this->useByteString()) {
  191. $max = $this->_toByteString($max);
  192. }
  193. return $max;
  194. }
  195. /**
  196. * Sets the maximum filesize
  197. *
  198. * @param integer $max The maximum filesize
  199. * @throws Zend_Validate_Exception When max is smaller than min
  200. * @return Zend_Validate_StringLength Provides a fluent interface
  201. */
  202. public function setMax($max)
  203. {
  204. if (!is_string($max) && !is_numeric($max)) {
  205. require_once 'Zend/Validate/Exception.php';
  206. throw new Zend_Validate_Exception ('Invalid options to validator provided');
  207. }
  208. $max = (integer) $this->_fromByteString($max);
  209. $min = $this->getMin(true);
  210. if (($min !== null) && ($max < $min)) {
  211. require_once 'Zend/Validate/Exception.php';
  212. throw new Zend_Validate_Exception("The maximum must be greater than or equal to the minimum filesize, but "
  213. . "$max < $min");
  214. }
  215. $this->_max = $max;
  216. return $this;
  217. }
  218. /**
  219. * Retrieve current detected file size
  220. *
  221. * @return int
  222. */
  223. protected function _getSize()
  224. {
  225. return $this->_size;
  226. }
  227. /**
  228. * Set current size
  229. *
  230. * @param int $size
  231. * @return Zend_Validate_File_Size
  232. */
  233. protected function _setSize($size)
  234. {
  235. $this->_size = $size;
  236. return $this;
  237. }
  238. /**
  239. * Defined by Zend_Validate_Interface
  240. *
  241. * Returns true if and only if the filesize of $value is at least min and
  242. * not bigger than max (when max is not null).
  243. *
  244. * @param string $value Real file to check for size
  245. * @param array $file File data from Zend_File_Transfer
  246. * @return boolean
  247. */
  248. public function isValid($value, $file = null)
  249. {
  250. // Is file readable ?
  251. require_once 'Zend/Loader.php';
  252. if (!Zend_Loader::isReadable($value)) {
  253. return $this->_throw($file, self::NOT_FOUND);
  254. }
  255. // limited to 4GB files
  256. $size = sprintf("%u", @filesize($value));
  257. // Check to see if it's smaller than min size
  258. $min = $this->getMin(true);
  259. $max = $this->getMax(true);
  260. if (($min !== null) && ($size < $min)) {
  261. if ($this->useByteString()) {
  262. $this->_min = $this->_toByteString($min);
  263. $this->_size = $this->_toByteString($size);
  264. $this->_throw($file, self::TOO_SMALL);
  265. $this->_min = $min;
  266. $this->_size = $size;
  267. } else {
  268. $this->_throw($file, self::TOO_SMALL);
  269. }
  270. }
  271. // Check to see if it's larger than max size
  272. if (($max !== null) && ($max < $size)) {
  273. if ($this->useByteString()) {
  274. $this->_max = $this->_toByteString($max);
  275. $this->_size = $this->_toByteString($size);
  276. $this->_throw($file, self::TOO_BIG);
  277. $this->_max = $max;
  278. $this->_size = $size;
  279. } else {
  280. $this->_throw($file, self::TOO_BIG);
  281. }
  282. }
  283. if (count($this->_messages) > 0) {
  284. return false;
  285. }
  286. return true;
  287. }
  288. /**
  289. * Returns the formatted size
  290. *
  291. * @param integer $size
  292. * @return string
  293. */
  294. protected function _toByteString($size)
  295. {
  296. $sizes = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
  297. for ($i=0; $size >= 1024 && $i < 9; $i++) {
  298. $size /= 1024;
  299. }
  300. return round($size, 2) . $sizes[$i];
  301. }
  302. /**
  303. * Returns the unformatted size
  304. *
  305. * @param string $size
  306. * @return integer
  307. */
  308. protected function _fromByteString($size)
  309. {
  310. if (is_numeric($size)) {
  311. return (integer) $size;
  312. }
  313. $type = trim(substr($size, -2, 1));
  314. $value = substr($size, 0, -1);
  315. if (!is_numeric($value)) {
  316. $value = substr($value, 0, -1);
  317. }
  318. switch (strtoupper($type)) {
  319. case 'Y':
  320. $value *= (1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024);
  321. break;
  322. case 'Z':
  323. $value *= (1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024);
  324. break;
  325. case 'E':
  326. $value *= (1024 * 1024 * 1024 * 1024 * 1024 * 1024);
  327. break;
  328. case 'P':
  329. $value *= (1024 * 1024 * 1024 * 1024 * 1024);
  330. break;
  331. case 'T':
  332. $value *= (1024 * 1024 * 1024 * 1024);
  333. break;
  334. case 'G':
  335. $value *= (1024 * 1024 * 1024);
  336. break;
  337. case 'M':
  338. $value *= (1024 * 1024);
  339. break;
  340. case 'K':
  341. $value *= 1024;
  342. break;
  343. default:
  344. break;
  345. }
  346. return $value;
  347. }
  348. /**
  349. * Throws an error of the given type
  350. *
  351. * @param string $file
  352. * @param string $errorType
  353. * @return false
  354. */
  355. protected function _throw($file, $errorType)
  356. {
  357. if ($file !== null) {
  358. $this->_value = $file['name'];
  359. }
  360. $this->_error($errorType);
  361. return false;
  362. }
  363. }