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
|
|||
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
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.');
}
![]() |
|||
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);
}
}
![]() |
|||
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
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 ![]() |
|||
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 | } |
'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:
For numeric data, we recommend to explicitly cast the data: