~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to www/php/phpBB3/includes/session.php

Modified the database so that exercises are now stored in the database, rather
than in flat files.

This also necessitated adding new tables and storm classes for test suites
and test cases.

Note that this commit merely changes the database and adds a script to
upload exercises. The code for actually reading exercises has yet
to be changed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
*
 
4
* @package phpBB3
 
5
* @version $Id: session.php,v 1.317 2007/11/04 12:07:46 acydburn Exp $
 
6
* @copyright (c) 2005 phpBB Group
 
7
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
 
8
*
 
9
*/
 
10
 
 
11
/**
 
12
* @ignore
 
13
*/
 
14
if (!defined('IN_PHPBB'))
 
15
{
 
16
        exit;
 
17
}
 
18
 
 
19
/**
 
20
* Session class
 
21
* @package phpBB3
 
22
*/
 
23
class session
 
24
{
 
25
        var $cookie_data = array();
 
26
        var $page = array();
 
27
        var $data = array();
 
28
        var $browser = '';
 
29
        var $forwarded_for = '';
 
30
        var $host = '';
 
31
        var $session_id = '';
 
32
        var $ip = '';
 
33
        var $load = 0;
 
34
        var $time_now = 0;
 
35
        var $update_session_page = true;
 
36
 
 
37
        /**
 
38
        * Extract current session page
 
39
        *
 
40
        * @param string $root_path current root path (phpbb_root_path)
 
41
        */
 
42
        function extract_current_page($root_path)
 
43
        {
 
44
                $page_array = array();
 
45
 
 
46
                // First of all, get the request uri...
 
47
                $script_name = (!empty($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : getenv('PHP_SELF');
 
48
                $args = (!empty($_SERVER['QUERY_STRING'])) ? explode('&', $_SERVER['QUERY_STRING']) : explode('&', getenv('QUERY_STRING'));
 
49
 
 
50
                // If we are unable to get the script name we use REQUEST_URI as a failover and note it within the page array for easier support...
 
51
                if (!$script_name)
 
52
                {
 
53
                        $script_name = (!empty($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : getenv('REQUEST_URI');
 
54
                        $script_name = (($pos = strpos($script_name, '?')) !== false) ? substr($script_name, 0, $pos) : $script_name;
 
55
                        $page_array['failover'] = 1;
 
56
                }
 
57
 
 
58
                // Replace backslashes and doubled slashes (could happen on some proxy setups)
 
59
                $script_name = str_replace(array('\\', '//'), '/', $script_name);
 
60
 
 
61
                // Now, remove the sid and let us get a clean query string...
 
62
                $use_args = array();
 
63
 
 
64
                // Since some browser do not encode correctly we need to do this with some "special" characters...
 
65
                // " -> %22, ' => %27, < -> %3C, > -> %3E
 
66
                $find = array('"', "'", '<', '>');
 
67
                $replace = array('%22', '%27', '%3C', '%3E');
 
68
 
 
69
                foreach ($args as $key => $argument)
 
70
                {
 
71
                        if (strpos($argument, 'sid=') === 0 || strpos($argument, '_f_=') === 0)
 
72
                        {
 
73
                                continue;
 
74
                        }
 
75
 
 
76
                        $use_args[str_replace($find, $replace, $key)] = str_replace($find, $replace, $argument);
 
77
                }
 
78
                unset($args);
 
79
 
 
80
                // The following examples given are for an request uri of {path to the phpbb directory}/adm/index.php?i=10&b=2
 
81
 
 
82
                // The current query string
 
83
                $query_string = trim(implode('&', $use_args));
 
84
 
 
85
                // basenamed page name (for example: index.php)
 
86
                $page_name = basename($script_name);
 
87
                $page_name = urlencode(htmlspecialchars($page_name));
 
88
 
 
89
                // current directory within the phpBB root (for example: adm)
 
90
                $root_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($root_path)));
 
91
                $page_dirs = explode('/', str_replace('\\', '/', phpbb_realpath('./')));
 
92
                $intersection = array_intersect_assoc($root_dirs, $page_dirs);
 
93
 
 
94
                $root_dirs = array_diff_assoc($root_dirs, $intersection);
 
95
                $page_dirs = array_diff_assoc($page_dirs, $intersection);
 
96
 
 
97
                $page_dir = str_repeat('../', sizeof($root_dirs)) . implode('/', $page_dirs);
 
98
 
 
99
                if ($page_dir && substr($page_dir, -1, 1) == '/')
 
100
                {
 
101
                        $page_dir = substr($page_dir, 0, -1);
 
102
                }
 
103
 
 
104
                // Current page from phpBB root (for example: adm/index.php?i=10&b=2)
 
105
                $page = (($page_dir) ? $page_dir . '/' : '') . $page_name . (($query_string) ? "?$query_string" : '');
 
106
 
 
107
                // The script path from the webroot to the current directory (for example: /phpBB3/adm/) : always prefixed with / and ends in /
 
108
                $script_path = trim(str_replace('\\', '/', dirname($script_name)));
 
109
 
 
110
                // The script path from the webroot to the phpBB root (for example: /phpBB3/)
 
111
                $script_dirs = explode('/', $script_path);
 
112
                array_splice($script_dirs, -sizeof($page_dirs));
 
113
                $root_script_path = implode('/', $script_dirs) . (sizeof($root_dirs) ? '/' . implode('/', $root_dirs) : '');
 
114
 
 
115
                // We are on the base level (phpBB root == webroot), lets adjust the variables a bit...
 
116
                if (!$root_script_path)
 
117
                {
 
118
                        $root_script_path = ($page_dir) ? str_replace($page_dir, '', $script_path) : $script_path;
 
119
                }
 
120
 
 
121
                $script_path .= (substr($script_path, -1, 1) == '/') ? '' : '/';
 
122
                $root_script_path .= (substr($root_script_path, -1, 1) == '/') ? '' : '/';
 
123
 
 
124
                $page_array += array(
 
125
                        'page_name'                     => $page_name,
 
126
                        'page_dir'                      => $page_dir,
 
127
 
 
128
                        'query_string'          => $query_string,
 
129
                        'script_path'           => str_replace(' ', '%20', htmlspecialchars($script_path)),
 
130
                        'root_script_path'      => str_replace(' ', '%20', htmlspecialchars($root_script_path)),
 
131
 
 
132
                        'page'                          => $page
 
133
                );
 
134
 
 
135
                return $page_array;
 
136
        }
 
137
 
 
138
        /**
 
139
        * Start session management
 
140
        *
 
141
        * This is where all session activity begins. We gather various pieces of
 
142
        * information from the client and server. We test to see if a session already
 
143
        * exists. If it does, fine and dandy. If it doesn't we'll go on to create a
 
144
        * new one ... pretty logical heh? We also examine the system load (if we're
 
145
        * running on a system which makes such information readily available) and
 
146
        * halt if it's above an admin definable limit.
 
147
        *
 
148
        * @param bool $update_session_page if true the session page gets updated.
 
149
        *                       This can be set to circumvent certain scripts to update the users last visited page.
 
150
        */
 
151
        function session_begin($update_session_page = true)
 
152
        {
 
153
                global $phpEx, $SID, $_SID, $_EXTRA_URL, $db, $config, $phpbb_root_path;
 
154
 
 
155
                // Give us some basic information
 
156
                $this->time_now                         = time();
 
157
                $this->cookie_data                      = array('u' => 0, 'k' => '');
 
158
                $this->update_session_page      = $update_session_page;
 
159
                $this->browser                          = (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((string) $_SERVER['HTTP_USER_AGENT']) : '';
 
160
                $this->forwarded_for            = (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) ? (string) $_SERVER['HTTP_X_FORWARDED_FOR'] : '';
 
161
                $this->host                                     = (!empty($_SERVER['HTTP_HOST'])) ? (string) $_SERVER['HTTP_HOST'] : 'localhost';
 
162
                $this->page                                     = $this->extract_current_page($phpbb_root_path);
 
163
 
 
164
                // if the forwarded for header shall be checked we have to validate its contents
 
165
                if ($config['forwarded_for_check'])
 
166
                {
 
167
                        $this->forwarded_for = preg_replace('#, +#', ', ', $this->forwarded_for);
 
168
 
 
169
                        // split the list of IPs
 
170
                        $ips = explode(', ', $this->forwarded_for);
 
171
                        foreach ($ips as $ip)
 
172
                        {
 
173
                                // check IPv4 first, the IPv6 is hopefully only going to be used very seldomly
 
174
                                if (!empty($ip) && !preg_match(get_preg_expression('ipv4'), $ip) && !preg_match(get_preg_expression('ipv6'), $ip))
 
175
                                {
 
176
                                        // contains invalid data, don't use the forwarded for header
 
177
                                        $this->forwarded_for = '';
 
178
                                        break;
 
179
                                }
 
180
                        }
 
181
                }
 
182
 
 
183
                // Add forum to the page for tracking online users - also adding a "x" to the end to properly identify the number
 
184
                $this->page['page'] .= (isset($_REQUEST['f'])) ? ((strpos($this->page['page'], '?') !== false) ? '&' : '?') . '_f_=' . (int) $_REQUEST['f'] . 'x' : '';
 
185
 
 
186
        
 
187
        if (isset($_COOKIE[$config['cookie_name'] . '_sid']) || 
 
188
        isset($_COOKIE[$config['cookie_name'] . '_u']))
 
189
        {
 
190
          $this->cookie_data['u'] = request_var($config['cookie_name'] . '_u', 0, 
 
191
          false, true);
 
192
          $this->cookie_data['k'] = request_var($config['cookie_name'] . '_k', '', 
 
193
          false, true);
 
194
          $this->session_id             = request_var($config['cookie_name'] . '_sid', '', 
 
195
          false, true);
 
196
 
 
197
          $SID = (defined('NEED_SID')) ? '?sid=' . $this->session_id : '?sid=';
 
198
          $_SID = (defined('NEED_SID')) ? $this->session_id : '';
 
199
 
 
200
          if (empty($this->session_id))
 
201
          {
 
202
                $this->session_id = $_SID = request_var('sid', '');
 
203
                $SID = '?sid=' . $this->session_id;
 
204
                $this->cookie_data = array('u' => 0, 'k' => '');
 
205
          }
 
206
        }
 
207
        else
 
208
        {
 
209
          $this->session_id = $_SID = request_var('sid', '');
 
210
          $SID = '?sid=' . $this->session_id;
 
211
        }
 
212
 
 
213
                $_EXTRA_URL = array();
 
214
 
 
215
                // Why no forwarded_for et al? Well, too easily spoofed. With the results of my recent requests
 
216
                // it's pretty clear that in the majority of cases you'll at least be left with a proxy/cache ip.
 
217
                $this->ip = (!empty($_SERVER['REMOTE_ADDR'])) ? htmlspecialchars($_SERVER['REMOTE_ADDR']) : '';
 
218
                $this->load = false;
 
219
 
 
220
                // Load limit check (if applicable)
 
221
                if ($config['limit_load'] || $config['limit_search_load'])
 
222
                {
 
223
                        if ($load = @file_get_contents('/proc/loadavg'))
 
224
                        {
 
225
                                $this->load = array_slice(explode(' ', $load), 0, 1);
 
226
                                $this->load = floatval($this->load[0]);
 
227
                        }
 
228
                        else
 
229
                        {
 
230
                                set_config('limit_load', '0');
 
231
                                set_config('limit_search_load', '0');
 
232
                        }
 
233
                }
 
234
 
 
235
                // Is session_id is set or session_id is set and matches the url param if required
 
236
                if (!empty($this->session_id) && (!defined('NEED_SID') || (isset($_GET['sid']) && $this->session_id === $_GET['sid'])))
 
237
                {
 
238
                        $sql = 'SELECT u.*, s.*
 
239
                                FROM ' . SESSIONS_TABLE . ' s, ' . USERS_TABLE . " u
 
240
                                WHERE s.session_id = '" . $db->sql_escape($this->session_id) . "'
 
241
                                        AND u.user_id = s.session_user_id";
 
242
          $result = $db->sql_query($sql);
 
243
                        $this->data = $db->sql_fetchrow($result);
 
244
                        $db->sql_freeresult($result);
 
245
 
 
246
          // IVLE
 
247
          $ivle_userid = $this->ivle_auth();
 
248
          if ($ivle_userid and $ivle_userid != $this->data['user_id']) {
 
249
                #$this->session_kill();
 
250
                #trigger_error($ivle_userid);
 
251
                return $this->session_create($ivle_userid);
 
252
          }
 
253
 
 
254
                        // Did the session exist in the DB?
 
255
                        if (isset($this->data['user_id']))
 
256
                        {
 
257
                                // Validate IP length according to admin ... enforces an IP
 
258
                                // check on bots if admin requires this
 
259
                                // $quadcheck = ($config['ip_check_bot'] && $this->data['user_type'] & USER_BOT) ? 4 : $config['ip_check'];
 
260
 
 
261
                                if (strpos($this->ip, ':') !== false && strpos($this->data['session_ip'], ':') !== false)
 
262
                                {
 
263
                                        $s_ip = short_ipv6($this->data['session_ip'], $config['ip_check']);
 
264
                                        $u_ip = short_ipv6($this->ip, $config['ip_check']);
 
265
                                }
 
266
                                else
 
267
                                {
 
268
                                        $s_ip = implode('.', array_slice(explode('.', $this->data['session_ip']), 0, $config['ip_check']));
 
269
                                        $u_ip = implode('.', array_slice(explode('.', $this->ip), 0, $config['ip_check']));
 
270
                                }
 
271
 
 
272
                                $s_browser = ($config['browser_check']) ? strtolower(substr($this->data['session_browser'], 0, 149)) : '';
 
273
                                $u_browser = ($config['browser_check']) ? strtolower(substr($this->browser, 0, 149)) : '';
 
274
 
 
275
                                $s_forwarded_for = ($config['forwarded_for_check']) ? substr($this->data['session_forwarded_for'], 0, 254) : '';
 
276
                                $u_forwarded_for = ($config['forwarded_for_check']) ? substr($this->forwarded_for, 0, 254) : '';
 
277
 
 
278
                                if ($u_ip === $s_ip && $s_browser === $u_browser && $s_forwarded_for === $u_forwarded_for)
 
279
                                {
 
280
                                        $session_expired = false;
 
281
 
 
282
                                        // Check whether the session is still valid if we have one
 
283
                                        $method = basename(trim($config['auth_method']));
 
284
                                        include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx);
 
285
 
 
286
                                        $method = 'validate_session_' . $method;
 
287
                                        if (function_exists($method))
 
288
                                        {
 
289
                                                if (!$method($this->data))
 
290
                                                {
 
291
                                                        $session_expired = true;
 
292
                                                }
 
293
                                        }
 
294
 
 
295
                                        if (!$session_expired)
 
296
                                        {
 
297
                                                // Check the session length timeframe if autologin is not enabled.
 
298
                                                // Else check the autologin length... and also removing those having autologin enabled but no longer allowed board-wide.
 
299
                                                if (!$this->data['session_autologin'])
 
300
                                                {
 
301
                                                        if ($this->data['session_time'] < $this->time_now - ($config['session_length'] + 60))
 
302
                                                        {
 
303
                                                                $session_expired = true;
 
304
                                                        }
 
305
                                                }
 
306
                                                else if (!$config['allow_autologin'] || ($config['max_autologin_time'] && $this->data['session_time'] < $this->time_now - (86400 * (int) $config['max_autologin_time']) + 60))
 
307
                                                {
 
308
                                                        $session_expired = true;
 
309
                                                }
 
310
                                        }
 
311
 
 
312
                                        if (!$session_expired)
 
313
                                        {
 
314
                                                // Only update session DB a minute or so after last update or if page changes
 
315
                                                if ($this->time_now - $this->data['session_time'] > 60 || ($this->update_session_page && $this->data['session_page'] != $this->page['page']))
 
316
                                                {
 
317
                                                        $sql_ary = array('session_time' => $this->time_now);
 
318
 
 
319
                                                        if ($this->update_session_page)
 
320
                                                        {
 
321
                                                                $sql_ary['session_page'] = substr($this->page['page'], 0, 199);
 
322
                                                        }
 
323
 
 
324
                                                        $sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
 
325
                                                                WHERE session_id = '" . $db->sql_escape($this->session_id) . "'";
 
326
                                                        $db->sql_query($sql);
 
327
                                                }
 
328
 
 
329
                                                $this->data['is_registered'] = ($this->data['user_id'] != ANONYMOUS && ($this->data['user_type'] == USER_NORMAL || $this->data['user_type'] == USER_FOUNDER)) ? true : false;
 
330
                                                $this->data['is_bot'] = (!$this->data['is_registered'] && $this->data['user_id'] != ANONYMOUS) ? true : false;
 
331
                                                $this->data['user_lang'] = basename($this->data['user_lang']);
 
332
 
 
333
                                                return true;
 
334
                                        }
 
335
                                }
 
336
                                else
 
337
                                {
 
338
                                        // Added logging temporarly to help debug bugs...
 
339
                                        if (defined('DEBUG_EXTRA') && $this->data['user_id'] != ANONYMOUS)
 
340
                                        {
 
341
                                                add_log('critical', 'LOG_IP_BROWSER_FORWARDED_CHECK', $u_ip, $s_ip, $u_browser, $s_browser, htmlspecialchars($u_forwarded_for), htmlspecialchars($s_forwarded_for));
 
342
                                        }
 
343
                                }
 
344
                        }
 
345
                }
 
346
 
 
347
                // If we reach here then no (valid) session exists. So we'll create a new one
 
348
                return $this->session_create();
 
349
        }
 
350
 
 
351
        /**
 
352
        * Create a new session
 
353
        *
 
354
        * If upon trying to start a session we discover there is nothing existing we
 
355
        * jump here. Additionally this method is called directly during login to regenerate
 
356
        * the session for the specific user. In this method we carry out a number of tasks;
 
357
        * garbage collection, (search)bot checking, banned user comparison. Basically
 
358
        * though this method will result in a new session for a specific user.
 
359
        */
 
360
        function session_create($user_id = false, $set_admin = false, $persist_login = false, $viewonline = true)
 
361
        {
 
362
                global $SID, $_SID, $db, $config, $cache, $phpbb_root_path, $phpEx;
 
363
 
 
364
                $this->data = array();
 
365
 
 
366
                /* Garbage collection ... remove old sessions updating user information
 
367
                // if necessary. It means (potentially) 11 queries but only infrequently
 
368
                if ($this->time_now > $config['session_last_gc'] + $config['session_gc'])
 
369
                {
 
370
                        $this->session_gc();
 
371
                }*/
 
372
                
 
373
                // Do we allow autologin on this board? No? Then override anything
 
374
                // that may be requested here
 
375
                if (!$config['allow_autologin'])
 
376
                {
 
377
                        $this->cookie_data['k'] = $persist_login = false;
 
378
                }
 
379
 
 
380
                /**
 
381
                * Here we do a bot check, oh er saucy! No, not that kind of bot
 
382
                * check. We loop through the list of bots defined by the admin and
 
383
                * see if we have any useragent and/or IP matches. If we do, this is a
 
384
                * bot, act accordingly
 
385
                */
 
386
                $bot = false;
 
387
                $active_bots = $cache->obtain_bots();
 
388
 
 
389
                foreach ($active_bots as $row)
 
390
                {
 
391
                        if ($row['bot_agent'] && preg_match('#' . str_replace('\*', '.*?', preg_quote($row['bot_agent'], '#')) . '#i', $this->browser))
 
392
                        {
 
393
                                $bot = $row['user_id'];
 
394
                        }
 
395
 
 
396
                        // If ip is supplied, we will make sure the ip is matching too...
 
397
                        if ($row['bot_ip'] && ($bot || !$row['bot_agent']))
 
398
                        {
 
399
                                // Set bot to false, then we only have to set it to true if it is matching
 
400
                                $bot = false;
 
401
 
 
402
                                foreach (explode(',', $row['bot_ip']) as $bot_ip)
 
403
                                {
 
404
                                        if (strpos($this->ip, $bot_ip) === 0)
 
405
                                        {
 
406
                                                $bot = (int) $row['user_id'];
 
407
                                                break;
 
408
                                        }
 
409
                                }
 
410
                        }
 
411
 
 
412
                        if ($bot)
 
413
                        {
 
414
                                break;
 
415
                        }
 
416
                }
 
417
 
 
418
                $method = basename(trim($config['auth_method']));
 
419
                include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx);
 
420
 
 
421
                $method = 'autologin_' . $method;
 
422
                if (function_exists($method))
 
423
                {
 
424
                        $this->data = $method();
 
425
 
 
426
                        if (sizeof($this->data))
 
427
                        {
 
428
                                $this->cookie_data['k'] = '';
 
429
                                $this->cookie_data['u'] = $this->data['user_id'];
 
430
                        }
 
431
                }
 
432
 
 
433
                // If we're presented with an autologin key we'll join against it.
 
434
                // Else if we've been passed a user_id we'll grab data based on that
 
435
                if (isset($this->cookie_data['k']) && $this->cookie_data['k'] && $this->cookie_data['u'] && !sizeof($this->data))
 
436
                {
 
437
                        $sql = 'SELECT u.*
 
438
                                FROM ' . USERS_TABLE . ' u, ' . SESSIONS_KEYS_TABLE . ' k
 
439
                                WHERE u.user_id = ' . (int) $this->cookie_data['u'] . '
 
440
                                        AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ")
 
441
                                        AND k.user_id = u.user_id
 
442
                                        AND k.key_id = '" . $db->sql_escape(md5($this->cookie_data['k'])) . "'";
 
443
                        $result = $db->sql_query($sql);
 
444
                        $this->data = $db->sql_fetchrow($result);
 
445
                        $db->sql_freeresult($result);
 
446
                        $bot = false;
 
447
                }
 
448
                else if ($user_id !== false && !sizeof($this->data))
 
449
                {
 
450
                        $this->cookie_data['k'] = '';
 
451
                        $this->cookie_data['u'] = $user_id;
 
452
 
 
453
                        $sql = 'SELECT *
 
454
                                FROM ' . USERS_TABLE . '
 
455
                                WHERE user_id = ' . (int) $this->cookie_data['u'] . '
 
456
                                        AND user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')';
 
457
                        $result = $db->sql_query($sql);
 
458
                        $this->data = $db->sql_fetchrow($result);
 
459
                        $db->sql_freeresult($result);
 
460
                        $bot = false;
 
461
                }
 
462
 
 
463
                // If no data was returned one or more of the following occurred:
 
464
                // Key didn't match one in the DB
 
465
                // User does not exist
 
466
                // User is inactive
 
467
                // User is bot
 
468
                if (!sizeof($this->data) || !is_array($this->data))
 
469
                {
 
470
                        $this->cookie_data['k'] = '';
 
471
                        $this->cookie_data['u'] = ($bot) ? $bot : ANONYMOUS;
 
472
 
 
473
                        if (!$bot)
 
474
                        {
 
475
                                $sql = 'SELECT *
 
476
                                        FROM ' . USERS_TABLE . '
 
477
                                        WHERE user_id = ' . (int) $this->cookie_data['u'];
 
478
                        }
 
479
                        else
 
480
                        {
 
481
                                // We give bots always the same session if it is not yet expired.
 
482
                                $sql = 'SELECT u.*, s.*
 
483
                                        FROM ' . USERS_TABLE . ' u
 
484
                                        LEFT JOIN ' . SESSIONS_TABLE . ' s ON (s.session_user_id = u.user_id)
 
485
                                        WHERE u.user_id = ' . (int) $bot;
 
486
                        }
 
487
 
 
488
                        $result = $db->sql_query($sql);
 
489
                        $this->data = $db->sql_fetchrow($result);
 
490
                        $db->sql_freeresult($result);
 
491
                }
 
492
 
 
493
                if ($this->data['user_id'] != ANONYMOUS && !$bot)
 
494
                {
 
495
                        $this->data['session_last_visit'] = (isset($this->data['session_time']) && $this->data['session_time']) ? $this->data['session_time'] : (($this->data['user_lastvisit']) ? $this->data['user_lastvisit'] : time());
 
496
                }
 
497
                else
 
498
                {
 
499
                        $this->data['session_last_visit'] = $this->time_now;
 
500
                }
 
501
 
 
502
                // Force user id to be integer...
 
503
                $this->data['user_id'] = (int) $this->data['user_id'];
 
504
 
 
505
                // At this stage we should have a filled data array, defined cookie u and k data.
 
506
                // data array should contain recent session info if we're a real user and a recent
 
507
                // session exists in which case session_id will also be set
 
508
 
 
509
                // Is user banned? Are they excluded? Won't return on ban, exists within method
 
510
                if ($this->data['user_type'] != USER_FOUNDER)
 
511
                {
 
512
                        if (!$config['forwarded_for_check'])
 
513
                        {
 
514
                                $this->check_ban($this->data['user_id'], $this->ip);
 
515
                        }
 
516
                        else
 
517
                        {
 
518
                                $ips = explode(', ', $this->forwarded_for);
 
519
                                $ips[] = $this->ip;
 
520
                                $this->check_ban($this->data['user_id'], $ips);
 
521
                        }
 
522
                }
 
523
 
 
524
                $this->data['is_registered'] = (!$bot && $this->data['user_id'] != ANONYMOUS && ($this->data['user_type'] == USER_NORMAL || $this->data['user_type'] == USER_FOUNDER)) ? true : false;
 
525
                $this->data['is_bot'] = ($bot) ? true : false;
 
526
 
 
527
                // If our friend is a bot, we re-assign a previously assigned session
 
528
                if ($this->data['is_bot'] && $bot == $this->data['user_id'] && $this->data['session_id'])
 
529
                {
 
530
                        // Only assign the current session if the ip, browser and forwarded_for match...
 
531
                        if (strpos($this->ip, ':') !== false && strpos($this->data['session_ip'], ':') !== false)
 
532
                        {
 
533
                                $s_ip = short_ipv6($this->data['session_ip'], $config['ip_check']);
 
534
                                $u_ip = short_ipv6($this->ip, $config['ip_check']);
 
535
                        }
 
536
                        else
 
537
                        {
 
538
                                $s_ip = implode('.', array_slice(explode('.', $this->data['session_ip']), 0, $config['ip_check']));
 
539
                                $u_ip = implode('.', array_slice(explode('.', $this->ip), 0, $config['ip_check']));
 
540
                        }
 
541
 
 
542
                        $s_browser = ($config['browser_check']) ? strtolower(substr($this->data['session_browser'], 0, 149)) : '';
 
543
                        $u_browser = ($config['browser_check']) ? strtolower(substr($this->browser, 0, 149)) : '';
 
544
 
 
545
                        $s_forwarded_for = ($config['forwarded_for_check']) ? substr($this->data['session_forwarded_for'], 0, 254) : '';
 
546
                        $u_forwarded_for = ($config['forwarded_for_check']) ? substr($this->forwarded_for, 0, 254) : '';
 
547
 
 
548
                        if ($u_ip === $s_ip && $s_browser === $u_browser && $s_forwarded_for === $u_forwarded_for)
 
549
                        {
 
550
                                $this->session_id = $this->data['session_id'];
 
551
 
 
552
                                // Only update session DB a minute or so after last update or if page changes
 
553
                                if ($this->time_now - $this->data['session_time'] > 60 || ($this->update_session_page && $this->data['session_page'] != $this->page['page']))
 
554
                                {
 
555
                                        $this->data['session_time'] = $this->data['session_last_visit'] = $this->time_now;
 
556
 
 
557
                                        $sql_ary = array('session_time' => $this->time_now, 'session_last_visit' => $this->time_now, 'session_admin' => 0);
 
558
 
 
559
                                        if ($this->update_session_page)
 
560
                                        {
 
561
                                                $sql_ary['session_page'] = substr($this->page['page'], 0, 199);
 
562
                                        }
 
563
 
 
564
                                        $sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
 
565
                                                WHERE session_id = '" . $db->sql_escape($this->session_id) . "'";
 
566
                                        $db->sql_query($sql);
 
567
 
 
568
                                        // Update the last visit time
 
569
                                        $sql = 'UPDATE ' . USERS_TABLE . '
 
570
                                                SET user_lastvisit = ' . (int) $this->data['session_time'] . '
 
571
                                                WHERE user_id = ' . (int) $this->data['user_id'];
 
572
                                        $db->sql_query($sql);
 
573
                                }
 
574
 
 
575
                                $SID = '?sid=';
 
576
                                $_SID = '';
 
577
                                return true;
 
578
                        }
 
579
                        else
 
580
                        {
 
581
                                // If the ip and browser does not match make sure we only have one bot assigned to one session
 
582
                                $db->sql_query('DELETE FROM ' . SESSIONS_TABLE . ' WHERE session_user_id = ' . $this->data['user_id']);
 
583
                        }
 
584
                }
 
585
 
 
586
                $session_autologin = (($this->cookie_data['k'] || $persist_login) && $this->data['is_registered']) ? true : false;
 
587
                $set_admin = ($set_admin && $this->data['is_registered']) ? true : false;
 
588
 
 
589
                // Create or update the session
 
590
                $sql_ary = array(
 
591
                        'session_user_id'               => (int) $this->data['user_id'],
 
592
                        'session_start'                 => (int) $this->time_now,
 
593
                        'session_last_visit'    => (int) $this->data['session_last_visit'],
 
594
                        'session_time'                  => (int) $this->time_now,
 
595
                        'session_browser'               => (string) substr($this->browser, 0, 149),
 
596
                        'session_forwarded_for' => (string) $this->forwarded_for,
 
597
                        'session_ip'                    => (string) $this->ip,
 
598
                        'session_autologin'             => ($session_autologin) ? 1 : 0,
 
599
                        'session_admin'                 => ($set_admin) ? 1 : 0,
 
600
                        'session_viewonline'    => ($viewonline) ? 1 : 0,
 
601
                );
 
602
 
 
603
                if ($this->update_session_page)
 
604
                {
 
605
                        $sql_ary['session_page'] = (string) substr($this->page['page'], 0, 199);
 
606
                }
 
607
 
 
608
                $db->sql_return_on_error(true);
 
609
 
 
610
                $sql = 'DELETE
 
611
                        FROM ' . SESSIONS_TABLE . '
 
612
                        WHERE session_id = \'' . $db->sql_escape($this->session_id) . '\'
 
613
                                AND session_user_id = ' . ANONYMOUS;
 
614
 
 
615
                if (!defined('IN_ERROR_HANDLER') && (!$this->session_id || !$db->sql_query($sql) || !$db->sql_affectedrows()))
 
616
                {
 
617
                        // Limit new sessions in 1 minute period (if required)
 
618
                        if (empty($this->data['session_time']) && $config['active_sessions'])
 
619
                        {
 
620
                                $sql = 'SELECT COUNT(session_id) AS sessions
 
621
                                        FROM ' . SESSIONS_TABLE . '
 
622
                                        WHERE session_time >= ' . ($this->time_now - 60);
 
623
                                $result = $db->sql_query($sql);
 
624
                                $row = $db->sql_fetchrow($result);
 
625
                                $db->sql_freeresult($result);
 
626
 
 
627
                                if ((int) $row['sessions'] > (int) $config['active_sessions'])
 
628
                                {
 
629
                                        header('HTTP/1.1 503 Service Unavailable');
 
630
                                        trigger_error('BOARD_UNAVAILABLE');
 
631
                                }
 
632
                        }
 
633
                }
 
634
 
 
635
                $this->session_id = $this->data['session_id'] = md5(unique_id());
 
636
 
 
637
                $sql_ary['session_id'] = (string) $this->session_id;
 
638
                $sql_ary['session_page'] = (string) substr($this->page['page'], 0, 199);
 
639
 
 
640
                $sql = 'INSERT INTO ' . SESSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
 
641
                $db->sql_query($sql);
 
642
 
 
643
                $db->sql_return_on_error(false);
 
644
 
 
645
                // Regenerate autologin/persistent login key
 
646
                if ($session_autologin)
 
647
                {
 
648
                        $this->set_login_key();
 
649
                }
 
650
 
 
651
                // refresh data
 
652
                $SID = '?sid=' . $this->session_id;
 
653
                $_SID = $this->session_id;
 
654
                $this->data = array_merge($this->data, $sql_ary);
 
655
 
 
656
                if (!$bot)
 
657
                {
 
658
                        $cookie_expire = $this->time_now + (($config['max_autologin_time']) ? 86400 * (int) $config['max_autologin_time'] : 31536000);
 
659
 
 
660
                        $this->set_cookie('u', $this->cookie_data['u'], $cookie_expire);
 
661
                        $this->set_cookie('k', $this->cookie_data['k'], $cookie_expire);
 
662
                        $this->set_cookie('sid', $this->session_id, $cookie_expire);
 
663
 
 
664
                        unset($cookie_expire);
 
665
                        
 
666
                        $sql = 'SELECT COUNT(session_id) AS sessions
 
667
                                        FROM ' . SESSIONS_TABLE . '
 
668
                                        WHERE session_user_id = ' . (int) $this->data['user_id'] . '
 
669
                                        AND session_time >= ' . ($this->time_now - $config['form_token_lifetime']);
 
670
                        $result = $db->sql_query($sql);
 
671
                        $row = $db->sql_fetchrow($result);
 
672
                        $db->sql_freeresult($result);
 
673
 
 
674
                        if ((int) $row['sessions'] <= 1 || empty($this->data['user_form_salt']))
 
675
                        {
 
676
                                $this->data['user_form_salt'] = unique_id();
 
677
                                // Update the form key
 
678
                                $sql = 'UPDATE ' . USERS_TABLE . '
 
679
                                        SET user_form_salt = \'' . $db->sql_escape($this->data['user_form_salt']) . '\'
 
680
                                        WHERE user_id = ' . (int) $this->data['user_id'];
 
681
                                $db->sql_query($sql);
 
682
                        }
 
683
                }
 
684
                else
 
685
                {
 
686
                        $this->data['session_time'] = $this->data['session_last_visit'] = $this->time_now;
 
687
 
 
688
                        // Update the last visit time
 
689
                        $sql = 'UPDATE ' . USERS_TABLE . '
 
690
                                SET user_lastvisit = ' . (int) $this->data['session_time'] . '
 
691
                                WHERE user_id = ' . (int) $this->data['user_id'];
 
692
                        $db->sql_query($sql);
 
693
 
 
694
                        $SID = '?sid=';
 
695
                        $_SID = '';
 
696
                }
 
697
 
 
698
                return true;
 
699
        }
 
700
 
 
701
        /**
 
702
        * Kills a session
 
703
        *
 
704
        * This method does what it says on the tin. It will delete a pre-existing session.
 
705
        * It resets cookie information (destroying any autologin key within that cookie data)
 
706
        * and update the users information from the relevant session data. It will then
 
707
        * grab guest user information.
 
708
        */
 
709
        function session_kill($new_session = true)
 
710
        {
 
711
                global $SID, $_SID, $db, $config, $phpbb_root_path, $phpEx;
 
712
 
 
713
                $sql = 'DELETE FROM ' . SESSIONS_TABLE . "
 
714
                        WHERE session_id = '" . $db->sql_escape($this->session_id) . "'
 
715
                                AND session_user_id = " . (int) $this->data['user_id'];
 
716
                $db->sql_query($sql);
 
717
 
 
718
                // Allow connecting logout with external auth method logout
 
719
                $method = basename(trim($config['auth_method']));
 
720
                include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx);
 
721
 
 
722
                $method = 'logout_' . $method;
 
723
                if (function_exists($method))
 
724
                {
 
725
                        $method($this->data, $new_session);
 
726
                }
 
727
 
 
728
                if ($this->data['user_id'] != ANONYMOUS)
 
729
                {
 
730
                        // Delete existing session, update last visit info first!
 
731
                        if (!isset($this->data['session_time']))
 
732
                        {
 
733
                                $this->data['session_time'] = time();
 
734
                        }
 
735
 
 
736
                        $sql = 'UPDATE ' . USERS_TABLE . '
 
737
                                SET user_lastvisit = ' . (int) $this->data['session_time'] . '
 
738
                                WHERE user_id = ' . (int) $this->data['user_id'];
 
739
                        $db->sql_query($sql);
 
740
 
 
741
                        if ($this->cookie_data['k'])
 
742
                        {
 
743
                                $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . '
 
744
                                        WHERE user_id = ' . (int) $this->data['user_id'] . "
 
745
                                                AND key_id = '" . $db->sql_escape(md5($this->cookie_data['k'])) . "'";
 
746
                                $db->sql_query($sql);
 
747
                        }
 
748
 
 
749
                        // Reset the data array
 
750
                        $this->data = array();
 
751
 
 
752
                        $sql = 'SELECT *
 
753
                                FROM ' . USERS_TABLE . '
 
754
                                WHERE user_id = ' . ANONYMOUS;
 
755
                        $result = $db->sql_query($sql);
 
756
                        $this->data = $db->sql_fetchrow($result);
 
757
                        $db->sql_freeresult($result);
 
758
                }
 
759
 
 
760
                $cookie_expire = $this->time_now - 31536000;
 
761
                $this->set_cookie('u', '', $cookie_expire);
 
762
                $this->set_cookie('k', '', $cookie_expire);
 
763
                $this->set_cookie('sid', '', $cookie_expire);
 
764
                unset($cookie_expire);
 
765
 
 
766
                $SID = '?sid=';
 
767
                $this->session_id = $_SID = '';
 
768
 
 
769
                // To make sure a valid session is created we create one for the anonymous user
 
770
                if ($new_session)
 
771
                {
 
772
                        $this->session_create(ANONYMOUS);
 
773
                }
 
774
 
 
775
                return true;
 
776
        }
 
777
 
 
778
        /**
 
779
        * Session garbage collection
 
780
        *
 
781
        * This looks a lot more complex than it really is. Effectively we are
 
782
        * deleting any sessions older than an admin definable limit. Due to the
 
783
        * way in which we maintain session data we have to ensure we update user
 
784
        * data before those sessions are destroyed. In addition this method
 
785
        * removes autologin key information that is older than an admin defined
 
786
        * limit.
 
787
        */
 
788
        function session_gc()
 
789
        {
 
790
                global $db, $config;
 
791
 
 
792
                $batch_size = 10;
 
793
                
 
794
                if (!$this->time_now)
 
795
                {
 
796
                        $this->time_now = time();
 
797
                }
 
798
 
 
799
                // Firstly, delete guest sessions
 
800
                $sql = 'DELETE FROM ' . SESSIONS_TABLE . '
 
801
                        WHERE session_user_id = ' . ANONYMOUS . '
 
802
                                AND session_time < ' . (int) ($this->time_now - $config['session_length']);
 
803
                $db->sql_query($sql);
 
804
 
 
805
                // Get expired sessions, only most recent for each user
 
806
                $sql = 'SELECT session_user_id, session_page, MAX(session_time) AS recent_time
 
807
                        FROM ' . SESSIONS_TABLE . '
 
808
                        WHERE session_time < ' . ($this->time_now - $config['session_length']) . '
 
809
                        GROUP BY session_user_id, session_page';
 
810
                $result = $db->sql_query_limit($sql, $batch_size);
 
811
 
 
812
                $del_user_id = array();
 
813
                $del_sessions = 0;
 
814
 
 
815
                while ($row = $db->sql_fetchrow($result))
 
816
                {
 
817
                        $sql = 'UPDATE ' . USERS_TABLE . '
 
818
                                SET user_lastvisit = ' . (int) $row['recent_time'] . ", user_lastpage = '" . $db->sql_escape($row['session_page']) . "'
 
819
                                WHERE user_id = " . (int) $row['session_user_id'];
 
820
                        $db->sql_query($sql);
 
821
 
 
822
                        $del_user_id[] = (int) $row['session_user_id'];
 
823
                        $del_sessions++;
 
824
                }
 
825
                $db->sql_freeresult($result);
 
826
 
 
827
                if (sizeof($del_user_id))
 
828
                {
 
829
                        // Delete expired sessions
 
830
                        $sql = 'DELETE FROM ' . SESSIONS_TABLE . '
 
831
                                WHERE ' . $db->sql_in_set('session_user_id', $del_user_id) . '
 
832
                                        AND session_time < ' . ($this->time_now - $config['session_length']);
 
833
                        $db->sql_query($sql);
 
834
                }
 
835
 
 
836
                if ($del_sessions < $batch_size)
 
837
                {
 
838
                        // Less than 10 users, update gc timer ... else we want gc
 
839
                        // called again to delete other sessions
 
840
                        set_config('session_last_gc', $this->time_now, true);
 
841
                        
 
842
                        if ($config['max_autologin_time'])
 
843
                        {
 
844
                                $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . '
 
845
                                        WHERE last_login < ' . (time() - (86400 * (int) $config['max_autologin_time']));
 
846
                                $db->sql_query($sql);
 
847
                        }
 
848
                        $this->confirm_gc();
 
849
                }
 
850
                
 
851
                return;
 
852
        }
 
853
        
 
854
        function confirm_gc($type = 0)
 
855
        {
 
856
                global $db, $config;
 
857
                
 
858
                $sql = 'SELECT DISTINCT c.session_id
 
859
                                FROM ' . CONFIRM_TABLE . ' c
 
860
                                LEFT JOIN ' . SESSIONS_TABLE . ' s ON (c.session_id = s.session_id)
 
861
                                WHERE s.session_id IS NULL' .
 
862
                                        ((empty($type)) ? '' : ' AND c.confirm_type = ' . (int) $type);
 
863
                $result = $db->sql_query($sql);
 
864
 
 
865
                if ($row = $db->sql_fetchrow($result))
 
866
                {
 
867
                        $sql_in = array();
 
868
                        do
 
869
                        {
 
870
                                $sql_in[] = (string) $row['session_id'];
 
871
                        }
 
872
                        while ($row = $db->sql_fetchrow($result));
 
873
 
 
874
                        if (sizeof($sql_in))
 
875
                        {
 
876
                                $sql = 'DELETE FROM ' . CONFIRM_TABLE . '
 
877
                                        WHERE ' . $db->sql_in_set('session_id', $sql_in);
 
878
                                $db->sql_query($sql);
 
879
                        }
 
880
                }
 
881
                $db->sql_freeresult($result);
 
882
        }
 
883
        
 
884
        
 
885
        /**
 
886
        * Sets a cookie
 
887
        *
 
888
        * Sets a cookie of the given name with the specified data for the given length of time.
 
889
        */
 
890
        function set_cookie($name, $cookiedata, $cookietime)
 
891
        {
 
892
                global $config;
 
893
 
 
894
                $name_data = rawurlencode($config['cookie_name'] . '_' . $name) . '=' . rawurlencode($cookiedata);
 
895
                $expire = gmdate('D, d-M-Y H:i:s \\G\\M\\T', $cookietime);
 
896
                $domain = (!$config['cookie_domain'] || $config['cookie_domain'] == 'localhost' || $config['cookie_domain'] == '127.0.0.1') ? '' : '; domain=' . $config['cookie_domain'];
 
897
 
 
898
                header('Set-Cookie: ' . $name_data . '; expires=' . $expire . '; path=' . $config['cookie_path'] . $domain . ((!$config['cookie_secure']) ? '' : '; secure') . '; HttpOnly', false);
 
899
        }
 
900
 
 
901
        /**
 
902
        * Check for banned user
 
903
        *
 
904
        * Checks whether the supplied user is banned by id, ip or email. If no parameters
 
905
        * are passed to the method pre-existing session data is used. If $return is false
 
906
        * this routine does not return on finding a banned user, it outputs a relevant
 
907
        * message and stops execution.
 
908
        *
 
909
        * @param string|array   $user_ips       Can contain a string with one IP or an array of multiple IPs
 
910
        */
 
911
        function check_ban($user_id = false, $user_ips = false, $user_email = false, $return = false)
 
912
        {
 
913
                global $config, $db;
 
914
 
 
915
                if (defined('IN_CHECK_BAN'))
 
916
                {
 
917
                        return;
 
918
                }
 
919
 
 
920
                $banned = false;
 
921
                $cache_ttl = 3600;
 
922
                $where_sql = array();
 
923
 
 
924
                $sql = 'SELECT ban_ip, ban_userid, ban_email, ban_exclude, ban_give_reason, ban_end
 
925
                        FROM ' . BANLIST_TABLE . '
 
926
                        WHERE ';
 
927
 
 
928
                // Determine which entries to check, only return those
 
929
                if ($user_email === false)
 
930
                {
 
931
                        $where_sql[] = "ban_email = ''";
 
932
                }
 
933
 
 
934
                if ($user_ips === false)
 
935
                {
 
936
                        $where_sql[] = "(ban_ip = '' OR ban_exclude = 1)";
 
937
                }
 
938
 
 
939
                if ($user_id === false)
 
940
                {
 
941
                        $where_sql[] = '(ban_userid = 0 OR ban_exclude = 1)';
 
942
                }
 
943
                else
 
944
                {
 
945
                        $cache_ttl = ($user_id == ANONYMOUS) ? 3600 : 0;
 
946
                        $_sql = '(ban_userid = ' . $user_id;
 
947
 
 
948
                        if ($user_email !== false)
 
949
                        {
 
950
                                $_sql .= " OR ban_email <> ''";
 
951
                        }
 
952
 
 
953
                        if ($user_ips !== false)
 
954
                        {
 
955
                                $_sql .= " OR ban_ip <> ''";
 
956
                        }
 
957
 
 
958
                        $_sql .= ')';
 
959
 
 
960
                        $where_sql[] = $_sql;
 
961
                }
 
962
 
 
963
                $sql .= (sizeof($where_sql)) ? implode(' AND ', $where_sql) : '';
 
964
                $result = $db->sql_query($sql, $cache_ttl);
 
965
 
 
966
                $ban_triggered_by = 'user';
 
967
                while ($row = $db->sql_fetchrow($result))
 
968
                {
 
969
                        if ($row['ban_end'] && $row['ban_end'] < time())
 
970
                        {
 
971
                                continue;
 
972
                        }
 
973
 
 
974
                        $ip_banned = false;
 
975
                        if (!empty($row['ban_ip']))
 
976
                        {
 
977
                                if (!is_array($user_ips))
 
978
                                {
 
979
                                        $ip_banned = preg_match('#^' . str_replace('\*', '.*?', preg_quote($row['ban_ip'], '#')) . '$#i', $user_ips);
 
980
                                }
 
981
                                else
 
982
                                {
 
983
                                        foreach ($user_ips as $user_ip)
 
984
                                        {
 
985
                                                if (preg_match('#^' . str_replace('\*', '.*?', preg_quote($row['ban_ip'], '#')) . '$#i', $user_ip))
 
986
                                                {
 
987
                                                        $ip_banned = true;
 
988
                                                        break;
 
989
                                                }
 
990
                                        }
 
991
                                }
 
992
                        }
 
993
 
 
994
                        if ((!empty($row['ban_userid']) && intval($row['ban_userid']) == $user_id) ||
 
995
                                $ip_banned ||
 
996
                                (!empty($row['ban_email']) && preg_match('#^' . str_replace('\*', '.*?', preg_quote($row['ban_email'], '#')) . '$#i', $user_email)))
 
997
                        {
 
998
                                if (!empty($row['ban_exclude']))
 
999
                                {
 
1000
                                        $banned = false;
 
1001
                                        break;
 
1002
                                }
 
1003
                                else
 
1004
                                {
 
1005
                                        $banned = true;
 
1006
                                        $ban_row = $row;
 
1007
 
 
1008
                                        if (!empty($row['ban_userid']) && intval($row['ban_userid']) == $user_id)
 
1009
                                        {
 
1010
                                                $ban_triggered_by = 'user';
 
1011
                                        }
 
1012
                                        else if ($ip_banned)
 
1013
                                        {
 
1014
                                                $ban_triggered_by = 'ip';
 
1015
                                        }
 
1016
                                        else
 
1017
                                        {
 
1018
                                                $ban_triggered_by = 'email';
 
1019
                                        }
 
1020
 
 
1021
                                        // Don't break. Check if there is an exclude rule for this user
 
1022
                                }
 
1023
                        }
 
1024
                }
 
1025
                $db->sql_freeresult($result);
 
1026
 
 
1027
                if ($banned && !$return)
 
1028
                {
 
1029
                        global $template;
 
1030
 
 
1031
                        // If the session is empty we need to create a valid one...
 
1032
                        if (empty($this->session_id))
 
1033
                        {
 
1034
                                // This seems to be no longer needed? - #14971
 
1035
                                //$this->session_create(ANONYMOUS);
 
1036
                        }
 
1037
 
 
1038
                        // Initiate environment ... since it won't be set at this stage
 
1039
                        $this->setup();
 
1040
 
 
1041
                        // Logout the user, banned users are unable to use the normal 'logout' link
 
1042
                        if ($this->data['user_id'] != ANONYMOUS)
 
1043
                        {
 
1044
                                $this->session_kill();
 
1045
                        }
 
1046
 
 
1047
                        // We show a login box here to allow founders accessing the board if banned by IP
 
1048
                        if (defined('IN_LOGIN') && $this->data['user_id'] == ANONYMOUS)
 
1049
                        {
 
1050
                                global $phpEx;
 
1051
 
 
1052
                                $this->setup('ucp');
 
1053
                                $this->data['is_registered'] = $this->data['is_bot'] = false;
 
1054
 
 
1055
                                // Set as a precaution to allow login_box() handling this case correctly as well as this function not being executed again.
 
1056
                                define('IN_CHECK_BAN', 1);
 
1057
 
 
1058
                                login_box("index.$phpEx");
 
1059
 
 
1060
                                // The false here is needed, else the user is able to circumvent the ban.
 
1061
                                $this->session_kill(false);
 
1062
                        }
 
1063
 
 
1064
                        // Ok, we catch the case of an empty session id for the anonymous user...
 
1065
                        // This can happen if the user is logging in, banned by username and the login_box() being called "again".
 
1066
                        if (empty($this->session_id) && defined('IN_CHECK_BAN'))
 
1067
                        {
 
1068
                                $this->session_create(ANONYMOUS);
 
1069
                        }
 
1070
 
 
1071
 
 
1072
                        // Determine which message to output
 
1073
                        $till_date = ($ban_row['ban_end']) ? $this->format_date($ban_row['ban_end']) : '';
 
1074
                        $message = ($ban_row['ban_end']) ? 'BOARD_BAN_TIME' : 'BOARD_BAN_PERM';
 
1075
 
 
1076
                        $message = sprintf($this->lang[$message], $till_date, '<a href="mailto:' . $config['board_contact'] . '">', '</a>');
 
1077
                        $message .= ($ban_row['ban_give_reason']) ? '<br /><br />' . sprintf($this->lang['BOARD_BAN_REASON'], $ban_row['ban_give_reason']) : '';
 
1078
                        $message .= '<br /><br /><em>' . $this->lang['BAN_TRIGGERED_BY_' . strtoupper($ban_triggered_by)] . '</em>';
 
1079
 
 
1080
                        // To circumvent session_begin returning a valid value and the check_ban() not called on second page view, we kill the session again
 
1081
                        $this->session_kill(false);
 
1082
 
 
1083
                        trigger_error($message);
 
1084
                }
 
1085
 
 
1086
                return ($banned) ? true : false;
 
1087
        }
 
1088
 
 
1089
        /**
 
1090
        * Check if ip is blacklisted
 
1091
        * This should be called only where absolutly necessary
 
1092
        *
 
1093
        * Only IPv4 (rbldns does not support AAAA records/IPv6 lookups)
 
1094
        *
 
1095
        * @author satmd (from the php manual)
 
1096
        * @param string $mode register/post - spamcop for example is ommitted for posting
 
1097
        * @return false if ip is not blacklisted, else an array([checked server], [lookup])
 
1098
        */
 
1099
        function check_dnsbl($mode, $ip = false)
 
1100
        {
 
1101
                if ($ip === false)
 
1102
                {
 
1103
                        $ip = $this->ip;
 
1104
                }
 
1105
 
 
1106
                $dnsbl_check = array(
 
1107
                        'list.dsbl.org'                 => 'http://dsbl.org/listing?',
 
1108
                        'sbl-xbl.spamhaus.org'  => 'http://www.spamhaus.org/query/bl?ip=',
 
1109
                );
 
1110
 
 
1111
                if ($mode == 'register')
 
1112
                {
 
1113
                        $dnsbl_check['bl.spamcop.net'] = 'http://spamcop.net/bl.shtml?';
 
1114
                }
 
1115
 
 
1116
                if ($ip)
 
1117
                {
 
1118
                        $quads = explode('.', $ip);
 
1119
                        $reverse_ip = $quads[3] . '.' . $quads[2] . '.' . $quads[1] . '.' . $quads[0];
 
1120
 
 
1121
                        // Need to be listed on all servers...
 
1122
                        $listed = true;
 
1123
                        $info = array();
 
1124
 
 
1125
                        foreach ($dnsbl_check as $dnsbl => $lookup)
 
1126
                        {
 
1127
                                if (phpbb_checkdnsrr($reverse_ip . '.' . $dnsbl . '.', 'A') === true)
 
1128
                                {
 
1129
                                        $info = array($dnsbl, $lookup . $ip);
 
1130
                                }
 
1131
                                else
 
1132
                                {
 
1133
                                        $listed = false;
 
1134
                                }
 
1135
                        }
 
1136
 
 
1137
                        if ($listed)
 
1138
                        {
 
1139
                                return $info;
 
1140
                        }
 
1141
                }
 
1142
 
 
1143
                return false;
 
1144
        }
 
1145
 
 
1146
        /**
 
1147
        * Check if URI is blacklisted
 
1148
        * This should be called only where absolutly necessary, for example on the submitted website field
 
1149
        * This function is not in use at the moment and is only included for testing purposes, it may not work at all!
 
1150
        * This means it is untested at the moment and therefore commented out
 
1151
        *
 
1152
        * @param string $uri URI to check
 
1153
        * @return true if uri is on blacklist, else false. Only blacklist is checked (~zero FP), no grey lists
 
1154
        function check_uribl($uri)
 
1155
        {
 
1156
                // Normally parse_url() is not intended to parse uris
 
1157
                // We need to get the top-level domain name anyway... change.
 
1158
                $uri = parse_url($uri);
 
1159
 
 
1160
                if ($uri === false || empty($uri['host']))
 
1161
                {
 
1162
                        return false;
 
1163
                }
 
1164
 
 
1165
                $uri = trim($uri['host']);
 
1166
 
 
1167
                if ($uri)
 
1168
                {
 
1169
                        // One problem here... the return parameter for the "windows" method is different from what
 
1170
                        // we expect... this may render this check useless...
 
1171
                        if (phpbb_checkdnsrr($uri . '.multi.uribl.com.', 'A') === true)
 
1172
                        {
 
1173
                                return true;
 
1174
                        }
 
1175
                }
 
1176
 
 
1177
                return false;
 
1178
        }
 
1179
        */
 
1180
 
 
1181
        /**
 
1182
        * Set/Update a persistent login key
 
1183
        *
 
1184
        * This method creates or updates a persistent session key. When a user makes
 
1185
        * use of persistent (formerly auto-) logins a key is generated and stored in the
 
1186
        * DB. When they revisit with the same key it's automatically updated in both the
 
1187
        * DB and cookie. Multiple keys may exist for each user representing different
 
1188
        * browsers or locations. As with _any_ non-secure-socket no passphrase login this
 
1189
        * remains vulnerable to exploit.
 
1190
        */
 
1191
        function set_login_key($user_id = false, $key = false, $user_ip = false)
 
1192
        {
 
1193
                global $config, $db;
 
1194
 
 
1195
                $user_id = ($user_id === false) ? $this->data['user_id'] : $user_id;
 
1196
                $user_ip = ($user_ip === false) ? $this->ip : $user_ip;
 
1197
                $key = ($key === false) ? (($this->cookie_data['k']) ? $this->cookie_data['k'] : false) : $key;
 
1198
 
 
1199
                $key_id = unique_id(hexdec(substr($this->session_id, 0, 8)));
 
1200
 
 
1201
                $sql_ary = array(
 
1202
                        'key_id'                => (string) md5($key_id),
 
1203
                        'last_ip'               => (string) $this->ip,
 
1204
                        'last_login'    => (int) time()
 
1205
                );
 
1206
 
 
1207
                if (!$key)
 
1208
                {
 
1209
                        $sql_ary += array(
 
1210
                                'user_id'       => (int) $user_id
 
1211
                        );
 
1212
                }
 
1213
 
 
1214
                if ($key)
 
1215
                {
 
1216
                        $sql = 'UPDATE ' . SESSIONS_KEYS_TABLE . '
 
1217
                                SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
 
1218
                                WHERE user_id = ' . (int) $user_id . "
 
1219
                                        AND key_id = '" . $db->sql_escape(md5($key)) . "'";
 
1220
                }
 
1221
                else
 
1222
                {
 
1223
                        $sql = 'INSERT INTO ' . SESSIONS_KEYS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
 
1224
                }
 
1225
                $db->sql_query($sql);
 
1226
 
 
1227
                $this->cookie_data['k'] = $key_id;
 
1228
 
 
1229
                return false;
 
1230
        }
 
1231
 
 
1232
        /**
 
1233
        * Reset all login keys for the specified user
 
1234
        *
 
1235
        * This method removes all current login keys for a specified (or the current)
 
1236
        * user. It will be called on password change to render old keys unusable
 
1237
        */
 
1238
        function reset_login_keys($user_id = false)
 
1239
        {
 
1240
                global $config, $db;
 
1241
 
 
1242
                $user_id = ($user_id === false) ? $this->data['user_id'] : $user_id;
 
1243
 
 
1244
                $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . '
 
1245
                        WHERE user_id = ' . (int) $user_id;
 
1246
                $db->sql_query($sql);
 
1247
 
 
1248
                // Let's also clear any current sessions for the specified user_id
 
1249
                // If it's the current user then we'll leave this session intact
 
1250
                $sql_where = 'session_user_id = ' . (int) $user_id;
 
1251
                $sql_where .= ($user_id === $this->data['user_id']) ? " AND session_id <> '" . $db->sql_escape($this->session_id) . "'" : '';
 
1252
 
 
1253
                $sql = 'DELETE FROM ' . SESSIONS_TABLE . "
 
1254
                        WHERE $sql_where";
 
1255
                $db->sql_query($sql);
 
1256
 
 
1257
                // We're changing the password of the current user and they have a key
 
1258
                // Lets regenerate it to be safe
 
1259
                if ($user_id === $this->data['user_id'] && $this->cookie_data['k'])
 
1260
                {
 
1261
                        $this->set_login_key($user_id);
 
1262
                }
 
1263
        }
 
1264
}
 
1265
 
 
1266
 
 
1267
/**
 
1268
* Base user class
 
1269
*
 
1270
* This is the overarching class which contains (through session extend)
 
1271
* all methods utilised for user functionality during a session.
 
1272
*
 
1273
* @package phpBB3
 
1274
*/
 
1275
class user extends session
 
1276
{
 
1277
        var $lang = array();
 
1278
        var $help = array();
 
1279
        var $theme = array();
 
1280
        var $date_format;
 
1281
        var $timezone;
 
1282
        var $dst;
 
1283
 
 
1284
        var $lang_name;
 
1285
        var $lang_id = false;
 
1286
        var $lang_path;
 
1287
        var $img_lang;
 
1288
        var $img_array = array();
 
1289
 
 
1290
        // Able to add new option (id 7)
 
1291
        var $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'popuppm' => 10);
 
1292
        var $keyvalues = array();
 
1293
 
 
1294
        /**
 
1295
        * Setup basic user-specific items (style, language, ...)
 
1296
        */
 
1297
        function setup($lang_set = false, $style = false)
 
1298
        {
 
1299
                global $db, $template, $config, $auth, $phpEx, $phpbb_root_path, $cache;
 
1300
 
 
1301
                if ($this->data['user_id'] != ANONYMOUS)
 
1302
                {
 
1303
                        $this->lang_name = (file_exists($phpbb_root_path . 'language/' . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']);
 
1304
                        $this->lang_path = $phpbb_root_path . 'language/' . $this->lang_name . '/';
 
1305
 
 
1306
                        $this->date_format = $this->data['user_dateformat'];
 
1307
                        $this->timezone = $this->data['user_timezone'] * 3600;
 
1308
                        $this->dst = $this->data['user_dst'] * 3600;
 
1309
                }
 
1310
                else
 
1311
                {
 
1312
                        $this->lang_name = basename($config['default_lang']);
 
1313
                        $this->lang_path = $phpbb_root_path . 'language/' . $this->lang_name . '/';
 
1314
                        $this->date_format = $config['default_dateformat'];
 
1315
                        $this->timezone = $config['board_timezone'] * 3600;
 
1316
                        $this->dst = $config['board_dst'] * 3600;
 
1317
 
 
1318
                        /**
 
1319
                        * If a guest user is surfing, we try to guess his/her language first by obtaining the browser language
 
1320
                        * If re-enabled we need to make sure only those languages installed are checked
 
1321
                        * Commented out so we do not loose the code.
 
1322
 
 
1323
                        if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
 
1324
                        {
 
1325
                                $accept_lang_ary = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
 
1326
 
 
1327
                                foreach ($accept_lang_ary as $accept_lang)
 
1328
                                {
 
1329
                                        // Set correct format ... guess full xx_YY form
 
1330
                                        $accept_lang = substr($accept_lang, 0, 2) . '_' . strtoupper(substr($accept_lang, 3, 2));
 
1331
                                        $accept_lang = basename($accept_lang);
 
1332
 
 
1333
                                        if (file_exists($phpbb_root_path . 'language/' . $accept_lang . "/common.$phpEx"))
 
1334
                                        {
 
1335
                                                $this->lang_name = $config['default_lang'] = $accept_lang;
 
1336
                                                $this->lang_path = $phpbb_root_path . 'language/' . $accept_lang . '/';
 
1337
                                                break;
 
1338
                                        }
 
1339
                                        else
 
1340
                                        {
 
1341
                                                // No match on xx_YY so try xx
 
1342
                                                $accept_lang = substr($accept_lang, 0, 2);
 
1343
                                                $accept_lang = basename($accept_lang);
 
1344
 
 
1345
                                                if (file_exists($phpbb_root_path . 'language/' . $accept_lang . "/common.$phpEx"))
 
1346
                                                {
 
1347
                                                        $this->lang_name = $config['default_lang'] = $accept_lang;
 
1348
                                                        $this->lang_path = $phpbb_root_path . 'language/' . $accept_lang . '/';
 
1349
                                                        break;
 
1350
                                                }
 
1351
                                        }
 
1352
                                }
 
1353
                        }
 
1354
                        */
 
1355
                }
 
1356
 
 
1357
                // We include common language file here to not load it every time a custom language file is included
 
1358
                $lang = &$this->lang;
 
1359
 
 
1360
                if ((@include $this->lang_path . "common.$phpEx") === false)
 
1361
                {
 
1362
                        die('Language file ' . $this->lang_name . "/common.$phpEx" . " couldn't be opened.");
 
1363
                }
 
1364
 
 
1365
                $this->add_lang($lang_set);
 
1366
                unset($lang_set);
 
1367
 
 
1368
                if (!empty($_GET['style']) && $auth->acl_get('a_styles'))
 
1369
                {
 
1370
                        global $SID, $_EXTRA_URL;
 
1371
 
 
1372
                        $style = request_var('style', 0);
 
1373
                        $SID .= '&amp;style=' . $style;
 
1374
                        $_EXTRA_URL = array('style=' . $style);
 
1375
                }
 
1376
                else
 
1377
                {
 
1378
                        // Set up style
 
1379
                        $style = ($style) ? $style : ((!$config['override_user_style']) ? $this->data['user_style'] : $config['default_style']);
 
1380
                }
 
1381
 
 
1382
                $sql = 'SELECT s.style_id, t.template_storedb, t.template_path, t.template_id, t.bbcode_bitfield, c.theme_path, c.theme_name, c.theme_storedb, c.theme_id, i.imageset_path, i.imageset_id, i.imageset_name
 
1383
                        FROM ' . STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c, ' . STYLES_IMAGESET_TABLE . " i
 
1384
                        WHERE s.style_id = $style
 
1385
                                AND t.template_id = s.template_id
 
1386
                                AND c.theme_id = s.theme_id
 
1387
                                AND i.imageset_id = s.imageset_id";
 
1388
                $result = $db->sql_query($sql, 3600);
 
1389
                $this->theme = $db->sql_fetchrow($result);
 
1390
                $db->sql_freeresult($result);
 
1391
 
 
1392
                // User has wrong style
 
1393
                if (!$this->theme && $style == $this->data['user_style'])
 
1394
                {
 
1395
                        $style = $this->data['user_style'] = $config['default_style'];
 
1396
 
 
1397
                        $sql = 'UPDATE ' . USERS_TABLE . "
 
1398
                                SET user_style = $style
 
1399
                                WHERE user_id = {$this->data['user_id']}";
 
1400
                        $db->sql_query($sql);
 
1401
 
 
1402
                        $sql = 'SELECT s.style_id, t.template_storedb, t.template_path, t.template_id, t.bbcode_bitfield, c.theme_path, c.theme_name, c.theme_storedb, c.theme_id, i.imageset_path, i.imageset_id, i.imageset_name
 
1403
                                FROM ' . STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c, ' . STYLES_IMAGESET_TABLE . " i
 
1404
                                WHERE s.style_id = $style
 
1405
                                        AND t.template_id = s.template_id
 
1406
                                        AND c.theme_id = s.theme_id
 
1407
                                        AND i.imageset_id = s.imageset_id";
 
1408
                        $result = $db->sql_query($sql, 3600);
 
1409
                        $this->theme = $db->sql_fetchrow($result);
 
1410
                        $db->sql_freeresult($result);
 
1411
                }
 
1412
 
 
1413
                if (!$this->theme)
 
1414
                {
 
1415
                        trigger_error('Could not get style data', E_USER_ERROR);
 
1416
                }
 
1417
 
 
1418
                // Now parse the cfg file and cache it
 
1419
                $parsed_items = $cache->obtain_cfg_items($this->theme);
 
1420
 
 
1421
                // We are only interested in the theme configuration for now
 
1422
                $parsed_items = $parsed_items['theme'];
 
1423
 
 
1424
                $check_for = array(
 
1425
                        'parse_css_file'        => (int) 0,
 
1426
                        'pagination_sep'        => (string) ', '
 
1427
                );
 
1428
 
 
1429
                foreach ($check_for as $key => $default_value)
 
1430
                {
 
1431
                        $this->theme[$key] = (isset($parsed_items[$key])) ? $parsed_items[$key] : $default_value;
 
1432
                        settype($this->theme[$key], gettype($default_value));
 
1433
 
 
1434
                        if (is_string($default_value))
 
1435
                        {
 
1436
                                $this->theme[$key] = htmlspecialchars($this->theme[$key]);
 
1437
                        }
 
1438
                }
 
1439
 
 
1440
                // If the style author specified the theme needs to be cached
 
1441
                // (because of the used paths and variables) than make sure it is the case.
 
1442
                // For example, if the theme uses language-specific images it needs to be stored in db.
 
1443
                if (!$this->theme['theme_storedb'] && $this->theme['parse_css_file'])
 
1444
                {
 
1445
                        $this->theme['theme_storedb'] = 1;
 
1446
 
 
1447
                        $stylesheet = file_get_contents("{$phpbb_root_path}styles/{$this->theme['theme_path']}/theme/stylesheet.css");
 
1448
                        // Match CSS imports
 
1449
                        $matches = array();
 
1450
                        preg_match_all('/@import url\(["\'](.*)["\']\);/i', $stylesheet, $matches);
 
1451
 
 
1452
                        if (sizeof($matches))
 
1453
                        {
 
1454
                                $content = '';
 
1455
                                foreach ($matches[0] as $idx => $match)
 
1456
                                {
 
1457
                                        if ($content = @file_get_contents("{$phpbb_root_path}styles/{$this->theme['theme_path']}/theme/" . $matches[1][$idx]))
 
1458
                                        {
 
1459
                                                $content = trim($content);
 
1460
                                        }
 
1461
                                        else
 
1462
                                        {
 
1463
                                                $content = '';
 
1464
                                        }
 
1465
                                        $stylesheet = str_replace($match, $content, $stylesheet);
 
1466
                                }
 
1467
                                unset($content);
 
1468
                        }
 
1469
 
 
1470
                        $stylesheet = str_replace('./', 'styles/' . $this->theme['theme_path'] . '/theme/', $stylesheet);
 
1471
 
 
1472
                        $sql_ary = array(
 
1473
                                'theme_data'    => $stylesheet,
 
1474
                                'theme_mtime'   => time(),
 
1475
                                'theme_storedb' => 1
 
1476
                        );
 
1477
 
 
1478
                        $sql = 'UPDATE ' . STYLES_THEME_TABLE . '
 
1479
                                SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
 
1480
                                WHERE theme_id = ' . $this->theme['theme_id'];
 
1481
                        $db->sql_query($sql);
 
1482
 
 
1483
                        unset($sql_ary);
 
1484
                }
 
1485
 
 
1486
                $template->set_template();
 
1487
 
 
1488
                $this->img_lang = (file_exists($phpbb_root_path . 'styles/' . $this->theme['imageset_path'] . '/imageset/' . $this->lang_name)) ? $this->lang_name : $config['default_lang'];
 
1489
 
 
1490
                $sql = 'SELECT image_name, image_filename, image_lang, image_height, image_width
 
1491
                        FROM ' . STYLES_IMAGESET_DATA_TABLE . '
 
1492
                        WHERE imageset_id = ' . $this->theme['imageset_id'] . "
 
1493
                        AND image_lang IN ('" . $db->sql_escape($this->img_lang) . "', '')";
 
1494
                $result = $db->sql_query($sql, 3600);
 
1495
 
 
1496
                $localised_images = false;
 
1497
                while ($row = $db->sql_fetchrow($result))
 
1498
                {
 
1499
                        if ($row['image_lang'])
 
1500
                        {
 
1501
                                $localised_images = true;
 
1502
                        }
 
1503
 
 
1504
                        $this->img_array[$row['image_name']] = $row;
 
1505
                }
 
1506
                $db->sql_freeresult($result);
 
1507
 
 
1508
                // there were no localised images, try to refresh the localised imageset for the user's language
 
1509
                if (!$localised_images)
 
1510
                {
 
1511
                        // Attention: this code ignores the image definition list from acp_styles and just takes everything
 
1512
                        // that the config file contains
 
1513
                        $sql_ary = array();
 
1514
 
 
1515
                        $db->sql_transaction('begin');
 
1516
 
 
1517
                        $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . '
 
1518
                                WHERE imageset_id = ' . $this->theme['imageset_id'] . '
 
1519
                                        AND image_lang = \'' . $db->sql_escape($this->img_lang) . '\'';
 
1520
                        $result = $db->sql_query($sql);
 
1521
 
 
1522
                        if (@file_exists("{$phpbb_root_path}styles/{$this->theme['imageset_path']}/imageset/{$this->img_lang}/imageset.cfg"))
 
1523
                        {
 
1524
                                $cfg_data_imageset_data = parse_cfg_file("{$phpbb_root_path}styles/{$this->theme['imageset_path']}/imageset/{$this->img_lang}/imageset.cfg");
 
1525
                                foreach ($cfg_data_imageset_data as $image_name => $value)
 
1526
                                {
 
1527
                                        if (strpos($value, '*') !== false)
 
1528
                                        {
 
1529
                                                if (substr($value, -1, 1) === '*')
 
1530
                                                {
 
1531
                                                        list($image_filename, $image_height) = explode('*', $value);
 
1532
                                                        $image_width = 0;
 
1533
                                                }
 
1534
                                                else
 
1535
                                                {
 
1536
                                                        list($image_filename, $image_height, $image_width) = explode('*', $value);
 
1537
                                                }
 
1538
                                        }
 
1539
                                        else
 
1540
                                        {
 
1541
                                                $image_filename = $value;
 
1542
                                                $image_height = $image_width = 0;
 
1543
                                        }
 
1544
 
 
1545
                                        if (strpos($image_name, 'img_') === 0 && $image_filename)
 
1546
                                        {
 
1547
                                                $image_name = substr($image_name, 4);
 
1548
                                                $sql_ary[] = array(
 
1549
                                                        'image_name'            => (string) $image_name,
 
1550
                                                        'image_filename'        => (string) $image_filename,
 
1551
                                                        'image_height'          => (int) $image_height,
 
1552
                                                        'image_width'           => (int) $image_width,
 
1553
                                                        'imageset_id'           => (int) $this->theme['imageset_id'],
 
1554
                                                        'image_lang'            => (string) $this->img_lang,
 
1555
                                                );
 
1556
                                        }
 
1557
                                }
 
1558
                        }
 
1559
 
 
1560
                        if (sizeof($sql_ary))
 
1561
                        {
 
1562
                                $db->sql_multi_insert(STYLES_IMAGESET_DATA_TABLE, $sql_ary);
 
1563
                                $db->sql_transaction('commit');
 
1564
                                $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE);
 
1565
 
 
1566
                                add_log('admin', 'LOG_IMAGESET_LANG_REFRESHED', $this->theme['imageset_name'], $this->img_lang);
 
1567
                        }
 
1568
                        else
 
1569
                        {
 
1570
                                $db->sql_transaction('commit');
 
1571
                                add_log('admin', 'LOG_IMAGESET_LANG_MISSING', $this->theme['imageset_name'], $this->img_lang);
 
1572
                        }
 
1573
                }
 
1574
 
 
1575
                // Call phpbb_user_session_handler() in case external application want to "bend" some variables or replace classes...
 
1576
                // After calling it we continue script execution...
 
1577
                phpbb_user_session_handler();
 
1578
 
 
1579
                // If this function got called from the error handler we are finished here.
 
1580
                if (defined('IN_ERROR_HANDLER'))
 
1581
                {
 
1582
                        return;
 
1583
                }
 
1584
 
 
1585
                // Disable board if the install/ directory is still present
 
1586
                // For the brave development army we do not care about this, else we need to comment out this everytime we develop locally
 
1587
                if (!defined('DEBUG_EXTRA') && !defined('ADMIN_START') && !defined('IN_INSTALL') && !defined('IN_LOGIN') && file_exists($phpbb_root_path . 'install'))
 
1588
                {
 
1589
                        // Adjust the message slightly according to the permissions
 
1590
                        if ($auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_'))
 
1591
                        {
 
1592
                                $message = 'REMOVE_INSTALL';
 
1593
                        }
 
1594
                        else
 
1595
                        {
 
1596
                                $message = (!empty($config['board_disable_msg'])) ? $config['board_disable_msg'] : 'BOARD_DISABLE';
 
1597
                        }
 
1598
                        trigger_error($message);
 
1599
                }
 
1600
 
 
1601
                // Is board disabled and user not an admin or moderator?
 
1602
                if ($config['board_disable'] && !defined('IN_LOGIN') && !$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_'))
 
1603
                {
 
1604
                        header('HTTP/1.1 503 Service Unavailable');
 
1605
 
 
1606
                        $message = (!empty($config['board_disable_msg'])) ? $config['board_disable_msg'] : 'BOARD_DISABLE';
 
1607
                        trigger_error($message);
 
1608
                }
 
1609
 
 
1610
                // Is load exceeded?
 
1611
                if ($config['limit_load'] && $this->load !== false)
 
1612
                {
 
1613
                        if ($this->load > floatval($config['limit_load']) && !defined('IN_LOGIN'))
 
1614
                        {
 
1615
                                // Set board disabled to true to let the admins/mods get the proper notification
 
1616
                                $config['board_disable'] = '1';
 
1617
 
 
1618
                                if (!$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_'))
 
1619
                                {
 
1620
                                        header('HTTP/1.1 503 Service Unavailable');
 
1621
                                        trigger_error('BOARD_UNAVAILABLE');
 
1622
                                }
 
1623
                        }
 
1624
                }
 
1625
 
 
1626
                if (isset($this->data['session_viewonline']))
 
1627
                {
 
1628
                        // Make sure the user is able to hide his session
 
1629
                        if (!$this->data['session_viewonline'])
 
1630
                        {
 
1631
                                // Reset online status if not allowed to hide the session...
 
1632
                                if (!$auth->acl_get('u_hideonline'))
 
1633
                                {
 
1634
                                        $sql = 'UPDATE ' . SESSIONS_TABLE . '
 
1635
                                                SET session_viewonline = 1
 
1636
                                                WHERE session_user_id = ' . $this->data['user_id'];
 
1637
                                        $db->sql_query($sql);
 
1638
                                        $this->data['session_viewonline'] = 1;
 
1639
                                }
 
1640
                        }
 
1641
                        else if (!$this->data['user_allow_viewonline'])
 
1642
                        {
 
1643
                                // the user wants to hide and is allowed to  -> cloaking device on.
 
1644
                                if ($auth->acl_get('u_hideonline'))
 
1645
                                {
 
1646
                                        $sql = 'UPDATE ' . SESSIONS_TABLE . '
 
1647
                                                SET session_viewonline = 0
 
1648
                                                WHERE session_user_id = ' . $this->data['user_id'];
 
1649
                                        $db->sql_query($sql);
 
1650
                                        $this->data['session_viewonline'] = 0;
 
1651
                                }
 
1652
                        }
 
1653
                }
 
1654
 
 
1655
 
 
1656
                // Does the user need to change their password? If so, redirect to the
 
1657
                // ucp profile reg_details page ... of course do not redirect if we're already in the ucp
 
1658
                if (!defined('IN_ADMIN') && !defined('ADMIN_START') && $config['chg_passforce'] && $this->data['is_registered'] && $auth->acl_get('u_chgpasswd') && $this->data['user_passchg'] < time() - ($config['chg_passforce'] * 86400))
 
1659
                {
 
1660
                        if (strpos($this->page['query_string'], 'mode=reg_details') === false && $this->page['page_name'] != "ucp.$phpEx")
 
1661
                        {
 
1662
                                redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=profile&amp;mode=reg_details'));
 
1663
                        }
 
1664
                }
 
1665
 
 
1666
                return;
 
1667
        }
 
1668
 
 
1669
        /**
 
1670
        * Add Language Items - use_db and use_help are assigned where needed (only use them to force inclusion)
 
1671
        *
 
1672
        * @param mixed $lang_set specifies the language entries to include
 
1673
        * @param bool $use_db internal variable for recursion, do not use
 
1674
        * @param bool $use_help internal variable for recursion, do not use
 
1675
        *
 
1676
        * Examples:
 
1677
        * <code>
 
1678
        * $lang_set = array('posting', 'help' => 'faq');
 
1679
        * $lang_set = array('posting', 'viewtopic', 'help' => array('bbcode', 'faq'))
 
1680
        * $lang_set = array(array('posting', 'viewtopic'), 'help' => array('bbcode', 'faq'))
 
1681
        * $lang_set = 'posting'
 
1682
        * $lang_set = array('help' => 'faq', 'db' => array('help:faq', 'posting'))
 
1683
        * </code>
 
1684
        */
 
1685
        function add_lang($lang_set, $use_db = false, $use_help = false)
 
1686
        {
 
1687
                global $phpEx;
 
1688
 
 
1689
                if (is_array($lang_set))
 
1690
                {
 
1691
                        foreach ($lang_set as $key => $lang_file)
 
1692
                        {
 
1693
                                // Please do not delete this line.
 
1694
                                // We have to force the type here, else [array] language inclusion will not work
 
1695
                                $key = (string) $key;
 
1696
 
 
1697
                                if ($key == 'db')
 
1698
                                {
 
1699
                                        $this->add_lang($lang_file, true, $use_help);
 
1700
                                }
 
1701
                                else if ($key == 'help')
 
1702
                                {
 
1703
                                        $this->add_lang($lang_file, $use_db, true);
 
1704
                                }
 
1705
                                else if (!is_array($lang_file))
 
1706
                                {
 
1707
                                        $this->set_lang($this->lang, $this->help, $lang_file, $use_db, $use_help);
 
1708
                                }
 
1709
                                else
 
1710
                                {
 
1711
                                        $this->add_lang($lang_file, $use_db, $use_help);
 
1712
                                }
 
1713
                        }
 
1714
                        unset($lang_set);
 
1715
                }
 
1716
                else if ($lang_set)
 
1717
                {
 
1718
                        $this->set_lang($this->lang, $this->help, $lang_set, $use_db, $use_help);
 
1719
                }
 
1720
        }
 
1721
 
 
1722
        /**
 
1723
        * Set language entry (called by add_lang)
 
1724
        * @access private
 
1725
        */
 
1726
        function set_lang(&$lang, &$help, $lang_file, $use_db = false, $use_help = false)
 
1727
        {
 
1728
                global $phpEx;
 
1729
 
 
1730
                // Make sure the language path is set (if the user setup did not happen it is not set)
 
1731
                if (!$this->lang_path)
 
1732
                {
 
1733
                        global $phpbb_root_path, $config;
 
1734
 
 
1735
                        $this->lang_path = $phpbb_root_path . 'language/' . basename($config['default_lang']) . '/';
 
1736
                }
 
1737
 
 
1738
                // $lang == $this->lang
 
1739
                // $help == $this->help
 
1740
                // - add appropriate variables here, name them as they are used within the language file...
 
1741
                if (!$use_db)
 
1742
                {
 
1743
                        if ($use_help && strpos($lang_file, '/') !== false)
 
1744
                        {
 
1745
                                $language_filename = $this->lang_path . substr($lang_file, 0, stripos($lang_file, '/') + 1) . 'help_' . substr($lang_file, stripos($lang_file, '/') + 1) . '.' . $phpEx;
 
1746
                        }
 
1747
                        else
 
1748
                        {
 
1749
                                $language_filename = $this->lang_path . (($use_help) ? 'help_' : '') . $lang_file . '.' . $phpEx;
 
1750
                        }
 
1751
 
 
1752
                        if ((@include $language_filename) === false)
 
1753
                        {
 
1754
                                trigger_error('Language file ' . basename($language_filename) . ' couldn\'t be opened.', E_USER_ERROR);
 
1755
                        }
 
1756
                }
 
1757
                else if ($use_db)
 
1758
                {
 
1759
                        // Get Database Language Strings
 
1760
                        // Put them into $lang if nothing is prefixed, put them into $help if help: is prefixed
 
1761
                        // For example: help:faq, posting
 
1762
                }
 
1763
        }
 
1764
 
 
1765
        /**
 
1766
        * Format user date
 
1767
        */
 
1768
        function format_date($gmepoch, $format = false, $forcedate = false)
 
1769
        {
 
1770
                static $midnight;
 
1771
 
 
1772
                $lang_dates = $this->lang['datetime'];
 
1773
                $format = (!$format) ? $this->date_format : $format;
 
1774
 
 
1775
                // Short representation of month in format
 
1776
                if ((strpos($format, '\M') === false && strpos($format, 'M') !== false) || (strpos($format, '\r') === false && strpos($format, 'r') !== false))
 
1777
                {
 
1778
                        $lang_dates['May'] = $lang_dates['May_short'];
 
1779
                }
 
1780
 
 
1781
                unset($lang_dates['May_short']);
 
1782
 
 
1783
                if (!$midnight)
 
1784
                {
 
1785
                        list($d, $m, $y) = explode(' ', gmdate('j n Y', time() + $this->timezone + $this->dst));
 
1786
                        $midnight = gmmktime(0, 0, 0, $m, $d, $y) - $this->timezone - $this->dst;
 
1787
                }
 
1788
 
 
1789
                if (strpos($format, '|') === false || ($gmepoch < $midnight - 86400 && !$forcedate) || ($gmepoch > $midnight + 172800 && !$forcedate))
 
1790
                {
 
1791
                        return strtr(@gmdate(str_replace('|', '', $format), $gmepoch + $this->timezone + $this->dst), $lang_dates);
 
1792
                }
 
1793
 
 
1794
                if ($gmepoch > $midnight + 86400 && !$forcedate)
 
1795
                {
 
1796
                        $format = substr($format, 0, strpos($format, '|')) . '||' . substr(strrchr($format, '|'), 1);
 
1797
                        return str_replace('||', $this->lang['datetime']['TOMORROW'], strtr(@gmdate($format, $gmepoch + $this->timezone + $this->dst), $lang_dates));
 
1798
                }
 
1799
                else if ($gmepoch > $midnight && !$forcedate)
 
1800
                {
 
1801
                        $format = substr($format, 0, strpos($format, '|')) . '||' . substr(strrchr($format, '|'), 1);
 
1802
                        return str_replace('||', $this->lang['datetime']['TODAY'], strtr(@gmdate($format, $gmepoch + $this->timezone + $this->dst), $lang_dates));
 
1803
                }
 
1804
                else if ($gmepoch > $midnight - 86400 && !$forcedate)
 
1805
                {
 
1806
                        $format = substr($format, 0, strpos($format, '|')) . '||' . substr(strrchr($format, '|'), 1);
 
1807
                        return str_replace('||', $this->lang['datetime']['YESTERDAY'], strtr(@gmdate($format, $gmepoch + $this->timezone + $this->dst), $lang_dates));
 
1808
                }
 
1809
 
 
1810
                return strtr(@gmdate(str_replace('|', '', $format), $gmepoch + $this->timezone + $this->dst), $lang_dates);
 
1811
        }
 
1812
 
 
1813
        /**
 
1814
        * Get language id currently used by the user
 
1815
        */
 
1816
        function get_iso_lang_id()
 
1817
        {
 
1818
                global $config, $db;
 
1819
 
 
1820
                if (!empty($this->lang_id))
 
1821
                {
 
1822
                        return $this->lang_id;
 
1823
                }
 
1824
 
 
1825
                if (!$this->lang_name)
 
1826
                {
 
1827
                        $this->lang_name = $config['default_lang'];
 
1828
                }
 
1829
 
 
1830
                $sql = 'SELECT lang_id
 
1831
                        FROM ' . LANG_TABLE . "
 
1832
                        WHERE lang_iso = '" . $db->sql_escape($this->lang_name) . "'";
 
1833
                $result = $db->sql_query($sql);
 
1834
                $this->lang_id = (int) $db->sql_fetchfield('lang_id');
 
1835
                $db->sql_freeresult($result);
 
1836
 
 
1837
                return $this->lang_id;
 
1838
        }
 
1839
 
 
1840
        /**
 
1841
        * Get users profile fields
 
1842
        */
 
1843
        function get_profile_fields($user_id)
 
1844
        {
 
1845
                global $db;
 
1846
 
 
1847
                if (isset($this->profile_fields))
 
1848
                {
 
1849
                        return;
 
1850
                }
 
1851
 
 
1852
                $sql = 'SELECT *
 
1853
                        FROM ' . PROFILE_FIELDS_DATA_TABLE . "
 
1854
                        WHERE user_id = $user_id";
 
1855
                $result = $db->sql_query_limit($sql, 1);
 
1856
                $this->profile_fields = (!($row = $db->sql_fetchrow($result))) ? array() : $row;
 
1857
                $db->sql_freeresult($result);
 
1858
        }
 
1859
 
 
1860
        /**
 
1861
        * Specify/Get image
 
1862
        */
 
1863
        function img($img, $alt = '', $width = false, $suffix = '', $type = 'full_tag')
 
1864
        {
 
1865
                static $imgs;
 
1866
                global $phpbb_root_path;
 
1867
 
 
1868
                $img_data = &$imgs[$img];
 
1869
 
 
1870
                if (empty($img_data))
 
1871
                {
 
1872
                        if (!isset($this->img_array[$img]))
 
1873
                        {
 
1874
                                // Do not fill the image to let designers decide what to do if the image is empty
 
1875
                                $img_data = '';
 
1876
                                return $img_data;
 
1877
                        }
 
1878
 
 
1879
                        $img_data['src'] = $phpbb_root_path . 'styles/' . $this->theme['imageset_path'] . '/imageset/' . ($this->img_array[$img]['image_lang'] ? $this->img_array[$img]['image_lang'] .'/' : '') . $this->img_array[$img]['image_filename'];
 
1880
                        $img_data['width'] = $this->img_array[$img]['image_width'];
 
1881
                        $img_data['height'] = $this->img_array[$img]['image_height'];
 
1882
                }
 
1883
 
 
1884
                $alt = (!empty($this->lang[$alt])) ? $this->lang[$alt] : $alt;
 
1885
 
 
1886
                switch ($type)
 
1887
                {
 
1888
                        case 'src':
 
1889
                                return $img_data['src'];
 
1890
                        break;
 
1891
 
 
1892
                        case 'width':
 
1893
                                return ($width === false) ? $img_data['width'] : $width;
 
1894
                        break;
 
1895
 
 
1896
                        case 'height':
 
1897
                                return $img_data['height'];
 
1898
                        break;
 
1899
 
 
1900
                        default:
 
1901
                                $use_width = ($width === false) ? $img_data['width'] : $width;
 
1902
 
 
1903
                                return '<img src="' . $img_data['src'] . '"' . (($use_width) ? ' width="' . $use_width . '"' : '') . (($img_data['height']) ? ' height="' . $img_data['height'] . '"' : '') . ' alt="' . $alt . '" title="' . $alt . '" />';
 
1904
                        break;
 
1905
                }
 
1906
        }
 
1907
 
 
1908
        /**
 
1909
        * Get option bit field from user options
 
1910
        */
 
1911
        function optionget($key, $data = false)
 
1912
        {
 
1913
                if (!isset($this->keyvalues[$key]))
 
1914
                {
 
1915
                        $var = ($data) ? $data : $this->data['user_options'];
 
1916
                        $this->keyvalues[$key] = ($var & 1 << $this->keyoptions[$key]) ? true : false;
 
1917
                }
 
1918
 
 
1919
                return $this->keyvalues[$key];
 
1920
        }
 
1921
 
 
1922
        /**
 
1923
        * Set option bit field for user options
 
1924
        */
 
1925
        function optionset($key, $value, $data = false)
 
1926
        {
 
1927
                $var = ($data) ? $data : $this->data['user_options'];
 
1928
 
 
1929
                if ($value && !($var & 1 << $this->keyoptions[$key]))
 
1930
                {
 
1931
                        $var += 1 << $this->keyoptions[$key];
 
1932
                }
 
1933
                else if (!$value && ($var & 1 << $this->keyoptions[$key]))
 
1934
                {
 
1935
                        $var -= 1 << $this->keyoptions[$key];
 
1936
                }
 
1937
                else
 
1938
                {
 
1939
                        return ($data) ? $var : false;
 
1940
                }
 
1941
 
 
1942
                if (!$data)
 
1943
                {
 
1944
                        $this->data['user_options'] = $var;
 
1945
                        return true;
 
1946
                }
 
1947
                else
 
1948
                {
 
1949
                        return $var;
 
1950
                }
 
1951
  }
 
1952
 
 
1953
  /** IVLE AUTH
 
1954
   * This function attempts to authenticate from a signed cookie provided by 
 
1955
   * IVLE. If it does it will return either the forum user_id for the logged in 
 
1956
   * IVLE user or will create a new one on-the-fly.
 
1957
   * 
 
1958
   * If a bad authentication is given then the ANONAMOUS user will be returned
 
1959
   */
 
1960
  function ivle_auth()
 
1961
  {
 
1962
        global $db, $phpEx;
 
1963
 
 
1964
        // Get the shared secret between IVLE and the Forum
 
1965
        require($phpbb_root_path . 'config.' . $phpEx);
 
1966
 
 
1967
        // Shared Cookie
 
1968
        $ivle_cookie = explode(':',$_COOKIE['ivleforumcookie']);
 
1969
   
 
1970
        if ($ivle_cookie == "NONE") {
 
1971
                return ANONYMOUS;
 
1972
        }
 
1973
 
 
1974
        // Decode and unescape the Cookie contents
 
1975
        $ivle_uid = urldecode($ivle_cookie[0]);
 
1976
        $ivle_nick = urldecode($ivle_cookie[1]);
 
1977
        $ivle_email = urldecode($ivle_cookie[2]);
 
1978
        $ivle_role = urldecode($ivle_cookie[3]);
 
1979
        $ivle_hash = $ivle_cookie[4];
 
1980
 
 
1981
        // Check if uid + nick + email + secret is the same as the hash
 
1982
        //$ivle_auth = False; // Flag just incase anything else need to know
 
1983
        if(md5($ivle_cookie[0].$ivle_cookie[1].$ivle_cookie[2].$ivle_cookie[3].$forum_secret) 
 
1984
        == $ivle_hash) {
 
1985
          //$ivle_auth = True;
 
1986
        
 
1987
        // Check if the user exists in the database
 
1988
        $sql = 'SELECT user_id
 
1989
                FROM ' . USERS_TABLE . "
 
1990
                WHERE username = '" . $db->sql_escape($ivle_uid) . "';";
 
1991
                $result = $db->sql_query($sql);
 
1992
                $row = $db->sql_fetchrow($result);
 
1993
                $user_id = $row['user_id'];
 
1994
                $db->sql_freeresult($result);
 
1995
 
 
1996
        // If no user_id is found for the username, create a new user
 
1997
        if(!$user_id) {
 
1998
                // Needed for IVLE auth overide
 
1999
                include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx);
 
2000
           
 
2001
                // Add all users to the Registered Group
 
2002
                $sql = 'SELECT group_id
 
2003
                        FROM ' . GROUPS_TABLE . "
 
2004
                        WHERE group_name = '" . $db->sql_escape('REGISTERED') . "'
 
2005
                        AND group_type = " . GROUP_SPECIAL;
 
2006
                $result = $db->sql_query($sql);
 
2007
                $row = $db->sql_fetchrow($result);
 
2008
                $db->sql_freeresult($result);
 
2009
                if (!$row) {
 
2010
                        trigger_error('NO_GROUP');
 
2011
                }
 
2012
 
 
2013
                $group_id = $row['group_id'];
 
2014
 
 
2015
                // Get the Time and Timezone
 
2016
                $timezone = date('Z') / 3600;
 
2017
                $is_dst = date('I');
 
2018
                $timezone = ($is_dst) ? $timezone - 1 : $timezone;
 
2019
                        
 
2020
                // Fill into array
 
2021
                $user_row = array(
 
2022
                        'username'                              => $ivle_uid,
 
2023
                        'user_password'                 => '', # Not a valid hash
 
2024
                        'user_email'                    => $ivle_email,
 
2025
                        'group_id'                              => (int) $group_id,
 
2026
                        'user_timezone'                 => (float) $timezone,
 
2027
                        'user_dst'                              => $is_dst,
 
2028
                        'user_lang'                             => 'en',
 
2029
                        'user_type'                             => USER_NORMAL,
 
2030
                        'user_actkey'                   => '',
 
2031
                        'user_ip'                               => $this->ip,
 
2032
                        'user_regdate'                  => time(),
 
2033
                        'user_inactive_reason'  => 0,
 
2034
                        'user_inactive_time'    => 0,
 
2035
                );
 
2036
                 
 
2037
                // Add user
 
2038
                $user_id = user_add($user_row);
 
2039
 
 
2040
                // Add any aditional groups
 
2041
                // Select the equvialent group
 
2042
                $group = False;
 
2043
                switch($ivle_role) {
 
2044
                        case('admin'):
 
2045
                                $group = 'ADMINISTRATORS';
 
2046
                                break;
 
2047
                        case('lecturer'):
 
2048
                                $group = 'GLOBAL_MODERATORS';
 
2049
                                break;
 
2050
                }
 
2051
                if ($group) {
 
2052
                        // Find the group_id
 
2053
                        $sql = 'SELECT group_id
 
2054
                                FROM ' . GROUPS_TABLE . "
 
2055
                                WHERE group_name = '" . $db->sql_escape($group) . "'
 
2056
                                AND group_type = " . GROUP_SPECIAL;
 
2057
                        
 
2058
                        $result = $db->sql_query($sql);
 
2059
                        $row = $db->sql_fetchrow($result);
 
2060
                        $db->sql_freeresult($result);
 
2061
 
 
2062
                        if (!$row) {
 
2063
                                trigger_error('NO_GROUP');
 
2064
                        }
 
2065
 
 
2066
                        $group_id = $row['group_id'];
 
2067
 
 
2068
                        group_user_add($group_id,Array($user_id));
 
2069
                }
 
2070
          }
 
2071
          return $user_id;
 
2072
        } else {
 
2073
          return False;
 
2074
        }
 
2075
  }
 
2076
}
 
2077
?>