[TASK] Adapt FAL dumpFile to use PSR-7 response objects
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Controller / FileDumpController.php
1 <?php
2 namespace TYPO3\CMS\Core\Controller;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use Psr\Http\Message\ResponseInterface;
18 use Psr\Http\Message\ServerRequestInterface;
19 use TYPO3\CMS\Core\Http\Response;
20 use TYPO3\CMS\Core\Resource\Hook\FileDumpEIDHookInterface;
21 use TYPO3\CMS\Core\Resource\ProcessedFileRepository;
22 use TYPO3\CMS\Core\Resource\ResourceFactory;
23 use TYPO3\CMS\Core\Utility\GeneralUtility;
24
25 /**
26 * Class FileDumpController
27 */
28 class FileDumpController
29 {
30 /**
31 * Main method to dump a file
32 *
33 * @param ServerRequestInterface $request
34 * @return ResponseInterface|null
35 *
36 * @throws \InvalidArgumentException
37 * @throws \RuntimeException
38 * @throws \TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException
39 * @throws \UnexpectedValueException
40 */
41 public function dumpAction(ServerRequestInterface $request)
42 {
43 $parameters = ['eID' => 'dumpFile'];
44 $t = $this->getGetOrPost($request, 't');
45 if ($t) {
46 $parameters['t'] = $t;
47 }
48 $f = $this->getGetOrPost($request, 'f');
49 if ($f) {
50 $parameters['f'] = $f;
51 }
52 $p = $this->getGetOrPost($request, 'p');
53 if ($p) {
54 $parameters['p'] = $p;
55 }
56
57 if (hash_equals(GeneralUtility::hmac(implode('|', $parameters), 'resourceStorageDumpFile'), $this->getGetOrPost($request, 'token'))) {
58 if (isset($parameters['f'])) {
59 try {
60 $file = ResourceFactory::getInstance()->getFileObject($parameters['f']);
61 if ($file->isDeleted() || $file->isMissing()) {
62 $file = null;
63 }
64 } catch (\Exception $e) {
65 $file = null;
66 }
67 } else {
68 $file = GeneralUtility::makeInstance(ProcessedFileRepository::class)->findByUid($parameters['p']);
69 if (!$file || $file->isDeleted()) {
70 $file = null;
71 }
72 }
73
74 if ($file === null) {
75 return (new Response)->withStatus(404);
76 }
77
78 // Hook: allow some other process to do some security/access checks. Hook should return 403 response if access is rejected, void otherwise
79 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['FileDumpEID.php']['checkFileAccess'] ?? [] as $className) {
80 $hookObject = GeneralUtility::makeInstance($className);
81 if (!$hookObject instanceof FileDumpEIDHookInterface) {
82 throw new \UnexpectedValueException($className . ' must implement interface ' . FileDumpEIDHookInterface::class, 1394442417);
83 }
84 $response = $hookObject->checkFileAccess($file);
85 if ($response instanceof ResponseInterface) {
86 return $response;
87 }
88 }
89
90 return $file->getStorage()->streamFile($file);
91 }
92 return (new Response)->withStatus(403);
93 }
94
95 /**
96 * @param ServerRequestInterface $request
97 * @param string $parameter
98 * @return mixed|null
99 */
100 protected function getGetOrPost(ServerRequestInterface $request, $parameter)
101 {
102 return $request->getParsedBody()[$parameter] ?? $request->getQueryParams()[$parameter] ?? null;
103 }
104 }