Passed
Push — development ( 924c99...c29c1d )
by Spuds
01:04 queued 20s
created

ManageServer::balancingSettings_search()   A

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

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