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

« back to all changes in this revision

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

  • Committer: William Grant
  • Date: 2009-02-23 23:47:02 UTC
  • mfrom: (1099.1.211 new-dispatch)
  • Revision ID: grantw@unimelb.edu.au-20090223234702-db4b1llly46ignwo
Merge from lp:~ivle-dev/ivle/new-dispatch.

Pretty much everything changes. Reread the setup docs. Backup your databases.
Every file is now in a different installed location, the configuration system
is rewritten, the dispatch system is rewritten, URLs are different, the
database is different, worksheets and exercises are no longer on the
filesystem, we use a templating engine, jail service protocols are rewritten,
we don't repeat ourselves, we have authorization rewritten, phpBB is gone,
and probably lots of other things that I cannot remember.

This is certainly the biggest commit I have ever made, and hopefully
the largest I ever will.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?php
2
 
/**
3
 
*
4
 
* @package phpBB3
5
 
* @version $Id: functions.php,v 1.647 2007/12/10 18:35:28 kellanved 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
 
// Common global functions
20
 
 
21
 
/**
22
 
* set_var
23
 
*
24
 
* Set variable, used by {@link request_var the request_var function}
25
 
*
26
 
* @access private
27
 
*/
28
 
function set_var(&$result, $var, $type, $multibyte = false)
29
 
{
30
 
        settype($var, $type);
31
 
        $result = $var;
32
 
 
33
 
        if ($type == 'string')
34
 
        {
35
 
                $result = trim(htmlspecialchars(str_replace(array("\r\n", "\r"), array("\n", "\n"), $result), ENT_COMPAT, 'UTF-8'));
36
 
 
37
 
                if (!empty($result))
38
 
                {
39
 
                        // Make sure multibyte characters are wellformed
40
 
                        if ($multibyte)
41
 
                        {
42
 
                                if (!preg_match('/^./u', $result))
43
 
                                {
44
 
                                        $result = '';
45
 
                                }
46
 
                        }
47
 
                        else
48
 
                        {
49
 
                                // no multibyte, allow only ASCII (0-127)
50
 
                                $result = preg_replace('/[\x80-\xFF]/', '?', $result);
51
 
                        }
52
 
                }
53
 
 
54
 
                $result = (STRIP) ? stripslashes($result) : $result;
55
 
        }
56
 
}
57
 
 
58
 
/**
59
 
* request_var
60
 
*
61
 
* Used to get passed variable
62
 
*/
63
 
function request_var($var_name, $default, $multibyte = false, $cookie = false)
64
 
{
65
 
        if (!$cookie && isset($_COOKIE[$var_name]))
66
 
        {
67
 
                if (!isset($_GET[$var_name]) && !isset($_POST[$var_name]))
68
 
                {
69
 
                        return (is_array($default)) ? array() : $default;
70
 
                }
71
 
                $_REQUEST[$var_name] = isset($_POST[$var_name]) ? $_POST[$var_name] : $_GET[$var_name];
72
 
        }
73
 
 
74
 
        if (!isset($_REQUEST[$var_name]) || (is_array($_REQUEST[$var_name]) && !is_array($default)) || (is_array($default) && !is_array($_REQUEST[$var_name])))
75
 
        {
76
 
                return (is_array($default)) ? array() : $default;
77
 
        }
78
 
 
79
 
        $var = $_REQUEST[$var_name];
80
 
        if (!is_array($default))
81
 
        {
82
 
                $type = gettype($default);
83
 
        }
84
 
        else
85
 
        {
86
 
                list($key_type, $type) = each($default);
87
 
                $type = gettype($type);
88
 
                $key_type = gettype($key_type);
89
 
                if ($type == 'array')
90
 
                {
91
 
                        reset($default);
92
 
                        $default = current($default);
93
 
                        list($sub_key_type, $sub_type) = each($default);
94
 
                        $sub_type = gettype($sub_type);
95
 
                        $sub_type = ($sub_type == 'array') ? 'NULL' : $sub_type;
96
 
                        $sub_key_type = gettype($sub_key_type);
97
 
                }
98
 
        }
99
 
 
100
 
        if (is_array($var))
101
 
        {
102
 
                $_var = $var;
103
 
                $var = array();
104
 
 
105
 
                foreach ($_var as $k => $v)
106
 
                {
107
 
                        set_var($k, $k, $key_type);
108
 
                        if ($type == 'array' && is_array($v))
109
 
                        {
110
 
                                foreach ($v as $_k => $_v)
111
 
                                {
112
 
                                        if (is_array($_v))
113
 
                                        {
114
 
                                                $_v = null;
115
 
                                        }
116
 
                                        set_var($_k, $_k, $sub_key_type);
117
 
                                        set_var($var[$k][$_k], $_v, $sub_type, $multibyte);
118
 
                                }
119
 
                        }
120
 
                        else
121
 
                        {
122
 
                                if ($type == 'array' || is_array($v))
123
 
                                {
124
 
                                        $v = null;
125
 
                                }
126
 
                                set_var($var[$k], $v, $type, $multibyte);
127
 
                        }
128
 
                }
129
 
        }
130
 
        else
131
 
        {
132
 
                set_var($var, $var, $type, $multibyte);
133
 
        }
134
 
 
135
 
        return $var;
136
 
}
137
 
 
138
 
/**
139
 
* Set config value. Creates missing config entry.
140
 
*/
141
 
function set_config($config_name, $config_value, $is_dynamic = false)
142
 
{
143
 
        global $db, $cache, $config;
144
 
 
145
 
        $sql = 'UPDATE ' . CONFIG_TABLE . "
146
 
                SET config_value = '" . $db->sql_escape($config_value) . "'
147
 
                WHERE config_name = '" . $db->sql_escape($config_name) . "'";
148
 
        $db->sql_query($sql);
149
 
 
150
 
        if (!$db->sql_affectedrows() && !isset($config[$config_name]))
151
 
        {
152
 
                $sql = 'INSERT INTO ' . CONFIG_TABLE . ' ' . $db->sql_build_array('INSERT', array(
153
 
                        'config_name'   => $config_name,
154
 
                        'config_value'  => $config_value,
155
 
                        'is_dynamic'    => ($is_dynamic) ? 1 : 0));
156
 
                $db->sql_query($sql);
157
 
        }
158
 
 
159
 
        $config[$config_name] = $config_value;
160
 
 
161
 
        if (!$is_dynamic)
162
 
        {
163
 
                $cache->destroy('config');
164
 
        }
165
 
}
166
 
 
167
 
/**
168
 
* Generates an alphanumeric random string of given length
169
 
*/
170
 
function gen_rand_string($num_chars = 8)
171
 
{
172
 
        $rand_str = unique_id();
173
 
        $rand_str = str_replace('0', 'Z', strtoupper(base_convert($rand_str, 16, 35)));
174
 
 
175
 
        return substr($rand_str, 0, $num_chars);
176
 
}
177
 
 
178
 
/**
179
 
* Return unique id
180
 
* @param string $extra additional entropy
181
 
*/
182
 
function unique_id($extra = 'c')
183
 
{
184
 
        static $dss_seeded = false;
185
 
        global $config;
186
 
 
187
 
        $val = $config['rand_seed'] . microtime();
188
 
        $val = md5($val);
189
 
        $config['rand_seed'] = md5($config['rand_seed'] . $val . $extra);
190
 
 
191
 
        if ($dss_seeded !== true && ($config['rand_seed_last_update'] < time() - rand(1,10)))
192
 
        {
193
 
                set_config('rand_seed', $config['rand_seed'], true);
194
 
                set_config('rand_seed_last_update', time(), true);
195
 
                $dss_seeded = true;
196
 
        }
197
 
 
198
 
        return substr($val, 4, 16);
199
 
}
200
 
 
201
 
/**
202
 
* Determine whether we are approaching the maximum execution time. Should be called once
203
 
* at the beginning of the script in which it's used.
204
 
* @return       bool    Either true if the maximum execution time is nearly reached, or false
205
 
*                                       if some time is still left.
206
 
*/
207
 
function still_on_time($extra_time = 15)
208
 
{
209
 
        static $max_execution_time, $start_time;
210
 
 
211
 
        $time = explode(' ', microtime());
212
 
        $current_time = $time[0] + $time[1];
213
 
 
214
 
        if (empty($max_execution_time))
215
 
        {
216
 
                $max_execution_time = (function_exists('ini_get')) ? (int) @ini_get('max_execution_time') : (int) @get_cfg_var('max_execution_time');
217
 
 
218
 
                // If zero, then set to something higher to not let the user catch the ten seconds barrier.
219
 
                if ($max_execution_time === 0)
220
 
                {
221
 
                        $max_execution_time = 50 + $extra_time;
222
 
                }
223
 
 
224
 
                $max_execution_time = min(max(10, ($max_execution_time - $extra_time)), 50);
225
 
 
226
 
                // For debugging purposes
227
 
                // $max_execution_time = 10;
228
 
 
229
 
                global $starttime;
230
 
                $start_time = (empty($starttime)) ? $current_time : $starttime;
231
 
        }
232
 
 
233
 
        return (ceil($current_time - $start_time) < $max_execution_time) ? true : false;
234
 
}
235
 
 
236
 
/**
237
 
*
238
 
* @version Version 0.1 / $Id: functions.php,v 1.647 2007/12/10 18:35:28 kellanved Exp $
239
 
*
240
 
* Portable PHP password hashing framework.
241
 
*
242
 
* Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in
243
 
* the public domain.
244
 
*
245
 
* There's absolutely no warranty.
246
 
*
247
 
* The homepage URL for this framework is:
248
 
*
249
 
*       http://www.openwall.com/phpass/
250
 
*
251
 
* Please be sure to update the Version line if you edit this file in any way.
252
 
* It is suggested that you leave the main version number intact, but indicate
253
 
* your project name (after the slash) and add your own revision information.
254
 
*
255
 
* Please do not change the "private" password hashing method implemented in
256
 
* here, thereby making your hashes incompatible.  However, if you must, please
257
 
* change the hash type identifier (the "$P$") to something different.
258
 
*
259
 
* Obviously, since this code is in the public domain, the above are not
260
 
* requirements (there can be none), but merely suggestions.
261
 
*
262
 
*
263
 
* Hash the password
264
 
*/
265
 
function phpbb_hash($password)
266
 
{
267
 
        $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
268
 
 
269
 
        $random_state = unique_id();
270
 
        $random = '';
271
 
        $count = 6;
272
 
 
273
 
        if (($fh = @fopen('/dev/urandom', 'rb')))
274
 
        {
275
 
                $random = fread($fh, $count);
276
 
                fclose($fh);
277
 
        }
278
 
 
279
 
        if (strlen($random) < $count)
280
 
        {
281
 
                $random = '';
282
 
 
283
 
                for ($i = 0; $i < $count; $i += 16)
284
 
                {
285
 
                        $random_state = md5(unique_id() . $random_state);
286
 
                        $random .= pack('H*', md5($random_state));
287
 
                }
288
 
                $random = substr($random, 0, $count);
289
 
        }
290
 
        
291
 
        $hash = _hash_crypt_private($password, _hash_gensalt_private($random, $itoa64), $itoa64);
292
 
 
293
 
        if (strlen($hash) == 34)
294
 
        {
295
 
                return $hash;
296
 
        }
297
 
 
298
 
        return md5($password);
299
 
}
300
 
 
301
 
/**
302
 
* Check for correct password
303
 
*/
304
 
function phpbb_check_hash($password, $hash)
305
 
{
306
 
        $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
307
 
        if (strlen($hash) == 34)
308
 
        {
309
 
                return (_hash_crypt_private($password, $hash, $itoa64) === $hash) ? true : false;
310
 
        }
311
 
 
312
 
        return (md5($password) === $hash) ? true : false;
313
 
}
314
 
 
315
 
/**
316
 
* Generate salt for hash generation
317
 
*/
318
 
function _hash_gensalt_private($input, &$itoa64, $iteration_count_log2 = 6)
319
 
{
320
 
        if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31)
321
 
        {
322
 
                $iteration_count_log2 = 8;
323
 
        }
324
 
 
325
 
        $output = '$H$';
326
 
        $output .= $itoa64[min($iteration_count_log2 + ((PHP_VERSION >= 5) ? 5 : 3), 30)];
327
 
        $output .= _hash_encode64($input, 6, $itoa64);
328
 
 
329
 
        return $output;
330
 
}
331
 
 
332
 
/**
333
 
* Encode hash
334
 
*/
335
 
function _hash_encode64($input, $count, &$itoa64)
336
 
{
337
 
        $output = '';
338
 
        $i = 0;
339
 
 
340
 
        do
341
 
        {
342
 
                $value = ord($input[$i++]);
343
 
                $output .= $itoa64[$value & 0x3f];
344
 
 
345
 
                if ($i < $count)
346
 
                {
347
 
                        $value |= ord($input[$i]) << 8;
348
 
                }
349
 
 
350
 
                $output .= $itoa64[($value >> 6) & 0x3f];
351
 
 
352
 
                if ($i++ >= $count)
353
 
                {
354
 
                        break;
355
 
                }
356
 
 
357
 
                if ($i < $count)
358
 
                {
359
 
                        $value |= ord($input[$i]) << 16;
360
 
                }
361
 
 
362
 
                $output .= $itoa64[($value >> 12) & 0x3f];
363
 
                
364
 
                if ($i++ >= $count)
365
 
                {
366
 
                        break;
367
 
                }
368
 
 
369
 
                $output .= $itoa64[($value >> 18) & 0x3f];
370
 
        }
371
 
        while ($i < $count);
372
 
 
373
 
        return $output;
374
 
}
375
 
 
376
 
/**
377
 
* The crypt function/replacement
378
 
*/
379
 
function _hash_crypt_private($password, $setting, &$itoa64)
380
 
{
381
 
        $output = '*';
382
 
 
383
 
        // Check for correct hash
384
 
        if (substr($setting, 0, 3) != '$H$')
385
 
        {
386
 
                return $output;
387
 
        }
388
 
 
389
 
        $count_log2 = strpos($itoa64, $setting[3]);
390
 
 
391
 
        if ($count_log2 < 7 || $count_log2 > 30)
392
 
        {
393
 
                return $output;
394
 
        }
395
 
 
396
 
        $count = 1 << $count_log2;
397
 
        $salt = substr($setting, 4, 8);
398
 
 
399
 
        if (strlen($salt) != 8)
400
 
        {
401
 
                return $output;
402
 
        }
403
 
 
404
 
        /**
405
 
        * We're kind of forced to use MD5 here since it's the only
406
 
        * cryptographic primitive available in all versions of PHP
407
 
        * currently in use.  To implement our own low-level crypto
408
 
        * in PHP would result in much worse performance and
409
 
        * consequently in lower iteration counts and hashes that are
410
 
        * quicker to crack (by non-PHP code).
411
 
        */
412
 
        if (PHP_VERSION >= 5)
413
 
        {
414
 
                $hash = md5($salt . $password, true);
415
 
                do
416
 
                {
417
 
                        $hash = md5($hash . $password, true);
418
 
                }
419
 
                while (--$count);
420
 
        }
421
 
        else
422
 
        {
423
 
                $hash = pack('H*', md5($salt . $password));
424
 
                do
425
 
                {
426
 
                        $hash = pack('H*', md5($hash . $password));
427
 
                }
428
 
                while (--$count);
429
 
        }
430
 
 
431
 
        $output = substr($setting, 0, 12);
432
 
        $output .= _hash_encode64($hash, 16, $itoa64);
433
 
 
434
 
        return $output;
435
 
}
436
 
 
437
 
// Compatibility functions
438
 
 
439
 
if (!function_exists('array_combine'))
440
 
{
441
 
        /**
442
 
        * A wrapper for the PHP5 function array_combine()
443
 
        * @param array $keys contains keys for the resulting array
444
 
        * @param array $values contains values for the resulting array
445
 
        *
446
 
        * @return Returns an array by using the values from the keys array as keys and the
447
 
        *       values from the values array as the corresponding values. Returns false if the
448
 
        *       number of elements for each array isn't equal or if the arrays are empty.
449
 
        */
450
 
        function array_combine($keys, $values)
451
 
        {
452
 
                $keys = array_values($keys);
453
 
                $values = array_values($values);
454
 
 
455
 
                $n = sizeof($keys);
456
 
                $m = sizeof($values);
457
 
                if (!$n || !$m || ($n != $m))
458
 
                {
459
 
                        return false;
460
 
                }
461
 
 
462
 
                $combined = array();
463
 
                for ($i = 0; $i < $n; $i++)
464
 
                {
465
 
                        $combined[$keys[$i]] = $values[$i];
466
 
                }
467
 
                return $combined;
468
 
        }
469
 
}
470
 
 
471
 
if (!function_exists('str_split'))
472
 
{
473
 
        /**
474
 
        * A wrapper for the PHP5 function str_split()
475
 
        * @param array $string contains the string to be converted
476
 
        * @param array $split_length contains the length of each chunk
477
 
        *
478
 
        * @return  Converts a string to an array. If the optional split_length parameter is specified,
479
 
        *       the returned array will be broken down into chunks with each being split_length in length,
480
 
        *       otherwise each chunk will be one character in length. FALSE is returned if split_length is
481
 
        *       less than 1. If the split_length length exceeds the length of string, the entire string is
482
 
        *       returned as the first (and only) array element.
483
 
        */
484
 
        function str_split($string, $split_length = 1)
485
 
        {
486
 
                if ($split_length < 1)
487
 
                {
488
 
                        return false;
489
 
                }
490
 
                else if ($split_length >= strlen($string))
491
 
                {
492
 
                        return array($string);
493
 
                }
494
 
                else
495
 
                {
496
 
                        preg_match_all('#.{1,' . $split_length . '}#s', $string, $matches);
497
 
                        return $matches[0];
498
 
                }
499
 
        }
500
 
}
501
 
 
502
 
if (!function_exists('stripos'))
503
 
{
504
 
        /**
505
 
        * A wrapper for the PHP5 function stripos
506
 
        * Find position of first occurrence of a case-insensitive string
507
 
        *
508
 
        * @param string $haystack is the string to search in
509
 
        * @param string $needle is the string to search for
510
 
        *
511
 
        * @return mixed Returns the numeric position of the first occurrence of needle in the haystack string. Unlike strpos(), stripos() is case-insensitive.
512
 
        * Note that the needle may be a string of one or more characters.
513
 
        * If needle is not found, stripos() will return boolean FALSE.
514
 
        */
515
 
        function stripos($haystack, $needle)
516
 
        {
517
 
                if (preg_match('#' . preg_quote($needle, '#') . '#i', $haystack, $m))
518
 
                {
519
 
                        return strpos($haystack, $m[0]);
520
 
                }
521
 
 
522
 
                return false;
523
 
        }
524
 
}
525
 
 
526
 
if (!function_exists('realpath'))
527
 
{
528
 
        /**
529
 
        * Checks if a path ($path) is absolute or relative
530
 
        *
531
 
        * @param string $path Path to check absoluteness of
532
 
        * @return boolean
533
 
        */
534
 
        function is_absolute($path)
535
 
        {
536
 
                return ($path[0] == '/' || (DIRECTORY_SEPARATOR == '\\' && preg_match('#^[a-z]:/#i', $path))) ? true : false;
537
 
        }
538
 
 
539
 
        /**
540
 
        * @author Chris Smith <chris@project-minerva.org>
541
 
        * @copyright 2006 Project Minerva Team
542
 
        * @param string $path The path which we should attempt to resolve.
543
 
        * @return mixed
544
 
        */
545
 
        function phpbb_realpath($path)
546
 
        {
547
 
                // Now to perform funky shizzle
548
 
 
549
 
                // Switch to use UNIX slashes
550
 
                $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
551
 
                $path_prefix = '';
552
 
 
553
 
                // Determine what sort of path we have
554
 
                if (is_absolute($path))
555
 
                {
556
 
                        $absolute = true;
557
 
 
558
 
                        if ($path[0] == '/')
559
 
                        {
560
 
                                // Absolute path, *NIX style
561
 
                                $path_prefix = '';
562
 
                        }
563
 
                        else
564
 
                        {
565
 
                                // Absolute path, Windows style
566
 
                                // Remove the drive letter and colon
567
 
                                $path_prefix = $path[0] . ':';
568
 
                                $path = substr($path, 2);
569
 
                        }
570
 
                }
571
 
                else
572
 
                {
573
 
                        // Relative Path
574
 
                        // Prepend the current working directory
575
 
                        if (function_exists('getcwd'))
576
 
                        {
577
 
                                // This is the best method, hopefully it is enabled!
578
 
                                $path = str_replace(DIRECTORY_SEPARATOR, '/', getcwd()) . '/' . $path;
579
 
                                $absolute = true;
580
 
                                if (preg_match('#^[a-z]:#i', $path))
581
 
                                {
582
 
                                        $path_prefix = $path[0] . ':';
583
 
                                        $path = substr($path, 2);
584
 
                                }
585
 
                                else
586
 
                                {
587
 
                                        $path_prefix = '';
588
 
                                }
589
 
                        }
590
 
                        else if (isset($_SERVER['SCRIPT_FILENAME']) && !empty($_SERVER['SCRIPT_FILENAME']))
591
 
                        {
592
 
                                // Warning: If chdir() has been used this will lie!
593
 
                                // Warning: This has some problems sometime (CLI can create them easily)
594
 
                                $path = str_replace(DIRECTORY_SEPARATOR, '/', dirname($_SERVER['SCRIPT_FILENAME'])) . '/' . $path;
595
 
                                $absolute = true;
596
 
                                $path_prefix = '';
597
 
                        }
598
 
                        else
599
 
                        {
600
 
                                // We have no way of getting the absolute path, just run on using relative ones.
601
 
                                $absolute = false;
602
 
                                $path_prefix = '.';
603
 
                        }
604
 
                }
605
 
 
606
 
                // Remove any repeated slashes
607
 
                $path = preg_replace('#/{2,}#', '/', $path);
608
 
 
609
 
                // Remove the slashes from the start and end of the path
610
 
                $path = trim($path, '/');
611
 
 
612
 
                // Break the string into little bits for us to nibble on
613
 
                $bits = explode('/', $path);
614
 
 
615
 
                // Remove any . in the path, renumber array for the loop below
616
 
                $bits = array_values(array_diff($bits, array('.')));
617
 
 
618
 
                // Lets get looping, run over and resolve any .. (up directory)
619
 
                for ($i = 0, $max = sizeof($bits); $i < $max; $i++)
620
 
                {
621
 
                        // @todo Optimise
622
 
                        if ($bits[$i] == '..' )
623
 
                        {
624
 
                                if (isset($bits[$i - 1]))
625
 
                                {
626
 
                                        if ($bits[$i - 1] != '..')
627
 
                                        {
628
 
                                                // We found a .. and we are able to traverse upwards, lets do it!
629
 
                                                unset($bits[$i]);
630
 
                                                unset($bits[$i - 1]);
631
 
                                                $i -= 2;
632
 
                                                $max -= 2;
633
 
                                                $bits = array_values($bits);
634
 
                                        }
635
 
                                }
636
 
                                else if ($absolute) // ie. !isset($bits[$i - 1]) && $absolute
637
 
                                {
638
 
                                        // We have an absolute path trying to descend above the root of the filesystem
639
 
                                        // ... Error!
640
 
                                        return false;
641
 
                                }
642
 
                        }
643
 
                }
644
 
 
645
 
                // Prepend the path prefix
646
 
                array_unshift($bits, $path_prefix);
647
 
 
648
 
                $resolved = '';
649
 
 
650
 
                $max = sizeof($bits) - 1;
651
 
 
652
 
                // Check if we are able to resolve symlinks, Windows cannot.
653
 
                $symlink_resolve = (function_exists('readlink')) ? true : false;
654
 
 
655
 
                foreach ($bits as $i => $bit)
656
 
                {
657
 
                        if (@is_dir("$resolved/$bit") || ($i == $max && @is_file("$resolved/$bit")))
658
 
                        {
659
 
                                // Path Exists
660
 
                                if ($symlink_resolve && is_link("$resolved/$bit") && ($link = readlink("$resolved/$bit")))
661
 
                                {
662
 
                                        // Resolved a symlink.
663
 
                                        $resolved = $link . (($i == $max) ? '' : '/');
664
 
                                        continue;
665
 
                                }
666
 
                        }
667
 
                        else
668
 
                        {
669
 
                                // Something doesn't exist here!
670
 
                                // This is correct realpath() behaviour but sadly open_basedir and safe_mode make this problematic
671
 
                                // return false;
672
 
                        }
673
 
                        $resolved .= $bit . (($i == $max) ? '' : '/');
674
 
                }
675
 
 
676
 
                // @todo If the file exists fine and open_basedir only has one path we should be able to prepend it
677
 
                // because we must be inside that basedir, the question is where...
678
 
                // @internal The slash in is_dir() gets around an open_basedir restriction
679
 
                if (!@file_exists($resolved) || (!is_dir($resolved . '/') && !is_file($resolved)))
680
 
                {
681
 
                        return false;
682
 
                }
683
 
 
684
 
                // Put the slashes back to the native operating systems slashes
685
 
                $resolved = str_replace('/', DIRECTORY_SEPARATOR, $resolved);
686
 
 
687
 
                // Check for DIRECTORY_SEPARATOR at the end (and remove it!)
688
 
                if (substr($resolved, -1) == DIRECTORY_SEPARATOR)
689
 
                {
690
 
                        return substr($resolved, 0, -1);
691
 
                }
692
 
 
693
 
                return $resolved; // We got here, in the end!
694
 
        }
695
 
}
696
 
else
697
 
{
698
 
        /**
699
 
        * A wrapper for realpath
700
 
        * @ignore
701
 
        */
702
 
        function phpbb_realpath($path)
703
 
        {
704
 
                $path = realpath($path);
705
 
 
706
 
                // Check for DIRECTORY_SEPARATOR at the end (and remove it!)
707
 
                if (substr($path, -1) == DIRECTORY_SEPARATOR)
708
 
                {
709
 
                        return substr($path, 0, -1);
710
 
                }
711
 
 
712
 
                return $path;
713
 
        }
714
 
}
715
 
 
716
 
if (!function_exists('htmlspecialchars_decode'))
717
 
{
718
 
        /**
719
 
        * A wrapper for htmlspecialchars_decode
720
 
        * @ignore
721
 
        */
722
 
        function htmlspecialchars_decode($string, $quote_style = ENT_COMPAT)
723
 
        {
724
 
                return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
725
 
        }
726
 
}
727
 
 
728
 
// functions used for building option fields
729
 
 
730
 
/**
731
 
* Pick a language, any language ...
732
 
*/
733
 
function language_select($default = '')
734
 
{
735
 
        global $db;
736
 
 
737
 
        $sql = 'SELECT lang_iso, lang_local_name
738
 
                FROM ' . LANG_TABLE . '
739
 
                ORDER BY lang_english_name';
740
 
        $result = $db->sql_query($sql);
741
 
 
742
 
        $lang_options = '';
743
 
        while ($row = $db->sql_fetchrow($result))
744
 
        {
745
 
                $selected = ($row['lang_iso'] == $default) ? ' selected="selected"' : '';
746
 
                $lang_options .= '<option value="' . $row['lang_iso'] . '"' . $selected . '>' . $row['lang_local_name'] . '</option>';
747
 
        }
748
 
        $db->sql_freeresult($result);
749
 
 
750
 
        return $lang_options;
751
 
}
752
 
 
753
 
/**
754
 
* Pick a template/theme combo,
755
 
*/
756
 
function style_select($default = '', $all = false)
757
 
{
758
 
        global $db;
759
 
 
760
 
        $sql_where = (!$all) ? 'WHERE style_active = 1 ' : '';
761
 
        $sql = 'SELECT style_id, style_name
762
 
                FROM ' . STYLES_TABLE . "
763
 
                $sql_where
764
 
                ORDER BY style_name";
765
 
        $result = $db->sql_query($sql);
766
 
 
767
 
        $style_options = '';
768
 
        while ($row = $db->sql_fetchrow($result))
769
 
        {
770
 
                $selected = ($row['style_id'] == $default) ? ' selected="selected"' : '';
771
 
                $style_options .= '<option value="' . $row['style_id'] . '"' . $selected . '>' . $row['style_name'] . '</option>';
772
 
        }
773
 
        $db->sql_freeresult($result);
774
 
 
775
 
        return $style_options;
776
 
}
777
 
 
778
 
/**
779
 
* Pick a timezone
780
 
*/
781
 
function tz_select($default = '', $truncate = false)
782
 
{
783
 
        global $user;
784
 
 
785
 
        $tz_select = '';
786
 
        foreach ($user->lang['tz_zones'] as $offset => $zone)
787
 
        {
788
 
                if ($truncate)
789
 
                {
790
 
                        $zone_trunc = truncate_string($zone, 50, false, '...');
791
 
                }
792
 
                else
793
 
                {
794
 
                        $zone_trunc = $zone;
795
 
                }
796
 
 
797
 
                if (is_numeric($offset))
798
 
                {
799
 
                        $selected = ($offset == $default) ? ' selected="selected"' : '';
800
 
                        $tz_select .= '<option title="'.$zone.'" value="' . $offset . '"' . $selected . '>' . $zone_trunc . '</option>';
801
 
                }
802
 
        }
803
 
 
804
 
        return $tz_select;
805
 
}
806
 
 
807
 
// Functions handling topic/post tracking/marking
808
 
 
809
 
/**
810
 
* Marks a topic/forum as read
811
 
* Marks a topic as posted to
812
 
*
813
 
* @param int $user_id can only be used with $mode == 'post'
814
 
*/
815
 
function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $user_id = 0)
816
 
