From 006fc89c099eb05f917f8e993d007f2ffc8a918e Mon Sep 17 00:00:00 2001 From: Claudiu Cristea Date: Tue, 9 Jul 2013 15:14:18 +0300 Subject: [PATCH] Issue #1987712 by damiankloip, andypost, dawehner, claudiu.cristea | vijaycs85: Convert file_download() to a new style controller. --- core/includes/file.inc | 39 ----- .../Drupal/config/Controller/ConfigController.php | 31 +++- core/modules/file/file.module | 2 +- core/modules/image/image.module | 46 ------ core/modules/image/image.routing.yml | 8 + core/modules/image/image.services.yml | 9 ++ .../Controller/ImageStyleDownloadController.php | 164 +++++++++++++++++++++ .../image/EventSubscriber/RouteSubscriber.php | 55 +++++++ .../image/lib/Drupal/image/ImageStyleInterface.php | 24 --- .../PathProcessor/PathProcessorImageStyles.php | 57 +++++++ .../Drupal/image/Plugin/Core/Entity/ImageStyle.php | 87 +---------- .../lib/Drupal/system/FileDownloadController.php | 99 +++++++++++++ .../system/PathProcessor/PathProcessorFiles.php | 33 +++++ core/modules/system/system.module | 7 - core/modules/system/system.routing.yml | 8 + core/modules/system/system.services.yml | 4 + 16 files changed, 464 insertions(+), 209 deletions(-) create mode 100644 core/modules/image/image.services.yml create mode 100644 core/modules/image/lib/Drupal/image/Controller/ImageStyleDownloadController.php create mode 100644 core/modules/image/lib/Drupal/image/EventSubscriber/RouteSubscriber.php create mode 100644 core/modules/image/lib/Drupal/image/PathProcessor/PathProcessorImageStyles.php create mode 100644 core/modules/system/lib/Drupal/system/FileDownloadController.php create mode 100644 core/modules/system/lib/Drupal/system/PathProcessor/PathProcessorFiles.php diff --git a/core/includes/file.inc b/core/includes/file.inc index 1af50cc..e70fa98 100644 --- a/core/includes/file.inc +++ b/core/includes/file.inc @@ -7,9 +7,6 @@ use Drupal\Core\StreamWrapper\LocalStream; use Drupal\Component\PhpStorage\MTimeProtectedFastFileStorage; -use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Symfony\Component\HttpFoundation\BinaryFileResponse; /** * Stream wrapper bit flags that are the basis for composite types. @@ -1332,42 +1329,6 @@ function file_unmanaged_save_data($data, $destination = NULL, $replace = FILE_EX } /** - * Page callback: Handles private file transfers. - * - * Call modules that implement hook_file_download() to find out if a file is - * accessible and what headers it should be transferred with. If one or more - * modules returned headers the download will start with the returned headers. - * If a module returns -1 an AccessDeniedHttpException will be thrown. - * If the file exists but no modules responded an AccessDeniedHttpException will - * be thrown.If the file does not exist a NotFoundHttpException will be thrown. - * - * @see hook_file_download() - * @see system_menu() - */ -function file_download() { - // Merge remaining path arguments into relative file path. - $args = func_get_args(); - $scheme = array_shift($args); - $target = implode('/', $args); - $uri = $scheme . '://' . $target; - if (file_stream_wrapper_valid_scheme($scheme) && file_exists($uri)) { - // Let other modules provide headers and controls access to the file. - $headers = module_invoke_all('file_download', $uri); - foreach ($headers as $result) { - if ($result == -1) { - throw new AccessDeniedHttpException(); - } - } - if (count($headers)) { - return new BinaryFileResponse($uri, 200, $headers); - } - throw new AccessDeniedHttpException(); - } - throw new NotFoundHttpException(); -} - - -/** * Finds all files that match a given mask in a given directory. * * Directories and files beginning with a period are excluded; this diff --git a/core/modules/config/lib/Drupal/config/Controller/ConfigController.php b/core/modules/config/lib/Drupal/config/Controller/ConfigController.php index 34366fc..13917c0 100644 --- a/core/modules/config/lib/Drupal/config/Controller/ConfigController.php +++ b/core/modules/config/lib/Drupal/config/Controller/ConfigController.php @@ -10,9 +10,10 @@ use Drupal\Core\Controller\ControllerInterface; use Drupal\Core\Config\StorageInterface; use Drupal\Component\Archiver\ArchiveTar; -use Drupal\Core\Ajax\AjaxResponse; -use Drupal\Core\Ajax\OpenModalDialogCommand; +use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\system\FileDownloadController; use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\HttpFoundation\Request; /** * Returns responses for config module routes. @@ -22,22 +23,33 @@ class ConfigController implements ControllerInterface { /** * The target storage. * - * @var \Drupal\Core\Config\StorageInterface; + * @var \Drupal\Core\Config\StorageInterface */ protected $targetStorage; /** * The source storage. * - * @var \Drupal\Core\Config\StorageInterface; + * @var \Drupal\Core\Config\StorageInterface */ protected $sourceStorage; /** + * The file download controller. + * + * @var \Drupal\Core\Controller\ControllerInterface + */ + protected $fileDownloadController; + + /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { - return new static($container->get('config.storage'), $container->get('config.storage.staging')); + return new static( + $container->get('config.storage'), + $container->get('config.storage.staging'), + FileDownloadController::create($container) + ); } /** @@ -47,10 +59,13 @@ public static function create(ContainerInterface $container) { * The target storage. * @param \Drupal\Core\Config\StorageInterface $source_storage * The source storage + * @param \Drupal\Core\Controller\ControllerInterface $file_download_controller + * The file download controller. */ - public function __construct(StorageInterface $target_storage, StorageInterface $source_storage) { + public function __construct(StorageInterface $target_storage, StorageInterface $source_storage, ControllerInterface $file_download_controller) { $this->targetStorage = $target_storage; $this->sourceStorage = $source_storage; + $this->fileDownloadController = $file_download_controller; } /** @@ -64,7 +79,9 @@ public function downloadExport() { $config_files[] = $config_dir . '/' . $config_name . '.yml'; } $archiver->createModify($config_files, '', config_get_config_directory()); - return file_download('temporary', 'config.tar.gz'); + + $request = new Request(array('file' => 'config.tar.gz')); + return $this->fileDownloadController->download($request, 'temporary'); } /** diff --git a/core/modules/file/file.module b/core/modules/file/file.module index 0d66adb..b5973dc 100644 --- a/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -1578,7 +1578,7 @@ function file_get_file_references(File $file, $field = NULL, $age = FIELD_LOAD_R // for every revision or the entity does not support revisions then // every usage is already a match. $match_entity_type = $age == FIELD_LOAD_REVISION || !isset($entity_info['entity_keys']['revision']); - $entities = entity_load_multiple($entity_type, $entity_ids); + $entities = entity_load_multiple($entity_type, array_keys($entity_ids)); foreach ($entities as $entity) { $bundle = $entity->bundle(); // We need to find file fields for this entity type and bundle. diff --git a/core/modules/image/image.module b/core/modules/image/image.module index 4e786bd..62aee35 100644 --- a/core/modules/image/image.module +++ b/core/modules/image/image.module @@ -95,28 +95,6 @@ function image_style_entity_uri(ImageStyle $style) { function image_menu() { $items = array(); - // Generate image derivatives of publicly available files. - // If clean URLs are disabled, image derivatives will always be served - // through the menu system. - // If clean URLs are enabled and the image derivative already exists, - // PHP will be bypassed. - $directory_path = file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath(); - $items[$directory_path . '/styles/%image_style'] = array( - 'title' => 'Generate image style', - 'page callback' => 'image_style_deliver', - 'page arguments' => array(count(explode('/', $directory_path)) + 1), - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); - // Generate and deliver image derivatives of private files. - // These image derivatives are always delivered through the menu system. - $items['system/files/styles/%image_style'] = array( - 'title' => 'Generate image style', - 'page callback' => 'image_style_deliver', - 'page arguments' => array(3), - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); $items['admin/config/media/image-styles'] = array( 'title' => 'Image styles', 'description' => 'Configure styles that can be used for resizing or adjusting images on display.', @@ -392,30 +370,6 @@ function image_style_options($include_empty = TRUE) { } /** - * Page callback: Generates a derivative, given a style and image path. - * - * After generating an image, transfer it to the requesting agent. - * - * @param \Drupal\image\ImageStyleInterface $style - * The image style. - * @param string $scheme - * The scheme name of the original image file stream wrapper ('public', - * 'private', 'temporary', etc.). - * - * @return \Symfony\Component\HttpFoundation\BinaryFileResponse|\Symfony\Component\HttpFoundation\Response - * The image to be delivered. - * - * @todo Remove this wrapper in https://drupal.org/node/1987712. - */ -function image_style_deliver(ImageStyleInterface $style, $scheme) { - $args = func_get_args(); - // Remove $style and $scheme from the arguments. - unset($args[0], $args[1]); - $target = implode('/', $args); - return $style->deliver($scheme, $target); -} - -/** * Returns a set of image effects. * * These image effects are exposed by modules implementing diff --git a/core/modules/image/image.routing.yml b/core/modules/image/image.routing.yml index b178d33..46a79f1 100644 --- a/core/modules/image/image.routing.yml +++ b/core/modules/image/image.routing.yml @@ -11,3 +11,11 @@ image_effect_delete: _form: '\Drupal\image\Form\ImageEffectDeleteForm' requirements: _permission: 'administer image styles' + +image_style_private: + pattern: '/system/files/styles/{image_style}/{scheme}' + defaults: + _controller: '\Drupal\image\Controller\ImageStyleDownloadController::deliver' + requirements: + _access: 'TRUE' + diff --git a/core/modules/image/image.services.yml b/core/modules/image/image.services.yml new file mode 100644 index 0000000..2661593 --- /dev/null +++ b/core/modules/image/image.services.yml @@ -0,0 +1,9 @@ +services: + image.route_subscriber: + class: Drupal\image\EventSubscriber\RouteSubscriber + tags: + - { name: 'event_subscriber' } + path_processor.image_styles: + class: Drupal\image\PathProcessor\PathProcessorImageStyles + tags: + - { name: path_processor_inbound, priority: 300 } diff --git a/core/modules/image/lib/Drupal/image/Controller/ImageStyleDownloadController.php b/core/modules/image/lib/Drupal/image/Controller/ImageStyleDownloadController.php new file mode 100644 index 0000000..1d65270 --- /dev/null +++ b/core/modules/image/lib/Drupal/image/Controller/ImageStyleDownloadController.php @@ -0,0 +1,164 @@ +configFactory = $config_factory; + $this->lock = $lock; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('module_handler'), + $container->get('config.factory'), + $container->get('lock') + ); + } + + /** + * Generates a derivative, given a style and image path. + * + * After generating an image, transfer it to the requesting agent. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The request object. + * @param string $scheme + * The file scheme, defaults to 'private'. + * @param \Drupal\image\ImageStyleInterface $image_style + * The image style to deliver. + * + * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException + * Thrown when the user does not have access to the file. + * + * @return \Symfony\Component\HttpFoundation\BinaryFileResponse|\Symfony\Component\HttpFoundation\Response + * The transferred file as response or some error response. + */ + public function deliver(Request $request, $scheme, ImageStyleInterface $image_style) { + $target = $request->query->get('file'); + $image_uri = $scheme . '://' . $target; + + // Check that the style is defined, the scheme is valid, and the image + // derivative token is valid. Sites which require image derivatives to be + // generated without a token can set the + // 'image.settings:allow_insecure_derivatives' configuration to TRUE to + // bypass the latter check, but this will increase the site's vulnerability + // to denial-of-service attacks. + $valid = !empty($image_style) && file_stream_wrapper_valid_scheme($scheme); + if (!$this->configFactory->get('image.settings')->get('allow_insecure_derivatives')) { + $valid &= $request->query->get(IMAGE_DERIVATIVE_TOKEN) === $image_style->getPathToken($image_uri); + } + if (!$valid) { + throw new AccessDeniedHttpException(); + } + + $derivative_uri = $image_style->buildUri($image_uri); + $headers = array(); + + // If using the private scheme, let other modules provide headers and + // control access to the file. + if ($scheme == 'private') { + if (file_exists($derivative_uri)) { + return parent::download($request, $scheme); + } + else { + $headers = $this->moduleHandler->invokeAll('file_download', array($image_uri)); + if (in_array(-1, $headers) || empty($headers)) { + throw new AccessDeniedHttpException(); + } + } + } + + // Don't try to generate file if source is missing. + if (!file_exists($image_uri)) { + watchdog('image', 'Source image at %source_image_path not found while trying to generate derivative image at %derivative_path.', array('%source_image_path' => $image_uri, '%derivative_path' => $derivative_uri)); + return new Response(t('Error generating image, missing source file.'), 404); + } + + // Don't start generating the image if the derivative already exists or if + // generation is in progress in another thread. + $lock_name = 'image_style_deliver:' . $image_style->id() . ':' . Crypt::hashBase64($image_uri); + if (!file_exists($derivative_uri)) { + $lock_acquired = $this->lock->acquire($lock_name); + if (!$lock_acquired) { + // Tell client to retry again in 3 seconds. Currently no browsers are + // known to support Retry-After. + throw new ServiceUnavailableHttpException(3, t('Image generation in progress. Try again shortly.')); + } + } + + // Try to generate the image, unless another thread just did it while we + // were acquiring the lock. + $success = file_exists($derivative_uri) || $image_style->createDerivative($image_uri, $derivative_uri); + + if (!empty($lock_acquired)) { + $this->lock->release($lock_name); + } + + if ($success) { + $image = image_load($derivative_uri); + $uri = $image->source; + $headers += array( + 'Content-Type' => $image->info['mime_type'], + 'Content-Length' => $image->info['file_size'], + ); + return new BinaryFileResponse($uri, 200, $headers); + } + else { + watchdog('image', 'Unable to generate the derived image located at %path.', array('%path' => $derivative_uri)); + return new Response(t('Error generating image.'), 500); + } + } + +} diff --git a/core/modules/image/lib/Drupal/image/EventSubscriber/RouteSubscriber.php b/core/modules/image/lib/Drupal/image/EventSubscriber/RouteSubscriber.php new file mode 100644 index 0000000..69f84f4 --- /dev/null +++ b/core/modules/image/lib/Drupal/image/EventSubscriber/RouteSubscriber.php @@ -0,0 +1,55 @@ +getRouteCollection(); + + $directory_path = file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath(); + + $route = new Route('/' . $directory_path . '/styles/{image_style}/{scheme}', + array( + '_controller' => 'Drupal\image\Controller\ImageStyleDownloadController::deliver', + ), + array( + '_access' => 'TRUE', + ) + ); + $collection->add('image_style_public', $route); + } + +} diff --git a/core/modules/image/lib/Drupal/image/ImageStyleInterface.php b/core/modules/image/lib/Drupal/image/ImageStyleInterface.php index d7803cd..2532cc7 100644 --- a/core/modules/image/lib/Drupal/image/ImageStyleInterface.php +++ b/core/modules/image/lib/Drupal/image/ImageStyleInterface.php @@ -15,30 +15,6 @@ interface ImageStyleInterface extends ConfigEntityInterface { /** - * Delivers an image derivative. - * - * Transfers a generated image derivative to the requesting agent. Modules may - * implement this method to set different serve different image derivatives - * from different stream wrappers or to customize different permissions on - * each image style. - * - * @param string $scheme - * The scheme name of the original image file stream wrapper ('public', - * 'private', 'temporary', etc.). - * @param string $target - * The target part of the uri. - * - * @return \Symfony\Component\HttpFoundation\BinaryFileResponse|\Symfony\Component\HttpFoundation\Response - * The image to be delivered. - * - * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException - * \Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException - * - * @todo Move to controller after https://drupal.org/node/1987712. - */ - public function deliver($scheme, $target); - - /** * Returns the URI of this image when using this style. * * The path returned by this function may not exist. The default generation diff --git a/core/modules/image/lib/Drupal/image/PathProcessor/PathProcessorImageStyles.php b/core/modules/image/lib/Drupal/image/PathProcessor/PathProcessorImageStyles.php new file mode 100644 index 0000000..c0c6f31 --- /dev/null +++ b/core/modules/image/lib/Drupal/image/PathProcessor/PathProcessorImageStyles.php @@ -0,0 +1,57 @@ +getDirectoryPath(); + if (strpos($path, $directory_path . '/styles/') === 0) { + $path_prefix = $directory_path . '/styles/'; + } + elseif (strpos($path, 'system/files/styles/') === 0) { + $path_prefix = 'system/files/styles/'; + } + else { + return $path; + } + + // Strip out path prefix. + $rest = preg_replace('|^' . $path_prefix . '|', '', $path); + + // Get the image style, scheme and path. + list($image_style, $scheme, $file) = explode('/', $rest, 3); + + // Set the file as query parameter. + $request->query->set('file', $file); + + return $path_prefix . $image_style . '/' . $scheme; + } + +} diff --git a/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php b/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php index 7dd36c0..7fc752b 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php +++ b/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php @@ -15,10 +15,6 @@ use Drupal\Component\Utility\Crypt; use Drupal\Component\Utility\Url; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\BinaryFileResponse; -use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; -use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException; /** * Defines an image style configuration entity. @@ -164,84 +160,6 @@ protected static function replaceImageStyle(ImageStyleInterface $style) { /** * {@inheritdoc} */ - public function deliver($scheme, $target) { - $original_uri = $scheme . '://' . $target; - - // Check that the scheme is valid, and the image derivative token is valid. - // (Sites which require image derivatives to be generated without a token - // can set the 'image.settings:allow_insecure_derivatives' configuration to - // TRUE to bypass the latter check, but this will increase the site's - // vulnerability to denial-of-service attacks.) - $valid = file_stream_wrapper_valid_scheme($scheme); - if (!\Drupal::config('image.settings')->get('allow_insecure_derivatives')) { - $image_derivative_token = \Drupal::request()->query->get(IMAGE_DERIVATIVE_TOKEN); - $valid &= isset($image_derivative_token) && $image_derivative_token === $this->getPathToken($original_uri); - } - if (!$valid) { - throw new AccessDeniedHttpException(); - } - - $derivative_uri = $this->buildUri($original_uri); - $headers = array(); - - // If using the private scheme, let other modules provide headers and - // control access to the file. - if ($scheme == 'private') { - if (file_exists($derivative_uri)) { - file_download($scheme, file_uri_target($derivative_uri)); - } - else { - $headers = \Drupal::moduleHandler()->invokeAll('file_download', array($original_uri)); - if (in_array(-1, $headers) || empty($headers)) { - throw new AccessDeniedHttpException(); - } - } - } - - // Don't try to generate file if source is missing. - if (!file_exists($original_uri)) { - watchdog('image', 'Source image at %source_image_path not found while trying to generate derivative image at %derivative_path.', array('%source_image_path' => $original_uri, '%derivative_path' => $derivative_uri)); - return new Response(t('Error generating image, missing source file.'), 404); - } - - // Don't start generating the image if the derivative already exists or if - // generation is in progress in another thread. - $lock_name = 'image_style_deliver:' . $this->id() . ':' . Crypt::hashBase64($original_uri); - if (!file_exists($derivative_uri)) { - $lock_acquired = \Drupal::lock()->acquire($lock_name); - if (!$lock_acquired) { - // Tell client to retry again in 3 seconds. Currently no browsers are - // known to support Retry-After. - throw new ServiceUnavailableHttpException(3, t('Image generation in progress. Try again shortly.')); - } - } - - // Try to generate the image, unless another thread just did it while we - // were acquiring the lock. - $success = file_exists($derivative_uri) || $this->createDerivative($original_uri, $derivative_uri); - - if (!empty($lock_acquired)) { - \Drupal::lock()->release($lock_name); - } - - if ($success) { - $image = image_load($derivative_uri); - $uri = $image->source; - $headers += array( - 'Content-Type' => $image->info['mime_type'], - 'Content-Length' => $image->info['file_size'], - ); - return new BinaryFileResponse($uri, 200, $headers); - } - else { - watchdog('image', 'Unable to generate the derived image located at %path.', array('%path' => $derivative_uri)); - return new Response(t('Error generating image.'), 500); - } - } - - /** - * {@inheritdoc} - */ public function buildUri($uri) { $scheme = file_uri_scheme($uri); if ($scheme) { @@ -397,14 +315,13 @@ public function transformDimensions(array &$dimensions) { * which can be costly both in CPU time and disk space. * * @param string $uri - * The URI of the image for this style, for example as returned by - * \Drupal\image\ImageStyleInterface::buildUri(). + * The URI of the original image of this style. * * @return string * An eight-character token which can be used to protect image style * derivatives against denial-of-service attacks. */ - protected function getPathToken($uri) { + public function getPathToken($uri) { // Return the first eight characters. return substr(Crypt::hmacBase64($this->id() . ':' . $uri, drupal_get_private_key() . drupal_get_hash_salt()), 0, 8); } diff --git a/core/modules/system/lib/Drupal/system/FileDownloadController.php b/core/modules/system/lib/Drupal/system/FileDownloadController.php new file mode 100644 index 0000000..8bff1bb --- /dev/null +++ b/core/modules/system/lib/Drupal/system/FileDownloadController.php @@ -0,0 +1,99 @@ +moduleHandler = $module_handler; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('module_handler') + ); + } + + /** + * Handles private file transfers. + * + * Call modules that implement hook_file_download() to find out if a file is + * accessible and what headers it should be transferred with. If one or more + * modules returned headers the download will start with the returned headers. + * If a module returns -1 an AccessDeniedHttpException will be thrown. If the + * file exists but no modules responded an AccessDeniedHttpException will be + * thrown. If the file does not exist a NotFoundHttpException will be thrown. + * + * @see hook_file_download() + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The request object. + * @param string $scheme + * The file scheme, defaults to 'private'. + * + * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException + * Thrown when the requested file does not exist. + * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException + * Thrown when the user does not have access to the file. + * + * @return \Symfony\Component\HttpFoundation\BinaryFileResponse + * The transferred file as response. + */ + public function download(Request $request, $scheme = 'private') { + $target = $request->query->get('file'); + // Merge remaining path arguments into relative file path. + $uri = $scheme . '://' . $target; + + if (file_stream_wrapper_valid_scheme($scheme) && file_exists($uri)) { + // Let other modules provide headers and controls access to the file. + $headers = $this->moduleHandler->invokeAll('file_download', array($uri)); + + foreach ($headers as $result) { + if ($result == -1) { + throw new AccessDeniedHttpException(); + } + } + + if (count($headers)) { + return new BinaryFileResponse($uri, 200, $headers); + } + + throw new AccessDeniedHttpException(); + } + + throw new NotFoundHttpException(); + } + +} diff --git a/core/modules/system/lib/Drupal/system/PathProcessor/PathProcessorFiles.php b/core/modules/system/lib/Drupal/system/PathProcessor/PathProcessorFiles.php new file mode 100644 index 0000000..bce1f7f --- /dev/null +++ b/core/modules/system/lib/Drupal/system/PathProcessor/PathProcessorFiles.php @@ -0,0 +1,33 @@ +query->has('file')) { + $file_path = preg_replace('|^system\/files\/|', '', $path); + $request->query->set('file', $file_path); + return 'system/files'; + } + return $path; + } + +} diff --git a/core/modules/system/system.module b/core/modules/system/system.module index ac42ea3..6eb7712 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -609,13 +609,6 @@ function system_element_info() { * Implements hook_menu(). */ function system_menu() { - $items['system/files'] = array( - 'title' => 'File download', - 'page callback' => 'file_download', - 'page arguments' => array('private'), - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); $items['system/temporary'] = array( 'title' => 'Temporary files', 'page callback' => 'file_download', diff --git a/core/modules/system/system.routing.yml b/core/modules/system/system.routing.yml index 301ab6d..d828fc7 100644 --- a/core/modules/system/system.routing.yml +++ b/core/modules/system/system.routing.yml @@ -151,6 +151,14 @@ system_admin_index: requirements: _permission: 'access administration pages' +system_files: + pattern: '/system/files/{scheme}' + defaults: + _controller: 'Drupal\system\FileDownloadController::download' + scheme: private + requirements: + _access: 'TRUE' + system_theme_settings: pattern: '/admin/appearance/settings' defaults: diff --git a/core/modules/system/system.services.yml b/core/modules/system/system.services.yml index 6aefa00..d9f29f7 100644 --- a/core/modules/system/system.services.yml +++ b/core/modules/system/system.services.yml @@ -13,6 +13,10 @@ services: class: Drupal\system\LegacyBreadcrumbBuilder tags: - {name: breadcrumb_builder, priority: 500} + path_processor.files: + class: Drupal\system\PathProcessor\PathProcessorFiles + tags: + - { name: path_processor_inbound, priority: 200 } system.route_subscriber: class: Drupal\system\Routing\RouteSubscriber tags: -- 1.8.3.1