[!!!][TASK] Drop TYPO3_CONF_VARS['SYS]['form_enctype']
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Service / SilentConfigurationUpgradeService.php
1 <?php
2 namespace TYPO3\CMS\Install\Service;
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 TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19 use TYPO3\CMS\Install\Controller\Exception\RedirectException;
20
21 /**
22 * Execute "silent" LocalConfiguration upgrades if needed.
23 *
24 * Some LocalConfiguration settings are obsolete or changed over time.
25 * This class handles upgrades of these settings. It is called by
26 * the step controller at an early point.
27 *
28 * Every change is encapsulated in one method an must throw a RedirectException
29 * if new data is written to LocalConfiguration. This is caught by above
30 * step controller to initiate a redirect and start again with adapted configuration.
31 */
32 class SilentConfigurationUpgradeService {
33
34 /**
35 * @var \TYPO3\CMS\Extbase\Object\ObjectManager
36 * @inject
37 */
38 protected $objectManager = NULL;
39
40 /**
41 * @var \TYPO3\CMS\Core\Configuration\ConfigurationManager
42 * @inject
43 */
44 protected $configurationManager = NULL;
45
46 /**
47 * List of obsolete configuration options in LocalConfiguration to be removed
48 * Example:
49 * // #forge-ticket
50 * 'BE/somesetting',
51 *
52 * @var array
53 */
54 protected $obsoleteLocalConfigurationSettings = array(
55 // #62402
56 'INSTALL/wizardDone/TYPO3\\CMS\\Install\\Updates\\ExtensionManagerTables',
57 'INSTALL/wizardDone/TYPO3\\CMS\\Install\\Updates\\FileIdentifierHashUpdate',
58 'INSTALL/wizardDone/TYPO3\\CMS\\Install\\Updates\\FilemountUpdateWizard',
59 'INSTALL/wizardDone/TYPO3\\CMS\\Install\\Updates\\FilePermissionUpdate',
60 'INSTALL/wizardDone/TYPO3\\CMS\\Install\\Updates\\FileTableSplittingUpdate',
61 'INSTALL/wizardDone/TYPO3\\CMS\\Install\\Updates\\InitUpdateWizard',
62 'INSTALL/wizardDone/TYPO3\\CMS\\Install\\Updates\\MediaFlexformUpdate',
63 'INSTALL/wizardDone/TYPO3\\CMS\\Install\\Updates\\ReferenceIntegrityUpdateWizard',
64 'INSTALL/wizardDone/TYPO3\\CMS\\Install\\Updates\\RteFileLinksUpdateWizard',
65 'INSTALL/wizardDone/TYPO3\\CMS\\Install\\Updates\\RteMagicImagesUpdateWizard',
66 'INSTALL/wizardDone/TYPO3\\CMS\\Install\\Updates\\TceformsUpdateWizard',
67 'INSTALL/wizardDone/TYPO3\\CMS\\Install\\Updates\\TtContentUploadsUpdateWizard',
68 'INSTALL/wizardDone/TYPO3\\CMS\\Install\\Updates\\TruncateSysFileProcessedFileTable',
69 // #63818
70 'BE/staticFileEditPath',
71 // #64226
72 'BE/accessListRenderMode',
73 // #66431
74 'BE/loginNewsTitle',
75 // #24900
76 'SYS/compat_version',
77 // #64643
78 'GFX/enable_typo3temp_db_tracking',
79 // #48542
80 'GFX/TTFdpi',
81 // #64872
82 'SYS/useCachingFramework',
83 // #65912
84 'FE/allowedTempPaths',
85 // #66034
86 'FE/activateContentAdapter',
87 // #66902
88 'SYS/loginCopyrightShowVersion',
89 // #66903
90 'BE/RTEenabled',
91 // #66906
92 'GFX/png_to_gif',
93 // #67411
94 'SYS/caching/cacheConfigurations/cache_classes',
95 // #68178
96 'SYS/form_enctype',
97 );
98
99 /**
100 * Executed configuration upgrades. Single upgrade methods must throw a
101 * RedirectException if something was written to LocalConfiguration.
102 *
103 * @return void
104 */
105 public function execute() {
106 $this->generateEncryptionKeyIfNeeded();
107 $this->configureBackendLoginSecurity();
108 $this->configureSaltedPasswords();
109 $this->setProxyAuthScheme();
110 $this->disableImageMagickAndGdlibIfImageProcessingIsDisabled();
111 $this->disableImageMagickDetailSettingsIfImageMagickIsDisabled();
112 $this->setImageMagickDetailSettings();
113 $this->removeObsoleteLocalConfigurationSettings();
114 }
115
116 /**
117 * Some settings in LocalConfiguration vanished in DefaultConfiguration
118 * and have no impact on the core anymore.
119 * To keep the configuration clean, those old settings are just silently
120 * removed from LocalConfiguration if set.
121 *
122 * @return void
123 */
124 protected function removeObsoleteLocalConfigurationSettings() {
125 $removed = $this->configurationManager->removeLocalConfigurationKeysByPath($this->obsoleteLocalConfigurationSettings);
126
127 // If something was changed: Trigger a reload to have new values in next request
128 if ($removed) {
129 $this->throwRedirectException();
130 }
131 }
132
133 /**
134 * Backend login security is set to rsa if rsaauth
135 * is installed (but not used) otherwise the default value "normal" has to be used.
136 * This forces either 'normal' or 'rsa' to be set in LocalConfiguration.
137 *
138 * @return void
139 */
140 protected function configureBackendLoginSecurity() {
141 $rsaauthLoaded = ExtensionManagementUtility::isLoaded('rsaauth');
142 try {
143 $currentLoginSecurityLevelValue = $this->configurationManager->getLocalConfigurationValueByPath('BE/loginSecurityLevel');
144 if ($rsaauthLoaded && $currentLoginSecurityLevelValue !== 'rsa') {
145 $this->configurationManager->setLocalConfigurationValueByPath('BE/loginSecurityLevel', 'rsa');
146 $this->throwRedirectException();
147 } elseif (!$rsaauthLoaded && $currentLoginSecurityLevelValue !== 'normal') {
148 $this->configurationManager->setLocalConfigurationValueByPath('BE/loginSecurityLevel', 'normal');
149 $this->throwRedirectException();
150 }
151 } catch (\RuntimeException $e) {
152 // If an exception is thrown, the value is not set in LocalConfiguration
153 $this->configurationManager->setLocalConfigurationValueByPath('BE/loginSecurityLevel', $rsaauthLoaded ? 'rsa' : 'normal');
154 $this->throwRedirectException();
155 }
156 }
157
158 /**
159 * Check the settings for salted passwords extension to load it as a required extension.
160 * Unset obsolete configuration options if given.
161 *
162 * @return void
163 */
164 protected function configureSaltedPasswords() {
165 $defaultConfiguration = $this->configurationManager->getDefaultConfiguration();
166 $defaultExtensionConfiguration = unserialize($defaultConfiguration['EXT']['extConf']['saltedpasswords']);
167 try {
168 $extensionConfiguration = @unserialize($this->configurationManager->getLocalConfigurationValueByPath('EXT/extConf/saltedpasswords'));
169 } catch (\RuntimeException $e) {
170 $extensionConfiguration = array();
171 }
172 if (is_array($extensionConfiguration) && !empty($extensionConfiguration)) {
173 if (isset($extensionConfiguration['BE.']['enabled'])) {
174 if ($extensionConfiguration['BE.']['enabled']) {
175 unset($extensionConfiguration['BE.']['enabled']);
176 } else {
177 $extensionConfiguration['BE.'] = $defaultExtensionConfiguration['BE.'];
178 }
179 $this->configurationManager->setLocalConfigurationValueByPath(
180 'EXT/extConf/saltedpasswords',
181 serialize($extensionConfiguration)
182 );
183 $this->throwRedirectException();
184 }
185 } else {
186 $this->configurationManager->setLocalConfigurationValueByPath(
187 'EXT/extConf/saltedpasswords',
188 serialize($defaultExtensionConfiguration)
189 );
190 $this->throwRedirectException();
191 }
192 }
193
194 /**
195 * The encryption key is crucial for securing form tokens
196 * and the whole TYPO3 link rendering later on. A random key is set here in
197 * LocalConfiguration if it does not exist yet. This might possible happen
198 * during upgrading and will happen during first install.
199 *
200 * @return void
201 */
202 protected function generateEncryptionKeyIfNeeded() {
203 try{
204 $currentValue = $this->configurationManager->getLocalConfigurationValueByPath('SYS/encryptionKey');
205 } catch (\RuntimeException $e) {
206 // If an exception is thrown, the value is not set in LocalConfiguration
207 $currentValue = '';
208 }
209
210 if (empty($currentValue)) {
211 $randomKey = GeneralUtility::getRandomHexString(96);
212 $this->configurationManager->setLocalConfigurationValueByPath('SYS/encryptionKey', $randomKey);
213 $this->throwRedirectException();
214 }
215 }
216
217 /**
218 * $GLOBALS['TYPO3_CONF_VARS']['HTTP']['proxy_auth_scheme'] must be either
219 * 'digest' or 'basic'. 'basic' is default in DefaultConfiguration, so the
220 * setting can be removed from LocalConfiguration if it is not set to 'digest'.
221 *
222 * @return void
223 */
224 protected function setProxyAuthScheme() {
225 // Get current value from LocalConfiguration
226 try {
227 $currentValueInLocalConfiguration = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/proxy_auth_scheme');
228 } catch (\RuntimeException $e) {
229 // If an exception is thrown, the value is not set in LocalConfiguration, so we don't need to do anything
230 return;
231 }
232 if ($currentValueInLocalConfiguration !== 'digest') {
233 $this->configurationManager->removeLocalConfigurationKeysByPath(array('HTTP/proxy_auth_scheme'));
234 $this->throwRedirectException();
235 }
236 }
237
238 /**
239 * GFX/im and GFX/gdlib must be set to 0 if image_processing is disabled.
240 *
241 * "Configuration presets" in install tool is not type safe, so value
242 * comparisons here are not type safe too, to not trigger changes to
243 * LocalConfiguration again.
244 *
245 * @return void
246 */
247 protected function disableImageMagickAndGdlibIfImageProcessingIsDisabled() {
248 $changedValues = array();
249 try {
250 $currentImageProcessingValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/image_processing');
251 } catch (\RuntimeException $e) {
252 $currentImageProcessingValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/image_processing');
253 }
254 try {
255 $currentImValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im');
256 } catch (\RuntimeException $e) {
257 $currentImValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/im');
258 }
259 try {
260 $currentGdlibValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/gdlib');
261 } catch (\RuntimeException $e) {
262 $currentGdlibValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/gdlib');
263 }
264 // If image processing is fully disabled, im and gdlib sub settings must be 0
265 if (!$currentImageProcessingValue) {
266 if ($currentImValue != 0) {
267 $changedValues['GFX/im'] = 0;
268 }
269 if ($currentGdlibValue != 0) {
270 $changedValues['GFX/gdlib'] = 0;
271 }
272 }
273 if (!empty($changedValues)) {
274 $this->configurationManager->setLocalConfigurationValuesByPathValuePairs($changedValues);
275 $this->throwRedirectException();
276 }
277 }
278
279 /**
280 * Detail configuration of Image Magick settings must be cleared
281 * if Image Magick handling is disabled.
282 *
283 * "Configuration presets" in install tool is not type safe, so value
284 * comparisons here are not type safe too, to not trigger changes to
285 * LocalConfiguration again.
286 *
287 * @return void
288 */
289 protected function disableImageMagickDetailSettingsIfImageMagickIsDisabled() {
290 $changedValues = array();
291 try {
292 $currentImValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im');
293 }
294 catch (\RuntimeException $e) {
295 $currentImValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/im');
296 }
297 try {
298 $currentImPathValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im_path');
299 }
300 catch (\RuntimeException $e) {
301 $currentImPathValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/im_path');
302 }
303 try {
304 $currentImPathLzwValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im_path_lzw');
305 }
306 catch (\RuntimeException $e) {
307 $currentImPathLzwValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/im_path_lzw');
308 }
309 try {
310 $currentImageFileExtValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/imagefile_ext');
311 }
312 catch (\RuntimeException $e) {
313 $currentImageFileExtValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/imagefile_ext');
314 }
315 try {
316 $currentThumbnailsValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/thumbnails');
317 }
318 catch (\RuntimeException $e) {
319 $currentThumbnailsValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/thumbnails');
320 }
321 if (!$currentImValue) {
322 if ($currentImPathValue != '') {
323 $changedValues['GFX/im_path'] = '';
324 }
325 if ($currentImPathLzwValue != '') {
326 $changedValues['GFX/im_path_lzw'] = '';
327 }
328 if ($currentImageFileExtValue !== 'gif,jpg,jpeg,png') {
329 $changedValues['GFX/imagefile_ext'] = 'gif,jpg,jpeg,png';
330 }
331 if ($currentThumbnailsValue != 0) {
332 $changedValues['GFX/thumbnails'] = 0;
333 }
334 }
335 if (!empty($changedValues)) {
336 $this->configurationManager->setLocalConfigurationValuesByPathValuePairs($changedValues);
337 $this->throwRedirectException();
338 }
339 }
340
341 /**
342 * Detail configuration of Image Magick and Graphics Magick settings
343 * depending on main values.
344 *
345 * "Configuration presets" in install tool is not type safe, so value
346 * comparisons here are not type safe too, to not trigger changes to
347 * LocalConfiguration again.
348 *
349 * @return void
350 */
351 protected function setImageMagickDetailSettings() {
352 $changedValues = array();
353 try {
354 $currentIm5Value = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im_version_5');
355 }
356 catch (\RuntimeException $e) {
357 $currentIm5Value = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/im_version_5');
358 }
359 try {
360 $currentImMaskValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im_mask_temp_ext_gif');
361 }
362 catch (\RuntimeException $e) {
363 $currentImMaskValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/im_mask_temp_ext_gif');
364 }
365 try {
366 $currentIm5EffectsValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im_v5effects');
367 }
368 catch (\RuntimeException $e) {
369 $currentIm5EffectsValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/im_v5effects');
370 }
371 if ((string)$currentIm5Value !== '') {
372 if ($currentImMaskValue != 1) {
373 $changedValues['GFX/im_mask_temp_ext_gif'] = 1;
374 }
375 if ($currentIm5Value === 'gm') {
376 if ($currentIm5EffectsValue != -1) {
377 $changedValues['GFX/im_v5effects'] = -1;
378 }
379 }
380 }
381 if (!empty($changedValues)) {
382 $this->configurationManager->setLocalConfigurationValuesByPathValuePairs($changedValues);
383 $this->throwRedirectException();
384 }
385 }
386
387 /**
388 * Throw exception after configuration change to trigger a redirect.
389 *
390 * @throws RedirectException
391 */
392 protected function throwRedirectException() {
393 throw new RedirectException(
394 'Configuration updated, reload needed',
395 1379024938
396 );
397 }
398
399 }