From 42643e3747cdf224cfbe9dbf4bd6f5be2f0bbb29 Mon Sep 17 00:00:00 2001 From: Mark Date: Sat, 14 Jun 2014 12:42:12 +0400 Subject: [PATCH] type validation adjusted --- framework/helpers/BaseFileHelper.php | 20 ++++++++ framework/validators/FileValidator.php | 69 ++++++++++++++++++++++++-- 2 files changed, 85 insertions(+), 4 deletions(-) diff --git a/framework/helpers/BaseFileHelper.php b/framework/helpers/BaseFileHelper.php index 526aef5501..71c2e5bf0b 100644 --- a/framework/helpers/BaseFileHelper.php +++ b/framework/helpers/BaseFileHelper.php @@ -161,6 +161,26 @@ class BaseFileHelper return null; } + /** + * Determines the extensions by given mime-type. + * This method will use a local map between extension names and MIME types. + * @param string $mimeType file mime-type. + * @param string $magicFile the path of the file that contains all available MIME type information. + * If this is not set, the default file aliased by `@yii/util/mimeTypes.php` will be used. + * @return array. + */ + public static function getExtensionsByMimeType($mimeType, $magicFile = null) + { + static $mimeTypes = []; + + if (!count($mimeTypes)) { + $magicFile = __DIR__ . '/mimeTypes.php'; + $mimeTypes = require($magicFile); + } + + return array_keys($mimeTypes, mb_strtolower($mimeType, 'utf-8')); + } + /** * Copies a whole directory as another one. * The files and sub-directories will also be copied over. diff --git a/framework/validators/FileValidator.php b/framework/validators/FileValidator.php index 864ba044d4..57eb09dcc9 100644 --- a/framework/validators/FileValidator.php +++ b/framework/validators/FileValidator.php @@ -30,6 +30,12 @@ class FileValidator extends Validator * @see wrongType */ public $types; + /** + * + * @var boolean whether to check file type (extension) with mime-type. If extension produced by + * file mime-type check differs from uploaded file extension, file will be counted as not valid. + */ + public $checkTypeAgainstMime = true; /** * @var array|string a list of file MIME types that are allowed to be uploaded. * This can be either an array or a string consisting of file MIME types @@ -197,15 +203,16 @@ class FileValidator extends Validator if (!$file instanceof UploadedFile || $file->error == UPLOAD_ERR_NO_FILE) { return [$this->uploadRequired, []]; } + switch ($file->error) { case UPLOAD_ERR_OK: - if ($this->maxSize !== null && $file->size > $this->maxSize) { + if ($this->maxSize !== null && !$this->validateMaxSize($file)) { return [$this->tooBig, ['file' => $file->name, 'limit' => $this->getSizeLimit()]]; - } elseif ($this->minSize !== null && $file->size < $this->minSize) { + } elseif ($this->minSize !== null && !$this->validateMinSize($file)) { return [$this->tooSmall, ['file' => $file->name, 'limit' => $this->minSize]]; - } elseif (!empty($this->types) && !in_array(strtolower(pathinfo($file->name, PATHINFO_EXTENSION)), $this->types, true)) { + } elseif (!empty($this->types) && !$this->validateType($file)) { return [$this->wrongType, ['file' => $file->name, 'extensions' => implode(', ', $this->types)]]; - } elseif (!empty($this->mimeTypes) && !in_array(FileHelper::getMimeType($file->tempName), $this->mimeTypes, true)) { + } elseif (!empty($this->mimeTypes) && !$this->validateMimeType($file)) { return [$this->wrongMimeType, ['file' => $file->name, 'mimeTypes' => implode(', ', $this->mimeTypes)]]; } else { return null; @@ -287,4 +294,58 @@ class FileValidator extends Validator return (int) $sizeStr; } } + + /** + * Checks if given uploaded file have correct type (extension) according current validator settings. + * @param \yii\web\UploadedFile $file + * @return boolean + */ + public function validateType($file) + { + if ($this->checkTypeAgainstMime) { + + $extensionsByMimeType = FileHelper::getExtensionsByMimeType(FileHelper::getMimeType($file->tempName)); + + if (!in_array($file->extension, $extensionsByMimeType, true)) { + return false; + } + } + + if (!in_array($file->extension, $this->types, true)) { + return false; + } + + return true; + } + + /** + * Checks if given uploaded file have correct mime-type. + * @param \yii\web\UploadedFile $file + * @return boolean + */ + public function validateMimeType($file) + { + return in_array(FileHelper::getMimeType($file->tempName), $this->mimeTypes, true); + } + + /** + * Checks if given uploaded file have correct size according current max size. + * @param \yii\web\UploadedFile $file + * @return boolean + */ + public function validateMaxSize($file) + { + return $this->maxSize > $file->size; + } + + /** + * Checks if given uploaded file have correct size according current min size. + * @param \yii\web\UploadedFile $file + * @return boolean + */ + public function validateMinSize($file) + { + return $this->minSize < $file->size; + } + }