[TASK] Replace inject methods with @inject
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Mvc / Controller / MvcPropertyMappingConfigurationService.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Mvc\Controller;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2010-2013 Extbase Team (http://forge.typo3.org/projects/typo3v4-mvc)
8 * Extbase is a backport of TYPO3 Flow. All credits go to the TYPO3 Flow team.
9 * All rights reserved
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 * A copy is found in the textfile GPL.txt and important notices to the license
20 * from the author is found in LICENSE.txt distributed with these scripts.
21 *
22 *
23 * This script is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * This copyright notice MUST APPEAR in all copies of the script!
29 ***************************************************************/
30
31 /**
32 * This is a Service which can generate a request hash and check whether the currently given arguments
33 * fit to the request hash.
34 *
35 * It is used when forms are generated and submitted:
36 * After a form has been generated, the method "generateRequestHash" is called with the names of all form fields.
37 * It cleans up the array of form fields and creates another representation of it, which is then serialized and hashed.
38 *
39 * Both serialized form field list and the added hash form the request hash, which will be sent over the wire (as an argument __hmac).
40 *
41 * On the validation side, the validation happens in two steps:
42 * 1) Check if the request hash is consistent (the hash value fits to the serialized string)
43 * 2) Check that _all_ GET/POST parameters submitted occur inside the form field list of the request hash.
44 *
45 * Note: It is crucially important that a private key is computed into the hash value! This is done inside the HashService.
46 */
47 class MvcPropertyMappingConfigurationService implements \TYPO3\CMS\Core\SingletonInterface {
48
49 /**
50 * The hash service class to use
51 *
52 * @var \TYPO3\CMS\Extbase\Security\Cryptography\HashService
53 * @inject
54 */
55 protected $hashService;
56
57 /**
58 * Generate a request hash for a list of form fields
59 *
60 * @param array $formFieldNames Array of form fields
61 * @param string $fieldNamePrefix
62 *
63 * @return string trusted properties token
64 * @throws \TYPO3\CMS\EXTBASE\Security\Exception\InvalidArgumentForHashGenerationException
65 */
66 public function generateTrustedPropertiesToken($formFieldNames, $fieldNamePrefix = '') {
67 $formFieldArray = array();
68 foreach ($formFieldNames as $formField) {
69 $formFieldParts = explode('[', $formField);
70 $currentPosition = &$formFieldArray;
71 for ($i = 0; $i < count($formFieldParts); $i++) {
72 $formFieldPart = $formFieldParts[$i];
73 $formFieldPart = rtrim($formFieldPart, ']');
74 if (!is_array($currentPosition)) {
75 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);
76 }
77 if ($i === count($formFieldParts) - 1) {
78 if (isset($currentPosition[$formFieldPart]) && is_array($currentPosition[$formFieldPart])) {
79 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);
80 }
81 // Last iteration - add a string
82 if ($formFieldPart === '') {
83 $currentPosition[] = 1;
84 } else {
85 $currentPosition[$formFieldPart] = 1;
86 }
87 } else {
88 if ($formFieldPart === '') {
89 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);
90 }
91 if (!isset($currentPosition[$formFieldPart])) {
92 $currentPosition[$formFieldPart] = array();
93 }
94 $currentPosition = &$currentPosition[$formFieldPart];
95 }
96 }
97 }
98 if ($fieldNamePrefix !== '') {
99 $formFieldArray = (isset($formFieldArray[$fieldNamePrefix]) ? $formFieldArray[$fieldNamePrefix] : array());
100 }
101 return $this->serializeAndHashFormFieldArray($formFieldArray);
102 }
103
104 /**
105 * Serialize and hash the form field array
106 *
107 * @param array $formFieldArray form field array to be serialized and hashed
108 *
109 * @return string Hash
110 */
111 protected function serializeAndHashFormFieldArray(array $formFieldArray) {
112 $serializedFormFieldArray = serialize($formFieldArray);
113 return $this->hashService->appendHmac($serializedFormFieldArray);
114 }
115
116 /**
117 * Initialize the property mapping configuration in $controllerArguments if
118 * the trusted properties are set inside the request.
119 *
120 * @param \TYPO3\CMS\Extbase\Mvc\Request $request
121 * @param \TYPO3\CMS\Extbase\Mvc\Controller\Arguments $controllerArguments
122 *
123 * @return void
124 */
125 public function initializePropertyMappingConfigurationFromRequest(\TYPO3\CMS\Extbase\Mvc\Request $request, \TYPO3\CMS\Extbase\Mvc\Controller\Arguments $controllerArguments) {
126 $trustedPropertiesToken = $request->getInternalArgument('__trustedProperties');
127 if (!is_string($trustedPropertiesToken)) {
128 return;
129 }
130
131 $serializedTrustedProperties = $this->hashService->validateAndStripHmac($trustedPropertiesToken);
132 $trustedProperties = unserialize($serializedTrustedProperties);
133 foreach ($trustedProperties as $propertyName => $propertyConfiguration) {
134 if (!$controllerArguments->hasArgument($propertyName)) {
135 continue;
136 }
137 $propertyMappingConfiguration = $controllerArguments->getArgument($propertyName)->getPropertyMappingConfiguration();
138 $this->modifyPropertyMappingConfiguration($propertyConfiguration, $propertyMappingConfiguration);
139 }
140 }
141
142 /**
143 * Modify the passed $propertyMappingConfiguration according to the $propertyConfiguration which
144 * has been generated by Fluid. In detail, if the $propertyConfiguration contains
145 * an __identity field, we allow modification of objects; else we allow creation.
146 *
147 * All other properties are specified as allowed properties.
148 *
149 * @param array $propertyConfiguration
150 * @param \TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration $propertyMappingConfiguration
151 *
152 * @return void
153 */
154 protected function modifyPropertyMappingConfiguration($propertyConfiguration, \TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration $propertyMappingConfiguration) {
155 if (!is_array($propertyConfiguration)) {
156 return;
157 }
158
159 if (isset($propertyConfiguration['__identity'])) {
160 $propertyMappingConfiguration->setTypeConverterOption('TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter', \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED, TRUE);
161 unset($propertyConfiguration['__identity']);
162 } else {
163 $propertyMappingConfiguration->setTypeConverterOption('TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter', \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED, TRUE);
164 }
165
166 foreach ($propertyConfiguration as $innerKey => $innerValue) {
167 if (is_array($innerValue)) {
168 $this->modifyPropertyMappingConfiguration($innerValue, $propertyMappingConfiguration->forProperty($innerKey));
169 }
170 $propertyMappingConfiguration->allowProperties($innerKey);
171 }
172 }
173 }
174
175 ?>