web/lib/Zend/Validate/File/Upload.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: Upload.php 22398 2010-06-09 19:05: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_Upload extends Zend_Validate_Abstract
       
    36 {
       
    37     /**@#+
       
    38      * @const string Error constants
       
    39      */
       
    40     const INI_SIZE       = 'fileUploadErrorIniSize';
       
    41     const FORM_SIZE      = 'fileUploadErrorFormSize';
       
    42     const PARTIAL        = 'fileUploadErrorPartial';
       
    43     const NO_FILE        = 'fileUploadErrorNoFile';
       
    44     const NO_TMP_DIR     = 'fileUploadErrorNoTmpDir';
       
    45     const CANT_WRITE     = 'fileUploadErrorCantWrite';
       
    46     const EXTENSION      = 'fileUploadErrorExtension';
       
    47     const ATTACK         = 'fileUploadErrorAttack';
       
    48     const FILE_NOT_FOUND = 'fileUploadErrorFileNotFound';
       
    49     const UNKNOWN        = 'fileUploadErrorUnknown';
       
    50     /**@#-*/
       
    51 
       
    52     /**
       
    53      * @var array Error message templates
       
    54      */
       
    55     protected $_messageTemplates = array(
       
    56         self::INI_SIZE       => "File '%value%' exceeds the defined ini size",
       
    57         self::FORM_SIZE      => "File '%value%' exceeds the defined form size",
       
    58         self::PARTIAL        => "File '%value%' was only partially uploaded",
       
    59         self::NO_FILE        => "File '%value%' was not uploaded",
       
    60         self::NO_TMP_DIR     => "No temporary directory was found for file '%value%'",
       
    61         self::CANT_WRITE     => "File '%value%' can't be written",
       
    62         self::EXTENSION      => "A PHP extension returned an error while uploading the file '%value%'",
       
    63         self::ATTACK         => "File '%value%' was illegally uploaded. This could be a possible attack",
       
    64         self::FILE_NOT_FOUND => "File '%value%' was not found",
       
    65         self::UNKNOWN        => "Unknown error while uploading file '%value%'"
       
    66     );
       
    67 
       
    68     /**
       
    69      * Internal array of files
       
    70      * @var array
       
    71      */
       
    72     protected $_files = array();
       
    73 
       
    74     /**
       
    75      * Sets validator options
       
    76      *
       
    77      * The array $files must be given in syntax of Zend_File_Transfer to be checked
       
    78      * If no files are given the $_FILES array will be used automatically.
       
    79      * NOTE: This validator will only work with HTTP POST uploads!
       
    80      *
       
    81      * @param  array|Zend_Config $files Array of files in syntax of Zend_File_Transfer
       
    82      * @return void
       
    83      */
       
    84     public function __construct($files = array())
       
    85     {
       
    86         if ($files instanceof Zend_Config) {
       
    87             $files = $files->toArray();
       
    88         }
       
    89 
       
    90         $this->setFiles($files);
       
    91     }
       
    92 
       
    93     /**
       
    94      * Returns the array of set files
       
    95      *
       
    96      * @param  string $files (Optional) The file to return in detail
       
    97      * @return array
       
    98      * @throws Zend_Validate_Exception If file is not found
       
    99      */
       
   100     public function getFiles($file = null)
       
   101     {
       
   102         if ($file !== null) {
       
   103             $return = array();
       
   104             foreach ($this->_files as $name => $content) {
       
   105                 if ($name === $file) {
       
   106                     $return[$file] = $this->_files[$name];
       
   107                 }
       
   108 
       
   109                 if ($content['name'] === $file) {
       
   110                     $return[$name] = $this->_files[$name];
       
   111                 }
       
   112             }
       
   113 
       
   114             if (count($return) === 0) {
       
   115                 require_once 'Zend/Validate/Exception.php';
       
   116                 throw new Zend_Validate_Exception("The file '$file' was not found");
       
   117             }
       
   118 
       
   119             return $return;
       
   120         }
       
   121 
       
   122         return $this->_files;
       
   123     }
       
   124 
       
   125     /**
       
   126      * Sets the files to be checked
       
   127      *
       
   128      * @param  array $files The files to check in syntax of Zend_File_Transfer
       
   129      * @return Zend_Validate_File_Upload Provides a fluent interface
       
   130      */
       
   131     public function setFiles($files = array())
       
   132     {
       
   133         if (count($files) === 0) {
       
   134             $this->_files = $_FILES;
       
   135         } else {
       
   136             $this->_files = $files;
       
   137         }
       
   138 
       
   139         foreach($this->_files as $file => $content) {
       
   140             if (!isset($content['error'])) {
       
   141                 unset($this->_files[$file]);
       
   142             }
       
   143         }
       
   144 
       
   145         return $this;
       
   146     }
       
   147 
       
   148     /**
       
   149      * Defined by Zend_Validate_Interface
       
   150      *
       
   151      * Returns true if and only if the file was uploaded without errors
       
   152      *
       
   153      * @param  string $value Single file to check for upload errors, when giving null the $_FILES array
       
   154      *                       from initialization will be used
       
   155      * @return boolean
       
   156      */
       
   157     public function isValid($value, $file = null)
       
   158     {
       
   159         $this->_messages = null;
       
   160         if (array_key_exists($value, $this->_files)) {
       
   161             $files[$value] = $this->_files[$value];
       
   162         } else {
       
   163             foreach ($this->_files as $file => $content) {
       
   164                 if (isset($content['name']) && ($content['name'] === $value)) {
       
   165                     $files[$file] = $this->_files[$file];
       
   166                 }
       
   167 
       
   168                 if (isset($content['tmp_name']) && ($content['tmp_name'] === $value)) {
       
   169                     $files[$file] = $this->_files[$file];
       
   170                 }
       
   171             }
       
   172         }
       
   173 
       
   174         if (empty($files)) {
       
   175             return $this->_throw($file, self::FILE_NOT_FOUND);
       
   176         }
       
   177 
       
   178         foreach ($files as $file => $content) {
       
   179             $this->_value = $file;
       
   180             switch($content['error']) {
       
   181                 case 0:
       
   182                     if (!is_uploaded_file($content['tmp_name'])) {
       
   183                         $this->_throw($file, self::ATTACK);
       
   184                     }
       
   185                     break;
       
   186 
       
   187                 case 1:
       
   188                     $this->_throw($file, self::INI_SIZE);
       
   189                     break;
       
   190 
       
   191                 case 2:
       
   192                     $this->_throw($file, self::FORM_SIZE);
       
   193                     break;
       
   194 
       
   195                 case 3:
       
   196                     $this->_throw($file, self::PARTIAL);
       
   197                     break;
       
   198 
       
   199                 case 4:
       
   200                     $this->_throw($file, self::NO_FILE);
       
   201                     break;
       
   202 
       
   203                 case 6:
       
   204                     $this->_throw($file, self::NO_TMP_DIR);
       
   205                     break;
       
   206 
       
   207                 case 7:
       
   208                     $this->_throw($file, self::CANT_WRITE);
       
   209                     break;
       
   210 
       
   211                 case 8:
       
   212                     $this->_throw($file, self::EXTENSION);
       
   213                     break;
       
   214 
       
   215                 default:
       
   216                     $this->_throw($file, self::UNKNOWN);
       
   217                     break;
       
   218             }
       
   219         }
       
   220 
       
   221         if (count($this->_messages) > 0) {
       
   222             return false;
       
   223         } else {
       
   224             return true;
       
   225         }
       
   226     }
       
   227 
       
   228     /**
       
   229      * Throws an error of the given type
       
   230      *
       
   231      * @param  string $file
       
   232      * @param  string $errorType
       
   233      * @return false
       
   234      */
       
   235     protected function _throw($file, $errorType)
       
   236     {
       
   237         if ($file !== null) {
       
   238             if (is_array($file) and !empty($file['name'])) {
       
   239                 $this->_value = $file['name'];
       
   240             }
       
   241         }
       
   242 
       
   243         $this->_error($errorType);
       
   244         return false;
       
   245     }
       
   246 }