Commit 084819b8 by Qiang Xue

refactored file validator.

parent c42942a0
...@@ -110,7 +110,7 @@ Yii Framework 2 Change Log ...@@ -110,7 +110,7 @@ Yii Framework 2 Change Log
- Chg #3640: All cookies are now httpOnly by default in order to increase overall security (samdark) - Chg #3640: All cookies are now httpOnly by default in order to increase overall security (samdark)
- Chg #3687: Default `sourceLanguage` and `language` are now `en-US` in order for i18n formatter to work correctly (samdark) - Chg #3687: Default `sourceLanguage` and `language` are now `en-US` in order for i18n formatter to work correctly (samdark)
- Chg #3804: Added `fileinfo` PHP extension to the basic requirement of Yii (Ragazzo) - Chg #3804: Added `fileinfo` PHP extension to the basic requirement of Yii (Ragazzo)
- Chg #3866: `FileValidator::types` attribute changed to `FileValidator::extensions` (Ragazzo) - Chg #3866: The `FileValidator::types` property is renamed to `FileValidator::extensions` (Ragazzo)
- Chg: Replaced `clearAll()` and `clearAllAssignments()` in `yii\rbac\ManagerInterface` with `removeAll()`, `removeAllRoles()`, `removeAllPermissions()`, `removeAllRules()` and `removeAllAssignments()` (qiangxue) - Chg: Replaced `clearAll()` and `clearAllAssignments()` in `yii\rbac\ManagerInterface` with `removeAll()`, `removeAllRoles()`, `removeAllPermissions()`, `removeAllRules()` and `removeAllAssignments()` (qiangxue)
- Chg: Added `$user` as the first parameter of `yii\rbac\Rule::execute()` (qiangxue) - Chg: Added `$user` as the first parameter of `yii\rbac\Rule::execute()` (qiangxue)
- Chg: `yii\grid\DataColumn::getDataCellValue()` visibility is now `public` to allow accessing the value from a GridView directly (cebe) - Chg: `yii\grid\DataColumn::getDataCellValue()` visibility is now `public` to allow accessing the value from a GridView directly (cebe)
......
...@@ -48,11 +48,10 @@ Upgrade from Yii 2.0 Beta ...@@ -48,11 +48,10 @@ Upgrade from Yii 2.0 Beta
* The database table of the `yii\log\DbTarget` now needs a `prefix` column to store context information. * The database table of the `yii\log\DbTarget` now needs a `prefix` column to store context information.
You can add it with `ALTER TABLE log ADD COLUMN prefix TEXT AFTER log_time;`. You can add it with `ALTER TABLE log ADD COLUMN prefix TEXT AFTER log_time;`.
* The `fileinfo` PHP extension is now required by Yii. If you use `yii\helpers\FileHelper::getMimeType()`, make sure * The `fileinfo` PHP extension is now required by Yii. If you use `yii\helpers\FileHelper::getMimeType()`, make sure
you have enabled this extension. This extension is [builtin](http://www.php.net/manual/en/fileinfo.installation.php) in php above `5.3`. you have enabled this extension. This extension is [builtin](http://www.php.net/manual/en/fileinfo.installation.php) in php above `5.3`.
* Please update your main layout file by adding this line in the `<head>` section: `<?= Html::csrfMetaTags() ?>`. * Please update your main layout file by adding this line in the `<head>` section: `<?= Html::csrfMetaTags() ?>`.
This change is needed because `yii\web\View` no longer automatically generates CSRF meta tags due to issue #3358. This change is needed because `yii\web\View` no longer automatically generates CSRF meta tags due to issue #3358.
* `FileValidator::types` attribute was changed to `FileValidator::extensions` for consistency. If you use this attribute in your code you * If your model code is using the `file` validation rule, you should rename its `types` option to `extensions`.
should consider this replacement.
...@@ -139,22 +139,17 @@ class BaseFileHelper ...@@ -139,22 +139,17 @@ class BaseFileHelper
* This method will use a local map between extension names and MIME types. * This method will use a local map between extension names and MIME types.
* @param string $file the file name. * @param string $file the file name.
* @param string $magicFile the path of the file that contains all available MIME type information. * @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. * If this is not set, the default file aliased by `@yii/helpers/mimeTypes.php` will be used.
* @return string the MIME type. Null is returned if the MIME type cannot be determined. * @return string the MIME type. Null is returned if the MIME type cannot be determined.
*/ */
public static function getMimeTypeByExtension($file, $magicFile = null) public static function getMimeTypeByExtension($file, $magicFile = null)
{ {
static $mimeTypes = []; $mimeTypes = static::loadMimeTypes($magicFile);
if ($magicFile === null) {
$magicFile = __DIR__ . '/mimeTypes.php';
}
if (!isset($mimeTypes[$magicFile])) {
$mimeTypes[$magicFile] = require($magicFile);
}
if (($ext = pathinfo($file, PATHINFO_EXTENSION)) !== '') { if (($ext = pathinfo($file, PATHINFO_EXTENSION)) !== '') {
$ext = strtolower($ext); $ext = strtolower($ext);
if (isset($mimeTypes[$magicFile][$ext])) { if (isset($mimeTypes[$ext])) {
return $mimeTypes[$magicFile][$ext]; return $mimeTypes[$ext];
} }
} }
...@@ -162,23 +157,36 @@ class BaseFileHelper ...@@ -162,23 +157,36 @@ class BaseFileHelper
} }
/** /**
* Determines the extensions by given mime-type. * Determines the extensions by given MIME type.
* This method will use a local map between extension names and MIME types. * This method will use a local map between extension names and MIME types.
* @param string $mimeType file mime-type. * @param string $mimeType file MIME type.
* @param string $magicFile the path of the file that contains all available MIME type information. * @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. * If this is not set, the default file aliased by `@yii/helpers/mimeTypes.php` will be used.
* @return array. * @return array the extensions corresponding to the specified MIME type
*/ */
public static function getExtensionsByMimeType($mimeType, $magicFile = null) public static function getExtensionsByMimeType($mimeType, $magicFile = null)
{ {
static $mimeTypes = []; $mimeTypes = static::loadMimeTypes($magicFile);
return array_keys($mimeTypes, mb_strtolower($mimeType, 'utf-8'), true);
}
private static $_mimeTypes = [];
if (!count($mimeTypes)) { /**
* Loads MIME types from the specified file.
* @param string $magicFile the file that contains MIME type information.
* If null, the file `@yii/helpers/mimeTypes.php` will be used.
* @return array the mapping from file extensions to MIME types
*/
protected static function loadMimeTypes($magicFile)
{
if ($magicFile === null) {
$magicFile = __DIR__ . '/mimeTypes.php'; $magicFile = __DIR__ . '/mimeTypes.php';
$mimeTypes = require($magicFile);
} }
if (!isset(self::$_mimeTypes[$magicFile])) {
return array_keys($mimeTypes, mb_strtolower($mimeType, 'utf-8')); self::$_mimeTypes[$magicFile] = require($magicFile);
}
return self::$_mimeTypes[$magicFile];
} }
/** /**
......
...@@ -31,9 +31,8 @@ class FileValidator extends Validator ...@@ -31,9 +31,8 @@ class FileValidator extends Validator
*/ */
public $extensions; public $extensions;
/** /**
*
* @var boolean whether to check file type (extension) with mime-type. If extension produced by * @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. * file mime-type check differs from uploaded file extension, the file will be considered as invalid.
*/ */
public $checkExtensionByMimeType = true; public $checkExtensionByMimeType = true;
/** /**
...@@ -93,6 +92,14 @@ class FileValidator extends Validator ...@@ -93,6 +92,14 @@ class FileValidator extends Validator
*/ */
public $tooSmall; public $tooSmall;
/** /**
* @var string the error message used if the count of multiple uploads exceeds limit.
* You may use the following tokens in the message:
*
* - {attribute}: the attribute name
* - {limit}: the value of [[maxFiles]]
*/
public $tooMany;
/**
* @var string the error message used when the uploaded file has an extension name * @var string the error message used when the uploaded file has an extension name
* that is not listed in [[extensions]]. You may use the following tokens in the message: * that is not listed in [[extensions]]. You may use the following tokens in the message:
* *
...@@ -102,14 +109,6 @@ class FileValidator extends Validator ...@@ -102,14 +109,6 @@ class FileValidator extends Validator
*/ */
public $wrongExtension; public $wrongExtension;
/** /**
* @var string the error message used if the count of multiple uploads exceeds limit.
* You may use the following tokens in the message:
*
* - {attribute}: the attribute name
* - {limit}: the value of [[maxFiles]]
*/
public $tooMany;
/**
* @var string the error message used when the file has an mime type * @var string the error message used when the file has an mime type
* that is not listed in [[mimeTypes]]. * that is not listed in [[mimeTypes]].
* You may use the following tokens in the message: * You may use the following tokens in the message:
...@@ -296,23 +295,28 @@ class FileValidator extends Validator ...@@ -296,23 +295,28 @@ class FileValidator extends Validator
/** /**
* Checks if given uploaded file have correct type (extension) according current validator settings. * Checks if given uploaded file have correct type (extension) according current validator settings.
* @param \yii\web\UploadedFile $file * @param UploadedFile $file
* @return boolean * @return boolean
*/ */
public function validateExtension($file) protected function validateExtension($file)
{ {
$fileExtension = mb_strtolower($file->extension, 'utf-8'); $extension = mb_strtolower($file->extension, 'utf-8');
if ($this->checkExtensionByMimeType) { if ($this->checkExtensionByMimeType) {
$extensionsByMimeType = FileHelper::getExtensionsByMimeType(FileHelper::getMimeType($file->tempName)); $mimeType = FileHelper::getMimeType($file->tempName);
if ($mimeType === null) {
return false;
}
$extensionsByMimeType = FileHelper::getExtensionsByMimeType($mimeType);
if (!in_array($fileExtension, $extensionsByMimeType, true)) { if (!in_array($extension, $extensionsByMimeType, true)) {
return false; return false;
} }
} }
if (!in_array($fileExtension, $this->extensions, true)) { if (!in_array($extension, $this->extensions, true)) {
return false; return false;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment