~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: 2010-02-15 08:49:58 UTC
  • Revision ID: grantw@unimelb.edu.au-20100215084958-8x5dzd9k4pbcddlz
Split subject/semester management out onto a separate page, and link to SemesterEdit.

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'