{
817
 
        global $db, $user, $config;
818
 
 
819
 
        if ($mode == 'all')
820
 
        {
821
 
                if ($forum_id === false || !sizeof($forum_id))
822
 
                {
823
 
                        if ($config['load_db_lastread'] && $user->data['is_registered'])
824
 
                        {
825
 
                                // Mark all forums read (index page)
826
 
                                $db->sql_query('DELETE FROM ' . TOPICS_TRACK_TABLE . " WHERE user_id = {$user->data['user_id']}");
827
 
                                $db->sql_query('DELETE FROM ' . FORUMS_TRACK_TABLE . " WHERE user_id = {$user->data['user_id']}");
828
 
                                $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_lastmark = ' . time() . " WHERE user_id = {$user->data['user_id']}");
829
 
                        }
830
 
                        else if ($config['load_anon_lastread'] || $user->data['is_registered'])
831
 
                        {
832
 
                                $tracking_topics = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : '';
833
 
                                $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
834
 
 
835
 
                                unset($tracking_topics['tf']);
836
 
                                unset($tracking_topics['t']);
837
 
                                unset($tracking_topics['f']);
838
 
                                $tracking_topics['l'] = base_convert(time() - $config['board_startdate'], 10, 36);
839
 
        
840
 
                                $user->set_cookie('track', tracking_serialize($tracking_topics), time() + 31536000);
841
 
                                $_COOKIE[$config['cookie_name'] . '_track'] = (STRIP) ? addslashes(tracking_serialize($tracking_topics)) : tracking_serialize($tracking_topics);
842
 
 
843
 
                                unset($tracking_topics);
844
 
 
845
 
                                if ($user->data['is_registered'])
846
 
                                {
847
 
                                        $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_lastmark = ' . time() . " WHERE user_id = {$user->data['user_id']}");
848
 
                                }
849
 
                        }
850
 
                }
851
 
 
852
 
                return;
853
 
        }
854
 
        else if ($mode == 'topics')
855
 
        {
856
 
                // Mark all topics in forums read
857
 
                if (!is_array($forum_id))
858
 
                {
859
 
                        $forum_id = array($forum_id);
860
 
                }
861
 
 
862
 
                // Add 0 to forums array to mark global announcements correctly
863
 
                $forum_id[] = 0;
864
 
 
865
 
                if ($config['load_db_lastread'] && $user->data['is_registered'])
866
 
                {
867
 
                        $sql = 'DELETE FROM ' . TOPICS_TRACK_TABLE . "
868
 
                                WHERE user_id = {$user->data['user_id']}
869
 
                                        AND " . $db->sql_in_set('forum_id', $forum_id);
870
 
                        $db->sql_query($sql);
871
 
 
872
 
                        $sql = 'SELECT forum_id
873
 
                                FROM ' . FORUMS_TRACK_TABLE . "
874
 
                                WHERE user_id = {$user->data['user_id']}
875
 
                                        AND " . $db->sql_in_set('forum_id', $forum_id);
876
 
                        $result = $db->sql_query($sql);
877
 
 
878
 
                        $sql_update = array();
879
 
                        while ($row = $db->sql_fetchrow($result))
880
 
                        {
881
 
                                $sql_update[] = $row['forum_id'];
882
 
                        }
883
 
                        $db->sql_freeresult($result);
884
 
 
885
 
                        if (sizeof($sql_update))
886
 
                        {
887
 
                                $sql = 'UPDATE ' . FORUMS_TRACK_TABLE . '
888
 
                                        SET mark_time = ' . time() . "
889
 
                                        WHERE user_id = {$user->data['user_id']}
890
 
                                                AND " . $db->sql_in_set('forum_id', $sql_update);
891
 
                                $db->sql_query($sql);
892
 
                        }
893
 
 
894
 
                        if ($sql_insert = array_diff($forum_id, $sql_update))
895
 
                        {
896
 
                                $sql_ary = array();
897
 
                                foreach ($sql_insert as $f_id)
898
 
                                {
899
 
                                        $sql_ary[] = array(
900
 
                                                'user_id'       => (int) $user->data['user_id'],
901
 
                                                'forum_id'      => (int) $f_id,
902
 
                                                'mark_time'     => time()
903
 
                                        );
904
 
                                }
905
 
 
906
 
                                $db->sql_multi_insert(FORUMS_TRACK_TABLE, $sql_ary);
907
 
                        }
908
 
                }
909
 
                else if ($config['load_anon_lastread'] || $user->data['is_registered'])
910
 
                {
911
 
                        $tracking = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : '';
912
 
                        $tracking = ($tracking) ? tracking_unserialize($tracking) : array();
913
 
 
914
 
                        foreach ($forum_id as $f_id)
915
 
                        {
916
 
                                $topic_ids36 = (isset($tracking['tf'][$f_id])) ? $tracking['tf'][$f_id] : array();
917
 
 
918
 
                                if (isset($tracking['tf'][$f_id]))
919
 
                                {
920
 
                                        unset($tracking['tf'][$f_id]);
921
 
                                }
922
 
 
923
 
                                foreach ($topic_ids36 as $topic_id36)
924
 
                                {
925
 
                                        unset($tracking['t'][$topic_id36]);
926
 
                                }
927
 
 
928
 
                                if (isset($tracking['f'][$f_id]))
929
 
                                {
930
 
                                        unset($tracking['f'][$f_id]);
931
 
                                }
932
 
 
933
 
                                $tracking['f'][$f_id] = base_convert(time() - $config['board_startdate'], 10, 36);
934
 
                        }
935
 
 
936
 
                        if (isset($tracking['tf']) && empty($tracking['tf']))
937
 
                        {
938
 
                                unset($tracking['tf']);
939
 
                        }
940
 
 
941
 
                        $user->set_cookie('track', tracking_serialize($tracking), time() + 31536000);
942
 
                        $_COOKIE[$config['cookie_name'] . '_track'] = (STRIP) ? addslashes(tracking_serialize($tracking)) : tracking_serialize($tracking);
943
 
 
944
 
                        unset($tracking);
945
 
                }
946
 
 
947
 
                return;
948
 
        }
949
 
        else if ($mode == 'topic')
950
 
        {
951
 
                if ($topic_id === false || $forum_id === false)
952
 
                {
953
 
                        return;
954
 
                }
955
 
 
956
 
                if ($config['load_db_lastread'] && $user->data['is_registered'])
957
 
                {
958
 
                        $sql = 'UPDATE ' . TOPICS_TRACK_TABLE . '
959
 
                                SET mark_time = ' . (($post_time) ? $post_time : time()) . "
960
 
                                WHERE user_id = {$user->data['user_id']}
961
 
                                        AND topic_id = $topic_id";
962
 
                        $db->sql_query($sql);
963
 
 
964
 
                        // insert row
965
 
                        if (!$db->sql_affectedrows())
966
 
                        {
967
 
                                $db->sql_return_on_error(true);
968
 
 
969
 
                                $sql_ary = array(
970
 
                                        'user_id'               => (int) $user->data['user_id'],
971
 
                                        'topic_id'              => (int) $topic_id,
972
 
                                        'forum_id'              => (int) $forum_id,
973
 
                                        'mark_time'             => ($post_time) ? (int) $post_time : time(),
974
 
                                );
975
 
 
976
 
                                $db->sql_query('INSERT INTO ' . TOPICS_TRACK_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
977
 
 
978
 
                                $db->sql_return_on_error(false);
979
 
                        }
980
 
                }
981
 
                else if ($config['load_anon_lastread'] || $user->data['is_registered'])
982
 
                {
983
 
                        $tracking = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : '';
984
 
                        $tracking = ($tracking) ? tracking_unserialize($tracking) : array();
985
 
 
986
 
                        $topic_id36 = base_convert($topic_id, 10, 36);
987
 
 
988
 
                        if (!isset($tracking['t'][$topic_id36]))
989
 
                        {
990
 
                                $tracking['tf'][$forum_id][$topic_id36] = true;
991
 
                        }
992
 
 
993
 
                        $post_time = ($post_time) ? $post_time : time();
994
 
                        $tracking['t'][$topic_id36] = base_convert($post_time - $config['board_startdate'], 10, 36);
995
 
 
996
 
                        // If the cookie grows larger than 10000 characters we will remove the smallest value
997
 
                        // This can result in old topics being unread - but most of the time it should be accurate...
998
 
                        if (isset($_COOKIE[$config['cookie_name'] . '_track']) && strlen($_COOKIE[$config['cookie_name'] . '_track']) > 10000)
999
 
                        {
1000
 
                                //echo 'Cookie grown too large' . print_r($tracking, true);
1001
 
 
1002
 
                                // We get the ten most minimum stored time offsets and its associated topic ids
1003
 
                                $time_keys = array();
1004
 
                                for ($i = 0; $i < 10 && sizeof($tracking['t']); $i++)
1005
 
                                {
1006
 
                                        $min_value = min($tracking['t']);
1007
 
                                        $m_tkey = array_search($min_value, $tracking['t']);
1008
 
                                        unset($tracking['t'][$m_tkey]);
1009
 
 
1010
 
                                        $time_keys[$m_tkey] = $min_value;
1011
 
                                }
1012
 
 
1013
 
                                // Now remove the topic ids from the array...
1014
 
                                foreach ($tracking['tf'] as $f_id => $topic_id_ary)
1015
 
                                {
1016
 
                                        foreach ($time_keys as $m_tkey => $min_value)
1017
 
                                        {
1018
 
                                                if (isset($topic_id_ary[$m_tkey]))
1019
 
                                                {
1020
 
                                                        $tracking['f'][$f_id] = $min_value;
1021
 
                                                        unset($tracking['tf'][$f_id][$m_tkey]);
1022
 
                                                }
1023
 
                                        }
1024
 
                                }
1025
 
 
1026
 
                                if ($user->data['is_registered'])
1027
 
                                {
1028
 
                                        $user->data['user_lastmark'] = intval(base_convert(max($time_keys) + $config['board_startdate'], 36, 10));
1029
 
                                        $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_lastmark = ' . $user->data['user_lastmark'] . " WHERE user_id = {$user->data['user_id']}");
1030
 
                                }
1031
 
                                else
1032
 
                                {
1033
 
                                        $tracking['l'] = max($time_keys);
1034
 
                                }
1035
 
                        }
1036
 
 
1037
 
                        $user->set_cookie('track', tracking_serialize($tracking), time() + 31536000);
1038
 
                        $_COOKIE[$config['cookie_name'] . '_track'] = (STRIP) ? addslashes(tracking_serialize($tracking)) : tracking_serialize($tracking);
1039
 
                }
1040
 
 
1041
 
                return;
1042
 
        }
1043
 
        else if ($mode == 'post')
1044
 
        {
1045
 
                if ($topic_id === false)
1046
 
                {
1047
 
                        return;
1048
 
                }
1049
 
 
1050
 
                $use_user_id = (!$user_id) ? $user->data['user_id'] : $user_id;
1051
 
 
1052
 
                if ($config['load_db_track'] && $use_user_id != ANONYMOUS)
1053
 
                {
1054
 
                        $db->sql_return_on_error(true);
1055
 
 
1056
 
                        $sql_ary = array(
1057
 
                                'user_id'               => (int) $use_user_id,
1058
 
                                'topic_id'              => (int) $topic_id,
1059
 
                                'topic_posted'  => 1
1060
 
                        );
1061
 
 
1062
 
                        $db->sql_query('INSERT INTO ' . TOPICS_POSTED_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
1063
 
 
1064
 
                        $db->sql_return_on_error(false);
1065
 
                }
1066
 
 
1067
 
                return;
1068
 
        }
1069
 
}
1070
 
 
1071
 
/**
1072
 
* Get topic tracking info by using already fetched info
1073
 
*/
1074
 
function get_topic_tracking($forum_id, $topic_ids, &$rowset, $forum_mark_time, $global_announce_list = false)
1075
 
{
1076
 
        global $config, $user;
1077
 
 
1078
 
        $last_read = array();
1079
 
 
1080
 
        if (!is_array($topic_ids))
1081
 
        {
1082
 
                $topic_ids = array($topic_ids);
1083
 
        }
1084
 
 
1085
 
        foreach ($topic_ids as $topic_id)
1086
 
        {
1087
 
                if (!empty($rowset[$topic_id]['mark_time']))
1088
 
                {
1089
 
                        $last_read[$topic_id] = $rowset[$topic_id]['mark_time'];
1090
 
                }
1091
 
        }
1092
 
 
1093
 
        $topic_ids = array_diff($topic_ids, array_keys($last_read));
1094
 
 
1095
 
        if (sizeof($topic_ids))
1096
 
        {
1097
 
                $mark_time = array();
1098
 
 
1099
 
                // Get global announcement info
1100
 
                if ($global_announce_list && sizeof($global_announce_list))
1101
 
                {
1102
 
                        if (!isset($forum_mark_time[0]))
1103
 
                        {
1104
 
                                global $db;
1105
 
 
1106
 
                                $sql = 'SELECT mark_time
1107
 
                                        FROM ' . FORUMS_TRACK_TABLE . "
1108
 
                                        WHERE user_id = {$user->data['user_id']}
1109
 
                                                AND forum_id = 0";
1110
 
                                $result = $db->sql_query($sql);
1111
 
                                $row = $db->sql_fetchrow($result);
1112
 
                                $db->sql_freeresult($result);
1113
 
 
1114
 
                                if ($row)
1115
 
                                {
1116
 
                                        $mark_time[0] = $row['mark_time'];
1117
 
                                }
1118
 
                        }
1119
 
                        else
1120
 
                        {
1121
 
                                if ($forum_mark_time[0] !== false)
1122
 
                                {
1123
 
                                        $mark_time[0] = $forum_mark_time[0];
1124
 
                                }
1125
 
                        }
1126
 
                }
1127
 
 
1128
 
                if (!empty($forum_mark_time[$forum_id]) && $forum_mark_time[$forum_id] !== false)
1129
 
                {
1130
 
                        $mark_time[$forum_id] = $forum_mark_time[$forum_id];
1131
 
                }
1132
 
                        
1133
 
                $user_lastmark = (isset($mark_time[$forum_id])) ? $mark_time[$forum_id] : $user->data['user_lastmark'];
1134
 
 
1135
 
                foreach ($topic_ids as $topic_id)
1136
 
                {
1137
 
                        if ($global_announce_list && isset($global_announce_list[$topic_id]))
1138
 
                        {
1139
 
                                $last_read[$topic_id] = (isset($mark_time[0])) ? $mark_time[0] : $user_lastmark;
1140
 
                        }
1141
 
                        else
1142
 
                        {
1143
 
                                $last_read[$topic_id] = $user_lastmark;
1144
 
                        }
1145
 
                }
1146
 
        }
1147
 
 
1148
 
        return $last_read;
1149
 
}
1150
 
 
1151
 
/**
1152
 
* Get topic tracking info from db (for cookie based tracking only this function is used)
1153
 
*/
1154
 
function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_list = false)
1155
 
{
1156
 
        global $config, $user;
1157
 
 
1158
 
        $last_read = array();
1159
 
 
1160
 
        if (!is_array($topic_ids))
1161
 
        {
1162
 
                $topic_ids = array($topic_ids);
1163
 
        }
1164
 
 
1165
 
        if ($config['load_db_lastread'] && $user->data['is_registered'])
1166
 
        {
1167
 
                global $db;
1168
 
 
1169
 
                $sql = 'SELECT topic_id, mark_time
1170
 
                        FROM ' . TOPICS_TRACK_TABLE . "
1171
 
                        WHERE user_id = {$user->data['user_id']}
1172
 
                                AND " . $db->sql_in_set('topic_id', $topic_ids);
1173
 
                $result = $db->sql_query($sql);
1174
 
 
1175
 
                while ($row = $db->sql_fetchrow($result))
1176
 
                {
1177
 
                        $last_read[$row['topic_id']] = $row['mark_time'];
1178
 
                }
1179
 
                $db->sql_freeresult($result);
1180
 
        
1181
 
                $topic_ids = array_diff($topic_ids, array_keys($last_read));
1182
 
 
1183
 
                if (sizeof($topic_ids))
1184
 
                {
1185
 
                        $sql = 'SELECT forum_id, mark_time
1186
 
                                FROM ' . FORUMS_TRACK_TABLE . "
1187
 
                                WHERE user_id = {$user->data['user_id']}
1188
 
                                        AND forum_id " .
1189
 
                                        (($global_announce_list && sizeof($global_announce_list)) ? "IN (0, $forum_id)" : "= $forum_id");
1190
 
                        $result = $db->sql_query($sql);
1191
 
                
1192
 
                        $mark_time = array();
1193
 
                        while ($row = $db->sql_fetchrow($result))
1194
 
                        {
1195
 
                                $mark_time[$row['forum_id']] = $row['mark_time'];
1196
 
                        }
1197
 
                        $db->sql_freeresult($result);
1198
 
 
1199
 
                        $user_lastmark = (isset($mark_time[$forum_id])) ? $mark_time[$forum_id] : $user->data['user_lastmark'];
1200
 
 
1201
 
                        foreach ($topic_ids as $topic_id)
1202
 
                        {
1203
 
                                if ($global_announce_list && isset($global_announce_list[$topic_id]))
1204
 
                                {
1205
 
                                        $last_read[$topic_id] = (isset($mark_time[0])) ? $mark_time[0] : $user_lastmark;
1206
 
                                }
1207
 
                                else
1208
 
                                {
1209
 
                                        $last_read[$topic_id] = $user_lastmark;
1210
 
                                }
1211
 
                        }
1212
 
                }
1213
 
        }
1214
 
        else if ($config['load_anon_lastread'] || $user->data['is_registered'])
1215
 
        {
1216
 
                global $tracking_topics;
1217
 
 
1218
 
                if (!isset($tracking_topics) || !sizeof($tracking_topics))
1219
 
                {
1220
 
                        $tracking_topics = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : '';
1221
 
                        $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
1222
 
                }
1223
 
 
1224
 
                if (!$user->data['is_registered'])
1225
 
                {
1226
 
                        $user_lastmark = (isset($tracking_topics['l'])) ? base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate'] : 0;
1227
 
                }
1228
 
                else
1229
 
                {
1230
 
                        $user_lastmark = $user->data['user_lastmark'];
1231
 
                }
1232
 
 
1233
 
                foreach ($topic_ids as $topic_id)
1234
 
                {
1235
 
                        $topic_id36 = base_convert($topic_id, 10, 36);
1236
 
 
1237
 
                        if (isset($tracking_topics['t'][$topic_id36]))
1238
 
                        {
1239
 
                                $last_read[$topic_id] = base_convert($tracking_topics['t'][$topic_id36], 36, 10) + $config['board_startdate'];
1240
 
                        }
1241
 
                }
1242
 
 
1243
 
                $topic_ids = array_diff($topic_ids, array_keys($last_read));
1244
 
 
1245
 
                if (sizeof($topic_ids))
1246
 
                {
1247
 
                        $mark_time = array();
1248
 
                        if ($global_announce_list && sizeof($global_announce_list))
1249
 
                        {
1250
 
                                if (isset($tracking_topics['f'][0]))
1251
 
                                {
1252
 
                                        $mark_time[0] = base_convert($tracking_topics['f'][0], 36, 10) + $config['board_startdate'];
1253
 
                                }
1254
 
                        }
1255
 
 
1256
 
                        if (isset($tracking_topics['f'][$forum_id]))
1257
 
                        {
1258
 
                                $mark_time[$forum_id] = base_convert($tracking_topics['f'][$forum_id], 36, 10) + $config['board_startdate'];
1259
 
                        }
1260
 
 
1261
 
                        $user_lastmark = (isset($mark_time[$forum_id])) ? $mark_time[$forum_id] : $user_lastmark;
1262
 
 
1263
 
                        foreach ($topic_ids as $topic_id)
1264
 
                        {
1265
 
                                if ($global_announce_list && isset($global_announce_list[$topic_id]))
1266
 
                                {
1267
 
                                        $last_read[$topic_id] = (isset($mark_time[0])) ? $mark_time[0] : $user_lastmark;
1268
 
                                }
1269
 
                                else
1270
 
                                {
1271
 
                                        $last_read[$topic_id] = $user_lastmark;
1272
 
                                }
1273
 
                        }
1274
 
                }
1275
 
        }
1276
 
 
1277
 
        return $last_read;
1278
 
}
1279
 
 
1280
 
/**
1281
 
* Check for read forums and update topic tracking info accordingly
1282
 
*
1283
 
* @param int $forum_id the forum id to check
1284
 
* @param int $forum_last_post_time the forums last post time
1285
 
* @param int $f_mark_time the forums last mark time if user is registered and load_db_lastread enabled
1286
 
* @param int $mark_time_forum false if the mark time needs to be obtained, else the last users forum mark time
1287
 
*
1288
 
* @return true if complete forum got marked read, else false.
1289
 
*/
1290
 
function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time = false, $mark_time_forum = false)
1291
 
{
1292
 
        global $db, $tracking_topics, $user, $config;
1293
 
 
1294
 
        // Determine the users last forum mark time if not given.
1295
 
        if ($mark_time_forum === false)
1296
 
        {
1297
 
                if ($config['load_db_lastread'] && $user->data['is_registered'])
1298
 
                {
1299
 
                        $mark_time_forum = (!empty($f_mark_time)) ? $f_mark_time : $user->data['user_lastmark'];
1300
 
                }
1301
 
                else if ($config['load_anon_lastread'] || $user->data['is_registered'])
1302
 
                {
1303
 
                        $tracking_topics = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : '';
1304
 
                        $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
1305
 
 
1306
 
                        if (!$user->data['is_registered'])
1307
 
                        {
1308
 
                                $user->data['user_lastmark'] = (isset($tracking_topics['l'])) ? (int) (base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate']) : 0;
1309
 
                        }
1310
 
 
1311
 
                        $mark_time_forum = (isset($tracking_topics['f'][$forum_id])) ? (int) (base_convert($tracking_topics['f'][$forum_id], 36, 10) + $config['board_startdate']) : $user->data['user_lastmark'];
1312
 
                }
1313
 
        }
1314
 
 
1315
 
        // Check the forum for any left unread topics.
1316
 
        // If there are none, we mark the forum as read.
1317
 
        if ($config['load_db_lastread'] && $user->data['is_registered'])
1318
 
        {
1319
 
                if ($mark_time_forum >= $forum_last_post_time)
1320
 
                {
1321
 
                        // We do not need to mark read, this happened before. Therefore setting this to true
1322
 
                        $row = true;
1323
 
                }
1324
 
                else
1325
 
                {
1326
 
                        $sql = 'SELECT t.forum_id FROM ' . TOPICS_TABLE . ' t
1327
 
                                LEFT JOIN ' . TOPICS_TRACK_TABLE . ' tt ON (tt.topic_id = t.topic_id AND tt.user_id = ' . $user->data['user_id'] . ')
1328
 
                                WHERE t.forum_id = ' . $forum_id . '
1329
 
                                        AND t.topic_last_post_time > ' . $mark_time_forum . '
1330
 
                                        AND t.topic_moved_id = 0
1331
 
                                        AND (tt.topic_id IS NULL OR tt.mark_time < t.topic_last_post_time)
1332
 
                                GROUP BY t.forum_id';
1333
 
                        $result = $db->sql_query_limit($sql, 1);
1334
 
                        $row = $db->sql_fetchrow($result);
1335
 
                        $db->sql_freeresult($result);
1336
 
                }
1337
 
        }
1338
 
        else if ($config['load_anon_lastread'] || $user->data['is_registered'])
1339
 
        {
1340
 
                // Get information from cookie
1341
 
                $row = false;
1342
 
 
1343
 
                if (!isset($tracking_topics['tf'][$forum_id]))
1344
 
                {
1345
 
                        // We do not need to mark read, this happened before. Therefore setting this to true
1346
 
                        $row = true;
1347
 
                }
1348
 
                else
1349
 
                {
1350
 
                        $sql = 'SELECT topic_id
1351
 
                                FROM ' . TOPICS_TABLE . '
1352
 
                                WHERE forum_id = ' . $forum_id . '
1353
 
                                        AND topic_last_post_time > ' . $mark_time_forum . '
1354
 
                                        AND topic_moved_id = 0';
1355
 
                        $result = $db->sql_query($sql);
1356
 
 
1357
 
                        $check_forum = $tracking_topics['tf'][$forum_id];
1358
 
                        $unread = false;
1359
 
 
1360
 
                        while ($row = $db->sql_fetchrow($result))
1361
 
                        {
1362
 
                                if (!in_array(base_convert($row['topic_id'], 10, 36), array_keys($check_forum)))
1363
 
                                {
1364
 
                                        $unread = true;
1365
 
                                        break;
1366
 
                                }
1367
 
                        }
1368
 
                        $db->sql_freeresult($result);
1369
 
 
1370
 
                        $row = $unread;
1371
 
                }
1372
 
        }
1373
 
        else
1374
 
        {
1375
 
                $row = true;
1376
 
        }
1377
 
 
1378
 
        if (!$row)
1379
 
        {
1380
 
                markread('topics', $forum_id);
1381
 
                return true;
1382
 
        }
1383
 
 
1384
 
        return false;
1385
 
}
1386
 
 
1387
 
/**
1388
 
* Transform an array into a serialized format
1389
 
*/
1390
 
function tracking_serialize($input)
1391
 
{
1392
 
        $out = '';
1393
 
        foreach ($input as $key => $value)
1394
 
        {
1395
 
                if (is_array($value))
1396
 
                {
1397
 
                        $out .= $key . ':(' . tracking_serialize($value) . ');';
1398
 
                }
1399
 
                else
1400
 
                {
1401
 
                        $out .= $key . ':' . $value . ';';
1402
 
                }
1403
 
        }
1404
 
        return $out;
1405
 
}
1406
 
 
1407
 
/**
1408
 
* Transform a serialized array into an actual array
1409
 
*/
1410
 
function tracking_unserialize($string, $max_depth = 3)
1411
 
{
1412
 
        $n = strlen($string);
1413
 
        if ($n > 10010)
1414
 
        {
1415
 
                die('Invalid data supplied');
1416
 
        }
1417
 
        $data = $stack = array();
1418
 
        $key = '';
1419
 
        $mode = 0;
1420
 
        $level = &$data;
1421
 
        for ($i = 0; $i < $n; ++$i)
1422
 
        {
1423
 
                switch ($mode)
1424
 
                {
1425
 
                        case 0:
1426
 
                                switch ($string[$i])
1427
 
                                {
1428
 
                                        case ':':
1429
 
                                                $level[$key] = 0;
1430
 
                                                $mode = 1;
1431
 
                                        break;
1432
 
                                        case ')':
1433
 
                                                unset($level);
1434
 
                                                $level = array_pop($stack);
1435
 
                                                $mode = 3;
1436
 
                                        break;
1437
 
                                        default:
1438
 
                                                $key .= $string[$i];
1439
 
                                }
1440
 
                        break;
1441
 
 
1442
 
                        case 1:
1443
 
                                switch ($string[$i])
1444
 
                                {
1445
 
                                        case '(':
1446
 
                                                if (sizeof($stack) >= $max_depth)
1447
 
                                                {
1448
 
                                                        die('Invalid data supplied');
1449
 
                                                }
1450
 
                                                $stack[] = &$level;
1451
 
                                                $level[$key] = array();
1452
 
                                                $level = &$level[$key];
1453
 
                                                $key = '';
1454
 
                                                $mode = 0;
1455
 
                                        break;
1456
 
                                        default:
1457
 
                                                $level[$key] = $string[$i];
1458
 
                                                $mode = 2;
1459
 
                                        break;
1460
 
                                }
1461
 
                        break;
1462
 
                        
1463
 
                        case 2:
1464
 
                                switch ($string[$i])
1465
 
                                {
1466
 
                                        case ')':
1467
 
                                                unset($level);
1468
 
                                                $level = array_pop($stack);
1469
 
                                                $mode = 3;
1470
 
                                        break;
1471
 
                                        case ';':
1472
 
                                                $key = '';
1473
 
                                                $mode = 0;
1474
 
                                        break;
1475
 
                                        default:
1476
 
                                                $level[$key] .= $string[$i];
1477
 
                                        break;
1478
 
                                }
1479
 
                        break;
1480
 
                        
1481
 
                        case 3:
1482
 
                                switch ($string[$i])
1483
 
                                {
1484
 
                                        case ')':
1485
 
                                                unset($level);
1486
 
                                                $level = array_pop($stack);
1487
 
                                        break;
1488
 
                                        case ';':
1489
 
                                                $key = '';
1490
 
                                                $mode = 0;
1491
 
                                        break;
1492
 
                                        default:
1493
 
                                                die('Invalid data supplied');
1494
 
                                        break;
1495
 
                                }
1496
 
                        break;
1497
 
                }
1498
 
        }
1499
 
 
1500
 
        if (sizeof($stack) != 0 || ($mode != 0 && $mode != 3))
1501
 
        {
1502
 
                die('Invalid data supplied');
1503
 
        }
1504
 
        
1505
 
        return $level;
1506
 
}
1507
 
 
1508
 
// Pagination functions
1509
 
 
1510
 
/**
1511
 
* Pagination routine, generates page number sequence
1512
 
* tpl_prefix is for using different pagination blocks at one page
1513
 
*/
1514
 
function generate_pagination($base_url, $num_items, $per_page, $start_item, $add_prevnext_text = false, $tpl_prefix = '')
1515
 
{
1516
 
        global $template, $user;
1517
 
 
1518
 
        // Make sure $per_page is a valid value
1519
 
        $per_page = ($per_page <= 0) ? 1 : $per_page;
1520
 
 
1521
 
        $seperator = '<span class="page-sep">' . $user->lang['COMMA_SEPARATOR'] . '</span>';
1522
 
        $total_pages = ceil($num_items / $per_page);
1523
 
 
1524
 
        if ($total_pages == 1 || !$num_items)
1525
 
        {
1526
 
                return false;
1527
 
        }
1528
 
 
1529
 
        $on_page = floor($start_item / $per_page) + 1;
1530
 
        $url_delim = (strpos($base_url, '?') === false) ? '?' : '&amp;';
1531
 
 
1532
 
        $page_string = ($on_page == 1) ? '<strong>1</strong>' : '<a href="' . $base_url . '">1</a>';
1533
 
 
1534
 
        if ($total_pages > 5)
1535
 
        {
1536
 
                $start_cnt = min(max(1, $on_page - 4), $total_pages - 5);
1537
 
                $end_cnt = max(min($total_pages, $on_page + 4), 6);
1538
 
 
1539
 
                $page_string .= ($start_cnt > 1) ? ' ... ' : $seperator;
1540
 
 
1541
 
                for ($i = $start_cnt + 1; $i < $end_cnt; $i++)
1542
 
                {
1543
 
                        $page_string .= ($i == $on_page) ? '<strong>' . $i . '</strong>' : '<a href="' . $base_url . "{$url_delim}start=" . (($i - 1) * $per_page) . '">' . $i . '</a>';
1544
 
                        if ($i < $end_cnt - 1)
1545
 
                        {
1546
 
                                $page_string .= $seperator;
1547
 
                        }
1548
 
                }
1549
 
 
1550
 
                $page_string .= ($end_cnt < $total_pages) ? ' ... ' : $seperator;
1551
 
        }
1552
 
        else
1553
 
        {
1554
 
                $page_string .= $seperator;
1555
 
 
1556
 
                for ($i = 2; $i < $total_pages; $i++)
1557
 
                {
1558
 
                        $page_string .= ($i == $on_page) ? '<strong>' . $i . '</strong>' : '<a href="' . $base_url . "{$url_delim}start=" . (($i - 1) * $per_page) . '">' . $i . '</a>';
1559
 
                        if ($i < $total_pages)
1560
 
                        {
1561
 
                                $page_string .= $seperator;
1562
 
                        }
1563
 
                }
1564
 
        }
1565
 
 
1566
 
        $page_string .= ($on_page == $total_pages) ? '<strong>' . $total_pages . '</strong>' : '<a href="' . $base_url . "{$url_delim}start=" . (($total_pages - 1) * $per_page) . '">' . $total_pages . '</a>';
1567
 
 
1568
 
        if ($add_prevnext_text)
1569
 
        {
1570
 
                if ($on_page != 1)
1571
 
                {
1572
 
                        $page_string = '<a href="' . $base_url . "{$url_delim}start=" . (($on_page - 2) * $per_page) . '">' . $user->lang['PREVIOUS'] . '</a>&nbsp;&nbsp;' . $page_string;
1573
 
                }
1574
 
 
1575
 
                if ($on_page != $total_pages)
1576
 
                {
1577
 
                        $page_string .= '&nbsp;&nbsp;<a href="' . $base_url . "{$url_delim}start=" . ($on_page * $per_page) . '">' . $user->lang['NEXT'] . '</a>';
1578
 
                }
1579
 
        }
1580
 
 
1581
 
        $template->assign_vars(array(
1582
 
                $tpl_prefix . 'BASE_URL'                => $base_url,
1583
 
                'A_' . $tpl_prefix . 'BASE_URL' => addslashes($base_url),
1584
 
                $tpl_prefix . 'PER_PAGE'                => $per_page,
1585
 
 
1586
 
                $tpl_prefix . 'PREVIOUS_PAGE'   => ($on_page == 1) ? '' : $base_url . "{$url_delim}start=" . (($on_page - 2) * $per_page),
1587
 
                $tpl_prefix . 'NEXT_PAGE'               => ($on_page == $total_pages) ? '' : $base_url . "{$url_delim}start=" . ($on_page * $per_page),
1588
 
                $tpl_prefix . 'TOTAL_PAGES'             => $total_pages,
1589
 
        ));
1590
 
 
1591
 
        return $page_string;
1592
 
}
1593
 
 
1594
 
/**
1595
 
* Return current page (pagination)
1596
 
*/
1597
 
function on_page($num_items, $per_page, $start)
1598
 
{
1599
 
        global $template, $user;
1600
 
 
1601
 
        // Make sure $per_page is a valid value
1602
 
        $per_page = ($per_page <= 0) ? 1 : $per_page;
1603
 
 
1604
 
        $on_page = floor($start / $per_page) + 1;
1605
 
 
1606
 
        $template->assign_vars(array(
1607
 
                'ON_PAGE'               => $on_page)
1608
 
        );
1609
 
 
1610
 
        return sprintf($user->lang['PAGE_OF'], $on_page, max(ceil($num_items / $per_page), 1));
1611
 
}
1612
 
 
1613
 
// Server functions (building urls, redirecting...)
1614
 
 
1615
 
/**
1616
 
* Append session id to url.
1617
 
* This function supports hooks.
1618
 
*
1619
 
* @param string $url The url the session id needs to be appended to (can have params)
1620
 
* @param mixed $params String or array of additional url parameters
1621
 
* @param bool $is_amp Is url using &amp; (true) or & (false)
1622
 
* @param string $session_id Possibility to use a custom session id instead of the global one
1623
 
*
1624
 
* Examples:
1625
 
* <code>
1626
 
* append_sid("{$phpbb_root_path}viewtopic.$phpEx?t=1&amp;f=2");
1627
 
* append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=1&amp;f=2');
1628
 
* append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=1&f=2', false);
1629
 
* append_sid("{$phpbb_root_path}viewtopic.$phpEx", array('t' => 1, 'f' => 2));
1630
 
* </code>
1631
 
*
1632
 
*/
1633
 
function append_sid($url, $params = false, $is_amp = true, $session_id = false)
1634
 
{
1635
 
        global $_SID, $_EXTRA_URL, $phpbb_hook;
1636
 
 
1637
 
        // Developers using the hook function need to globalise the $_SID and $_EXTRA_URL on their own and also handle it appropiatly.
1638
 
        // They could mimick most of what is within this function
1639
 
        if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__, $url, $params, $is_amp, $session_id))
