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.4 |
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.4'); |
96
|
|
|
|
97
|
|
|
// Shortcut for the browser cache stale |
98
|
|
|
define('CACHE_STALE', '?R114'); |
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')) |
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(); |
|
|
|
|
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
|
|
View Code Duplication |
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 |
386
|
|
|
loadBadBehavior(); |
387
|
|
|
|
388
|
|
|
// @todo: probably not the best place, but somewhere it should be set... |
389
|
|
|
if (!headers_sent()) |
390
|
|
|
{ |
391
|
|
|
header('Content-Type: text/html; charset=UTF-8'); |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
// Take care of any banning that needs to be done. |
395
|
|
|
if (isset($_REQUEST['ssi_ban']) || (isset($ssi_ban) && $ssi_ban === true)) |
396
|
|
|
{ |
397
|
|
|
is_not_banned(); |
398
|
|
|
} |
399
|
|
|
|
400
|
|
|
// Do we allow guests in here? |
401
|
|
|
if (empty($ssi_guest_access) && empty($modSettings['allow_guestAccess']) && $user_info['is_guest'] && basename($_SERVER['PHP_SELF']) !== 'SSI.php') |
402
|
|
|
{ |
403
|
|
|
$controller = new Auth_Controller(); |
404
|
|
|
$controller->action_kickguest(); |
405
|
|
|
obExit(null, true); |
406
|
|
|
} |
407
|
|
|
|
408
|
|
|
if (!empty($modSettings['front_page']) && is_callable(array($modSettings['front_page'], 'frontPageHook'))) |
409
|
|
|
{ |
410
|
|
|
$modSettings['default_forum_action'] = '?action=forum;'; |
411
|
|
|
} |
412
|
|
|
else |
413
|
|
|
{ |
414
|
|
|
$modSettings['default_forum_action'] = ''; |
415
|
|
|
} |
416
|
|
|
|
417
|
|
|
// Load the stuff like the menu bar, etc. |
418
|
|
|
if (isset($ssi_layers)) |
419
|
|
|
{ |
420
|
|
|
$template_layers = Template_Layers::instance(); |
421
|
|
|
$template_layers->removeAll(); |
422
|
|
|
foreach ($ssi_layers as $layer) |
423
|
|
|
{ |
424
|
|
|
$template_layers->addBegin($layer); |
425
|
|
|
} |
426
|
|
|
template_header(); |
427
|
|
|
} |
428
|
|
|
else |
429
|
|
|
{ |
430
|
|
|
setupThemeContext(); |
431
|
|
|
} |
432
|
|
|
|
433
|
|
|
// We need to set up user agent, and make more checks on the request |
434
|
|
|
$req = request(); |
435
|
|
|
|
436
|
|
|
// Make sure they didn't muss around with the settings... but only if it's not cli. |
437
|
|
|
if (isset($_SERVER['REMOTE_ADDR']) && session_id() === '') |
438
|
|
|
{ |
439
|
|
|
trigger_error($txt['ssi_session_broken'], E_USER_NOTICE); |
440
|
|
|
} |
441
|
|
|
|
442
|
|
|
// Without visiting the forum this session variable might not be set on submit. |
443
|
|
|
if (!isset($_SESSION['USER_AGENT']) && (!isset($_GET['ssi_function']) || $_GET['ssi_function'] !== 'pollVote')) |
444
|
|
|
{ |
445
|
|
|
$_SESSION['USER_AGENT'] = $req->user_agent(); |
446
|
|
|
} |
447
|
|
|
} |
448
|
|
|
|
449
|
|
|
/** |
450
|
|
|
* Used to ensure SSI requests are valid and not a probing attempt |
451
|
|
|
*/ |
452
|
|
|
private function _validRequestCheck() |
453
|
|
|
{ |
454
|
|
|
global $ssi_theme, $ssi_layers; |
455
|
|
|
|
456
|
|
|
if (isset($_REQUEST['ssi_theme']) && (int) $_REQUEST['ssi_theme'] === (int) $ssi_theme) |
457
|
|
|
{ |
458
|
|
|
die('No access...'); |
|
|
|
|
459
|
|
|
} |
460
|
|
|
elseif (isset($_COOKIE['ssi_theme']) && (int) $_COOKIE['ssi_theme'] === (int) $ssi_theme) |
461
|
|
|
{ |
462
|
|
|
die('No access...'); |
|
|
|
|
463
|
|
|
} |
464
|
|
|
elseif (isset($_REQUEST['ssi_layers'], $ssi_layers) && (@get_magic_quotes_gpc() ? stripslashes($_REQUEST['ssi_layers']) : $_REQUEST['ssi_layers']) == $ssi_layers) |
465
|
|
|
{ |
466
|
|
|
die('No access...'); |
|
|
|
|
467
|
|
|
} |
468
|
|
|
|
469
|
|
|
// Yeah right |
470
|
|
|
if (isset($_REQUEST['context'])) |
471
|
|
|
{ |
472
|
|
|
die('No access...'); |
|
|
|
|
473
|
|
|
} |
474
|
|
|
} |
475
|
|
|
} |
476
|
|
|
|