Passed
Pull Request — patch_1-1-7 (#3404)
by
unknown
15:47
created

Bootstrap::setDebug()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 8
rs 10
c 1
b 0
f 0
1
<?php
2
3
/**
4
 * Initialize the ElkArte environment.
5
 *
6
 * @name      ElkArte Forum
7
 * @copyright ElkArte Forum contributors
8
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
9
 *
10
 * This file contains code covered by:
11
 * copyright:	2011 Simple Machines (http://www.simplemachines.org)
12
 * license:		BSD, See included LICENSE.TXT for terms and conditions.
13
 *
14
 * @version 1.1.7
15
 *
16
 */
17
18
/**
19
 * Class Bootstrap
20
 *
21
 * This takes care of the initial loading and feeding of Elkarte from
22
 * either SSI or Index
23
 */
24
class Bootstrap
25
{
26
	/**
27
	 * Bootstrap constructor.
28
	 *
29
	 * @param bool $standalone
30
	 *  - true to boot outside of elkarte
31
	 *  - false to bootstrap the main elkarte site.
32
	 * @throws \Elk_Exception
33
	 */
34
	public function __construct($standalone = true)
35
	{
36
		// Bootstrap only once.
37
		if (defined('ELKBOOT'))
38
		{
39
			return true;
40
		}
41
42
		// We're going to set a few globals
43
		global $time_start, $ssi_error_reporting, $db_show_debug;
44
45
		// Your on the clock
46
		$time_start = microtime(true);
47
48
		// Unless settings.php tells us otherwise
49
		$db_show_debug = false;
50
51
		// Report errors but not depreciated ones
52
		$ssi_error_reporting = error_reporting(E_ALL | E_STRICT & ~8192);
53
54
		// Get the things needed for ALL modes
55
		$this->bringUpBasics();
56
57
		// Going to run from the side entrance and not directly from inside elkarte
58
		if ($standalone)
59
		{
60
			$this->ssi_main();
61
		}
62
	}
63
64
	/**
65
	 * Calls the various initialization functions in the needed order
66
	 */
67
	public function bringUpBasics()
68
	{
69
		$this->setConstants();
70
		$this->setRusage();
71
		$this->clearGloballs();
72
		$this->loadSettingsFile();
73
		$this->validatePaths();
74
		$this->loadDependants();
75
		$this->loadAutoloader();
76
		$this->checkMaintance();
77
		$this->setDebug();
78
		$this->bringUp();
79
	}
80
81
	/**
82
	 * Set the core constants, you know the ones we often forget to
83
	 * update on new releases.
84
	 */
85
	private function setConstants()
86
	{
87
		// First things first, but not necessarily in that order.
88
		if (!defined('ELK'))
89
		{
90
			define('ELK', '1');
91
		}
92
		define('ELKBOOT', '1');
93
94
		// The software version
95
		define('FORUM_VERSION', 'ElkArte 1.1.6');
96
97
		// Shortcut for the browser cache stale
98
		define('CACHE_STALE', '?R116');
99
	}
100
101
	/**
102
	 * Get initial resource usage
103
	 */
104
	private function setRusage()
105
	{
106
		global $rusage_start;
107
108
		// Directional only script time usage for display
109
		// getrusage is missing in php < 7 on Windows
110
		if (function_exists('getrusage'))
111
		{
112
			$rusage_start = getrusage();
113
		}
114
		else
115
		{
116
			$rusage_start = array();
117
		}
118
	}
119
120
	/**
121
	 * If they glo, they need to be cleaned.
122
	 */
123
	private function clearGloballs()
124
	{
125
		// We don't need no globals. (a bug in "old" versions of PHP)
126
		foreach (array('db_character_set', 'cachedir') as $variable)
127
		{
128
			if (isset($GLOBALS[$variable]))
129
			{
130
				unset($GLOBALS[$variable], $GLOBALS[$variable]);
131
			}
132
		}
133
	}
134
135
	/**
136
	 * Loads the settings values into the global space
137
	 */
138
	private function loadSettingsFile()
139
	{
140
		// All those wonderful things found in settings
141
		global $maintenance, $mtitle, $msubject, $mmessage, $mbname, $language, $boardurl, $webmaster_email;
142
		global $cookiename, $db_type, $db_server, $db_port, $db_name, $db_user, $db_passwd;
143
		global $ssi_db_user, $ssi_db_passwd, $db_prefix, $db_persist, $db_error_send, $cache_accelerator;
144
		global $cache_uid, $cache_password, $cache_enable, $cache_memcached, $db_show_debug;
145
		global $cachedir, $boarddir, $sourcedir, $extdir, $languagedir, $ignore_install_dir;
146
147
		// Where the Settings.php file is located
148
		$settings_loc = __DIR__ . '/Settings.php';
149
150
		// First thing: if the install dir exists, just send anybody there
151
		// The ignore_install_dir var is for developers only. Do not add it on production sites
152
		if (file_exists('install') && (file_exists('install/install.php') || file_exists('install/upgrade.php')))
153
		{
154
			if (file_exists($settings_loc))
155
			{
156
				require_once($settings_loc);
157
			}
158
159
			if (empty($ignore_install_dir))
160
			{
161
				if (file_exists($settings_loc) && empty($_SESSION['installing']))
162
				{
163
					$redirec_file = 'upgrade.php';
164
				}
165
				else
166
				{
167
					$redirec_file = 'install.php';
168
				}
169
170
				header('Location: http' . (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) === 'on' ? 's' : '') . '://' . (empty($_SERVER['HTTP_HOST']) ? $_SERVER['SERVER_NAME'] . (empty($_SERVER['SERVER_PORT']) || $_SERVER['SERVER_PORT'] === '80' ? '' : ':' . $_SERVER['SERVER_PORT']) : $_SERVER['HTTP_HOST']) . (strtr(dirname($_SERVER['PHP_SELF']), '\\', '/') == '/' ? '' : strtr(dirname($_SERVER['PHP_SELF']), '\\', '/')) . '/install/' . $redirec_file);
171
				die();
172
			}
173
		}
174
		else
175
		{
176
			require_once($settings_loc);
177
		}
178
	}
179
180
	/**
181
	 * Validate the paths set in Settings.php, correct as needed and move
182
	 * them to constants.
183
	 */
184
	private function validatePaths()
185
	{
186
		global $boarddir, $sourcedir, $cachedir, $extdir, $languagedir;
187
188
		// Make sure the paths are correct... at least try to fix them.
189
		if (!file_exists($boarddir) && file_exists(__DIR__ . '/agreement.txt'))
190
		{
191
			$boarddir = __DIR__;
192
		}
193
194
		if (!file_exists($sourcedir . '/SiteDispatcher.class.php') && file_exists($boarddir . '/sources'))
195
		{
196
			$sourcedir = $boarddir . '/sources';
197
		}
198
199
		// Check that directories which didn't exist in past releases are initialized.
200
		if ((empty($cachedir) || !file_exists($cachedir)) && file_exists($boarddir . '/cache'))
201
		{
202
			$cachedir = $boarddir . '/cache';
203
		}
204
205
		if ((empty($extdir) || !file_exists($extdir)) && file_exists($sourcedir . '/ext'))
206
		{
207
			$extdir = $sourcedir . '/ext';
208
		}
209
210
		if ((empty($languagedir) || !file_exists($languagedir)) && file_exists($boarddir . '/themes/default/languages'))
211
		{
212
			$languagedir = $boarddir . '/themes/default/languages';
213
		}
214
215
		// Time to forget about variables and go with constants!
216
		define('BOARDDIR', $boarddir);
217
		define('CACHEDIR', $cachedir);
218
		define('EXTDIR', $extdir);
219
		define('LANGUAGEDIR', $languagedir);
220
		define('SOURCEDIR', $sourcedir);
221
		define('ADMINDIR', $sourcedir . '/admin');
222
		define('CONTROLLERDIR', $sourcedir . '/controllers');
223
		define('SUBSDIR', $sourcedir . '/subs');
224
		define('ADDONSDIR', $boarddir . '/addons');
225
		unset($boarddir, $cachedir, $sourcedir, $languagedir, $extdir);
226
	}
227
228
	/**
229
	 * We require access to several important files, so load them upfront
230
	 */
231
	private function loadDependants()
232
	{
233
		// Files we cannot live without.
234
		require_once(SOURCEDIR . '/QueryString.php');
235
		require_once(SOURCEDIR . '/Session.php');
236
		require_once(SOURCEDIR . '/Subs.php');
237
		require_once(SOURCEDIR . '/Logging.php');
238
		require_once(SOURCEDIR . '/Load.php');
239
		require_once(SOURCEDIR . '/Security.php');
240
		require_once(SUBSDIR . '/Cache.subs.php');
241
	}
242
243
	/**
244
	 * The autoloader will take care most requests for files
245
	 */
246
	private function loadAutoloader()
247
	{
248
		// Initialize the class Autoloader
249
		require_once(SOURCEDIR . '/Autoloader.class.php');
250
		$autoloader = Elk_Autoloader::instance();
251
		$autoloader->setupAutoloader(array(SOURCEDIR, SUBSDIR, CONTROLLERDIR, ADMINDIR, ADDONSDIR));
252
		$autoloader->register(SOURCEDIR, '\\ElkArte');
253
		$autoloader->register(SOURCEDIR . '/subs/BBC', '\\BBC');
254
	}
255
256
	/**
257
	 * Check if we are in maintance mode, if so end here.
258
	 */
259
	private function checkMaintance()
260
	{
261
		global $maintenance, $ssi_maintenance_off;
262
263
		// Don't do john didley if the forum's been shut down completely.
264
		if (!empty($maintenance) && $maintenance == 2 && (!isset($ssi_maintenance_off) || $ssi_maintenance_off !== true))
265
		{
266
			Errors::instance()->display_maintenance_message();
267
		}
268
	}
269
270
	/**
271
	 * If you like lots of debug information in error messages and below the footer
272
	 * then set $db_show_debug to true in settings.  Don't do this on a production site.
273
	 */
274
	private function setDebug()
275
	{
276
		global $db_show_debug, $rusage_start;
277
278
		// Show lots of debug information below the page, not for production sites
279
		if ($db_show_debug === true)
280
		{
281
			Debug::instance()->rusage('start', $rusage_start);
282
		}
283
	}
284
285
	/**
286
	 * Time to see what has been requested, by whom and dispatch it to the proper handler
287
	 */
288
	private function bringUp()
289
	{
290
		global $context;
291
292
		// Clean the request.
293
		cleanRequest();
294
295
		// Initiate the database connection and define some database functions to use.
296
		loadDatabase();
297
298
		// Let's set up our shiny new hooks handler.
299
		Hooks::init(database(), Debug::instance());
300
301
		// It's time for settings loaded from the database.
302
		reloadSettings();
303
304
		// Our good ole' contextual array, which will hold everything
305
		if (empty($context))
306
		{
307
			$context = array();
308
		}
309
310
		// Seed the random generator.
311
		elk_seed_generator();
0 ignored issues
show
Deprecated Code introduced by
The function elk_seed_generator() has been deprecated. ( Ignorable by Annotation )

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

311
		/** @scrutinizer ignore-deprecated */ elk_seed_generator();
Loading history...
312
	}
313
314
	/**
315
	 * If you are running SSI standalone, you need to call this function after bootstrap is
316
	 * initialized.
317
	 *
318
	 * @throws \Elk_Exception
319
	 */
320
	public function ssi_main()
321
	{
322
		global $ssi_layers, $ssi_theme, $ssi_gzip, $ssi_ban, $ssi_guest_access;
323
		global $modSettings, $context, $sc, $board, $topic, $user_info, $txt;
324
325
		// Check on any hacking attempts.
326
		$this->_validRequestCheck();
327
328
		// Gzip output? (because it must be boolean and true, this can't be hacked.)
329
		if (isset($ssi_gzip) && $ssi_gzip === true && detectServer()->outPutCompressionEnabled())
330
		{
331
			ob_start('ob_gzhandler');
332
		}
333
		else
334
		{
335
			$modSettings['enableCompressedOutput'] = '0';
336
		}
337
338
		// Primarily, this is to fix the URLs...
339
		ob_start('ob_sessrewrite');
340
341
		// Start the session... known to scramble SSI includes in cases...
342
		if (!headers_sent())
343
		{
344
			loadSession();
345
		}
346
		else
347
		{
348
			if (isset($_COOKIE[session_name()]) || isset($_REQUEST[session_name()]))
349
			{
350
				// Make a stab at it, but ignore the E_WARNINGs generated because we can't send headers.
351
				$temp = error_reporting(error_reporting() & !E_WARNING);
352
				loadSession();
353
				error_reporting($temp);
354
			}
355
356
			if (!isset($_SESSION['session_value']))
357
			{
358
				$tokenizer = new Token_Hash();
359
				$_SESSION['session_value'] = $tokenizer->generate_hash(32, session_id());
360
				$_SESSION['session_var'] = substr(preg_replace('~^\d+~', '', $tokenizer->generate_hash(16, session_id())), 0, rand(7, 12));
361
			}
362
363
			$sc = $_SESSION['session_value'];
364
			// This is here only to avoid session errors in PHP7
365
			// microtime effectively forces the replacing of the session in the db each
366
			// time the page is loaded
367
			$_SESSION['mictrotime'] = microtime();
368
		}
369
370
		// Get rid of $board and $topic... do stuff loadBoard would do.
371
		unset($board, $topic);
372
		$user_info['is_mod'] = false;
373
		$context['user']['is_mod'] = &$user_info['is_mod'];
374
		$context['linktree'] = array();
375
376
		// Load the user and their cookie, as well as their settings.
377
		loadUserSettings();
378
379
		// Load the current user's permissions....
380
		loadPermissions();
381
382
		// Load the current or SSI theme. (just use $ssi_theme = id_theme;)
383
		loadTheme(isset($ssi_theme) ? (int) $ssi_theme : 0);
384
385
		// Load BadBehavior functions, but not when running from CLI
386
		if (!defined('STDIN'))
387
		{
388
			loadBadBehavior();
389
		}
390
391
		// @todo: probably not the best place, but somewhere it should be set...
392
		if (!headers_sent())
393
		{
394
			header('Content-Type: text/html; charset=UTF-8');
395
		}
396
397
		// Take care of any banning that needs to be done.
398
		if (isset($_REQUEST['ssi_ban']) || (isset($ssi_ban) && $ssi_ban === true))
399
		{
400
			is_not_banned();
401
		}
402
403
		// Do we allow guests in here?
404
		if (empty($ssi_guest_access) && empty($modSettings['allow_guestAccess']) && $user_info['is_guest'] && basename($_SERVER['PHP_SELF']) !== 'SSI.php')
405
		{
406
			$controller = new Auth_Controller();
407
			$controller->action_kickguest();
408
			obExit(null, true);
409
		}
410
411
		if (!empty($modSettings['front_page']) && is_callable(array($modSettings['front_page'], 'frontPageHook')))
412
		{
413
			$modSettings['default_forum_action'] = '?action=forum;';
414
		}
415
		else
416
		{
417
			$modSettings['default_forum_action'] = '';
418
		}
419
420
		// Load the stuff like the menu bar, etc.
421
		if (isset($ssi_layers))
422
		{
423
			$template_layers = Template_Layers::instance();
424
			$template_layers->removeAll();
425
			foreach ($ssi_layers as $layer)
426
			{
427
				$template_layers->addBegin($layer);
428
			}
429
			template_header();
430
		}
431
		else
432
		{
433
			setupThemeContext();
434
		}
435
436
		// We need to set up user agent, and make more checks on the request
437
		$req = request();
438
439
		// Make sure they didn't muss around with the settings... but only if it's not cli.
440
		if (isset($_SERVER['REMOTE_ADDR']) && session_id() === '')
441
		{
442
			trigger_error($txt['ssi_session_broken'], E_USER_NOTICE);
443
		}
444
445
		// Without visiting the forum this session variable might not be set on submit.
446
		if (!isset($_SESSION['USER_AGENT']) && (!isset($_GET['ssi_function']) || $_GET['ssi_function'] !== 'pollVote'))
447
		{
448
			$_SESSION['USER_AGENT'] = $req->user_agent();
449
		}
450
	}
451
452
	/**
453
	 * Used to ensure SSI requests are valid and not a probing attempt
454
	 */
455
	private function _validRequestCheck()
456
	{
457
		global $ssi_theme, $ssi_layers;
458
459
		if (isset($_REQUEST['ssi_theme']) && (int) $_REQUEST['ssi_theme'] === (int) $ssi_theme)
460
		{
461
			die('No access...');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
462
		}
463
		elseif (isset($_COOKIE['ssi_theme']) && (int) $_COOKIE['ssi_theme'] === (int) $ssi_theme)
464
		{
465
			die('No access...');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
466
		}
467
		elseif (isset($_REQUEST['ssi_layers'], $ssi_layers) && (@get_magic_quotes_gpc() ? stripslashes($_REQUEST['ssi_layers']) : $_REQUEST['ssi_layers']) == $ssi_layers)
468
		{
469
			die('No access...');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
470
		}
471
472
		// Yeah right
473
		if (isset($_REQUEST['context']))
474
		{
475
			die('No access...');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
476
		}
477
	}
478
}
479