[SECURITY] Unsafe unserialize of GET parameter in Add-Wizard
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / Wizard / AddController.php
1 <?php
2 namespace TYPO3\CMS\Backend\Controller\Wizard;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 1999-2013 Kasper Skårhøj (kasperYYYY@typo3.com)
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29
30 use TYPO3\CMS\Backend\Utility\BackendUtility;
31 use TYPO3\CMS\Core\Utility\GeneralUtility;
32 use TYPO3\CMS\Core\Utility\HttpUtility;
33
34 /**
35 * Script Class for adding new items to a group/select field. Performs proper redirection as needed.
36 *
37 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
38 */
39 class AddController {
40
41 // Internal, dynamic:
42 // Content accumulation for the module.
43 /**
44 * @todo Define visibility
45 */
46 public $content;
47
48 // If set, the TCEmain class is loaded and used to add the returning ID to the parent record.
49 /**
50 * @todo Define visibility
51 */
52 public $processDataFlag = 0;
53
54 // Internal, static:
55 // Create new record -pid (pos/neg). If blank, return immediately
56 /**
57 * @todo Define visibility
58 */
59 public $pid;
60
61 // The parent table we are working on.
62 /**
63 * @todo Define visibility
64 */
65 public $table;
66
67 // Loaded with the created id of a record when TCEforms (alt_doc.php) returns ...
68 /**
69 * @todo Define visibility
70 */
71 public $id;
72
73 // Internal, static: GPvars
74 // Wizard parameters, coming from TCEforms linking to the wizard.
75 /**
76 * @todo Define visibility
77 */
78 public $P;
79
80 // Information coming back from alt_doc.php script, telling what the table/id was of the newly created record.
81 /**
82 * @todo Define visibility
83 */
84 public $returnEditConf;
85
86 /**
87 * Constructor
88 */
89 public function __construct() {
90 $GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_wizards.xlf');
91 $GLOBALS['SOBE'] = $this;
92
93 $this->init();
94 }
95
96 /**
97 * Initialization of the class.
98 *
99 * @return void
100 */
101 protected function init() {
102 // Init GPvars:
103 $this->P = GeneralUtility::_GP('P');
104 $this->returnEditConf = GeneralUtility::_GP('returnEditConf');
105 // Get this record
106 $origRow = BackendUtility::getRecord($this->P['table'], $this->P['uid']);
107 // Set table:
108 $this->table = $this->P['params']['table'];
109 // Get TSconfig for it.
110 $TSconfig = BackendUtility::getTCEFORM_TSconfig($this->P['table'], is_array($origRow) ? $origRow : array('pid' => $this->P['pid']));
111 // Set [params][pid]
112 if (substr($this->P['params']['pid'], 0, 3) == '###' && substr($this->P['params']['pid'], -3) == '###') {
113 $this->pid = intval($TSconfig['_' . substr($this->P['params']['pid'], 3, -3)]);
114 } else {
115 $this->pid = intval($this->P['params']['pid']);
116 }
117 // Return if new record as parent (not possibly/allowed)
118 if (!strcmp($this->pid, '')) {
119 HttpUtility::redirect(GeneralUtility::sanitizeLocalUrl($this->P['returnUrl']));
120 }
121 // Else proceed:
122 // If a new id has returned from a newly created record...
123 if ($this->returnEditConf) {
124 $eC = json_decode($this->returnEditConf, TRUE);
125 if (is_array($eC[$this->table]) && \TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($this->P['uid'])) {
126 // Getting id and cmd from returning editConf array.
127 reset($eC[$this->table]);
128 $this->id = intval(key($eC[$this->table]));
129 $cmd = current($eC[$this->table]);
130 // ... and if everything seems OK we will register some classes for inclusion and instruct the object to perform processing later.
131 if ($this->P['params']['setValue'] && $cmd == 'edit' && $this->id && $this->P['table'] && $this->P['field'] && $this->P['uid']) {
132 if ($LiveRec = BackendUtility::getLiveVersionOfRecord($this->table, $this->id, 'uid')) {
133 $this->id = $LiveRec['uid'];
134 }
135 $this->processDataFlag = 1;
136 }
137 }
138 }
139 }
140
141 /**
142 * Main function
143 * Will issue a location-header, redirecting either BACK or to a new alt_doc.php instance...
144 *
145 * @return void
146 */
147 public function main() {
148 if ($this->returnEditConf) {
149 if ($this->processDataFlag) {
150 // Preparing the data of the parent record...:
151 $trData = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\DataPreprocessor');
152 // 'new'
153 $trData->fetchRecord($this->P['table'], $this->P['uid'], '');
154 $current = reset($trData->regTableItems_data);
155 // If that record was found (should absolutely be...), then init TCEmain and set, prepend or append the record
156 if (is_array($current)) {
157 $tce = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\DataHandling\\DataHandler');
158 $tce->stripslashes_values = 0;
159 $data = array();
160 $addEl = $this->table . '_' . $this->id;
161 // Setting the new field data:
162 // If the field is a flexform field, work with the XML structure instead:
163 if ($this->P['flexFormPath']) {
164 // Current value of flexform path:
165 $currentFlexFormData = GeneralUtility::xml2array($current[$this->P['field']]);
166 $flexToolObj = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Configuration\\FlexForm\\FlexFormTools');
167 $curValueOfFlexform = $flexToolObj->getArrayValueByPath($this->P['flexFormPath'], $currentFlexFormData);
168 $insertValue = '';
169 switch ((string) $this->P['params']['setValue']) {
170 case 'set':
171 $insertValue = $addEl;
172 break;
173 case 'prepend':
174 $insertValue = $curValueOfFlexform . ',' . $addEl;
175 break;
176 case 'append':
177 $insertValue = $addEl . ',' . $curValueOfFlexform;
178 break;
179 }
180 $insertValue = implode(',', GeneralUtility::trimExplode(',', $insertValue, TRUE));
181 $data[$this->P['table']][$this->P['uid']][$this->P['field']] = array();
182 $flexToolObj->setArrayValueByPath($this->P['flexFormPath'], $data[$this->P['table']][$this->P['uid']][$this->P['field']], $insertValue);
183 } else {
184 switch ((string) $this->P['params']['setValue']) {
185 case 'set':
186 $data[$this->P['table']][$this->P['uid']][$this->P['field']] = $addEl;
187 break;
188 case 'prepend':
189 $data[$this->P['table']][$this->P['uid']][$this->P['field']] = $current[$this->P['field']] . ',' . $addEl;
190 break;
191 case 'append':
192 $data[$this->P['table']][$this->P['uid']][$this->P['field']] = $addEl . ',' . $current[$this->P['field']];
193 break;
194 }
195 $data[$this->P['table']][$this->P['uid']][$this->P['field']] = implode(',', GeneralUtility::trimExplode(',', $data[$this->P['table']][$this->P['uid']][$this->P['field']], TRUE));
196 }
197 // Submit the data:
198 $tce->start($data, array());
199 $tce->process_datamap();
200 }
201 }
202 // Return to the parent alt_doc.php record editing session:
203 HttpUtility::redirect(GeneralUtility::sanitizeLocalUrl($this->P['returnUrl']));
204 } else {
205 // Redirecting to alt_doc.php with instructions to create a new record
206 // AND when closing to return back with information about that records ID etc.
207 $redirectUrl = 'alt_doc.php?returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')) . '&returnEditConf=1&edit[' . $this->P['params']['table'] . '][' . $this->pid . ']=new';
208 HttpUtility::redirect($redirectUrl);
209 }
210 }
211
212 }