diff --git a/core/includes/file.inc b/core/includes/file.inc index e3ac8ea..47933db 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/lib/Drupal/Core/StreamWrapper/PrivateStream.php b/core/lib/Drupal/Core/StreamWrapper/PrivateStream.php index 833580f..921c223 100644 --- a/core/lib/Drupal/Core/StreamWrapper/PrivateStream.php +++ b/core/lib/Drupal/Core/StreamWrapper/PrivateStream.php @@ -30,6 +30,6 @@ public function getDirectoryPath() { */ function getExternalUrl() { $path = str_replace('\\', '/', $this->getTarget()); - return url('system/files/' . $path, array('absolute' => TRUE)); + return url('system/files', array('absolute' => TRUE, 'query' => array('file' => $path))); } } diff --git a/core/modules/file/lib/Drupal/file/Tests/DownloadTest.php b/core/modules/file/lib/Drupal/file/Tests/DownloadTest.php index 0763507..3febe1c 100644 --- a/core/modules/file/lib/Drupal/file/Tests/DownloadTest.php +++ b/core/modules/file/lib/Drupal/file/Tests/DownloadTest.php @@ -103,7 +103,7 @@ function testFileCreateUrl() { $script_path_original = $script_path; foreach (array('', 'index.php/') as $script_path) { $this->checkUrl('public', '', $basename, $base_url . '/' . file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath() . '/' . $basename_encoded); - $this->checkUrl('private', '', $basename, $base_url . '/' . $script_path . 'system/files/' . $basename_encoded); + $this->checkUrl('private', '', $basename, $base_url . '/' . $script_path . 'system/files?file=' . $basename_encoded); } $script_path = $script_path_original; } diff --git a/core/modules/system/lib/Drupal/system/FileController.php b/core/modules/system/lib/Drupal/system/FileController.php new file mode 100644 index 0000000..07e129f --- /dev/null +++ b/core/modules/system/lib/Drupal/system/FileController.php @@ -0,0 +1,77 @@ +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() + */ + public function fileDownload(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/system.module b/core/modules/system/system.module index 4d2f61e..7e8bc78 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -617,13 +617,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 b285844..25a2cd4 100644 --- a/core/modules/system/system.routing.yml +++ b/core/modules/system/system.routing.yml @@ -73,3 +73,11 @@ system_site_maintenance_mode: _form: 'Drupal\system\Form\SiteMaintenanceModeForm' requirements: _permission: 'administer site configuration' + +system_files: + pattern: '/system/files' + defaults: + _controller: 'Drupal\system\FileController::fileDownload' + scheme: private + requirements: + _access: 'TRUE'