File indexing completed on 2025-01-19 05:21:38

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category  Zend
0016  * @package   Zend_Validate
0017  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0018  * @license   http://framework.zend.com/license/new-bsd     New BSD License
0019  * @version   $Id$
0020  */
0021 
0022 /**
0023  * @see Zend_Validate_Abstract
0024  */
0025 // require_once 'Zend/Validate/Abstract.php';
0026 
0027 /**
0028  * Validator for the maximum size of a file up to a max of 2GB
0029  *
0030  * @category  Zend
0031  * @package   Zend_Validate
0032  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0033  * @license   http://framework.zend.com/license/new-bsd     New BSD License
0034  */
0035 class Zend_Validate_File_Size extends Zend_Validate_Abstract
0036 {
0037     /**#@+
0038      * @const string Error constants
0039      */
0040     const TOO_BIG   = 'fileSizeTooBig';
0041     const TOO_SMALL = 'fileSizeTooSmall';
0042     const NOT_FOUND = 'fileSizeNotFound';
0043     /**#@-*/
0044 
0045     /**
0046      * @var array Error message templates
0047      */
0048     protected $_messageTemplates = array(
0049         self::TOO_BIG   => "Maximum allowed size for file '%value%' is '%max%' but '%size%' detected",
0050         self::TOO_SMALL => "Minimum expected size for file '%value%' is '%min%' but '%size%' detected",
0051         self::NOT_FOUND => "File '%value%' is not readable or does not exist",
0052     );
0053 
0054     /**
0055      * @var array Error message template variables
0056      */
0057     protected $_messageVariables = array(
0058         'min'  => '_min',
0059         'max'  => '_max',
0060         'size' => '_size',
0061     );
0062 
0063     /**
0064      * Minimum filesize
0065      * @var integer
0066      */
0067     protected $_min;
0068 
0069     /**
0070      * Maximum filesize
0071      *
0072      * If null, there is no maximum filesize
0073      *
0074      * @var integer|null
0075      */
0076     protected $_max;
0077 
0078     /**
0079      * Detected size
0080      *
0081      * @var integer
0082      */
0083     protected $_size;
0084 
0085     /**
0086      * Use bytestring ?
0087      *
0088      * @var boolean
0089      */
0090     protected $_useByteString = true;
0091 
0092     /**
0093      * Sets validator options
0094      *
0095      * If $options is a integer, it will be used as maximum filesize
0096      * As Array is accepts the following keys:
0097      * 'min': Minimum filesize
0098      * 'max': Maximum filesize
0099      * 'bytestring': Use bytestring or real size for messages
0100      *
0101      * @param  integer|array $options Options for the adapter
0102      * @throws Zend_Validate_Exception
0103      */
0104     public function __construct($options)
0105     {
0106         if ($options instanceof Zend_Config) {
0107             $options = $options->toArray();
0108         } elseif (is_string($options) || is_numeric($options)) {
0109             $options = array('max' => $options);
0110         } elseif (!is_array($options)) {
0111             // require_once 'Zend/Validate/Exception.php';
0112             throw new Zend_Validate_Exception ('Invalid options to validator provided');
0113         }
0114 
0115         if (1 < func_num_args()) {
0116             $argv = func_get_args();
0117             array_shift($argv);
0118             $options['max'] = array_shift($argv);
0119             if (!empty($argv)) {
0120                 $options['bytestring'] = array_shift($argv);
0121             }
0122         }
0123 
0124         if (isset($options['bytestring'])) {
0125             $this->setUseByteString($options['bytestring']);
0126         }
0127 
0128         if (isset($options['min'])) {
0129             $this->setMin($options['min']);
0130         }
0131 
0132         if (isset($options['max'])) {
0133             $this->setMax($options['max']);
0134         }
0135     }
0136 
0137     /**
0138      * Returns the minimum filesize
0139      *
0140      * @param  boolean $byteString Use bytestring ?
0141      * @return integer
0142      */
0143     public function setUseByteString($byteString = true)
0144     {
0145         $this->_useByteString = (bool) $byteString;
0146         return $this;
0147     }
0148 
0149     /**
0150      * Will bytestring be used?
0151      *
0152      * @return boolean
0153      */
0154     public function useByteString()
0155     {
0156         return $this->_useByteString;
0157     }
0158 
0159     /**
0160      * Returns the minimum filesize
0161      *
0162      * @param  bool $raw Whether or not to force return of the raw value (defaults off)
0163      * @return integer|string
0164      */
0165     public function getMin($raw = false)
0166     {
0167         $min = $this->_min;
0168         if (!$raw && $this->useByteString()) {
0169             $min = $this->_toByteString($min);
0170         }
0171 
0172         return $min;
0173     }
0174 
0175     /**
0176      * Sets the minimum filesize
0177      *
0178      * @param  integer $min The minimum filesize
0179      * @throws Zend_Validate_Exception When min is greater than max
0180      * @return Zend_Validate_File_Size Provides a fluent interface
0181      */
0182     public function setMin($min)
0183     {
0184         if (!is_string($min) and !is_numeric($min)) {
0185             // require_once 'Zend/Validate/Exception.php';
0186             throw new Zend_Validate_Exception ('Invalid options to validator provided');
0187         }
0188 
0189         $min = (integer) $this->_fromByteString($min);
0190         $max = $this->getMax(true);
0191         if (($max !== null) && ($min > $max)) {
0192             // require_once 'Zend/Validate/Exception.php';
0193             throw new Zend_Validate_Exception("The minimum must be less than or equal to the maximum filesize, but $min >"
0194                                             . " $max");
0195         }
0196 
0197         $this->_min = $min;
0198         return $this;
0199     }
0200 
0201     /**
0202      * Returns the maximum filesize
0203      *
0204      * @param  bool $raw Whether or not to force return of the raw value (defaults off)
0205      * @return integer|string
0206      */
0207     public function getMax($raw = false)
0208     {
0209         $max = $this->_max;
0210         if (!$raw && $this->useByteString()) {
0211             $max = $this->_toByteString($max);
0212         }
0213 
0214         return $max;
0215     }
0216 
0217     /**
0218      * Sets the maximum filesize
0219      *
0220      * @param  integer $max The maximum filesize
0221      * @throws Zend_Validate_Exception When max is smaller than min
0222      * @return Zend_Validate_StringLength Provides a fluent interface
0223      */
0224     public function setMax($max)
0225     {
0226         if (!is_string($max) && !is_numeric($max)) {
0227             // require_once 'Zend/Validate/Exception.php';
0228             throw new Zend_Validate_Exception ('Invalid options to validator provided');
0229         }
0230 
0231         $max = (integer) $this->_fromByteString($max);
0232         $min = $this->getMin(true);
0233         if (($min !== null) && ($max < $min)) {
0234             // require_once 'Zend/Validate/Exception.php';
0235             throw new Zend_Validate_Exception("The maximum must be greater than or equal to the minimum filesize, but "
0236                                             . "$max < $min");
0237         }
0238 
0239         $this->_max = $max;
0240         return $this;
0241     }
0242 
0243     /**
0244      * Retrieve current detected file size
0245      *
0246      * @return int
0247      */
0248     protected function _getSize()
0249     {
0250         return $this->_size;
0251     }
0252 
0253     /**
0254      * Set current size
0255      *
0256      * @param  int $size
0257      * @return Zend_Validate_File_Size
0258      */
0259     protected function _setSize($size)
0260     {
0261         $this->_size = $size;
0262         return $this;
0263     }
0264 
0265     /**
0266      * Defined by Zend_Validate_Interface
0267      *
0268      * Returns true if and only if the filesize of $value is at least min and
0269      * not bigger than max (when max is not null).
0270      *
0271      * @param  string $value Real file to check for size
0272      * @param  array  $file  File data from Zend_File_Transfer
0273      * @return boolean
0274      */
0275     public function isValid($value, $file = null)
0276     {
0277         // Is file readable ?
0278         // require_once 'Zend/Loader.php';
0279         if (!Zend_Loader::isReadable($value)) {
0280             return $this->_throw($file, self::NOT_FOUND);
0281         }
0282 
0283         // limited to 4GB files
0284         $size        = sprintf("%u", @filesize($value));
0285         $this->_size = $size;
0286 
0287         // Check to see if it's smaller than min size
0288         $min = $this->getMin(true);
0289         $max = $this->getMax(true);
0290         if (($min !== null) && ($size < $min)) {
0291             if ($this->useByteString()) {
0292                 $this->_min  = $this->_toByteString($min);
0293                 $this->_size = $this->_toByteString($size);
0294                 $this->_throw($file, self::TOO_SMALL);
0295                 $this->_min  = $min;
0296                 $this->_size = $size;
0297             } else {
0298                 $this->_throw($file, self::TOO_SMALL);
0299             }
0300         }
0301 
0302         // Check to see if it's larger than max size
0303         if (($max !== null) && ($max < $size)) {
0304             if ($this->useByteString()) {
0305                 $this->_max  = $this->_toByteString($max);
0306                 $this->_size = $this->_toByteString($size);
0307                 $this->_throw($file, self::TOO_BIG);
0308                 $this->_max  = $max;
0309                 $this->_size = $size;
0310             } else {
0311                 $this->_throw($file, self::TOO_BIG);
0312             }
0313         }
0314 
0315         if (count($this->_messages) > 0) {
0316             return false;
0317         }
0318 
0319         return true;
0320     }
0321 
0322     /**
0323      * Returns the formatted size
0324      *
0325      * @param  integer $size
0326      * @return string
0327      */
0328     protected function _toByteString($size)
0329     {
0330         $sizes = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
0331         for ($i=0; $size >= 1024 && $i < 9; $i++) {
0332             $size /= 1024;
0333         }
0334 
0335         return round($size, 2) . $sizes[$i];
0336     }
0337 
0338     /**
0339      * Returns the unformatted size
0340      *
0341      * @param  string $size
0342      * @return integer
0343      */
0344     protected function _fromByteString($size)
0345     {
0346         if (is_numeric($size)) {
0347             return (integer) $size;
0348         }
0349 
0350         $type  = trim(substr($size, -2, 1));
0351 
0352         $value = substr($size, 0, -1);
0353         if (!is_numeric($value)) {
0354             $value = substr($value, 0, -1);
0355         }
0356 
0357         switch (strtoupper($type)) {
0358             case 'Y':
0359                 $value *= (1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024);
0360                 break;
0361             case 'Z':
0362                 $value *= (1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024);
0363                 break;
0364             case 'E':
0365                 $value *= (1024 * 1024 * 1024 * 1024 * 1024 * 1024);
0366                 break;
0367             case 'P':
0368                 $value *= (1024 * 1024 * 1024 * 1024 * 1024);
0369                 break;
0370             case 'T':
0371                 $value *= (1024 * 1024 * 1024 * 1024);
0372                 break;
0373             case 'G':
0374                 $value *= (1024 * 1024 * 1024);
0375                 break;
0376             case 'M':
0377                 $value *= (1024 * 1024);
0378                 break;
0379             case 'K':
0380                 $value *= 1024;
0381                 break;
0382             default:
0383                 break;
0384         }
0385 
0386         return $value;
0387     }
0388 
0389     /**
0390      * Throws an error of the given type
0391      *
0392      * @param  string $file
0393      * @param  string $errorType
0394      * @return false
0395      */
0396     protected function _throw($file, $errorType)
0397     {
0398         if ($file !== null) {
0399             $this->_value = $file['name'];
0400         }
0401 
0402         $this->_error($errorType);
0403         return false;
0404     }
0405 }