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