Completed
Push — release-2.1 ( a5f46d...d1d1b8 )
by Mert
05:27
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 2015 Simple Machines and individual contributors
18
 * @license http://www.simplemachines.org/about/smf/license.php BSD
19
 *
20
 * @version 2.1 Beta 2
21
 */
22
23
$forum_version = 'SMF 2.1 Beta 2';
24
$software_year = '2015';
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)
0 ignored issues
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'))
0 ignored issues
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
// Displaying attachments.
83
elseif (isset($_GET['action']) && $_GET['action'] == 'dlattach' && isset($_GET['type']) && ($_GET['type'] == 'avatar' || $_GET['type'] == 'preview'))
84
{
85
	require_once($sourcedir. '/ShowAttachments.php');
86
	showAttachment();
87
}
88
89
// And important includes.
90
require_once($sourcedir . '/Session.php');
91
require_once($sourcedir . '/Errors.php');
92
require_once($sourcedir . '/Logging.php');
93
require_once($sourcedir . '/Security.php');
94
require_once($sourcedir . '/Class-BrowserDetect.php');
95
96
// Check if compressed output is enabled, supported, and not already being done.
97
if (!empty($modSettings['enableCompressedOutput']) && !headers_sent())
98
{
99
	// If zlib is being used, turn off output compression.
100 View Code Duplication
	if (ini_get('zlib.output_compression') >=  1 || ini_get('output_handler') == 'ob_gzhandler')
0 ignored issues
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...
101
		$modSettings['enableCompressedOutput'] = '0';
102
	else
103
	{
104
		ob_end_clean();
105
		ob_start('ob_gzhandler');
106
	}
107
}
108
109
// Register an error handler.
110
set_error_handler('smf_error_handler');
111
112
// Start the session. (assuming it hasn't already been.)
113
loadSession();
114
115
// What function shall we execute? (done like this for memory's sake.)
116
call_user_func(smf_main());
117
118
// Call obExit specially; we're coming from the main area ;).
119
obExit(null, null, true);
120
121
/**
122
 * The main dispatcher.
123
 * This delegates to each area.
124
 * @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.
125
 */
126
function smf_main()
127
{
128
	global $modSettings, $settings, $user_info, $board, $topic;
129
	global $board_info, $maintenance, $sourcedir;
130
131
	// Special case: session keep-alive, output a transparent pixel.
132
	if (isset($_GET['action']) && $_GET['action'] == 'keepalive')
133
	{
134
		header('Content-Type: image/gif');
135
		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");
136
	}
137
138
	// We should set our security headers now.
139
	frameOptionsHeader();
140
141
	// Load the user's cookie (or set as guest) and load their settings.
142
	loadUserSettings();
143
144
	// Load the current board's information.
145
	loadBoard();
146
147
	// Load the current user's permissions.
148
	loadPermissions();
149
150
	// Attachments don't require the entire theme to be loaded.
151
	if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'dlattach')
152
		detectBrowser();
153
	// Load the current theme.  (note that ?theme=1 will also work, may be used for guest theming.)
154
	else
155
		loadTheme();
156
157
	// Check if the user should be disallowed access.
158
	is_not_banned();
159
160
	// If we are in a topic and don't have permission to approve it then duck out now.
161
	if (!empty($topic) && empty($board_info['cur_topic_approved']) && !allowedTo('approve_posts') && ($user_info['id'] != $board_info['cur_topic_starter'] || $user_info['is_guest']))
162
		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...
163
164
	$no_stat_actions = array('clock', 'dlattach', 'findmember', 'jsoption', 'likes', 'loadeditorlocale', 'modifycat', 'requestmembers', 'smstats', 'suggest', 'about:unknown', '.xml', 'xmlhttp', 'verificationcode', 'viewquery', 'viewsmfile');
165
	call_integration_hook('integrate_pre_log_stats', array(&$no_stat_actions));
166
	// Do some logging, unless this is an attachment, avatar, toggle of editor buttons, theme option, XML feed etc.
167
	if (empty($_REQUEST['action']) || !in_array($_REQUEST['action'], $no_stat_actions))
168
	{
169
		// Log this user as online.
170
		writeLog();
171
172
		// Track forum statistics and hits...?
173
		if (!empty($modSettings['hitStats']))
174
			trackStats(array('hits' => '+'));
175
	}
176
	unset($no_stat_actions);
177
178
	// Is the forum in maintenance mode? (doesn't apply to administrators.)
179
	if (!empty($maintenance) && !allowedTo('admin_forum'))
180
	{
181
		// You can only login.... otherwise, you're getting the "maintenance mode" display.
182
		if (isset($_REQUEST['action']) && (in_array($_REQUEST['action'], array('login2', 'logintfa', 'logout'))))
183
		{
184
			require_once($sourcedir . '/LogInOut.php');
185
			return ($_REQUEST['action'] == 'login2' ? 'Login2' : ($_REQUEST['action'] == 'logintfa' ? 'LoginTFA' : 'Logout'));
186
		}
187
		// Don't even try it, sonny.
188
		else
189
			return 'InMaintenance';
190
	}
191
	// If guest access is off, a guest can only do one of the very few following actions.
192
	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'))))
193
		return 'KickGuest';
194
	elseif (empty($_REQUEST['action']))
195
	{
196
		// Action and board are both empty... BoardIndex! Unless someone else wants to do something different.
197
		if (empty($board) && empty($topic))
198
		{
199
			$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...
200
201
			if (!empty($modSettings['integrate_default_action']))
202
			{
203
				$defaultAction = explode(',', $modSettings['integrate_default_action']);
204
205
				// Sorry, only one default action is needed.
206
				$defaultAction = $defaultAction[0];
207
208
				$call = call_helper($defaultAction, true);
209
210
				if (!empty($call))
211
					return $call;
212
			}
213
214
			// No default action huh? then go to our good old BoardIndex.
215
			else
216
			{
217
				require_once($sourcedir . '/BoardIndex.php');
218
219
				return 'BoardIndex';
220
			}
221
		}
222
223
		// Topic is empty, and action is empty.... MessageIndex!
224
		elseif (empty($topic))
225
		{
226
			require_once($sourcedir . '/MessageIndex.php');
227
			return 'MessageIndex';
228
		}
229
230
		// Board is not empty... topic is not empty... action is empty.. Display!
231
		else
232
		{
233
			require_once($sourcedir . '/Display.php');
234
			return 'Display';
235
		}
236
	}
237
238
	// Here's the monstrous $_REQUEST['action'] array - $_REQUEST['action'] => array($file, $function).
239
	$actionArray = array(
240
		'activate' => array('Register.php', 'Activate'),
241
		'admin' => array('Admin.php', 'AdminMain'),
242
		'announce' => array('Post.php', 'AnnounceTopic'),
243
		'attachapprove' => array('ManageAttachments.php', 'ApproveAttach'),
244
		'buddy' => array('Subs-Members.php', 'BuddyListToggle'),
245
		'calendar' => array('Calendar.php', 'CalendarMain'),
246
		'clock' => array('Calendar.php', 'clock'),
247
		'coppa' => array('Register.php', 'CoppaForm'),
248
		'credits' => array('Who.php', 'Credits'),
249
		'deletemsg' => array('RemoveTopic.php', 'DeleteMessage'),
250
		'dlattach' => array('Display.php', 'Download'),
251
		'editpoll' => array('Poll.php', 'EditPoll'),
252
		'editpoll2' => array('Poll.php', 'EditPoll2'),
253
		'findmember' => array('Subs-Auth.php', 'JSMembers'),
254
		'groups' => array('Groups.php', 'Groups'),
255
		'help' => array('Help.php', 'ShowHelp'),
256
		'helpadmin' => array('Help.php', 'ShowAdminHelp'),
257
		'jsmodify' => array('Post.php', 'JavaScriptModify'),
258
		'jsoption' => array('Themes.php', 'SetJavaScript'),
259
		'likes' => array('Likes.php', 'Likes::call#'),
260
		'loadeditorlocale' => array('Subs-Editor.php', 'loadLocale'),
261
		'lock' => array('Topic.php', 'LockTopic'),
262
		'lockvoting' => array('Poll.php', 'LockVoting'),
263
		'login' => array('LogInOut.php', 'Login'),
264
		'login2' => array('LogInOut.php', 'Login2'),
265
		'logintfa' => array('LogInOut.php', 'LoginTFA'),
266
		'logout' => array('LogInOut.php', 'Logout'),
267
		'markasread' => array('Subs-Boards.php', 'MarkRead'),
268
		'mergetopics' => array('SplitTopics.php', 'MergeTopics'),
269
		'mlist' => array('Memberlist.php', 'Memberlist'),
270
		'moderate' => array('ModerationCenter.php', 'ModerationMain'),
271
		'modifycat' => array('ManageBoards.php', 'ModifyCat'),
272
		'movetopic' => array('MoveTopic.php', 'MoveTopic'),
273
		'movetopic2' => array('MoveTopic.php', 'MoveTopic2'),
274
		'notify' => array('Notify.php', 'Notify'),
275
		'notifyboard' => array('Notify.php', 'BoardNotify'),
276
		'notifytopic' => array('Notify.php', 'TopicNotify'),
277
		'pm' => array('PersonalMessage.php', 'MessageMain'),
278
		'post' => array('Post.php', 'Post'),
279
		'post2' => array('Post.php', 'Post2'),
280
		'printpage' => array('Printpage.php', 'PrintTopic'),
281
		'profile' => array('Profile.php', 'ModifyProfile'),
282
		'quotefast' => array('Post.php', 'QuoteFast'),
283
		'quickmod' => array('MessageIndex.php', 'QuickModeration'),
284
		'quickmod2' => array('Display.php', 'QuickInTopicModeration'),
285
		'recent' => array('Recent.php', 'RecentPosts'),
286
		'reminder' => array('Reminder.php', 'RemindMe'),
287
		'removepoll' => array('Poll.php', 'RemovePoll'),
288
		'removetopic2' => array('RemoveTopic.php', 'RemoveTopic2'),
289
		'reporttm' => array('ReportToMod.php', 'ReportToModerator'),
290
		'requestmembers' => array('Subs-Auth.php', 'RequestMembers'),
291
		'restoretopic' => array('RemoveTopic.php', 'RestoreTopic'),
292
		'search' => array('Search.php', 'PlushSearch1'),
293
		'search2' => array('Search.php', 'PlushSearch2'),
294
		'sendactivation' => array('Register.php', 'SendActivation'),
295
		'signup' => array('Register.php', 'Register'),
296
		'signup2' => array('Register.php', 'Register2'),
297
		'smstats' => array('Stats.php', 'SMStats'),
298
		'suggest' => array('Subs-Editor.php', 'AutoSuggestHandler'),
299
		'spellcheck' => array('Subs-Post.php', 'SpellCheck'),
300
		'splittopics' => array('SplitTopics.php', 'SplitTopics'),
301
		'stats' => array('Stats.php', 'DisplayStats'),
302
		'sticky' => array('Topic.php', 'Sticky'),
303
		'theme' => array('Themes.php', 'ThemesMain'),
304
		'trackip' => array('Profile-View.php', 'trackIP'),
305
		'about:unknown' => array('Likes.php', 'BookOfUnknown'),
306
		'unread' => array('Recent.php', 'UnreadTopics'),
307
		'unreadreplies' => array('Recent.php', 'UnreadTopics'),
308
		'uploadAttach' => array('Attachments.php', 'Attachments::call#'),
309
		'verificationcode' => array('Register.php', 'VerificationCode'),
310
		'viewprofile' => array('Profile.php', 'ModifyProfile'),
311
		'vote' => array('Poll.php', 'Vote'),
312
		'viewquery' => array('ViewQuery.php', 'ViewQuery'),
313
		'viewsmfile' => array('Admin.php', 'DisplayAdminFile'),
314
		'who' => array('Who.php', 'Who'),
315
		'.xml' => array('News.php', 'ShowXmlFeed'),
316
		'xmlhttp' => array('Xml.php', 'XMLhttpMain'),
317
	);
318
319
	// Allow modifying $actionArray easily.
320
	call_integration_hook('integrate_actions', array(&$actionArray));
321
322
	// Get the function and file to include - if it's not there, do the board index.
323
	if (!isset($_REQUEST['action']) || !isset($actionArray[$_REQUEST['action']]))
324
	{
325
		// Catch the action with the theme?
326
		if (!empty($settings['catch_action']))
327
		{
328
			require_once($sourcedir . '/Themes.php');
329
			return 'WrapAction';
330
		}
331
332
		if (!empty($modSettings['integrate_fallback_action']))
333
		{
334
			$fallbackAction = explode(',', $modSettings['integrate_fallback_action']);
335
336
			// Sorry, only one fallback action is needed.
337
			$fallbackAction = $fallbackAction[0];
338
339
			$call = call_helper($fallbackAction, true);
340
341
			if (!empty($call))
342
				return $call;
343
		}
344
345
		// No fallback action, huh?
346
		else
347
		{
348
			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...
349
		}
350
	}
351
352
	// Otherwise, it was set - so let's go to that action.
353
	require_once($sourcedir . '/' . $actionArray[$_REQUEST['action']][0]);
354
355
	// Do the right thing.
356
	return call_helper($actionArray[$_REQUEST['action']][1], true);
357
}
358
359
?>
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...
360