yii2: Composite file extension validation is not supported

Feature request.

What steps will reproduce the problem?

Try to validate composite file extension such as tar.xz

What is the expected result?

File name file.bar.xz should not be uploaded only file.tar.xz should be allowed.

What do you get instead?

Any file ended with .xz is uploaded.

Additional info

Checkout this question on Stack Overflow

Q A
Yii version 2.0.?
PHP version 7
Operating system

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 18 (18 by maintainers)

Most upvoted comments

What is the problem? a file named loremLibsum.com.html to be com.html!

I’m not sure how it helps. com.html is definitely not a valid extensions of this file, so this regex cannot be used for detecting extensions. And it does not really help if we need to use StringHelper::endsWith() to compare list of extensions with file name, since we can call it on file path directly. basename does not help here either (BTW: there is separate basename() method for this).

Don’t fight the definition! As regarded in the Wikipedia, the file extension is the portion that is separated by period. It is so simple. Any thing after the first dot is regarded as an extension.

From the API, StringHelper::endsWith method takes two required string parameters and the third is optional, so we could use it like the following:

$path = getThePathByAnyWay();
$allowedExtensionsList = getAnArrayOfAllowedExtensionsByAnyWay()
$fileBaseName = pathinfo($path)['basename'];
$matches = [];
$fileExtension = preg_match('/\.([a-z0-9\.]*)/',$fileBaseName,$matches)
//return StringHelper::endsWith($fileBaseName,$fileExtension[1])  
//OR
// return in_array($fileExtension[1], $allowedExtensionsList)

Again this is closest to be pseudo code!

@saidbakr Simply the computer may assume it as well.

But it’s not. For simple implementations it is better to check extension after the last dot instead of first one, and I can’t imagine any app which would decide that com.index is valid extension of example.com.html file and does not treat it as a bug.

@samdark Or we could use StringHelper::endsWith() for comparing list of extensions with file path to check if file name match any of extensions specified in FileValidator::$extensions - then user can use anything here (even com.html) and it still will be simpler and foolproof than regex. For MIME validation we may use “real” extension, because this is the only sane thing to do. So for tar.gz we should check if file name ends with .tar.gz and for MIME validation we would check if application/gzip type match gz extension.

I’ve re-checked everything.

  1. In this case we want to validate extension and mime type separately so we need to set 'checkExtensionByMimeType' => false.
  2. Mime validation would work as expected with 'mimeTypes' => ['application/x-xz'] if you’ll add corresponding mime type to config.
  3. As for extension, it won’t work because it’s not clear what to consider an extension. According PHP’s pathinfo it is what comes after last . in the full name.

In order to solve point 3, we can introduce another option to validate file name according to something like regular expression. Then you’d be able to do 'mask' => '~\.tar\.xz$~i'.