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