PageRenderTime 26ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/library/Zend/Validator/File/Size.php

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