1640
 
        {
1641
 
                if ($phpbb_hook->hook_return(__FUNCTION__))
1642
 
                {
1643
 
                        return $phpbb_hook->hook_return_result(__FUNCTION__);
1644
 
                }
1645
 
        }
1646
 
 
1647
 
        // Assign sid if session id is not specified
1648
 
        if ($session_id === false)
1649
 
        {
1650
 
                $session_id = $_SID;
1651
 
        }
1652
 
 
1653
 
        $amp_delim = ($is_amp) ? '&amp;' : '&';
1654
 
        $url_delim = (strpos($url, '?') === false) ? '?' : $amp_delim;
1655
 
 
1656
 
        // Appending custom url parameter?
1657
 
        $append_url = (!empty($_EXTRA_URL)) ? implode($amp_delim, $_EXTRA_URL) : '';
1658
 
 
1659
 
        $anchor = '';
1660
 
        if (strpos($url, '#') !== false)
1661
 
        {
1662
 
                list($url, $anchor) = explode('#', $url, 2);
1663
 
                $anchor = '#' . $anchor;
1664
 
        }
1665
 
        else if (!is_array($params) && strpos($params, '#') !== false)
1666
 
        {
1667
 
                list($params, $anchor) = explode('#', $params, 2);
1668
 
                $anchor = '#' . $anchor;
1669
 
        }
1670
 
 
1671
 
        // Use the short variant if possible ;)
1672
 
        if ($params === false)
1673
 
        {
1674
 
                // Append session id
1675
 
                if (!$session_id)
1676
 
                {
1677
 
                        return $url . (($append_url) ? $url_delim . $append_url : '') . $anchor;
1678
 
                }
1679
 
                else
1680
 
                {
1681
 
                        return $url . (($append_url) ? $url_delim . $append_url . $amp_delim : $url_delim) . 'sid=' . $session_id . $anchor;
1682
 
                }
1683
 
        }
1684
 
 
1685
 
        // Build string if parameters are specified as array
1686
 
        if (is_array($params))
1687
 
        {
1688
 
                $output = array();
1689
 
 
1690
 
                foreach ($params as $key => $item)
1691
 
                {
1692
 
                        if ($item === NULL)
1693
 
                        {
1694
 
                                continue;
1695
 
                        }
1696
 
 
1697
 
                        if ($key == '#')
1698
 
                        {
1699
 
                                $anchor = '#' . $item;
1700
 
                                continue;
1701
 
                        }
1702
 
 
1703
 
                        $output[] = $key . '=' . $item;
1704
 
                }
1705
 
 
1706
 
                $params = implode($amp_delim, $output);
1707
 
        }
1708
 
 
1709
 
        // Append session id and parameters (even if they are empty)
1710
 
        // If parameters are empty, the developer can still append his/her parameters without caring about the delimiter
1711
 
        return $url . (($append_url) ? $url_delim . $append_url . $amp_delim : $url_delim) . $params . ((!$session_id) ? '' : $amp_delim . 'sid=' . $session_id) . $anchor;
1712
 
}
1713
 
 
1714
 
/**
1715
 
* Generate board url (example: http://www.example.com/phpBB)
1716
 
* @param bool $without_script_path if set to true the script path gets not appended (example: http://www.example.com)
1717
 
*/
1718
 
function generate_board_url($without_script_path = false)
1719
 
{
1720
 
        global $config, $user;
1721
 
 
1722
 
        $server_name = (!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME');
1723
 
        $server_port = (!empty($_SERVER['SERVER_PORT'])) ? (int) $_SERVER['SERVER_PORT'] : (int) getenv('SERVER_PORT');
1724
 
 
1725
 
        // Forcing server vars is the only way to specify/override the protocol
1726
 
        if ($config['force_server_vars'] || !$server_name)
1727
 
        {
1728
 
                $server_protocol = ($config['server_protocol']) ? $config['server_protocol'] : (($config['cookie_secure']) ? 'https://' : 'http://');
1729
 
                $server_name = $config['server_name'];
1730
 
                $server_port = (int) $config['server_port'];
1731
 
                $script_path = $config['script_path'];
1732
 
 
1733
 
                $url = $server_protocol . $server_name;
1734
 
        }
1735
 
        else
1736
 
        {
1737
 
                // Do not rely on cookie_secure, users seem to think that it means a secured cookie instead of an encrypted connection
1738
 
                $cookie_secure = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 1 : 0;
1739
 
                $url = (($cookie_secure) ? 'https://' : 'http://') . $server_name;
1740
 
 
1741
 
                $script_path = $user->page['root_script_path'];
1742
 
        }
1743
 
 
1744
 
        if ($server_port && (($config['cookie_secure'] && $server_port <> 443) || (!$config['cookie_secure'] && $server_port <> 80)))
1745
 
        {
1746
 
                $url .= ':' . $server_port;
1747
 
        }
1748
 
 
1749
 
        if (!$without_script_path)
1750
 
        {
1751
 
                $url .= $script_path;
1752
 
        }
1753
 
 
1754
 
        // Strip / from the end
1755
 
        if (substr($url, -1, 1) == '/')
1756
 
        {
1757
 
                $url = substr($url, 0, -1);
1758
 
        }
1759
 
 
1760
 
        return $url;
1761
 
}
1762
 
 
1763
 
/**
1764
 
* Redirects the user to another page then exits the script nicely
1765
 
*/
1766
 
function redirect($url, $return = false)
1767
 
{
1768
 
        global $db, $cache, $config, $user, $phpbb_root_path;
1769
 
 
1770
 
        if (empty($user->lang))
1771
 
        {
1772
 
                $user->add_lang('common');
1773
 
        }
1774
 
 
1775
 
        if (!$return)
1776
 
        {
1777
 
                garbage_collection();
1778
 
        }
1779
 
 
1780
 
        // Make sure no &amp;'s are in, this will break the redirect
1781
 
        $url = str_replace('&amp;', '&', $url);
1782
 
 
1783
 
        // Determine which type of redirect we need to handle...
1784
 
        $url_parts = parse_url($url);
1785
 
 
1786
 
        if ($url_parts === false)
1787
 
        {
1788
 
                // Malformed url, redirect to current page...
1789
 
                $url = generate_board_url() . '/' . $user->page['page'];
1790
 
        }
1791
 
        else if (!empty($url_parts['scheme']) && !empty($url_parts['host']))
1792
 
        {
1793
 
                // Full URL
1794
 
        }
1795
 
        else if ($url[0] == '/')
1796
 
        {
1797
 
                // Absolute uri, prepend direct url...
1798
 
                $url = generate_board_url(true) . $url;
1799
 
        }
1800
 
        else
1801
 
        {
1802
 
                // Relative uri
1803
 
                $pathinfo = pathinfo($url);
1804
 
 
1805
 
                // Is the uri pointing to the current directory?
1806
 
                if ($pathinfo['dirname'] == '.')
1807
 
                {
1808
 
                        $url = str_replace('./', '', $url);
1809
 
 
1810
 
                        // Strip / from the beginning
1811
 
                        if ($url && substr($url, 0, 1) == '/')
1812
 
                        {
1813
 
                                $url = substr($url, 1);
1814
 
                        }
1815
 
 
1816
 
                        if ($user->page['page_dir'])
1817
 
                        {
1818
 
                                $url = generate_board_url() . '/' . $user->page['page_dir'] . '/' . $url;
1819
 
                        }
1820
 
                        else
1821
 
                        {
1822
 
                                $url = generate_board_url() . '/' . $url;
1823
 
                        }
1824
 
                }
1825
 
                else
1826
 
                {
1827
 
                        // Used ./ before, but $phpbb_root_path is working better with urls within another root path
1828
 
                        $root_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($phpbb_root_path)));
1829
 
                        $page_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($pathinfo['dirname'])));
1830
 
                        $intersection = array_intersect_assoc($root_dirs, $page_dirs);
1831
 
 
1832
 
                        $root_dirs = array_diff_assoc($root_dirs, $intersection);
1833
 
                        $page_dirs = array_diff_assoc($page_dirs, $intersection);
1834
 
 
1835
 
                        $dir = str_repeat('../', sizeof($root_dirs)) . implode('/', $page_dirs);
1836
 
 
1837
 
                        // Strip / from the end
1838
 
                        if ($dir && substr($dir, -1, 1) == '/')
1839
 
                        {
1840
 
                                $dir = substr($dir, 0, -1);
1841
 
                        }
1842
 
 
1843
 
                        // Strip / from the beginning
1844
 
                        if ($dir && substr($dir, 0, 1) == '/')
1845
 
                        {
1846
 
                                $dir = substr($dir, 1);
1847
 
                        }
1848
 
 
1849
 
                        $url = str_replace($pathinfo['dirname'] . '/', '', $url);
1850
 
 
1851
 
                        // Strip / from the beginning
1852
 
                        if (substr($url, 0, 1) == '/')
1853
 
                        {
1854
 
                                $url = substr($url, 1);
1855
 
                        }
1856
 
 
1857
 
                        $url = $dir . '/' . $url;
1858
 
                        $url = generate_board_url() . '/' . $url;
1859
 
                }
1860
 
        }
1861
 
 
1862
 
        // Make sure no linebreaks are there... to prevent http response splitting for PHP < 4.4.2
1863
 
        if (strpos(urldecode($url), "\n") !== false || strpos(urldecode($url), "\r") !== false || strpos($url, ';') !== false)
1864
 
        {
1865
 
                trigger_error('Tried to redirect to potentially insecure url.', E_USER_ERROR);
1866
 
        }
1867
 
 
1868
 
        // Now, also check the protocol and for a valid url the last time...
1869
 
        $allowed_protocols = array('http', 'https', 'ftp', 'ftps');
1870
 
        $url_parts = parse_url($url);
1871
 
 
1872
 
        if ($url_parts === false || empty($url_parts['scheme']) || !in_array($url_parts['scheme'], $allowed_protocols))
1873
 
        {
1874
 
                trigger_error('Tried to redirect to potentially insecure url.', E_USER_ERROR);
1875
 
        }
1876
 
 
1877
 
        if ($return)
1878
 
        {
1879
 
                return $url;
1880
 
        }
1881
 
 
1882
 
        // Redirect via an HTML form for PITA webservers
1883
 
        if (@preg_match('#Microsoft|WebSTAR|Xitami#', getenv('SERVER_SOFTWARE')))
1884
 
        {
1885
 
                header('Refresh: 0; URL=' . $url);
1886
 
 
1887
 
                echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
1888
 
                echo '<html xmlns="http://www.w3.org/1999/xhtml" dir="' . $user->lang['DIRECTION'] . '" lang="' . $user->lang['USER_LANG'] . '" xml:lang="' . $user->lang['USER_LANG'] . '">';
1889
 
                echo '<head>';
1890
 
                echo '<meta http-equiv="content-type" content="text/html; charset=utf-8" />';
1891
 
                echo '<meta http-equiv="refresh" content="0; url=' . str_replace('&', '&amp;', $url) . '" />';
1892
 
                echo '<title>' . $user->lang['REDIRECT'] . '</title>';
1893
 
                echo '</head>';
1894
 
                echo '<body>';
1895
 
                echo '<div style="text-align: center;">' . sprintf($user->lang['URL_REDIRECT'], '<a href="' . str_replace('&', '&amp;', $url) . '">', '</a>') . '</div>';
1896
 
                echo '</body>';
1897
 
                echo '</html>';
1898
 
 
1899
 
                exit;
1900
 
        }
1901
 
 
1902
 
        // Behave as per HTTP/1.1 spec for others
1903
 
        header('Location: ' . $url);
1904
 
        exit;
1905
 
}
1906
 
 
1907
 
/**
1908
 
* Re-Apply session id after page reloads
1909
 
*/
1910
 
function reapply_sid($url)
1911
 
{
1912
 
        global $phpEx, $phpbb_root_path;
1913
 
 
1914
 
        if ($url === "index.$phpEx")
1915
 
        {
1916
 
                return append_sid("index.$phpEx");
1917
 
        }
1918
 
        else if ($url === "{$phpbb_root_path}index.$phpEx")
1919
 
        {
1920
 
                return append_sid("{$phpbb_root_path}index.$phpEx");
1921
 
        }
1922
 
 
1923
 
        // Remove previously added sid
1924
 
        if (strpos($url, '?sid=') !== false)
1925
 
        {
1926
 
                $url = preg_replace('/(\?)sid=[a-z0-9]+(&amp;|&)?/', '\1', $url);
1927
 
        }
1928
 
        else if (strpos($url, '&sid=') !== false)
1929
 
        {
1930
 
                $url = preg_replace('/&sid=[a-z0-9]+(&)?/', '\1', $url);
1931
 
        }
1932
 
        else if (strpos($url, '&amp;sid=') !== false)
1933
 
        {
1934
 
                $url = preg_replace('/&amp;sid=[a-z0-9]+(&amp;)?/', '\1', $url);
1935
 
        }
1936
 
 
1937
 
        return append_sid($url);
1938
 
}
1939
 
 
1940
 
/**
1941
 
* Returns url from the session/current page with an re-appended SID with optionally stripping vars from the url
1942
 
*/
1943
 
