Version 1
[yaffs-website] / web / core / modules / system / src / FileDownloadController.php
diff --git a/web/core/modules/system/src/FileDownloadController.php b/web/core/modules/system/src/FileDownloadController.php
new file mode 100644 (file)
index 0000000..08b1632
--- /dev/null
@@ -0,0 +1,70 @@
+<?php
+
+namespace Drupal\system;
+
+use Drupal\Core\Controller\ControllerBase;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+use Symfony\Component\HttpFoundation\BinaryFileResponse;
+
+/**
+ * System file controller.
+ */
+class FileDownloadController extends ControllerBase {
+
+  /**
+   * 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'.
+   *
+   * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
+   *   The transferred file as response.
+   *
+   * @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.
+   */
+  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', [$uri]);
+
+      foreach ($headers as $result) {
+        if ($result == -1) {
+          throw new AccessDeniedHttpException();
+        }
+      }
+
+      if (count($headers)) {
+        // \Drupal\Core\EventSubscriber\FinishResponseSubscriber::onRespond()
+        // sets response as not cacheable if the Cache-Control header is not
+        // already modified. We pass in FALSE for non-private schemes for the
+        // $public parameter to make sure we don't change the headers.
+        return new BinaryFileResponse($uri, 200, $headers, $scheme !== 'private');
+      }
+
+      throw new AccessDeniedHttpException();
+    }
+
+    throw new NotFoundHttpException();
+  }
+
+}