You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							231 lines
						
					
					
						
							8.3 KiB
						
					
					
				
			
		
		
	
	
							231 lines
						
					
					
						
							8.3 KiB
						
					
					
				| <?php | |
| /** | |
|  * CFileValidator class file. | |
|  * | |
|  * @link http://www.yiiframework.com/ | |
|  * @copyright Copyright © 2008-2012 Yii Software LLC | |
|  * @license http://www.yiiframework.com/license/ | |
|  */ | |
|  | |
| namespace yii\validators; | |
|  | |
| /** | |
|  * CFileValidator verifies if an attribute is receiving a valid uploaded file. | |
|  * | |
|  * It uses the model class and attribute name to retrieve the information | |
|  * about the uploaded file. It then checks if a file is uploaded successfully, | |
|  * if the file size is within the limit and if the file type is allowed. | |
|  * | |
|  * This validator will attempt to fetch uploaded data if attribute is not | |
|  * previously set. Please note that this cannot be done if input is tabular: | |
|  * <pre> | |
|  *  foreach($models as $i=>$model) | |
|  *     $model->attribute = CUploadedFile::getInstance($model, "[$i]attribute"); | |
|  * </pre> | |
|  * Please note that you must use {@link CUploadedFile::getInstances} for multiple | |
|  * file uploads. | |
|  * | |
|  * When using CFileValidator with an active record, the following code is often used: | |
|  * <pre> | |
|  *  if($model->save()) | |
|  *  { | |
|  *     // single upload | |
|  *     $model->attribute->saveAs($path); | |
|  *     // multiple upload | |
|  *     foreach($model->attribute as $file) | |
|  *        $file->saveAs($path); | |
|  *  } | |
|  * </pre> | |
|  * | |
|  * You can use {@link CFileValidator} to validate the file attribute. | |
|  * | |
|  * @author Qiang Xue <qiang.xue@gmail.com> | |
|  * @since 2.0 | |
|  */ | |
| class CFileValidator extends Validator | |
| { | |
| 	/** | |
| 	 * @var boolean whether the attribute requires a file to be uploaded or not. | |
| 	 * Defaults to false, meaning a file is required to be uploaded. | |
| 	 */ | |
| 	public $allowEmpty = false; | |
| 	/** | |
| 	 * @var mixed a list of file name extensions that are allowed to be uploaded. | |
| 	 * This can be either an array or a string consisting of file extension names | |
| 	 * separated by space or comma (e.g. "gif, jpg"). | |
| 	 * Extension names are case-insensitive. Defaults to null, meaning all file name | |
| 	 * extensions are allowed. | |
| 	 */ | |
| 	public $types; | |
| 	/** | |
| 	 * @var integer the minimum number of bytes required for the uploaded file. | |
| 	 * Defaults to null, meaning no limit. | |
| 	 * @see tooSmall | |
| 	 */ | |
| 	public $minSize; | |
| 	/** | |
| 	 * @var integer the maximum number of bytes required for the uploaded file. | |
| 	 * Defaults to null, meaning no limit. | |
| 	 * Note, the size limit is also affected by 'upload_max_filesize' INI setting | |
| 	 * and the 'MAX_FILE_SIZE' hidden field value. | |
| 	 * @see tooLarge | |
| 	 */ | |
| 	public $maxSize; | |
| 	/** | |
| 	 * @var string the error message used when the uploaded file is too large. | |
| 	 * @see maxSize | |
| 	 */ | |
| 	public $tooLarge; | |
| 	/** | |
| 	 * @var string the error message used when the uploaded file is too small. | |
| 	 * @see minSize | |
| 	 */ | |
| 	public $tooSmall; | |
| 	/** | |
| 	 * @var string the error message used when the uploaded file has an extension name | |
| 	 * that is not listed among {@link extensions}. | |
| 	 */ | |
| 	public $wrongType; | |
| 	/** | |
| 	 * @var integer the maximum file count the given attribute can hold. | |
| 	 * It defaults to 1, meaning single file upload. By defining a higher number, | |
| 	 * multiple uploads become possible. | |
| 	 */ | |
| 	public $maxFiles = 1; | |
| 	/** | |
| 	 * @var string the error message used if the count of multiple uploads exceeds | |
| 	 * limit. | |
| 	 */ | |
| 	public $tooMany; | |
|  | |
| 	/** | |
| 	 * Set the attribute and then validates using {@link validateFile}. | |
| 	 * If there is any error, the error message is added to the object. | |
| 	 * @param \yii\base\Model $object the object being validated | |
| 	 * @param string $attribute the attribute being validated | |
| 	 */ | |
| 	public function validateAttribute($object, $attribute) | |
| 	{ | |
| 		if ($this->maxFiles > 1) | |
| 		{ | |
| 			$files = $object->$attribute; | |
| 			if (!is_array($files) || !isset($files[0]) || !$files[0] instanceof CUploadedFile) | |
| 				$files = CUploadedFile::getInstances($object, $attribute); | |
| 			if (array() === $files) | |
| 				return $this->emptyAttribute($object, $attribute); | |
| 			if (count($files) > $this->maxFiles) | |
| 			{ | |
| 				$message = $this->tooMany !== null ? $this->tooMany : \Yii::t('yii', '{attribute} cannot accept more than {limit} files.'); | |
| 				$this->addError($object, $attribute, $message, array('{attribute}' => $attribute, '{limit}' => $this->maxFiles)); | |
| 			} else | |
| 				foreach ($files as $file) | |
| 					$this->validateFile($object, $attribute, $file); | |
| 		} else | |
| 		{ | |
| 			$file = $object->$attribute; | |
| 			if (!$file instanceof CUploadedFile) | |
| 			{ | |
| 				$file = CUploadedFile::getInstance($object, $attribute); | |
| 				if (null === $file) | |
| 					return $this->emptyAttribute($object, $attribute); | |
| 			} | |
| 			$this->validateFile($object, $attribute, $file); | |
| 		} | |
| 	} | |
|  | |
| 	/** | |
| 	 * Internally validates a file object. | |
| 	 * @param \yii\base\Model $object the object being validated | |
| 	 * @param string $attribute the attribute being validated | |
| 	 * @param CUploadedFile $file uploaded file passed to check against a set of rules | |
| 	 */ | |
| 	public function validateFile($object, $attribute, $file) | |
| 	{ | |
| 		if (null === $file || ($error = $file->getError()) == UPLOAD_ERR_NO_FILE) | |
| 			return $this->emptyAttribute($object, $attribute); | |
| 		elseif ($error == UPLOAD_ERR_INI_SIZE || $error == UPLOAD_ERR_FORM_SIZE || $this->maxSize !== null && $file->getSize() > $this->maxSize) | |
| 		{ | |
| 			$message = $this->tooLarge !== null ? $this->tooLarge : \Yii::t('yii', 'The file "{file}" is too large. Its size cannot exceed {limit} bytes.'); | |
| 			$this->addError($object, $attribute, $message, array('{file}' => $file->getName(), '{limit}' => $this->getSizeLimit())); | |
| 		} elseif ($error == UPLOAD_ERR_PARTIAL) | |
| 			throw new CException(\Yii::t('yii', 'The file "{file}" was only partially uploaded.', array('{file}' => $file->getName()))); | |
| 		elseif ($error == UPLOAD_ERR_NO_TMP_DIR) | |
| 			throw new CException(\Yii::t('yii', 'Missing the temporary folder to store the uploaded file "{file}".', array('{file}' => $file->getName()))); | |
| 		elseif ($error == UPLOAD_ERR_CANT_WRITE) | |
| 			throw new CException(\Yii::t('yii', 'Failed to write the uploaded file "{file}" to disk.', array('{file}' => $file->getName()))); | |
| 		elseif (defined('UPLOAD_ERR_EXTENSION') && $error == UPLOAD_ERR_EXTENSION)  // available for PHP 5.2.0 or above | |
| 			throw new CException(\Yii::t('yii', 'File upload was stopped by extension.')); | |
|  | |
| 		if ($this->minSize !== null && $file->getSize() < $this->minSize) | |
| 		{ | |
| 			$message = $this->tooSmall !== null ? $this->tooSmall : \Yii::t('yii', 'The file "{file}" is too small. Its size cannot be smaller than {limit} bytes.'); | |
| 			$this->addError($object, $attribute, $message, array('{file}' => $file->getName(), '{limit}' => $this->minSize)); | |
| 		} | |
|  | |
| 		if ($this->types !== null) | |
| 		{ | |
| 			if (is_string($this->types)) | |
| 				$types = preg_split('/[\s,]+/', strtolower($this->types), -1, PREG_SPLIT_NO_EMPTY); | |
| 			else | |
| 				$types = $this->types; | |
| 			if (!in_array(strtolower($file->getExtensionName()), $types)) | |
| 			{ | |
| 				$message = $this->wrongType !== null ? $this->wrongType : \Yii::t('yii', 'The file "{file}" cannot be uploaded. Only files with these extensions are allowed: {extensions}.'); | |
| 				$this->addError($object, $attribute, $message, array('{file}' => $file->getName(), '{extensions}' => implode(', ', $types))); | |
| 			} | |
| 		} | |
| 	} | |
|  | |
| 	/** | |
| 	 * Raises an error to inform end user about blank attribute. | |
| 	 * @param \yii\base\Model $object the object being validated | |
| 	 * @param string $attribute the attribute being validated | |
| 	 */ | |
| 	public function emptyAttribute($object, $attribute) | |
| 	{ | |
| 		if (!$this->allowEmpty) | |
| 		{ | |
| 			$message = $this->message !== null ? $this->message : \Yii::t('yii', '{attribute} cannot be blank.'); | |
| 			$this->addError($object, $attribute, $message); | |
| 		} | |
| 	} | |
|  | |
| 	/** | |
| 	 * Returns the maximum size allowed for uploaded files. | |
| 	 * This is determined based on three factors: | |
| 	 * <ul> | |
| 	 * <li>'upload_max_filesize' in php.ini</li> | |
| 	 * <li>'MAX_FILE_SIZE' hidden field</li> | |
| 	 * <li>{@link maxSize}</li> | |
| 	 * </ul> | |
| 	 * | |
| 	 * @return integer the size limit for uploaded files. | |
| 	 */ | |
| 	public function getSizeLimit() | |
| 	{ | |
| 		$limit = ini_get('upload_max_filesize'); | |
| 		$limit = $this->sizeToBytes($limit); | |
| 		if ($this->maxSize !== null && $limit > 0 && $this->maxSize < $limit) | |
| 			$limit = $this->maxSize; | |
| 		if (isset($_POST['MAX_FILE_SIZE']) && $_POST['MAX_FILE_SIZE'] > 0 && $_POST['MAX_FILE_SIZE'] < $limit) | |
| 			$limit = $_POST['MAX_FILE_SIZE']; | |
| 		return $limit; | |
| 	} | |
|  | |
| 	/** | |
| 	 * Converts php.ini style size to bytes | |
| 	 * | |
| 	 * @param string $sizeStr $sizeStr | |
| 	 * @return int | |
| 	 */ | |
| 	private function sizeToBytes($sizeStr) | |
| 	{ | |
| 		switch (substr($sizeStr, -1)) | |
| 		{ | |
| 			case 'M': case 'm': return (int)$sizeStr * 1048576; | |
| 			case 'K': case 'k': return (int)$sizeStr * 1024; | |
| 			case 'G': case 'g': return (int)$sizeStr * 1073741824; | |
| 			default: return (int)$sizeStr; | |
| 		} | |
| 	} | |
| } |