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