TYPO3 CMS  TYPO3_8-7
MvcPropertyMappingConfigurationService.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 
34 {
40  protected $hashService;
41 
45  public function injectHashService(\TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService)
46  {
47  $this->hashService = $hashService;
48  }
49 
59  public function generateTrustedPropertiesToken($formFieldNames, $fieldNamePrefix = '')
60  {
61  $formFieldArray = [];
62  foreach ($formFieldNames as $formField) {
63  $formFieldParts = explode('[', $formField);
64  $currentPosition = &$formFieldArray;
65  $formFieldPartsCount = count($formFieldParts);
66  for ($i = 0; $i < $formFieldPartsCount; $i++) {
67  $formFieldPart = $formFieldParts[$i];
68  $formFieldPart = rtrim($formFieldPart, ']');
69  if (!is_array($currentPosition)) {
70  throw new \TYPO3\CMS\Extbase\Security\Exception\InvalidArgumentForHashGenerationException('The form field "' . $formField . '" is declared as array, but it collides with a previous form field of the same name which declared the field as string. This is an inconsistency you need to fix inside your Fluid form. (String overridden by Array)', 1255072196);
71  }
72  if ($i === $formFieldPartsCount - 1) {
73  if (isset($currentPosition[$formFieldPart]) && is_array($currentPosition[$formFieldPart])) {
74  throw new \TYPO3\CMS\Extbase\Security\Exception\InvalidArgumentForHashGenerationException('The form field "' . $formField . '" is declared as string, but it collides with a previous form field of the same name which declared the field as array. This is an inconsistency you need to fix inside your Fluid form. (Array overridden by String)', 1255072587);
75  }
76  // Last iteration - add a string
77  if ($formFieldPart === '') {
78  $currentPosition[] = 1;
79  } else {
80  $currentPosition[$formFieldPart] = 1;
81  }
82  } else {
83  if ($formFieldPart === '') {
84  throw new \TYPO3\CMS\Extbase\Security\Exception\InvalidArgumentForHashGenerationException('The form field "' . $formField . '" is invalid. Reason: "[]" used not as last argument, but somewhere in the middle (like foo[][bar]).', 1255072832);
85  }
86  if (!isset($currentPosition[$formFieldPart])) {
87  $currentPosition[$formFieldPart] = [];
88  }
89  $currentPosition = &$currentPosition[$formFieldPart];
90  }
91  }
92  }
93  if ($fieldNamePrefix !== '') {
94  $formFieldArray = (isset($formFieldArray[$fieldNamePrefix]) ? $formFieldArray[$fieldNamePrefix] : []);
95  }
96  return $this->serializeAndHashFormFieldArray($formFieldArray);
97  }
98 
106  protected function serializeAndHashFormFieldArray(array $formFieldArray)
107  {
108  $serializedFormFieldArray = serialize($formFieldArray);
109  return $this->hashService->appendHmac($serializedFormFieldArray);
110  }
111 
119  public function initializePropertyMappingConfigurationFromRequest(\TYPO3\CMS\Extbase\Mvc\Request $request, \TYPO3\CMS\Extbase\Mvc\Controller\Arguments $controllerArguments)
120  {
121  $trustedPropertiesToken = $request->getInternalArgument('__trustedProperties');
122  if (!is_string($trustedPropertiesToken)) {
123  return;
124  }
125 
126  $serializedTrustedProperties = $this->hashService->validateAndStripHmac($trustedPropertiesToken);
127  $trustedProperties = unserialize($serializedTrustedProperties, ['allowed_classes' => false]);
128  foreach ($trustedProperties as $propertyName => $propertyConfiguration) {
129  if (!$controllerArguments->hasArgument($propertyName)) {
130  continue;
131  }
132  $propertyMappingConfiguration = $controllerArguments->getArgument($propertyName)->getPropertyMappingConfiguration();
133  $this->modifyPropertyMappingConfiguration($propertyConfiguration, $propertyMappingConfiguration);
134  }
135  }
136 
147  protected function modifyPropertyMappingConfiguration($propertyConfiguration, \TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration $propertyMappingConfiguration)
148  {
149  if (!is_array($propertyConfiguration)) {
150  return;
151  }
152 
153  if (isset($propertyConfiguration['__identity'])) {
154  $propertyMappingConfiguration->setTypeConverterOption(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::class, \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED, true);
155  unset($propertyConfiguration['__identity']);
156  } else {
157  $propertyMappingConfiguration->setTypeConverterOption(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::class, \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED, true);
158  }
159 
160  foreach ($propertyConfiguration as $innerKey => $innerValue) {
161  if (is_array($innerValue)) {
162  $this->modifyPropertyMappingConfiguration($innerValue, $propertyMappingConfiguration->forProperty($innerKey));
163  }
164  $propertyMappingConfiguration->allowProperties($innerKey);
165  }
166  }
167 }
modifyPropertyMappingConfiguration($propertyConfiguration, \TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration $propertyMappingConfiguration)
initializePropertyMappingConfigurationFromRequest(\TYPO3\CMS\Extbase\Mvc\Request $request, \TYPO3\CMS\Extbase\Mvc\Controller\Arguments $controllerArguments)
injectHashService(\TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService)