Skip to content
Snippets Groups Projects
Commit 6fbf4f4e authored by catch's avatar catch
Browse files

Issue #3172550 by bradjones1, DuaelFr, alexpott, smustgrave, longwave:...

Issue #3172550 by bradjones1, DuaelFr, alexpott, smustgrave, longwave: Register Drupal's mime type guesser the Symfony MimeTypes service
parent 0ad1db0b
No related branches found
No related tags found
No related merge requests found
Showing with 126 additions and 4 deletions
......@@ -17,6 +17,7 @@
use Drupal\Core\DependencyInjection\YamlFileLoader;
use Drupal\Core\Extension\Extension;
use Drupal\Core\Extension\ExtensionDiscovery;
use Drupal\Core\File\MimeType\MimeTypeGuesser;
use Drupal\Core\Http\TrustedHostsRequestFactory;
use Drupal\Core\Installer\InstallerKernel;
use Drupal\Core\Installer\InstallerRedirectTrait;
......@@ -596,6 +597,9 @@ public function preHandle(Request $request) {
// Set the allowed protocols.
UrlHelper::setAllowedProtocols($this->container->getParameter('filter_protocols'));
// Override of Symfony's MIME type guesser singleton.
MimeTypeGuesser::registerWithSymfonyGuesser($this->container);
$this->prepared = TRUE;
}
......
......@@ -153,6 +153,8 @@ class ExtensionMimeTypeGuesser implements MimeTypeGuesserInterface {
129 => 'application/x-iphone',
130 => 'application/x-iso9660-image',
131 => 'application/x-java-jnlp-file',
// Per RFC 9239, text/javascript is preferred over application/javascript.
// @see https://www.rfc-editor.org/rfc/rfc9239
132 => 'text/javascript',
133 => 'application/x-jmol',
134 => 'application/x-kchart',
......
......@@ -3,7 +3,9 @@
namespace Drupal\Core\File\MimeType;
use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Mime\MimeTypeGuesserInterface;
use Symfony\Component\Mime\MimeTypes;
/**
* Defines a MIME type guesser that also supports stream wrapper paths.
......@@ -111,4 +113,19 @@ protected function sortGuessers() {
return array_merge(...$this->guessers);
}
/**
* A helper function to register with Symfony's singleton MIME type guesser.
*
* Symfony's default mimetype guessers have dependencies on PHP's fileinfo
* extension or being able to run the system command file. Drupal's guesser
* does not have these dependencies.
*
* @see \Symfony\Component\Mime\MimeTypes
*/
public static function registerWithSymfonyGuesser(ContainerInterface $container) {
$guesser = new MimeTypes();
$guesser->registerGuesser($container->get('file.mime_type.guesser'));
MimeTypes::setDefault($guesser);
}
}
......@@ -23,7 +23,11 @@ class SettingsConfigValidationTest extends KernelTestBase {
public function testPreviewImagePathIsValidated(): void {
$this->installConfig('image');
$file = sys_get_temp_dir() . '/fake_image.png';
// Drupal does not have a hard dependency on the fileinfo extension and
// implements an extension-based mimetype guesser. Therefore, we must use
// an incorrect extension here instead of writing text to a supposed PNG
// file and depending on a check of the file contents.
$file = sys_get_temp_dir() . '/fake_image.png.txt';
file_put_contents($file, 'Not an image!');
$this->expectException(SchemaIncompleteException::class);
......
......@@ -119,9 +119,6 @@ public function deliver(Request $request, string $file_name) {
if (file_exists($uri)) {
return new BinaryFileResponse($uri, 200, [
'Cache-control' => static::CACHE_CONTROL,
// @todo: remove the explicit setting of Content-Type once this is
// fixed in https://www.drupal.org/project/drupal/issues/3172550.
'Content-Type' => $this->contentType,
]);
}
......
name: 'Binary File Response test'
type: module
description: 'Support module for Batch Binary File Response tests.'
package: Testing
version: VERSION
binary_file_response_test.download:
path: '/binary_file_response_test/download'
defaults:
_controller: '\Drupal\binary_file_response_test\Controller\BinaryFileResponseTestController::download'
_title: 'Redirect'
requirements:
_access: 'TRUE'
<?php
namespace Drupal\binary_file_response_test\Controller;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
/**
* Controller routines for binary file response tests.
*/
class BinaryFileResponseTestController {
/**
* Download the file set in the relative_file_url query parameter.
*
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
* The response wrapping the file content.
*/
public function download(Request $request) {
if (!$request->query->has('relative_file_url')) {
throw new BadRequestHttpException();
}
$relative_file_url = $request->query->get('relative_file_url');
// A relative URL for a file contains '%20' instead of spaces. A relative
// file path contains spaces.
$relative_file_path = rawurldecode($relative_file_url);
// Ensure the file path does not start with a slash to prevent exploring
// the file system root.
$relative_file_path = ltrim($relative_file_path, '/');
return new BinaryFileResponse($relative_file_path);
}
}
<?php
declare(strict_types=1);
namespace Drupal\KernelTests\Core\Http;
use Drupal\KernelTests\KernelTestBase;
use Symfony\Component\HttpFoundation\Request;
/**
* Tests the headers added by BinaryFileResponse.
*
* @group Http
*/
class BinaryFileResponseTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['binary_file_response_test'];
/**
* Test the content type generated by Drupal is correct.
*
* @dataProvider providerTestCalculatedContentType
*/
public function testCalculatedContentType($path, $content_type): void {
$query = ['relative_file_url' => $path];
$request = Request::create('/binary_file_response_test/download', 'GET', $query);
$response = \Drupal::service('http_kernel')->handle($request);
$response->prepare($request);
$this->assertSame($content_type, current(explode(';', $response->headers->get('Content-Type'))));
}
/**
* Data provider of file names and expected content-type values.
*/
public static function providerTestCalculatedContentType(): array {
return [
['core/misc/print.css', 'text/css'],
['core/misc/checkbox.js', 'text/javascript'],
['core/misc/tree.png', 'image/png'],
];
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment