Completed
Pull Request — development (#2316)
by Joshua
09:55
created

index.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * This, as you have probably guessed, is the crux for all functions.
5
 * Everything should start here, so all the setup and security is done
6
 * properly.
7
 *
8
 * @name      ElkArte Forum
9
 * @copyright ElkArte Forum contributors
10
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
11
 *
12
 * This software is a derived product, based on:
13
 *
14
 * Simple Machines Forum (SMF)
15
 * copyright:	2011 Simple Machines (http://www.simplemachines.org)
16
 * license:		BSD, See included LICENSE.TXT for terms and conditions.
17
 *
18
 * @version 1.1 dev
19
 *
20
 */
21
22
$time_start = microtime(true);
23
24
// The software version
25
const FORUM_VERSION = 'ElkArte 1.1';
26
27
// First things first, but not necessarily in that order.
28
const ELK = '1';
29
30
// Shortcut for the browser cache stale
31
const CACHE_STALE = '?R11';
32
33
// Report errors but not depreciated ones
34
error_reporting(E_ALL | E_STRICT & ~8192);
35
36
// Directional only script time usage for display
37
if (function_exists('getrusage'))
38
	$rusage_start = getrusage();
39
else
40
	$rusage_start = array();
41
42
// Turn on output buffering if it isn't already on (via php.ini for example)
43
if (!ob_get_level())
44
	ob_start();
45
46
$db_show_debug = false;
47
48
// We don't need no globals. (a bug in "old" versions of PHP)
49
foreach (array('db_character_set', 'cachedir') as $variable)
50
	if (isset($GLOBALS[$variable]))
51
		unset($GLOBALS[$variable], $GLOBALS[$variable]);
52
53
// Where the Settings.php file is located
54
$settings_loc = 'Settings.php';
55
56
// First thing: if the install dir exists, just send anybody there
57
if (file_exists('install'))
58
{
59
	if (file_exists($settings_loc))
60
	{
61
		require_once($settings_loc);
62
	}
63
64
	// The ignore_install_dir var is for developers only. Do not add it on production sites
65
	if (empty($ignore_install_dir))
66
	{
67
		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/install.php');
0 ignored issues
show
Security Response Splitting introduced by
'Location: http' . (!emp... '/install/install.php' can contain request data and is used in response header context(s) leading to a potential security vulnerability.

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
68
		die;
69
	}
70
}
71
else
72
{
73
	require_once($settings_loc);
74
}
75
76
77
// Make sure the paths are correct... at least try to fix them.
78
if (!file_exists($boarddir) && file_exists('agreement.txt'))
79
	$boarddir = __DIR__;
80
if (!file_exists($sourcedir . '/SiteDispatcher.class.php') && file_exists($boarddir . '/sources'))
81
	$sourcedir = $boarddir . '/sources';
82
83
// Check that directories which didn't exist in past releases are initialized.
84
if ((empty($cachedir) || !file_exists($cachedir)) && file_exists($boarddir . '/cache'))
85
	$cachedir = $boarddir . '/cache';
86
if ((empty($extdir) || !file_exists($extdir)) && file_exists($sourcedir . '/ext'))
87
	$extdir = $sourcedir . '/ext';
88
if ((empty($languagedir) || !file_exists($languagedir)) && file_exists($boarddir . '/themes/default/languages'))
89
	$languagedir = $boarddir . '/themes/default/languages';
90
91
// Time to forget about variables and go with constants!
92
DEFINE('BOARDDIR', $boarddir);
93
DEFINE('CACHEDIR', $cachedir);
94
DEFINE('EXTDIR', $extdir);
95
DEFINE('LANGUAGEDIR', $languagedir);
96
DEFINE('SOURCEDIR', $sourcedir);
97
DEFINE('ADMINDIR', $sourcedir . '/admin');
98
DEFINE('CONTROLLERDIR', $sourcedir . '/controllers');
99
DEFINE('SUBSDIR', $sourcedir . '/subs');
100
DEFINE('ADDONSDIR', $boarddir . '/addons');
101
unset($boarddir, $cachedir, $sourcedir, $languagedir, $extdir);
102
103
// Files we cannot live without.
104
require_once(SOURCEDIR . '/QueryString.php');
105
require_once(SOURCEDIR . '/Session.php');
106
require_once(SOURCEDIR . '/Subs.php');
107
require_once(SOURCEDIR . '/Logging.php');
108
require_once(SOURCEDIR . '/Load.php');
109
require_once(SOURCEDIR . '/Security.php');
110
require_once(SUBSDIR . '/Cache.subs.php');
111
112
// Initialize the class Autoloader
113
require(SOURCEDIR . '/Autoloader.class.php');
114
$autoloder = Elk_Autoloader::getInstance();
115
$autoloder->setupAutoloader(array(SOURCEDIR, SUBSDIR, CONTROLLERDIR, ADMINDIR, ADDONSDIR));
116
$autoloder->register(SOURCEDIR, '\\ElkArte');
117
118
// Show lots of debug information below the page, not for production sites
119
if ($db_show_debug === true)
120
	Debug::get()->rusage('start', $rusage_start);
121
122
// Forum in extended maintenance mode? Our trip ends here with a bland message.
123
if (!empty($maintenance) && $maintenance == 2)
124
	Errors::instance()->display_maintenance_message();
125
126
// Clean the request.
127
cleanRequest();
128
129
// Initiate the database connection and define some database functions to use.
130
loadDatabase();
131
132
// Let's set up out shiny new hooks handler.
133
Hooks::init(database(), Debug::get());
134
135
// It's time for settings loaded from the database.
136
reloadSettings();
137
138
// Our good ole' contextual array, which will hold everything
139
$context = array();
140
141
// Seed the random generator.
142
elk_seed_generator();
143
144
// Before we get carried away, are we doing a scheduled task? If so save CPU cycles by jumping out!
145
if (isset($_GET['scheduled']))
146
{
147
	// Don't make people wait on us if we can help it.
148
	if (function_exists('fastcgi_finish_request'))
149
		fastcgi_finish_request();
150
151
	$controller = new ScheduledTasks_Controller();
152
	$controller->action_autotask();
153
}
154
155
// Check if compressed output is enabled, supported, and not already being done.
156
if (!empty($modSettings['enableCompressedOutput']) && !headers_sent())
157
{
158
	// If zlib is being used, turn off output compression.
159
	if (ini_get('zlib.output_compression') >= 1 || ini_get('output_handler') == 'ob_gzhandler')
160
		$modSettings['enableCompressedOutput'] = 0;
161
	else
162
	{
163
		@ob_end_clean();
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
164
		ob_start('ob_gzhandler');
165
	}
166
}
167
168
// Register error & exception handlers.
169
Errors::instance()->register_handlers();
170
171
// Start the session. (assuming it hasn't already been.)
172
loadSession();
173
174
// Restore post data if we are revalidating OpenID.
175
if (isset($_GET['openid_restore_post']) && !empty($_SESSION['openid']['saved_data'][$_GET['openid_restore_post']]['post']) && empty($_POST))
176
{
177
	$_POST = $_SESSION['openid']['saved_data'][$_GET['openid_restore_post']]['post'];
178
	unset($_SESSION['openid']['saved_data'][$_GET['openid_restore_post']]);
179
}
180
181
// Pre-dispatch
182
elk_main();
183
184
// Call obExit specially; we're coming from the main area ;).
185
obExit(null, null, true);
186
187
/**
188
 * The main dispatcher.
189
 * This delegates to each area.
190
 */
191
function elk_main()
0 ignored issues
show
elk_main uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
192
{
193
	global $modSettings, $user_info, $topic, $board_info, $context, $maintenance;
194
195
	$_req = HttpReq::instance();
196
197
	// Special case: session keep-alive, output a transparent pixel.
198
	if ($_req->getQuery('action') === 'keepalive')
199
	{
200
		header('Content-Type: image/gif');
201
		die("\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x21\xF9\x04\x01\x00\x00\x00\x00\x2C\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x44\x01\x00\x3B");
0 ignored issues
show
Coding Style Compatibility introduced by
The function elk_main() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
202
	}
203
204
	// We should set our security headers now.
205
	frameOptionsHeader();
206
	securityOptionsHeader();
207
208
	// Load the user's cookie (or set as guest) and load their settings.
209
	loadUserSettings();
210
211
	// Load the current board's information.
212
	loadBoard();
213
214
	// Load the current user's permissions.
215
	loadPermissions();
216
217
	// Load BadBehavior before we go much further
218
	loadBadBehavior();
219
220
	// Attachments don't require the entire theme to be loaded.
221
	if ($_req->getQuery('action') === 'dlattach' && (!empty($modSettings['allow_guestAccess']) && $user_info['is_guest']) && (empty($maintenance) || allowedTo('admin_forum')))
222
		detectBrowser();
223
	// Load the current theme.  (note that ?theme=1 will also work, may be used for guest theming.)
224
	else
225
		loadTheme();
226
227
	loadBBCParsers();
228
229
	// Check if the user should be disallowed access.
230
	is_not_banned();
231
232
	// If we are in a topic and don't have permission to approve it then duck out now.
233
	if (!empty($topic) && empty($board_info['cur_topic_approved']) && !allowedTo('approve_posts') && ($user_info['id'] != $board_info['cur_topic_starter'] || $user_info['is_guest']))
234
		Errors::instance()->fatal_lang_error('not_a_topic', false);
235
236
	$no_stat_actions = array('dlattach', 'jsoption', 'requestmembers', 'jslocale', 'xmlpreview', 'suggest', '.xml', 'xmlhttp', 'verificationcode', 'viewquery', 'viewadminfile');
237
	call_integration_hook('integrate_pre_log_stats', array(&$no_stat_actions));
238
239
	// Do some logging, unless this is an attachment, avatar, toggle of editor buttons, theme option, XML feed etc.
240
	if (empty($_REQUEST['action']) || !in_array($_REQUEST['action'], $no_stat_actions)
241
		|| (!empty($_REQUEST['sa']) && !in_array($_REQUEST['sa'], $no_stat_actions)))
242
	{
243
		// I see you!
244
		writeLog();
245
246
		// Track forum statistics and hits...?
247
		if (!empty($modSettings['hitStats']))
248
			trackStats(array('hits' => '+'));
249
	}
250
	unset($no_stat_actions);
251
252
	// What shall we do?
253
	$dispatcher = new Site_Dispatcher();
254
255
	// Show where we came from, and go
256
	$context['site_action'] = $dispatcher->site_action();
257
	$context['site_action'] = !empty($context['site_action']) ? $context['site_action'] : (isset($_REQUEST['action']) ? $_REQUEST['action'] : '');
258
	$dispatcher->dispatch();
259
}