Completed
Push — release-2.1 ( e49a83...286127 )
by Michael
06:45
created

index.php (8 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 on which SMF functions.
5
 * Everything should start here, so all the setup and security is done
6
 * properly.  The most interesting part of this file is the action array in
7
 * the smf_main() function.  It is formatted as so:
8
 * 	'action-in-url' => array('Source-File.php', 'FunctionToCall'),
9
 *
10
 * Then, you can access the FunctionToCall() function from Source-File.php
11
 * with the URL index.php?action=action-in-url.  Relatively simple, no?
12
 *
13
 * Simple Machines Forum (SMF)
14
 *
15
 * @package SMF
16
 * @author Simple Machines http://www.simplemachines.org
17
 * @copyright 2016 Simple Machines and individual contributors
18
 * @license http://www.simplemachines.org/about/smf/license.php BSD
19
 *
20
 * @version 2.1 Beta 3
21
 */
22
23
$forum_version = 'SMF 2.1 Beta 3';
24
$software_year = '2016';
25
26
// Get everything started up...
27
define('SMF', 1);
28
if (function_exists('set_magic_quotes_runtime') && strnatcmp(phpversion(),'5.3.0') < 0)
29
	@set_magic_quotes_runtime(0);
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...
30
error_reporting(defined('E_STRICT') ? E_ALL | E_STRICT : E_ALL);
31
$time_start = microtime();
32
33
// This makes it so headers can be sent!
34
ob_start();
35
36
// Do some cleaning, just in case.
37 View Code Duplication
foreach (array('db_character_set', 'cachedir') as $variable)
1 ignored issue
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
38
	if (isset($GLOBALS[$variable]))
39
		unset($GLOBALS[$variable], $GLOBALS[$variable]);
40
41
// Load the settings...
42
require_once(dirname(__FILE__) . '/Settings.php');
43
44
// Make absolutely sure the cache directory is defined.
45 View Code Duplication
if ((empty($cachedir) || !file_exists($cachedir)) && file_exists($boarddir . '/cache'))
1 ignored issue
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
46
	$cachedir = $boarddir . '/cache';
47
48
// Without those we can't go anywhere
49
require_once($sourcedir . '/QueryString.php');
50
require_once($sourcedir . '/Subs.php');
51
require_once($sourcedir . '/Subs-Auth.php');
52
require_once($sourcedir . '/Errors.php');
53
require_once($sourcedir . '/Load.php');
54
55
// If $maintenance is set specifically to 2, then we're upgrading or something.
56
if (!empty($maintenance) && $maintenance == 2)
57
	display_maintenance_message();
58
59
// Create a variable to store some SMF specific functions in.
60
$smcFunc = array();
61
62
// Initiate the database connection and define some database functions to use.
63
loadDatabase();
64
65
// Load the settings from the settings table, and perform operations like optimizing.
66
$context = array();
67
reloadSettings();
68
// Clean the request variables, add slashes, etc.
69
cleanRequest();
70
71
// Seed the random generator.
72
if (empty($modSettings['rand_seed']) || mt_rand(1, 250) == 69)
73
	smf_seed_generator();
74
75
// Before we get carried away, are we doing a scheduled task? If so save CPU cycles by jumping out!
76
if (isset($_GET['scheduled']))
77
{
78
	require_once($sourcedir . '/ScheduledTasks.php');
79
	AutoTask();
80
}
81
82
// And important includes.
83
require_once($sourcedir . '/Session.php');
84
require_once($sourcedir . '/Errors.php');
85
require_once($sourcedir . '/Logging.php');
86
require_once($sourcedir . '/Security.php');
87
require_once($sourcedir . '/Class-BrowserDetect.php');
88
89
// Check if compressed output is enabled, supported, and not already being done.
90
if (!empty($modSettings['enableCompressedOutput']) && !headers_sent())
91
{
92
	// If zlib is being used, turn off output compression.
93 View Code Duplication
	if (ini_get('zlib.output_compression') >=  1 || ini_get('output_handler') == 'ob_gzhandler')
1 ignored issue
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
94
		$modSettings['enableCompressedOutput'] = '0';
95
	else
96
	{
97
		ob_end_clean();
98
		ob_start('ob_gzhandler');
99
	}
100
}
101
102
// Register an error handler.
103
set_error_handler('smf_error_handler');
104
105
// Start the session. (assuming it hasn't already been.)
106
loadSession();
107
108
// What function shall we execute? (done like this for memory's sake.)
109
call_user_func(smf_main());
110
111
// Call obExit specially; we're coming from the main area ;).
112
obExit(null, null, true);
113
114
/**
115
 * The main dispatcher.
116
 * This delegates to each area.
117
 * @return array|string|void An array containing the file to include and name of function to call, the name of a function to call or dies with a fatal_lang_error if we couldn't find anything to do.
118
 */
119
function smf_main()
120
{
121
	global $modSettings, $settings, $user_info, $board, $topic;
122
	global $board_info, $maintenance, $sourcedir;
123
124
	// Special case: session keep-alive, output a transparent pixel.
125
	if (isset($_GET['action']) && $_GET['action'] == 'keepalive')
126
	{
127
		header('Content-Type: image/gif');
128
		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");
129
	}
130
131
	// We should set our security headers now.
132
	frameOptionsHeader();
133
134
	// Load the user's cookie (or set as guest) and load their settings.
135
	loadUserSettings();
136
137
	// Load the current board's information.
138
	loadBoard();
139
140
	// Load the current user's permissions.
141
	loadPermissions();
142
143
	// Attachments don't require the entire theme to be loaded.
144
	if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'dlattach')
145
		detectBrowser();
146
	// Load the current theme.  (note that ?theme=1 will also work, may be used for guest theming.)
147
	else
148
		loadTheme();
149
150
	// Check if the user should be disallowed access.
151
	is_not_banned();
152
153
	// If we are in a topic and don't have permission to approve it then duck out now.
154
	if (!empty($topic) && empty($board_info['cur_topic_approved']) && !allowedTo('approve_posts') && ($user_info['id'] != $board_info['cur_topic_starter'] || $user_info['is_guest']))
155
		fatal_lang_error('not_a_topic', false);
0 ignored issues
show
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
156
157
	$no_stat_actions = array('clock', 'dlattach', 'findmember', 'jsoption', 'likes', 'loadeditorlocale', 'modifycat', 'requestmembers', 'smstats', 'suggest', 'about:unknown', '.xml', 'xmlhttp', 'verificationcode', 'viewquery', 'viewsmfile');
158
	call_integration_hook('integrate_pre_log_stats', array(&$no_stat_actions));
159
	// Do some logging, unless this is an attachment, avatar, toggle of editor buttons, theme option, XML feed etc.
160
	if (empty($_REQUEST['action']) || !in_array($_REQUEST['action'], $no_stat_actions))
161
	{
162
		// Log this user as online.
163
		writeLog();
164
165
		// Track forum statistics and hits...?
166
		if (!empty($modSettings['hitStats']))
167
			trackStats(array('hits' => '+'));
168
	}
169
	unset($no_stat_actions);
170
171
	// Is the forum in maintenance mode? (doesn't apply to administrators.)
172
	if (!empty($maintenance) && !allowedTo('admin_forum'))
173
	{
174
		// You can only login.... otherwise, you're getting the "maintenance mode" display.
175
		if (isset($_REQUEST['action']) && (in_array($_REQUEST['action'], array('login2', 'logintfa', 'logout'))))
176
		{
177
			require_once($sourcedir . '/LogInOut.php');
178
			return ($_REQUEST['action'] == 'login2' ? 'Login2' : ($_REQUEST['action'] == 'logintfa' ? 'LoginTFA' : 'Logout'));
179
		}
180
		// Don't even try it, sonny.
181
		else
182
			return 'InMaintenance';
183
	}
184
	// If guest access is off, a guest can only do one of the very few following actions.
185
	elseif (empty($modSettings['allow_guestAccess']) && $user_info['is_guest'] && (!isset($_REQUEST['action']) || !in_array($_REQUEST['action'], array('coppa', 'login', 'login2', 'logintfa', 'reminder', 'activate', 'help', 'helpadmin', 'smstats', 'verificationcode', 'signup', 'signup2'))))
186
		return 'KickGuest';
187
	elseif (empty($_REQUEST['action']))
188
	{
189
		// Action and board are both empty... BoardIndex! Unless someone else wants to do something different.
190
		if (empty($board) && empty($topic))
191
		{
192
			$defaultAction = false;
0 ignored issues
show
$defaultAction is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
193
194
			if (!empty($modSettings['integrate_default_action']))
195
			{
196
				$defaultAction = explode(',', $modSettings['integrate_default_action']);
197
198
				// Sorry, only one default action is needed.
199
				$defaultAction = $defaultAction[0];
200
201
				$call = call_helper($defaultAction, true);
202
203
				if (!empty($call))
204
					return $call;
205
			}
206
207
			// No default action huh? then go to our good old BoardIndex.
208
			else
209
			{
210
				require_once($sourcedir . '/BoardIndex.php');
211
212
				return 'BoardIndex';
213
			}
214
		}
215
216
		// Topic is empty, and action is empty.... MessageIndex!
217
		elseif (empty($topic))
218
		{
219
			require_once($sourcedir . '/MessageIndex.php');
220
			return 'MessageIndex';
221
		}
222
223
		// Board is not empty... topic is not empty... action is empty.. Display!
224
		else
225
		{
226
			require_once($sourcedir . '/Display.php');
227
			return 'Display';
228
		}
229
	}
230
231
	// Here's the monstrous $_REQUEST['action'] array - $_REQUEST['action'] => array($file, $function).
232
	$actionArray = array(
233
		'activate' => array('Register.php', 'Activate'),
234
		'admin' => array('Admin.php', 'AdminMain'),
235
		'announce' => array('Post.php', 'AnnounceTopic'),
236
		'attachapprove' => array('ManageAttachments.php', 'ApproveAttach'),
237
		'buddy' => array('Subs-Members.php', 'BuddyListToggle'),
238
		'calendar' => array('Calendar.php', 'CalendarMain'),
239
		'clock' => array('Calendar.php', 'clock'),
240
		'coppa' => array('Register.php', 'CoppaForm'),
241
		'credits' => array('Who.php', 'Credits'),
242
		'deletemsg' => array('RemoveTopic.php', 'DeleteMessage'),
243
		'dlattach' => array('ShowAttachments.php', 'showAttachment'),
244
		'editpoll' => array('Poll.php', 'EditPoll'),
245
		'editpoll2' => array('Poll.php', 'EditPoll2'),
246
		'findmember' => array('Subs-Auth.php', 'JSMembers'),
247
		'groups' => array('Groups.php', 'Groups'),
248
		'help' => array('Help.php', 'ShowHelp'),
249
		'helpadmin' => array('Help.php', 'ShowAdminHelp'),
250
		'jsmodify' => array('Post.php', 'JavaScriptModify'),
251
		'jsoption' => array('Themes.php', 'SetJavaScript'),
252
		'likes' => array('Likes.php', 'Likes::call#'),
253
		'loadeditorlocale' => array('Subs-Editor.php', 'loadLocale'),
254
		'lock' => array('Topic.php', 'LockTopic'),
255
		'lockvoting' => array('Poll.php', 'LockVoting'),
256
		'login' => array('LogInOut.php', 'Login'),
257
		'login2' => array('LogInOut.php', 'Login2'),
258
		'logintfa' => array('LogInOut.php', 'LoginTFA'),
259
		'logout' => array('LogInOut.php', 'Logout'),
260
		'markasread' => array('Subs-Boards.php', 'MarkRead'),
261
		'mergetopics' => array('SplitTopics.php', 'MergeTopics'),
262
		'mlist' => array('Memberlist.php', 'Memberlist'),
263
		'moderate' => array('ModerationCenter.php', 'ModerationMain'),
264
		'modifycat' => array('ManageBoards.php', 'ModifyCat'),
265
		'movetopic' => array('MoveTopic.php', 'MoveTopic'),
266
		'movetopic2' => array('MoveTopic.php', 'MoveTopic2'),
267
		'notify' => array('Notify.php', 'Notify'),
268
		'notifyboard' => array('Notify.php', 'BoardNotify'),
269
		'notifytopic' => array('Notify.php', 'TopicNotify'),
270
		'pm' => array('PersonalMessage.php', 'MessageMain'),
271
		'post' => array('Post.php', 'Post'),
272
		'post2' => array('Post.php', 'Post2'),
273
		'printpage' => array('Printpage.php', 'PrintTopic'),
274
		'profile' => array('Profile.php', 'ModifyProfile'),
275
		'quotefast' => array('Post.php', 'QuoteFast'),
276
		'quickmod' => array('MessageIndex.php', 'QuickModeration'),
277
		'quickmod2' => array('Display.php', 'QuickInTopicModeration'),
278
		'recent' => array('Recent.php', 'RecentPosts'),
279
		'reminder' => array('Reminder.php', 'RemindMe'),
280
		'removepoll' => array('Poll.php', 'RemovePoll'),
281
		'removetopic2' => array('RemoveTopic.php', 'RemoveTopic2'),
282
		'reporttm' => array('ReportToMod.php', 'ReportToModerator'),
283
		'requestmembers' => array('Subs-Auth.php', 'RequestMembers'),
284
		'restoretopic' => array('RemoveTopic.php', 'RestoreTopic'),
285
		'search' => array('Search.php', 'PlushSearch1'),
286
		'search2' => array('Search.php', 'PlushSearch2'),
287
		'sendactivation' => array('Register.php', 'SendActivation'),
288
		'signup' => array('Register.php', 'Register'),
289
		'signup2' => array('Register.php', 'Register2'),
290
		'smstats' => array('Stats.php', 'SMStats'),
291
		'suggest' => array('Subs-Editor.php', 'AutoSuggestHandler'),
292
		'spellcheck' => array('Subs-Post.php', 'SpellCheck'),
293
		'splittopics' => array('SplitTopics.php', 'SplitTopics'),
294
		'stats' => array('Stats.php', 'DisplayStats'),
295
		'sticky' => array('Topic.php', 'Sticky'),
296
		'theme' => array('Themes.php', 'ThemesMain'),
297
		'trackip' => array('Profile-View.php', 'trackIP'),
298
		'about:unknown' => array('Likes.php', 'BookOfUnknown'),
299
		'unread' => array('Recent.php', 'UnreadTopics'),
300
		'unreadreplies' => array('Recent.php', 'UnreadTopics'),
301
		'uploadAttach' => array('Attachments.php', 'Attachments::call#'),
302
		'verificationcode' => array('Register.php', 'VerificationCode'),
303
		'viewprofile' => array('Profile.php', 'ModifyProfile'),
304
		'vote' => array('Poll.php', 'Vote'),
305
		'viewquery' => array('ViewQuery.php', 'ViewQuery'),
306
		'viewsmfile' => array('Admin.php', 'DisplayAdminFile'),
307
		'who' => array('Who.php', 'Who'),
308
		'.xml' => array('News.php', 'ShowXmlFeed'),
309
		'xmlhttp' => array('Xml.php', 'XMLhttpMain'),
310
	);
311
312
	// Allow modifying $actionArray easily.
313
	call_integration_hook('integrate_actions', array(&$actionArray));
314
315
	// Get the function and file to include - if it's not there, do the board index.
316
	if (!isset($_REQUEST['action']) || !isset($actionArray[$_REQUEST['action']]))
317
	{
318
		// Catch the action with the theme?
319
		if (!empty($settings['catch_action']))
320
		{
321
			require_once($sourcedir . '/Themes.php');
322
			return 'WrapAction';
323
		}
324
325
		if (!empty($modSettings['integrate_fallback_action']))
326
		{
327
			$fallbackAction = explode(',', $modSettings['integrate_fallback_action']);
328
329
			// Sorry, only one fallback action is needed.
330
			$fallbackAction = $fallbackAction[0];
331
332
			$call = call_helper($fallbackAction, true);
333
334
			if (!empty($call))
335
				return $call;
336
		}
337
338
		// No fallback action, huh?
339
		else
340
		{
341
			fatal_lang_error('not_found', false, array(), 404);
0 ignored issues
show
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
342
		}
343
	}
344
345
	// Otherwise, it was set - so let's go to that action.
346
	require_once($sourcedir . '/' . $actionArray[$_REQUEST['action']][0]);
347
348
	// Do the right thing.
349
	return call_helper($actionArray[$_REQUEST['action']][1], true);
350
}
351
352
?>
0 ignored issues
show
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
353