‪TYPO3CMS  9.5
ShowImageController.php
Go to the documentation of this file.
1 <?php
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;
26 
43 {
44  protected const ‪ALLOWED_PARAMETER_NAMES = ['width', 'height', 'crop', 'bodyTag', 'title'];
45 
49  protected ‪$request;
50 
54  protected ‪$file;
55 
59  protected ‪$width;
60 
64  protected ‪$height;
65 
69  protected ‪$crop;
70 
74  protected ‪$frame;
75 
79  protected ‪$bodyTag = '<body>';
80 
84  protected ‪$title = 'Image';
85 
89  protected ‪$content = <<<EOF
90 <!DOCTYPE html>
91 <html>
92 <head>
93  <title>###TITLE###</title>
94  <meta name="robots" content="noindex,follow" />
95 </head>
96 ###BODY###
97  ###IMAGE###
98 </body>
99 </html>
100 EOF;
101 
105  protected ‪$imageTag = '<img src="###publicUrl###" alt="###alt###" title="###title###" width="###width###" height="###height###" />';
106 
113  public function ‪initialize()
114  {
115  $fileUid = $this->request->getQueryParams()['file'] ?? null;
116  $parametersArray = $this->request->getQueryParams()['parameters'] ?? null;
117 
118  // If no file-param or parameters are given, we must exit
119  if (!$fileUid || !isset($parametersArray) || !is_array($parametersArray)) {
120  throw new \InvalidArgumentException('No valid fileUid given', 1476048455);
121  }
122 
123  // rebuild the parameter array and check if the HMAC is correct
124  $parametersEncoded = implode('', $parametersArray);
125 
126  /* For backwards compatibility the HMAC is transported within the md5 param */
127  $hmacParameter = $this->request->getQueryParams()['md5'] ?? null;
128  $hmac = GeneralUtility::hmac(implode('|', [$fileUid, $parametersEncoded]));
129  if (!is_string($hmacParameter) || !hash_equals($hmac, $hmacParameter)) {
130  throw new \InvalidArgumentException('hash does not match', 1476048456);
131  }
132 
133  // decode the parameters Array - `bodyTag` contains HTML if set and would lead
134  // to a false-positive XSS-detection, that's why parameters are base64-encoded
135  $parameters = json_decode(base64_decode($parametersEncoded), true) ?? [];
136  foreach ($parameters as $parameterName => $parameterValue) {
137  if (in_array($parameterName, static::ALLOWED_PARAMETER_NAMES, true)) {
138  $this->{$parameterName} = $parameterValue;
139  }
140  }
141 
143  $this->file = ‪ResourceFactory::getInstance()->‪getFileObject((int)$fileUid);
144  } else {
146  }
147  if ($this->file !== null && !$this->‪isFileValid($this->file)) {
148  throw new ‪Exception('File processing for local storage is denied', 1594043425);
149  }
150 
151  $this->frame = $this->request->getQueryParams()['frame'] ?? null;
152  }
153 
158  public function ‪main()
159  {
160  $processedImage = $this->‪processImage();
161  $imageTagMarkers = [
162  '###publicUrl###' => htmlspecialchars($processedImage->getPublicUrl()),
163  '###alt###' => htmlspecialchars($this->file->getProperty('alternative') ?: $this->title),
164  '###title###' => htmlspecialchars($this->file->getProperty('title') ?: $this->title),
165  '###width###' => $processedImage->getProperty('width'),
166  '###height###' => $processedImage->getProperty('height')
167  ];
168  $this->imageTag = str_replace(array_keys($imageTagMarkers), array_values($imageTagMarkers), $this->imageTag);
169  $markerArray = [
170  '###TITLE###' => $this->file->getProperty('title') ?: ‪$this->title,
171  '###IMAGE###' => ‪$this->imageTag,
172  '###BODY###' => ‪$this->bodyTag
173  ];
174 
175  $this->content = str_replace(array_keys($markerArray), array_values($markerArray), $this->content);
176  }
177 
183  protected function ‪processImage()
184  {
185  if (strstr($this->width . $this->height, 'm')) {
186  $max = 'm';
187  } else {
188  $max = '';
189  }
190  $this->height = ‪MathUtility::forceIntegerInRange($this->height, 0);
191  $this->width = ‪MathUtility::forceIntegerInRange($this->width, 0) . $max;
192 
193  $processingConfiguration = [
194  'width' => ‪$this->width,
195  'height' => ‪$this->height,
196  'frame' => ‪$this->frame,
197  'crop' => ‪$this->crop,
198  ];
199  return $this->file->process(‪ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $processingConfiguration);
200  }
201 
208  public function ‪processRequest(ServerRequestInterface ‪$request): ResponseInterface
209  {
210  $this->request = ‪$request;
211 
212  try {
213  $this->‪initialize();
214  $this->‪main();
215  $response = new ‪Response();
216  $response->getBody()->write($this->content);
217  return $response;
218  } catch (\InvalidArgumentException $e) {
219  // add a 410 "gone" if invalid parameters given
220  return (new ‪Response)->withStatus(410);
221  } catch (‪Exception $e) {
222  return (new Response)->withStatus(404);
223  }
224  }
225 
226  protected function ‪isFileValid(FileInterface ‪$file): bool
227  {
228  return ‪$file->getStorage()->getDriverType() !== 'Local'
229  || GeneralUtility::verifyFilenameAgainstDenyPattern(basename(‪$file->getIdentifier()));
230  }
231 }
‪TYPO3\CMS\Frontend\Controller\ShowImageController\$file
‪TYPO3 CMS Core Resource File $file
Definition: ShowImageController.php:52
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:73
‪TYPO3\CMS\Frontend\Controller\ShowImageController\$bodyTag
‪string $bodyTag
Definition: ShowImageController.php:72
‪TYPO3\CMS\Core\Resource\FileInterface
Definition: FileInterface.php:21
‪TYPO3\CMS\Frontend\Controller\ShowImageController\$width
‪int $width
Definition: ShowImageController.php:56
‪TYPO3\CMS\Core\Exception
Definition: Exception.php:21
‪TYPO3\CMS\Frontend\Controller\ShowImageController\ALLOWED_PARAMETER_NAMES
‪const ALLOWED_PARAMETER_NAMES
Definition: ShowImageController.php:44
‪TYPO3\CMS\Core\Resource\ProcessedFile\CONTEXT_IMAGECROPSCALEMASK
‪const CONTEXT_IMAGECROPSCALEMASK
Definition: ProcessedFile.php:56
‪TYPO3\CMS\Core\Utility\MathUtility\forceIntegerInRange
‪static int forceIntegerInRange($theInt, $min, $max=2000000000, $defaultValue=0)
Definition: MathUtility.php:31
‪TYPO3\CMS\Core\Exception
‪TYPO3\CMS\Frontend\Controller\ShowImageController\processImage
‪TYPO3 CMS Core Resource ProcessedFile processImage()
Definition: ShowImageController.php:173
‪TYPO3\CMS\Frontend\Controller\ShowImageController\$frame
‪int $frame
Definition: ShowImageController.php:68
‪TYPO3\CMS\Core\Resource\ResourceFactory\getInstance
‪static ResourceFactory getInstance()
Definition: ResourceFactory.php:39
‪TYPO3\CMS\Frontend\Controller\ShowImageController\isFileValid
‪isFileValid(FileInterface $file)
Definition: ShowImageController.php:216
‪TYPO3\CMS\Frontend\Controller\ShowImageController\processRequest
‪ResponseInterface processRequest(ServerRequestInterface $request)
Definition: ShowImageController.php:198
‪TYPO3\CMS\Frontend\Controller\ShowImageController\initialize
‪initialize()
Definition: ShowImageController.php:103
‪TYPO3\CMS\Frontend\Controller\ShowImageController\$crop
‪string $crop
Definition: ShowImageController.php:64
‪TYPO3\CMS\Core\Http\Response
Definition: Response.php:28
‪TYPO3\CMS\Frontend\Controller\ShowImageController\$title
‪string $title
Definition: ShowImageController.php:76
‪TYPO3\CMS\Frontend\Controller\ShowImageController\$request
‪Psr Http Message ServerRequestInterface $request
Definition: ShowImageController.php:48
‪TYPO3\CMS\Frontend\Exception
Definition: Exception.php:23
‪TYPO3\CMS\Frontend\Controller\ShowImageController\$content
‪string $content
Definition: ShowImageController.php:80
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:33
‪TYPO3\CMS\Frontend\Controller\ShowImageController\main
‪main()
Definition: ShowImageController.php:148
‪TYPO3\CMS\Frontend\Controller\ShowImageController\$height
‪int $height
Definition: ShowImageController.php:60
‪TYPO3\CMS\Frontend\Controller\ShowImageController\$imageTag
‪string $imageTag
Definition: ShowImageController.php:95
‪TYPO3\CMS\Core\Resource\ProcessedFile
Definition: ProcessedFile.php:42
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:21
‪TYPO3\CMS\Core\Resource\ResourceFactory\getFileObject
‪File getFileObject($uid, array $fileData=[])
Definition: ResourceFactory.php:399
‪TYPO3\CMS\Frontend\Controller
Definition: ErrorController.php:3
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Core\Resource\ResourceFactory\retrieveFileOrFolderObject
‪File Folder null retrieveFileOrFolderObject($input)
Definition: ResourceFactory.php:491
‪TYPO3\CMS\Frontend\Controller\ShowImageController
Definition: ShowImageController.php:43