Added support for multiple mime-types per file extension [#3422]

This commit is contained in:
Matias Griese
2021-08-13 13:05:32 +03:00
parent c975f894ae
commit f45afd1f54
5 changed files with 2120 additions and 6 deletions

View File

@@ -6,7 +6,8 @@
* Added `UserObject::$authorizeCallable` to allow `$user->authorize()` customization
1. [](#improved)
* Added meta support for `UploadedFile` class
* Add `setCurrent()` method to Page Collection [#3398](https://github.com/getgrav/grav/pull/3398)
* Added support for multiple mime-types per file extension [#3422](https://github.com/getgrav/grav/issues/3422)
* Added `setCurrent()` method to Page Collection [#3398](https://github.com/getgrav/grav/pull/3398)
* Initialize `$grav['uri]` before session
1. [](#bugfix)
* Fixed `Warning: Undefined array key "SERVER_SOFTWARE" in index.php` [#3408](https://github.com/getgrav/grav/issues/3408)

1986
system/config/mime.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -20,11 +20,13 @@ use Grav\Common\Security;
use Grav\Common\Utils;
use Grav\Framework\Filesystem\Filesystem;
use Grav\Framework\Form\FormFlashFile;
use Grav\Framework\Mime\MimeTypes;
use Psr\Http\Message\UploadedFileInterface;
use RocketTheme\Toolbox\File\YamlFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use RuntimeException;
use function dirname;
use function in_array;
/**
* Implements media upload and delete functionality.
@@ -179,16 +181,20 @@ trait MediaUploadTrait
}
}
$grav = Grav::instance();
/** @var MimeTypes $mimeChecker */
$mimeChecker = $grav['mime'];
// Handle Accepted file types. Accept can only be mime types (image/png | image/*) or file extensions (.pdf | .jpg)
$accepted = false;
$errors = [];
// Do not trust mime type sent by the browser.
$mime = Utils::getMimeByFilename($filename);
$mimeTest = $metadata['mime'] ?? $mime;
if ($mime !== $mimeTest) {
$mime = $metadata['mime'] ?? $mimeChecker->getMimeType($extension);
$validExtensions = $mimeChecker->getExtensions($mime);
if (!in_array($extension, $validExtensions, true)) {
throw new RuntimeException('The mime type does not match to file extension', 400);
}
$accepted = false;
$errors = [];
foreach ((array)$settings['accept'] as $type) {
// Force acceptance of any file when star notation
if ($type === '*') {

View File

@@ -17,6 +17,7 @@ use Grav\Common\Config\Config;
use Grav\Common\Config\ConfigFileFinder;
use Grav\Common\Config\Setup;
use Grav\Common\Language\Language;
use Grav\Framework\Mime\MimeTypes;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use RocketTheme\Toolbox\File\YamlFile;
@@ -56,6 +57,19 @@ class ConfigServiceProvider implements ServiceProviderInterface
return $config;
};
$container['mime'] = function ($c) {
/** @var Config $config */
$config = $c['config'];
$mimes = $config->get('mime.types', []);
foreach ($config->get('media.types', []) as $ext => $media) {
if (!empty($media['mime'])) {
$mimes[$ext] = array_unique(array_merge([$media['mime']], $mimes[$ext] ?? []));
}
}
return MimeTypes::createFromMimes($mimes);
};
$container['languages'] = function ($c) {
return static::languages($c);
};

View File

@@ -0,0 +1,107 @@
<?php declare(strict_types=1);
/**
* @package Grav\Framework\Mime
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Framework\Mime;
use function in_array;
/**
* Class to handle mime-types.
*/
class MimeTypes
{
/** @var array */
protected $extensions;
/** @var array */
protected $mimes;
/**
* Create a new mime types instance with the given mappings.
*
* @param array $mimes An associative array containing ['ext' => ['mime/type', 'mime/type2']]
*/
public static function createFromMimes(array $mimes): self
{
$extensions = [];
foreach ($mimes as $ext => $list) {
foreach ($list as $mime) {
$list = $extensions[$mime] ?? [];
if (!in_array($ext, $list, true)) {
$list[] = $ext;
$extensions[$mime] = $list;
}
}
}
return new static($extensions, $mimes);
}
/**
* @param string $extension
* @return string|null
*/
public function getMimeType(string $extension): ?string
{
$extension = $this->cleanInput($extension);
return $this->mimes[$extension][0] ?? null;
}
/**
* @param string $mime
* @return string|null
*/
public function getExtension(string $mime): ?string
{
$mime = $this->cleanInput($mime);
return $this->extensions[$mime][0] ?? null;
}
/**
* @param string $extension
* @return array
*/
public function getMimeTypes(string $extension): array
{
$extension = $this->cleanInput($extension);
return $this->mimes[$extension] ?? [];
}
/**
* @param string $mime
* @return array
*/
public function getExtensions(string $mime): array
{
$mime = $this->cleanInput($mime);
return $this->extensions[$mime] ?? [];
}
/**
* @param string $input
* @return string
*/
protected function cleanInput(string $input): string
{
return strtolower(trim($input));
}
/**
* @param array $extensions
* @param array $mimes
*/
protected function __construct(array $extensions, array $mimes)
{
$this->extensions = $extensions;
$this->mimes = $mimes;
}
}