Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 303 lines (292 sloc) 11.916 kb
0d046d1 Added CFileValidator and CUploadedFile.
qiang.xue authored
1 <?php
2 /**
3 * CFileValidator class file.
4 *
5 * @author Qiang Xue <qiang.xue@gmail.com>
6 * @link http://www.yiiframework.com/
4be0af6 changed copyright year.
qiang.xue authored
7 * @copyright Copyright &copy; 2008-2011 Yii Software LLC
0d046d1 Added CFileValidator and CUploadedFile.
qiang.xue authored
8 * @license http://www.yiiframework.com/license/
9 */
10
11 /**
45ebe4c Finished CFileValidator and CUploadedFile.
qiang.xue authored
12 * CFileValidator verifies if an attribute is receiving a valid uploaded file.
0d046d1 Added CFileValidator and CUploadedFile.
qiang.xue authored
13 *
45ebe4c Finished CFileValidator and CUploadedFile.
qiang.xue authored
14 * It uses the model class and attribute name to retrieve the information
15 * about the uploaded file. It then checks if a file is uploaded successfully,
16 * if the file size is within the limit and if the file type is allowed.
17 *
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
18 * This validator will attempt to fetch uploaded data if attribute is not
19 * previously set. Please note that this cannot be done if input is tabular:
20 * <pre>
21 * foreach($models as $i=>$model)
22 * $model->attribute = CUploadedFile::getInstance($model, "[$i]attribute");
23 * </pre>
93ab63f Fixes issue 1466
mdomba authored
24 * Please note that you must use {@link CUploadedFile::getInstances} for multiple
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
25 * file uploads.
26 *
45ebe4c Finished CFileValidator and CUploadedFile.
qiang.xue authored
27 * When using CFileValidator with an active record, the following code is often used:
28 * <pre>
80c0b7d merge from 1.0
qiang.xue authored
29 * if($model->save())
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
30 * {
31 * // single upload
32 * $model->attribute->saveAs($path);
33 * // multiple upload
34 * foreach($model->attribute as $file)
35 * $file->saveAs($path);
36 * }
45ebe4c Finished CFileValidator and CUploadedFile.
qiang.xue authored
37 * </pre>
0d046d1 Added CFileValidator and CUploadedFile.
qiang.xue authored
38 *
80c0b7d merge from 1.0
qiang.xue authored
39 * You can use {@link CFileValidator} to validate the file attribute.
40 *
d788810 @samdark CFileValidator now always sets field value to null when allowEmpty is…
samdark authored
41 * In addition to the {@link message} property for setting a custom error message,
c4493b7 adding documentation about placeholders in different validator custom…
jefftulsa authored
42 * CFileValidator has a few custom error messages you can set that correspond to different
43 * validation scenarios. When the file is too large, you may use the {@link tooLarge} property
d788810 @samdark CFileValidator now always sets field value to null when allowEmpty is…
samdark authored
44 * to define a custom error message. Similarly for {@link tooSmall}, {@link wrongType} and
45 * {@link tooMany}. The messages may contain additional placeholders that will be replaced
46 * with the actual content. In addition to the "{attribute}" placeholder, recognized by all
47 * validators (see {@link CValidator}), CFileValidator allows for the following placeholders
c4493b7 adding documentation about placeholders in different validator custom…
jefftulsa authored
48 * to be specified:
49 * <ul>
50 * <li>{file}: replaced with the name of the file.</li>
d788810 @samdark CFileValidator now always sets field value to null when allowEmpty is…
samdark authored
51 * <li>{limit}: when using {@link tooLarge}, replaced with {@link maxSize};
52 * when using {@link tooSmall}, replaced with {@link minSize}; and when using {@link tooMany}
c4493b7 adding documentation about placeholders in different validator custom…
jefftulsa authored
53 * replaced with {@link maxFiles}.</li>
54 * <li>{extensions}: when using {@link wrongType}, it will be replaced with the allowed extensions.</li>
55 * </ul>
56 *
0d046d1 Added CFileValidator and CUploadedFile.
qiang.xue authored
57 * @author Qiang Xue <qiang.xue@gmail.com>
58 * @package system.validators
59 * @since 1.0
60 */
61 class CFileValidator extends CValidator
62 {
63 /**
45ebe4c Finished CFileValidator and CUploadedFile.
qiang.xue authored
64 * @var boolean whether the attribute requires a file to be uploaded or not.
65 * Defaults to false, meaning a file is required to be uploaded.
66 */
67 public $allowEmpty=false;
68 /**
a2d8907 merge from 1.0
qiang.xue authored
69 * @var mixed a list of file name extensions that are allowed to be uploaded.
70 * This can be either an array or a string consisting of file extension names
71 * separated by space or comma (e.g. "gif, jpg").
45ebe4c Finished CFileValidator and CUploadedFile.
qiang.xue authored
72 * Extension names are case-insensitive. Defaults to null, meaning all file name
73 * extensions are allowed.
74 */
75 public $types;
76 /**
e8bd65e @resurtm CFileValidator could validate uploaded file by its MIME-type, added $…
resurtm authored
77 * @var mixed a list of MIME-types of the file that are allowed to be uploaded.
78 * This can be either an array or a string consisting of MIME-types separated
79 * by space or comma (e.g. "image/gif, image/jpeg"). MIME-types are
80 * case-insensitive. Defaults to null, meaning all MIME-types are allowed.
81 * In order to use this property fileinfo PECL extension should be installed.
82 * @since 1.1.11
83 */
84 public $mimeTypes;
85 /**
45ebe4c Finished CFileValidator and CUploadedFile.
qiang.xue authored
86 * @var integer the minimum number of bytes required for the uploaded file.
87 * Defaults to null, meaning no limit.
88 * @see tooSmall
89 */
90 public $minSize;
91 /**
92 * @var integer the maximum number of bytes required for the uploaded file.
93 * Defaults to null, meaning no limit.
94 * Note, the size limit is also affected by 'upload_max_filesize' INI setting
95 * and the 'MAX_FILE_SIZE' hidden field value.
96 * @see tooLarge
0d046d1 Added CFileValidator and CUploadedFile.
qiang.xue authored
97 */
45ebe4c Finished CFileValidator and CUploadedFile.
qiang.xue authored
98 public $maxSize;
99 /**
100 * @var string the error message used when the uploaded file is too large.
101 * @see maxSize
102 */
103 public $tooLarge;
104 /**
105 * @var string the error message used when the uploaded file is too small.
106 * @see minSize
107 */
108 public $tooSmall;
109 /**
110 * @var string the error message used when the uploaded file has an extension name
e8bd65e @resurtm CFileValidator could validate uploaded file by its MIME-type, added $…
resurtm authored
111 * that is not listed among {@link types}.
45ebe4c Finished CFileValidator and CUploadedFile.
qiang.xue authored
112 */
113 public $wrongType;
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
114 /**
e8bd65e @resurtm CFileValidator could validate uploaded file by its MIME-type, added $…
resurtm authored
115 * @var string the error message used when the uploaded file has a MIME-type
116 * that is not listed among {@link mimeTypes}. In order to use this property
117 * fileinfo PECL extension should be installed.
118 * @since 1.1.11
119 */
120 public $wrongMimeType;
121 /**
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
122 * @var integer the maximum file count the given attribute can hold.
123 * It defaults to 1, meaning single file upload. By defining a higher number,
124 * multiple uploads become possible.
125 */
126 public $maxFiles=1;
127 /**
128 * @var string the error message used if the count of multiple uploads exceeds
129 * limit.
130 */
131 public $tooMany;
1d33c35 @samdark updated CFileValidator to be unsafe
samdark authored
132 /**
133 * @var boolean whether attributes listed with this validator should be considered safe for massive assignment.
134 * For this validator it defaults to false.
135 * @since 1.1.12
136 */
137 public $safe=false;
0d046d1 Added CFileValidator and CUploadedFile.
qiang.xue authored
138
139 /**
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
140 * Set the attribute and then validates using {@link validateFile}.
0d046d1 Added CFileValidator and CUploadedFile.
qiang.xue authored
141 * If there is any error, the error message is added to the object.
72b9745 Updated PHPDoc @param parameter names
mdomba authored
142 * @param CModel $object the object being validated
143 * @param string $attribute the attribute being validated
0d046d1 Added CFileValidator and CUploadedFile.
qiang.xue authored
144 */
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
145 protected function validateAttribute($object, $attribute)
0d046d1 Added CFileValidator and CUploadedFile.
qiang.xue authored
146 {
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
147 if($this->maxFiles > 1)
45ebe4c Finished CFileValidator and CUploadedFile.
qiang.xue authored
148 {
bb5ef90 Fixes the bug that using CFileValidator causes an error about accessi…
qiang.xue authored
149 $files=$object->$attribute;
97b7bfd (Fixes issue 1643)
qiang.xue authored
150 if(!is_array($files) || !isset($files[0]) || !$files[0] instanceof CUploadedFile)
bb5ef90 Fixes the bug that using CFileValidator causes an error about accessi…
qiang.xue authored
151 $files = CUploadedFile::getInstances($object, $attribute);
152 if(array()===$files)
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
153 return $this->emptyAttribute($object, $attribute);
bb5ef90 Fixes the bug that using CFileValidator causes an error about accessi…
qiang.xue authored
154 if(count($files) > $this->maxFiles)
f1021d4 (Fixes issue 429) Native support for multiple file uploads
pestaa.hu authored
155 {
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
156 $message=$this->tooMany!==null?$this->tooMany : Yii::t('yii', '{attribute} cannot accept more than {limit} files.');
157 $this->addError($object, $attribute, $message, array('{attribute}'=>$attribute, '{limit}'=>$this->maxFiles));
f1021d4 (Fixes issue 429) Native support for multiple file uploads
pestaa.hu authored
158 }
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
159 else
bb5ef90 Fixes the bug that using CFileValidator causes an error about accessi…
qiang.xue authored
160 foreach($files as $file)
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
161 $this->validateFile($object, $attribute, $file);
162 }
163 else
164 {
bb5ef90 Fixes the bug that using CFileValidator causes an error about accessi…
qiang.xue authored
165 $file = $object->$attribute;
166 if(!$file instanceof CUploadedFile)
f1021d4 (Fixes issue 429) Native support for multiple file uploads
pestaa.hu authored
167 {
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
168 $file = CUploadedFile::getInstance($object, $attribute);
169 if(null===$file)
170 return $this->emptyAttribute($object, $attribute);
f1021d4 (Fixes issue 429) Native support for multiple file uploads
pestaa.hu authored
171 }
bb5ef90 Fixes the bug that using CFileValidator causes an error about accessi…
qiang.xue authored
172 $this->validateFile($object, $attribute, $file);
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
173 }
174 }
45ebe4c Finished CFileValidator and CUploadedFile.
qiang.xue authored
175
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
176 /**
177 * Internally validates a file object.
72b9745 Updated PHPDoc @param parameter names
mdomba authored
178 * @param CModel $object the object being validated
179 * @param string $attribute the attribute being validated
180 * @param CUploadedFile $file uploaded file passed to check against a set of rules
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
181 */
182 protected function validateFile($object, $attribute, $file)
183 {
184 if(null===$file || ($error=$file->getError())==UPLOAD_ERR_NO_FILE)
185 return $this->emptyAttribute($object, $attribute);
4867238 @creocoder else if => elseif
creocoder authored
186 elseif($error==UPLOAD_ERR_INI_SIZE || $error==UPLOAD_ERR_FORM_SIZE || $this->maxSize!==null && $file->getSize()>$this->maxSize)
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
187 {
188 $message=$this->tooLarge!==null?$this->tooLarge : Yii::t('yii','The file "{file}" is too large. Its size cannot exceed {limit} bytes.');
189 $this->addError($object,$attribute,$message,array('{file}'=>$file->getName(), '{limit}'=>$this->getSizeLimit()));
190 }
4867238 @creocoder else if => elseif
creocoder authored
191 elseif($error==UPLOAD_ERR_PARTIAL)
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
192 throw new CException(Yii::t('yii','The file "{file}" was only partially uploaded.',array('{file}'=>$file->getName())));
4867238 @creocoder else if => elseif
creocoder authored
193 elseif($error==UPLOAD_ERR_NO_TMP_DIR)
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
194 throw new CException(Yii::t('yii','Missing the temporary folder to store the uploaded file "{file}".',array('{file}'=>$file->getName())));
4867238 @creocoder else if => elseif
creocoder authored
195 elseif($error==UPLOAD_ERR_CANT_WRITE)
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
196 throw new CException(Yii::t('yii','Failed to write the uploaded file "{file}" to disk.',array('{file}'=>$file->getName())));
4867238 @creocoder else if => elseif
creocoder authored
197 elseif(defined('UPLOAD_ERR_EXTENSION') && $error==UPLOAD_ERR_EXTENSION) // available for PHP 5.2.0 or above
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
198 throw new CException(Yii::t('yii','File upload was stopped by extension.'));
45ebe4c Finished CFileValidator and CUploadedFile.
qiang.xue authored
199
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
200 if($this->minSize!==null && $file->getSize()<$this->minSize)
201 {
202 $message=$this->tooSmall!==null?$this->tooSmall : Yii::t('yii','The file "{file}" is too small. Its size cannot be smaller than {limit} bytes.');
203 $this->addError($object,$attribute,$message,array('{file}'=>$file->getName(), '{limit}'=>$this->minSize));
204 }
205
206 if($this->types!==null)
207 {
208 if(is_string($this->types))
209 $types=preg_split('/[\s,]+/',strtolower($this->types),-1,PREG_SPLIT_NO_EMPTY);
210 else
211 $types=$this->types;
212 if(!in_array(strtolower($file->getExtensionName()),$types))
45ebe4c Finished CFileValidator and CUploadedFile.
qiang.xue authored
213 {
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
214 $message=$this->wrongType!==null?$this->wrongType : Yii::t('yii','The file "{file}" cannot be uploaded. Only files with these extensions are allowed: {extensions}.');
215 $this->addError($object,$attribute,$message,array('{file}'=>$file->getName(), '{extensions}'=>implode(', ',$types)));
45ebe4c Finished CFileValidator and CUploadedFile.
qiang.xue authored
216 }
e8bd65e @resurtm CFileValidator could validate uploaded file by its MIME-type, added $…
resurtm authored
217 }
218
219 if($this->mimeTypes!==null)
220 {
221 if(function_exists('finfo_open'))
222 {
223 $mimeType=false;
224 if($info=finfo_open(defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME))
225 $mimeType=finfo_file($info,$file->getTempName());
226 }
4867238 @creocoder else if => elseif
creocoder authored
227 elseif(function_exists('mime_content_type'))
e8bd65e @resurtm CFileValidator could validate uploaded file by its MIME-type, added $…
resurtm authored
228 $mimeType=mime_content_type($file->getTempName());
229 else
230 throw new CException(Yii::t('yii','In order to use MIME-type validation provided by CFileValidator fileinfo PECL extension should be installed.'));
231
232 if(is_string($this->mimeTypes))
233 $mimeTypes=preg_split('/[\s,]+/',strtolower($this->mimeTypes),-1,PREG_SPLIT_NO_EMPTY);
234 else
235 $mimeTypes=$this->mimeTypes;
236
237 if($mimeType===false || !in_array(strtolower($mimeType),$mimeTypes))
238 {
239 $message=$this->wrongMimeType!==null?$this->wrongMimeType : Yii::t('yii','The file "{file}" cannot be uploaded. Only files of these MIME-types are allowed: {mimeTypes}.');
240 $this->addError($object,$attribute,$message,array('{file}'=>$file->getName(), '{mimeTypes}'=>implode(', ',$mimeTypes)));
241 }
45ebe4c Finished CFileValidator and CUploadedFile.
qiang.xue authored
242 }
243 }
244
245 /**
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
246 * Raises an error to inform end user about blank attribute.
72b9745 Updated PHPDoc @param parameter names
mdomba authored
247 * @param CModel $object the object being validated
248 * @param string $attribute the attribute being validated
372d23d Clarify upload mechanism, separate logic into methods, update API; fu…
pestaa.hu authored
249 */
250 protected function emptyAttribute($object, $attribute)
251 {
252 if(!$this->allowEmpty)
253 {
254 $message=$this->message!==null?$this->message : Yii::t('yii','{attribute} cannot be blank.');
255 $this->addError($object,$attribute,$message);
256 }
257 }
258
259 /**
45ebe4c Finished CFileValidator and CUploadedFile.
qiang.xue authored
260 * Returns the maximum size allowed for uploaded files.
261 * This is determined based on three factors:
262 * <ul>
263 * <li>'upload_max_filesize' in php.ini</li>
264 * <li>'MAX_FILE_SIZE' hidden field</li>
265 * <li>{@link maxSize}</li>
266 * </ul>
267 *
268 * @return integer the size limit for uploaded files.
269 */
270 protected function getSizeLimit()
271 {
272 $limit=ini_get('upload_max_filesize');
97b7bfd (Fixes issue 1643)
qiang.xue authored
273 $limit=$this->sizeToBytes($limit);
45ebe4c Finished CFileValidator and CUploadedFile.
qiang.xue authored
274 if($this->maxSize!==null && $limit>0 && $this->maxSize<$limit)
275 $limit=$this->maxSize;
276 if(isset($_POST['MAX_FILE_SIZE']) && $_POST['MAX_FILE_SIZE']>0 && $_POST['MAX_FILE_SIZE']<$limit)
277 $limit=$_POST['MAX_FILE_SIZE'];
278 return $limit;
0d046d1 Added CFileValidator and CUploadedFile.
qiang.xue authored
279 }
faa64a3 CFileValidator now works with php.ini's upload_max_filesize strings w…
alexander.makarow authored
280
281 /**
205cf9d @resurtm Fix #938, solution #2.
resurtm authored
282 * Converts php.ini style size to bytes. Examples of size strings are: 150, 1g, 500k, 5M (size suffix
283 * is case insensitive). If you pass here the number with a fractional part, then everything after
284 * the decimal point will be ignored (php.ini values common behavior). For example 1.5G value would be
285 * treated as 1G and 1073741824 number will be returned as a result. This method is public
286 * (was private before) since 1.1.11.
faa64a3 CFileValidator now works with php.ini's upload_max_filesize strings w…
alexander.makarow authored
287 *
205cf9d @resurtm Fix #938, solution #2.
resurtm authored
288 * @param string $sizeStr the size string to convert.
7a19449 @rawtaz Fix a bunch of @param and @return phpdoc errors in various files.
rawtaz authored
289 * @return integer the byte count in the given size string.
205cf9d @resurtm Fix #938, solution #2.
resurtm authored
290 * @since 1.1.11
faa64a3 CFileValidator now works with php.ini's upload_max_filesize strings w…
alexander.makarow authored
291 */
205cf9d @resurtm Fix #938, solution #2.
resurtm authored
292 public function sizeToBytes($sizeStr)
faa64a3 CFileValidator now works with php.ini's upload_max_filesize strings w…
alexander.makarow authored
293 {
205cf9d @resurtm Fix #938, solution #2.
resurtm authored
294 // get the latest character
cc2faf5 @resurtm Removed extra case's in the CFileValidator::sizeToBytes() method.
resurtm authored
295 switch (strtolower(substr($sizeStr, -1)))
faa64a3 CFileValidator now works with php.ini's upload_max_filesize strings w…
alexander.makarow authored
296 {
cc2faf5 @resurtm Removed extra case's in the CFileValidator::sizeToBytes() method.
resurtm authored
297 case 'm': return (int)$sizeStr * 1048576; // 1024 * 1024
298 case 'k': return (int)$sizeStr * 1024; // 1024
299 case 'g': return (int)$sizeStr * 1073741824; // 1024 * 1024 * 1024
205cf9d @resurtm Fix #938, solution #2.
resurtm authored
300 default: return (int)$sizeStr; // do nothing
a688230
alexander.makarow authored
301 }
faa64a3 CFileValidator now works with php.ini's upload_max_filesize strings w…
alexander.makarow authored
302 }
303 }
Something went wrong with that request. Please try again.