function build_url($strip_vars = false)
1944
 
{
1945
 
        global $user, $phpbb_root_path;
1946
 
 
1947
 
        // Append SID
1948
 
        $redirect = append_sid($user->page['page'], false, false);
1949
 
 
1950
 
        // Add delimiter if not there...
1951
 
        if (strpos($redirect, '?') === false)
1952
 
        {
1953
 
                $redirect .= '?';
1954
 
        }
1955
 
 
1956
 
        // Strip vars...
1957
 
        if ($strip_vars !== false && strpos($redirect, '?') !== false)
1958
 
        {
1959
 
                if (!is_array($strip_vars))
1960
 
                {
1961
 
                        $strip_vars = array($strip_vars);
1962
 
                }
1963
 
 
1964
 
                $query = $_query = array();
1965
 
 
1966
 
                $args = substr($redirect, strpos($redirect, '?') + 1);
1967
 
                $args = ($args) ? explode('&', $args) : array();
1968
 
                $redirect = substr($redirect, 0, strpos($redirect, '?'));
1969
 
 
1970
 
                foreach ($args as $argument)
1971
 
                {
1972
 
                        $arguments = explode('=', $argument);
1973
 
                        $key = $arguments[0];
1974
 
                        unset($arguments[0]);
1975
 
 
1976
 
                        $query[$key] = implode('=', $arguments);
1977
 
                }
1978
 
 
1979
 
                // Strip the vars off
1980
 
                foreach ($strip_vars as $strip)
1981
 
                {
1982
 
                        if (isset($query[$strip]))
1983
 
                        {
1984
 
                                unset($query[$strip]);
1985
 
                        }
1986
 
                }
1987
 
        
1988
 
                // Glue the remaining parts together... already urlencoded
1989
 
                foreach ($query as $key => $value)
1990
 
                {
1991
 
                        $_query[] = $key . '=' . $value;
1992
 
                }
1993
 
                $query = implode('&', $_query);
1994
 
 
1995
 
                $redirect .= ($query) ? '?' . $query : '';
1996
 
        }
1997
 
 
1998
 
        return $phpbb_root_path . str_replace('&', '&amp;', $redirect);
1999
 
}
2000
 
 
2001
 
/**
2002
 
* Meta refresh assignment
2003
 
*/
2004
 
function meta_refresh($time, $url)
2005
 
{
2006
 
        global $template;
2007
 
 
2008
 
        $url = redirect($url, true);
2009
 
 
2010
 
        // For XHTML compatibility we change back & to &amp;
2011
 
        $template->assign_vars(array(
2012
 
                'META' => '<meta http-equiv="refresh" content="' . $time . ';url=' . str_replace('&', '&amp;', $url) . '" />')
2013
 
        );
2014
 
}
2015
 
 
2016
 
//Form validation
2017
 
 
2018
 
/**
2019
 
* Add a secret token to the form (requires the S_FORM_TOKEN template variable)
2020
 
* @param string  $form_name The name of the form; has to match the name used in check_form_key, otherwise no restrictions apply
2021
 
*/
2022
 
function add_form_key($form_name)
2023
 
{
2024
 
        global $config, $template, $user;
2025
 
        $now = time();
2026
 
        $token_sid = ($user->data['user_id'] == ANONYMOUS && !empty($config['form_token_sid_guests'])) ? $user->session_id : '';
2027
 
        $token = sha1($now . $user->data['user_form_salt'] . $form_name . $token_sid);
2028
 
 
2029
 
        $s_fields = build_hidden_fields(array(
2030
 
                        'creation_time' => $now,
2031
 
                        'form_token'    => $token,
2032
 
        ));
2033
 
        $template->assign_vars(array(
2034
 
                        'S_FORM_TOKEN'  => $s_fields,
2035
 
        ));
2036
 
}
2037
 
 
2038
 
/**
2039
 
* Check the form key. Required for all altering actions not secured by confirm_box
2040
 
* @param string  $form_name The name of the form; has to match the name used in add_form_key, otherwise no restrictions apply
2041
 
* @param int $timespan The maximum acceptable age for a submitted form in seconds. Defaults to the config setting.
2042
 
* @param string $return_page The address for the return link
2043
 
* @param bool $trigger If true, the function will triger an error when encountering an invalid form
2044
 
* @param int $minimum_time The minimum acceptable age for a submitted form in seconds
2045
 
*/
2046
 
function check_form_key($form_name, $timespan = false, $return_page = '', $trigger = false, $minimum_time = false)
2047
 
{
2048
 
        global $config, $user;
2049
 
 
2050
 
        if ($timespan === false)
2051
 
        {
2052
 
                // we enforce a minimum value of half a minute here.
2053
 
                $timespan = ($config['form_token_lifetime'] == -1) ? -1 : max(30, $config['form_token_lifetime']);
2054
 
        }
2055
 
        if ($minimum_time === false)
2056
 
        {
2057
 
                $minimum_time = (int) $config['form_token_mintime'];
2058
 
        }
2059
 
        
2060
 
        if (isset($_POST['creation_time']) && isset($_POST['form_token']))
2061
 
        {
2062
 
                $creation_time  = abs(request_var('creation_time', 0));
2063
 
                $token = request_var('form_token', '');
2064
 
 
2065
 
                $diff = (time() - $creation_time);
2066
 
 
2067
 
                if (($diff >= $minimum_time) && (($diff <= $timespan) || $timespan == -1))
2068
 
                {
2069
 
                        $token_sid = ($user->data['user_id'] == ANONYMOUS && !empty($config['form_token_sid_guests'])) ? $user->session_id : '';
2070
 
                        
2071
 
                        $key = sha1($creation_time . $user->data['user_form_salt'] . $form_name . $token_sid);
2072
 
                        if ($key === $token)
2073
 
                        {
2074
 
                                return true;
2075
 
                        }
2076
 
                }
2077
 
        }
2078
 
        if ($trigger)
2079
 
        {
2080
 
                trigger_error($user->lang['FORM_INVALID'] . $return_page);
2081
 
        }
2082
 
        return false;
2083
 
}
2084
 
 
2085
 
// Message/Login boxes
2086
 
 
2087
 
/**
2088
 
* Build Confirm box
2089
 
* @param boolean $check True for checking if confirmed (without any additional parameters) and false for displaying the confirm box
2090
 
* @param string $title Title/Message used for confirm box.
2091
 
*               message text is _CONFIRM appended to title.
2092
 
*               If title cannot be found in user->lang a default one is displayed
2093
 
*               If title_CONFIRM cannot be found in user->lang the text given is used.
2094
 
* @param string $hidden Hidden variables
2095
 
* @param string $html_body Template used for confirm box
2096
 
* @param string $u_action Custom form action
2097
 
*/
2098
 
function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_body.html', $u_action = '')
2099
 
{
2100
 
        global $user, $template, $db;
2101
 
        global $phpEx, $phpbb_root_path;
2102
 
 
2103
 
        if (isset($_POST['cancel']))
2104
 
        {
2105
 
                return false;
2106
 
        }
2107
 
 
2108
 
        $confirm = false;
2109
 
        if (isset($_POST['confirm']))
2110
 
        {
2111
 
                // language frontier
2112
 
                if ($_POST['confirm'] === $user->lang['YES'])
2113
 
                {
2114
 
                        $confirm = true;
2115
 
                }
2116
 
        }
2117
 
 
2118
 
        if ($check && $confirm)
2119
 
        {
2120
 
                $user_id = request_var('user_id', 0);
2121
 
                $session_id = request_var('sess', '');
2122
 
                $confirm_key = request_var('confirm_key', '');
2123
 
 
2124
 
                if ($user_id != $user->data['user_id'] || $session_id != $user->session_id || !$confirm_key || !$user->data['user_last_confirm_key'] || $confirm_key != $user->data['user_last_confirm_key'])
2125
 
                {
2126
 
                        return false;
2127
 
                }
2128
 
 
2129
 
                // Reset user_last_confirm_key
2130
 
                $sql = 'UPDATE ' . USERS_TABLE . " SET user_last_confirm_key = ''
2131
 
                        WHERE user_id = " . $user->data['user_id'];
2132
 
                $db->sql_query($sql);
2133
 
 
2134
 
                return true;
2135
 
        }
2136
 
        else if ($check)
2137
 
        {
2138
 
                return false;
2139
 
        }
2140
 
 
2141
 
        $s_hidden_fields = build_hidden_fields(array(
2142
 
                'user_id'       => $user->data['user_id'],
2143
 
                'sess'          => $user->session_id,
2144
 
                'sid'           => $user->session_id)
2145
 
        );
2146
 
 
2147
 
        // generate activation key
2148
 
        $confirm_key = gen_rand_string(10);
2149
 
 
2150
 
        if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin'])
2151
 
        {
2152
 
                adm_page_header((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]);
2153
 
        }
2154
 
        else
2155
 
        {
2156
 
                page_header((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]);
2157
 
        }
2158
 
 
2159
 
        $template->set_filenames(array(
2160
 
                'body' => $html_body)
2161
 
        );
2162
 
 
2163
 
        // If activation key already exist, we better do not re-use the key (something very strange is going on...)
2164
 
        if (request_var('confirm_key', ''))
2165
 
        {
2166
 
                // This should not occur, therefore we cancel the operation to safe the user
2167
 
                return false;
2168
 
        }
2169
 
 
2170
 
        // re-add sid / transform & to &amp; for user->page (user->page is always using &)
2171
 
        $use_page = ($u_action) ? $phpbb_root_path . $u_action : $phpbb_root_path . str_replace('&', '&amp;', $user->page['page']);
2172
 
        $u_action = reapply_sid($use_page);
2173
 
        $u_action .= ((strpos($u_action, '?') === false) ? '?' : '&amp;') . 'confirm_key=' . $confirm_key;
2174
 
 
2175
 
        $template->assign_vars(array(
2176
 
                'MESSAGE_TITLE'         => (!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title],
2177
 
                'MESSAGE_TEXT'          => (!isset($user->lang[$title . '_CONFIRM'])) ? $title : $user->lang[$title . '_CONFIRM'],
2178
 
 
2179
 
                'YES_VALUE'                     => $user->lang['YES'],
2180
 
                'S_CONFIRM_ACTION'      => $u_action,
2181
 
                'S_HIDDEN_FIELDS'       => $hidden . $s_hidden_fields)
2182
 
        );
2183
 
 
2184
 
        $sql = 'UPDATE ' . USERS_TABLE . " SET user_last_confirm_key = '" . $db->sql_escape($confirm_key) . "'
2185
 
                WHERE user_id = " . $user->data['user_id'];
2186
 
        $db->sql_query($sql);
2187
 
 
2188
 
        if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin'])
2189
 
        {
2190
 
                adm_page_footer();
2191
 
        }
2192
 
        else
2193
 
        {
2194
 
                page_footer();
2195
 
        }
2196
 
}
2197
 
 
2198
 
/**
2199
 
* Generate login box or verify password
2200
 
*/
2201
 
function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = false, $s_display = true)
2202
 
{
2203
 
        global $db, $user, $template, $auth, $phpEx, $phpbb_root_path, $config;
2204
 
 
2205
 
        $err = '';
2206
 
 
2207
 
        // Make sure user->setup() has been called
2208
 
        if (empty($user->lang))
2209
 
        {
2210
 
                $user->setup();
2211
 
        }
2212
 
 
2213
 
        // Print out error if user tries to authenticate as an administrator without having the privileges...
2214
 
        if ($admin && !$auth->acl_get('a_'))
2215
 
        {
2216
 
                // Not authd
2217
 
                // anonymous/inactive users are never able to go to the ACP even if they have the relevant permissions
2218
 
                if ($user->data['is_registered'])
2219
 
                {
2220
 
                        add_log('admin', 'LOG_ADMIN_AUTH_FAIL');
2221
 
                }
2222
 
                trigger_error('NO_AUTH_ADMIN');
2223
 
        }
2224
 
 
2225
 
        if (isset($_POST['login']))
2226
 
        {
2227
 
                // Get credential
2228
 
                if ($admin)
2229
 
                {
2230
 
                        $credential = request_var('credential', '');
2231
 
 
2232
 
                        if (strspn($credential, 'abcdef0123456789') !== strlen($credential) || strlen($credential) != 32)
2233
 
                        {
2234
 
                                if ($user->data['is_registered'])
2235
 
                                {
2236
 
                                        add_log('admin', 'LOG_ADMIN_AUTH_FAIL');
2237
 
                                }
2238
 
                                trigger_error('NO_AUTH_ADMIN');
2239
 
                        }
2240
 
 
2241
 
                        $password       = request_var('password_' . $credential, '', true);
2242
 
                }
2243
 
                else
2244
 
                {
2245
 
                        $password       = request_var('password', '', true);
2246
 
                }
2247
 
 
2248
 
                $username       = request_var('username', '', true);
2249
 
                $autologin      = (!empty($_POST['autologin'])) ? true : false;
2250
 
                $viewonline = (!empty($_POST['viewonline'])) ? 0 : 1;
2251
 
                $admin          = ($admin) ? 1 : 0;
2252
 
                $viewonline = ($admin) ? $user->data['session_viewonline'] : $viewonline;
2253
 
 
2254
 
                // Check if the supplied username is equal to the one stored within the database if re-authenticating
2255
 
                if ($admin && utf8_clean_string($username) != utf8_clean_string($user->data['username']))
2256
 
                {
2257
 
                        // We log the attempt to use a different username...
2258
 
                        add_log('admin', 'LOG_ADMIN_AUTH_FAIL');
2259
 
                        trigger_error('NO_AUTH_ADMIN_USER_DIFFER');
2260
 
                }
2261
 
 
2262
 
                // If authentication is successful we redirect user to previous page
2263
 
                $result = $auth->login($username, $password, $autologin, $viewonline, $admin);
2264
 
 
2265
 
                // If admin authentication and login, we will log if it was a success or not...
2266
 
                // We also break the operation on the first non-success login - it could be argued that the user already knows
2267
 
                if ($admin)
2268
 
                {
2269
 
                        if ($result['status'] == LOGIN_SUCCESS)
2270
 
                        {
2271
 
                                add_log('admin', 'LOG_ADMIN_AUTH_SUCCESS');
2272
 
                        }
2273
 
                        else
2274
 
                        {
2275
 
                                // Only log the failed attempt if a real user tried to.
2276
 
                                // anonymous/inactive users are never able to go to the ACP even if they have the relevant permissions
2277
 
                                if ($user->data['is_registered'])
2278
 
                                {
2279
 
                                        add_log('admin', 'LOG_ADMIN_AUTH_FAIL');
2280
 
                                }
2281
 
                        }
2282
 
                }
2283
 
 
2284
 
                // The result parameter is always an array, holding the relevant information...
2285
 
                if ($result['status'] == LOGIN_SUCCESS)
2286
 
                {
2287
 
                        $redirect = request_var('redirect', "{$phpbb_root_path}index.$phpEx");
2288
 
                        $message = ($l_success) ? $l_success : $user->lang['LOGIN_REDIRECT'];
2289
 
                        $l_redirect = ($admin) ? $user->lang['PROCEED_TO_ACP'] : (($redirect === "{$phpbb_root_path}index.$phpEx" || $redirect === "index.$phpEx") ? $user->lang['RETURN_INDEX'] : $user->lang['RETURN_PAGE']);
2290
 
 
2291
 
                        // append/replace SID (may change during the session for AOL users)
2292
 
                        $redirect = reapply_sid($redirect);
2293
 
 
2294
 
                        // Special case... the user is effectively banned, but we allow founders to login
2295
 
                        if (defined('IN_CHECK_BAN') && $result['user_row']['user_type'] != USER_FOUNDER)
2296
 
                        {
2297
 
                                return;
2298
 
                        }
2299
 
 
2300
 
                        meta_refresh(3, $redirect);
2301
 
                        trigger_error($message . '<br /><br />' . sprintf($l_redirect, '<a href="' . $redirect . '">', '</a>'));
2302
 
                }
2303
 
 
2304
 
                // Something failed, determine what...
2305
 
                if ($result['status'] == LOGIN_BREAK)
2306
 
                {
2307
 
                        trigger_error($result['error_msg'], E_USER_ERROR);
2308
 
                }
2309
 
 
2310
 
                // Special cases... determine
2311
 
                switch ($result['status'])
2312
 
                {
2313
 
                        case LOGIN_ERROR_ATTEMPTS:
2314
 
 
2315
 
                                // Show confirm image
2316
 
                                $sql = 'DELETE FROM ' . CONFIRM_TABLE . "
2317
 
                                        WHERE session_id = '" . $db->sql_escape($user->session_id) . "'
2318
 
                                                AND confirm_type = " . CONFIRM_LOGIN;
2319
 
                                $db->sql_query($sql);
2320
 
 
2321
 
                                // Generate code
2322
 
                                $code = gen_rand_string(mt_rand(5, 8));
2323
 
                                $confirm_id = md5(unique_id($user->ip));
2324
 
                                $seed = hexdec(substr(unique_id(), 4, 10));
2325
 
 
2326
 
                                // compute $seed % 0x7fffffff
2327
 
                                $seed -= 0x7fffffff * floor($seed / 0x7fffffff);
2328
 
 
2329
 
                                $sql = 'INSERT INTO ' . CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array(
2330
 
                                        'confirm_id'    => (string) $confirm_id,
2331
 
                                        'session_id'    => (string) $user->session_id,
2332
 
                                        'confirm_type'  => (int) CONFIRM_LOGIN,
2333
 
                                        'code'                  => (string) $code,
2334
 
                                        'seed'                  => (int) $seed)
2335
 
                                );
2336
 
                                $db->sql_query($sql);
2337
 
 
2338
 
                                $template->assign_vars(array(
2339
 
                                        'S_CONFIRM_CODE'                        => true,
2340
 
                                        'CONFIRM_ID'                            => $confirm_id,
2341
 
                                        'CONFIRM_IMAGE'                         => '<img src="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=confirm&amp;id=' . $confirm_id . '&amp;type=' . CONFIRM_LOGIN) . '" alt="" title="" />',
2342
 
                                        'L_LOGIN_CONFIRM_EXPLAIN'       => sprintf($user->lang['LOGIN_CONFIRM_EXPLAIN'], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'),
2343
 
                                ));
2344
 
 
2345
 
                                $err = $user->lang[$result['error_msg']];
2346
 
 
2347
 
                        break;
2348
 
 
2349
 
                        case LOGIN_ERROR_PASSWORD_CONVERT:
2350
 
                                $err = sprintf(
2351
 
                                        $user->lang[$result['error_msg']],
2352
 
                                        ($config['email_enable']) ? '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=sendpassword') . '">' : '',
2353
 
                                        ($config['email_enable']) ? '</a>' : '',
2354
 
                                        ($config['board_contact']) ? '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">' : '',
2355
 
                                        ($config['board_contact']) ? '</a>' : ''
2356
 
                                );
2357
 
                        break;
2358
 
 
2359
 
                        // Username, password, etc...
2360
 
                        default:
2361
 
                                $err = $user->lang[$result['error_msg']];
2362
 
 
2363
 
                                // Assign admin contact to some error messages
2364
 
                                if ($result['error_msg'] == 'LOGIN_ERROR_USERNAME' || $result['error_msg'] == 'LOGIN_ERROR_PASSWORD')
2365
 
                                {
2366
 
                                        $err = (!$config['board_contact']) ? sprintf($user->lang[$result['error_msg']], '', '') : sprintf($user->lang[$result['error_msg']], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>');
2367
 
                                }
2368
 
                                
2369
 
                        break;
2370
 
                }
2371
 
        }
2372
 
 
2373
 
        if (!$redirect)
