ManageServer::balancingSettings_search()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 0
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Contains all the functionality required to be able to edit the core server settings.
5
 * This includes anything from which an error may result in the forum destroying
6
 * itself in a firey fury.
7
 *
8
 * @package   ElkArte Forum
9
 * @copyright ElkArte Forum contributors
10
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
11
 *
12
 * This file contains code covered by:
13
 * copyright: 2011 Simple Machines (http://www.simplemachines.org)
14
 *
15
 * @version 2.0 dev
16
 *
17
 */
18
19
namespace ElkArte\AdminController;
20
21
use ElkArte\AbstractController;
22
use ElkArte\Action;
23
use ElkArte\Cache\CacheMethod\AbstractCacheMethod;
24
use ElkArte\Exceptions\Exception;
25
use ElkArte\SettingsForm\SettingsForm;
26
use ElkArte\Languages\Txt;
27
use ElkArte\User;
28
29
/**
30
 * ManageServer administration pages controller.
31
 *
32
 * This handles several screens, with low-level essential settings such as
33
 * database settings, cache, general forum settings, and others.
34
 * It sends the data for display, and it allows the admin to change it.
35
 */
36
class ManageServer extends AbstractController
37
{
38
	/**
39
	 * This is the main dispatcher. Sets up all the available sub-actions, all the tabs and selects
40
	 * the appropriate one based on the sub-action.
41
	 *
42
	 * What it does:
43
	 *
44
	 * - Requires the admin_forum permission.
45
	 * - Redirects to the appropriate function based on the sub-action.
46
	 *
47
	 * @event integrate_sa_server_settings
48
	 * @uses edit_settings adminIndex.
49
	 * @see AbstractController::action_index()
50
	 */
51
	public function action_index()
52
	{
53
		global $context, $txt;
54
55
		// The settings are in here, I swear!
56
		Txt::load('ManageSettings');
57
58
		// This is just to keep the database password more secure.
59
		isAllowedTo('admin_forum');
60
		checkSession('request');
61
62
		$subActions = [
63
			'general' => [$this, 'action_generalSettings_display', 'permission' => 'admin_forum'],
64
			'database' => [$this, 'action_databaseSettings_display', 'permission' => 'admin_forum'],
65
			'cookie' => [$this, 'action_cookieSettings_display', 'permission' => 'admin_forum'],
66
			'cache' => [$this, 'action_cacheSettings_display', 'permission' => 'admin_forum'],
67
			'loads' => [$this, 'action_loadavgSettings_display', 'permission' => 'admin_forum'],
68
			'phpinfo' => [$this, 'action_phpinfo', 'permission' => 'admin_forum'],
69
		];
70
71
		$action = new Action('server_settings');
72
73
		// By default we're editing the core settings, call integrate_sa_server_settings
74
		$subAction = $action->initialize($subActions, 'general');
75
76
		// Last things for the template
77
		$context['sub_action'] = $subAction;
78
		$context['page_title'] = $txt['admin_server_settings'];
79
		$context['sub_template'] = 'show_settings';
80
81
		// Load up all the tabs...
82
		$context[$context['admin_menu_name']]['object']->prepareTabData([
83
			'title' => 'admin_server_settings',
84
			'help' => 'serversettings',
85
			'description' => 'admin_basic_settings',
86
		]);
87
88
		// Any messages to speak of?
89
		$context['settings_message'] = (isset($this->_req->query->msg, $txt[$this->_req->query->msg])) ? $txt[$this->_req->query->msg] : '';
90
91
		// Warn the user if there's any relevant information regarding Settings.php.
92
		$settings_not_writable = !is_writable(BOARDDIR . '/Settings.php');
93
94
		// Warn the user if the backup of Settings.php failed.
95
		$settings_backup_fail = !@is_writable(BOARDDIR . '/Settings_bak.php') || !@copy(BOARDDIR . '/Settings.php', BOARDDIR . '/Settings_bak.php');
96
97
		if ($settings_not_writable)
98
		{
99
			$context['settings_message'] = $txt['settings_not_writable'];
100
			$context['error_type'] = 'notice';
101
		}
102
		elseif ($settings_backup_fail)
103
		{
104
			$context['settings_message'] = $txt['admin_backup_fail'];
105
			$context['error_type'] = 'notice';
106
		}
107
108
		$context['settings_not_writable'] = $settings_not_writable;
109
110
		// Call the right function for this sub-action.
111
		$action->dispatch($subAction);
112
	}
113
114
	/**
115
	 * General forum settings - forum name, maintenance mode, etc.
116
	 *
117
	 * Practically, this shows an interface for the settings in Settings.php to
118
	 * be changed. The method handles the display, allows to edit, and saves
119
	 * the result for generalSettings form.
120
	 *
121
	 * What it does:
122
	 *
123
	 * - Requires the admin_forum permission.
124
	 * - Uses the edit_settings administration area.
125
	 * - Contains the actual array of settings to show from Settings.php.
126
	 * - Accessed from ?action=admin;area=serversettings;sa=general.
127
	 *
128
	 * @event integrate_save_general_settings
129
	 */
130
	public function action_generalSettings_display(): void
131
	{
132
		global $context, $txt;
133
134
		// Initialize the form
135
		$settingsForm = new SettingsForm(SettingsForm::FILE_ADAPTER);
136
137
		// Initialize it with our settings
138
		$settingsForm->setConfigVars($this->_generalSettings());
139
140
		// Setup the template stuff.
141
		$context['post_url'] = getUrl('admin', ['action' => 'admin', 'area' => 'serversettings', 'sa' => 'general', 'save']);
142
		$context['settings_title'] = $txt['general_settings'];
143
144
		// Saving settings?
145
		if (isset($this->_req->query->save))
146
		{
147
			call_integration_hook('integrate_save_general_settings');
148
149
			// Reset this in the event the server has changed, it will get set again if needed.
150
			updateSettings(['host_to_dis' => 0]);
151
152
			$settingsForm->setConfigValues((array) $this->_req->post);
153
			$settingsForm->save();
154
			redirectexit('action=admin;area=serversettings;sa=general;' . $context['session_var'] . '=' . $context['session_id'] . ';msg=' . (empty($context['settings_message']) ? 'core_settings_saved' : $context['settings_message']));
155
		}
156
157
		// Fill the config array for the template and all that.
158
		$settingsForm->prepare();
159
	}
160
161 2
	/**
162
	 * This function returns all general settings.
163 2
	 *
164
	 * @event integrate_modify_general_settings
165
	 */
166
	private function _generalSettings()
167 2
	{
168 2
		global $txt;
169 2
170 2
		// initialize configuration
171 2
		$config_vars = [
172 2
			['mbname', $txt['admin_title'], 'file', 'text', 30],
173 2
			'',
174 2
			['maintenance', $txt['admin_maintain'], 'file', 'check'],
175 2
			['mtitle', $txt['maintenance_subject'], 'file', 'text', 36],
176 2
			['mmessage', $txt['maintenance_message'], 'file', 'large_text', 6],
177 2
			'',
178
			['webmaster_email', $txt['admin_webmaster_email'], 'file', 'text', 30],
179
			'',
180
			['enableCompressedOutput', $txt['enableCompressedOutput'], 'db', 'check', null, 'enableCompressedOutput'],
181 2
			['disableHostnameLookup', $txt['disableHostnameLookup'], 'db', 'check', null, 'disableHostnameLookup'],
182
			// This is not really a server setting, it's here for convenience so its saved in Settings.php
183 2
			['url_format', $txt['url_format'], 'file', 'select', ['standard' => $txt['url_format_standard'], 'semantic' => $txt['url_format_semantic'], 'queryless' => $txt['url_format_queryless']]],
184
		];
185
186
		// Notify the integration
187
		call_integration_hook('integrate_modify_general_settings', [&$config_vars]);
188
189
		return $config_vars;
190
	}
191
192
	/**
193
	 * Basic database and paths settings - database name, host, etc.
194
	 *
195
	 * This method handles the display, allows to edit, and saves the results
196
	 * for _databaseSettings.
197
	 *
198
	 * What it does:
199
	 *
200
	 * - It shows an interface for the settings in Settings.php to be changed.
201
	 * - It contains the actual array of settings to show from Settings.php.
202
	 * - Requires the admin_forum permission.
203
	 * - Uses the edit_settings administration area.
204
	 * - Accessed from ?action=admin;area=serversettings;sa=database.
205
	 *
206
	 * @event integrate_save_database_settings
207
	 */
208
	public function action_databaseSettings_display(): void
209
	{
210
		global $context, $txt;
211
212
		// Initialize the form
213
		$settingsForm = new SettingsForm(SettingsForm::FILE_ADAPTER);
214
215
		// Initialize it with our settings
216
		$settingsForm->setConfigVars($this->_databaseSettings());
217
218
		// Setup the template stuff.
219
		$context['post_url'] = getUrl('admin', ['action' => 'admin', 'area' => 'serversettings', 'sa' => 'database', 'save']);
220
		$context['settings_title'] = $txt['database_paths_settings'];
221
		$context['save_disabled'] = $context['settings_not_writable'];
222
223
		// Saving settings?
224
		if (isset($this->_req->query->save))
225
		{
226
			call_integration_hook('integrate_save_database_settings');
227
228
			$settingsForm->setConfigValues((array) $this->_req->post);
229
			$settingsForm->save();
230
			redirectexit('action=admin;area=serversettings;sa=database;' . $context['session_var'] . '=' . $context['session_id'] . ';msg=' . (empty($context['settings_message']) ? 'core_settings_saved' : $context['settings_message']));
231
		}
232
233
		// Fill the config array for the template.
234
		$settingsForm->prepare();
235
	}
236 2
237
	/**
238 2
	 * This function returns database settings.
239
	 *
240
	 * @event integrate_modify_database_settings
241
	 */
242 2
	private function _databaseSettings()
243 2
	{
244 2
		global $txt;
245 2
246 2
		// initialize settings
247 2
		$config_vars = [
248 2
			['db_server', $txt['database_server'], 'file', 'text'],
249 2
			['db_user', $txt['database_user'], 'file', 'text'],
250 2
			['db_passwd', $txt['database_password'], 'file', 'password'],
251 2
			['db_name', $txt['database_name'], 'file', 'text'],
252 2
			['db_prefix', $txt['database_prefix'], 'file', 'text'],
253 2
			['db_persist', $txt['db_persist'], 'file', 'check', null, 'db_persist'],
254 2
			['db_error_send', $txt['db_error_send'], 'file', 'check'],
255 2
			['ssi_db_user', $txt['ssi_db_user'], 'file', 'text', null, 'ssi_db_user'],
256 2
			['ssi_db_passwd', $txt['ssi_db_passwd'], 'file', 'password'],
257 2
			'',
258 2
			['autoFixDatabase', $txt['autoFixDatabase'], 'db', 'check', false, 'autoFixDatabase'],
259
			['autoOptMaxOnline', $txt['autoOptMaxOnline'], 'subtext' => $txt['zero_for_no_limit'], 'db', 'int'],
260
			'',
261
			['boardurl', $txt['admin_url'], 'file', 'text', 36],
262 2
			['boarddir', $txt['boarddir'], 'file', 'text', 36],
263
			['sourcedir', $txt['sourcesdir'], 'file', 'text', 36],
264 2
			['cachedir', $txt['cachedir'], 'file', 'text', 36],
265
		];
266
267
		// Notify the integration
268
		call_integration_hook('integrate_modify_database_settings', [&$config_vars]);
269
270
		return $config_vars;
271
	}
272
273
	/**
274
	 * Modify cookies settings.
275
	 *
276
	 * This method handles the display, allows to edit, and saves the result
277
	 * for the _cookieSettings form.
278
	 *
279
	 * @event integrate_save_cookie_settings
280
	 */
281
	public function action_cookieSettings_display(): void
282
	{
283
		global $context, $txt, $modSettings, $cookiename, $boardurl;
284
285
		// Initialize the form
286
		$settingsForm = new SettingsForm(SettingsForm::FILE_ADAPTER);
287
288
		// Initialize it with our settings
289
		$settingsForm->setConfigVars($this->_cookieSettings());
290
291
		$context['post_url'] = getUrl('admin', ['action' => 'admin', 'area' => 'serversettings', 'sa' => 'cookie', 'save']);
292
		$context['settings_title'] = $txt['cookies_sessions_settings'];
293
294
		// Saving settings?
295
		if (isset($this->_req->query->save))
296
		{
297
			call_integration_hook('integrate_save_cookie_settings');
298
299
			// Its either local or global cookies
300
			if (!empty($this->_req->post->localCookies) && !empty($this->_req->post->globalCookies))
301
			{
302
				unset($this->_req->post->globalCookies);
303
			}
304
305
			if (!empty($this->_req->post->globalCookiesDomain) && strpos($boardurl, (string) $this->_req->post->globalCookiesDomain) === false)
306
			{
307
				throw new Exception('invalid_cookie_domain', false);
308
			}
309
310
			if ($this->_req->getPost('cookiename', 'trim', '') === '')
311
			{
312
				$this->_req->post->cookiename = $cookiename;
313
			}
314
315
			$settingsForm->setConfigValues((array) $this->_req->post);
316
			$settingsForm->save();
317
318
			// If the cookie name was changed, reset the cookie.
319
			if ($cookiename !== $this->_req->post->cookiename)
320
			{
321
				require_once(SUBSDIR . '/Auth.subs.php');
322
323
				$original_session_id = $context['session_id'];
324
325
				// Remove the old cookie, nom nom nom
326
				setLoginCookie(-3600, 0);
327
328
				// Set the new one.
329
				$cookiename = $this->_req->post->cookiename;
330
				setLoginCookie(60 * $modSettings['cookieTime'], (int) User::$settings['id_member'], hash('sha256', User::$settings['passwd'] . User::$settings['password_salt']));
331
332
				redirectexit('action=admin;area=serversettings;sa=cookie;' . $context['session_var'] . '=' . $original_session_id);
333
			}
334
335
			redirectexit('action=admin;area=serversettings;sa=cookie;' . $context['session_var'] . '=' . $context['session_id'] . ';msg=' . (empty($context['settings_message']) ? 'core_settings_saved' : $context['settings_message']));
336
		}
337
338
		theme()->addInlineJavascript('
339
		// Initial state
340
		hideGlobalCookies();
341
342
		// Update when clicked
343
		document.querySelectorAll("#localCookies, #globalCookies").forEach(function(element) {
344
             element.addEventListener("click", function() {
345 2
			    hideGlobalCookies();
346
              });
347 2
		});', true);
348
349
		// Fill the config array.
350
		$settingsForm->prepare();
351
	}
352 2
353 2
	/**
354 2
	 * This little function returns all cookie settings.
355 2
	 *
356 2
	 * @event integrate_modify_cookie_settings
357 2
	 */
358 2
	private function _cookieSettings()
359 2
	{
360
		global $txt;
361 2
362 2
		// Define the variables we want to edit or show in the cookie form.
363 2
		$config_vars = [
364
			// Cookies...
365
			['cookiename', $txt['cookie_name'], 'file', 'text', 20],
366
			['cookieTime', $txt['cookieTime'], 'db', 'int', 'postinput' => $txt['minutes']],
367 2
			['localCookies', $txt['localCookies'], 'subtext' => $txt['localCookies_note'], 'db', 'check', false, 'localCookies'],
368
			['globalCookies', $txt['globalCookies'], 'subtext' => $txt['globalCookies_note'], 'db', 'check', false, 'globalCookies'],
369
			['globalCookiesDomain', $txt['globalCookiesDomain'], 'subtext' => $txt['globalCookiesDomain_note'], 'db', 'text', false, 'globalCookiesDomain'],
370 2
			['secureCookies', $txt['secureCookies'], 'subtext' => $txt['secureCookies_note'], 'db', 'check', false, 'secureCookies', 'disabled' => !isset($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) !== 'on' && strtolower($_SERVER['HTTPS']) != '1'],
371
			['httponlyCookies', $txt['httponlyCookies'], 'subtext' => $txt['httponlyCookies_note'], 'db', 'check', false, 'httponlyCookies'],
372
			'',
373
			// Sessions
374
			['databaseSession_enable', $txt['databaseSession_enable'], 'db', 'check', false, 'databaseSession_enable'],
375
			['databaseSession_loose', $txt['databaseSession_loose'], 'db', 'check', false, 'databaseSession_loose'],
376
			['databaseSession_lifetime', $txt['databaseSession_lifetime'], 'db', 'int', false, 'databaseSession_lifetime', 'postinput' => $txt['seconds']],
377
		];
378
379
		// Notify the integration
380
		call_integration_hook('integrate_modify_cookie_settings', [&$config_vars]);
381
382
		// Set them vars for our settings form
383
		return $config_vars;
384
	}
385
386
	/**
387
	 * Cache settings editing and submission.
388
	 *
389
	 * This method handles the display, allows to edit, and saves the result
390
	 * for _cacheSettings form.
391
	 *
392
	 * @event integrate_save_cache_settings
393
	 */
394
	public function action_cacheSettings_display(): void
395
	{
396
		global $context, $txt;
397
398
		// Initialize the form
399
		$settingsForm = new SettingsForm(SettingsForm::FILE_ADAPTER);
400
401
		// Initialize it with our settings
402
		$settingsForm->setConfigVars($this->_cacheSettings());
403
404
		// Saving again?
405
		if (isset($this->_req->query->save))
406
		{
407
			call_integration_hook('integrate_save_cache_settings');
408
409
			// Move accelerator servers to the cache_servers value
410
			$var = 'cache_servers_' . $this->_req->post->cache_accelerator;
411
			if (isset($this->_req->post->$var))
412
			{
413
				$this->_req->post->cache_servers = $this->_req->post->$var;
414
			}
415
416
			$settingsForm->setConfigValues((array) $this->_req->post);
417
			$settingsForm->save();
418
419
			// we need to save the $cache_enable to $modSettings as well
420
			updateSettings(['cache_enable' => (int) $this->_req->post->cache_enable]);
421
422
			// exit so we reload our new settings on the page
423
			redirectexit('action=admin;area=serversettings;sa=cache;' . $context['session_var'] . '=' . $context['session_id']);
424
		}
425
426
		Txt::load('Maintenance');
427
		createToken('admin-maint');
428
		theme()->getLayers()->add('clean_cache_button');
429
430
		// Some javascript to enable / disable certain settings if the option is not selected
431
		theme()->addInlineJavascript('
432
			let cache_type = document.getElementById(\'cache_accelerator\');
433
434 2
			cache_type.addEventListener("change", showCache);
435
			cache_type.addEventListener("change", toggleCache);
436 2
			
437
			let event = new Event("change");
438
			cache_type.dispatchEvent(event);
439 2
			', true);
440 2
441 2
		$context['post_url'] = getUrl('admin', ['action' => 'admin', 'area' => 'serversettings', 'sa' => 'cache', 'save']);
442 2
		$context['settings_title'] = $txt['caching_settings'];
443
		$context['settings_message'] = $txt['caching_information'] . '<br /><br />' . $txt['cache_settings_message'];
444 2
445
		// Prepare the template.
446 2
		createToken('admin-ssc');
447
448 2
		// Prepare settings for display in the template.
449
		$settingsForm->prepare();
450 2
	}
451
452
	/**
453
	 * This little function returns all cache settings.
454 2
	 *
455
	 * @event integrate_modify_cache_settings
456
	 */
457 2
	private function _cacheSettings()
458 2
	{
459
		global $txt, $cache_accelerator, $context;
460
461
		// Detect all available cache engines
462
		require_once(SUBSDIR . '/Cache.subs.php');
463 2
		$detected = loadCacheEngines(false);
464 2
		$detected_names = [];
465
		$detected_supported = [];
466
467
		/** @var $value AbstractCacheMethod */
468 2
		foreach ($detected as $key => $value)
469
		{
470 2
			$detected_names[] = $value->title();
471
472 2
			if (!empty($value->isAvailable()))
473
			{
474
				$detected_supported[$key] = $value->title();
475
				if ($key === $cache_accelerator)
476
				{
477 2
					$context['cache_accelerator_stats'] = $value->getStats();
478
				}
479 2
			}
480
		}
481
482
		$txt['caching_information'] = str_replace('{supported_accelerators}', '<i>' . implode(', ', $detected_names) . '</i><br />', $txt['caching_information']);
483
484
		// Set our values to show what, if anything, we found
485
		$txt['cache_settings_message'] = sprintf($txt['detected_accelerators'], implode(', ', $detected_supported));
486
		$cache_level = [$txt['cache_off'], $txt['cache_level1'], $txt['cache_level2'], $txt['cache_level3']];
487
488
		// Define the variables we want to edit.
489
		$config_vars = [
490
			// Only a few settings, but they are important
491
			['cache_enable', $txt['cache_enable'], 'file', 'select', $cache_level, 'cache_enable'],
492
			['cache_accelerator', $txt['cache_accelerator'], 'file', 'select', $detected_supported],
493
		];
494
495
		// If the cache engine has any specific settings, add them in
496
		foreach ($detected as $engine)
497
		{
498
			/** @var $engine AbstractCacheMethod */
499
			if ($engine->isAvailable())
500
			{
501
				$engine->settings($config_vars);
502
			}
503
		}
504
505
		// Notify the integration that we're preparing to mess with cache settings...
506
		call_integration_hook('integrate_modify_cache_settings', [&$config_vars]);
507
508
		return $config_vars;
509
	}
510
511
	/**
512
	 * Allows to edit load management settings.
513
	 *
514
	 * This method handles the display, allows to edit, and saves the result
515
	 * for the _loadavgSettings form.
516
	 *
517
	 * @event integrate_loadavg_settings
518
	 * @event integrate_save_loadavg_settings
519
	 */
520
	public function action_loadavgSettings_display(): void
521
	{
522
		global $txt, $context;
523
524
		// Initialize the form
525
		$settingsForm = new SettingsForm(SettingsForm::DB_ADAPTER);
526
527
		// Initialize it with our settings
528
		$settingsForm->setConfigVars($this->_loadavgSettings());
529
530
		call_integration_hook('integrate_loadavg_settings');
531
532
		$context['post_url'] = getUrl('admin', ['action' => 'admin', 'area' => 'serversettings', 'sa' => 'loads', 'save']);
533
		$context['settings_title'] = $txt['loadavg_settings'];
534
535
		// Saving?
536
		if (isset($this->_req->query->save))
537
		{
538
			// Stupidity is not allowed.
539
			foreach ($this->_req->post as $key => $value)
540
			{
541
				if (strpos($key, 'loadavg') === 0 || $key === 'loadavg_enable')
542
				{
543
					continue;
544
				}
545
546
				if ($key === 'loadavg_auto_opt' && $value <= 1)
547
				{
548 2
					$this->_req->post->loadavg_auto_opt = '1.0';
549
				}
550 2
				elseif ($key === 'loadavg_forum' && $value < 10)
551
				{
552
					$this->_req->post->loadavg_forum = '10.0';
553 2
				}
554 2
				elseif ($value < 2)
555
				{
556
					$this->_req->{$key} = '2.0';
557 2
				}
558
			}
559
560
			call_integration_hook('integrate_save_loadavg_settings');
561
562
			$settingsForm->setConfigValues((array) $this->_req->post);
563 2
			$settingsForm->save();
564 2
			redirectexit('action=admin;area=serversettings;sa=loads;' . $context['session_var'] . '=' . $context['session_id']);
565
		}
566 2
567
		createToken('admin-ssc');
568 2
		createToken('admin-dbsc');
569 2
		$settingsForm->prepare();
570
	}
571
572
	/**
573
	 * This little function returns load management settings.
574
	 *
575 2
	 * @event integrate_modify_loadavg_settings
576
	 */
577
	private function _loadavgSettings()
578
	{
579
		global $txt, $modSettings, $context;
580 2
581
		// Initialize settings for the form to show, disabled by default.
582
		$disabled = true;
583
		$context['settings_message'] = $txt['loadavg_disabled_conf'];
584
585
		// Don't say you're using that win-thing, no cookies for you :P
586
		if (strpos(PHP_OS_FAMILY, 'Win') === 0)
587
		{
588
			$context['settings_message'] = $txt['loadavg_disabled_windows'];
589
		}
590
		else
591 2
		{
592
			require_once(SUBSDIR . '/Server.subs.php');
593
			$modSettings['load_average'] = detectServerLoad();
594 2
595 2
			if ($modSettings['load_average'] !== false)
596
			{
597
				$disabled = false;
598
				$context['settings_message'] = sprintf($txt['loadavg_warning'], $modSettings['load_average']);
599 2
			}
600
		}
601 2
602
		// Start with a simple checkbox.
603
		$config_vars = [
604
			['check', 'loadavg_enable', 'disabled' => $disabled],
605
		];
606
607
		// Set the default values for each option.
608
		$default_values = [
609
			'loadavg_auto_opt' => '1.0',
610
			'loadavg_search' => '2.5',
611
			'loadavg_allunread' => '2.0',
612
			'loadavg_unreadreplies' => '3.5',
613
			'loadavg_show_posts' => '2.0',
614
			'loadavg_userstats' => '10.0',
615
			'loadavg_bbc' => '30.0',
616
			'loadavg_forum' => '40.0',
617
		];
618
619
		// Loop through the settings.
620
		foreach ($default_values as $name => $value)
621
		{
622
			// Use the default value if the setting isn't set yet.
623
			$value = $modSettings[$name] ?? $value;
624
			$config_vars[] = ['text', $name, 'value' => $value, 'disabled' => $disabled];
625
		}
626
627
		// Notify the integration that we're preparing to mess with load management settings...
628
		call_integration_hook('integrate_modify_loadavg_settings', [&$config_vars]);
629
630
		return $config_vars;
631
	}
632
633
	/**
634
	 * Allows us to see the servers php settings
635
	 *
636
	 * What it does:
637
	 *
638
	 * - loads the settings into an array for display in a template
639
	 * - drops cookie values just in case
640
	 *
641
	 * @uses sub-template php_info
642
	 */
643
	public function action_phpinfo(): void
644
	{
645
		global $context, $txt;
646
647
		$category = $txt['phpinfo_settings'];
648
		$pinfo = [];
649
650
		// Get the data
651
		ob_start();
652
		phpinfo();
653
654
		// We only want it for its body, pigs that we are
655
		$info_lines = preg_replace('~^.*<body>(.*)</body>.*$~', '$1', ob_get_contents());
656
		$info_lines = explode("\n", strip_tags($info_lines, '<tr><td><h2>'));
657
		@ob_end_clean();
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for ob_end_clean(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

657
		/** @scrutinizer ignore-unhandled */ @ob_end_clean();

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
658
659
		// Remove things that could be considered sensitive
660
		$remove = '_COOKIE|Cookie|_GET|_REQUEST|REQUEST_URI|QUERY_STRING|REQUEST_URL|HTTP_REFERER';
661
662
		// Put all of it into an array
663
		foreach ($info_lines as $line)
664
		{
665
			if (preg_match('~(' . $remove . ')~', $line))
666
			{
667 2
				continue;
668
			}
669 2
670
			// New category?
671
			if (strpos($line, '<h2>') !== false)
672
			{
673
				$category = preg_match('~<h2>(.*)</h2>~', $line, $title) ? $title[1] : $category;
674
			}
675 2
676
			// Load it as setting => value or the old setting local master
677 2
			if (preg_match('~<tr><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td></tr>~', $line, $val))
678
			{
679
				$pinfo[$category][$val[1]] = $val[2];
680
			}
681
			elseif (preg_match('~<tr><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td></tr>~', $line, $val))
682
			{
683 2
				$pinfo[$category][$val[1]] = [$txt['phpinfo_localsettings'] => $val[2], $txt['phpinfo_defaultsettings'] => $val[3]];
684
			}
685 2
		}
686
687
		// Load it in to context and display it
688
		$context['pinfo'] = $pinfo;
689
		$context['page_title'] = $txt['admin_server_settings'];
690
		$context['sub_template'] = 'php_info';
691 2
	}
692
693 2
	/**
694
	 * Return the search settings for use in admin search
695
	 */
696
	public function generalSettings_search()
697
	{
698
		return $this->_generalSettings();
699 2
	}
700
701 2
	/**
702
	 * Return the search settings for use in admin search
703
	 */
704
	public function databaseSettings_search()
705
	{
706
		return $this->_databaseSettings();
707
	}
708
709
	/**
710
	 * Return the search settings for use in admin search
711
	 */
712
	public function cookieSettings_search()
713
	{
714
		return $this->_cookieSettings();
715
	}
716
717
	/**
718
	 * Return the search settings for use in admin search
719
	 */
720
	public function cacheSettings_search()
721
	{
722
		return $this->_cacheSettings();
723
	}
724
725
	/**
726
	 * Return the search settings for use in admin search
727
	 */
728
	public function balancingSettings_search()
729
	{
730
		return $this->_loadavgSettings();
731
	}
732
}
733