[TASK] Create own response instance in controller actions
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / Controller / ShowImageController.php
1 <?php
2 namespace TYPO3\CMS\Frontend\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\Exception;
20 use TYPO3\CMS\Core\Http\HtmlResponse;
21 use TYPO3\CMS\Core\Resource\ProcessedFile;
22 use TYPO3\CMS\Core\Resource\ResourceFactory;
23 use TYPO3\CMS\Core\Utility\GeneralUtility;
24 use TYPO3\CMS\Core\Utility\MathUtility;
25
26 /**
27 * eID-Script "tx_cms_showpic"
28 *
29 * Shows a picture from FAL in enlarged format in a separate window.
30 * Picture file and settings is supplied by GET-parameters:
31 *
32 * - file = fileUid or Combined Identifier
33 * - encoded in an parameter Array (with weird format - see ContentObjectRenderer about ll. 1500)
34 * - width, height = usual width an height, m/c supported
35 * - frame
36 * - bodyTag
37 * - title
38 */
39 class ShowImageController
40 {
41 /**
42 * @var \Psr\Http\Message\ServerRequestInterface
43 */
44 protected $request;
45
46 /**
47 * @var \TYPO3\CMS\Core\Resource\File
48 */
49 protected $file;
50
51 /**
52 * @var int
53 */
54 protected $width;
55
56 /**
57 * @var int
58 */
59 protected $height;
60
61 /**
62 * @var string
63 */
64 protected $crop;
65
66 /**
67 * @var int
68 */
69 protected $frame;
70
71 /**
72 * @var string
73 */
74 protected $bodyTag = '<body>';
75
76 /**
77 * @var string
78 */
79 protected $title = 'Image';
80
81 /**
82 * @var string
83 */
84 protected $content = <<<EOF
85 <!DOCTYPE html>
86 <html>
87 <head>
88 <title>###TITLE###</title>
89 <meta name="robots" content="noindex,follow" />
90 </head>
91 ###BODY###
92 ###IMAGE###
93 </body>
94 </html>
95 EOF;
96
97 /**
98 * @var string
99 */
100 protected $imageTag = '<img src="###publicUrl###" alt="###alt###" title="###title###" width="###width###" height="###height###" />';
101
102 /**
103 * Init function, setting the input vars in the global space.
104 *
105 * @throws \InvalidArgumentException
106 * @throws \TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException
107 */
108 public function initialize()
109 {
110 $fileUid = $this->request->getQueryParams()['file'] ?? null;
111 $parametersArray = $this->request->getQueryParams()['parameters'] ?? null;
112
113 // If no file-param or parameters are given, we must exit
114 if (!$fileUid || !isset($parametersArray) || !is_array($parametersArray)) {
115 throw new \InvalidArgumentException('No valid fileUid given', 1476048455);
116 }
117
118 // rebuild the parameter array and check if the HMAC is correct
119 $parametersEncoded = implode('', $parametersArray);
120
121 /* For backwards compatibility the HMAC is transported within the md5 param */
122 $hmacParameter = $this->request->getQueryParams()['md5'] ?? null;
123 $hmac = GeneralUtility::hmac(implode('|', [$fileUid, $parametersEncoded]));
124 if (!hash_equals($hmac, $hmacParameter)) {
125 throw new \InvalidArgumentException('hash does not match', 1476048456);
126 }
127
128 // decode the parameters Array
129 $parameters = unserialize(base64_decode($parametersEncoded));
130 foreach ($parameters as $parameterName => $parameterValue) {
131 $this->{$parameterName} = $parameterValue;
132 }
133
134 if (MathUtility::canBeInterpretedAsInteger($fileUid)) {
135 $this->file = ResourceFactory::getInstance()->getFileObject((int)$fileUid);
136 } else {
137 $this->file = ResourceFactory::getInstance()->retrieveFileOrFolderObject($fileUid);
138 }
139 $this->frame = $this->request->getQueryParams()['frame'] ?? null;
140 }
141
142 /**
143 * Main function which creates the image if needed and outputs the HTML code for the page displaying the image.
144 * Accumulates the content in $this->content
145 */
146 public function main()
147 {
148 $processedImage = $this->processImage();
149 $imageTagMarkers = [
150 '###publicUrl###' => htmlspecialchars($processedImage->getPublicUrl()),
151 '###alt###' => htmlspecialchars($this->file->getProperty('alternative') ?: $this->title),
152 '###title###' => htmlspecialchars($this->file->getProperty('title') ?: $this->title),
153 '###width###' => $processedImage->getProperty('width'),
154 '###height###' => $processedImage->getProperty('height')
155 ];
156 $this->imageTag = str_replace(array_keys($imageTagMarkers), array_values($imageTagMarkers), $this->imageTag);
157 $markerArray = [
158 '###TITLE###' => ($this->file->getProperty('title') ?: $this->title),
159 '###IMAGE###' => $this->imageTag,
160 '###BODY###' => $this->bodyTag
161 ];
162
163 $this->content = str_replace(array_keys($markerArray), array_values($markerArray), $this->content);
164 }
165
166 /**
167 * Does the actual image processing
168 *
169 * @return \TYPO3\CMS\Core\Resource\ProcessedFile
170 */
171 protected function processImage()
172 {
173 if (strstr($this->width . $this->height, 'm')) {
174 $max = 'm';
175 } else {
176 $max = '';
177 }
178 $this->height = MathUtility::forceIntegerInRange($this->height, 0);
179 $this->width = MathUtility::forceIntegerInRange($this->width, 0) . $max;
180
181 $processingConfiguration = [
182 'width' => $this->width,
183 'height' => $this->height,
184 'frame' => $this->frame,
185 'crop' => $this->crop,
186 ];
187 return $this->file->process(ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $processingConfiguration);
188 }
189
190 /**
191 * Fetches the content and builds a content file out of it
192 *
193 * @param ServerRequestInterface $request the current request object
194 * @return ResponseInterface the modified response
195 */
196 public function processRequest(ServerRequestInterface $request): ResponseInterface
197 {
198 $this->request = $request;
199
200 try {
201 $this->initialize();
202 $this->main();
203 return new HtmlResponse($this->content);
204 } catch (\InvalidArgumentException $e) {
205 // add a 410 "gone" if invalid parameters given
206 return new HtmlResponse('', 410);
207 } catch (Exception $e) {
208 return new HtmlResponse('', 404);
209 }
210 }
211 }