2374
 
        {
2375
 
                // We just use what the session code determined...
2376
 
                // If we are not within the admin directory we use the page dir...
2377
 
                $redirect = '';
2378
 
 
2379
 
                if (!$admin)
2380
 
                {
2381
 
                        $redirect .= ($user->page['page_dir']) ? $user->page['page_dir'] . '/' : '';
2382
 
                }
2383
 
 
2384
 
                $redirect .= $user->page['page_name'] . (($user->page['query_string']) ? '?' . htmlspecialchars($user->page['query_string']) : '');
2385
 
        }
2386
 
 
2387
 
        // Assign credential for username/password pair
2388
 
        $credential = ($admin) ? md5(unique_id()) : false;
2389
 
 
2390
 
        $s_hidden_fields = array(
2391
 
                'redirect'      => $redirect,
2392
 
                'sid'           => $user->session_id,
2393
 
        );
2394
 
 
2395
 
        if ($admin)
2396
 
        {
2397
 
                $s_hidden_fields['credential'] = $credential;
2398
 
        }
2399
 
 
2400
 
        $s_hidden_fields = build_hidden_fields($s_hidden_fields);
2401
 
 
2402
 
        $template->assign_vars(array(
2403
 
                'LOGIN_ERROR'           => $err,
2404
 
                'LOGIN_EXPLAIN'         => $l_explain,
2405
 
 
2406
 
                'U_SEND_PASSWORD'               => ($config['email_enable']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=sendpassword') : '',
2407
 
                'U_RESEND_ACTIVATION'   => ($config['require_activation'] != USER_ACTIVATION_NONE && $config['email_enable']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=resend_act') : '',
2408
 
                'U_TERMS_USE'                   => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=terms'),
2409
 
                'U_PRIVACY'                             => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy'),
2410
 
 
2411
 
                'S_DISPLAY_FULL_LOGIN'  => ($s_display) ? true : false,
2412
 
                'S_LOGIN_ACTION'                => (!$admin) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login') : append_sid("index.$phpEx", false, true, $user->session_id), // Needs to stay index.$phpEx because we are within the admin directory
2413
 
                'S_HIDDEN_FIELDS'               => $s_hidden_fields,
2414
 
 
2415
 
                'S_ADMIN_AUTH'                  => $admin,
2416
 
                'USERNAME'                              => ($admin) ? $user->data['username'] : '',
2417
 
 
2418
 
                'USERNAME_CREDENTIAL'   => 'username',
2419
 
                'PASSWORD_CREDENTIAL'   => ($admin) ? 'password_' . $credential : 'password',
2420
 
        ));
2421
 
 
2422
 
        page_header($user->lang['LOGIN']);
2423
 
 
2424
 
        $template->set_filenames(array(
2425
 
                'body' => 'login_body.html')
2426
 
        );
2427
 
        make_jumpbox(append_sid("{$phpbb_root_path}viewforum.$phpEx"));
2428
 
 
2429
 
        page_footer();
2430
 
}
2431
 
 
2432
 
/**
2433
 
* Generate forum login box
2434
 
*/
2435
 
function login_forum_box($forum_data)
2436
 
{
2437
 
        global $db, $config, $user, $template, $phpEx;
2438
 
 
2439
 
        $password = request_var('password', '', true);
2440
 
 
2441
 
        $sql = 'SELECT forum_id
2442
 
                FROM ' . FORUMS_ACCESS_TABLE . '
2443
 
                WHERE forum_id = ' . $forum_data['forum_id'] . '
2444
 
                        AND user_id = ' . $user->data['user_id'] . "
2445
 
                        AND session_id = '" . $db->sql_escape($user->session_id) . "'";
2446
 
        $result = $db->sql_query($sql);
2447
 
        $row = $db->sql_fetchrow($result);
2448
 
        $db->sql_freeresult($result);
2449
 
 
2450
 
        if ($row)
2451
 
        {
2452
 
                return true;
2453
 
        }
2454
 
 
2455
 
        if ($password)
2456
 
        {
2457
 
                // Remove expired authorised sessions
2458
 
                $sql = 'SELECT f.session_id
2459
 
                        FROM ' . FORUMS_ACCESS_TABLE . ' f
2460
 
                        LEFT JOIN ' . SESSIONS_TABLE . ' s ON (f.session_id = s.session_id)
2461
 
                        WHERE s.session_id IS NULL';
2462
 
                $result = $db->sql_query($sql);
2463
 
 
2464
 
                if ($row = $db->sql_fetchrow($result))
2465
 
                {
2466
 
                        $sql_in = array();
2467
 
                        do
2468
 
                        {
2469
 
                                $sql_in[] = (string) $row['session_id'];
2470
 
                        }
2471
 
                        while ($row = $db->sql_fetchrow($result));
2472
 
 
2473
 
                        // Remove expired sessions
2474
 
                        $sql = 'DELETE FROM ' . FORUMS_ACCESS_TABLE . '
2475
 
                                WHERE ' . $db->sql_in_set('session_id', $sql_in);
2476
 
                        $db->sql_query($sql);
2477
 
                }
2478
 
                $db->sql_freeresult($result);
2479
 
 
2480
 
                if (phpbb_check_hash($password, $forum_data['forum_password']))
2481
 
                {
2482
 
                        $sql_ary = array(
2483
 
                                'forum_id'              => (int) $forum_data['forum_id'],
2484
 
                                'user_id'               => (int) $user->data['user_id'],
2485
 
                                'session_id'    => (string) $user->session_id,
2486
 
                        );
2487
 
 
2488
 
                        $db->sql_query('INSERT INTO ' . FORUMS_ACCESS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
2489
 
 
2490
 
                        return true;
2491
 
                }
2492
 
 
2493
 
                $template->assign_var('LOGIN_ERROR', $user->lang['WRONG_PASSWORD']);
2494
 
        }
2495
 
 
2496
 
        page_header($user->lang['LOGIN']);
2497
 
 
2498
 
        $template->assign_vars(array(
2499
 
                'S_HIDDEN_FIELDS'               => build_hidden_fields(array('f' => $forum_data['forum_id'])))
2500
 
        );
2501
 
 
2502
 
        $template->set_filenames(array(
2503
 
                'body' => 'login_forum.html')
2504
 
        );
2505
 
        
2506
 
        page_footer();
2507
 
}
2508
 
 
2509
 
// Little helpers
2510
 
 
2511
 
/**
2512
 
* Little helper for the build_hidden_fields function
2513
 
*/
2514
 
function _build_hidden_fields($key, $value, $specialchar, $stripslashes)
2515
 
{
2516
 
        $hidden_fields = '';
2517
 
 
2518
 
        if (!is_array($value))
2519
 
        {
2520
 
                $value = ($stripslashes) ? stripslashes($value) : $value;
2521
 
                $value = ($specialchar) ? htmlspecialchars($value, ENT_COMPAT, 'UTF-8') : $value;
2522
 
 
2523
 
                $hidden_fields .= '<input type="hidden" name="' . $key . '" value="' . $value . '" />' . "\n";
2524
 
        }
2525
 
        else
2526
 
        {
2527
 
                foreach ($value as $_key => $_value)
2528
 
                {
2529
 
                        $_key = ($stripslashes) ? stripslashes($_key) : $_key;
2530
 
                        $_key = ($specialchar) ? htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') : $_key;
2531
 
 
2532
 
                        $hidden_fields .= _build_hidden_fields($key . '[' . $_key . ']', $_value, $specialchar, $stripslashes);
2533
 
                }
2534
 
        }
2535
 
 
2536
 
        return $hidden_fields;
2537
 
}
2538
 
 
2539
 
/**
2540
 
* Build simple hidden fields from array
2541
 
*
2542
 
* @param array $field_ary an array of values to build the hidden field from
2543
 
* @param bool $specialchar if true, keys and values get specialchared
2544
 
* @param bool $stripslashes if true, keys and values get stripslashed
2545
 
*
2546
 
* @return string the hidden fields
2547
 
*/
2548
 
function build_hidden_fields($field_ary, $specialchar = false, $stripslashes = false)
2549
 
{
2550
 
        $s_hidden_fields = '';
2551
 
 
2552
 
        foreach ($field_ary as $name => $vars)
2553
 
        {
2554
 
                $name = ($stripslashes) ? stripslashes($name) : $name;
2555
 
                $name = ($specialchar) ? htmlspecialchars($name, ENT_COMPAT, 'UTF-8') : $name;
2556
 
 
2557
 
                $s_hidden_fields .= _build_hidden_fields($name, $vars, $specialchar, $stripslashes);
2558
 
        }
2559
 
 
2560
 
        return $s_hidden_fields;
2561
 
}
2562
 
 
2563
 
/**
2564
 
* Parse cfg file
2565
 
*/
2566
 
function parse_cfg_file($filename, $lines = false)
2567
 
{
2568
 
        $parsed_items = array();
2569
 
 
2570
 
        if ($lines === false)
2571
 
        {
2572
 
                $lines = file($filename);
2573
 
        }
2574
 
 
2575
 
        foreach ($lines as $line)
2576
 
        {
2577
 
                $line = trim($line);
2578
 
 
2579
 
                if (!$line || $line[0] == '#' || ($delim_pos = strpos($line, '=')) === false)
2580
 
                {
2581
 
                        continue;
2582
 
                }
2583
 
 
2584
 
                // Determine first occurrence, since in values the equal sign is allowed
2585
 
                $key = strtolower(trim(substr($line, 0, $delim_pos)));
2586
 
                $value = trim(substr($line, $delim_pos + 1));
2587
 
 
2588
 
                if (in_array($value, array('off', 'false', '0')))
2589
 
                {
2590
 
                        $value = false;
2591
 
                }
2592
 
                else if (in_array($value, array('on', 'true', '1')))
2593
 
                {
2594
 
                        $value = true;
2595
 
                }
2596
 
                else if (!trim($value))
2597
 
                {
2598
 
                        $value = '';
2599
 
                }
2600
 
                else if (($value[0] == "'" && $value[sizeof($value) - 1] == "'") || ($value[0] == '"' && $value[sizeof($value) - 1] == '"'))
2601
 
                {
2602
 
                        $value = substr($value, 1, sizeof($value)-2);
2603
 
                }
2604
 
        
2605
 
                $parsed_items[$key] = $value;
2606
 
        }
2607
 
        
2608
 
        return $parsed_items;
2609
 
}
2610
 
 
2611
 
/**
2612
 
* Add log event
2613
 
*/
2614
 
function add_log()
2615
 
{
2616
 
        global $db, $user;
2617
 
 
2618
 
        $args = func_get_args();
2619
 
 
2620
 
        $mode                   = array_shift($args);
2621
 
        $reportee_id    = ($mode == 'user') ? intval(array_shift($args)) : '';
2622
 
        $forum_id               = ($mode == 'mod') ? intval(array_shift($args)) : '';
2623
 
        $topic_id               = ($mode == 'mod') ? intval(array_shift($args)) : '';
2624
 
        $action                 = array_shift($args);
2625
 
        $data                   = (!sizeof($args)) ? '' : serialize($args);
2626
 
 
2627
 
        $sql_ary = array(
2628
 
                'user_id'               => (empty($user->data)) ? ANONYMOUS : $user->data['user_id'],
2629
 
                'log_ip'                => $user->ip,
2630
 
                'log_time'              => time(),
2631
 
                'log_operation' => $action,
2632
 
                'log_data'              => $data,
2633
 
        );
2634
 
        
2635
 
        switch ($mode)
2636
 
        {
2637
 
                case 'admin':
2638
 
                        $sql_ary['log_type'] = LOG_ADMIN;
2639
 
                break;
2640
 
                
2641
 
                case 'mod':
2642
 
                        $sql_ary += array(
2643
 
                                'log_type'      => LOG_MOD,
2644
 
                                'forum_id'      => $forum_id,
2645
 
                                'topic_id'      => $topic_id
2646
 
                        );
2647
 
                break;
2648
 
 
2649
 
                case 'user':
2650
 
                        $sql_ary += array(
2651
 
                                'log_type'              => LOG_USERS,
2652
 
                                'reportee_id'   => $reportee_id
2653
 
                        );
2654
 
                break;
2655
 
 
2656
 
                case 'critical':
2657
 
                        $sql_ary['log_type'] = LOG_CRITICAL;
2658
 
                break;
2659
 
                
2660
 
                default:
2661
 
                        return false;
2662
 
        }
2663
 
 
2664
 
        $db->sql_query('INSERT INTO ' . LOG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
2665
 
 
2666
 
        return $db->sql_nextid();
2667
 
}
2668
 
 
2669
 
/**
2670
 
* Return a nicely formatted backtrace (parts from the php manual by diz at ysagoon dot com)
2671
 
*/
2672
 
function get_backtrace()
2673
 
{
2674
 
        global $phpbb_root_path;
2675
 
 
2676
 
        $output = '<div style="font-family: monospace;">';
2677
 
        $backtrace = debug_backtrace();
2678
 
        $path = phpbb_realpath($phpbb_root_path);
2679
 
 
2680
 
        foreach ($backtrace as $number => $trace)
2681
 
        {
2682
 
                // We skip the first one, because it only shows this file/function
2683
 
                if ($number == 0)
2684
 
                {
2685
 
                        continue;
2686
 
                }
2687
 
 
2688
 
                // Strip the current directory from path
2689
 
                if (empty($trace['file']))
2690
 
                {
2691
 
                        $trace['file'] = '';
2692
 
                }
2693
 
                else
2694
 
                {
2695
 
                        $trace['file'] = str_replace(array($path, '\\'), array('', '/'), $trace['file']);
2696
 
                        $trace['file'] = substr($trace['file'], 1);
2697
 
                }
2698
 
                $args = array();
2699
 
 
2700
 
                // If include/require/include_once is not called, do not show arguments - they may contain sensible information
2701
 
                if (!in_array($trace['function'], array('include', 'require', 'include_once')))
2702
 
                {
2703
 
                        unset($trace['args']);
2704
 
                }
2705
 
                else
2706
 
                {
2707
 
                        // Path...
2708
 
                        if (!empty($trace['args'][0]))
2709
 
                        {
2710
 
                                $argument = htmlspecialchars($trace['args'][0]);
2711
 
                                $argument = str_replace(array($path, '\\'), array('', '/'), $argument);
2712
 
                                $argument = substr($argument, 1);
2713
 
                                $args[] = "'{$argument}'";
2714
 
                        }
2715
 
                }
2716
 
 
2717
 
                $trace['class'] = (!isset($trace['class'])) ? '' : $trace['class'];
2718
 
                $trace['type'] = (!isset($trace['type'])) ? '' : $trace['type'];
2719
 
 
2720
 
                $output .= '<br />';
2721
 
                $output .= '<b>FILE:</b> ' . htmlspecialchars($trace['file']) . '<br />';
2722
 
                $output .= '<b>LINE:</b> ' . ((!empty($trace['line'])) ? $trace['line'] : '') . '<br />';
2723
 
 
2724
 
                $output .= '<b>CALL:</b> ' . htmlspecialchars($trace['class'] . $trace['type'] . $trace['function']) . '(' . ((sizeof($args)) ? implode(', ', $args) : '') . ')<br />';
2725
 
        }
2726
 
        $output .= '</div>';
2727
 
        return $output;
2728
 
}
2729
 
 
2730
 
/**
2731
 
* This function returns a regular expression pattern for commonly used expressions
2732
 
* Use with / as delimiter for email mode and # for url modes
2733
 
* mode can be: email|bbcode_htm|url|url_inline|www_url|www_url_inline|relative_url|relative_url_inline|ipv4|ipv6
2734
 
*/
2735
 
function get_preg_expression($mode)
2736
 
{
2737
 
        switch ($mode)
2738
 
        {
2739
 
                case 'email':
2740
 
                        return '[a-z0-9&\'\.\-_\+]+@[a-z0-9\-]+\.([a-z0-9\-]+\.)*[a-z]+';
2741
 
                break;
2742
 
 
2743
 
                case 'bbcode_htm':
2744
 
                        return array(
2745
 
                                '#<!\-\- e \-\-><a href="mailto:(.*?)">.*?</a><!\-\- e \-\->#',
2746
 
                                '#<!\-\- l \-\-><a (?:class="[\w-]+" )?href="(.*?)(?:(&amp;|\?)sid=[0-9a-f]{32})?">.*?</a><!\-\- l \-\->#',
2747
 
                                '#<!\-\- ([mw]) \-\-><a (?:class="[\w-]+" )?href="(.*?)">.*?</a><!\-\- \1 \-\->#',
2748
 
                                '#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/.*? \/><!\-\- s\1 \-\->#',
2749
 
                                '#<!\-\- .*? \-\->#s',
2750
 
                                '#<.*?>#s',
2751
 
                        );
2752
 
                break;
2753
 
 
2754
 
                // Whoa these look impressive!
2755
 
                // The code to generate the following two regular expressions which match valid IPv4/IPv6 addresses
2756
 
                // can be found in the develop directory
2757
 
                case 'ipv4':
2758
 
                        return '#^(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$#';
2759
 
                break;
2760
 
 
2761
 
                case 'ipv6':
2762
 
                        return '#^(?:(?:(?:[\dA-F]{1,4}:){6}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:::(?:[\dA-F]{1,4}:){5}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:):(?:[\dA-F]{1,4}:){4}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,2}:(?:[\dA-F]{1,4}:){3}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,3}:(?:[\dA-F]{1,4}:){2}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,4}:(?:[\dA-F]{1,4}:)(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,5}:(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,6}:[\dA-F]{1,4})|(?:(?:[\dA-F]{1,4}:){1,7}:))$#i';
2763
 
                break;
2764
 
 
2765
 
                case 'url':
2766
 
                case 'url_inline':
2767
 
                        $inline = ($mode == 'url') ? ')' : '';
2768
 
                        $scheme = ($mode == 'url') ? '[a-z\d+\-.]' : '[a-z\d+]'; // avoid automatic parsing of "word" in "last word.http://..."
2769
 
                        // generated with regex generation file in the develop folder
2770
 
                        return "[a-z]$scheme*:/{2}(?:(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:/(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?";
2771
 
                break;
2772
 
 
2773
 
                case 'www_url':
2774
 
                case 'www_url_inline':
2775
 
                        $inline = ($mode == 'www_url') ? ')' : '';
2776
 
                        return "www\.(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})+(?::\d*)?(?:/(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?";
2777
 
                break;
2778
 
 
2779
 
                case 'relative_url':
2780
 
                case 'relative_url_inline':
2781
 
                        $inline = ($mode == 'relative_url') ? ')' : '';
2782
 
                        return "(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})*(?:/(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?";
2783
 
                break;
2784
 
        }
2785
 
 
2786
 
        return '';
2787
 
}
2788
 
 
2789
 
/**
2790
 
* Returns the first block of the specified IPv6 address and as many additional
2791
 
* ones as specified in the length paramater.
2792
 
* If length is zero, then an empty string is returned.
2793
 
* If length is greater than 3 the complete IP will be returned
2794
 
*/
2795
 
function short_ipv6($ip, $length)
2796
 
{
2797
 
        if ($length < 1)
2798
 
        {
2799
 
                return '';
2800
 
        }
2801
 
 
2802
 
        // extend IPv6 addresses
2803
 
        $blocks = substr_count($ip, ':') + 1;
2804
 
        if ($blocks < 9)
2805
 
        {
2806
 
                $ip = str_replace('::', ':' . str_repeat('0000:', 9 - $blocks), $ip);
2807
 
        }
2808
 
        if ($ip[0] == ':')
2809
 
        {
2810
 
                $ip = '0000' . $ip;
2811
 
        }
2812
 
        if ($length < 4)
2813
 
        {
2814
 
                $ip = implode(':', array_slice(explode(':', $ip), 0, 1 + $length));
2815
 
        }
2816
 
 
2817
 
        return $ip;
2818
 
}
2819
 
 
2820
 
/**
2821
 
* Wrapper for php's checkdnsrr function.
2822
 
*
2823
 
* The windows failover is from the php manual
2824
 
* Please make sure to check the return value for === true and === false, since NULL could
2825
 
* be returned too.
2826
 
*
2827
 
* @return true if entry found, false if not, NULL if this function is not supported by this environment
2828
 
*/
2829
 
function phpbb_checkdnsrr($host, $type = '')
2830
 
{
2831
 
        $type = (!$type) ? 'MX' : $type;
2832
 
 
2833
 
        if (DIRECTORY_SEPARATOR == '\\')
2834
 
        {
2835
 
                if (!function_exists('exec'))
2836
 
                {
2837
 
                        return NULL;
2838
 
                }
2839
 
 
2840
 
                // @exec('nslookup -retry=1 -timout=1 -type=' . escapeshellarg($type) . ' ' . escapeshellarg($host), $output);
2841
 
                @exec('nslookup -type=' . escapeshellarg($type) . ' ' . escapeshellarg($host), $output);
2842
 
 
2843
 
                // If output is empty, the nslookup failed
2844
 
                if (empty($output))
2845
 
                {
2846
 
                        return NULL;
2847
 
                }
2848
 
 
2849
 
                foreach ($output as $line)
2850
 
                {
2851
 
                        if (!trim($line))
2852
 
                        {
2853
 
                                continue;
2854
 
                        }
2855
 
 
2856
 
                        // Valid records begin with host name:
2857
 
                        if (strpos($line, $host) === 0)
2858
 
                        {
2859
 
                                return true;
2860
 
                        }
2861
 
                }
2862
 
 
2863
 
                return false;
2864
 
        }
2865
 
        else if (function_exists('checkdnsrr'))
2866
 
        {
2867
 
                return (checkdnsrr($host, $type)) ? true : false;
2868
 
        }
2869
 
 
2870
 
        return NULL;
2871
 
}
2872
 
 
2873
 
// Handler, header and footer
2874
 
 
2875
 
/**
2876
 
* Error and message handler, call with trigger_error if reqd
2877
 
*/
2878
 
function msg_handler($errno, $msg_text, $errfile, $errline)
2879
 
{
2880
 
        global $cache, $db, $auth, $template, $config, $user;
2881
 
        global $phpEx, $phpbb_root_path, $msg_title, $msg_long_text;
2882
 
 
2883
 
        // Do not display notices if we suppress them via @
2884
 
        if (error_reporting() == 0)
2885
 
        {
2886
 
                return;
2887
 
        }
2888
 
 
2889
 
        // Message handler is stripping text. In case we need it, we are possible to define long text...
2890
 
        if (isset($msg_long_text) && $msg_long_text && !$msg_text)
2891
 
        {
2892
 
                $msg_text = $msg_long_text;
2893
 
        }
2894
 
 
2895
 
        switch ($errno)
2896
 
        {
2897
 
                case E_NOTICE:
2898
 
                case E_WARNING:
2899
 
 
2900
 
                        // Check the error reporting level and return if the error level does not match
2901
 
                        // If DEBUG is defined the default level is E_ALL
2902
 
                        if (($errno & ((defined('DEBUG')) ? E_ALL : error_reporting())) == 0)
2903
 
                        {
2904
 
                                return;
2905
 
                        }
2906
 
 
2907
 
                        if (strpos($errfile, 'cache') === false && strpos($errfile, 'template.') === false)
2908
 
                        {
2909
 
                                // flush the content, else we get a white page if output buffering is on
2910
 
                                if ($config['gzip_compress'])
2911
 
                                {
2912
 
                                        if (@extension_loaded('zlib') && !headers_sent())
2913
 
                                        {
2914
 
                                                ob_flush();
2915
 
                                        }
2916
 
                                }
2917
 
 
2918
 
                                // remove complete path to installation, with the risk of changing backslashes meant to be there
2919
 
                                $errfile = str_replace(array(phpbb_realpath($phpbb_root_path), '\\'), array('', '/'), $errfile);
2920
 
                                $msg_text = str_replace(array(phpbb_realpath($phpbb_root_path), '\\'), array('', '/'), $msg_text);
2921
 
 
2922
 
                                echo '<b>[phpBB Debug] PHP Notice</b>: in file <b>' . $errfile . '</b> on line <b>' . $errline . '</b>: <b>' . $msg_text . '</b><br />' . "\n";
2923
 
                        }
2924
 
 
2925
 
                        return;
2926
 
 
2927
 
                break;
2928
 
 
2929
 
                case E_USER_ERROR:
2930
 
 
2931
 
                        if (!empty($user) && !empty($user->lang))
2932
 
                        {
2933
 
                                $msg_text = (!empty($user->lang[$msg_text])) ? $user->lang[$msg_text] : $msg_text;
2934
 
                                $msg_title = (!isset($msg_title)) ? $user->lang['GENERAL_ERROR'] : ((!empty($user->lang[$msg_title])) ? $user->lang[$msg_title] : $msg_title);
2935
 
 
2936
 
                                $l_return_index = sprintf($user->lang['RETURN_INDEX'], '<a href="' . $phpbb_root_path . '">', '</a>');
2937
 
                                $l_notify = '';
2938
 
 
2939
 
                                if (!empty($config['board_contact']))
2940
 
                                {
2941
 
                                        $l_notify = '<p>' . sprintf($user->lang['NOTIFY_ADMIN_EMAIL'], $config['board_contact']) . '</p>';
2942
 
                                }
2943
 
                        }
2944
 
                        else
2945
 
                        {
2946
 
                                $msg_title = 'General Error';
2947
 
                                $l_return_index = '<a href="' . $phpbb_root_path . '">Return to index page</a>';
2948
 
                                $l_notify = '';
2949
 
 
2950
 
                                if (!empty($config['board_contact']))
2951
 
                                {
2952
 
                                        $l_notify = '<p>Please notify the board administrator or webmaster: <a href="mailto:' . $config['board_contact'] . '">' . $config['board_contact'] . '</a></p>';
2953
 
                                }
2954
 
                        }
2955
 
 
2956
 
                        garbage_collection();
2957
 
 
2958
 
                        // Try to not call the adm page data...
2959
 
 
2960
 
                        echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
2961
 
                        echo '<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">';
2962
 
                        echo '<head>';
2963
 
                        echo '<meta http-equiv="content-type" content="text/html; charset=utf-8" />';
2964
 
                        echo '<title>' . $msg_title . '</title>';
2965
 
                        echo '<style type="text/css">' . "\n" . '<!--' . "\n";
2966
 
                        echo '* { margin: 0; padding: 0; } html { font-size: 100%; height: 100%; margin-bottom: 1px; background-color: #E4EDF0; } body { font-family: "Lucida Grande", Verdana, Helvetica, Arial, sans-serif; color: #536482; background: #E4EDF0; font-size: 62.5%; margin: 0; } ';
2967
 
                        echo 'a:link, a:active, a:visited { color: #006699; text-decoration: none; } a:hover { color: #DD6900; text-decoration: underline; } ';
2968
 
                        echo '#wrap { padding: 0 20px 15px 20px; min-width: 615px; } #page-header { text-align: right; height: 40px; } #page-footer { clear: both; font-size: 1em; text-align: center; } ';
2969
 
                        echo '.panel { margin: 4px 0; background-color: #FFFFFF; border: solid 1px  #A9B8C2; } ';
2970
 
                        echo '#errorpage #page-header a { font-weight: bold; line-height: 6em; } #errorpage #content { padding: 10px; } #errorpage #content h1 { line-height: 1.2em; margin-bottom: 0; color: #DF075C; } ';
2971
 
                        echo '#errorpage #content div { margin-top: 20px; margin-bottom: 5px; border-bottom: 1px solid #CCCCCC; padding-bottom: 5px; color: #333333; font: bold 1.2em "Lucida Grande", Arial, Helvetica, sans-serif; text-decoration: none; line-height: 120%; text-align: left; } ';
2972
 
                        echo "\n" . '//-->' . "\n";
2973
 
                        echo '</style>';
2974
 
                        echo '</head>';
2975
 
                        echo '<body id="errorpage">';
2976
 
                        echo '<div id="wrap">';
2977
 
                        echo '  <div id="page-header">';
2978
 
                        echo '          ' . $l_return_index;
2979
 
                        echo '  </div>';
2980
 
                        echo '  <div id="acp">';
2981
 
                        echo '  <div class="panel">';
2982
 
                        echo '          <div id="content">';
2983
 
                        echo '                  <h1>' . $msg_title . '</h1>';
2984
 
                        
2985
 
                        echo '                  <div>' . $msg_text . '</div>';
2986
 
                        
2987
 
                        echo $l_notify;
2988
 
 
2989
 
                        echo '          </div>';
2990
 
                        echo '  </div>';
2991
 
                        echo '  </div>';
2992
 
                        echo '  <div id="page-footer">';
2993
 
                        echo '          Powered by phpBB &copy; 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a>';
2994
 
                        echo '  </div>';
2995
 
                        echo '</div>';
2996
 
                        echo '</body>';
2997
 
                        echo '</html>';
2998
 
                        
2999
 
                        exit_handler();
3000
 
                break;
3001
 
 
3002
 
                case E_USER_WARNING:
3003
 
                case E_USER_NOTICE:
3004
 
 
3005
 
                        define('IN_ERROR_HANDLER', true);
3006
 
 
3007
 
                        if (empty($user->data))
3008
 
                        {
3009
 
                                $user->session_begin();
3010
 
                        }
3011
 
 
3012
 
                        // We re-init the auth array to get correct results on login/logout
3013
 
                        $auth->acl($user->data);
3014
 
 
3015
 
                        if (empty($user->lang))
3016
 
                        {
3017
 
                                $user->setup();
3018
 
                        }
3019
 
 
3020
 
                        $msg_text = (!empty($user->lang[$msg_text])) ? $user->lang[$msg_text] : $msg_text;
3021
 
                        $msg_title = (!isset($msg_title)) ? $user->lang['INFORMATION'] : ((!empty($user->lang[$msg_title])) ? $user->lang[$msg_title] : $msg_title);
3022
 
 
3023
 
                        if (!defined('HEADER_INC'))
3024
 
                        {
3025
 
                                if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin'])
3026
 
                                {
3027
 
                                        adm_page_header($msg_title);
3028
 
                                }
3029
 
                                else
3030
 
                                {
3031
 
                                        page_header($msg_title);
3032
 
                                }
3033
 
                        }
3034
 
 
3035
 
                        $template->set_filenames(array(
3036
 
                                'body' => 'message_body.html')
3037
 
                        );
3038
 
 
3039
 
                        $template->assign_vars(array(
3040
 
                                'MESSAGE_TITLE'         => $msg_title,
3041
 
                                'MESSAGE_TEXT'          => $msg_text,
3042
 
                                'S_USER_WARNING'        => ($errno == E_USER_WARNING) ? true : false,
3043
 
                                'S_USER_NOTICE'         => ($errno == E_USER_NOTICE) ? true : false)
3044
 
                        );
3045
 
 
3046
 
                        // We do not want the cron script to be called on error messages
3047
 
                        define('IN_CRON', true);
3048
 
                        
3049
 
                        if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin'])
3050
 
                        {
3051
 
                                adm_page_footer();
3052
 
                        }
3053
 
                        else
3054
 
                        {
3055
 
                                page_footer();
3056
 
                        }
3057
 
 
3058
 
                        exit_handler();
3059
 
                break;
3060
 
        }
3061
 
 
3062
 
        // If we notice an error not handled here we pass this back to PHP by returning false
3063
 
        // This may not work for all php versions
3064
 
        return false;
3065
 
}
3066
 
 
3067
 
/**
3068
 
* Generate page header
3069
 
*/
3070
 
function page_header($page_title = '', $display_online_list = true)
3071
 
{
3072
 
        global $db, $config, $template, $SID, $_SID, $user, $auth, $phpEx, $phpbb_root_path;
3073
 
 
3074
 
        if (defined('HEADER_INC'))
3075
 
        {
3076
 
                return;
3077
 
        }
3078
 
        
3079
 
        define('HEADER_INC', true);
3080
 
 
3081
 
        // gzip_compression
3082
 
        if ($config['gzip_compress'])
3083
 
        {
3084
 
                if (@extension_loaded('zlib') && !headers_sent())
3085
 
                {
3086
 
                        ob_start('ob_gzhandler');
3087
 
                }
3088
 
        }
3089
 
 
3090
 
        // Generate logged in/logged out status
3091
 
        if ($user->data['user_id'] != ANONYMOUS)
3092
 
        {
3093
 
                $u_login_logout = append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=logout', true, $user->session_id);
3094
 
                $l_login_logout = sprintf($user->lang['LOGOUT_USER'], $user->data['username']);
3095
 
        }
3096
 
        else
3097
 
        {
3098
 
                $u_login_logout = append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login');
3099
 
                $l_login_logout = $user->lang['LOGIN'];
3100
 
        }
3101
 
 
3102
 
        // Last visit date/time
3103
 
        $s_last_visit = ($user->data['user_id'] != ANONYMOUS) ? $user->format_date($user->data['session_last_visit']) : '';
3104
 
 
3105
 
        // Get users online list ... if required
3106
 
        $l_online_users = $online_userlist = $l_online_record = '';
3107
 
 
3108
 
        if ($config['load_online'] && $config['load_online_time'] && $display_online_list)
3109
 
        {
3110
 
                $logged_visible_online = $logged_hidden_online = $guests_online = $prev_user_id = 0;
3111
 
                $prev_session_ip = $reading_sql = '';
3112
 
 
3113
 
                if (!empty($_REQUEST['f']))
3114
 
                {
3115
 
                        $f = request_var('f', 0);
3116
 
 
3117
 
                        $reading_sql = ' AND s.session_page ' . $db->sql_like_expression("{$db->any_char}_f_={$f}x{$db->any_char}");
3118
 
                }
3119
 
 
3120
 
                // Get number of online guests
3121
 
                if (!$config['load_online_guests'])
3122
 
                {
3123
 
                        if ($db->sql_layer === 'sqlite')
3124
 
                        {
3125
 
                                $sql = 'SELECT COUNT(session_ip) as num_guests
3126
 
                                        FROM (
3127
 
                                                SELECT DISTINCT s.session_ip
3128
 
                                                        FROM ' . SESSIONS_TABLE . ' s
3129
 
                                                        WHERE s.session_user_id = ' . ANONYMOUS . '
3130
 
                                                                AND s.session_time >= ' . (time() - ($config['load_online_time'] * 60)) .
3131
 
                                                                $reading_sql .
3132
 
                                        ')';
3133
 
                        }
3134
 
                        else
3135
 
                        {
3136
 
                                $sql = 'SELECT COUNT(DISTINCT s.session_ip) as num_guests
3137
 
                                        FROM ' . SESSIONS_TABLE . ' s
3138
 
                                        WHERE s.session_user_id = ' . ANONYMOUS . '
3139
 
                                                AND s.session_time >= ' . (time() - ($config['load_online_time'] * 60)) .
3140
 
                                        $reading_sql;
3141
 
                        }
3142
 
                        $result = $db->sql_query($sql);
3143
 
                        $guests_online = (int) $db->sql_fetchfield('num_guests');
3144
 
                        $db->sql_freeresult($result);
3145
 
                }
3146
 
 
3147
 
                $sql = 'SELECT u.username, u.username_clean, u.user_id, u.user_type, u.user_allow_viewonline, u.user_colour, s.session_ip, s.session_viewonline
3148
 
                        FROM ' . USERS_TABLE . ' u, ' . SESSIONS_TABLE . ' s
3149
 
                        WHERE s.session_time >= ' . (time() - (intval($config['load_online_time']) * 60)) .
3150
 
                                $reading_sql .
3151
 
                                ((!$config['load_online_guests']) ? ' AND s.session_user_id <> ' . ANONYMOUS : '') . '
3152
 
                                AND u.user_id = s.session_user_id
3153
 
                        ORDER BY u.username_clean ASC, s.session_ip ASC';
3154
 
                $result = $db->sql_query($sql);
3155
 
 
3156
 
                while ($row = $db->sql_fetchrow($result))
3157
 
                {
3158
 
                        // User is logged in and therefore not a guest
3159
 
                        if ($row['user_id'] != ANONYMOUS)
3160
 
                        {
3161
 
                                // Skip multiple sessions for one user
3162
 
                                if ($row['user_id'] != $prev_user_id)
3163
 
                                {
3164
 
                                        if ($row['session_viewonline'])
3165
 
                                        {
3166
 
                                                $logged_visible_online++;
3167
 
                                        }
3168
 
                                        else
3169
 
                                        {
3170
 
                                                $row['username'] = '<em>' . $row['username'] . '</em>';
3171
 
                                                $logged_hidden_online++;
3172
 
                                        }
3173
 
 
3174
 
                                        if (($row['session_viewonline']) || $auth->acl_get('u_viewonline'))
3175
 
                                        {
3176
 
                                                $user_online_link = get_username_string(($row['user_type'] <> USER_IGNORE) ? 'full' : 'no_profile', $row['user_id'], $row['username'], $row['user_colour']);
3177
 
                                                $online_userlist .= ($online_userlist != '') ? ', ' . $user_online_link : $user_online_link;
3178
 
                                        }
3179
 
                                }
3180
 
 
3181
 
                                $prev_user_id = $row['user_id'];
3182
 
                        }
3183
 
                        else
3184
 
                        {
3185
 
                                // Skip multiple sessions for one user
3186
 
                                if ($row['session_ip'] != $prev_session_ip)
3187
 
                                {
3188
 
                                        $guests_online++;
3189
 
                                }
3190
 
                        }
3191
 
 
3192
 
                        $prev_session_ip = $row['session_ip'];
3193
 
                }
3194
 
                $db->sql_freeresult($result);
3195
 
 
3196
 
                if (!$online_userlist)
3197
 
                {
3198
 
                        $online_userlist = $user->lang['NO_ONLINE_USERS'];
3199
 
                }
3200
 
 
3201
 
                if (empty($_REQUEST['f']))
3202
 
                {
3203
 
                        $online_userlist = $user->lang['REGISTERED_USERS'] . ' ' . $online_userlist;
3204
 
                }
3205
 
                else
3206
 
                {
3207
 
                        $l_online = ($guests_online == 1) ? $user->lang['BROWSING_FORUM_GUEST'] : $user->lang['BROWSING_FORUM_GUESTS'];
3208
 
                        $online_userlist = sprintf($l_online, $online_userlist, $guests_online);
3209
 
                }
3210
 
 
3211
 
                $total_online_users = $logged_visible_online + $logged_hidden_online + $guests_online;
3212
 
 
3213
 
                if ($total_online_users > $config['record_online_users'])
3214
 
                {
3215
 
                        set_config('record_online_users', $total_online_users, true);
3216
 
                        set_config('record_online_date', time(), true);
3217
 
                }
3218
 
 
3219
 
                // Build online listing
3220
 
                $vars_online = array(
3221
 
                        'ONLINE'        => array('total_online_users', 'l_t_user_s'),
3222
 
                        'REG'           => array('logged_visible_online', 'l_r_user_s'),
3223
 
                        'HIDDEN'        => array('logged_hidden_online', 'l_h_user_s'),
3224
 
                        'GUEST'         => array('guests_online', 'l_g_user_s')
3225
 
                );
3226
 
 
3227
 
                foreach ($vars_online as $l_prefix => $var_ary)
3228
 
                {
3229
 
                        switch (${$var_ary[0]})
3230
 
                        {
3231
 
                                case 0:
3232
 
                                        ${$var_ary[1]} = $user->lang[$l_prefix . '_USERS_ZERO_TOTAL'];
3233
 
                                break;
3234
 
 
3235
 
                                case 1:
3236
 
                                        ${$var_ary[1]} = $user->lang[$l_prefix . '_USER_TOTAL'];
3237
 
                                break;
3238
 
 
3239
 
                                default:
3240
 
                                        ${$var_ary[1]} = $user->lang[$l_prefix . '_USERS_TOTAL'];
3241
 
                                break;
3242
 
                        }
3243
 
                }
3244
 
                unset($vars_online);
3245
 
 
3246
 
                $l_online_users = sprintf($l_t_user_s, $total_online_users);
3247
 
                $l_online_users .= sprintf($l_r_user_s, $logged_visible_online);
3248
 
                $l_online_users .= sprintf($l_h_user_s, $logged_hidden_online);
3249
 
                $l_online_users .= sprintf($l_g_user_s, $guests_online);
3250
 
 
3251
 
                $l_online_record = sprintf($user->lang['RECORD_ONLINE_USERS'], $config['record_online_users'], $user->format_date($config['record_online_date']));
3252
 
 
3253
 
                $l_online_time = ($config['load_online_time'] == 1) ? 'VIEW_ONLINE_TIME' : 'VIEW_ONLINE_TIMES';
3254
 
                $l_online_time = sprintf($user->lang[$l_online_time], $config['load_online_time']);
3255
 
        }
3256
 
        else
3257
 
        {
3258
 
                $l_online_time = '';
3259
 
        }
3260
 
 
3261
 
        $l_privmsgs_text = $l_privmsgs_text_unread = '';
3262
 
        $s_privmsg_new = false;
3263
 
 
3264
 
        // Obtain number of new private messages if user is logged in
3265
 
        if (isset($user->data['is_registered']) && $user->data['is_registered'])
3266
 
        {
3267
 
                if ($user->data['user_new_privmsg'])
3268
 
                {
3269
 
                        $l_message_new = ($user->data['user_new_privmsg'] == 1) ? $user->lang['NEW_PM'] : $user->lang['NEW_PMS'];
3270
 
                        $l_privmsgs_text = sprintf($l_message_new, $user->data['user_new_privmsg']);
3271
 
 
3272
 
                        if (!$user->data['user_last_privmsg'] || $user->data['user_last_privmsg'] > $user->data['session_last_visit'])
3273
 
                        {
3274
 
                                $sql = 'UPDATE ' . USERS_TABLE . '
3275
 
                                        SET user_last_privmsg = ' . $user->data['session_last_visit'] . '
3276
 
                                        WHERE user_id = ' . $user->data['user_id'];
3277
 
                                $db->sql_query($sql);
3278
 
 
3279
 
                                $s_privmsg_new = true;
3280
 
                        }
3281
 
                        else
3282
 
                        {
3283
 
                                $s_privmsg_new = false;
3284
 
                        }
3285
 
                }
3286
 
                else
3287
 
                {
3288
 
                        $l_privmsgs_text = $user->lang['NO_NEW_PM'];
3289
 
                        $s_privmsg_new = false;
3290
 
                }
3291
 
 
3292
 
                $l_privmsgs_text_unread = '';
3293
 
 
3294
 
                if ($user->data['user_unread_privmsg'] && $user->data['user_unread_privmsg'] != $user->data['user_new_privmsg'])
3295
 
                {
3296
 
                        $l_message_unread = ($user->data['user_unread_privmsg'] == 1) ? $user->lang['UNREAD_PM'] : $user->lang['UNREAD_PMS'];
3297
 
                        $l_privmsgs_text_unread = sprintf($l_message_unread, $user->data['user_unread_privmsg']);
3298
 
                }
3299
 
        }
3300
 
 
3301
 
        // Which timezone?
3302
 
        $tz = ($user->data['user_id'] != ANONYMOUS) ? strval(doubleval($user->data['user_timezone'])) : strval(doubleval($config['board_timezone']));
3303
 
        
3304
 
        // The following assigns all _common_ variables that may be used at any point in a template.
3305
 
        $template->assign_vars(array(
3306
 
                'SITENAME'                                              => $config['sitename'],
3307
 
                'SITE_DESCRIPTION'                              => $config['site_desc'],
3308
 
                'PAGE_TITLE'                                    => $page_title,
3309
 
                'SCRIPT_NAME'                                   => str_replace('.' . $phpEx, '', $user->page['page_name']),
3310
 
                'LAST_VISIT_DATE'                               => sprintf($user->lang['YOU_LAST_VISIT'], $s_last_visit),
3311
 
                'LAST_VISIT_YOU'                                => $s_last_visit,
3312
 
                'CURRENT_TIME'                                  => sprintf($user->lang['CURRENT_TIME'], $user->format_date(time(), false, true)),
3313
 
                'TOTAL_USERS_ONLINE'                    => $l_online_users,
3314
 
                'LOGGED_IN_USER_LIST'                   => $online_userlist,
3315
 
                'RECORD_USERS'                                  => $l_online_record,
3316
 
                'PRIVATE_MESSAGE_INFO'                  => $l_privmsgs_text,
3317
 
                'PRIVATE_MESSAGE_INFO_UNREAD'   => $l_privmsgs_text_unread,
3318
 
 
3319
 
                'S_USER_NEW_PRIVMSG'                    => $user->data['user_new_privmsg'],
3320
 
                'S_USER_UNREAD_PRIVMSG'                 => $user->data['user_unread_privmsg'],
3321
 
 
3322
 
                'SID'                           => $SID,
3323
 
                '_SID'                          => $_SID,
3324
 
                'SESSION_ID'            => $user->session_id,
3325
 
                'ROOT_PATH'                     => $phpbb_root_path,
3326
 
 
3327
 
                'L_LOGIN_LOGOUT'        => $l_login_logout,
3328
 
                'L_INDEX'                       => $user->lang['FORUM_INDEX'],
3329
 
                'L_ONLINE_EXPLAIN'      => $l_online_time,
3330
 
 
3331
 
                'U_PRIVATEMSGS'                 => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=inbox'),
3332
 
                'U_RETURN_INBOX'                => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=inbox'),
3333
 
                'U_POPUP_PM'                    => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;mode=popup'),
3334
 
                'UA_POPUP_PM'                   => addslashes(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;mode=popup')),
3335
 
                'U_MEMBERLIST'                  => append_sid("{$phpbb_root_path}memberlist.$phpEx"),
3336
 
                'U_MEMBERSLIST'                 => append_sid("{$phpbb_root_path}memberlist.$phpEx"),
3337
 
                'U_VIEWONLINE'                  => ($auth->acl_gets('u_viewprofile', 'a_user', 'a_useradd', 'a_userdel')) ? append_sid("{$phpbb_root_path}viewonline.$phpEx") : '',
3338
 
                'U_LOGIN_LOGOUT'                => $u_login_logout,
3339
 
                'U_INDEX'                               => append_sid("{$phpbb_root_path}index.$phpEx"),
3340
 
                'U_SEARCH'                              => append_sid("{$phpbb_root_path}search.$phpEx"),
3341
 
                'U_REGISTER'                    => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register'),
3342
 
                'U_PROFILE'                             => append_sid("{$phpbb_root_path}ucp.$phpEx"),
3343
 
                'U_MODCP'                               => append_sid("{$phpbb_root_path}mcp.$phpEx", false, true, $user->session_id),
3344
 
                'U_FAQ'                                 => append_sid("{$phpbb_root_path}faq.$phpEx"),
3345
 
                'U_SEARCH_SELF'                 => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=egosearch'),
3346
 
                'U_SEARCH_NEW'                  => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=newposts'),
3347
 
                'U_SEARCH_UNANSWERED'   => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unanswered'),
3348
 
                'U_SEARCH_ACTIVE_TOPICS'=> append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=active_topics'),
3349
 
                'U_DELETE_COOKIES'              => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=delete_cookies'),
3350
 
                'U_TEAM'                                => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=leaders'),
3351
 
                'U_RESTORE_PERMISSIONS' => ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=restore_perm') : '',
3352
 
 
3353
 
                'S_USER_LOGGED_IN'              => ($user->data['user_id'] != ANONYMOUS) ? true : false,
3354
 
                'S_AUTOLOGIN_ENABLED'   => ($config['allow_autologin']) ? true : false,
3355
 
                'S_BOARD_DISABLED'              => ($config['board_disable']) ? true : false,
3356
 
                'S_REGISTERED_USER'             => $user->data['is_registered'],
3357
 
                'S_IS_BOT'                              => $user->data['is_bot'],
3358
 
                'S_USER_PM_POPUP'               => $user->optionget('popuppm'),
3359
 
                'S_USER_LANG'                   => $user->lang['USER_LANG'],
3360
 
                'S_USER_BROWSER'                => (isset($user->data['session_browser'])) ? $user->data['session_browser'] : $user->lang['UNKNOWN_BROWSER'],
3361
 
                'S_USERNAME'                    => $user->data['username'],
3362
 
                'S_CONTENT_DIRECTION'   => $user->lang['DIRECTION'],
3363
 
                'S_CONTENT_FLOW_BEGIN'  => ($user->lang['DIRECTION'] == 'ltr') ? 'left' : 'right',
3364
 
                'S_CONTENT_FLOW_END'    => ($user->lang['DIRECTION'] == 'ltr') ? 'right' : 'left',
3365
 
                'S_CONTENT_ENCODING'    => 'UTF-8',
3366
 
                'S_TIMEZONE'                    => ($user->data['user_dst'] || ($user->data['user_id'] == ANONYMOUS && $config['board_dst'])) ? sprintf($user->lang['ALL_TIMES'], $user->lang['tz'][$tz], $user->lang['tz']['dst']) : sprintf($user->lang['ALL_TIMES'], $user->lang['tz'][$tz], ''),
3367
 
                'S_DISPLAY_ONLINE_LIST' => ($l_online_time) ? 1 : 0,
3368
 
                'S_DISPLAY_SEARCH'              => (!$config['load_search']) ? 0 : (isset($auth) ? ($auth->acl_get('u_search') && $auth->acl_getf_global('f_search')) : 1),
3369
 
                'S_DISPLAY_PM'                  => ($config['allow_privmsg'] && $user->data['is_registered'] && ($auth->acl_get('u_readpm') || $auth->acl_get('u_sendpm'))) ? true : false,
3370
 
                'S_DISPLAY_MEMBERLIST'  => (isset($auth)) ? $auth->acl_get('u_viewprofile') : 0,
3371
 
                'S_NEW_PM'                              => ($s_privmsg_new) ? 1 : 0,
3372
 
 
3373
 
                'T_THEME_PATH'                  => "{$phpbb_root_path}styles/" . $user->theme['theme_path'] . '/theme',
3374
 
                'T_TEMPLATE_PATH'               => "{$phpbb_root_path}styles/" . $user->theme['template_path'] . '/template',
3375
 
                'T_IMAGESET_PATH'               => "{$phpbb_root_path}styles/" . $user->theme['imageset_path'] . '/imageset',
3376
 
                'T_IMAGESET_LANG_PATH'  => "{$phpbb_root_path}styles/" . $user->theme['imageset_path'] . '/imageset/' . $user->data['user_lang'],
3377
 
                'T_IMAGES_PATH'                 => "{$phpbb_root_path}images/",
3378
 
                'T_SMILIES_PATH'                => "{$phpbb_root_path}{$config['smilies_path']}/",
3379
 
                'T_AVATAR_PATH'                 => "{$phpbb_root_path}{$config['avatar_path']}/",
3380
 
                'T_AVATAR_GALLERY_PATH' => "{$phpbb_root_path}{$config['avatar_gallery_path']}/",
3381
 
                'T_ICONS_PATH'                  => "{$phpbb_root_path}{$config['icons_path']}/",
3382
 
                'T_RANKS_PATH'                  => "{$phpbb_root_path}{$config['ranks_path']}/",
3383
 
                'T_UPLOAD_PATH'                 => "{$phpbb_root_path}{$config['upload_path']}/",
3384
 
                'T_STYLESHEET_LINK'             => (!$user->theme['theme_storedb']) ? "{$phpbb_root_path}styles/" . $user->theme['theme_path'] . '/theme/stylesheet.css' : "{$phpbb_root_path}style.$phpEx?sid=$user->session_id&amp;id=" . $user->theme['style_id'] . '&amp;lang=' . $user->data['user_lang'],
3385
 
                'T_STYLESHEET_NAME'             => $user->theme['theme_name'],
3386
 
 
3387
 
                'SITE_LOGO_IMG'                 => $user->img('site_logo'))
3388
 
        );
3389
 
 
3390
 
        // application/xhtml+xml not used because of IE
3391
 
        header('Content-type: text/html; charset=UTF-8');
3392
 
 
3393
 
        header('Cache-Control: private, no-cache="set-cookie"');
3394
 
        header('Expires: 0');
3395
 
        header('Pragma: no-cache');
3396
 
 
3397
 
        return;
3398
 
}
3399
 
 
3400
 
/**
3401
 
* Generate page footer
3402
 
*/
3403
 
function page_footer($run_cron = true)
3404
 
{
3405
 
        global $db, $config, $template, $user, $auth, $cache, $starttime, $phpbb_root_path, $phpEx;
3406
 
 
3407
 
        // Output page creation time
3408
 
        if (defined('DEBUG'))
3409
 
        {
3410
 
                $mtime = explode(' ', microtime());
3411
 
                $totaltime = $mtime[0] + $mtime[1] - $starttime;
3412
 
 
3413
 
                if (!empty($_REQUEST['explain']) && $auth->acl_get('a_') && defined('DEBUG_EXTRA') && method_exists($db, 'sql_report'))
3414
 
                {
3415
 
                        $db->sql_report('display');
3416
 
                }
3417
 
 
3418
 
                $debug_output = sprintf('Time : %.3fs | ' . $db->sql_num_queries() . ' Queries | GZIP : ' . (($config['gzip_compress']) ? 'On' : 'Off') . (($user->load) ? ' | Load : ' . $user->load : ''), $totaltime);
3419
 
 
3420
 
                if ($auth->acl_get('a_') && defined('DEBUG_EXTRA'))
3421
 
                {
3422
 
                        if (function_exists('memory_get_usage'))
3423
 
                        {
3424
 
                                if ($memory_usage = memory_get_usage())
3425
 
                                {
3426
 
                                        global $base_memory_usage;
3427
 
                                        $memory_usage -= $base_memory_usage;
3428
 
                                        $memory_usage = ($memory_usage >= 1048576) ? round((round($memory_usage / 1048576 * 100) / 100), 2) . ' ' . $user->lang['MB'] : (($memory_usage >= 1024) ? round((round($memory_usage / 1024 * 100) / 100), 2) . ' ' . $user->lang['KB'] : $memory_usage . ' ' . $user->lang['BYTES']);
3429
 
 
3430
 
                                        $debug_output .= ' | Memory Usage: ' . $memory_usage;
3431
 
                                }
3432
 
                        }
3433
 
 
3434
 
                        $debug_output .= ' | <a href="' . build_url() . '&amp;explain=1">Explain</a>';
3435
 
                }
3436
 
        }
3437
 
 
3438
 
        $template->assign_vars(array(
3439
 
                'DEBUG_OUTPUT'                  => (defined('DEBUG')) ? $debug_output : '',
3440
 
                'TRANSLATION_INFO'              => (!empty($user->lang['TRANSLATION_INFO'])) ? $user->lang['TRANSLATION_INFO'] : '',
3441
 
 
3442
 
                'U_ACP' => ($auth->acl_get('a_') && $user->data['is_registered']) ? append_sid("{$phpbb_root_path}adm/index.$phpEx", false, true, $user->session_id) : '')
3443
 
        );
3444
 
 
3445
 
        // Call cron-type script
3446
 
        if (!defined('IN_CRON') && $run_cron && !$config['board_disable'])
3447
 
        {
3448
 
                $cron_type = '';
3449
 
        
3450
 
                if (time() - $config['queue_interval'] > $config['last_queue_run'] && !defined('IN_ADMIN') && file_exists($phpbb_root_path . 'cache/queue.' . $phpEx))
3451
 
                {
3452
 
                        // Process email queue
3453
 
                        $cron_type = 'queue';
3454
 
                }
3455
 
                else if (method_exists($cache, 'tidy') && time() - $config['cache_gc'] > $config['cache_last_gc'])
3456
 
                {
3457
 
                        // Tidy the cache
3458
 
                        $cron_type = 'tidy_cache';
3459
 
                }
3460
 
                else if (time() - $config['warnings_gc'] > $config['warnings_last_gc'])
3461
 
                {
3462
 
                        $cron_type = 'tidy_warnings';
3463
 
                }
3464
 
                else if (time() - $config['database_gc'] > $config['database_last_gc'])
3465
 
                {
3466
 
                        // Tidy the database
3467
 
                        $cron_type = 'tidy_database';
3468
 
                }
3469
 
                else if (time() - $config['search_gc'] > $config['search_last_gc'])
3470
 
                {
3471
 
                        // Tidy the search
3472
 
                        $cron_type = 'tidy_search';
3473
 
                }
3474
 
                else if (time() - $config['session_gc'] > $config['session_last_gc'])
3475
 
                {
3476
 
                        $cron_type = 'tidy_sessions';
3477
 
                }
3478
 
 
3479
 
                if ($cron_type)
3480
 
                {
3481
 
                        $template->assign_var('RUN_CRON_TASK', '<img src="' . append_sid($phpbb_root_path . 'cron.' . $phpEx, 'cron_type=' . $cron_type) . '" width="1" height="1" alt="cron" />');
3482
 
                }
3483
 
        }
3484
 
 
3485
 
        $template->display('body');
3486
 
 
3487
 
        garbage_collection();
3488
 
        exit_handler();
3489
 
}
3490
 
 
3491
 
/**
3492
 
* Closing the cache object and the database
3493
 
* Cool function name, eh? We might want to add operations to it later
3494
 
*/
3495
 
function garbage_collection()
3496
 
{
3497
 
        global $cache, $db;
3498
 
 
3499
 
        // Unload cache, must be done before the DB connection if closed
3500
 
        if (!empty($cache))
3501
 
        {
3502
 
                $cache->unload();
3503
 
        }
3504
 
 
3505
 
        // Close our DB connection.
3506
 
        if (!empty($db))
3507
 
        {
3508
 
                $db->sql_close();
3509
 
        }
3510
 
}
3511
 
 
3512
 
/**
3513
 
* Handler for exit calls in phpBB.
3514
 
* This function supports hooks.
3515
 
*
3516
 
* Note: This function is called after the template has been outputted.
3517
 
*/
3518
 
function exit_handler()
3519
 
{
3520
 
        global $phpbb_hook;
3521
 
 
3522
 
        if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__))
3523
 
        {
3524
 
                if ($phpbb_hook->hook_return(__FUNCTION__))
3525
 
                {
3526
 
                        return $phpbb_hook->hook_return_result(__FUNCTION__);
3527
 
                }
3528
 
        }
3529
 
 
3530
 
        exit;
3531
 
}
3532
 
 
3533
 
/**
3534
 
* Handler for init calls in phpBB. This function is called in user::setup();
3535
 
* This function supports hooks.
3536
 
*/
3537
 
function phpbb_user_session_handler()
3538
 
{
3539
 
        global $phpbb_hook;
3540
 
 
3541
 
        if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__))
3542
 
        {
3543
 
                if ($phpbb_hook->hook_return(__FUNCTION__))
3544
 
                {
3545
 
                        return $phpbb_hook->hook_return_result(__FUNCTION__);
3546
 
                }
3547
 
        }
3548
 
 
3549
 
        return;
3550
 
}
3551
 
 
3552
 
?>
 
 
b'\\ No newline at end of file'