‪TYPO3CMS  ‪main
LinkVarsCalculator.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
24 
31 {
36  public function ‪getAllowedLinkVarsFromRequest(string $linkVarsSetting, array $queryParams, ‪Context $context): string
37  {
38  $calculatedLinkVars = '';
39  $adminCommand = $queryParams['ADMCMD_prev'] ?? '';
40  $isBackendUserLoggedIn = $context->‪getAspect('backend.user')->isLoggedIn();
41 
42  // This allows to keep the current logged-in workspace when navigating through the Frontend from a Backend link, and keep the logged-in state
43  if (($adminCommand === 'LIVE' || $adminCommand === 'IGNORE') && $isBackendUserLoggedIn) {
44  $linkVarsSetting = ltrim($linkVarsSetting . ',ADMCMD_prev', ',');
45  }
46  // This allows to keep the "ADMCMD_simUser" parameter when navigating through the Frontend from a Backend link, and keep the logged-in state
47  if (!empty($queryParams['ADMCMD_simUser']) && $isBackendUserLoggedIn) {
48  $linkVarsSetting = ltrim($linkVarsSetting . ',ADMCMD_simUser', ',');
49  }
50  // This allows to keep the "ADMCMD_simUser" parameter when navigating through the Frontend from a Backend link, and keep the logged-in state
51  if (!empty($queryParams['ADMCMD_simTime']) && $isBackendUserLoggedIn) {
52  $linkVarsSetting = ltrim($linkVarsSetting . ',ADMCMD_simTime', ',');
53  }
54 
55  if (empty($linkVarsSetting)) {
56  return '';
57  }
58 
59  $linkVars = $this->‪splitLinkVarsString($linkVarsSetting);
60  if (empty($linkVars)) {
61  return '';
62  }
63  foreach ($linkVars as $linkVar) {
64  $test = '';
65  if (preg_match('/^(.*)\\((.+)\\)$/', $linkVar, $match)) {
66  $linkVar = trim($match[1]);
67  $test = trim($match[2]);
68  }
69 
70  $keys = explode('|', $linkVar);
71  $numberOfLevels = count($keys);
72  $rootKey = trim($keys[0]);
73  if (!isset($queryParams[$rootKey])) {
74  continue;
75  }
76  $value = $queryParams[$rootKey];
77  for ($i = 1; $i < $numberOfLevels; $i++) {
78  $currentKey = trim($keys[$i]);
79  if (isset($value[$currentKey])) {
80  $value = $value[$currentKey];
81  } else {
82  $value = false;
83  break;
84  }
85  }
86  if ($value !== false) {
87  $parameterName = $keys[0];
88  for ($i = 1; $i < $numberOfLevels; $i++) {
89  $parameterName .= '[' . $keys[$i] . ']';
90  }
91  if (!is_array($value)) {
92  $temp = rawurlencode((string)$value);
93  if ($test !== '' && !$this->‪isAllowedLinkVarValue($temp, $test)) {
94  // Error: This value was not allowed for this key
95  continue;
96  }
97  $value = '&' . $parameterName . '=' . $temp;
98  } else {
99  if ($test !== '' && $test !== 'array') {
100  // Error: This key must not be an array!
101  continue;
102  }
103  $value = ‪HttpUtility::buildQueryString([$parameterName => $value], '&');
104  }
105  $calculatedLinkVars .= $value;
106  }
107  }
108  return $calculatedLinkVars;
109  }
110 
114  protected function ‪splitLinkVarsString(string $string): array
115  {
116  $tempCommaReplacementString = '###KASPER###';
117 
118  // replace every "," wrapped in "()" by a "unique" string
119  $string = preg_replace_callback('/\‍((?>[^()]|(?R))*\‍)/', static function ($result) use ($tempCommaReplacementString) {
120  return str_replace(',', $tempCommaReplacementString, $result[0]);
121  }, $string) ?? '';
122 
123  $string = ‪GeneralUtility::trimExplode(',', $string);
124 
125  // replace all "unique" strings back to ","
126  return str_replace($tempCommaReplacementString, ',', $string);
127  }
128 
137  protected function ‪isAllowedLinkVarValue(string $haystack, string $value): bool
138  {
139  $isAllowed = false;
140  // Integer
141  if ($value === 'int' || $value === 'integer') {
143  $isAllowed = true;
144  }
145  } elseif (preg_match('/^\\/.+\\/[imsxeADSUXu]*$/', $value)) {
146  // Regular expression, only "//" is allowed as delimiter
147  if (@preg_match($value, $haystack)) {
148  $isAllowed = true;
149  }
150  } elseif (str_contains($value, '-')) {
151  // Range
153  $range = explode('-', $value);
154  if ($range[0] <= $haystack && $range[1] >= $haystack) {
155  $isAllowed = true;
156  }
157  }
158  } elseif (str_contains($value, '|')) {
159  // List
160  // Trim the input
161  $haystack = str_replace(' ', '', $haystack);
162  if (str_contains('|' . $value . '|', '|' . $haystack . '|')) {
163  $isAllowed = true;
164  }
165  } elseif ($value === $haystack) {
166  // String comparison
167  $isAllowed = true;
168  }
169  return $isAllowed;
170  }
171 }
‪TYPO3\CMS\Core\Context\Context\getAspect
‪getAspect(string $name)
Definition: Context.php:76
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:54
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger(mixed $var)
Definition: MathUtility.php:69
‪TYPO3\CMS\Core\Utility\HttpUtility\buildQueryString
‪static string buildQueryString(array $parameters, string $prependCharacter='', bool $skipEmptyParameters=false)
Definition: HttpUtility.php:124
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:24
‪TYPO3\CMS\Core\Utility\HttpUtility
Definition: HttpUtility.php:24
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static list< string > trimExplode(string $delim, string $string, bool $removeEmptyValues=false, int $limit=0)
Definition: GeneralUtility.php:822