e64e42ba9c60b30dba30b409d1f94937974a73db
[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\Resource\Hook\FileDumpEIDHookInterface;
20 use TYPO3\CMS\Core\Resource\ProcessedFileRepository;
21 use TYPO3\CMS\Core\Resource\ResourceFactory;
22 use TYPO3\CMS\Core\Utility\GeneralUtility;
23 use TYPO3\CMS\Core\Utility\HttpUtility;
24
25 /**
26 * Class FileDumpController
27 */
28 class FileDumpController
29 {
30 /**
31 * Main method to dump a file
32 *
33 * @param ServerRequestInterface $request
34 * @param ResponseInterface $response
35 * @return NULL|ResponseInterface
36 *
37 * @throws \InvalidArgumentException
38 * @throws \RuntimeException
39 * @throws \TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException
40 * @throws \UnexpectedValueException
41 */
42 public function dumpAction(ServerRequestInterface $request, ResponseInterface $response)
43 {
44 $parameters = ['eID' => 'dumpFile'];
45 $t = $this->getGetOrPost($request, 't');
46 if ($t) {
47 $parameters['t'] = $t;
48 }
49 $f = $this->getGetOrPost($request, 'f');
50 if ($f) {
51 $parameters['f'] = $f;
52 }
53 $p = $this->getGetOrPost($request, 'p');
54 if ($p) {
55 $parameters['p'] = $p;
56 }
57
58 if (GeneralUtility::hmac(implode('|', $parameters), 'resourceStorageDumpFile') === $this->getGetOrPost($request, 'token')) {
59 if (isset($parameters['f'])) {
60 try {
61 $file = ResourceFactory::getInstance()->getFileObject($parameters['f']);
62 if ($file->isDeleted() || $file->isMissing()) {
63 $file = null;
64 }
65 } catch (\Exception $e) {
66 $file = null;
67 }
68 } else {
69 $file = GeneralUtility::makeInstance(ProcessedFileRepository::class)->findByUid($parameters['p']);
70 if (!$file || $file->isDeleted()) {
71 $file = null;
72 }
73 }
74
75 if ($file === null) {
76 HttpUtility::setResponseCodeAndExit(HttpUtility::HTTP_STATUS_404);
77 }
78
79 // Hook: allow some other process to do some security/access checks. Hook should issue 403 if access is rejected
80 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['FileDumpEID.php']['checkFileAccess'])) {
81 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['FileDumpEID.php']['checkFileAccess'] as $className) {
82 $hookObject = GeneralUtility::makeInstance($className);
83 if (!$hookObject instanceof FileDumpEIDHookInterface) {
84 throw new \UnexpectedValueException($className . ' must implement interface ' . FileDumpEIDHookInterface::class, 1394442417);
85 }
86 $hookObject->checkFileAccess($file);
87 }
88 }
89 $file->getStorage()->dumpFileContents($file);
90 // @todo Refactor FAL to not echo directly, but to implement a stream for output here and use response
91 return null;
92 }
93 return $response->withStatus(403);
94 }
95
96 /**
97 * @param ServerRequestInterface $request
98 * @param string $parameter
99 * @return NULL|mixed
100 */
101 protected function getGetOrPost(ServerRequestInterface $request, $parameter)
102 {
103 return isset($request->getParsedBody()[$parameter])
104 ? $request->getParsedBody()[$parameter]
105 : (isset($request->getQueryParams()[$parameter]) ? $request->getQueryParams()[$parameter] : null);
106 }
107 }