[!!!][TASK] Remove BE/fileExtensions/webspace
[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\Configuration\ConfigurationManager;
18 use TYPO3\CMS\Core\Crypto\Random;
19 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21 use TYPO3\CMS\Install\Service\Exception\ConfigurationChangedException;
22
23 /**
24 * Execute "silent" LocalConfiguration upgrades if needed.
25 *
26 * Some LocalConfiguration settings are obsolete or changed over time.
27 * This class handles upgrades of these settings. It is called by
28 * the step controller at an early point.
29 *
30 * Every change is encapsulated in one method an must throw a ConfigurationChangedException
31 * if new data is written to LocalConfiguration. This is caught by above
32 * step controller to initiate a redirect and start again with adapted configuration.
33 */
34 class SilentConfigurationUpgradeService
35 {
36 /**
37 * @var \TYPO3\CMS\Core\Configuration\ConfigurationManager
38 */
39 protected $configurationManager;
40
41 /**
42 * List of obsolete configuration options in LocalConfiguration to be removed
43 * Example:
44 * // #forge-ticket
45 * 'BE/somesetting',
46 *
47 * @var array
48 */
49 protected $obsoleteLocalConfigurationSettings = [
50 // #72400
51 'BE/spriteIconGenerator_handler',
52 // #72417
53 'SYS/lockingMode',
54 // #72473
55 'FE/secureFormmail',
56 'FE/strictFormmail',
57 'FE/formmailMaxAttachmentSize',
58 // #72337
59 'SYS/t3lib_cs_utils',
60 'SYS/t3lib_cs_convMethod',
61 // #72604
62 'SYS/maxFileNameLength',
63 // #72602
64 'BE/unzip_path',
65 // #72615
66 'BE/notificationPrefix',
67 // #72616
68 'BE/XCLASS',
69 'FE/XCLASS',
70 // #43085
71 'GFX/image_processing',
72 // #70056
73 'SYS/curlUse',
74 'SYS/curlProxyNTLM',
75 'SYS/curlProxyServer',
76 'SYS/curlProxyTunnel',
77 'SYS/curlProxyUserPass',
78 'SYS/curlTimeout',
79 // #75355
80 'BE/niceFlexFormXMLtags',
81 'BE/compactFlexFormXML',
82 // #75625
83 'SYS/clearCacheSystem',
84 // #77411
85 'SYS/caching/cacheConfigurations/extbase_typo3dbbackend_tablecolumns',
86 // #77460
87 'SYS/caching/cacheConfigurations/extbase_typo3dbbackend_queries',
88 // #79513
89 'FE/lockHashKeyWords',
90 'BE/lockHashKeyWords',
91 // #78835
92 'SYS/cookieHttpOnly',
93 // #71095
94 'BE/lang',
95 // #80050
96 'FE/cHashIncludePageId',
97 // #80711
98 'FE/noPHPscriptInclude',
99 'FE/maxSessionDataSize',
100 // #82162
101 'SYS/enable_errorDLOG',
102 'SYS/enable_exceptionDLOG',
103 // #82377
104 'EXT/allowSystemInstall',
105 // #82421
106 'SYS/sqlDebug',
107 'SYS/no_pconnect',
108 'SYS/setDBinit',
109 'SYS/dbClientCompress',
110 // #82430
111 'SYS/syslogErrorReporting',
112 // #82639
113 'SYS/enable_DLOG',
114 'SC_OPTIONS/t3lib/class.t3lib_userauth.php/writeDevLog',
115 'SC_OPTIONS/t3lib/class.t3lib_userauth.php/writeDevLogBE',
116 'SC_OPTIONS/t3lib/class.t3lib_userauth.php/writeDevLogFE',
117 // #82438
118 'SYS/enableDeprecationLog',
119 // #82680
120 'GFX/png_truecolor',
121 // #82803
122 'FE/content_doktypes',
123 // #83081
124 'BE/fileExtensions'
125 ];
126
127 public function __construct(ConfigurationManager $configurationManager = null)
128 {
129 $this->configurationManager = $configurationManager ?: GeneralUtility::makeInstance(ConfigurationManager::class);
130 }
131
132 /**
133 * Executed configuration upgrades. Single upgrade methods must throw a
134 * ConfigurationChangedException if something was written to LocalConfiguration.
135 */
136 public function execute()
137 {
138 $this->generateEncryptionKeyIfNeeded();
139 $this->configureBackendLoginSecurity();
140 $this->migrateImageProcessorSetting();
141 $this->transferHttpSettings();
142 $this->disableImageMagickDetailSettingsIfImageMagickIsDisabled();
143 $this->setImageMagickDetailSettings();
144 $this->migrateThumbnailsPngSetting();
145 $this->migrateLockSslSetting();
146 $this->migrateDatabaseConnectionSettings();
147 $this->migrateDatabaseConnectionCharset();
148 $this->migrateDatabaseDriverOptions();
149 $this->migrateLangDebug();
150 $this->migrateCacheHashOptions();
151 $this->migrateExceptionErrors();
152
153 // Should run at the end to prevent that obsolete settings are removed before migration
154 $this->removeObsoleteLocalConfigurationSettings();
155 }
156
157 /**
158 * Some settings in LocalConfiguration vanished in DefaultConfiguration
159 * and have no impact on the core anymore.
160 * To keep the configuration clean, those old settings are just silently
161 * removed from LocalConfiguration if set.
162 */
163 protected function removeObsoleteLocalConfigurationSettings()
164 {
165 $removed = $this->configurationManager->removeLocalConfigurationKeysByPath($this->obsoleteLocalConfigurationSettings);
166
167 // If something was changed: Trigger a reload to have new values in next request
168 if ($removed) {
169 $this->throwConfigurationChangedException();
170 }
171 }
172
173 /**
174 * Backend login security is set to rsa if rsaauth
175 * is installed (but not used) otherwise the default value "normal" has to be used.
176 * This forces either 'normal' or 'rsa' to be set in LocalConfiguration.
177 */
178 protected function configureBackendLoginSecurity()
179 {
180 $rsaauthLoaded = ExtensionManagementUtility::isLoaded('rsaauth');
181 try {
182 $currentLoginSecurityLevelValue = $this->configurationManager->getLocalConfigurationValueByPath('BE/loginSecurityLevel');
183 if ($rsaauthLoaded && $currentLoginSecurityLevelValue !== 'rsa') {
184 $this->configurationManager->setLocalConfigurationValueByPath('BE/loginSecurityLevel', 'rsa');
185 $this->throwConfigurationChangedException();
186 } elseif (!$rsaauthLoaded && $currentLoginSecurityLevelValue !== 'normal') {
187 $this->configurationManager->setLocalConfigurationValueByPath('BE/loginSecurityLevel', 'normal');
188 $this->throwConfigurationChangedException();
189 }
190 } catch (\RuntimeException $e) {
191 // If an exception is thrown, the value is not set in LocalConfiguration
192 $this->configurationManager->setLocalConfigurationValueByPath(
193 'BE/loginSecurityLevel',
194 $rsaauthLoaded ? 'rsa' : 'normal'
195 );
196 $this->throwConfigurationChangedException();
197 }
198 }
199
200 /**
201 * The encryption key is crucial for securing form tokens
202 * and the whole TYPO3 link rendering later on. A random key is set here in
203 * LocalConfiguration if it does not exist yet. This might possible happen
204 * during upgrading and will happen during first install.
205 */
206 protected function generateEncryptionKeyIfNeeded()
207 {
208 try {
209 $currentValue = $this->configurationManager->getLocalConfigurationValueByPath('SYS/encryptionKey');
210 } catch (\RuntimeException $e) {
211 // If an exception is thrown, the value is not set in LocalConfiguration
212 $currentValue = '';
213 }
214
215 if (empty($currentValue)) {
216 $randomKey = GeneralUtility::makeInstance(Random::class)->generateRandomHexString(96);
217 $this->configurationManager->setLocalConfigurationValueByPath('SYS/encryptionKey', $randomKey);
218 $this->throwConfigurationChangedException();
219 }
220 }
221
222 /**
223 * Parse old curl and HTTP options and set new HTTP options, related to Guzzle
224 */
225 protected function transferHttpSettings()
226 {
227 $changed = false;
228 $newParameters = [];
229 $obsoleteParameters = [];
230
231 // Remove / migrate options to new options
232 try {
233 // Check if the adapter option is set, if so, set it to the parameters that are obsolete
234 $this->configurationManager->getLocalConfigurationValueByPath('HTTP/adapter');
235 $obsoleteParameters[] = 'HTTP/adapter';
236 } catch (\RuntimeException $e) {
237 }
238 try {
239 $newParameters['HTTP/version'] = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/protocol_version');
240 $obsoleteParameters[] = 'HTTP/protocol_version';
241 } catch (\RuntimeException $e) {
242 }
243 try {
244 $this->configurationManager->getLocalConfigurationValueByPath('HTTP/ssl_verify_host');
245 $obsoleteParameters[] = 'HTTP/ssl_verify_host';
246 } catch (\RuntimeException $e) {
247 }
248 try {
249 $legacyUserAgent = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/userAgent');
250 $newParameters['HTTP/headers/User-Agent'] = $legacyUserAgent;
251 $obsoleteParameters[] = 'HTTP/userAgent';
252 } catch (\RuntimeException $e) {
253 }
254
255 // Redirects
256 try {
257 $legacyFollowRedirects = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/follow_redirects');
258 $obsoleteParameters[] = 'HTTP/follow_redirects';
259 } catch (\RuntimeException $e) {
260 $legacyFollowRedirects = '';
261 }
262 try {
263 $legacyMaximumRedirects = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/max_redirects');
264 $obsoleteParameters[] = 'HTTP/max_redirects';
265 } catch (\RuntimeException $e) {
266 $legacyMaximumRedirects = '';
267 }
268 try {
269 $legacyStrictRedirects = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/strict_redirects');
270 $obsoleteParameters[] = 'HTTP/strict_redirects';
271 } catch (\RuntimeException $e) {
272 $legacyStrictRedirects = '';
273 }
274
275 // Check if redirects have been disabled
276 if ($legacyFollowRedirects !== '' && (bool)$legacyFollowRedirects === false) {
277 $newParameters['HTTP/allow_redirects'] = false;
278 } elseif ($legacyMaximumRedirects !== '' || $legacyStrictRedirects !== '') {
279 $newParameters['HTTP/allow_redirects'] = [];
280 if ($legacyMaximumRedirects !== '' && (int)$legacyMaximumRedirects !== 5) {
281 $newParameters['HTTP/allow_redirects']['max'] = (int)$legacyMaximumRedirects;
282 }
283 if ($legacyStrictRedirects !== '' && (bool)$legacyStrictRedirects === true) {
284 $newParameters['HTTP/allow_redirects']['strict'] = true;
285 }
286 // defaults are used, no need to set the option in LocalConfiguration.php
287 if (empty($newParameters['HTTP/allow_redirects'])) {
288 unset($newParameters['HTTP/allow_redirects']);
289 }
290 }
291
292 // Migrate Proxy settings
293 try {
294 // Currently without protocol or port
295 $legacyProxyHost = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/proxy_host');
296 $obsoleteParameters[] = 'HTTP/proxy_host';
297 } catch (\RuntimeException $e) {
298 $legacyProxyHost = '';
299 }
300 try {
301 $legacyProxyPort = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/proxy_port');
302 $obsoleteParameters[] = 'HTTP/proxy_port';
303 } catch (\RuntimeException $e) {
304 $legacyProxyPort = '';
305 }
306 try {
307 $legacyProxyUser = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/proxy_user');
308 $obsoleteParameters[] = 'HTTP/proxy_user';
309 } catch (\RuntimeException $e) {
310 $legacyProxyUser = '';
311 }
312 try {
313 $legacyProxyPassword = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/proxy_password');
314 $obsoleteParameters[] = 'HTTP/proxy_password';
315 } catch (\RuntimeException $e) {
316 $legacyProxyPassword = '';
317 }
318 // Auth Scheme: Basic, digest etc.
319 try {
320 $legacyProxyAuthScheme = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/proxy_auth_scheme');
321 $obsoleteParameters[] = 'HTTP/proxy_auth_scheme';
322 } catch (\RuntimeException $e) {
323 $legacyProxyAuthScheme = '';
324 }
325
326 if ($legacyProxyHost !== '') {
327 $proxy = 'http://';
328 if ($legacyProxyAuthScheme !== '' && $legacyProxyUser !== '' && $legacyProxyPassword !== '') {
329 $proxy .= $legacyProxyUser . ':' . $legacyProxyPassword . '@';
330 }
331 $proxy .= $legacyProxyHost;
332 if ($legacyProxyPort !== '') {
333 $proxy .= ':' . $legacyProxyPort;
334 }
335 $newParameters['HTTP/proxy'] = $proxy;
336 }
337
338 // Verify peers
339 // see http://docs.guzzlephp.org/en/latest/request-options.html#verify
340 try {
341 $legacySslVerifyPeer = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/ssl_verify_peer');
342 $obsoleteParameters[] = 'HTTP/ssl_verify_peer';
343 } catch (\RuntimeException $e) {
344 $legacySslVerifyPeer = '';
345 }
346
347 // Directory holding multiple Certificate Authority files
348 try {
349 $legacySslCaPath = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/ssl_capath');
350 $obsoleteParameters[] = 'HTTP/ssl_capath';
351 } catch (\RuntimeException $e) {
352 $legacySslCaPath = '';
353 }
354 // Certificate Authority file to verify the peer with (use when ssl_verify_peer is TRUE)
355 try {
356 $legacySslCaFile = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/ssl_cafile');
357 $obsoleteParameters[] = 'HTTP/ssl_cafile';
358 } catch (\RuntimeException $e) {
359 $legacySslCaFile = '';
360 }
361 if ($legacySslVerifyPeer !== '') {
362 if ($legacySslCaFile !== '' && $legacySslCaPath !== '') {
363 $newParameters['HTTP/verify'] = $legacySslCaPath . $legacySslCaFile;
364 } elseif ((bool)$legacySslVerifyPeer === false) {
365 $newParameters['HTTP/verify'] = false;
366 }
367 }
368
369 // SSL Key + Passphrase
370 // Name of a file containing local certificate
371 try {
372 $legacySslLocalCert = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/ssl_local_cert');
373 $obsoleteParameters[] = 'HTTP/ssl_local_cert';
374 } catch (\RuntimeException $e) {
375 $legacySslLocalCert = '';
376 }
377
378 // Passphrase with which local certificate was encoded
379 try {
380 $legacySslPassphrase = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/ssl_passphrase');
381 $obsoleteParameters[] = 'HTTP/ssl_passphrase';
382 } catch (\RuntimeException $e) {
383 $legacySslPassphrase = '';
384 }
385
386 if ($legacySslLocalCert !== '') {
387 if ($legacySslPassphrase !== '') {
388 $newParameters['HTTP/ssl_key'] = [
389 $legacySslLocalCert,
390 $legacySslPassphrase
391 ];
392 } else {
393 $newParameters['HTTP/ssl_key'] = $legacySslLocalCert;
394 }
395 }
396
397 // Update the LocalConfiguration file if obsolete parameters or new parameters are set
398 if (!empty($obsoleteParameters)) {
399 $this->configurationManager->removeLocalConfigurationKeysByPath($obsoleteParameters);
400 $changed = true;
401 }
402 if (!empty($newParameters)) {
403 $this->configurationManager->setLocalConfigurationValuesByPathValuePairs($newParameters);
404 $changed = true;
405 }
406 if ($changed) {
407 $this->throwConfigurationChangedException();
408 }
409 }
410
411 /**
412 * Detail configuration of Image Magick settings must be cleared
413 * if Image Magick handling is disabled.
414 *
415 * "Configuration presets" in install tool is not type safe, so value
416 * comparisons here are not type safe too, to not trigger changes to
417 * LocalConfiguration again.
418 */
419 protected function disableImageMagickDetailSettingsIfImageMagickIsDisabled()
420 {
421 $changedValues = [];
422 try {
423 $currentImValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/processor_enabled');
424 } catch (\RuntimeException $e) {
425 $currentImValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/processor_enabled');
426 }
427
428 try {
429 $currentImPathValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/processor_path');
430 } catch (\RuntimeException $e) {
431 $currentImPathValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/processor_path');
432 }
433
434 try {
435 $currentImPathLzwValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/processor_path_lzw');
436 } catch (\RuntimeException $e) {
437 $currentImPathLzwValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/processor_path_lzw');
438 }
439
440 try {
441 $currentImageFileExtValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/imagefile_ext');
442 } catch (\RuntimeException $e) {
443 $currentImageFileExtValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/imagefile_ext');
444 }
445
446 try {
447 $currentThumbnailsValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/thumbnails');
448 } catch (\RuntimeException $e) {
449 $currentThumbnailsValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/thumbnails');
450 }
451
452 if (!$currentImValue) {
453 if ($currentImPathValue != '') {
454 $changedValues['GFX/processor_path'] = '';
455 }
456 if ($currentImPathLzwValue != '') {
457 $changedValues['GFX/processor_path_lzw'] = '';
458 }
459 if ($currentImageFileExtValue !== 'gif,jpg,jpeg,png') {
460 $changedValues['GFX/imagefile_ext'] = 'gif,jpg,jpeg,png';
461 }
462 if ($currentThumbnailsValue != 0) {
463 $changedValues['GFX/thumbnails'] = 0;
464 }
465 }
466 if (!empty($changedValues)) {
467 $this->configurationManager->setLocalConfigurationValuesByPathValuePairs($changedValues);
468 $this->throwConfigurationChangedException();
469 }
470 }
471
472 /**
473 * Detail configuration of Image Magick and Graphics Magick settings
474 * depending on main values.
475 *
476 * "Configuration presets" in install tool is not type safe, so value
477 * comparisons here are not type safe too, to not trigger changes to
478 * LocalConfiguration again.
479 */
480 protected function setImageMagickDetailSettings()
481 {
482 $changedValues = [];
483 try {
484 $currentProcessorValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/processor');
485 } catch (\RuntimeException $e) {
486 $currentProcessorValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/processor');
487 }
488
489 try {
490 $currentProcessorMaskValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/processor_allowTemporaryMasksAsPng');
491 } catch (\RuntimeException $e) {
492 $currentProcessorMaskValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/processor_allowTemporaryMasksAsPng');
493 }
494
495 try {
496 $currentProcessorEffectsValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/processor_effects');
497 } catch (\RuntimeException $e) {
498 $currentProcessorEffectsValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/processor_effects');
499 }
500
501 if ((string)$currentProcessorValue !== '') {
502 if ($currentProcessorMaskValue != 0) {
503 $changedValues['GFX/processor_allowTemporaryMasksAsPng'] = 0;
504 }
505 if ($currentProcessorValue === 'GraphicsMagick') {
506 if ($currentProcessorEffectsValue != -1) {
507 $changedValues['GFX/processor_effects'] = -1;
508 }
509 }
510 }
511 if (!empty($changedValues)) {
512 $this->configurationManager->setLocalConfigurationValuesByPathValuePairs($changedValues);
513 $this->throwConfigurationChangedException();
514 }
515 }
516
517 /**
518 * Migrate the definition of the image processor from the configuration value
519 * im_version_5 to the setting processor.
520 */
521 protected function migrateImageProcessorSetting()
522 {
523 $changedSettings = [];
524 $settingsToRename = [
525 'GFX/im' => 'GFX/processor_enabled',
526 'GFX/im_version_5' => 'GFX/processor',
527 'GFX/im_v5effects' => 'GFX/processor_effects',
528 'GFX/im_path' => 'GFX/processor_path',
529 'GFX/im_path_lzw' => 'GFX/processor_path_lzw',
530 'GFX/im_mask_temp_ext_gif' => 'GFX/processor_allowTemporaryMasksAsPng',
531 'GFX/im_noScaleUp' => 'GFX/processor_allowUpscaling',
532 'GFX/im_noFramePrepended' => 'GFX/processor_allowFrameSelection',
533 'GFX/im_stripProfileCommand' => 'GFX/processor_stripColorProfileCommand',
534 'GFX/im_useStripProfileByDefault' => 'GFX/processor_stripColorProfileByDefault',
535 'GFX/colorspace' => 'GFX/processor_colorspace',
536 ];
537
538 foreach ($settingsToRename as $oldPath => $newPath) {
539 try {
540 $value = $this->configurationManager->getLocalConfigurationValueByPath($oldPath);
541 $this->configurationManager->setLocalConfigurationValueByPath($newPath, $value);
542 $changedSettings[$oldPath] = true;
543 } catch (\RuntimeException $e) {
544 // If an exception is thrown, the value is not set in LocalConfiguration
545 $changedSettings[$oldPath] = false;
546 }
547 }
548
549 if (!empty($changedSettings['GFX/im_version_5'])) {
550 $currentProcessorValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im_version_5');
551 $newProcessorValue = $currentProcessorValue === 'gm' ? 'GraphicsMagick' : 'ImageMagick';
552 $this->configurationManager->setLocalConfigurationValueByPath('GFX/processor', $newProcessorValue);
553 }
554
555 if (!empty($changedSettings['GFX/im_noScaleUp'])) {
556 $currentProcessorValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im_noScaleUp');
557 $newProcessorValue = !$currentProcessorValue;
558 $this->configurationManager->setLocalConfigurationValueByPath(
559 'GFX/processor_allowUpscaling',
560 $newProcessorValue
561 );
562 }
563
564 if (!empty($changedSettings['GFX/im_noFramePrepended'])) {
565 $currentProcessorValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im_noFramePrepended');
566 $newProcessorValue = !$currentProcessorValue;
567 $this->configurationManager->setLocalConfigurationValueByPath(
568 'GFX/processor_allowFrameSelection',
569 $newProcessorValue
570 );
571 }
572
573 if (!empty($changedSettings['GFX/im_mask_temp_ext_gif'])) {
574 $currentProcessorValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im_mask_temp_ext_gif');
575 $newProcessorValue = !$currentProcessorValue;
576 $this->configurationManager->setLocalConfigurationValueByPath(
577 'GFX/processor_allowTemporaryMasksAsPng',
578 $newProcessorValue
579 );
580 }
581
582 if (!empty(array_filter($changedSettings))) {
583 $this->configurationManager->removeLocalConfigurationKeysByPath(array_keys($changedSettings));
584 $this->throwConfigurationChangedException();
585 }
586 }
587
588 /**
589 * Throw exception after configuration change to trigger a redirect.
590 *
591 * @throws ConfigurationChangedException
592 */
593 protected function throwConfigurationChangedException()
594 {
595 throw new ConfigurationChangedException(
596 'Configuration updated, reload needed',
597 1379024938
598 );
599 }
600
601 /**
602 * Migrate the configuration value thumbnails_png to a boolean value.
603 */
604 protected function migrateThumbnailsPngSetting()
605 {
606 $changedValues = [];
607 try {
608 $currentThumbnailsPngValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/thumbnails_png');
609 } catch (\RuntimeException $e) {
610 $currentThumbnailsPngValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/thumbnails_png');
611 }
612
613 if (is_int($currentThumbnailsPngValue) && $currentThumbnailsPngValue > 0) {
614 $changedValues['GFX/thumbnails_png'] = true;
615 }
616 if (!empty($changedValues)) {
617 $this->configurationManager->setLocalConfigurationValuesByPathValuePairs($changedValues);
618 $this->throwConfigurationChangedException();
619 }
620 }
621
622 /**
623 * Migrate the configuration setting BE/lockSSL to boolean if set in the LocalConfiguration.php file
624 */
625 protected function migrateLockSslSetting()
626 {
627 try {
628 $currentOption = $this->configurationManager->getLocalConfigurationValueByPath('BE/lockSSL');
629 // check if the current option is an integer/string and if it is active
630 if (!is_bool($currentOption) && (int)$currentOption > 0) {
631 $this->configurationManager->setLocalConfigurationValueByPath('BE/lockSSL', true);
632 $this->throwConfigurationChangedException();
633 }
634 } catch (\RuntimeException $e) {
635 // no change inside the LocalConfiguration.php found, so nothing needs to be modified
636 }
637 }
638
639 /**
640 * Move the database connection settings to a "Default" connection
641 */
642 protected function migrateDatabaseConnectionSettings()
643 {
644 $confManager = $this->configurationManager;
645
646 $newSettings = [];
647 $removeSettings = [];
648
649 try {
650 $value = $confManager->getLocalConfigurationValueByPath('DB/username');
651 $removeSettings[] = 'DB/username';
652 $newSettings['DB/Connections/Default/user'] = $value;
653 } catch (\RuntimeException $e) {
654 // Old setting does not exist, do nothing
655 }
656
657 try {
658 $value= $confManager->getLocalConfigurationValueByPath('DB/password');
659 $removeSettings[] = 'DB/password';
660 $newSettings['DB/Connections/Default/password'] = $value;
661 } catch (\RuntimeException $e) {
662 // Old setting does not exist, do nothing
663 }
664
665 try {
666 $value = $confManager->getLocalConfigurationValueByPath('DB/host');
667 $removeSettings[] = 'DB/host';
668 $newSettings['DB/Connections/Default/host'] = $value;
669 } catch (\RuntimeException $e) {
670 // Old setting does not exist, do nothing
671 }
672
673 try {
674 $value = $confManager->getLocalConfigurationValueByPath('DB/port');
675 $removeSettings[] = 'DB/port';
676 $newSettings['DB/Connections/Default/port'] = $value;
677 } catch (\RuntimeException $e) {
678 // Old setting does not exist, do nothing
679 }
680
681 try {
682 $value = $confManager->getLocalConfigurationValueByPath('DB/socket');
683 $removeSettings[] = 'DB/socket';
684 // Remove empty socket connects
685 if (!empty($value)) {
686 $newSettings['DB/Connections/Default/unix_socket'] = $value;
687 }
688 } catch (\RuntimeException $e) {
689 // Old setting does not exist, do nothing
690 }
691
692 try {
693 $value = $confManager->getLocalConfigurationValueByPath('DB/database');
694 $removeSettings[] = 'DB/database';
695 $newSettings['DB/Connections/Default/dbname'] = $value;
696 } catch (\RuntimeException $e) {
697 // Old setting does not exist, do nothing
698 }
699
700 try {
701 $value = (bool)$confManager->getLocalConfigurationValueByPath('SYS/dbClientCompress');
702 $removeSettings[] = 'SYS/dbClientCompress';
703 if ($value) {
704 $newSettings['DB/Connections/Default/driverOptions'] = [
705 'flags' => MYSQLI_CLIENT_COMPRESS,
706 ];
707 }
708 } catch (\RuntimeException $e) {
709 // Old setting does not exist, do nothing
710 }
711
712 try {
713 $value = (bool)$confManager->getLocalConfigurationValueByPath('SYS/no_pconnect');
714 $removeSettings[] = 'SYS/no_pconnect';
715 if (!$value) {
716 $newSettings['DB/Connections/Default/persistentConnection'] = true;
717 }
718 } catch (\RuntimeException $e) {
719 // Old setting does not exist, do nothing
720 }
721
722 try {
723 $value = $confManager->getLocalConfigurationValueByPath('SYS/setDBinit');
724 $removeSettings[] = 'SYS/setDBinit';
725 $newSettings['DB/Connections/Default/initCommands'] = $value;
726 } catch (\RuntimeException $e) {
727 // Old setting does not exist, do nothing
728 }
729
730 try {
731 $confManager->getLocalConfigurationValueByPath('DB/Connections/Default/charset');
732 } catch (\RuntimeException $e) {
733 // If there is no charset option yet, add it.
734 $newSettings['DB/Connections/Default/charset'] = 'utf8';
735 }
736
737 try {
738 $confManager->getLocalConfigurationValueByPath('DB/Connections/Default/driver');
739 } catch (\RuntimeException $e) {
740 // Use the mysqli driver by default if no value has been provided yet
741 $newSettings['DB/Connections/Default/driver'] = 'mysqli';
742 }
743
744 // Add new settings and remove old ones
745 if (!empty($newSettings)) {
746 $confManager->setLocalConfigurationValuesByPathValuePairs($newSettings);
747 }
748 if (!empty($removeSettings)) {
749 $confManager->removeLocalConfigurationKeysByPath($removeSettings);
750 }
751
752 // Throw redirect if something was changed
753 if (!empty($newSettings) || !empty($removeSettings)) {
754 $this->throwConfigurationChangedException();
755 }
756 }
757
758 /**
759 * Migrate the configuration setting DB/Connections/Default/charset to 'utf8' as
760 * 'utf-8' is not supported by all MySQL versions.
761 */
762 protected function migrateDatabaseConnectionCharset()
763 {
764 $confManager = $this->configurationManager;
765 try {
766 $driver = $confManager->getLocalConfigurationValueByPath('DB/Connections/Default/driver');
767 $charset = $confManager->getLocalConfigurationValueByPath('DB/Connections/Default/charset');
768 if (in_array($driver, ['mysqli', 'pdo_mysql', 'drizzle_pdo_mysql'], true) && $charset === 'utf-8') {
769 $confManager->setLocalConfigurationValueByPath('DB/Connections/Default/charset', 'utf8');
770 $this->throwConfigurationChangedException();
771 }
772 } catch (\RuntimeException $e) {
773 // no incompatible charset configuration found, so nothing needs to be modified
774 }
775 }
776
777 /**
778 * Migrate the configuration setting DB/Connections/Default/driverOptions to array type.
779 */
780 protected function migrateDatabaseDriverOptions()
781 {
782 $confManager = $this->configurationManager;
783 try {
784 $options = $confManager->getLocalConfigurationValueByPath('DB/Connections/Default/driverOptions');
785 if (!is_array($options)) {
786 $confManager->setLocalConfigurationValueByPath(
787 'DB/Connections/Default/driverOptions',
788 ['flags' => (int)$options]
789 );
790 }
791 } catch (\RuntimeException $e) {
792 // no driver options found, nothing needs to be modified
793 }
794 }
795
796 /**
797 * Migrate the configuration setting BE/lang/debug if set in the LocalConfiguration.php file
798 */
799 protected function migrateLangDebug()
800 {
801 $confManager = $this->configurationManager;
802 try {
803 $currentOption = $confManager->getLocalConfigurationValueByPath('BE/lang/debug');
804 // check if the current option is set and boolean
805 if (isset($currentOption) && is_bool($currentOption)) {
806 $confManager->setLocalConfigurationValueByPath('BE/languageDebug', $currentOption);
807 }
808 } catch (\RuntimeException $e) {
809 // no change inside the LocalConfiguration.php found, so nothing needs to be modified
810 }
811 }
812
813 /**
814 * Migrate single cache hash related options under "FE" into "FE/cacheHash"
815 */
816 protected function migrateCacheHashOptions()
817 {
818 $confManager = $this->configurationManager;
819 $removeSettings = [];
820 $newSettings = [];
821
822 try {
823 $value = $confManager->getLocalConfigurationValueByPath('FE/cHashOnlyForParameters');
824 $removeSettings[] = 'FE/cHashOnlyForParameters';
825 $newSettings['FE/cacheHash/cachedParametersWhiteList'] = GeneralUtility::trimExplode(',', $value, true);
826 } catch (\RuntimeException $e) {
827 }
828
829 try {
830 $value = $confManager->getLocalConfigurationValueByPath('FE/cHashExcludedParameters');
831 $removeSettings[] = 'FE/cHashExcludedParameters';
832 $newSettings['FE/cacheHash/excludedParameters'] = GeneralUtility::trimExplode(',', $value, true);
833 } catch (\RuntimeException $e) {
834 }
835
836 try {
837 $value = $confManager->getLocalConfigurationValueByPath('FE/cHashRequiredParameters');
838 $removeSettings[] = 'FE/cHashRequiredParameters';
839 $newSettings['FE/cacheHash/requireCacheHashPresenceParameters'] = GeneralUtility::trimExplode(',', $value, true);
840 } catch (\RuntimeException $e) {
841 }
842
843 try {
844 $value = $confManager->getLocalConfigurationValueByPath('FE/cHashExcludedParametersIfEmpty');
845 $removeSettings[] = 'FE/cHashExcludedParametersIfEmpty';
846 if (trim($value) === '*') {
847 $newSettings['FE/cacheHash/excludeAllEmptyParameters'] = true;
848 } else {
849 $newSettings['FE/cacheHash/excludedParametersIfEmpty'] = GeneralUtility::trimExplode(',', $value, true);
850 }
851 } catch (\RuntimeException $e) {
852 }
853
854 // Add new settings and remove old ones
855 if (!empty($newSettings)) {
856 $confManager->setLocalConfigurationValuesByPathValuePairs($newSettings);
857 }
858 if (!empty($removeSettings)) {
859 $confManager->removeLocalConfigurationKeysByPath($removeSettings);
860 }
861
862 // Throw redirect if something was changed
863 if (!empty($newSettings) || !empty($removeSettings)) {
864 $this->throwConfigurationChangedException();
865 }
866 }
867
868 /**
869 * Migrate SYS/exceptionalErrors to not contain E_USER_DEPRECATED
870 */
871 protected function migrateExceptionErrors()
872 {
873 $confManager = $this->configurationManager;
874 try {
875 $currentOption = (int)$confManager->getLocalConfigurationValueByPath('SYS/exceptionalErrors');
876 // make sure E_USER_DEPRECATED is not part of the exceptionalErrors
877 if ($currentOption & E_USER_DEPRECATED) {
878 $confManager->setLocalConfigurationValueByPath('SYS/exceptionalErrors', $currentOption & ~E_USER_DEPRECATED);
879 }
880 } catch (\RuntimeException $e) {
881 // no change inside the LocalConfiguration.php found, so nothing needs to be modified
882 }
883 }
884 }