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