phpBB
Statistics
| Revision:

root / branches / phpBB-3_0_0 / phpBB / includes / functions.php

History | View | Annotate | Download (137.6 kB)

1 182 psotfx
<?php
2 7736 acydburn
/**
3 5114 acydburn
*
4 5114 acydburn
* @package phpBB3
5 5114 acydburn
* @version $Id$
6 7736 acydburn
* @copyright (c) 2005 phpBB Group
7 7736 acydburn
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
8 5114 acydburn
*
9 5114 acydburn
*/
10 182 psotfx
11 8129 acydburn
/**
12 8129 acydburn
* @ignore
13 8129 acydburn
*/
14 8129 acydburn
if (!defined('IN_PHPBB'))
15 8129 acydburn
{
16 8129 acydburn
        exit;
17 8129 acydburn
}
18 8129 acydburn
19 5712 acydburn
// Common global functions
20 5709 acydburn
21 5114 acydburn
/**
22 5240 acydburn
* set_var
23 5240 acydburn
*
24 5114 acydburn
* Set variable, used by {@link request_var the request_var function}
25 5240 acydburn
*
26 6312 acydburn
* @access private
27 5114 acydburn
*/
28 5109 acydburn
function set_var(&$result, $var, $type, $multibyte = false)
29 4636 acydburn
{
30 4636 acydburn
        settype($var, $type);
31 4636 acydburn
        $result = $var;
32 4636 acydburn
33 4636 acydburn
        if ($type == 'string')
34 4636 acydburn
        {
35 8967 acydburn
                $result = trim(htmlspecialchars(str_replace(array("\r\n", "\r", "\0"), array("\n", "\n", ''), $result), ENT_COMPAT, 'UTF-8'));
36 5784 acydburn
37 6380 naderman
                if (!empty($result))
38 5109 acydburn
                {
39 6380 naderman
                        // Make sure multibyte characters are wellformed
40 6380 naderman
                        if ($multibyte)
41 6380 naderman
                        {
42 6380 naderman
                                if (!preg_match('/^./u', $result))
43 6380 naderman
                                {
44 6380 naderman
                                        $result = '';
45 6380 naderman
                                }
46 6380 naderman
                        }
47 6380 naderman
                        else
48 6380 naderman
                        {
49 6380 naderman
                                // no multibyte, allow only ASCII (0-127)
50 6380 naderman
                                $result = preg_replace('/[\x80-\xFF]/', '?', $result);
51 6380 naderman
                        }
52 5109 acydburn
                }
53 6380 naderman
54 6380 naderman
                $result = (STRIP) ? stripslashes($result) : $result;
55 4636 acydburn
        }
56 4636 acydburn
}
57 4636 acydburn
58 5114 acydburn
/**
59 5114 acydburn
* request_var
60 5114 acydburn
*
61 5114 acydburn
* Used to get passed variable
62 5114 acydburn
*/
63 6423 grahamje
function request_var($var_name, $default, $multibyte = false, $cookie = false)
64 4521 psotfx
{
65 6423 grahamje
        if (!$cookie && isset($_COOKIE[$var_name]))
66 6423 grahamje
        {
67 6423 grahamje
                if (!isset($_GET[$var_name]) && !isset($_POST[$var_name]))
68 6423 grahamje
                {
69 6423 grahamje
                        return (is_array($default)) ? array() : $default;
70 6423 grahamje
                }
71 6423 grahamje
                $_REQUEST[$var_name] = isset($_POST[$var_name]) ? $_POST[$var_name] : $_GET[$var_name];
72 6423 grahamje
        }
73 6423 grahamje
74 9728 bantu
        $super_global = ($cookie) ? '_COOKIE' : '_REQUEST';
75 9729 bantu
        if (!isset($GLOBALS[$super_global][$var_name]) || is_array($GLOBALS[$super_global][$var_name]) != is_array($default))
76 4521 psotfx
        {
77 5152 acydburn
                return (is_array($default)) ? array() : $default;
78 4521 psotfx
        }
79 5152 acydburn
80 9729 bantu
        $var = $GLOBALS[$super_global][$var_name];
81 5152 acydburn
        if (!is_array($default))
82 5152 acydburn
        {
83 5152 acydburn
                $type = gettype($default);
84 5152 acydburn
        }
85 4521 psotfx
        else
86 4521 psotfx
        {
87 5152 acydburn
                list($key_type, $type) = each($default);
88 5152 acydburn
                $type = gettype($type);
89 5152 acydburn
                $key_type = gettype($key_type);
90 7685 naderman
                if ($type == 'array')
91 7685 naderman
                {
92 7685 naderman
                        reset($default);
93 8223 acydburn
                        $default = current($default);
94 8223 acydburn
                        list($sub_key_type, $sub_type) = each($default);
95 7685 naderman
                        $sub_type = gettype($sub_type);
96 7685 naderman
                        $sub_type = ($sub_type == 'array') ? 'NULL' : $sub_type;
97 7685 naderman
                        $sub_key_type = gettype($sub_key_type);
98 7685 naderman
                }
99 5152 acydburn
        }
100 4521 psotfx
101 5152 acydburn
        if (is_array($var))
102 5152 acydburn
        {
103 5152 acydburn
                $_var = $var;
104 5152 acydburn
                $var = array();
105 5152 acydburn
106 5152 acydburn
                foreach ($_var as $k => $v)
107 4521 psotfx
                {
108 7685 naderman
                        set_var($k, $k, $key_type);
109 7685 naderman
                        if ($type == 'array' && is_array($v))
110 4521 psotfx
                        {
111 5152 acydburn
                                foreach ($v as $_k => $_v)
112 4521 psotfx
                                {
113 7685 naderman
                                        if (is_array($_v))
114 7685 naderman
                                        {
115 7685 naderman
                                                $_v = null;
116 7685 naderman
                                        }
117 10571 git-gate
                                        set_var($_k, $_k, $sub_key_type, $multibyte);
118 7685 naderman
                                        set_var($var[$k][$_k], $_v, $sub_type, $multibyte);
119 4521 psotfx
                                }
120 4521 psotfx
                        }
121 5152 acydburn
                        else
122 5152 acydburn
                        {
123 7685 naderman
                                if ($type == 'array' || is_array($v))
124 7685 naderman
                                {
125 7685 naderman
                                        $v = null;
126 7685 naderman
                                }
127 5152 acydburn
                                set_var($var[$k], $v, $type, $multibyte);
128 5152 acydburn
                        }
129 4521 psotfx
                }
130 4521 psotfx
        }
131 5152 acydburn
        else
132 5152 acydburn
        {
133 5152 acydburn
                set_var($var, $var, $type, $multibyte);
134 5152 acydburn
        }
135 6015 acydburn
136 5152 acydburn
        return $var;
137 4521 psotfx
}
138 4521 psotfx
139 5114 acydburn
/**
140 5114 acydburn
* Set config value. Creates missing config entry.
141 5114 acydburn
*/
142 4994 acydburn
function set_config($config_name, $config_value, $is_dynamic = false)
143 3312 ludovic_arnaud
{
144 3312 ludovic_arnaud
        global $db, $cache, $config;
145 3316 ludovic_arnaud
146 4365 ludovic_arnaud
        $sql = 'UPDATE ' . CONFIG_TABLE . "
147 4365 ludovic_arnaud
                SET config_value = '" . $db->sql_escape($config_value) . "'
148 4883 acydburn
                WHERE config_name = '" . $db->sql_escape($config_name) . "'";
149 4365 ludovic_arnaud
        $db->sql_query($sql);
150 3316 ludovic_arnaud
151 4365 ludovic_arnaud
        if (!$db->sql_affectedrows() && !isset($config[$config_name]))
152 4365 ludovic_arnaud
        {
153 4994 acydburn
                $sql = 'INSERT INTO ' . CONFIG_TABLE . ' ' . $db->sql_build_array('INSERT', array(
154 4994 acydburn
                        'config_name'        => $config_name,
155 4994 acydburn
                        'config_value'        => $config_value,
156 4994 acydburn
                        'is_dynamic'        => ($is_dynamic) ? 1 : 0));
157 3316 ludovic_arnaud
                $db->sql_query($sql);
158 3316 ludovic_arnaud
        }
159 3316 ludovic_arnaud
160 3312 ludovic_arnaud
        $config[$config_name] = $config_value;
161 3312 ludovic_arnaud
162 3359 ludovic_arnaud
        if (!$is_dynamic)
163 3359 ludovic_arnaud
        {
164 4365 ludovic_arnaud
                $cache->destroy('config');
165 3359 ludovic_arnaud
        }
166 3312 ludovic_arnaud
}
167 3312 ludovic_arnaud
168 5114 acydburn
/**
169 9398 acydburn
* Set dynamic config value with arithmetic operation.
170 9398 acydburn
*/
171 9398 acydburn
function set_config_count($config_name, $increment, $is_dynamic = false)
172 9398 acydburn
{
173 9398 acydburn
        global $db, $cache;
174 9398 acydburn
175 9398 acydburn
        switch ($db->sql_layer)
176 9398 acydburn
        {
177 9398 acydburn
                case 'firebird':
178 11147 git-gate
                        // Precision must be from 1 to 18
179 11147 git-gate
                        $sql_update = 'CAST(CAST(config_value as DECIMAL(18, 0)) + ' . (int) $increment . ' as VARCHAR(255))';
180 9398 acydburn
                break;
181 9398 acydburn
182 11044 git-gate
                case 'postgres':
183 11044 git-gate
                        // Need to cast to text first for PostgreSQL 7.x
184 11044 git-gate
                        $sql_update = 'CAST(CAST(config_value::text as DECIMAL(255, 0)) + ' . (int) $increment . ' as VARCHAR(255))';
185 11044 git-gate
                break;
186 11044 git-gate
187 9398 acydburn
                // MySQL, SQlite, mssql, mssql_odbc, oracle
188 9398 acydburn
                default:
189 9398 acydburn
                        $sql_update = 'config_value + ' . (int) $increment;
190 9398 acydburn
                break;
191 9398 acydburn
        }
192 9398 acydburn
193 9398 acydburn
        $db->sql_query('UPDATE ' . CONFIG_TABLE . ' SET config_value = ' . $sql_update . " WHERE config_name = '" . $db->sql_escape($config_name) . "'");
194 9398 acydburn
195 9398 acydburn
        if (!$is_dynamic)
196 9398 acydburn
        {
197 9398 acydburn
                $cache->destroy('config');
198 9398 acydburn
        }
199 9398 acydburn
}
200 9398 acydburn
201 9398 acydburn
/**
202 5114 acydburn
* Generates an alphanumeric random string of given length
203 10733 git-gate
*
204 10733 git-gate
* @return string
205 5114 acydburn
*/
206 5813 grahamje
function gen_rand_string($num_chars = 8)
207 4785 psotfx
{
208 10733 git-gate
        // [a, z] + [0, 9] = 36
209 10740 git-gate
        return substr(strtoupper(base_convert(unique_id(), 16, 36)), 0, $num_chars);
210 10733 git-gate
}
211 10733 git-gate
212 10733 git-gate
/**
213 10733 git-gate
* Generates a user-friendly alphanumeric random string of given length
214 10733 git-gate
* We remove 0 and O so users cannot confuse those in passwords etc.
215 10733 git-gate
*
216 10733 git-gate
* @return string
217 10733 git-gate
*/
218 10733 git-gate
function gen_rand_string_friendly($num_chars = 8)
219 10733 git-gate
{
220 5819 grahamje
        $rand_str = unique_id();
221 10733 git-gate
222 10733 git-gate
        // Remove Z and Y from the base_convert(), replace 0 with Z and O with Y
223 10733 git-gate
        // [a, z] + [0, 9] - {z, y} = [a, z] + [0, 9] - {0, o} = 34
224 10480 bantu
        $rand_str = str_replace(array('0', 'O'), array('Z', 'Y'), strtoupper(base_convert($rand_str, 16, 34)));
225 4785 psotfx
226 5813 grahamje
        return substr($rand_str, 0, $num_chars);
227 4785 psotfx
}
228 4785 psotfx
229 5114 acydburn
/**
230 5135 acydburn
* Return unique id
231 6595 acydburn
* @param string $extra additional entropy
232 5135 acydburn
*/
233 5813 grahamje
function unique_id($extra = 'c')
234 5135 acydburn
{
235 6578 davidmj
        static $dss_seeded = false;
236 5911 davidmj
        global $config;
237 5813 grahamje
238 5813 grahamje
        $val = $config['rand_seed'] . microtime();
239 5813 grahamje
        $val = md5($val);
240 5813 grahamje
        $config['rand_seed'] = md5($config['rand_seed'] . $val . $extra);
241 5858 acydburn
242 6542 grahamje
        if ($dss_seeded !== true && ($config['rand_seed_last_update'] < time() - rand(1,10)))
243 5813 grahamje
        {
244 11065 git-gate
                set_config('rand_seed_last_update', time(), true);
245 6117 acydburn
                set_config('rand_seed', $config['rand_seed'], true);
246 5813 grahamje
                $dss_seeded = true;
247 5813 grahamje
        }
248 5813 grahamje
249 5813 grahamje
        return substr($val, 4, 16);
250 5135 acydburn
}
251 5135 acydburn
252 5135 acydburn
/**
253 11175 git-gate
* Wrapper for mt_rand() which allows swapping $min and $max parameters.
254 11175 git-gate
*
255 11175 git-gate
* PHP does not allow us to swap the order of the arguments for mt_rand() anymore.
256 11175 git-gate
* (since PHP 5.3.4, see http://bugs.php.net/46587)
257 11175 git-gate
*
258 11175 git-gate
* @param int $min                Lowest value to be returned
259 11175 git-gate
* @param int $max                Highest value to be returned
260 11175 git-gate
*
261 11175 git-gate
* @return int                        Random integer between $min and $max (or $max and $min)
262 11175 git-gate
*/
263 11175 git-gate
function phpbb_mt_rand($min, $max)
264 11175 git-gate
{
265 11175 git-gate
        return ($min > $max) ? mt_rand($max, $min) : mt_rand($min, $max);
266 11175 git-gate
}
267 11175 git-gate
268 11175 git-gate
/**
269 11309 git-gate
* Wrapper for getdate() which returns the equivalent array for UTC timestamps.
270 11309 git-gate
*
271 11309 git-gate
* @param int $time                Unix timestamp (optional)
272 11309 git-gate
*
273 11309 git-gate
* @return array                        Returns an associative array of information related to the timestamp.
274 11309 git-gate
*                                                See http://www.php.net/manual/en/function.getdate.php
275 11309 git-gate
*/
276 11309 git-gate
function phpbb_gmgetdate($time = false)
277 11309 git-gate
{
278 11309 git-gate
        if ($time === false)
279 11309 git-gate
        {
280 11309 git-gate
                $time = time();
281 11309 git-gate
        }
282 11309 git-gate
283 11309 git-gate
        // getdate() interprets timestamps in local time.
284 11309 git-gate
        // What follows uses the fact that getdate() and
285 11309 git-gate
        // date('Z') balance each other out.
286 11309 git-gate
        return getdate($time - date('Z'));
287 11309 git-gate
}
288 11309 git-gate
289 11309 git-gate
/**
290 8389 acydburn
* Return formatted string for filesizes
291 9748 bantu
*
292 9748 bantu
* @param int        $value                        filesize in bytes
293 9748 bantu
* @param bool        $string_only        true if language string should be returned
294 9748 bantu
* @param array        $allowed_units        only allow these units (data array indexes)
295 9748 bantu
*
296 9748 bantu
* @return mixed                                        data array if $string_only is false
297 9748 bantu
* @author bantu
298 8389 acydburn
*/
299 9748 bantu
function get_formatted_filesize($value, $string_only = true, $allowed_units = false)
300 8389 acydburn
{
301 8389 acydburn
        global $user;
302 8389 acydburn
303 9748 bantu
        $available_units = array(
304 9748 bantu
                'gb' => array(
305 9748 bantu
                        'min'                 => 1073741824, // pow(2, 30)
306 9748 bantu
                        'index'                => 3,
307 9748 bantu
                        'si_unit'        => 'GB',
308 9748 bantu
                        'iec_unit'        => 'GIB',
309 9748 bantu
                ),
310 9748 bantu
                'mb' => array(
311 9748 bantu
                        'min'                => 1048576, // pow(2, 20)
312 9748 bantu
                        'index'                => 2,
313 9748 bantu
                        'si_unit'        => 'MB',
314 9748 bantu
                        'iec_unit'        => 'MIB',
315 9748 bantu
                ),
316 9748 bantu
                'kb' => array(
317 9748 bantu
                        'min'                => 1024, // pow(2, 10)
318 9748 bantu
                        'index'                => 1,
319 9748 bantu
                        'si_unit'        => 'KB',
320 9748 bantu
                        'iec_unit'        => 'KIB',
321 9748 bantu
                ),
322 9748 bantu
                'b' => array(
323 9748 bantu
                        'min'                => 0,
324 9748 bantu
                        'index'                => 0,
325 9748 bantu
                        'si_unit'        => 'BYTES', // Language index
326 9748 bantu
                        'iec_unit'        => 'BYTES',  // Language index
327 9748 bantu
                ),
328 9748 bantu
        );
329 9748 bantu
330 9748 bantu
        foreach ($available_units as $si_identifier => $unit_info)
331 9474 acydburn
        {
332 9748 bantu
                if (!empty($allowed_units) && $si_identifier != 'b' && !in_array($si_identifier, $allowed_units))
333 9748 bantu
                {
334 9748 bantu
                        continue;
335 9748 bantu
                }
336 9748 bantu
337 9748 bantu
                if ($value >= $unit_info['min'])
338 9748 bantu
                {
339 9748 bantu
                        $unit_info['si_identifier'] = $si_identifier;
340 9748 bantu
341 9748 bantu
                        break;
342 9748 bantu
                }
343 9474 acydburn
        }
344 9748 bantu
        unset($available_units);
345 9474 acydburn
346 9748 bantu
        for ($i = 0; $i < $unit_info['index']; $i++)
347 8389 acydburn
        {
348 9748 bantu
                $value /= 1024;
349 8389 acydburn
        }
350 9748 bantu
        $value = round($value, 2);
351 8389 acydburn
352 9748 bantu
        // Lookup units in language dictionary
353 9748 bantu
        $unit_info['si_unit'] = (isset($user->lang[$unit_info['si_unit']])) ? $user->lang[$unit_info['si_unit']] : $unit_info['si_unit'];
354 9748 bantu
        $unit_info['iec_unit'] = (isset($user->lang[$unit_info['iec_unit']])) ? $user->lang[$unit_info['iec_unit']] : $unit_info['iec_unit'];
355 9748 bantu
356 9748 bantu
        // Default to IEC
357 9748 bantu
        $unit_info['unit'] = $unit_info['iec_unit'];
358 9748 bantu
359 9748 bantu
        if (!$string_only)
360 8389 acydburn
        {
361 9748 bantu
                $unit_info['value'] = $value;
362 9748 bantu
363 9748 bantu
                return $unit_info;
364 8389 acydburn
        }
365 8389 acydburn
366 9748 bantu
        return $value  . ' ' . $unit_info['unit'];
367 8389 acydburn
}
368 8389 acydburn
369 8389 acydburn
/**
370 7076 naderman
* Determine whether we are approaching the maximum execution time. Should be called once
371 7076 naderman
* at the beginning of the script in which it's used.
372 7076 naderman
* @return        bool        Either true if the maximum execution time is nearly reached, or false
373 7076 naderman
*                                        if some time is still left.
374 7076 naderman
*/
375 7119 naderman
function still_on_time($extra_time = 15)
376 7076 naderman
{
377 7076 naderman
        static $max_execution_time, $start_time;
378 7076 naderman
379 7076 naderman
        $time = explode(' ', microtime());
380 7076 naderman
        $current_time = $time[0] + $time[1];
381 7076 naderman
382 7076 naderman
        if (empty($max_execution_time))
383 7076 naderman
        {
384 8116 acydburn
                $max_execution_time = (function_exists('ini_get')) ? (int) @ini_get('max_execution_time') : (int) @get_cfg_var('max_execution_time');
385 7076 naderman
386 7076 naderman
                // If zero, then set to something higher to not let the user catch the ten seconds barrier.
387 7076 naderman
                if ($max_execution_time === 0)
388 7076 naderman
                {
389 7119 naderman
                        $max_execution_time = 50 + $extra_time;
390 7076 naderman
                }
391 7076 naderman
392 7119 naderman
                $max_execution_time = min(max(10, ($max_execution_time - $extra_time)), 50);
393 7076 naderman
394 7076 naderman
                // For debugging purposes
395 7076 naderman
                // $max_execution_time = 10;
396 7076 naderman
397 7076 naderman
                global $starttime;
398 7076 naderman
                $start_time = (empty($starttime)) ? $current_time : $starttime;
399 7076 naderman
        }
400 7076 naderman
401 7076 naderman
        return (ceil($current_time - $start_time) < $max_execution_time) ? true : false;
402 7076 naderman
}
403 7076 naderman
404 8146 acydburn
/**
405 8139 acydburn
*
406 8651 acydburn
* @version Version 0.1 / slightly modified for phpBB 3.0.x (using $H$ as hash type identifier)
407 8139 acydburn
*
408 8139 acydburn
* Portable PHP password hashing framework.
409 8139 acydburn
*
410 8139 acydburn
* Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in
411 8139 acydburn
* the public domain.
412 8139 acydburn
*
413 8139 acydburn
* There's absolutely no warranty.
414 8139 acydburn
*
415 8139 acydburn
* The homepage URL for this framework is:
416 8139 acydburn
*
417 8139 acydburn
*        http://www.openwall.com/phpass/
418 8139 acydburn
*
419 8139 acydburn
* Please be sure to update the Version line if you edit this file in any way.
420 8139 acydburn
* It is suggested that you leave the main version number intact, but indicate
421 8139 acydburn
* your project name (after the slash) and add your own revision information.
422 8139 acydburn
*
423 8139 acydburn
* Please do not change the "private" password hashing method implemented in
424 8139 acydburn
* here, thereby making your hashes incompatible.  However, if you must, please
425 8139 acydburn
* change the hash type identifier (the "$P$") to something different.
426 8139 acydburn
*
427 8139 acydburn
* Obviously, since this code is in the public domain, the above are not
428 8139 acydburn
* requirements (there can be none), but merely suggestions.
429 8139 acydburn
*
430 8139 acydburn
*
431 8139 acydburn
* Hash the password
432 5114 acydburn
*/
433 8139 acydburn
function phpbb_hash($password)
434 3530 psotfx
{
435 8139 acydburn
        $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
436 3530 psotfx
437 8139 acydburn
        $random_state = unique_id();
438 8139 acydburn
        $random = '';
439 8139 acydburn
        $count = 6;
440 3530 psotfx
441 8241 acydburn
        if (($fh = @fopen('/dev/urandom', 'rb')))
442 6477 acydburn
        {
443 8241 acydburn
                $random = fread($fh, $count);
444 8241 acydburn
                fclose($fh);
445 6477 acydburn
        }
446 6477 acydburn
447 8241 acydburn
        if (strlen($random) < $count)
448 8241 acydburn
        {
449 8241 acydburn
                $random = '';
450 8241 acydburn
451 8241 acydburn
                for ($i = 0; $i < $count; $i += 16)
452 8241 acydburn
                {
453 8241 acydburn
                        $random_state = md5(unique_id() . $random_state);
454 8241 acydburn
                        $random .= pack('H*', md5($random_state));
455 8241 acydburn
                }
456 8241 acydburn
                $random = substr($random, 0, $count);
457 8241 acydburn
        }
458 8348 acydburn
459 8139 acydburn
        $hash = _hash_crypt_private($password, _hash_gensalt_private($random, $itoa64), $itoa64);
460 3530 psotfx
461 8139 acydburn
        if (strlen($hash) == 34)
462 3530 psotfx
        {
463 8139 acydburn
                return $hash;
464 3530 psotfx
        }
465 3530 psotfx
466 8139 acydburn
        return md5($password);
467 8139 acydburn
}
468 8139 acydburn
469 8139 acydburn
/**
470 8139 acydburn
* Check for correct password
471 8691 acydburn
*
472 8691 acydburn
* @param string $password The password in plain text
473 8691 acydburn
* @param string $hash The stored password hash
474 8691 acydburn
*
475 8691 acydburn
* @return bool Returns true if the password is correct, false if not.
476 8139 acydburn
*/
477 8139 acydburn
function phpbb_check_hash($password, $hash)
478 8139 acydburn
{
479 8139 acydburn
        $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
480 8139 acydburn
        if (strlen($hash) == 34)
481 3530 psotfx
        {
482 8139 acydburn
                return (_hash_crypt_private($password, $hash, $itoa64) === $hash) ? true : false;
483 3530 psotfx
        }
484 3530 psotfx
485 8139 acydburn
        return (md5($password) === $hash) ? true : false;
486 3530 psotfx
}
487 3530 psotfx
488 5114 acydburn
/**
489 8139 acydburn
* Generate salt for hash generation
490 5114 acydburn
*/
491 8139 acydburn
function _hash_gensalt_private($input, &$itoa64, $iteration_count_log2 = 6)
492 2665 psotfx
{
493 8139 acydburn
        if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31)
494 4643 psotfx
        {
495 8139 acydburn
                $iteration_count_log2 = 8;
496 4643 psotfx
        }
497 4643 psotfx
498 8139 acydburn
        $output = '$H$';
499 8139 acydburn
        $output .= $itoa64[min($iteration_count_log2 + ((PHP_VERSION >= 5) ? 5 : 3), 30)];
500 8139 acydburn
        $output .= _hash_encode64($input, 6, $itoa64);
501 2665 psotfx
502 8139 acydburn
        return $output;
503 8139 acydburn
}
504 4870 acydburn
505 8139 acydburn
/**
506 8139 acydburn
* Encode hash
507 8139 acydburn
*/
508 8139 acydburn
function _hash_encode64($input, $count, &$itoa64)
509 8139 acydburn
{
510 8139 acydburn
        $output = '';
511 8139 acydburn
        $i = 0;
512 4957 acydburn
513 8139 acydburn
        do
514 2665 psotfx
        {
515 8139 acydburn
                $value = ord($input[$i++]);
516 8139 acydburn
                $output .= $itoa64[$value & 0x3f];
517 8139 acydburn
518 8139 acydburn
                if ($i < $count)
519 5116 acydburn
                {
520 8139 acydburn
                        $value |= ord($input[$i]) << 8;
521 5116 acydburn
                }
522 5116 acydburn
523 8139 acydburn
                $output .= $itoa64[($value >> 6) & 0x3f];
524 5116 acydburn
525 8139 acydburn
                if ($i++ >= $count)
526 1512 psotfx
                {
527 8139 acydburn
                        break;
528 3064 psotfx
                }
529 3064 psotfx
530 8139 acydburn
                if ($i < $count)
531 3064 psotfx
                {
532 8139 acydburn
                        $value |= ord($input[$i]) << 16;
533 3064 psotfx
                }
534 4920 acydburn
535 8139 acydburn
                $output .= $itoa64[($value >> 12) & 0x3f];
536 8348 acydburn
537 8139 acydburn
                if ($i++ >= $count)
538 4920 acydburn
                {
539 8139 acydburn
                        break;
540 4920 acydburn
                }
541 4920 acydburn
542 8139 acydburn
                $output .= $itoa64[($value >> 18) & 0x3f];
543 8139 acydburn
        }
544 8139 acydburn
        while ($i < $count);
545 3064 psotfx
546 8139 acydburn
        return $output;
547 8139 acydburn
}
548 4970 psotfx
549 8139 acydburn
/**
550 8139 acydburn
* The crypt function/replacement
551 8139 acydburn
*/
552 8139 acydburn
function _hash_crypt_private($password, $setting, &$itoa64)
553 8139 acydburn
{
554 8139 acydburn
        $output = '*';
555 4870 acydburn
556 8139 acydburn
        // Check for correct hash
557 11074 git-gate
        if (substr($setting, 0, 3) != '$H$' && substr($setting, 0, 3) != '$P$')
558 8139 acydburn
        {
559 8139 acydburn
                return $output;
560 8139 acydburn
        }
561 8139 acydburn
562 8139 acydburn
        $count_log2 = strpos($itoa64, $setting[3]);
563 8139 acydburn
564 8139 acydburn
        if ($count_log2 < 7 || $count_log2 > 30)
565 8139 acydburn
        {
566 8139 acydburn
                return $output;
567 8139 acydburn
        }
568 8139 acydburn
569 8139 acydburn
        $count = 1 << $count_log2;
570 8139 acydburn
        $salt = substr($setting, 4, 8);
571 8139 acydburn
572 8139 acydburn
        if (strlen($salt) != 8)
573 8139 acydburn
        {
574 8139 acydburn
                return $output;
575 8139 acydburn
        }
576 8139 acydburn
577 8139 acydburn
        /**
578 8139 acydburn
        * We're kind of forced to use MD5 here since it's the only
579 8139 acydburn
        * cryptographic primitive available in all versions of PHP
580 8139 acydburn
        * currently in use.  To implement our own low-level crypto
581 8139 acydburn
        * in PHP would result in much worse performance and
582 8139 acydburn
        * consequently in lower iteration counts and hashes that are
583 8139 acydburn
        * quicker to crack (by non-PHP code).
584 8139 acydburn
        */
585 8139 acydburn
        if (PHP_VERSION >= 5)
586 8139 acydburn
        {
587 8139 acydburn
                $hash = md5($salt . $password, true);
588 8139 acydburn
                do
589 3064 psotfx
                {
590 8139 acydburn
                        $hash = md5($hash . $password, true);
591 3064 psotfx
                }
592 8139 acydburn
                while (--$count);
593 182 psotfx
        }
594 8139 acydburn
        else
595 8139 acydburn
        {
596 8139 acydburn
                $hash = pack('H*', md5($salt . $password));
597 8139 acydburn
                do
598 8139 acydburn
                {
599 8139 acydburn
                        $hash = pack('H*', md5($hash . $password));
600 8139 acydburn
                }
601 8139 acydburn
                while (--$count);
602 8139 acydburn
        }
603 2950 ludovic_arnaud
604 8139 acydburn
        $output = substr($setting, 0, 12);
605 8139 acydburn
        $output .= _hash_encode64($hash, 16, $itoa64);
606 2448 psotfx
607 8139 acydburn
        return $output;
608 182 psotfx
}
609 182 psotfx
610 8763 acydburn
/**
611 10071 bantu
* Hashes an email address to a big integer
612 10071 bantu
*
613 10071 bantu
* @param string $email                Email address
614 10071 bantu
*
615 10499 bantu
* @return string                        Unsigned Big Integer
616 10060 nickvergessen
*/
617 10060 nickvergessen
function phpbb_email_hash($email)
618 10060 nickvergessen
{
619 10499 bantu
        return sprintf('%u', crc32(strtolower($email))) . strlen($email);
620 10060 nickvergessen
}
621 10060 nickvergessen
622 10060 nickvergessen
/**
623 11315 git-gate
* Wrapper for version_compare() that allows using uppercase A and B
624 11315 git-gate
* for alpha and beta releases.
625 11315 git-gate
*
626 11315 git-gate
* See http://www.php.net/manual/en/function.version-compare.php
627 11315 git-gate
*
628 11315 git-gate
* @param string $version1                First version number
629 11315 git-gate
* @param string $version2                Second version number
630 11315 git-gate
* @param string $operator                Comparison operator (optional)
631 11315 git-gate
*
632 11334 git-gate
* @return mixed                                        Boolean (true, false) if comparison operator is specified.
633 11334 git-gate
*                                                                Integer (-1, 0, 1) otherwise.
634 11315 git-gate
*/
635 11315 git-gate
function phpbb_version_compare($version1, $version2, $operator = null)
636 11315 git-gate
{
637 11315 git-gate
        $version1 = strtolower($version1);
638 11315 git-gate
        $version2 = strtolower($version2);
639 11315 git-gate
640 11315 git-gate
        if (is_null($operator))
641 11315 git-gate
        {
642 11315 git-gate
                return version_compare($version1, $version2);
643 11315 git-gate
        }
644 11315 git-gate
        else
645 11315 git-gate
        {
646 11315 git-gate
                return version_compare($version1, $version2, $operator);
647 11315 git-gate
        }
648 11315 git-gate
}
649 11315 git-gate
650 11315 git-gate
/**
651 8780 acydburn
* Global function for chmodding directories and files for internal use
652 9394 acydburn
*
653 8780 acydburn
* This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions.
654 9394 acydburn
* The function determines owner and group from common.php file and sets the same to the provided file.
655 8780 acydburn
* The function uses bit fields to build the permissions.
656 8780 acydburn
* The function sets the appropiate execute bit on directories.
657 8763 acydburn
*
658 8780 acydburn
* Supported constants representing bit fields are:
659 8763 acydburn
*
660 8780 acydburn
* CHMOD_ALL - all permissions (7)
661 8780 acydburn
* CHMOD_READ - read permission (4)
662 8780 acydburn
* CHMOD_WRITE - write permission (2)
663 8780 acydburn
* CHMOD_EXECUTE - execute permission (1)
664 8763 acydburn
*
665 8780 acydburn
* NOTE: The function uses POSIX extension and fileowner()/filegroup() functions. If any of them is disabled, this function tries to build proper permissions, by calling is_readable() and is_writable() functions.
666 8763 acydburn
*
667 9394 acydburn
* @param string        $filename        The file/directory to be chmodded
668 9394 acydburn
* @param int        $perms                Permissions to set
669 8763 acydburn
*
670 9394 acydburn
* @return bool        true on success, otherwise false
671 8780 acydburn
* @author faw, phpBB Group
672 8763 acydburn
*/
673 8780 acydburn
function phpbb_chmod($filename, $perms = CHMOD_READ)
674 8763 acydburn
{
675 9394 acydburn
        static $_chmod_info;
676 9394 acydburn
677 8780 acydburn
        // Return if the file no longer exists.
678 8780 acydburn
        if (!file_exists($filename))
679 8763 acydburn
        {
680 8780 acydburn
                return false;
681 8780 acydburn
        }
682 8763 acydburn
683 9394 acydburn
        // Determine some common vars
684 9394 acydburn
        if (empty($_chmod_info))
685 8780 acydburn
        {
686 9394 acydburn
                if (!function_exists('fileowner') || !function_exists('filegroup'))
687 9394 acydburn
                {
688 9394 acydburn
                        // No need to further determine owner/group - it is unknown
689 9394 acydburn
                        $_chmod_info['process'] = false;
690 9394 acydburn
                }
691 9394 acydburn
                else
692 9394 acydburn
                {
693 9394 acydburn
                        global $phpbb_root_path, $phpEx;
694 8763 acydburn
695 9394 acydburn
                        // Determine owner/group of common.php file and the filename we want to change here
696 9519 acydburn
                        $common_php_owner = @fileowner($phpbb_root_path . 'common.' . $phpEx);
697 9519 acydburn
                        $common_php_group = @filegroup($phpbb_root_path . 'common.' . $phpEx);
698 8763 acydburn
699 9394 acydburn
                        // And the owner and the groups PHP is running under.
700 9394 acydburn
                        $php_uid = (function_exists('posix_getuid')) ? @posix_getuid() : false;
701 9394 acydburn
                        $php_gids = (function_exists('posix_getgroups')) ? @posix_getgroups() : false;
702 8763 acydburn
703 9394 acydburn
                        // If we are unable to get owner/group, then do not try to set them by guessing
704 9394 acydburn
                        if (!$php_uid || empty($php_gids) || !$common_php_owner || !$common_php_group)
705 8780 acydburn
                        {
706 9394 acydburn
                                $_chmod_info['process'] = false;
707 8780 acydburn
                        }
708 9394 acydburn
                        else
709 8780 acydburn
                        {
710 9394 acydburn
                                $_chmod_info = array(
711 9394 acydburn
                                        'process'                => true,
712 9394 acydburn
                                        'common_owner'        => $common_php_owner,
713 9394 acydburn
                                        'common_group'        => $common_php_group,
714 9394 acydburn
                                        'php_uid'                => $php_uid,
715 9394 acydburn
                                        'php_gids'                => $php_gids,
716 9394 acydburn
                                );
717 8780 acydburn
                        }
718 8780 acydburn
                }
719 8763 acydburn
        }
720 8763 acydburn
721 9394 acydburn
        if ($_chmod_info['process'])
722 9394 acydburn
        {
723 9519 acydburn
                $file_uid = @fileowner($filename);
724 9519 acydburn
                $file_gid = @filegroup($filename);
725 9410 acydburn
726 9394 acydburn
                // Change owner
727 9394 acydburn
                if (@chown($filename, $_chmod_info['common_owner']))
728 9394 acydburn
                {
729 9394 acydburn
                        clearstatcache();
730 9519 acydburn
                        $file_uid = @fileowner($filename);
731 9394 acydburn
                }
732 8780 acydburn
733 9394 acydburn
                // Change group
734 9394 acydburn
                if (@chgrp($filename, $_chmod_info['common_group']))
735 9394 acydburn
                {
736 9394 acydburn
                        clearstatcache();
737 9519 acydburn
                        $file_gid = @filegroup($filename);
738 9394 acydburn
                }
739 9394 acydburn
740 9394 acydburn
                // If the file_uid/gid now match the one from common.php we can process further, else we are not able to change something
741 9394 acydburn
                if ($file_uid != $_chmod_info['common_owner'] || $file_gid != $_chmod_info['common_group'])
742 9394 acydburn
                {
743 9394 acydburn
                        $_chmod_info['process'] = false;
744 9394 acydburn
                }
745 8763 acydburn
        }
746 9394 acydburn
747 9394 acydburn
        // Still able to process?
748 9394 acydburn
        if ($_chmod_info['process'])
749 8780 acydburn
        {
750 9394 acydburn
                if ($file_uid == $_chmod_info['php_uid'])
751 9394 acydburn
                {
752 9394 acydburn
                        $php = 'owner';
753 9394 acydburn
                }
754 9394 acydburn
                else if (in_array($file_gid, $_chmod_info['php_gids']))
755 9394 acydburn
                {
756 9394 acydburn
                        $php = 'group';
757 9394 acydburn
                }
758 9394 acydburn
                else
759 9394 acydburn
                {
760 9394 acydburn
                        // Since we are setting the everyone bit anyway, no need to do expensive operations
761 9394 acydburn
                        $_chmod_info['process'] = false;
762 9394 acydburn
                }
763 8780 acydburn
        }
764 9394 acydburn
765 9394 acydburn
        // We are not able to determine or change something
766 9394 acydburn
        if (!$_chmod_info['process'])
767 8780 acydburn
        {
768 8780 acydburn
                $php = 'other';
769 8780 acydburn
        }
770 8763 acydburn
771 8780 acydburn
        // Owner always has read/write permission
772 8780 acydburn
        $owner = CHMOD_READ | CHMOD_WRITE;
773 8763 acydburn
        if (is_dir($filename))
774 8763 acydburn
        {
775 8780 acydburn
                $owner |= CHMOD_EXECUTE;
776 8780 acydburn
777 8780 acydburn
                // Only add execute bit to the permission if the dir needs to be readable
778 8780 acydburn
                if ($perms & CHMOD_READ)
779 8780 acydburn
                {
780 8780 acydburn
                        $perms |= CHMOD_EXECUTE;
781 8780 acydburn
                }
782 8763 acydburn
        }
783 8763 acydburn
784 8780 acydburn
        switch ($php)
785 8763 acydburn
        {
786 8780 acydburn
                case 'owner':
787 8780 acydburn
                        $result = @chmod($filename, ($owner << 6) + (0 << 3) + (0 << 0));
788 8763 acydburn
789 9146 toonarmy
                        clearstatcache();
790 9144 toonarmy
791 10757 git-gate
                        if (is_readable($filename) && phpbb_is_writable($filename))
792 8763 acydburn
                        {
793 8780 acydburn
                                break;
794 8763 acydburn
                        }
795 8763 acydburn
796 8780 acydburn
                case 'group':
797 8780 acydburn
                        $result = @chmod($filename, ($owner << 6) + ($perms << 3) + (0 << 0));
798 8763 acydburn
799 9146 toonarmy
                        clearstatcache();
800 9144 toonarmy
801 10757 git-gate
                        if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || phpbb_is_writable($filename)))
802 8763 acydburn
                        {
803 8780 acydburn
                                break;
804 8763 acydburn
                        }
805 8780 acydburn
806 8780 acydburn
                case 'other':
807 8780 acydburn
                        $result = @chmod($filename, ($owner << 6) + ($perms << 3) + ($perms << 0));
808 8780 acydburn
809 9146 toonarmy
                        clearstatcache();
810 9144 toonarmy
811 10757 git-gate
                        if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || phpbb_is_writable($filename)))
812 8780 acydburn
                        {
813 8780 acydburn
                                break;
814 8780 acydburn
                        }
815 8780 acydburn
816 8780 acydburn
                default:
817 8780 acydburn
                        return false;
818 8780 acydburn
                break;
819 8763 acydburn
        }
820 8763 acydburn
821 8763 acydburn
        return $result;
822 8763 acydburn
}
823 8763 acydburn
824 9528 toonarmy
/**
825 9554 acydburn
* Test if a file/directory is writable
826 9554 acydburn
*
827 9554 acydburn
* This function calls the native is_writable() when not running under
828 9554 acydburn
* Windows and it is not disabled.
829 9554 acydburn
*
830 9554 acydburn
* @param string $file Path to perform write test on
831 9554 acydburn
* @return bool True when the path is writable, otherwise false.
832 9554 acydburn
*/
833 9528 toonarmy
function phpbb_is_writable($file)
834 9528 toonarmy
{
835 9554 acydburn
        if (strtolower(substr(PHP_OS, 0, 3)) === 'win' || !function_exists('is_writable'))
836 9528 toonarmy
        {
837 9528 toonarmy
                if (file_exists($file))
838 9528 toonarmy
                {
839 9528 toonarmy
                        // Canonicalise path to absolute path
840 9528 toonarmy
                        $file = phpbb_realpath($file);
841 9528 toonarmy
842 9528 toonarmy
                        if (is_dir($file))
843 9528 toonarmy
                        {
844 9528 toonarmy
                                // Test directory by creating a file inside the directory
845 9528 toonarmy
                                $result = @tempnam($file, 'i_w');
846 9528 toonarmy
847 9528 toonarmy
                                if (is_string($result) && file_exists($result))
848 9528 toonarmy
                                {
849 9528 toonarmy
                                        unlink($result);
850 9528 toonarmy
851 9528 toonarmy
                                        // Ensure the file is actually in the directory (returned realpathed)
852 9528 toonarmy
                                        return (strpos($result, $file) === 0) ? true : false;
853 9528 toonarmy
                                }
854 9528 toonarmy
                        }
855 9528 toonarmy
                        else
856 9528 toonarmy
                        {
857 9528 toonarmy
                                $handle = @fopen($file, 'r+');
858 9528 toonarmy
859 9528 toonarmy
                                if (is_resource($handle))
860 9528 toonarmy
                                {
861 9528 toonarmy
                                        fclose($handle);
862 9528 toonarmy
                                        return true;
863 9528 toonarmy
                                }
864 9528 toonarmy
                        }
865 9528 toonarmy
                }
866 9528 toonarmy
                else
867 9528 toonarmy
                {
868 9528 toonarmy
                        // file does not exist test if we can write to the directory
869 9528 toonarmy
                        $dir = dirname($file);
870 9528 toonarmy
871 9528 toonarmy
                        if (file_exists($dir) && is_dir($dir) && phpbb_is_writable($dir))
872 9528 toonarmy
                        {
873 9528 toonarmy
                                return true;
874 9528 toonarmy
                        }
875 9528 toonarmy
                }
876 9554 acydburn
877 9528 toonarmy
                return false;
878 9528 toonarmy
        }
879 9528 toonarmy
        else
880 9528 toonarmy
        {
881 9528 toonarmy
                return is_writable($file);
882 9528 toonarmy
        }
883 9528 toonarmy
}
884 9528 toonarmy
885 5712 acydburn
// Compatibility functions
886 5712 acydburn
887 5712 acydburn
if (!function_exists('array_combine'))
888 5712 acydburn
{
889 5712 acydburn
        /**
890 5712 acydburn
        * A wrapper for the PHP5 function array_combine()
891 5712 acydburn
        * @param array $keys contains keys for the resulting array
892 5712 acydburn
        * @param array $values contains values for the resulting array
893 5712 acydburn
        *
894 5712 acydburn
        * @return Returns an array by using the values from the keys array as keys and the
895 5712 acydburn
        *         values from the values array as the corresponding values. Returns false if the
896 5712 acydburn
        *         number of elements for each array isn't equal or if the arrays are empty.
897 5712 acydburn
        */
898 5712 acydburn
        function array_combine($keys, $values)
899 5712 acydburn
        {
900 5712 acydburn
                $keys = array_values($keys);
901 5712 acydburn
                $values = array_values($values);
902 5712 acydburn
903 5712 acydburn
                $n = sizeof($keys);
904 5712 acydburn
                $m = sizeof($values);
905 5712 acydburn
                if (!$n || !$m || ($n != $m))
906 5712 acydburn
                {
907 5712 acydburn
                        return false;
908 5712 acydburn
                }
909 5712 acydburn
910 5712 acydburn
                $combined = array();
911 5712 acydburn
                for ($i = 0; $i < $n; $i++)
912 5712 acydburn
                {
913 5712 acydburn
                        $combined[$keys[$i]] = $values[$i];
914 5712 acydburn
                }
915 5712 acydburn
                return $combined;
916 5712 acydburn
        }
917 5712 acydburn
}
918 5712 acydburn
919 5712 acydburn
if (!function_exists('str_split'))
920 5712 acydburn
{
921 5712 acydburn
        /**
922 5712 acydburn
        * A wrapper for the PHP5 function str_split()
923 5712 acydburn
        * @param array $string contains the string to be converted
924 5712 acydburn
        * @param array $split_length contains the length of each chunk
925 5712 acydburn
        *
926 5712 acydburn
        * @return  Converts a string to an array. If the optional split_length parameter is specified,
927 5712 acydburn
        *          the returned array will be broken down into chunks with each being split_length in length,
928 5712 acydburn
        *          otherwise each chunk will be one character in length. FALSE is returned if split_length is
929 5712 acydburn
        *          less than 1. If the split_length length exceeds the length of string, the entire string is
930 8129 acydburn
        *          returned as the first (and only) array element.
931 5712 acydburn
        */
932 5712 acydburn
        function str_split($string, $split_length = 1)
933 5712 acydburn
        {
934 5712 acydburn
                if ($split_length < 1)
935 5712 acydburn
                {
936 5712 acydburn
                        return false;
937 5712 acydburn
                }
938 5712 acydburn
                else if ($split_length >= strlen($string))
939 5712 acydburn
                {
940 5712 acydburn
                        return array($string);
941 5712 acydburn
                }
942 5712 acydburn
                else
943 5712 acydburn
                {
944 5712 acydburn
                        preg_match_all('#.{1,' . $split_length . '}#s', $string, $matches);
945 5712 acydburn
                        return $matches[0];
946 5712 acydburn
                }
947 5712 acydburn
        }
948 5712 acydburn
}
949 5712 acydburn
950 6043 acydburn
if (!function_exists('stripos'))
951 6043 acydburn
{
952 6043 acydburn
        /**
953 6043 acydburn
        * A wrapper for the PHP5 function stripos
954 6043 acydburn
        * Find position of first occurrence of a case-insensitive string
955 6043 acydburn
        *
956 6043 acydburn
        * @param string $haystack is the string to search in
957 6595 acydburn
        * @param string $needle is the string to search for
958 6043 acydburn
        *
959 6930 acydburn
        * @return mixed Returns the numeric position of the first occurrence of needle in the haystack string. Unlike strpos(), stripos() is case-insensitive.
960 6043 acydburn
        * Note that the needle may be a string of one or more characters.
961 8129 acydburn
        * If needle is not found, stripos() will return boolean FALSE.
962 6043 acydburn
        */
963 6043 acydburn
        function stripos($haystack, $needle)
964 6043 acydburn
        {
965 6043 acydburn
                if (preg_match('#' . preg_quote($needle, '#') . '#i', $haystack, $m))
966 6043 acydburn
                {
967 6043 acydburn
                        return strpos($haystack, $m[0]);
968 6043 acydburn
                }
969 6043 acydburn
970 6043 acydburn
                return false;
971 6043 acydburn
        }
972 6043 acydburn
}
973 6043 acydburn
974 8355 acydburn
/**
975 8355 acydburn
* Checks if a path ($path) is absolute or relative
976 8355 acydburn
*
977 8355 acydburn
* @param string $path Path to check absoluteness of
978 8355 acydburn
* @return boolean
979 8355 acydburn
*/
980 8355 acydburn
function is_absolute($path)
981 6122 acydburn
{
982 9316 toonarmy
        return ($path[0] == '/' || (DIRECTORY_SEPARATOR == '\\' && preg_match('#^[a-z]:[/\\\]#i', $path))) ? true : false;
983 8355 acydburn
}
984 8129 acydburn
985 8355 acydburn
/**
986 8355 acydburn
* @author Chris Smith <chris@project-minerva.org>
987 8355 acydburn
* @copyright 2006 Project Minerva Team
988 8355 acydburn
* @param string $path The path which we should attempt to resolve.
989 8355 acydburn
* @return mixed
990 8355 acydburn
*/
991 8355 acydburn
function phpbb_own_realpath($path)
992 8355 acydburn
{
993 8355 acydburn
        // Now to perform funky shizzle
994 8355 acydburn
995 8355 acydburn
        // Switch to use UNIX slashes
996 8355 acydburn
        $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
997 8355 acydburn
        $path_prefix = '';
998 8355 acydburn
999 8355 acydburn
        // Determine what sort of path we have
1000 8355 acydburn
        if (is_absolute($path))
1001 6296 davidmj
        {
1002 8355 acydburn
                $absolute = true;
1003 6122 acydburn
1004 8355 acydburn
                if ($path[0] == '/')
1005 6296 davidmj
                {
1006 8355 acydburn
                        // Absolute path, *NIX style
1007 8355 acydburn
                        $path_prefix = '';
1008 8355 acydburn
                }
1009 8355 acydburn
                else
1010 8355 acydburn
                {
1011 8355 acydburn
                        // Absolute path, Windows style
1012 8355 acydburn
                        // Remove the drive letter and colon
1013 8355 acydburn
                        $path_prefix = $path[0] . ':';
1014 8355 acydburn
                        $path = substr($path, 2);
1015 8355 acydburn
                }
1016 8355 acydburn
        }
1017 8355 acydburn
        else
1018 8355 acydburn
        {
1019 8355 acydburn
                // Relative Path
1020 8355 acydburn
                // Prepend the current working directory
1021 8355 acydburn
                if (function_exists('getcwd'))
1022 8355 acydburn
                {
1023 8355 acydburn
                        // This is the best method, hopefully it is enabled!
1024 8355 acydburn
                        $path = str_replace(DIRECTORY_SEPARATOR, '/', getcwd()) . '/' . $path;
1025 8129 acydburn
                        $absolute = true;
1026 8355 acydburn
                        if (preg_match('#^[a-z]:#i', $path))
1027 6296 davidmj
                        {
1028 8355 acydburn
                                $path_prefix = $path[0] . ':';
1029 8355 acydburn
                                $path = substr($path, 2);
1030 8129 acydburn
                        }
1031 8129 acydburn
                        else
1032 8129 acydburn
                        {
1033 8355 acydburn
                                $path_prefix = '';
1034 8129 acydburn
                        }
1035 8129 acydburn
                }
1036 8355 acydburn
                else if (isset($_SERVER['SCRIPT_FILENAME']) && !empty($_SERVER['SCRIPT_FILENAME']))
1037 8355 acydburn
                {
1038 8355 acydburn
                        // Warning: If chdir() has been used this will lie!
1039 8355 acydburn
                        // Warning: This has some problems sometime (CLI can create them easily)
1040 8355 acydburn
                        $path = str_replace(DIRECTORY_SEPARATOR, '/', dirname($_SERVER['SCRIPT_FILENAME'])) . '/' . $path;
1041 8355 acydburn
                        $absolute = true;
1042 8355 acydburn
                        $path_prefix = '';
1043 8355 acydburn
                }
1044 8129 acydburn
                else
1045 8129 acydburn
                {
1046 8355 acydburn
                        // We have no way of getting the absolute path, just run on using relative ones.
1047 8355 acydburn
                        $absolute = false;
1048 8355 acydburn
                        $path_prefix = '.';
1049 8129 acydburn
                }
1050 8355 acydburn
        }
1051 6122 acydburn
1052 8355 acydburn
        // Remove any repeated slashes
1053 8355 acydburn
        $path = preg_replace('#/{2,}#', '/', $path);
1054 6122 acydburn
1055 8355 acydburn
        // Remove the slashes from the start and end of the path
1056 8355 acydburn
        $path = trim($path, '/');
1057 6296 davidmj
1058 8355 acydburn
        // Break the string into little bits for us to nibble on
1059 8355 acydburn
        $bits = explode('/', $path);
1060 6296 davidmj
1061 8355 acydburn
        // Remove any . in the path, renumber array for the loop below
1062 8355 acydburn
        $bits = array_values(array_diff($bits, array('.')));
1063 6296 davidmj
1064 8355 acydburn
        // Lets get looping, run over and resolve any .. (up directory)
1065 8355 acydburn
        for ($i = 0, $max = sizeof($bits); $i < $max; $i++)
1066 8355 acydburn
        {
1067 8355 acydburn
                // @todo Optimise
1068 8355 acydburn
                if ($bits[$i] == '..' )
1069 8129 acydburn
                {
1070 8355 acydburn
                        if (isset($bits[$i - 1]))
1071 6122 acydburn
                        {
1072 8355 acydburn
                                if ($bits[$i - 1] != '..')
1073 6296 davidmj
                                {
1074 8355 acydburn
                                        // We found a .. and we are able to traverse upwards, lets do it!
1075 8355 acydburn
                                        unset($bits[$i]);
1076 8355 acydburn
                                        unset($bits[$i - 1]);
1077 8355 acydburn
                                        $i -= 2;
1078 8355 acydburn
                                        $max -= 2;
1079 8355 acydburn
                                        $bits = array_values($bits);
1080 6296 davidmj
                                }
1081 6122 acydburn
                        }
1082 8355 acydburn
                        else if ($absolute) // ie. !isset($bits[$i - 1]) && $absolute
1083 8355 acydburn
                        {
1084 8355 acydburn
                                // We have an absolute path trying to descend above the root of the filesystem
1085 8355 acydburn
                                // ... Error!
1086 8355 acydburn
                                return false;
1087 8355 acydburn
                        }
1088 8129 acydburn
                }
1089 8355 acydburn
        }
1090 6122 acydburn
1091 8355 acydburn
        // Prepend the path prefix
1092 8355 acydburn
        array_unshift($bits, $path_prefix);
1093 6122 acydburn
1094 8355 acydburn
        $resolved = '';
1095 6296 davidmj
1096 8355 acydburn
        $max = sizeof($bits) - 1;
1097 6296 davidmj
1098 8355 acydburn
        // Check if we are able to resolve symlinks, Windows cannot.
1099 8355 acydburn
        $symlink_resolve = (function_exists('readlink')) ? true : false;
1100 6296 davidmj
1101 8355 acydburn
        foreach ($bits as $i => $bit)
1102 8355 acydburn
        {
1103 8355 acydburn
                if (@is_dir("$resolved/$bit") || ($i == $max && @is_file("$resolved/$bit")))
1104 8129 acydburn
                {
1105 8355 acydburn
                        // Path Exists
1106 8355 acydburn
                        if ($symlink_resolve && is_link("$resolved/$bit") && ($link = readlink("$resolved/$bit")))
1107 6122 acydburn
                        {
1108 8355 acydburn
                                // Resolved a symlink.
1109 8355 acydburn
                                $resolved = $link . (($i == $max) ? '' : '/');
1110 8355 acydburn
                                continue;
1111 6122 acydburn
                        }
1112 8129 acydburn
                }
1113 8355 acydburn
                else
1114 8129 acydburn
                {
1115 8355 acydburn
                        // Something doesn't exist here!
1116 8355 acydburn
                        // This is correct realpath() behaviour but sadly open_basedir and safe_mode make this problematic
1117 8355 acydburn
                        // return false;
1118 6122 acydburn
                }
1119 8355 acydburn
                $resolved .= $bit . (($i == $max) ? '' : '/');
1120 8355 acydburn
        }
1121 8129 acydburn
1122 8355 acydburn
        // @todo If the file exists fine and open_basedir only has one path we should be able to prepend it
1123 8355 acydburn
        // because we must be inside that basedir, the question is where...
1124 8355 acydburn
        // @internal The slash in is_dir() gets around an open_basedir restriction
1125 10847 git-gate
        if (!@file_exists($resolved) || (!@is_dir($resolved . '/') && !is_file($resolved)))
1126 8355 acydburn
        {
1127 8355 acydburn
                return false;
1128 8355 acydburn
        }
1129 8129 acydburn
1130 8355 acydburn
        // Put the slashes back to the native operating systems slashes
1131 8355 acydburn
        $resolved = str_replace('/', DIRECTORY_SEPARATOR, $resolved);
1132 8201 acydburn
1133 8355 acydburn
        // Check for DIRECTORY_SEPARATOR at the end (and remove it!)
1134 8355 acydburn
        if (substr($resolved, -1) == DIRECTORY_SEPARATOR)
1135 8355 acydburn
        {
1136 8355 acydburn
                return substr($resolved, 0, -1);
1137 6122 acydburn
        }
1138 8355 acydburn
1139 8355 acydburn
        return $resolved; // We got here, in the end!
1140 6122 acydburn
}
1141 8355 acydburn
1142 8355 acydburn
if (!function_exists('realpath'))
1143 6122 acydburn
{
1144 6122 acydburn
        /**
1145 6122 acydburn
        * A wrapper for realpath
1146 6447 acydburn
        * @ignore
1147 6122 acydburn
        */
1148 6122 acydburn
        function phpbb_realpath($path)
1149 6122 acydburn
        {
1150 8355 acydburn
                return phpbb_own_realpath($path);
1151 8355 acydburn
        }
1152 8355 acydburn
}
1153 8355 acydburn
else
1154 8355 acydburn
{
1155 8355 acydburn
        /**
1156 8355 acydburn
        * A wrapper for realpath
1157 8355 acydburn
        */
1158 8355 acydburn
        function phpbb_realpath($path)
1159 8355 acydburn
        {
1160 8355 acydburn
                $realpath = realpath($path);
1161 8201 acydburn
1162 8355 acydburn
                // Strangely there are provider not disabling realpath but returning strange values. :o
1163 8355 acydburn
                // We at least try to cope with them.
1164 8355 acydburn
                if ($realpath === $path || $realpath === false)
1165 8355 acydburn
                {
1166 8355 acydburn
                        return phpbb_own_realpath($path);
1167 8355 acydburn
                }
1168 8355 acydburn
1169 8201 acydburn
                // Check for DIRECTORY_SEPARATOR at the end (and remove it!)
1170 8355 acydburn
                if (substr($realpath, -1) == DIRECTORY_SEPARATOR)
1171 8201 acydburn
                {
1172 8355 acydburn
                        $realpath = substr($realpath, 0, -1);
1173 8201 acydburn
                }
1174 8201 acydburn
1175 8355 acydburn
                return $realpath;
1176 6122 acydburn
        }
1177 6122 acydburn
}
1178 6122 acydburn
1179 6549 davidmj
if (!function_exists('htmlspecialchars_decode'))
1180 6549 davidmj
{
1181 6584 acydburn
        /**
1182 6584 acydburn
        * A wrapper for htmlspecialchars_decode
1183 6584 acydburn
        * @ignore
1184 6584 acydburn
        */
1185 6549 davidmj
        function htmlspecialchars_decode($string, $quote_style = ENT_COMPAT)
1186 6549 davidmj
        {
1187 6549 davidmj
                return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
1188 6549 davidmj
        }
1189 6549 davidmj
}
1190 6549 davidmj
1191 5712 acydburn
// functions used for building option fields
1192 5712 acydburn
1193 5114 acydburn
/**
1194 5114 acydburn
* Pick a language, any language ...
1195 5114 acydburn
*/
1196 3441 psotfx
function language_select($default = '')
1197 182 psotfx
{
1198 3996 psotfx
        global $db;
1199 3989 psotfx
1200 4970 psotfx
        $sql = 'SELECT lang_iso, lang_local_name
1201 3996 psotfx
                FROM ' . LANG_TABLE . '
1202 3996 psotfx
                ORDER BY lang_english_name';
1203 6719 acydburn
        $result = $db->sql_query($sql);
1204 226 psotfx
1205 3969 psotfx
        $lang_options = '';
1206 3969 psotfx
        while ($row = $db->sql_fetchrow($result))
1207 3969 psotfx
        {
1208 3969 psotfx
                $selected = ($row['lang_iso'] == $default) ? ' selected="selected"' : '';
1209 3969 psotfx
                $lang_options .= '<option value="' . $row['lang_iso'] . '"' . $selected . '>' . $row['lang_local_name'] . '</option>';
1210 3969 psotfx
        }
1211 3969 psotfx
        $db->sql_freeresult($result);
1212 3969 psotfx
1213 3969 psotfx
        return $lang_options;
1214 2665 psotfx
}
1215 1566 psotfx
1216 8129 acydburn
/**
1217 5114 acydburn
* Pick a template/theme combo,
1218 5114 acydburn
*/
1219 4253 psotfx
function style_select($default = '', $all = false)
1220 2665 psotfx
{
1221 2665 psotfx
        global $db;
1222 1566 psotfx
1223 4253 psotfx
        $sql_where = (!$all) ? 'WHERE style_active = 1 ' : '';
1224 3996 psotfx
        $sql = 'SELECT style_id, style_name
1225 4970 psotfx
                FROM ' . STYLES_TABLE . "
1226 4253 psotfx
                $sql_where
1227 4253 psotfx
                ORDER BY style_name";
1228 2665 psotfx
        $result = $db->sql_query($sql);
1229 1566 psotfx
1230 3969 psotfx
        $style_options = '';
1231 3060 psotfx
        while ($row = $db->sql_fetchrow($result))
1232 1566 psotfx
        {
1233 3441 psotfx
                $selected = ($row['style_id'] == $default) ? ' selected="selected"' : '';
1234 3969 psotfx
                $style_options .= '<option value="' . $row['style_id'] . '"' . $selected . '>' . $row['style_name'] . '</option>';
1235 1332 psotfx
        }
1236 3969 psotfx
        $db->sql_freeresult($result);
1237 1332 psotfx
1238 3969 psotfx
        return $style_options;
1239 182 psotfx
}
1240 222 thefinn
1241 5114 acydburn
/**
1242 5114 acydburn
* Pick a timezone
1243 5114 acydburn
*/
1244 6104 acydburn
function tz_select($default = '', $truncate = false)
1245 182 psotfx
{
1246 6597 davidmj
        global $user;
1247 237 psotfx
1248 4883 acydburn
        $tz_select = '';
1249 5315 acydburn
        foreach ($user->lang['tz_zones'] as $offset => $zone)
1250 222 thefinn
        {
1251 6104 acydburn
                if ($truncate)
1252 6104 acydburn
                {
1253 8667 acydburn
                        $zone_trunc = truncate_string($zone, 50, 255, false, '...');
1254 6671 acydburn
                }
1255 6667 dhn2
                else
1256 6667 dhn2
                {
1257 6667 dhn2
                        $zone_trunc = $zone;
1258 6104 acydburn
                }
1259 6104 acydburn
1260 3441 psotfx
                if (is_numeric($offset))
1261 3441 psotfx
                {
1262 4003 psotfx
                        $selected = ($offset == $default) ? ' selected="selected"' : '';
1263 9777 toonarmy
                        $tz_select .= '<option title="' . $zone . '" value="' . $offset . '"' . $selected . '>' . $zone_trunc . '</option>';
1264 3441 psotfx
                }
1265 222 thefinn
        }
1266 1083 psotfx
1267 2665 psotfx
        return $tz_select;
1268 2665 psotfx
}
1269 1083 psotfx
1270 5712 acydburn
// Functions handling topic/post tracking/marking
1271 5712 acydburn
1272 5114 acydburn
/**
1273 5272 acydburn
* Marks a topic/forum as read
1274 5272 acydburn
* Marks a topic as posted to
1275 5779 naderman
*
1276 5779 naderman
* @param int $user_id can only be used with $mode == 'post'
1277 5114 acydburn
*/
1278 5779 naderman
function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $user_id = 0)
1279 3097 bartvb
{
1280 5272 acydburn
        global $db, $user, $config;
1281 6015 acydburn
1282 5272 acydburn
        if ($mode == 'all')
1283 5272 acydburn
        {
1284 5272 acydburn
                if ($forum_id === false || !sizeof($forum_id))
1285 5272 acydburn
                {
1286 5272 acydburn
                        if ($config['load_db_lastread'] && $user->data['is_registered'])
1287 5272 acydburn
                        {
1288 5272 acydburn
                                // Mark all forums read (index page)
1289 5272 acydburn
                                $db->sql_query('DELETE FROM ' . TOPICS_TRACK_TABLE . " WHERE user_id = {$user->data['user_id']}");
1290 5272 acydburn
                                $db->sql_query('DELETE FROM ' . FORUMS_TRACK_TABLE . " WHERE user_id = {$user->data['user_id']}");
1291 5272 acydburn
                                $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_lastmark = ' . time() . " WHERE user_id = {$user->data['user_id']}");
1292 5272 acydburn
                        }
1293 6256 acydburn
                        else if ($config['load_anon_lastread'] || $user->data['is_registered'])
1294 5272 acydburn
                        {
1295 6015 acydburn
                                $tracking_topics = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : '';
1296 7120 davidmj
                                $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
1297 4970 psotfx
1298 6015 acydburn
                                unset($tracking_topics['tf']);
1299 6015 acydburn
                                unset($tracking_topics['t']);
1300 6015 acydburn
                                unset($tracking_topics['f']);
1301 6015 acydburn
                                $tracking_topics['l'] = base_convert(time() - $config['board_startdate'], 10, 36);
1302 8348 acydburn
1303 7120 davidmj
                                $user->set_cookie('track', tracking_serialize($tracking_topics), time() + 31536000);
1304 7884 acydburn
                                $_COOKIE[$config['cookie_name'] . '_track'] = (STRIP) ? addslashes(tracking_serialize($tracking_topics)) : tracking_serialize($tracking_topics);
1305 7884 acydburn
1306 6015 acydburn
                                unset($tracking_topics);
1307 5494 acydburn
1308 5494 acydburn
                                if ($user->data['is_registered'])
1309 5494 acydburn
                                {
1310 5494 acydburn
                                        $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_lastmark = ' . time() . " WHERE user_id = {$user->data['user_id']}");
1311 5494 acydburn
                                }
1312 5272 acydburn
                        }
1313 5272 acydburn
                }
1314 6015 acydburn
1315 3097 bartvb
                return;
1316 3097 bartvb
        }
1317 5272 acydburn
        else if ($mode == 'topics')
1318 4883 acydburn
        {
1319 5272 acydburn
                // Mark all topics in forums read
1320 5272 acydburn
                if (!is_array($forum_id))
1321 5272 acydburn
                {
1322 5272 acydburn
                        $forum_id = array($forum_id);
1323 5272 acydburn
                }
1324 4883 acydburn
1325 5272 acydburn
                // Add 0 to forums array to mark global announcements correctly
1326 9926 rxu
                // $forum_id[] = 0;
1327 3953 psotfx
1328 5272 acydburn
                if ($config['load_db_lastread'] && $user->data['is_registered'])
1329 5272 acydburn
                {
1330 8129 acydburn
                        $sql = 'DELETE FROM ' . TOPICS_TRACK_TABLE . "
1331 5272 acydburn
                                WHERE user_id = {$user->data['user_id']}
1332 6271 acydburn
                                        AND " . $db->sql_in_set('forum_id', $forum_id);
1333 6015 acydburn
                        $db->sql_query($sql);
1334 5272 acydburn
1335 5272 acydburn
                        $sql = 'SELECT forum_id
1336 5272 acydburn
                                FROM ' . FORUMS_TRACK_TABLE . "
1337 5272 acydburn
                                WHERE user_id = {$user->data['user_id']}
1338 6271 acydburn
                                        AND " . $db->sql_in_set('forum_id', $forum_id);
1339 5272 acydburn
                        $result = $db->sql_query($sql);
1340 5272 acydburn
1341 5272 acydburn
                        $sql_update = array();
1342 5272 acydburn
                        while ($row = $db->sql_fetchrow($result))
1343 3097 bartvb
                        {
1344 9399 toonarmy
                                $sql_update[] = (int) $row['forum_id'];
1345 5272 acydburn
                        }
1346 5272 acydburn
                        $db->sql_freeresult($result);
1347 4970 psotfx
1348 5272 acydburn
                        if (sizeof($sql_update))
1349 5272 acydburn
                        {
1350 5272 acydburn
                                $sql = 'UPDATE ' . FORUMS_TRACK_TABLE . '
1351 5272 acydburn
                                        SET mark_time = ' . time() . "
1352 5272 acydburn
                                        WHERE user_id = {$user->data['user_id']}
1353 6271 acydburn
                                                AND " . $db->sql_in_set('forum_id', $sql_update);
1354 5272 acydburn
                                $db->sql_query($sql);
1355 5272 acydburn
                        }
1356 5272 acydburn
1357 5272 acydburn
                        if ($sql_insert = array_diff($forum_id, $sql_update))
1358 5272 acydburn
                        {
1359 5272 acydburn
                                $sql_ary = array();
1360 5272 acydburn
                                foreach ($sql_insert as $f_id)
1361 3953 psotfx
                                {
1362 5272 acydburn
                                        $sql_ary[] = array(
1363 7961 acydburn
                                                'user_id'        => (int) $user->data['user_id'],
1364 7961 acydburn
                                                'forum_id'        => (int) $f_id,
1365 5272 acydburn
                                                'mark_time'        => time()
1366 5272 acydburn
                                        );
1367 4757 psotfx
                                }
1368 4757 psotfx
1369 6497 acydburn
                                $db->sql_multi_insert(FORUMS_TRACK_TABLE, $sql_ary);
1370 5272 acydburn
                        }
1371 5272 acydburn
                }
1372 6256 acydburn
                else if ($config['load_anon_lastread'] || $user->data['is_registered'])
1373 5272 acydburn
                {
1374 6015 acydburn
                        $tracking = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : '';
1375 7120 davidmj
                        $tracking = ($tracking) ? tracking_unserialize($tracking) : array();
1376 5135 acydburn
1377 5272 acydburn
                        foreach ($forum_id as $f_id)
1378 5272 acydburn
                        {
1379 5272 acydburn
                                $topic_ids36 = (isset($tracking['tf'][$f_id])) ? $tracking['tf'][$f_id] : array();
1380 5272 acydburn
1381 5586 naderman
                                if (isset($tracking['tf'][$f_id]))
1382 5586 naderman
                                {
1383 5586 naderman
                                        unset($tracking['tf'][$f_id]);
1384 5586 naderman
                                }
1385 5586 naderman
1386 5272 acydburn
                                foreach ($topic_ids36 as $topic_id36)
1387 5272 acydburn
                                {
1388 5272 acydburn
                                        unset($tracking['t'][$topic_id36]);
1389 3953 psotfx
                                }
1390 6015 acydburn
1391 5586 naderman
                                if (isset($tracking['f'][$f_id]))
1392 5586 naderman
                                {
1393 5586 naderman
                                        unset($tracking['f'][$f_id]);
1394 5586 naderman
                                }
1395 5586 naderman
1396 5272 acydburn
                                $tracking['f'][$f_id] = base_convert(time() - $config['board_startdate'], 10, 36);
1397 5272 acydburn
                        }
1398 3953 psotfx
1399 7884 acydburn
                        if (isset($tracking['tf']) && empty($tracking['tf']))
1400 7884 acydburn
                        {
1401 7884 acydburn
                                unset($tracking['tf']);
1402 7884 acydburn
                        }
1403 7884 acydburn
1404 7120 davidmj
                        $user->set_cookie('track', tracking_serialize($tracking), time() + 31536000);
1405 7884 acydburn
                        $_COOKIE[$config['cookie_name'] . '_track'] = (STRIP) ? addslashes(tracking_serialize($tracking)) : tracking_serialize($tracking);
1406 7884 acydburn
1407 5272 acydburn
                        unset($tracking);
1408 5272 acydburn
                }
1409 5272 acydburn
1410 5272 acydburn
                return;
1411 5272 acydburn
        }
1412 5272 acydburn
        else if ($mode == 'topic')
1413 5272 acydburn
        {
1414 5272 acydburn
                if ($topic_id === false || $forum_id === false)
1415 5272 acydburn
                {
1416 5272 acydburn
                        return;
1417 5272 acydburn
                }
1418 5272 acydburn
1419 5272 acydburn
                if ($config['load_db_lastread'] && $user->data['is_registered'])
1420 5272 acydburn
                {
1421 5272 acydburn
                        $sql = 'UPDATE ' . TOPICS_TRACK_TABLE . '
1422 5272 acydburn
                                SET mark_time = ' . (($post_time) ? $post_time : time()) . "
1423 5272 acydburn
                                WHERE user_id = {$user->data['user_id']}
1424 5272 acydburn
                                        AND topic_id = $topic_id";
1425 5272 acydburn
                        $db->sql_query($sql);
1426 5272 acydburn
1427 5272 acydburn
                        // insert row
1428 5272 acydburn
                        if (!$db->sql_affectedrows())
1429 5272 acydburn
                        {
1430 5272 acydburn
                                $db->sql_return_on_error(true);
1431 5272 acydburn
1432 5272 acydburn
                                $sql_ary = array(
1433 7961 acydburn
                                        'user_id'                => (int) $user->data['user_id'],
1434 7961 acydburn
                                        'topic_id'                => (int) $topic_id,
1435 5272 acydburn
                                        'forum_id'                => (int) $forum_id,
1436 7961 acydburn
                                        'mark_time'                => ($post_time) ? (int) $post_time : time(),
1437 5272 acydburn
                                );
1438 5272 acydburn
1439 5272 acydburn
                                $db->sql_query('INSERT INTO ' . TOPICS_TRACK_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
1440 5272 acydburn
1441 5272 acydburn
                                $db->sql_return_on_error(false);
1442 5272 acydburn
                        }
1443 5272 acydburn
                }
1444 6256 acydburn
                else if ($config['load_anon_lastread'] || $user->data['is_registered'])
1445 5272 acydburn
                {
1446 6015 acydburn
                        $tracking = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : '';
1447 7120 davidmj
                        $tracking = ($tracking) ? tracking_unserialize($tracking) : array();
1448 5272 acydburn
1449 5272 acydburn
                        $topic_id36 = base_convert($topic_id, 10, 36);
1450 5272 acydburn
1451 5272 acydburn
                        if (!isset($tracking['t'][$topic_id36]))
1452 5272 acydburn
                        {
1453 5272 acydburn
                                $tracking['tf'][$forum_id][$topic_id36] = true;
1454 5272 acydburn
                        }
1455 6015 acydburn
1456 5272 acydburn
                        $post_time = ($post_time) ? $post_time : time();
1457 5272 acydburn
                        $tracking['t'][$topic_id36] = base_convert($post_time - $config['board_startdate'], 10, 36);
1458 5272 acydburn
1459 5612 acydburn
                        // If the cookie grows larger than 10000 characters we will remove the smallest value
1460 5612 acydburn
                        // This can result in old topics being unread - but most of the time it should be accurate...
1461 5612 acydburn
                        if (isset($_COOKIE[$config['cookie_name'] . '_track']) && strlen($_COOKIE[$config['cookie_name'] . '_track']) > 10000)
1462 5272 acydburn
                        {
1463 5612 acydburn
                                //echo 'Cookie grown too large' . print_r($tracking, true);
1464 5272 acydburn
1465 5612 acydburn
                                // We get the ten most minimum stored time offsets and its associated topic ids
1466 5612 acydburn
                                $time_keys = array();
1467 5612 acydburn
                                for ($i = 0; $i < 10 && sizeof($tracking['t']); $i++)
1468 5612 acydburn
                                {
1469 5612 acydburn
                                        $min_value = min($tracking['t']);
1470 5612 acydburn
                                        $m_tkey = array_search($min_value, $tracking['t']);
1471 5612 acydburn
                                        unset($tracking['t'][$m_tkey]);
1472 5612 acydburn
1473 5612 acydburn
                                        $time_keys[$m_tkey] = $min_value;
1474 5612 acydburn
                                }
1475 5612 acydburn
1476 5612 acydburn
                                // Now remove the topic ids from the array...
1477 5272 acydburn
                                foreach ($tracking['tf'] as $f_id => $topic_id_ary)
1478 3953 psotfx
                                {
1479 5612 acydburn
                                        foreach ($time_keys as $m_tkey => $min_value)
1480 3953 psotfx
                                        {
1481 5612 acydburn
                                                if (isset($topic_id_ary[$m_tkey]))
1482 5612 acydburn
                                                {
1483 5612 acydburn
                                                        $tracking['f'][$f_id] = $min_value;
1484 5612 acydburn
                                                        unset($tracking['tf'][$f_id][$m_tkey]);
1485 5612 acydburn
                                                }
1486 5272 acydburn
                                        }
1487 5272 acydburn
                                }
1488 5612 acydburn
1489 5612 acydburn
                                if ($user->data['is_registered'])
1490 5612 acydburn
                                {
1491 6256 acydburn
                                        $user->data['user_lastmark'] = intval(base_convert(max($time_keys) + $config['board_startdate'], 36, 10));
1492 6256 acydburn
                                        $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_lastmark = ' . $user->data['user_lastmark'] . " WHERE user_id = {$user->data['user_id']}");
1493 5612 acydburn
                                }
1494 5612 acydburn
                                else
1495 5612 acydburn
                                {
1496 5612 acydburn
                                        $tracking['l'] = max($time_keys);
1497 5612 acydburn
                                }
1498 5272 acydburn
                        }
1499 5612 acydburn
1500 7120 davidmj
                        $user->set_cookie('track', tracking_serialize($tracking), time() + 31536000);
1501 7884 acydburn
                        $_COOKIE[$config['cookie_name'] . '_track'] = (STRIP) ? addslashes(tracking_serialize($tracking)) : tracking_serialize($tracking);
1502 5272 acydburn
                }
1503 3262 psotfx
1504 5272 acydburn
                return;
1505 5272 acydburn
        }
1506 5272 acydburn
        else if ($mode == 'post')
1507 5272 acydburn
        {
1508 5272 acydburn
                if ($topic_id === false)
1509 5272 acydburn
                {
1510 5272 acydburn
                        return;
1511 5272 acydburn
                }
1512 3953 psotfx
1513 5973 acydburn
                $use_user_id = (!$user_id) ? $user->data['user_id'] : $user_id;
1514 3953 psotfx
1515 5973 acydburn
                if ($config['load_db_track'] && $use_user_id != ANONYMOUS)
1516 5973 acydburn
                {
1517 5973 acydburn
                        $db->sql_return_on_error(true);
1518 5135 acydburn
1519 5973 acydburn
                        $sql_ary = array(
1520 7961 acydburn
                                'user_id'                => (int) $use_user_id,
1521 7961 acydburn
                                'topic_id'                => (int) $topic_id,
1522 5973 acydburn
                                'topic_posted'        => 1
1523 5973 acydburn
                        );
1524 5973 acydburn
1525 5973 acydburn
                        $db->sql_query('INSERT INTO ' . TOPICS_POSTED_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
1526 6015 acydburn
1527 5973 acydburn
                        $db->sql_return_on_error(false);
1528 5973 acydburn
                }
1529 5973 acydburn
1530 5272 acydburn
                return;
1531 5272 acydburn
        }
1532 5272 acydburn
}
1533 5272 acydburn
1534 5272 acydburn
/**
1535 5272 acydburn
* Get topic tracking info by using already fetched info
1536 5272 acydburn
*/
1537 5272 acydburn
function get_topic_tracking($forum_id, $topic_ids, &$rowset, $forum_mark_time, $global_announce_list = false)
1538 5272 acydburn
{
1539 5272 acydburn
        global $config, $user;
1540 5272 acydburn
1541 5272 acydburn
        $last_read = array();
1542 5272 acydburn
1543 5272 acydburn
        if (!is_array($topic_ids))
1544 5272 acydburn
        {
1545 5272 acydburn
                $topic_ids = array($topic_ids);
1546 5272 acydburn
        }
1547 5272 acydburn
1548 5272 acydburn
        foreach ($topic_ids as $topic_id)
1549 5272 acydburn
        {
1550 5272 acydburn
                if (!empty($rowset[$topic_id]['mark_time']))
1551 5272 acydburn
                {
1552 5272 acydburn
                        $last_read[$topic_id] = $rowset[$topic_id]['mark_time'];
1553 5272 acydburn
                }
1554 5272 acydburn
        }
1555 5272 acydburn
1556 5272 acydburn
        $topic_ids = array_diff($topic_ids, array_keys($last_read));
1557 5272 acydburn
1558 5272 acydburn
        if (sizeof($topic_ids))
1559 5272 acydburn
        {
1560 5272 acydburn
                $mark_time = array();
1561 5272 acydburn
1562 5272 acydburn
                // Get global announcement info
1563 5272 acydburn
                if ($global_announce_list && sizeof($global_announce_list))
1564 5272 acydburn
                {
1565 5272 acydburn
                        if (!isset($forum_mark_time[0]))
1566 5272 acydburn
                        {
1567 5272 acydburn
                                global $db;
1568 5272 acydburn
1569 5272 acydburn
                                $sql = 'SELECT mark_time
1570 5272 acydburn
                                        FROM ' . FORUMS_TRACK_TABLE . "
1571 5272 acydburn
                                        WHERE user_id = {$user->data['user_id']}
1572 5272 acydburn
                                                AND forum_id = 0";
1573 5272 acydburn
                                $result = $db->sql_query($sql);
1574 5272 acydburn
                                $row = $db->sql_fetchrow($result);
1575 5272 acydburn
                                $db->sql_freeresult($result);
1576 5272 acydburn
1577 5272 acydburn
                                if ($row)
1578 5272 acydburn
                                {
1579 5272 acydburn
                                        $mark_time[0] = $row['mark_time'];
1580 3097 bartvb
                                }
1581 4757 psotfx
                        }
1582 4757 psotfx
                        else
1583 4757 psotfx
                        {
1584 5272 acydburn
                                if ($forum_mark_time[0] !== false)
1585 3953 psotfx
                                {
1586 5272 acydburn
                                        $mark_time[0] = $forum_mark_time[0];
1587 3953 psotfx
                                }
1588 5272 acydburn
                        }
1589 5272 acydburn
                }
1590 4757 psotfx
1591 5272 acydburn
                if (!empty($forum_mark_time[$forum_id]) && $forum_mark_time[$forum_id] !== false)
1592 5272 acydburn
                {
1593 5272 acydburn
                        $mark_time[$forum_id] = $forum_mark_time[$forum_id];
1594 5272 acydburn
                }
1595 8348 acydburn
1596 5272 acydburn
                $user_lastmark = (isset($mark_time[$forum_id])) ? $mark_time[$forum_id] : $user->data['user_lastmark'];
1597 5272 acydburn
1598 5272 acydburn
                foreach ($topic_ids as $topic_id)
1599 5272 acydburn
                {
1600 5272 acydburn
                        if ($global_announce_list && isset($global_announce_list[$topic_id]))
1601 5272 acydburn
                        {
1602 5272 acydburn
                                $last_read[$topic_id] = (isset($mark_time[0])) ? $mark_time[0] : $user_lastmark;
1603 3097 bartvb
                        }
1604 5272 acydburn
                        else
1605 5272 acydburn
                        {
1606 5272 acydburn
                                $last_read[$topic_id] = $user_lastmark;
1607 5272 acydburn
                        }
1608 5272 acydburn
                }
1609 5272 acydburn
        }
1610 3262 psotfx
1611 5272 acydburn
        return $last_read;
1612 5272 acydburn
}
1613 3262 psotfx
1614 5272 acydburn
/**
1615 5272 acydburn
* Get topic tracking info from db (for cookie based tracking only this function is used)
1616 5272 acydburn
*/
1617 5272 acydburn
function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_list = false)
1618 5272 acydburn
{
1619 5272 acydburn
        global $config, $user;
1620 6015 acydburn
1621 5272 acydburn
        $last_read = array();
1622 5272 acydburn
1623 5272 acydburn
        if (!is_array($topic_ids))
1624 5272 acydburn
        {
1625 5272 acydburn
                $topic_ids = array($topic_ids);
1626 5272 acydburn
        }
1627 5272 acydburn
1628 5272 acydburn
        if ($config['load_db_lastread'] && $user->data['is_registered'])
1629 5272 acydburn
        {
1630 5272 acydburn
                global $db;
1631 5272 acydburn
1632 5272 acydburn
                $sql = 'SELECT topic_id, mark_time
1633 5272 acydburn
                        FROM ' . TOPICS_TRACK_TABLE . "
1634 5272 acydburn
                        WHERE user_id = {$user->data['user_id']}
1635 6271 acydburn
                                AND " . $db->sql_in_set('topic_id', $topic_ids);
1636 5272 acydburn
                $result = $db->sql_query($sql);
1637 5272 acydburn
1638 5272 acydburn
                while ($row = $db->sql_fetchrow($result))
1639 5272 acydburn
                {
1640 5272 acydburn
                        $last_read[$row['topic_id']] = $row['mark_time'];
1641 5272 acydburn
                }
1642 5272 acydburn
                $db->sql_freeresult($result);
1643 8348 acydburn
1644 5272 acydburn
                $topic_ids = array_diff($topic_ids, array_keys($last_read));
1645 5272 acydburn
1646 5272 acydburn
                if (sizeof($topic_ids))
1647 5272 acydburn
                {
1648 8129 acydburn
                        $sql = 'SELECT forum_id, mark_time
1649 5272 acydburn
                                FROM ' . FORUMS_TRACK_TABLE . "
1650 5272 acydburn
                                WHERE user_id = {$user->data['user_id']}
1651 8129 acydburn
                                        AND forum_id " .
1652 6015 acydburn
                                        (($global_announce_list && sizeof($global_announce_list)) ? "IN (0, $forum_id)" : "= $forum_id");
1653 5272 acydburn
                        $result = $db->sql_query($sql);
1654 8348 acydburn
1655 5272 acydburn
                        $mark_time = array();
1656 5272 acydburn
                        while ($row = $db->sql_fetchrow($result))
1657 5038 acydburn
                        {
1658 5272 acydburn
                                $mark_time[$row['forum_id']] = $row['mark_time'];
1659 5038 acydburn
                        }
1660 5272 acydburn
                        $db->sql_freeresult($result);
1661 4970 psotfx
1662 5272 acydburn
                        $user_lastmark = (isset($mark_time[$forum_id])) ? $mark_time[$forum_id] : $user->data['user_lastmark'];
1663 5272 acydburn
1664 5272 acydburn
                        foreach ($topic_ids as $topic_id)
1665 3097 bartvb
                        {
1666 5272 acydburn
                                if ($global_announce_list && isset($global_announce_list[$topic_id]))
1667 3097 bartvb
                                {
1668 5272 acydburn
                                        $last_read[$topic_id] = (isset($mark_time[0])) ? $mark_time[0] : $user_lastmark;
1669 5272 acydburn
                                }
1670 5272 acydburn
                                else
1671 5272 acydburn
                                {
1672 5272 acydburn
                                        $last_read[$topic_id] = $user_lastmark;
1673 5272 acydburn
                                }
1674 5272 acydburn
                        }
1675 5272 acydburn
                }
1676 5272 acydburn
        }
1677 6256 acydburn
        else if ($config['load_anon_lastread'] || $user->data['is_registered'])
1678 5272 acydburn
        {
1679 5272 acydburn
                global $tracking_topics;
1680 4508 ludovic_arnaud
1681 5272 acydburn
                if (!isset($tracking_topics) || !sizeof($tracking_topics))
1682 5272 acydburn
                {
1683 6015 acydburn
                        $tracking_topics = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : '';
1684 7120 davidmj
                        $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
1685 5272 acydburn
                }
1686 4508 ludovic_arnaud
1687 5272 acydburn
                if (!$user->data['is_registered'])
1688 5272 acydburn
                {
1689 5272 acydburn
                        $user_lastmark = (isset($tracking_topics['l'])) ? base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate'] : 0;
1690 5272 acydburn
                }
1691 5272 acydburn
                else
1692 5272 acydburn
                {
1693 5272 acydburn
                        $user_lastmark = $user->data['user_lastmark'];
1694 5272 acydburn
                }
1695 5272 acydburn
1696 5272 acydburn
                foreach ($topic_ids as $topic_id)
1697 5272 acydburn
                {
1698 5272 acydburn
                        $topic_id36 = base_convert($topic_id, 10, 36);
1699 5272 acydburn
1700 5272 acydburn
                        if (isset($tracking_topics['t'][$topic_id36]))
1701 5272 acydburn
                        {
1702 5272 acydburn
                                $last_read[$topic_id] = base_convert($tracking_topics['t'][$topic_id36], 36, 10) + $config['board_startdate'];
1703 3953 psotfx
                        }
1704 5272 acydburn
                }
1705 5272 acydburn
1706 5272 acydburn
                $topic_ids = array_diff($topic_ids, array_keys($last_read));
1707 5272 acydburn
1708 5272 acydburn
                if (sizeof($topic_ids))
1709 5272 acydburn
                {
1710 5272 acydburn
                        $mark_time = array();
1711 5272 acydburn
                        if ($global_announce_list && sizeof($global_announce_list))
1712 3953 psotfx
                        {
1713 5272 acydburn
                                if (isset($tracking_topics['f'][0]))
1714 4052 psotfx
                                {
1715 5272 acydburn
                                        $mark_time[0] = base_convert($tracking_topics['f'][0], 36, 10) + $config['board_startdate'];
1716 4052 psotfx
                                }
1717 5272 acydburn
                        }
1718 3953 psotfx
1719 5272 acydburn
                        if (isset($tracking_topics['f'][$forum_id]))
1720 5272 acydburn
                        {
1721 5272 acydburn
                                $mark_time[$forum_id] = base_convert($tracking_topics['f'][$forum_id], 36, 10) + $config['board_startdate'];
1722 5272 acydburn
                        }
1723 5272 acydburn
1724 5272 acydburn
                        $user_lastmark = (isset($mark_time[$forum_id])) ? $mark_time[$forum_id] : $user_lastmark;
1725 5272 acydburn
1726 5272 acydburn
                        foreach ($topic_ids as $topic_id)
1727 5272 acydburn
                        {
1728 5272 acydburn
                                if ($global_announce_list && isset($global_announce_list[$topic_id]))
1729 4147 psotfx
                                {
1730 5272 acydburn
                                        $last_read[$topic_id] = (isset($mark_time[0])) ? $mark_time[0] : $user_lastmark;
1731 4147 psotfx
                                }
1732 5272 acydburn
                                else
1733 5038 acydburn
                                {
1734 5272 acydburn
                                        $last_read[$topic_id] = $user_lastmark;
1735 5038 acydburn
                                }
1736 3097 bartvb
                        }
1737 5272 acydburn
                }
1738 3097 bartvb
        }
1739 5272 acydburn
1740 5272 acydburn
        return $last_read;
1741 3097 bartvb
}
1742 3097 bartvb
1743 6256 acydburn
/**
1744 9884 bantu
* Get list of unread topics
1745 9884 bantu
*
1746 9885 bantu
* @param int $user_id                        User ID (or false for current user)
1747 9884 bantu
* @param string $sql_extra                Extra WHERE SQL statement
1748 10057 rxu
* @param string $sql_sort                ORDER BY SQL sorting statement
1749 10057 rxu
* @param string $sql_limit                Limits the size of unread topics list, 0 for unlimited query
1750 10679 git-gate
* @param string $sql_limit_offset  Sets the offset of the first row to search, 0 to search from the start
1751 9884 bantu
*
1752 9884 bantu
* @return array[int][int]                Topic ids as keys, mark_time of topic as value
1753 9884 bantu
*/
1754 10679 git-gate
function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $sql_limit = 1001, $sql_limit_offset = 0)
1755 9884 bantu
{
1756 9884 bantu
        global $config, $db, $user;
1757 9884 bantu
1758 10113 bantu
        $user_id = ($user_id === false) ? (int) $user->data['user_id'] : (int) $user_id;
1759 9884 bantu
1760 10120 bantu
        // Data array we're going to return
1761 10120 bantu
        $unread_topics = array();
1762 10120 bantu
1763 10057 rxu
        if (empty($sql_sort))
1764 10057 rxu
        {
1765 10057 rxu
                $sql_sort = 'ORDER BY t.topic_last_post_time DESC';
1766 10057 rxu
        }
1767 10057 rxu
1768 9884 bantu
        if ($config['load_db_lastread'] && $user->data['is_registered'])
1769 9884 bantu
        {
1770 10118 acydburn
                // Get list of the unread topics
1771 10936 git-gate
                $last_mark = (int) $user->data['user_lastmark'];
1772 10121 acydburn
1773 10118 acydburn
                $sql_array = array(
1774 10118 acydburn
                        'SELECT'                => 't.topic_id, t.topic_last_post_time, tt.mark_time as topic_mark_time, ft.mark_time as forum_mark_time',
1775 9884 bantu
1776 10118 acydburn
                        'FROM'                        => array(TOPICS_TABLE => 't'),
1777 10113 bantu
1778 10118 acydburn
                        'LEFT_JOIN'                => array(
1779 10118 acydburn
                                array(
1780 10118 acydburn
                                        'FROM'        => array(TOPICS_TRACK_TABLE => 'tt'),
1781 10172 acydburn
                                        'ON'        => "tt.user_id = $user_id AND t.topic_id = tt.topic_id",
1782 10118 acydburn
                                ),
1783 10118 acydburn
                                array(
1784 10118 acydburn
                                        'FROM'        => array(FORUMS_TRACK_TABLE => 'ft'),
1785 10172 acydburn
                                        'ON'        => "ft.user_id = $user_id AND t.forum_id = ft.forum_id",
1786 10118 acydburn
                                ),
1787 10118 acydburn
                        ),
1788 9884 bantu
1789 10121 acydburn
                        'WHERE'                        => "
1790 10936 git-gate
                                 t.topic_last_post_time > $last_mark AND
1791 10121 acydburn
                                (
1792 10129 bantu
                                (tt.mark_time IS NOT NULL AND t.topic_last_post_time > tt.mark_time) OR
1793 10129 bantu
                                (tt.mark_time IS NULL AND ft.mark_time IS NOT NULL AND t.topic_last_post_time > ft.mark_time) OR
1794 10936 git-gate
                                (tt.mark_time IS NULL AND ft.mark_time IS NULL)
1795 10121 acydburn
                                )
1796 10045 rxu
                                $sql_extra
1797 10118 acydburn
                                $sql_sort",
1798 10118 acydburn
                );
1799 9884 bantu
1800 10118 acydburn
                $sql = $db->sql_build_query('SELECT', $sql_array);
1801 10679 git-gate
                $result = $db->sql_query_limit($sql, $sql_limit, $sql_limit_offset);
1802 9884 bantu
1803 10118 acydburn
                while ($row = $db->sql_fetchrow($result))
1804 10118 acydburn
                {
1805 10118 acydburn
                        $topic_id = (int) $row['topic_id'];
1806 10121 acydburn
                        $unread_topics[$topic_id] = ($row['topic_mark_time']) ? (int) $row['topic_mark_time'] : (($row['forum_mark_time']) ? (int) $row['forum_mark_time'] : $last_mark);
1807 9884 bantu
                }
1808 10118 acydburn
                $db->sql_freeresult($result);
1809 9884 bantu
        }
1810 9884 bantu
        else if ($config['load_anon_lastread'] || $user->data['is_registered'])
1811 9884 bantu
        {
1812 10005 rxu
                global $tracking_topics;
1813 10005 rxu
1814 10113 bantu
                if (empty($tracking_topics))
1815 10005 rxu
                {
1816 10113 bantu
                        $tracking_topics = request_var($config['cookie_name'] . '_track', '', false, true);
1817 10005 rxu
                        $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
1818 10005 rxu
                }
1819 10005 rxu
1820 10005 rxu
                if (!$user->data['is_registered'])
1821 10005 rxu
                {
1822 10005 rxu
                        $user_lastmark = (isset($tracking_topics['l'])) ? base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate'] : 0;
1823 10005 rxu
                }
1824 10005 rxu
                else
1825 10005 rxu
                {
1826 10113 bantu
                        $user_lastmark = (int) $user->data['user_lastmark'];
1827 10005 rxu
                }
1828 10005 rxu
1829 10005 rxu
                $sql = 'SELECT t.topic_id, t.forum_id, t.topic_last_post_time
1830 10005 rxu
                        FROM ' . TOPICS_TABLE . ' t
1831 10005 rxu
                        WHERE t.topic_last_post_time > ' . $user_lastmark . "
1832 10005 rxu
                        $sql_extra
1833 10057 rxu
                        $sql_sort";
1834 10679 git-gate
                $result = $db->sql_query_limit($sql, $sql_limit, $sql_limit_offset);
1835 10005 rxu
1836 10005 rxu
                while ($row = $db->sql_fetchrow($result))
1837 10005 rxu
                {
1838 10005 rxu
                        $forum_id = (int) $row['forum_id'];
1839 10005 rxu
                        $topic_id = (int) $row['topic_id'];
1840 10005 rxu
                        $topic_id36 = base_convert($topic_id, 10, 36);
1841 10005 rxu
1842 10005 rxu
                        if (isset($tracking_topics['t'][$topic_id36]))
1843 10005 rxu
                        {
1844 10120 bantu
                                $last_read = base_convert($tracking_topics['t'][$topic_id36], 36, 10) + $config['board_startdate'];
1845 10120 bantu
1846 10120 bantu
                                if ($row['topic_last_post_time'] > $last_read)
1847 10005 rxu
                                {
1848 10120 bantu
                                        $unread_topics[$topic_id] = $last_read;
1849 10005 rxu
                                }
1850 10005 rxu
                        }
1851 10005 rxu
                        else if (isset($tracking_topics['f'][$forum_id]))
1852 10005 rxu
                        {
1853 10120 bantu
                                $mark_time = base_convert($tracking_topics['f'][$forum_id], 36, 10) + $config['board_startdate'];
1854 10120 bantu
1855 10120 bantu
                                if ($row['topic_last_post_time'] > $mark_time)
1856 10005 rxu
                                {
1857 10120 bantu
                                        $unread_topics[$topic_id] = $mark_time;
1858 10005 rxu
                                }
1859 10005 rxu
                        }
1860 10005 rxu
                        else
1861 10005 rxu
                        {
1862 10120 bantu
                                $unread_topics[$topic_id] = $user_lastmark;
1863 10005 rxu
                        }
1864 10005 rxu
                }
1865 10005 rxu
                $db->sql_freeresult($result);
1866 9884 bantu
        }
1867 9884 bantu
1868 10120 bantu
        return $unread_topics;
1869 9884 bantu
}
1870 9884 bantu
1871 9884 bantu
/**
1872 6256 acydburn
* Check for read forums and update topic tracking info accordingly
1873 6256 acydburn
*
1874 6256 acydburn
* @param int $forum_id the forum id to check
1875 6256 acydburn
* @param int $forum_last_post_time the forums last post time
1876 6256 acydburn
* @param int $f_mark_time the forums last mark time if user is registered and load_db_lastread enabled
1877 6256 acydburn
* @param int $mark_time_forum false if the mark time needs to be obtained, else the last users forum mark time
1878 6256 acydburn
*
1879 6320 acydburn
* @return true if complete forum got marked read, else false.
1880 6256 acydburn
*/
1881 6256 acydburn
function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time = false, $mark_time_forum = false)
1882 6256 acydburn
{
1883 11546 git-gate
        global $db, $tracking_topics, $user, $config, $auth;
1884 6256 acydburn
1885 6256 acydburn
        // Determine the users last forum mark time if not given.
1886 6256 acydburn
        if ($mark_time_forum === false)
1887 6256 acydburn
        {
1888 6256 acydburn
                if ($config['load_db_lastread'] && $user->data['is_registered'])
1889 6256 acydburn
                {
1890 6256 acydburn
                        $mark_time_forum = (!empty($f_mark_time)) ? $f_mark_time : $user->data['user_lastmark'];
1891 6256 acydburn
                }
1892 6256 acydburn
                else if ($config['load_anon_lastread'] || $user->data['is_registered'])
1893 6256 acydburn
                {
1894 7884 acydburn
                        $tracking_topics = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : '';
1895 7884 acydburn
                        $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
1896 6256 acydburn
1897 6256 acydburn
                        if (!$user->data['is_registered'])
1898 6256 acydburn
                        {
1899 6256 acydburn
                                $user->data['user_lastmark'] = (isset($tracking_topics['l'])) ? (int) (base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate']) : 0;
1900 6256 acydburn
                        }
1901 6256 acydburn
1902 6256 acydburn
                        $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'];
1903 6256 acydburn
                }
1904 6256 acydburn
        }
1905 6256 acydburn
1906 11546 git-gate
        // Handle update of unapproved topics info.
1907 11546 git-gate
        // Only update for moderators having m_approve permission for the forum.
1908 11546 git-gate
        $sql_update_unapproved = ($auth->acl_get('m_approve', $forum_id)) ? '': 'AND t.topic_approved = 1';
1909 11546 git-gate
1910 6256 acydburn
        // Check the forum for any left unread topics.
1911 6256 acydburn
        // If there are none, we mark the forum as read.
1912 6256 acydburn
        if ($config['load_db_lastread'] && $user->data['is_registered'])
1913 6256 acydburn
        {
1914 6256 acydburn
                if ($mark_time_forum >= $forum_last_post_time)
1915 6256 acydburn
                {
1916 6256 acydburn
                        // We do not need to mark read, this happened before. Therefore setting this to true
1917 6256 acydburn
                        $row = true;
1918 6256 acydburn
                }
1919 6256 acydburn
                else
1920 6256 acydburn
                {
1921 6256 acydburn
                        $sql = 'SELECT t.forum_id FROM ' . TOPICS_TABLE . ' t
1922 6256 acydburn
                                LEFT JOIN ' . TOPICS_TRACK_TABLE . ' tt ON (tt.topic_id = t.topic_id AND tt.user_id = ' . $user->data['user_id'] . ')
1923 6256 acydburn
                                WHERE t.forum_id = ' . $forum_id . '
1924 6256 acydburn
                                        AND t.topic_last_post_time > ' . $mark_time_forum . '
1925 11546 git-gate
                                        AND t.topic_moved_id = 0 ' .
1926 11546 git-gate
                                        $sql_update_unapproved . '
1927 7749 acydburn
                                        AND (tt.topic_id IS NULL OR tt.mark_time < t.topic_last_post_time)
1928 6256 acydburn
                                GROUP BY t.forum_id';
1929 6256 acydburn
                        $result = $db->sql_query_limit($sql, 1);
1930 6256 acydburn
                        $row = $db->sql_fetchrow($result);
1931 6256 acydburn
                        $db->sql_freeresult($result);
1932 6256 acydburn
                }
1933 6256 acydburn
        }
1934 6256 acydburn
        else if ($config['load_anon_lastread'] || $user->data['is_registered'])
1935 6256 acydburn
        {
1936 6256 acydburn
                // Get information from cookie
1937 6256 acydburn
                $row = false;
1938 6256 acydburn
1939 6256 acydburn
                if (!isset($tracking_topics['tf'][$forum_id]))
1940 6256 acydburn
                {
1941 6256 acydburn
                        // We do not need to mark read, this happened before. Therefore setting this to true
1942 6256 acydburn
                        $row = true;
1943 6256 acydburn
                }
1944 6256 acydburn
                else
1945 6256 acydburn
                {
1946 11595 git-gate
                        $sql = 'SELECT t.topic_id
1947 11595 git-gate
                                FROM ' . TOPICS_TABLE . ' t
1948 11595 git-gate
                                WHERE t.forum_id = ' . $forum_id . '
1949 11595 git-gate
                                        AND t.topic_last_post_time > ' . $mark_time_forum . '
1950 11595 git-gate
                                        AND t.topic_moved_id = 0 ' .
1951 11546 git-gate
                                        $sql_update_unapproved;
1952 6256 acydburn
                        $result = $db->sql_query($sql);
1953 6256 acydburn
1954 6256 acydburn
                        $check_forum = $tracking_topics['tf'][$forum_id];
1955 6256 acydburn
                        $unread = false;
1956 7884 acydburn
1957 6256 acydburn
                        while ($row = $db->sql_fetchrow($result))
1958 6256 acydburn
                        {
1959 8350 acydburn
                                if (!isset($check_forum[base_convert($row['topic_id'], 10, 36)]))
1960 6256 acydburn
                                {
1961 6256 acydburn
                                        $unread = true;
1962 6256 acydburn
                                        break;
1963 6256 acydburn
                                }
1964 6256 acydburn
                        }
1965 6256 acydburn
                        $db->sql_freeresult($result);
1966 6256 acydburn
1967 6256 acydburn
                        $row = $unread;
1968 6256 acydburn
                }
1969 6256 acydburn
        }
1970 6256 acydburn
        else
1971 6256 acydburn
        {
1972 6256 acydburn
                $row = true;
1973 6256 acydburn
        }
1974 6256 acydburn
1975 6256 acydburn
        if (!$row)
1976 6256 acydburn
        {
1977 6256 acydburn
                markread('topics', $forum_id);
1978 6320 acydburn
                return true;
1979 6256 acydburn
        }
1980 6320 acydburn
1981 6320 acydburn
        return false;
1982 6256 acydburn
}
1983 6256 acydburn
1984 7120 davidmj
/**
1985 7120 davidmj
* Transform an array into a serialized format
1986 7120 davidmj
*/
1987 7120 davidmj
function tracking_serialize($input)
1988 7120 davidmj
{
1989 7120 davidmj
        $out = '';
1990 7120 davidmj
        foreach ($input as $key => $value)
1991 7120 davidmj
        {
1992 7120 davidmj
                if (is_array($value))
1993 7120 davidmj
                {
1994 7164 acydburn
                        $out .= $key . ':(' . tracking_serialize($value) . ');';
1995 7120 davidmj
                }
1996 7120 davidmj
                else
1997 7120 davidmj
                {
1998 7120 davidmj
                        $out .= $key . ':' . $value . ';';
1999 7120 davidmj
                }
2000 7120 davidmj
        }
2001 7120 davidmj
        return $out;
2002 7120 davidmj
}
2003 7120 davidmj
2004 7120 davidmj
/**
2005 7120 davidmj
* Transform a serialized array into an actual array
2006 7120 davidmj
*/
2007 7120 davidmj
function tracking_unserialize($string, $max_depth = 3)
2008 7120 davidmj
{
2009 7120 davidmj
        $n = strlen($string);
2010 7120 davidmj
        if ($n > 10010)
2011 7120 davidmj
        {
2012 7120 davidmj
                die('Invalid data supplied');
2013 7120 davidmj
        }
2014 7120 davidmj
        $data = $stack = array();
2015 7120 davidmj
        $key = '';
2016 7120 davidmj
        $mode = 0;
2017 7120 davidmj
        $level = &$data;
2018 7121 davidmj
        for ($i = 0; $i < $n; ++$i)
2019 7120 davidmj
        {
2020 7120 davidmj
                switch ($mode)
2021 7120 davidmj
                {
2022 7120 davidmj
                        case 0:
2023 7120 davidmj
                                switch ($string[$i])
2024 7120 davidmj
                                {
2025 7120 davidmj
                                        case ':':
2026 7120 davidmj
                                                $level[$key] = 0;
2027 7120 davidmj
                                                $mode = 1;
2028 7120 davidmj
                                        break;
2029 7120 davidmj
                                        case ')':
2030 7120 davidmj
                                                unset($level);
2031 7120 davidmj
                                                $level = array_pop($stack);
2032 7120 davidmj
                                                $mode = 3;
2033 7120 davidmj
                                        break;
2034 7120 davidmj
                                        default:
2035 7120 davidmj
                                                $key .= $string[$i];
2036 7120 davidmj
                                }
2037 7120 davidmj
                        break;
2038 7120 davidmj
2039 7120 davidmj
                        case 1:
2040 7120 davidmj
                                switch ($string[$i])
2041 7120 davidmj
                                {
2042 7120 davidmj
                                        case '(':
2043 7120 davidmj
                                                if (sizeof($stack) >= $max_depth)
2044 7120 davidmj
                                                {
2045 7120 davidmj
                                                        die('Invalid data supplied');
2046 7120 davidmj
                                                }
2047 7120 davidmj
                                                $stack[] = &$level;
2048 7120 davidmj
                                                $level[$key] = array();
2049 7120 davidmj
                                                $level = &$level[$key];
2050 7120 davidmj
                                                $key = '';
2051 7120 davidmj
                                                $mode = 0;
2052 7120 davidmj
                                        break;
2053 7120 davidmj
                                        default:
2054 7120 davidmj
                                                $level[$key] = $string[$i];
2055 7120 davidmj
                                                $mode = 2;
2056 7120 davidmj
                                        break;
2057 7120 davidmj
                                }
2058 7120 davidmj
                        break;
2059 8348 acydburn
2060 7120 davidmj
                        case 2:
2061 7120 davidmj
                                switch ($string[$i])
2062 7120 davidmj
                                {
2063 7120 davidmj
                                        case ')':
2064 7120 davidmj
                                                unset($level);
2065 7120 davidmj
                                                $level = array_pop($stack);
2066 7120 davidmj
                                                $mode = 3;
2067 7120 davidmj
                                        break;
2068 7120 davidmj
                                        case ';':
2069 7120 davidmj
                                                $key = '';
2070 7120 davidmj
                                                $mode = 0;
2071 7120 davidmj
                                        break;
2072 7120 davidmj
                                        default:
2073 7120 davidmj
                                                $level[$key] .= $string[$i];
2074 7120 davidmj
                                        break;
2075 7120 davidmj
                                }
2076 7120 davidmj
                        break;
2077 8348 acydburn
2078 7120 davidmj
                        case 3:
2079 7120 davidmj
                                switch ($string[$i])
2080 7120 davidmj
                                {
2081 7120 davidmj
                                        case ')':
2082 7120 davidmj
                                                unset($level);
2083 7120 davidmj
                                                $level = array_pop($stack);
2084 7120 davidmj
                                        break;
2085 7120 davidmj
                                        case ';':
2086 7120 davidmj
                                                $key = '';
2087 7120 davidmj
                                                $mode = 0;
2088 7120 davidmj
                                        break;
2089 7120 davidmj
                                        default:
2090 7120 davidmj
                                                die('Invalid data supplied');
2091 7120 davidmj
                                        break;
2092 7120 davidmj
                                }
2093 7120 davidmj
                        break;
2094 7120 davidmj
                }
2095 7120 davidmj
        }
2096 7120 davidmj
2097 7120 davidmj
        if (sizeof($stack) != 0 || ($mode != 0 && $mode != 3))
2098 7120 davidmj
        {
2099 7120 davidmj
                die('Invalid data supplied');
2100 7120 davidmj
        }
2101 8348 acydburn
2102 7120 davidmj
        return $level;
2103 7120 davidmj
}
2104 7120 davidmj
2105 5712 acydburn
// Pagination functions
2106 5712 acydburn
2107 5114 acydburn
/**
2108 5114 acydburn
* Pagination routine, generates page number sequence
2109 5114 acydburn
* tpl_prefix is for using different pagination blocks at one page
2110 5114 acydburn
*/
2111 5114 acydburn
function generate_pagination($base_url, $num_items, $per_page, $start_item, $add_prevnext_text = false, $tpl_prefix = '')
2112 265 psotfx
{
2113 4430 psotfx
        global $template, $user;
2114 336 thefinn
2115 6894 acydburn
        // Make sure $per_page is a valid value
2116 6894 acydburn
        $per_page = ($per_page <= 0) ? 1 : $per_page;
2117 6894 acydburn
2118 6940 shs
        $seperator = '<span class="page-sep">' . $user->lang['COMMA_SEPARATOR'] . '</span>';
2119 6894 acydburn
        $total_pages = ceil($num_items / $per_page);
2120 1247 psotfx
2121 3060 psotfx
        if ($total_pages == 1 || !$num_items)
2122 265 psotfx
        {
2123 4430 psotfx
                return false;
2124 265 psotfx
        }
2125 265 psotfx
2126 1247 psotfx
        $on_page = floor($start_item / $per_page) + 1;
2127 10094 Kellanved
        $url_delim = (strpos($base_url, '?') === false) ? '?' : ((strpos($base_url, '?') === strlen($base_url) - 1) ? '' : '&amp;');
2128 7497 acydburn
2129 4984 acydburn
        $page_string = ($on_page == 1) ? '<strong>1</strong>' : '<a href="' . $base_url . '">1</a>';
2130 2923 psotfx
2131 3060 psotfx
        if ($total_pages > 5)
2132 265 psotfx
        {
2133 2923 psotfx
                $start_cnt = min(max(1, $on_page - 4), $total_pages - 5);
2134 2923 psotfx
                $end_cnt = max(min($total_pages, $on_page + 4), 6);
2135 265 psotfx
2136 11444 git-gate
                $page_string .= ($start_cnt > 1) ? '<span class="page-dots"> ... </span>' : $seperator;
2137 2923 psotfx
2138 6015 acydburn
                for ($i = $start_cnt + 1; $i < $end_cnt; $i++)
2139 265 psotfx
                {
2140 7497 acydburn
                        $page_string .= ($i == $on_page) ? '<strong>' . $i . '</strong>' : '<a href="' . $base_url . "{$url_delim}start=" . (($i - 1) * $per_page) . '">' . $i . '</a>';
2141 3060 psotfx
                        if ($i < $end_cnt - 1)
2142 1247 psotfx
                        {
2143 4899 acydburn
                                $page_string .= $seperator;
2144 1247 psotfx
                        }
2145 265 psotfx
                }
2146 265 psotfx
2147 11444 git-gate
                $page_string .= ($end_cnt < $total_pages) ? '<span class="page-dots"> ... </span>' : $seperator;
2148 265 psotfx
        }
2149 1247 psotfx
        else
2150 1247 psotfx
        {
2151 4899 acydburn
                $page_string .= $seperator;
2152 2923 psotfx
2153 6015 acydburn
                for ($i = 2; $i < $total_pages; $i++)
2154 1247 psotfx
                {
2155 7497 acydburn
                        $page_string .= ($i == $on_page) ? '<strong>' . $i . '</strong>' : '<a href="' . $base_url . "{$url_delim}start=" . (($i - 1) * $per_page) . '">' . $i . '</a>';
2156 3060 psotfx
                        if ($i < $total_pages)
2157 1247 psotfx
                        {
2158 4899 acydburn
                                $page_string .= $seperator;
2159 1247 psotfx
                        }
2160 1247 psotfx
                }
2161 1247 psotfx
        }
2162 336 thefinn
2163 7497 acydburn
        $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>';
2164 1247 psotfx
2165 5114 acydburn
        if ($add_prevnext_text)
2166 5114 acydburn
        {
2167 8129 acydburn
                if ($on_page != 1)
2168 5114 acydburn
                {
2169 7497 acydburn
                        $page_string = '<a href="' . $base_url . "{$url_delim}start=" . (($on_page - 2) * $per_page) . '">' . $user->lang['PREVIOUS'] . '</a>&nbsp;&nbsp;' . $page_string;
2170 5114 acydburn
                }
2171 5114 acydburn
2172 5114 acydburn
                if ($on_page != $total_pages)
2173 5114 acydburn
                {
2174 7497 acydburn
                        $page_string .= '&nbsp;&nbsp;<a href="' . $base_url . "{$url_delim}start=" . ($on_page * $per_page) . '">' . $user->lang['NEXT'] . '</a>';
2175 5114 acydburn
                }
2176 5114 acydburn
        }
2177 5114 acydburn
2178 4984 acydburn
        $template->assign_vars(array(
2179 8099 acydburn
                $tpl_prefix . 'BASE_URL'                => $base_url,
2180 8099 acydburn
                'A_' . $tpl_prefix . 'BASE_URL'        => addslashes($base_url),
2181 8099 acydburn
                $tpl_prefix . 'PER_PAGE'                => $per_page,
2182 4990 psotfx
2183 7497 acydburn
                $tpl_prefix . 'PREVIOUS_PAGE'        => ($on_page == 1) ? '' : $base_url . "{$url_delim}start=" . (($on_page - 2) * $per_page),
2184 7497 acydburn
                $tpl_prefix . 'NEXT_PAGE'                => ($on_page == $total_pages) ? '' : $base_url . "{$url_delim}start=" . ($on_page * $per_page),
2185 8099 acydburn
                $tpl_prefix . 'TOTAL_PAGES'                => $total_pages,
2186 8099 acydburn
        ));
2187 4430 psotfx
2188 265 psotfx
        return $page_string;
2189 265 psotfx
}
2190 265 psotfx
2191 5114 acydburn
/**
2192 5114 acydburn
* Return current page (pagination)
2193 5114 acydburn
*/
2194 2810 psotfx
function on_page($num_items, $per_page, $start)
2195 2810 psotfx
{
2196 4430 psotfx
        global $template, $user;
2197 2810 psotfx
2198 6894 acydburn
        // Make sure $per_page is a valid value
2199 6894 acydburn
        $per_page = ($per_page <= 0) ? 1 : $per_page;
2200 6894 acydburn
2201 4430 psotfx
        $on_page = floor($start / $per_page) + 1;
2202 4430 psotfx
2203 5315 acydburn
        $template->assign_vars(array(
2204 6969 acydburn
                'ON_PAGE'                => $on_page)
2205 5315 acydburn
        );
2206 4430 psotfx
2207 4430 psotfx
        return sprintf($user->lang['PAGE_OF'], $on_page, max(ceil($num_items / $per_page), 1));
2208 2810 psotfx
}
2209 2810 psotfx
2210 5712 acydburn
// Server functions (building urls, redirecting...)
2211 5712 acydburn
2212 5114 acydburn
/**
2213 8100 acydburn
* Append session id to url.
2214 8100 acydburn
* This function supports hooks.
2215 6015 acydburn
*
2216 6015 acydburn
* @param string $url The url the session id needs to be appended to (can have params)
2217 6015 acydburn
* @param mixed $params String or array of additional url parameters
2218 6015 acydburn
* @param bool $is_amp Is url using &amp; (true) or & (false)
2219 6015 acydburn
* @param string $session_id Possibility to use a custom session id instead of the global one
2220 6015 acydburn
*
2221 6015 acydburn
* Examples:
2222 6015 acydburn
* <code>
2223 6015 acydburn
* append_sid("{$phpbb_root_path}viewtopic.$phpEx?t=1&amp;f=2");
2224 6015 acydburn
* append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=1&amp;f=2');
2225 6015 acydburn
* append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=1&f=2', false);
2226 6015 acydburn
* append_sid("{$phpbb_root_path}viewtopic.$phpEx", array('t' => 1, 'f' => 2));
2227 6015 acydburn
* </code>
2228 8072 acydburn
*
2229 6015 acydburn
*/
2230 6015 acydburn
function append_sid($url, $params = false, $is_amp = true, $session_id = false)
2231 6015 acydburn
{
2232 8100 acydburn
        global $_SID, $_EXTRA_URL, $phpbb_hook;
2233 6015 acydburn
2234 11401 git-gate
        if ($params === '' || (is_array($params) && empty($params)))
2235 11401 git-gate
        {
2236 11401 git-gate
                // Do not append the ? if the param-list is empty anyway.
2237 11401 git-gate
                $params = false;
2238 11401 git-gate
        }
2239 11401 git-gate
2240 10582 git-gate
        // Developers using the hook function need to globalise the $_SID and $_EXTRA_URL on their own and also handle it appropriately.
2241 10582 git-gate
        // They could mimic most of what is within this function
2242 8131 acydburn
        if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__, $url, $params, $is_amp, $session_id))
2243 7994 acydburn
        {
2244 8100 acydburn
                if ($phpbb_hook->hook_return(__FUNCTION__))
2245 8100 acydburn
                {
2246 8100 acydburn
                        return $phpbb_hook->hook_return_result(__FUNCTION__);
2247 8100 acydburn
                }
2248 7994 acydburn
        }
2249 7994 acydburn
2250 9150 acydburn
        $params_is_array = is_array($params);
2251 9150 acydburn
2252 9150 acydburn
        // Get anchor
2253 9150 acydburn
        $anchor = '';
2254 9150 acydburn
        if (strpos($url, '#') !== false)
2255 9150 acydburn
        {
2256 9150 acydburn
                list($url, $anchor) = explode('#', $url, 2);
2257 9150 acydburn
                $anchor = '#' . $anchor;
2258 9150 acydburn
        }
2259 9150 acydburn
        else if (!$params_is_array && strpos($params, '#') !== false)
2260 9150 acydburn
        {
2261 9150 acydburn
                list($params, $anchor) = explode('#', $params, 2);
2262 9150 acydburn
                $anchor = '#' . $anchor;
2263 9150 acydburn
        }
2264 9150 acydburn
2265 9150 acydburn
        // Handle really simple cases quickly
2266 9150 acydburn
        if ($_SID == '' && $session_id === false && empty($_EXTRA_URL) && !$params_is_array && !$anchor)
2267 9150 acydburn
        {
2268 9150 acydburn
                if ($params === false)
2269 9150 acydburn
                {
2270 9150 acydburn
                        return $url;
2271 9150 acydburn
                }
2272 9150 acydburn
2273 9150 acydburn
                $url_delim = (strpos($url, '?') === false) ? '?' : (($is_amp) ? '&amp;' : '&');
2274 9150 acydburn
                return $url . ($params !== false ? $url_delim. $params : '');
2275 9150 acydburn
        }
2276 9150 acydburn
2277 6015 acydburn
        // Assign sid if session id is not specified
2278 6015 acydburn
        if ($session_id === false)
2279 6015 acydburn
        {
2280 6015 acydburn
                $session_id = $_SID;
2281 6015 acydburn
        }
2282 6015 acydburn
2283 6015 acydburn
        $amp_delim = ($is_amp) ? '&amp;' : '&';
2284 6015 acydburn
        $url_delim = (strpos($url, '?') === false) ? '?' : $amp_delim;
2285 6015 acydburn
2286 6015 acydburn
        // Appending custom url parameter?
2287 6015 acydburn
        $append_url = (!empty($_EXTRA_URL)) ? implode($amp_delim, $_EXTRA_URL) : '';
2288 6015 acydburn
2289 6015 acydburn
        // Use the short variant if possible ;)
2290 6015 acydburn
        if ($params === false)
2291 6015 acydburn
        {
2292 6015 acydburn
                // Append session id
2293 7736 acydburn
                if (!$session_id)
2294 7736 acydburn
                {
2295 7736 acydburn
                        return $url . (($append_url) ? $url_delim . $append_url : '') . $anchor;
2296 7736 acydburn
                }
2297 7736 acydburn
                else
2298 7736 acydburn
                {
2299 7736 acydburn
                        return $url . (($append_url) ? $url_delim . $append_url . $amp_delim : $url_delim) . 'sid=' . $session_id . $anchor;
2300 7736 acydburn
                }
2301 6015 acydburn
        }
2302 6015 acydburn
2303 6015 acydburn
        // Build string if parameters are specified as array
2304 6015 acydburn
        if (is_array($params))
2305 6015 acydburn
        {
2306 6015 acydburn
                $output = array();
2307 6015 acydburn
2308 6015 acydburn
                foreach ($params as $key => $item)
2309 6015 acydburn
                {
2310 6015 acydburn
                        if ($item === NULL)
2311 6015 acydburn
                        {
2312 6015 acydburn
                                continue;
2313 6015 acydburn
                        }
2314 6015 acydburn
2315 7736 acydburn
                        if ($key == '#')
2316 7736 acydburn
                        {
2317 7736 acydburn
                                $anchor = '#' . $item;
2318 7736 acydburn
                                continue;
2319 7736 acydburn
                        }
2320 7736 acydburn
2321 6015 acydburn
                        $output[] = $key . '=' . $item;
2322 6015 acydburn
                }
2323 6015 acydburn
2324 6015 acydburn
                $params = implode($amp_delim, $output);
2325 6015 acydburn
        }
2326 6015 acydburn
2327 6015 acydburn
        // Append session id and parameters (even if they are empty)
2328 6015 acydburn
        // If parameters are empty, the developer can still append his/her parameters without caring about the delimiter
2329 7736 acydburn
        return $url . (($append_url) ? $url_delim . $append_url . $amp_delim : $url_delim) . $params . ((!$session_id) ? '' : $amp_delim . 'sid=' . $session_id) . $anchor;
2330 6015 acydburn
}
2331 6015 acydburn
2332 6015 acydburn
/**
2333 8148 acydburn
* Generate board url (example: http://www.example.com/phpBB)
2334 11122 git-gate
*
2335 8148 acydburn
* @param bool $without_script_path if set to true the script path gets not appended (example: http://www.example.com)
2336 11122 git-gate
*
2337 11122 git-gate
* @return string the generated board url
2338 5114 acydburn
*/
2339 5626 acydburn
function generate_board_url($without_script_path = false)
2340 3718 psotfx
{
2341 5595 acydburn
        global $config, $user;
2342 3718 psotfx
2343 8348 acydburn
        $server_name = $user->host;
2344 5595 acydburn
        $server_port = (!empty($_SERVER['SERVER_PORT'])) ? (int) $_SERVER['SERVER_PORT'] : (int) getenv('SERVER_PORT');
2345 4412 ludovic_arnaud
2346 5595 acydburn
        // Forcing server vars is the only way to specify/override the protocol
2347 5595 acydburn
        if ($config['force_server_vars'] || !$server_name)
2348 5595 acydburn
        {
2349 5595 acydburn
                $server_protocol = ($config['server_protocol']) ? $config['server_protocol'] : (($config['cookie_secure']) ? 'https://' : 'http://');
2350 5595 acydburn
                $server_name = $config['server_name'];
2351 5595 acydburn
                $server_port = (int) $config['server_port'];
2352 6730 acydburn
                $script_path = $config['script_path'];
2353 5595 acydburn
2354 5595 acydburn
                $url = $server_protocol . $server_name;
2355 8737 acydburn
                $cookie_secure = $config['cookie_secure'];
2356 5595 acydburn
        }
2357 6147 acydburn
        else
2358 6147 acydburn
        {
2359 6147 acydburn
                // Do not rely on cookie_secure, users seem to think that it means a secured cookie instead of an encrypted connection
2360 6147 acydburn
                $cookie_secure = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 1 : 0;
2361 6147 acydburn
                $url = (($cookie_secure) ? 'https://' : 'http://') . $server_name;
2362 6730 acydburn
2363 6730 acydburn
                $script_path = $user->page['root_script_path'];
2364 6147 acydburn
        }
2365 5595 acydburn
2366 8737 acydburn
        if ($server_port && (($cookie_secure && $server_port <> 443) || (!$cookie_secure && $server_port <> 80)))
2367 5595 acydburn
        {
2368 8636 acydburn
                // HTTP HOST can carry a port number (we fetch $user->host, but for old versions this may be true)
2369 8348 acydburn
                if (strpos($server_name, ':') === false)
2370 8348 acydburn
                {
2371 8348 acydburn
                        $url .= ':' . $server_port;
2372 8348 acydburn
                }
2373 5595 acydburn
        }
2374 5595 acydburn
2375 6730 acydburn
        if (!$without_script_path)
2376 5626 acydburn
        {
2377 6730 acydburn
                $url .= $script_path;
2378 5626 acydburn
        }
2379 5626 acydburn
2380 6015 acydburn
        // Strip / from the end
2381 6730 acydburn
        if (substr($url, -1, 1) == '/')
2382 6730 acydburn
        {
2383 6730 acydburn
                $url = substr($url, 0, -1);
2384 6730 acydburn
        }
2385 6730 acydburn
2386 6730 acydburn
        return $url;
2387 3718 psotfx
}
2388 3718 psotfx
2389 5114 acydburn
/**
2390 5114 acydburn
* Redirects the user to another page then exits the script nicely
2391 8643 acydburn
* This function is intended for urls within the board. It's not meant to redirect to cross-domains.
2392 8674 acydburn
*
2393 8674 acydburn
* @param string $url The url to redirect to
2394 8674 acydburn
* @param bool $return If true, do not redirect but return the sanitized URL. Default is no return.
2395 8674 acydburn
* @param bool $disable_cd_check If true, redirect() will redirect to an external domain. If false, the redirect point to the boards url if it does not match the current domain. Default is false.
2396 5114 acydburn
*/
2397 8674 acydburn
function redirect($url, $return = false, $disable_cd_check = false)
2398 2948 ludovic_arnaud
{
2399 6544 acydburn
        global $db, $cache, $config, $user, $phpbb_root_path;
2400 2958 psotfx
2401 10583 git-gate
        $failover_flag = false;
2402 10583 git-gate
2403 6149 acydburn
        if (empty($user->lang))
2404 2950 ludovic_arnaud
        {
2405 6149 acydburn
                $user->add_lang('common');
2406 2950 ludovic_arnaud
        }
2407 3870 psotfx
2408 6500 davidmj
        if (!$return)
2409 6500 davidmj
        {
2410 6500 davidmj
                garbage_collection();
2411 6500 davidmj
        }
2412 2948 ludovic_arnaud
2413 4920 acydburn
        // Make sure no &amp;'s are in, this will break the redirect
2414 4920 acydburn
        $url = str_replace('&amp;', '&', $url);
2415 4920 acydburn
2416 5626 acydburn
        // Determine which type of redirect we need to handle...
2417 9907 acydburn
        $url_parts = @parse_url($url);
2418 5626 acydburn
2419 5626 acydburn
        if ($url_parts === false)
2420 5626 acydburn
        {
2421 5626 acydburn
                // Malformed url, redirect to current page...
2422 5626 acydburn
                $url = generate_board_url() . '/' . $user->page['page'];
2423 5626 acydburn
        }
2424 5626 acydburn
        else if (!empty($url_parts['scheme']) && !empty($url_parts['host']))
2425 5626 acydburn
        {
2426 8674 acydburn
                // Attention: only able to redirect within the same domain if $disable_cd_check is false (yourdomain.com -> www.yourdomain.com will not work)
2427 8674 acydburn
                if (!$disable_cd_check && $url_parts['host'] !== $user->host)
2428 8611 Kellanved
                {
2429 8622 Kellanved
                        $url = generate_board_url();
2430 8611 Kellanved
                }
2431 5626 acydburn
        }
2432 6459 acydburn
        else if ($url[0] == '/')
2433 5626 acydburn
        {
2434 5626 acydburn
                // Absolute uri, prepend direct url...
2435 5627 acydburn
                $url = generate_board_url(true) . $url;
2436 5626 acydburn
        }
2437 5626 acydburn
        else
2438 5626 acydburn
        {
2439 5626 acydburn
                // Relative uri
2440 5626 acydburn
                $pathinfo = pathinfo($url);
2441 5626 acydburn
2442 10880 git-gate
                if (!$disable_cd_check && !file_exists($pathinfo['dirname'] . '/'))
2443 10536 jelly_doughnut
                {
2444 10536 jelly_doughnut
                        $url = str_replace('../', '', $url);
2445 10536 jelly_doughnut
                        $pathinfo = pathinfo($url);
2446 10536 jelly_doughnut
2447 10880 git-gate
                        if (!file_exists($pathinfo['dirname'] . '/'))
2448 10536 jelly_doughnut
                        {
2449 10536 jelly_doughnut
                                // fallback to "last known user page"
2450 10583 git-gate
                                // at least this way we know the user does not leave the phpBB root
2451 10536 jelly_doughnut
                                $url = generate_board_url() . '/' . $user->page['page'];
2452 10583 git-gate
                                $failover_flag = true;
2453 10536 jelly_doughnut
                        }
2454 10536 jelly_doughnut
                }
2455 10536 jelly_doughnut
2456 10583 git-gate
                if (!$failover_flag)
2457 5626 acydburn
                {
2458 10583 git-gate
                        // Is the uri pointing to the current directory?
2459 10583 git-gate
                        if ($pathinfo['dirname'] == '.')
2460 7216 acydburn
                        {
2461 10583 git-gate
                                $url = str_replace('./', '', $url);
2462 7216 acydburn
2463 10583 git-gate
                                // Strip / from the beginning
2464 10583 git-gate
                                if ($url && substr($url, 0, 1) == '/')
2465 10583 git-gate
                                {
2466 10583 git-gate
                                        $url = substr($url, 1);
2467 10583 git-gate
                                }
2468 10583 git-gate
2469 10583 git-gate
                                if ($user->page['page_dir'])
2470 10583 git-gate
                                {
2471 10583 git-gate
                                        $url = generate_board_url() . '/' . $user->page['page_dir'] . '/' . $url;
2472 10583 git-gate
                                }
2473 10583 git-gate
                                else
2474 10583 git-gate
                                {
2475 10583 git-gate
                                        $url = generate_board_url() . '/' . $url;
2476 10583 git-gate
                                }
2477 5745 acydburn
                        }
2478 5745 acydburn
                        else
2479 5745 acydburn
                        {
2480 10583 git-gate
                                // Used ./ before, but $phpbb_root_path is working better with urls within another root path
2481 10583 git-gate
                                $root_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($phpbb_root_path)));
2482 10583 git-gate
                                $page_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($pathinfo['dirname'])));
2483 10583 git-gate
                                $intersection = array_intersect_assoc($root_dirs, $page_dirs);
2484 5626 acydburn
2485 10583 git-gate
                                $root_dirs = array_diff_assoc($root_dirs, $intersection);
2486 10583 git-gate
                                $page_dirs = array_diff_assoc($page_dirs, $intersection);
2487 5626 acydburn
2488 10583 git-gate
                                $dir = str_repeat('../', sizeof($root_dirs)) . implode('/', $page_dirs);
2489 6015 acydburn
2490 10583 git-gate
                                // Strip / from the end
2491 10583 git-gate
                                if ($dir && substr($dir, -1, 1) == '/')
2492 10583 git-gate
                                {
2493 10583 git-gate
                                        $dir = substr($dir, 0, -1);
2494 10583 git-gate
                                }
2495 6015 acydburn
2496 10583 git-gate
                                // Strip / from the beginning
2497 10583 git-gate
                                if ($dir && substr($dir, 0, 1) == '/')
2498 10583 git-gate
                                {
2499 10583 git-gate
                                        $dir = substr($dir, 1);
2500 10583 git-gate
                                }
2501 7216 acydburn
2502 10583 git-gate
                                $url = str_replace($pathinfo['dirname'] . '/', '', $url);
2503 7216 acydburn
2504 10583 git-gate
                                // Strip / from the beginning
2505 10583 git-gate
                                if (substr($url, 0, 1) == '/')
2506 10583 git-gate
                                {
2507 10583 git-gate
                                        $url = substr($url, 1);
2508 10583 git-gate
                                }
2509 10583 git-gate
2510 10583 git-gate
                                $url = (!empty($dir) ? $dir . '/' : '') . $url;
2511 10583 git-gate
                                $url = generate_board_url() . '/' . $url;
2512 7216 acydburn
                        }
2513 5626 acydburn
                }
2514 5626 acydburn
        }
2515 5626 acydburn
2516 6487 acydburn
        // Make sure no linebreaks are there... to prevent http response splitting for PHP < 4.4.2
2517 6508 acydburn
        if (strpos(urldecode($url), "\n") !== false || strpos(urldecode($url), "\r") !== false || strpos($url, ';') !== false)
2518 6487 acydburn
        {
2519 6487 acydburn
                trigger_error('Tried to redirect to potentially insecure url.', E_USER_ERROR);
2520 6487 acydburn
        }
2521 6487 acydburn
2522 8114 acydburn
        // Now, also check the protocol and for a valid url the last time...
2523 8114 acydburn
        $allowed_protocols = array('http', 'https', 'ftp', 'ftps');
2524 8114 acydburn
        $url_parts = parse_url($url);
2525 8114 acydburn
2526 8114 acydburn
        if ($url_parts === false || empty($url_parts['scheme']) || !in_array($url_parts['scheme'], $allowed_protocols))
2527 8114 acydburn
        {
2528 8114 acydburn
                trigger_error('Tried to redirect to potentially insecure url.', E_USER_ERROR);
2529 8114 acydburn
        }
2530 8114 acydburn
2531 6487 acydburn
        if ($return)
2532 6487 acydburn
        {
2533 6487 acydburn
                return $url;
2534 6487 acydburn
        }
2535 6487 acydburn
2536 3284 psotfx
        // Redirect via an HTML form for PITA webservers
2537 3870 psotfx
        if (@preg_match('#Microsoft|WebSTAR|Xitami#', getenv('SERVER_SOFTWARE')))
2538 3161 psotfx
        {
2539 3870 psotfx
                header('Refresh: 0; URL=' . $url);
2540 5023 acydburn
2541 6934 acydburn
                echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
2542 6934 acydburn
                echo '<html xmlns="http://www.w3.org/1999/xhtml" dir="' . $user->lang['DIRECTION'] . '" lang="' . $user->lang['USER_LANG'] . '" xml:lang="' . $user->lang['USER_LANG'] . '">';
2543 6934 acydburn
                echo '<head>';
2544 6934 acydburn
                echo '<meta http-equiv="content-type" content="text/html; charset=utf-8" />';
2545 7052 acydburn
                echo '<meta http-equiv="refresh" content="0; url=' . str_replace('&', '&amp;', $url) . '" />';
2546 6934 acydburn
                echo '<title>' . $user->lang['REDIRECT'] . '</title>';
2547 6934 acydburn
                echo '</head>';
2548 6934 acydburn
                echo '<body>';
2549 7052 acydburn
                echo '<div style="text-align: center;">' . sprintf($user->lang['URL_REDIRECT'], '<a href="' . str_replace('&', '&amp;', $url) . '">', '</a>') . '</div>';
2550 6934 acydburn
                echo '</body>';
2551 6934 acydburn
                echo '</html>';
2552 6934 acydburn
2553 3284 psotfx
                exit;
2554 3161 psotfx
        }
2555 3284 psotfx
2556 3284 psotfx
        // Behave as per HTTP/1.1 spec for others
2557 3870 psotfx
        header('Location: ' . $url);
2558 2948 ludovic_arnaud
        exit;
2559 2948 ludovic_arnaud
}
2560 2948 ludovic_arnaud
2561 5114 acydburn
/**
2562 6015 acydburn
* Re-Apply session id after page reloads
2563 5931 acydburn
*/
2564 5931 acydburn
function reapply_sid($url)
2565 5931 acydburn
{
2566 6015 acydburn
        global $phpEx, $phpbb_root_path;
2567 5931 acydburn
2568 5931 acydburn
        if ($url === "index.$phpEx")
2569 5931 acydburn
        {
2570 6015 acydburn
                return append_sid("index.$phpEx");
2571 5931 acydburn
        }
2572 6015 acydburn
        else if ($url === "{$phpbb_root_path}index.$phpEx")
2573 6015 acydburn
        {
2574 6015 acydburn
                return append_sid("{$phpbb_root_path}index.$phpEx");
2575 6015 acydburn
        }
2576 5931 acydburn
2577 5931 acydburn
        // Remove previously added sid
2578 9648 leviatan21
        if (strpos($url, 'sid=') !== false)
2579 5931 acydburn
        {
2580 9648 leviatan21
                // All kind of links
2581 9648 leviatan21
                $url = preg_replace('/(\?)?(&amp;|&)?sid=[a-z0-9]+/', '', $url);
2582 9668 acydburn
                // if the sid was the first param, make the old second as first ones
2583 9648 leviatan21
                $url = preg_replace("/$phpEx(&amp;|&)+?/", "$phpEx?", $url);
2584 5931 acydburn
        }
2585 5931 acydburn
2586 6015 acydburn
        return append_sid($url);
2587 5931 acydburn
}
2588 5931 acydburn
2589 5931 acydburn
/**
2590 5902 acydburn
* Returns url from the session/current page with an re-appended SID with optionally stripping vars from the url
2591 5902 acydburn
*/
2592 5902 acydburn
function build_url($strip_vars = false)
2593 5902 acydburn
{
2594 6015 acydburn
        global $user, $phpbb_root_path;
2595 5902 acydburn
2596 5902 acydburn
        // Append SID
2597 8098 acydburn
        $redirect = append_sid($user->page['page'], false, false);
2598 5902 acydburn
2599 6022 acydburn
        // Add delimiter if not there...
2600 6022 acydburn
        if (strpos($redirect, '?') === false)
2601 6022 acydburn
        {
2602 6022 acydburn
                $redirect .= '?';
2603 6022 acydburn
        }
2604 6022 acydburn
2605 5902 acydburn
        // Strip vars...
2606 5905 acydburn
        if ($strip_vars !== false && strpos($redirect, '?') !== false)
2607 5902 acydburn
        {
2608 5902 acydburn
                if (!is_array($strip_vars))
2609 5902 acydburn
                {
2610 5902 acydburn
                        $strip_vars = array($strip_vars);
2611 5902 acydburn
                }
2612 5902 acydburn
2613 5905 acydburn
                $query = $_query = array();
2614 6476 acydburn
2615 6476 acydburn
                $args = substr($redirect, strpos($redirect, '?') + 1);
2616 6476 acydburn
                $args = ($args) ? explode('&', $args) : array();
2617 5905 acydburn
                $redirect = substr($redirect, 0, strpos($redirect, '?'));
2618 5905 acydburn
2619 6476 acydburn
                foreach ($args as $argument)
2620 6476 acydburn
                {
2621 6476 acydburn
                        $arguments = explode('=', $argument);
2622 6476 acydburn
                        $key = $arguments[0];
2623 6476 acydburn
                        unset($arguments[0]);
2624 6476 acydburn
2625 10731 git-gate
                        if ($key === '')
2626 10731 git-gate
                        {
2627 10731 git-gate
                                continue;
2628 10731 git-gate
                        }
2629 10731 git-gate
2630 6476 acydburn
                        $query[$key] = implode('=', $arguments);
2631 6476 acydburn
                }
2632 6476 acydburn
2633 5905 acydburn
                // Strip the vars off
2634 5905 acydburn
                foreach ($strip_vars as $strip)
2635 5902 acydburn
                {
2636 5905 acydburn
                        if (isset($query[$strip]))
2637 5902 acydburn
                        {
2638 5905 acydburn
                                unset($query[$strip]);
2639 5902 acydburn
                        }
2640 5902 acydburn
                }
2641 8348 acydburn
2642 6476 acydburn
                // Glue the remaining parts together... already urlencoded
2643 5905 acydburn
                foreach ($query as $key => $value)
2644 5905 acydburn
                {
2645 5905 acydburn
                        $_query[] = $key . '=' . $value;
2646 5905 acydburn
                }
2647 5905 acydburn
                $query = implode('&', $_query);
2648 5905 acydburn
2649 5905 acydburn
                $redirect .= ($query) ? '?' . $query : '';
2650 5902 acydburn
        }
2651 5902 acydburn
2652 9907 acydburn
        // We need to be cautious here.
2653 9907 acydburn
        // On some situations, the redirect path is an absolute URL, sometimes a relative path
2654 9907 acydburn
        // For a relative path, let's prefix it with $phpbb_root_path to point to the correct location,
2655 9907 acydburn
        // else we use the URL directly.
2656 9907 acydburn
        $url_parts = @parse_url($redirect);
2657 9907 acydburn
2658 9907 acydburn
        // URL
2659 9907 acydburn
        if ($url_parts !== false && !empty($url_parts['scheme']) && !empty($url_parts['host']))
2660 9907 acydburn
        {
2661 9907 acydburn
                return str_replace('&', '&amp;', $redirect);
2662 9907 acydburn
        }
2663 9907 acydburn
2664 5902 acydburn
        return $phpbb_root_path . str_replace('&', '&amp;', $redirect);
2665 5902 acydburn
}
2666 5902 acydburn
2667 5902 acydburn
/**
2668 5114 acydburn
* Meta refresh assignment
2669 9153 acydburn
* Adds META template variable with meta http tag.
2670 9153 acydburn
*
2671 9153 acydburn
* @param int $time Time in seconds for meta refresh tag
2672 9153 acydburn
* @param string $url URL to redirect to. The url will go through redirect() first before the template variable is assigned
2673 9153 acydburn
* @param bool $disable_cd_check If true, meta_refresh() will redirect to an external domain. If false, the redirect point to the boards url if it does not match the current domain. Default is false.
2674 5114 acydburn
*/
2675 9153 acydburn
function meta_refresh($time, $url, $disable_cd_check = false)
2676 3953 psotfx
{
2677 3953 psotfx
        global $template;
2678 2983 psotfx
2679 9153 acydburn
        $url = redirect($url, true, $disable_cd_check);
2680 8611 Kellanved
        $url = str_replace('&', '&amp;', $url);
2681 6487 acydburn
2682 7052 acydburn
        // For XHTML compatibility we change back & to &amp;
2683 3953 psotfx
        $template->assign_vars(array(
2684 8611 Kellanved
                'META' => '<meta http-equiv="refresh" content="' . $time . ';url=' . $url . '" />')
2685 3953 psotfx
        );
2686 8636 acydburn
2687 8611 Kellanved
        return $url;
2688 3953 psotfx
}
2689 3953 psotfx
2690 10664 git-gate
/**
2691 10664 git-gate
* Outputs correct status line header.
2692 10664 git-gate
*
2693 10664 git-gate
* Depending on php sapi one of the two following forms is used:
2694 10664 git-gate
*
2695 10664 git-gate
* Status: 404 Not Found
2696 10664 git-gate
*
2697 10664 git-gate
* HTTP/1.x 404 Not Found
2698 10664 git-gate
*
2699 10664 git-gate
* HTTP version is taken from HTTP_VERSION environment variable,
2700 10664 git-gate
* and defaults to 1.0.
2701 10664 git-gate
*
2702 10664 git-gate
* Sample usage:
2703 10664 git-gate
*
2704 10664 git-gate
* send_status_line(404, 'Not Found');
2705 10664 git-gate
*
2706 10664 git-gate
* @param int $code HTTP status code
2707 10664 git-gate
* @param string $message Message for the status code
2708 10664 git-gate
* @return void
2709 10664 git-gate
*/
2710 10664 git-gate
function send_status_line($code, $message)
2711 10664 git-gate
{
2712 10664 git-gate
        if (substr(strtolower(@php_sapi_name()), 0, 3) === 'cgi')
2713 10664 git-gate
        {
2714 10664 git-gate
                // in theory, we shouldn't need that due to php doing it. Reality offers a differing opinion, though
2715 10664 git-gate
                header("Status: $code $message", true, $code);
2716 10664 git-gate
        }
2717 10664 git-gate
        else
2718 10664 git-gate
        {
2719 10959 git-gate
                if (!empty($_SERVER['SERVER_PROTOCOL']))
2720 10664 git-gate
                {
2721 10959 git-gate
                        $version = $_SERVER['SERVER_PROTOCOL'];
2722 10959 git-gate
                }
2723 10664 git-gate
                else
2724 10664 git-gate
                {
2725 10664 git-gate
                        $version = 'HTTP/1.0';
2726 10664 git-gate
                }
2727 10664 git-gate
                header("$version $code $message", true, $code);
2728 10664 git-gate
        }
2729 10664 git-gate
}
2730 10664 git-gate
2731 8120 kellanved
//Form validation
2732 8120 kellanved
2733 8775 Kellanved
2734 8120 kellanved
/**
2735 8775 Kellanved
* Add a secret hash   for use in links/GET requests
2736 8778 Kellanved
* @param string  $link_name The name of the link; has to match the name used in check_link_hash, otherwise no restrictions apply
2737 8778 Kellanved
* @return string the hash
2738 8775 Kellanved
2739 8775 Kellanved
*/
2740 8775 Kellanved
function generate_link_hash($link_name)
2741 8775 Kellanved
{
2742 8775 Kellanved
        global $user;
2743 8801 acydburn
2744 8775 Kellanved
        if (!isset($user->data["hash_$link_name"]))
2745 8775 Kellanved
        {
2746 8775 Kellanved
                $user->data["hash_$link_name"] = substr(sha1($user->data['user_form_salt'] . $link_name), 0, 8);
2747 8775 Kellanved
        }
2748 8801 acydburn
2749 8775 Kellanved
        return $user->data["hash_$link_name"];
2750 8775 Kellanved
}
2751 8775 Kellanved
2752 8775 Kellanved
2753 8775 Kellanved
/**
2754 8775 Kellanved
* checks a link hash - for GET requests
2755 8783 acydburn
* @param string $token the submitted token
2756 8778 Kellanved
* @param string $link_name The name of the link
2757 8775 Kellanved
* @return boolean true if all is fine
2758 8775 Kellanved
*/
2759 8775 Kellanved
function check_link_hash($token, $link_name)
2760 8775 Kellanved
{
2761 8775 Kellanved
        return $token === generate_link_hash($link_name);
2762 8775 Kellanved
}
2763 8775 Kellanved
2764 8775 Kellanved
/**
2765 8120 kellanved
* Add a secret token to the form (requires the S_FORM_TOKEN template variable)
2766 8120 kellanved
* @param string  $form_name The name of the form; has to match the name used in check_form_key, otherwise no restrictions apply
2767 8120 kellanved
*/
2768 8120 kellanved
function add_form_key($form_name)
2769 8120 kellanved
{
2770 8156 kellanved
        global $config, $template, $user;
2771 8801 acydburn
2772 8120 kellanved
        $now = time();
2773 8156 kellanved
        $token_sid = ($user->data['user_id'] == ANONYMOUS && !empty($config['form_token_sid_guests'])) ? $user->session_id : '';
2774 8156 kellanved
        $token = sha1($now . $user->data['user_form_salt'] . $form_name . $token_sid);
2775 8120 kellanved
2776 8120 kellanved
        $s_fields = build_hidden_fields(array(
2777 8801 acydburn
                'creation_time' => $now,
2778 8801 acydburn
                'form_token'        => $token,
2779 8120 kellanved
        ));
2780 8801 acydburn
2781 8120 kellanved
        $template->assign_vars(array(
2782 8801 acydburn
                'S_FORM_TOKEN'        => $s_fields,
2783 8120 kellanved
        ));
2784 8120 kellanved
}
2785 8120 kellanved
2786 8120 kellanved
/**
2787 8120 kellanved
* Check the form key. Required for all altering actions not secured by confirm_box
2788 8120 kellanved
* @param string  $form_name The name of the form; has to match the name used in add_form_key, otherwise no restrictions apply
2789 8120 kellanved
* @param int $timespan The maximum acceptable age for a submitted form in seconds. Defaults to the config setting.
2790 8120 kellanved
* @param string $return_page The address for the return link
2791 8120 kellanved
* @param bool $trigger If true, the function will triger an error when encountering an invalid form
2792 8120 kellanved
*/
2793 8409 Kellanved
function check_form_key($form_name, $timespan = false, $return_page = '', $trigger = false)
2794 8120 kellanved
{
2795 8156 kellanved
        global $config, $user;
2796 8120 kellanved
2797 8129 acydburn
        if ($timespan === false)
2798 8120 kellanved
        {
2799 8199 kellanved
                // we enforce a minimum value of half a minute here.
2800 8273 kellanved
                $timespan = ($config['form_token_lifetime'] == -1) ? -1 : max(30, $config['form_token_lifetime']);
2801 8120 kellanved
        }
2802 8348 acydburn
2803 8120 kellanved
        if (isset($_POST['creation_time']) && isset($_POST['form_token']))
2804 8120 kellanved
        {
2805 8120 kellanved
                $creation_time        = abs(request_var('creation_time', 0));
2806 8120 kellanved
                $token = request_var('form_token', '');
2807 8120 kellanved
2808 8801 acydburn
                $diff = time() - $creation_time;
2809 8120 kellanved
2810 8801 acydburn
                // If creation_time and the time() now is zero we can assume it was not a human doing this (the check for if ($diff)...
2811 8801 acydburn
                if ($diff && ($diff <= $timespan || $timespan === -1))
2812 8120 kellanved
                {
2813 8156 kellanved
                        $token_sid = ($user->data['user_id'] == ANONYMOUS && !empty($config['form_token_sid_guests'])) ? $user->session_id : '';
2814 8801 acydburn
                        $key = sha1($creation_time . $user->data['user_form_salt'] . $form_name . $token_sid);
2815 8348 acydburn
2816 8120 kellanved
                        if ($key === $token)
2817 8120 kellanved
                        {
2818 8120 kellanved
                                return true;
2819 8120 kellanved
                        }
2820 8120 kellanved
                }
2821 8120 kellanved
        }
2822 8801 acydburn
2823 8120 kellanved
        if ($trigger)
2824 8120 kellanved
        {
2825 8120 kellanved
                trigger_error($user->lang['FORM_INVALID'] . $return_page);
2826 8120 kellanved
        }
2827 8801 acydburn
2828 8120 kellanved
        return false;
2829 8120 kellanved
}
2830 8120 kellanved
2831 5712 acydburn
// Message/Login boxes
2832 5712 acydburn
2833 5114 acydburn
/**
2834 5114 acydburn
* Build Confirm box
2835 5325 acydburn
* @param boolean $check True for checking if confirmed (without any additional parameters) and false for displaying the confirm box
2836 5325 acydburn
* @param string $title Title/Message used for confirm box.
2837 8129 acydburn
*                message text is _CONFIRM appended to title.
2838 8061 acydburn
*                If title cannot be found in user->lang a default one is displayed
2839 8061 acydburn
*                If title_CONFIRM cannot be found in user->lang the text given is used.
2840 5325 acydburn
* @param string $hidden Hidden variables
2841 5325 acydburn
* @param string $html_body Template used for confirm box
2842 5325 acydburn
* @param string $u_action Custom form action
2843 5114 acydburn
*/
2844 5195 acydburn
function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_body.html', $u_action = '')
2845 4883 acydburn
{
2846 4996 acydburn
        global $user, $template, $db;
2847 6015 acydburn
        global $phpEx, $phpbb_root_path;
2848 3953 psotfx
2849 4899 acydburn
        if (isset($_POST['cancel']))
2850 4883 acydburn
        {
2851 4899 acydburn
                return false;
2852 4899 acydburn
        }
2853 4970 psotfx
2854 4899 acydburn
        $confirm = false;
2855 4899 acydburn
        if (isset($_POST['confirm']))
2856 4899 acydburn
        {
2857 4899 acydburn
                // language frontier
2858 8033 acydburn
                if ($_POST['confirm'] === $user->lang['YES'])
2859 4899 acydburn
                {
2860 4899 acydburn
                        $confirm = true;
2861 4899 acydburn
                }
2862 4899 acydburn
        }
2863 4899 acydburn
2864 4899 acydburn
        if ($check && $confirm)
2865 4899 acydburn
        {
2866 9641 acydburn
                $user_id = request_var('confirm_uid', 0);
2867 4899 acydburn
                $session_id = request_var('sess', '');
2868 4957 acydburn
                $confirm_key = request_var('confirm_key', '');
2869 4883 acydburn
2870 5135 acydburn
                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'])
2871 4883 acydburn
                {
2872 4883 acydburn
                        return false;
2873 4883 acydburn
                }
2874 4970 psotfx
2875 5135 acydburn
                // Reset user_last_confirm_key
2876 5135 acydburn
                $sql = 'UPDATE ' . USERS_TABLE . " SET user_last_confirm_key = ''
2877 5135 acydburn
                        WHERE user_id = " . $user->data['user_id'];
2878 5135 acydburn
                $db->sql_query($sql);
2879 5135 acydburn
2880 4883 acydburn
                return true;
2881 4883 acydburn
        }
2882 4899 acydburn
        else if ($check)
2883 4899 acydburn
        {
2884 4899 acydburn
                return false;
2885 4899 acydburn
        }
2886 4970 psotfx
2887 5201 acydburn
        $s_hidden_fields = build_hidden_fields(array(
2888 9641 acydburn
                'confirm_uid'        => $user->data['user_id'],
2889 9641 acydburn
                'sess'                        => $user->session_id,
2890 9641 acydburn
                'sid'                        => $user->session_id,
2891 9641 acydburn
        ));
2892 4883 acydburn
2893 4899 acydburn
        // generate activation key
2894 4957 acydburn
        $confirm_key = gen_rand_string(10);
2895 4899 acydburn
2896 5272 acydburn
        if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin'])
2897 5272 acydburn
        {
2898 5272 acydburn
                adm_page_header((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]);
2899 5272 acydburn
        }
2900 5272 acydburn
        else
2901 5272 acydburn
        {
2902 10000 nickvergessen
                page_header(((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]), false);
2903 5272 acydburn
        }
2904 4883 acydburn
2905 4883 acydburn
        $template->set_filenames(array(
2906 4920 acydburn
                'body' => $html_body)
2907 4883 acydburn
        );
2908 4883 acydburn
2909 4899 acydburn
        // If activation key already exist, we better do not re-use the key (something very strange is going on...)
2910 4957 acydburn
        if (request_var('confirm_key', ''))
2911 4899 acydburn
        {
2912 4996 acydburn
                // This should not occur, therefore we cancel the operation to safe the user
2913 4996 acydburn
                return false;
2914 4899 acydburn
        }
2915 4899 acydburn
2916 6015 acydburn
        // re-add sid / transform & to &amp; for user->page (user->page is always using &)
2917 5595 acydburn
        $use_page = ($u_action) ? $phpbb_root_path . $u_action : $phpbb_root_path . str_replace('&', '&amp;', $user->page['page']);
2918 6015 acydburn
        $u_action = reapply_sid($use_page);
2919 5595 acydburn
        $u_action .= ((strpos($u_action, '?') === false) ? '?' : '&amp;') . 'confirm_key=' . $confirm_key;
2920 4996 acydburn
2921 4883 acydburn
        $template->assign_vars(array(
2922 5195 acydburn
                'MESSAGE_TITLE'                => (!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title],
2923 5195 acydburn
                'MESSAGE_TEXT'                => (!isset($user->lang[$title . '_CONFIRM'])) ? $title : $user->lang[$title . '_CONFIRM'],
2924 4883 acydburn
2925 4899 acydburn
                'YES_VALUE'                        => $user->lang['YES'],
2926 4996 acydburn
                'S_CONFIRM_ACTION'        => $u_action,
2927 4883 acydburn
                'S_HIDDEN_FIELDS'        => $hidden . $s_hidden_fields)
2928 4883 acydburn
        );
2929 4970 psotfx
2930 4957 acydburn
        $sql = 'UPDATE ' . USERS_TABLE . " SET user_last_confirm_key = '" . $db->sql_escape($confirm_key) . "'
2931 4957 acydburn
                WHERE user_id = " . $user->data['user_id'];
2932 4899 acydburn
        $db->sql_query($sql);
2933 4899 acydburn
2934 5272 acydburn
        if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin'])
2935 5272 acydburn
        {
2936 5272 acydburn
                adm_page_footer();
2937 5272 acydburn
        }
2938 5272 acydburn
        else
2939 5272 acydburn
        {
2940 5272 acydburn
                page_footer();
2941 5272 acydburn
        }
2942 4883 acydburn
}
2943 4883 acydburn
2944 5114 acydburn
/**
2945 5114 acydburn
* Generate login box or verify password
2946 5114 acydburn
*/
2947 4970 psotfx
function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = false, $s_display = true)
2948 3650 psotfx
{
2949 8591 Kellanved
        global $db, $user, $template, $auth, $phpEx, $phpbb_root_path, $config;
2950 3650 psotfx
2951 9524 Kellanved
        if (!class_exists('phpbb_captcha_factory'))
2952 9524 Kellanved
        {
2953 9524 Kellanved
                include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx);
2954 9524 Kellanved
        }
2955 9554 acydburn
2956 3650 psotfx
        $err = '';
2957 4970 psotfx
2958 5558 acydburn
        // Make sure user->setup() has been called
2959 5558 acydburn
        if (empty($user->lang))
2960 5558 acydburn
        {
2961 5558 acydburn
                $user->setup();
2962 5558 acydburn
        }
2963 5558 acydburn
2964 5724 acydburn
        // Print out error if user tries to authenticate as an administrator without having the privileges...
2965 5724 acydburn
        if ($admin && !$auth->acl_get('a_'))
2966 5724 acydburn
        {
2967 5724 acydburn
                // Not authd
2968 6135 acydburn
                // anonymous/inactive users are never able to go to the ACP even if they have the relevant permissions
2969 6135 acydburn
                if ($user->data['is_registered'])
2970 6135 acydburn
                {
2971 6135 acydburn
                        add_log('admin', 'LOG_ADMIN_AUTH_FAIL');
2972 6135 acydburn
                }
2973 5724 acydburn
                trigger_error('NO_AUTH_ADMIN');
2974 5724 acydburn
        }
2975 5724 acydburn
2976 3650 psotfx
        if (isset($_POST['login']))
2977 3650 psotfx
        {
2978 8126 acydburn
                // Get credential
2979 8126 acydburn
                if ($admin)
2980 8126 acydburn
                {
2981 8126 acydburn
                        $credential = request_var('credential', '');
2982 8126 acydburn
2983 8126 acydburn
                        if (strspn($credential, 'abcdef0123456789') !== strlen($credential) || strlen($credential) != 32)
2984 8126 acydburn
                        {
2985 8126 acydburn
                                if ($user->data['is_registered'])
2986 8126 acydburn
                                {
2987 8126 acydburn
                                        add_log('admin', 'LOG_ADMIN_AUTH_FAIL');
2988 8126 acydburn
                                }
2989 8126 acydburn
                                trigger_error('NO_AUTH_ADMIN');
2990 8126 acydburn
                        }
2991 8126 acydburn
2992 8126 acydburn
                        $password        = request_var('password_' . $credential, '', true);
2993 8126 acydburn
                }
2994 8126 acydburn
                else
2995 8126 acydburn
                {
2996 8126 acydburn
                        $password        = request_var('password', '', true);
2997 8126 acydburn
                }
2998 8126 acydburn
2999 6494 naderman
                $username        = request_var('username', '', true);
3000 5315 acydburn
                $autologin        = (!empty($_POST['autologin'])) ? true : false;
3001 7151 acydburn
                $viewonline = (!empty($_POST['viewonline'])) ? 0 : 1;
3002 4970 psotfx
                $admin                 = ($admin) ? 1 : 0;
3003 7089 davidmj
                $viewonline = ($admin) ? $user->data['session_viewonline'] : $viewonline;
3004 3650 psotfx
3005 5724 acydburn
                // Check if the supplied username is equal to the one stored within the database if re-authenticating
3006 6494 naderman
                if ($admin && utf8_clean_string($username) != utf8_clean_string($user->data['username']))
3007 5724 acydburn
                {
3008 5724 acydburn
                        // We log the attempt to use a different username...
3009 5724 acydburn
                        add_log('admin', 'LOG_ADMIN_AUTH_FAIL');
3010 5724 acydburn
                        trigger_error('NO_AUTH_ADMIN_USER_DIFFER');
3011 5724 acydburn
                }
3012 6015 acydburn
3013 4970 psotfx
                // If authentication is successful we redirect user to previous page
3014 5622 acydburn
                $result = $auth->login($username, $password, $autologin, $viewonline, $admin);
3015 5622 acydburn
3016 5724 acydburn
                // If admin authentication and login, we will log if it was a success or not...
3017 8129 acydburn
                // We also break the operation on the first non-success login - it could be argued that the user already knows
3018 5724 acydburn
                if ($admin)
3019 3650 psotfx
                {
3020 5724 acydburn
                        if ($result['status'] == LOGIN_SUCCESS)
3021 5114 acydburn
                        {
3022 5724 acydburn
                                add_log('admin', 'LOG_ADMIN_AUTH_SUCCESS');
3023 5114 acydburn
                        }
3024 5724 acydburn
                        else
3025 5724 acydburn
                        {
3026 6135 acydburn
                                // Only log the failed attempt if a real user tried to.
3027 6135 acydburn
                                // anonymous/inactive users are never able to go to the ACP even if they have the relevant permissions
3028 6135 acydburn
                                if ($user->data['is_registered'])
3029 6135 acydburn
                                {
3030 6135 acydburn
                                        add_log('admin', 'LOG_ADMIN_AUTH_FAIL');
3031 6135 acydburn
                                }
3032 5724 acydburn
                        }
3033 5724 acydburn
                }
3034 5558 acydburn
3035 6650 acydburn
                // The result parameter is always an array, holding the relevant information...
3036 5724 acydburn
                if ($result['status'] == LOGIN_SUCCESS)
3037 5724 acydburn
                {
3038 6015 acydburn
                        $redirect = request_var('redirect', "{$phpbb_root_path}index.$phpEx");
3039 5881 acydburn
                        $message = ($l_success) ? $l_success : $user->lang['LOGIN_REDIRECT'];
3040 7242 acydburn
                        $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']);
3041 4578 psotfx
3042 5881 acydburn
                        // append/replace SID (may change during the session for AOL users)
3043 5931 acydburn
                        $redirect = reapply_sid($redirect);
3044 5881 acydburn
3045 6803 acydburn
                        // Special case... the user is effectively banned, but we allow founders to login
3046 6803 acydburn
                        if (defined('IN_CHECK_BAN') && $result['user_row']['user_type'] != USER_FOUNDER)
3047 6803 acydburn
                        {
3048 6803 acydburn
                                return;
3049 6803 acydburn
                        }
3050 6803 acydburn
3051 8611 Kellanved
                        $redirect = meta_refresh(3, $redirect);
3052 5881 acydburn
                        trigger_error($message . '<br /><br />' . sprintf($l_redirect, '<a href="' . $redirect . '">', '</a>'));
3053 3650 psotfx
                }
3054 3650 psotfx
3055 5622 acydburn
                // Something failed, determine what...
3056 5622 acydburn
                if ($result['status'] == LOGIN_BREAK)
3057 3650 psotfx
                {
3058 8350 acydburn
                        trigger_error($result['error_msg']);
3059 3650 psotfx
                }
3060 3650 psotfx
3061 5622 acydburn
                // Special cases... determine
3062 5622 acydburn
                switch ($result['status'])
3063 5622 acydburn
                {
3064 5622 acydburn
                        case LOGIN_ERROR_ATTEMPTS:
3065 5622 acydburn
3066 9524 Kellanved
                                $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']);
3067 9524 Kellanved
                                $captcha->init(CONFIRM_LOGIN);
3068 10094 Kellanved
                                // $captcha->reset();
3069 6015 acydburn
3070 5622 acydburn
                                $template->assign_vars(array(
3071 9609 Kellanved
                                        'CAPTCHA_TEMPLATE'                        => $captcha->get_template(),
3072 5622 acydburn
                                ));
3073 5622 acydburn
3074 5622 acydburn
                                $err = $user->lang[$result['error_msg']];
3075 5622 acydburn
                        break;
3076 5622 acydburn
3077 7076 naderman
                        case LOGIN_ERROR_PASSWORD_CONVERT:
3078 7076 naderman
                                $err = sprintf(
3079 7076 naderman
                                        $user->lang[$result['error_msg']],
3080 7076 naderman
                                        ($config['email_enable']) ? '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=sendpassword') . '">' : '',
3081 7076 naderman
                                        ($config['email_enable']) ? '</a>' : '',
3082 7076 naderman
                                        ($config['board_contact']) ? '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">' : '',
3083 7076 naderman
                                        ($config['board_contact']) ? '</a>' : ''
3084 7076 naderman
                                );
3085 7076 naderman
                        break;
3086 7076 naderman
3087 5622 acydburn
                        // Username, password, etc...
3088 5622 acydburn
                        default:
3089 5622 acydburn
                                $err = $user->lang[$result['error_msg']];
3090 5995 acydburn
3091 5995 acydburn
                                // Assign admin contact to some error messages
3092 5995 acydburn
                                if ($result['error_msg'] == 'LOGIN_ERROR_USERNAME' || $result['error_msg'] == 'LOGIN_ERROR_PASSWORD')
3093 5995 acydburn
                                {
3094 6548 acydburn
                                        $err = (!$config['board_contact']) ? sprintf($user->lang[$result['error_msg']], '', '') : sprintf($user->lang[$result['error_msg']], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>');
3095 5995 acydburn
                                }
3096 8348 acydburn
3097 5622 acydburn
                        break;
3098 5622 acydburn
                }
3099 3650 psotfx
        }
3100 3650 psotfx
3101 8126 acydburn
        // Assign credential for username/password pair
3102 8126 acydburn
        $credential = ($admin) ? md5(unique_id()) : false;
3103 4768 psotfx
3104 8126 acydburn
        $s_hidden_fields = array(
3105 8126 acydburn
                'sid'                => $user->session_id,
3106 8126 acydburn
        );
3107 8126 acydburn
3108 10067 acydburn
        if ($redirect)
3109 10067 acydburn
        {
3110 10067 acydburn
                $s_hidden_fields['redirect'] = $redirect;
3111 10067 acydburn
        }
3112 10067 acydburn
3113 8126 acydburn
        if ($admin)
3114 8126 acydburn
        {
3115 8126 acydburn
                $s_hidden_fields['credential'] = $credential;
3116 8126 acydburn
        }
3117 8126 acydburn
3118 8126 acydburn
        $s_hidden_fields = build_hidden_fields($s_hidden_fields);
3119 8126 acydburn
3120 3650 psotfx
        $template->assign_vars(array(
3121 4970 psotfx
                'LOGIN_ERROR'                => $err,
3122 4970 psotfx
                'LOGIN_EXPLAIN'                => $l_explain,
3123 3650 psotfx
3124 6015 acydburn
                'U_SEND_PASSWORD'                 => ($config['email_enable']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=sendpassword') : '',
3125 10088 terrafrost
                'U_RESEND_ACTIVATION'        => ($config['require_activation'] == USER_ACTIVATION_SELF && $config['email_enable']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=resend_act') : '',
3126 6015 acydburn
                'U_TERMS_USE'                        => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=terms'),
3127 6015 acydburn
                'U_PRIVACY'                                => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy'),
3128 3650 psotfx
3129 4970 psotfx
                'S_DISPLAY_FULL_LOGIN'        => ($s_display) ? true : false,
3130 5724 acydburn
                'S_HIDDEN_FIELDS'                 => $s_hidden_fields,
3131 5724 acydburn
3132 5724 acydburn
                'S_ADMIN_AUTH'                        => $admin,
3133 8126 acydburn
                'USERNAME'                                => ($admin) ? $user->data['username'] : '',
3134 3650 psotfx
3135 8126 acydburn
                'USERNAME_CREDENTIAL'        => 'username',
3136 8126 acydburn
                'PASSWORD_CREDENTIAL'        => ($admin) ? 'password_' . $credential : 'password',
3137 8126 acydburn
        ));
3138 8591 Kellanved
3139 8591 Kellanved
        page_header($user->lang['LOGIN'], false);
3140 8591 Kellanved
3141 8591 Kellanved
        $template->set_filenames(array(
3142 8591 Kellanved
                'body' => 'login_body.html')
3143 8591 Kellanved
        );
3144 6015 acydburn
        make_jumpbox(append_sid("{$phpbb_root_path}viewforum.$phpEx"));
3145 8591 Kellanved
3146 8591 Kellanved
        page_footer();
3147 3650 psotfx
}
3148 3650 psotfx
3149 5114 acydburn
/**
3150 5114 acydburn
* Generate forum login box
3151 5114 acydburn
*/
3152 5902 acydburn
function login_forum_box($forum_data)
3153 3969 psotfx
{
3154 3969 psotfx
        global $db, $config, $user, $template, $phpEx;
3155 3650 psotfx
3156 6552 acydburn
        $password = request_var('password', '', true);
3157 4655 psotfx
3158 4448 ludovic_arnaud
        $sql = 'SELECT forum_id
3159 4970 psotfx
                FROM ' . FORUMS_ACCESS_TABLE . '
3160 3969 psotfx
                WHERE forum_id = ' . $forum_data['forum_id'] . '
3161 3969 psotfx
                        AND user_id = ' . $user->data['user_id'] . "
3162 5902 acydburn
                        AND session_id = '" . $db->sql_escape($user->session_id) . "'";
3163 3969 psotfx
        $result = $db->sql_query($sql);
3164 5902 acydburn
        $row = $db->sql_fetchrow($result);
3165 5902 acydburn
        $db->sql_freeresult($result);
3166 3969 psotfx
3167 5902 acydburn
        if ($row)
3168 3969 psotfx
        {
3169 3969 psotfx
                return true;
3170 3969 psotfx
        }
3171 3969 psotfx
3172 4655 psotfx
        if ($password)
3173 3969 psotfx
        {
3174 4655 psotfx
                // Remove expired authorised sessions
3175 8057 acydburn
                $sql = 'SELECT f.session_id
3176 8057 acydburn
                        FROM ' . FORUMS_ACCESS_TABLE . ' f
3177 8057 acydburn
                        LEFT JOIN ' . SESSIONS_TABLE . ' s ON (f.session_id = s.session_id)
3178 8057 acydburn
                        WHERE s.session_id IS NULL';
3179 4655 psotfx
                $result = $db->sql_query($sql);
3180 4440 psotfx
3181 4655 psotfx
                if ($row = $db->sql_fetchrow($result))
3182 3969 psotfx
                {
3183 4655 psotfx
                        $sql_in = array();
3184 4655 psotfx
                        do
3185 4655 psotfx
                        {
3186 6271 acydburn
                                $sql_in[] = (string) $row['session_id'];
3187 4655 psotfx
                        }
3188 4655 psotfx
                        while ($row = $db->sql_fetchrow($result));
3189 4655 psotfx
3190 5116 acydburn
                        // Remove expired sessions
3191 4655 psotfx
                        $sql = 'DELETE FROM ' . FORUMS_ACCESS_TABLE . '
3192 8057 acydburn
                                WHERE ' . $db->sql_in_set('session_id', $sql_in);
3193 4655 psotfx
                        $db->sql_query($sql);
3194 4655 psotfx
                }
3195 4655 psotfx
                $db->sql_freeresult($result);
3196 4655 psotfx
3197 8143 kellanved
                if (phpbb_check_hash($password, $forum_data['forum_password']))
3198 4655 psotfx
                {
3199 5902 acydburn
                        $sql_ary = array(
3200 5902 acydburn
                                'forum_id'                => (int) $forum_data['forum_id'],
3201 5902 acydburn
                                'user_id'                => (int) $user->data['user_id'],
3202 5902 acydburn
                                'session_id'        => (string) $user->session_id,
3203 5902 acydburn
                        );
3204 3969 psotfx
3205 5902 acydburn
                        $db->sql_query('INSERT INTO ' . FORUMS_ACCESS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
3206 5902 acydburn
3207 3969 psotfx
                        return true;
3208 3969 psotfx
                }
3209 3969 psotfx
3210 3969 psotfx
                $template->assign_var('LOGIN_ERROR', $user->lang['WRONG_PASSWORD']);
3211 3969 psotfx
        }
3212 3969 psotfx
3213 10000 nickvergessen
        page_header($user->lang['LOGIN'], false);
3214 5902 acydburn
3215 6367 acydburn
        $template->assign_vars(array(
3216 10147 acydburn
                'S_LOGIN_ACTION'                => build_url(array('f')),
3217 6367 acydburn
                'S_HIDDEN_FIELDS'                => build_hidden_fields(array('f' => $forum_data['forum_id'])))
3218 6367 acydburn
        );
3219 6367 acydburn
3220 3969 psotfx
        $template->set_filenames(array(
3221 3969 psotfx
                'body' => 'login_forum.html')
3222 3969 psotfx
        );
3223 8348 acydburn
3224 3969 psotfx
        page_footer();
3225 3969 psotfx
}
3226 3969 psotfx
3227 5712 acydburn
// Little helpers
3228 5712 acydburn
3229 5114 acydburn
/**
3230 6139 acydburn
* Little helper for the build_hidden_fields function
3231 6139 acydburn
*/
3232 6584 acydburn
function _build_hidden_fields($key, $value, $specialchar, $stripslashes)
3233 6139 acydburn
{
3234 6139 acydburn
        $hidden_fields = '';
3235 6139 acydburn
3236 6139 acydburn
        if (!is_array($value))
3237 6139 acydburn
        {
3238 6584 acydburn
                $value = ($stripslashes) ? stripslashes($value) : $value;
3239 6584 acydburn
                $value = ($specialchar) ? htmlspecialchars($value, ENT_COMPAT, 'UTF-8') : $value;
3240 6139 acydburn
3241 6139 acydburn
                $hidden_fields .= '<input type="hidden" name="' . $key . '" value="' . $value . '" />' . "\n";
3242 6139 acydburn
        }
3243 6139 acydburn
        else
3244 6139 acydburn
        {
3245 6139 acydburn
                foreach ($value as $_key => $_value)
3246 6139 acydburn
                {
3247 6601 acydburn
                        $_key = ($stripslashes) ? stripslashes($_key) : $_key;
3248 6584 acydburn
                        $_key = ($specialchar) ? htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') : $_key;
3249 6584 acydburn
3250 6584 acydburn
                        $hidden_fields .= _build_hidden_fields($key . '[' . $_key . ']', $_value, $specialchar, $stripslashes);
3251 6139 acydburn
                }
3252 6139 acydburn
        }
3253 6139 acydburn
3254 6139 acydburn
        return $hidden_fields;
3255 6139 acydburn
}
3256 6139 acydburn
3257 6139 acydburn
/**
3258 5195 acydburn
* Build simple hidden fields from array
3259 6584 acydburn
*
3260 6584 acydburn
* @param array $field_ary an array of values to build the hidden field from
3261 6584 acydburn
* @param bool $specialchar if true, keys and values get specialchared
3262 6584 acydburn
* @param bool $stripslashes if true, keys and values get stripslashed
3263 6584 acydburn
*
3264 6584 acydburn
* @return string the hidden fields
3265 5195 acydburn
*/
3266 6584 acydburn
function build_hidden_fields($field_ary, $specialchar = false, $stripslashes = false)
3267 5195 acydburn
{
3268 5195 acydburn
        $s_hidden_fields = '';
3269 5195 acydburn
3270 5195 acydburn
        foreach ($field_ary as $name => $vars)
3271 5195 acydburn
        {
3272 6584 acydburn
                $name = ($stripslashes) ? stripslashes($name) : $name;
3273 6584 acydburn
                $name = ($specialchar) ? htmlspecialchars($name, ENT_COMPAT, 'UTF-8') : $name;
3274 6584 acydburn
3275 6584 acydburn
                $s_hidden_fields .= _build_hidden_fields($name, $vars, $specialchar, $stripslashes);
3276 5195 acydburn
        }
3277 5195 acydburn
3278 5195 acydburn
        return $s_hidden_fields;
3279 5195 acydburn
}
3280 5195 acydburn
3281 5195 acydburn
/**
3282 5372 acydburn
* Parse cfg file
3283 5372 acydburn
*/
3284 5388 acydburn
function parse_cfg_file($filename, $lines = false)
3285 5372 acydburn
{
3286 5372 acydburn
        $parsed_items = array();
3287 5372 acydburn
3288 5388 acydburn
        if ($lines === false)
3289 5388 acydburn
        {
3290 5388 acydburn
                $lines = file($filename);
3291 5388 acydburn
        }
3292 5372 acydburn
3293 5372 acydburn
        foreach ($lines as $line)
3294 5372 acydburn
        {
3295 5372 acydburn
                $line = trim($line);
3296 5372 acydburn
3297 6459 acydburn
                if (!$line || $line[0] == '#' || ($delim_pos = strpos($line, '=')) === false)
3298 5372 acydburn
                {
3299 5372 acydburn
                        continue;
3300 5372 acydburn
                }
3301 5372 acydburn
3302 5372 acydburn
                // Determine first occurrence, since in values the equal sign is allowed
3303 5372 acydburn
                $key = strtolower(trim(substr($line, 0, $delim_pos)));
3304 5372 acydburn
                $value = trim(substr($line, $delim_pos + 1));
3305 5372 acydburn
3306 5372 acydburn
                if (in_array($value, array('off', 'false', '0')))
3307 5372 acydburn
                {
3308 5372 acydburn
                        $value = false;
3309 5372 acydburn
                }
3310 5372 acydburn
                else if (in_array($value, array('on', 'true', '1')))
3311 5372 acydburn
                {
3312 5372 acydburn
                        $value = true;
3313 5372 acydburn
                }
3314 5416 acydburn
                else if (!trim($value))
3315 5416 acydburn
                {
3316 5416 acydburn
                        $value = '';
3317 5416 acydburn
                }
3318 6459 acydburn
                else if (($value[0] == "'" && $value[sizeof($value) - 1] == "'") || ($value[0] == '"' && $value[sizeof($value) - 1] == '"'))
3319 5372 acydburn
                {
3320 5372 acydburn
                        $value = substr($value, 1, sizeof($value)-2);
3321 5372 acydburn
                }
3322 8348 acydburn
3323 5372 acydburn
                $parsed_items[$key] = $value;
3324 5372 acydburn
        }
3325 11671 git-gate
3326 11671 git-gate
        if (isset($parsed_items['inherit_from']) && isset($parsed_items['name']) && $parsed_items['inherit_from'] == $parsed_items['name'])
3327 11671 git-gate
        {
3328 11671 git-gate
                unset($parsed_items['inherit_from']);
3329 11671 git-gate
        }
3330 8348 acydburn
3331 5372 acydburn
        return $parsed_items;
3332 5372 acydburn
}
3333 5372 acydburn
3334 5372 acydburn
/**
3335 5494 acydburn
* Add log event
3336 5494 acydburn
*/
3337 5494 acydburn
function add_log()
3338 5494 acydburn
{
3339 5494 acydburn
        global $db, $user;
3340 5494 acydburn
3341 10003 acydburn
        // In phpBB 3.1.x i want to have logging in a class to be able to control it
3342 10003 acydburn
        // For now, we need a quite hakish approach to circumvent logging for some actions
3343 10003 acydburn
        // @todo implement cleanly
3344 10003 acydburn
        if (!empty($GLOBALS['skip_add_log']))
3345 10003 acydburn
        {
3346 10003 acydburn
                return false;
3347 10003 acydburn
        }
3348 10003 acydburn
3349 5494 acydburn
        $args = func_get_args();
3350 5494 acydburn
3351 5494 acydburn
        $mode                        = array_shift($args);
3352 5494 acydburn
        $reportee_id        = ($mode == 'user') ? intval(array_shift($args)) : '';
3353 5494 acydburn
        $forum_id                = ($mode == 'mod') ? intval(array_shift($args)) : '';
3354 5494 acydburn
        $topic_id                = ($mode == 'mod') ? intval(array_shift($args)) : '';
3355 5494 acydburn
        $action                        = array_shift($args);
3356 5790 acydburn
        $data                        = (!sizeof($args)) ? '' : serialize($args);
3357 5494 acydburn
3358 5494 acydburn
        $sql_ary = array(
3359 5957 acydburn
                'user_id'                => (empty($user->data)) ? ANONYMOUS : $user->data['user_id'],
3360 5494 acydburn
                'log_ip'                => $user->ip,
3361 5494 acydburn
                'log_time'                => time(),
3362 5494 acydburn
                'log_operation'        => $action,
3363 5494 acydburn
                'log_data'                => $data,
3364 5494 acydburn
        );
3365 8348 acydburn
3366 5494 acydburn
        switch ($mode)
3367 5494 acydburn
        {
3368 5494 acydburn
                case 'admin':
3369 5494 acydburn
                        $sql_ary['log_type'] = LOG_ADMIN;
3370 5494 acydburn
                break;
3371 8348 acydburn
3372 5494 acydburn
                case 'mod':
3373 5494 acydburn
                        $sql_ary += array(
3374 5494 acydburn
                                'log_type'        => LOG_MOD,
3375 5494 acydburn
                                'forum_id'        => $forum_id,
3376 5494 acydburn
                                'topic_id'        => $topic_id
3377 5494 acydburn
                        );
3378 5494 acydburn
                break;
3379 5494 acydburn
3380 5494 acydburn
                case 'user':
3381 5494 acydburn
                        $sql_ary += array(
3382 5494 acydburn
                                'log_type'                => LOG_USERS,
3383 5494 acydburn
                                'reportee_id'        => $reportee_id
3384 5494 acydburn
                        );
3385 5494 acydburn
                break;
3386 5494 acydburn
3387 5494 acydburn
                case 'critical':
3388 5494 acydburn
                        $sql_ary['log_type'] = LOG_CRITICAL;
3389 5494 acydburn
                break;
3390 8348 acydburn
3391 5494 acydburn
                default:
3392 5967 acydburn
                        return false;
3393 5494 acydburn
        }
3394 5494 acydburn
3395 5494 acydburn
        $db->sql_query('INSERT INTO ' . LOG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
3396 5631 grahamje
3397 5631 grahamje
        return $db->sql_nextid();
3398 5494 acydburn
}
3399 5494 acydburn
3400 5494 acydburn
/**
3401 11423 git-gate
* Return a nicely formatted backtrace.
3402 11423 git-gate
*
3403 11423 git-gate
* Turns the array returned by debug_backtrace() into HTML markup.
3404 11423 git-gate
* Also filters out absolute paths to phpBB root.
3405 11423 git-gate
*
3406 11423 git-gate
* @return string        HTML markup
3407 5712 acydburn
*/
3408 5712 acydburn
function get_backtrace()
3409 5712 acydburn
{
3410 5712 acydburn
        $output = '<div style="font-family: monospace;">';
3411 5712 acydburn
        $backtrace = debug_backtrace();
3412 5712 acydburn
3413 11423 git-gate
        // We skip the first one, because it only shows this file/function
3414 11423 git-gate
        unset($backtrace[0]);
3415 5712 acydburn
3416 11423 git-gate
        foreach ($backtrace as $trace)
3417 11423 git-gate
        {
3418 5712 acydburn
                // Strip the current directory from path
3419 11423 git-gate
                $trace['file'] = (empty($trace['file'])) ? '(not given by php)' : htmlspecialchars(phpbb_filter_root_path($trace['file']));
3420 11423 git-gate
                $trace['line'] = (empty($trace['line'])) ? '(not given by php)' : $trace['line'];
3421 5973 acydburn
3422 11423 git-gate
                // Only show function arguments for include etc.
3423 11423 git-gate
                // Other parameters may contain sensible information
3424 11423 git-gate
                $argument = '';
3425 11423 git-gate
                if (!empty($trace['args'][0]) && in_array($trace['function'], array('include', 'require', 'include_once', 'require_once')))
3426 5712 acydburn
                {
3427 11423 git-gate
                        $argument = htmlspecialchars(phpbb_filter_root_path($trace['args'][0]));
3428 5973 acydburn
                }
3429 5973 acydburn
3430 5712 acydburn
                $trace['class'] = (!isset($trace['class'])) ? '' : $trace['class'];
3431 5712 acydburn
                $trace['type'] = (!isset($trace['type'])) ? '' : $trace['type'];
3432 5712 acydburn
3433 5712 acydburn
                $output .= '<br />';
3434 11423 git-gate
                $output .= '<b>FILE:</b> ' . $trace['file'] . '<br />';
3435 7143 acydburn
                $output .= '<b>LINE:</b> ' . ((!empty($trace['line'])) ? $trace['line'] : '') . '<br />';
3436 5824 acydburn
3437 11423 git-gate
                $output .= '<b>CALL:</b> ' . htmlspecialchars($trace['class'] . $trace['type'] . $trace['function']);
3438 11423 git-gate
                $output .= '(' . (($argument !== '') ? "'$argument'" : '') . ')<br />';
3439 5712 acydburn
        }
3440 5712 acydburn
        $output .= '</div>';
3441 5712 acydburn
        return $output;
3442 5712 acydburn
}
3443 5712 acydburn
3444 6135 acydburn
/**
3445 6135 acydburn
* This function returns a regular expression pattern for commonly used expressions
3446 6774 naderman
* Use with / as delimiter for email mode and # for url modes
3447 8094 acydburn
* mode can be: email|bbcode_htm|url|url_inline|www_url|www_url_inline|relative_url|relative_url_inline|ipv4|ipv6
3448 6135 acydburn
*/
3449 6135 acydburn
function get_preg_expression($mode)
3450 6135 acydburn
{
3451 6135 acydburn
        switch ($mode)
3452 6135 acydburn
        {
3453 6135 acydburn
                case 'email':
3454 10710 git-gate
                        // Regex written by James Watts and Francisco Jose Martin Moreno
3455 10710 git-gate
                        // http://fightingforalostcause.net/misc/2006/compare-email-regex.php
3456 10710 git-gate
                        return '([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&amp;)+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)';
3457 6135 acydburn
                break;
3458 6364 acydburn
3459 6364 acydburn
                case 'bbcode_htm':
3460 6364 acydburn
                        return array(
3461 6364 acydburn
                                '#<!\-\- e \-\-><a href="mailto:(.*?)">.*?</a><!\-\- e \-\->#',
3462 7424 naderman
                                '#<!\-\- l \-\-><a (?:class="[\w-]+" )?href="(.*?)(?:(&amp;|\?)sid=[0-9a-f]{32})?">.*?</a><!\-\- l \-\->#',
3463 7437 acydburn
                                '#<!\-\- ([mw]) \-\-><a (?:class="[\w-]+" )?href="(.*?)">.*?</a><!\-\- \1 \-\->#',
3464 6364 acydburn
                                '#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/.*? \/><!\-\- s\1 \-\->#',
3465 6364 acydburn
                                '#<!\-\- .*? \-\->#s',
3466 6364 acydburn
                                '#<.*?>#s',
3467 6364 acydburn
                        );
3468 6364 acydburn
                break;
3469 6774 naderman
3470 8094 acydburn
                // Whoa these look impressive!
3471 8094 acydburn
                // The code to generate the following two regular expressions which match valid IPv4/IPv6 addresses
3472 8094 acydburn
                // can be found in the develop directory
3473 8094 acydburn
                case 'ipv4':
3474 8094 acydburn
                        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])$#';
3475 8094 acydburn
                break;
3476 8094 acydburn
3477 8094 acydburn
                case 'ipv6':
3478 10655 git-gate
                        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}:){0,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';
3479 8094 acydburn
                break;
3480 8094 acydburn
3481 6774 naderman
                case 'url':
3482 6886 naderman
                case 'url_inline':
3483 6886 naderman
                        $inline = ($mode == 'url') ? ')' : '';
3484 8246 naderman
                        $scheme = ($mode == 'url') ? '[a-z\d+\-.]' : '[a-z\d+]'; // avoid automatic parsing of "word" in "last word.http://..."
3485 6774 naderman
                        // generated with regex generation file in the develop folder
3486 8246 naderman
                        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})*)?";
3487 6774 naderman
                break;
3488 6774 naderman
3489 6774 naderman
                case 'www_url':
3490 6886 naderman
                case 'www_url_inline':
3491 6886 naderman
                        $inline = ($mode == 'www_url') ? ')' : '';
3492 7428 naderman
                        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})*)?";
3493 6774 naderman
                break;
3494 6774 naderman
3495 6774 naderman
                case 'relative_url':
3496 6886 naderman
                case 'relative_url_inline':
3497 6886 naderman
                        $inline = ($mode == 'relative_url') ? ')' : '';
3498 6886 naderman
                        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})*)?";
3499 6774 naderman
                break;
3500 11535 git-gate
3501 11535 git-gate
                case 'table_prefix':
3502 11535 git-gate
                        return '#^[a-zA-Z][a-zA-Z0-9_]*$#';
3503 11535 git-gate
                break;
3504 6135 acydburn
        }
3505 6135 acydburn
3506 6135 acydburn
        return '';
3507 6135 acydburn
}
3508 6135 acydburn
3509 6224 acydburn
/**
3510 10913 git-gate
* Generate regexp for naughty words censoring
3511 10913 git-gate
* Depends on whether installed PHP version supports unicode properties
3512 10913 git-gate
*
3513 10930 git-gate
* @param string        $word                        word template to be replaced
3514 11187 git-gate
* @param bool        $use_unicode        whether or not to take advantage of PCRE supporting unicode
3515 10913 git-gate
*
3516 10913 git-gate
* @return string $preg_expr                regex to use with word censor
3517 10913 git-gate
*/
3518 10930 git-gate
function get_censor_preg_expression($word, $use_unicode = true)
3519 10913 git-gate
{
3520 10930 git-gate
        static $unicode_support = null;
3521 10913 git-gate
3522 10913 git-gate
        // Check whether PHP version supports unicode properties
3523 10930 git-gate
        if (is_null($unicode_support))
3524 10913 git-gate
        {
3525 10930 git-gate
                $unicode_support = ((version_compare(PHP_VERSION, '5.1.0', '>=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.0', '>='))) && @preg_match('/\p{L}/u', 'a') !== false) ? true : false;
3526 10913 git-gate
        }
3527 10913 git-gate
3528 10930 git-gate
        // Unescape the asterisk to simplify further conversions
3529 10930 git-gate
        $word = str_replace('\*', '*', preg_quote($word, '#'));
3530 10930 git-gate
3531 10930 git-gate
        if ($use_unicode && $unicode_support)
3532 10913 git-gate
        {
3533 10913 git-gate
                // Replace asterisk(s) inside the pattern, at the start and at the end of it with regexes
3534 10913 git-gate
                $word = preg_replace(array('#(?<=[\p{Nd}\p{L}_])\*+(?=[\p{Nd}\p{L}_])#iu', '#^\*+#', '#\*+$#'), array('([\x20]*?|[\p{Nd}\p{L}_-]*?)', '[\p{Nd}\p{L}_-]*?', '[\p{Nd}\p{L}_-]*?'), $word);
3535 10913 git-gate
3536 10913 git-gate
                // Generate the final substitution
3537 10913 git-gate
                $preg_expr = '#(?<![\p{Nd}\p{L}_-])(' . $word . ')(?![\p{Nd}\p{L}_-])#iu';
3538 10913 git-gate
        }
3539 10913 git-gate
        else
3540 10913 git-gate
        {
3541 10930 git-gate
                // Replace the asterisk inside the pattern, at the start and at the end of it with regexes
3542 10930 git-gate
                $word = preg_replace(array('#(?<=\S)\*+(?=\S)#iu', '#^\*+#', '#\*+$#'), array('(\x20*?\S*?)', '\S*?', '\S*?'), $word);
3543 10930 git-gate
3544 10930 git-gate
                // Generate the final substitution
3545 10930 git-gate
                $preg_expr = '#(?<!\S)(' . $word . ')(?!\S)#iu';
3546 10913 git-gate
        }
3547 10913 git-gate
3548 10913 git-gate
        return $preg_expr;
3549 10913 git-gate
}
3550 10913 git-gate
3551 10913 git-gate
/**
3552 7561 naderman
* Returns the first block of the specified IPv6 address and as many additional
3553 7561 naderman
* ones as specified in the length paramater.
3554 7559 naderman
* If length is zero, then an empty string is returned.
3555 7561 naderman
* If length is greater than 3 the complete IP will be returned
3556 7559 naderman
*/
3557 7559 naderman
function short_ipv6($ip, $length)
3558 7559 naderman
{
3559 7559 naderman
        if ($length < 1)
3560 7559 naderman
        {
3561 7559 naderman
                return '';
3562 7559 naderman
        }
3563 7559 naderman
3564 7559 naderman
        // extend IPv6 addresses
3565 7559 naderman
        $blocks = substr_count($ip, ':') + 1;
3566 7559 naderman
        if ($blocks < 9)
3567 7559 naderman
        {
3568 7559 naderman
                $ip = str_replace('::', ':' . str_repeat('0000:', 9 - $blocks), $ip);
3569 7559 naderman
        }
3570 7559 naderman
        if ($ip[0] == ':')
3571 7559 naderman
        {
3572 7559 naderman
                $ip = '0000' . $ip;
3573 7559 naderman
        }
3574 7561 naderman
        if ($length < 4)
3575 7561 naderman
        {
3576 7561 naderman
                $ip = implode(':', array_slice(explode(':', $ip), 0, 1 + $length));
3577 7561 naderman
        }
3578 7559 naderman
3579 7559 naderman
        return $ip;
3580 7559 naderman
}
3581 7559 naderman
3582 7559 naderman
/**
3583 6415 acydburn
* Wrapper for php's checkdnsrr function.
3584 6415 acydburn
*
3585 10737 git-gate
* @param string $host        Fully-Qualified Domain Name
3586 10737 git-gate
* @param string $type        Resource record type to lookup
3587 10737 git-gate
*                                                Supported types are: MX (default), A, AAAA, NS, TXT, CNAME
3588 10737 git-gate
*                                                Other types may work or may not work
3589 8129 acydburn
*
3590 10737 git-gate
* @return mixed                true if entry found,
3591 10737 git-gate
*                                        false if entry not found,
3592 10737 git-gate
*                                        null if this function is not supported by this environment
3593 10737 git-gate
*
3594 10737 git-gate
* Since null can also be returned, you probably want to compare the result
3595 10737 git-gate
* with === true or === false,
3596 10737 git-gate
*
3597 10737 git-gate
* @author bantu
3598 6414 acydburn
*/
3599 10737 git-gate
function phpbb_checkdnsrr($host, $type = 'MX')
3600 6414 acydburn
{
3601 10737 git-gate
        // The dot indicates to search the DNS root (helps those having DNS prefixes on the same domain)
3602 10737 git-gate
        if (substr($host, -1) == '.')
3603 10737 git-gate
        {
3604 10737 git-gate
                $host_fqdn = $host;
3605 10737 git-gate
                $host = substr($host, 0, -1);
3606 10737 git-gate
        }
3607 10737 git-gate
        else
3608 10737 git-gate
        {
3609 10737 git-gate
                $host_fqdn = $host . '.';
3610 10737 git-gate
        }
3611 10737 git-gate
        // $host                has format        some.host.example.com
3612 10737 git-gate
        // $host_fqdn        has format        some.host.example.com.
3613 6414 acydburn
3614 10737 git-gate
        // If we're looking for an A record we can use gethostbyname()
3615 10737 git-gate
        if ($type == 'A' && function_exists('gethostbyname'))
3616 6414 acydburn
        {
3617 10737 git-gate
                return (@gethostbyname($host_fqdn) == $host_fqdn) ? false : true;
3618 10612 git-gate
        }
3619 10737 git-gate
3620 10737 git-gate
        // checkdnsrr() is available on Windows since PHP 5.3,
3621 10737 git-gate
        // but until 5.3.3 it only works for MX records
3622 10737 git-gate
        // See: http://bugs.php.net/bug.php?id=51844
3623 10737 git-gate
3624 11187 git-gate
        // Call checkdnsrr() if
3625 10737 git-gate
        // we're looking for an MX record or
3626 10737 git-gate
        // we're not on Windows or
3627 10737 git-gate
        // we're running a PHP version where #51844 has been fixed
3628 10737 git-gate
3629 10737 git-gate
        // checkdnsrr() supports AAAA since 5.0.0
3630 10737 git-gate
        // checkdnsrr() supports TXT since 5.2.4
3631 10737 git-gate
        if (
3632 10737 git-gate
                ($type == 'MX' || DIRECTORY_SEPARATOR != '\\' || version_compare(PHP_VERSION, '5.3.3', '>=')) &&
3633 10737 git-gate
                ($type != 'AAAA' || version_compare(PHP_VERSION, '5.0.0', '>=')) &&
3634 10737 git-gate
                ($type != 'TXT' || version_compare(PHP_VERSION, '5.2.4', '>=')) &&
3635 10737 git-gate
                function_exists('checkdnsrr')
3636 10737 git-gate
        )
3637 10612 git-gate
        {
3638 10737 git-gate
                return checkdnsrr($host_fqdn, $type);
3639 10737 git-gate
        }
3640 6414 acydburn
3641 10737 git-gate
        // dns_get_record() is available since PHP 5; since PHP 5.3 also on Windows,
3642 10737 git-gate
        // but on Windows it does not work reliable for AAAA records before PHP 5.3.1
3643 10737 git-gate
3644 11187 git-gate
        // Call dns_get_record() if
3645 10737 git-gate
        // we're not looking for an AAAA record or
3646 10737 git-gate
        // we're not on Windows or
3647 10737 git-gate
        // we're running a PHP version where AAAA lookups work reliable
3648 10737 git-gate
        if (
3649 10737 git-gate
                ($type != 'AAAA' || DIRECTORY_SEPARATOR != '\\' || version_compare(PHP_VERSION, '5.3.1', '>=')) &&
3650 10737 git-gate
                function_exists('dns_get_record')
3651 10737 git-gate
        )
3652 10737 git-gate
        {
3653 10737 git-gate
                // dns_get_record() expects an integer as second parameter
3654 10737 git-gate
                // We have to convert the string $type to the corresponding integer constant.
3655 10737 git-gate
                $type_constant = 'DNS_' . $type;
3656 10737 git-gate
                $type_param = (defined($type_constant)) ? constant($type_constant) : DNS_ANY;
3657 10737 git-gate
3658 10737 git-gate
                // dns_get_record() might throw E_WARNING and return false for records that do not exist
3659 10737 git-gate
                $resultset = @dns_get_record($host_fqdn, $type_param);
3660 10737 git-gate
3661 10737 git-gate
                if (empty($resultset) || !is_array($resultset))
3662 10737 git-gate
                {
3663 10737 git-gate
                        return false;
3664 10737 git-gate
                }
3665 10737 git-gate
                else if ($type_param == DNS_ANY)
3666 10737 git-gate
                {
3667 10737 git-gate
                        // $resultset is a non-empty array
3668 10737 git-gate
                        return true;
3669 10737 git-gate
                }
3670 10737 git-gate
3671 10737 git-gate
                foreach ($resultset as $result)
3672 10737 git-gate
                {
3673 10737 git-gate
                        if (
3674 11187 git-gate
                                isset($result['host']) && $result['host'] == $host &&
3675 10737 git-gate
                                isset($result['type']) && $result['type'] == $type
3676 10737 git-gate
                        )
3677 10737 git-gate
                        {
3678 10737 git-gate
                                return true;
3679 10737 git-gate
                        }
3680 10737 git-gate
                }
3681 10737 git-gate
3682 10737 git-gate
                return false;
3683 10737 git-gate
        }
3684 10737 git-gate
3685 10737 git-gate
        // If we're on Windows we can still try to call nslookup via exec() as a last resort
3686 10737 git-gate
        if (DIRECTORY_SEPARATOR == '\\' && function_exists('exec'))
3687 10737 git-gate
        {
3688 10737 git-gate
                @exec('nslookup -type=' . escapeshellarg($type) . ' ' . escapeshellarg($host_fqdn), $output);
3689 10737 git-gate
3690 6584 acydburn
                // If output is empty, the nslookup failed
3691 6584 acydburn
                if (empty($output))
3692 6584 acydburn
                {
3693 6584 acydburn
                        return NULL;
3694 6584 acydburn
                }
3695 6584 acydburn
3696 6414 acydburn
                foreach ($output as $line)
3697 6414 acydburn
                {
3698 10737 git-gate
                        $line = trim($line);
3699 10737 git-gate
3700 10737 git-gate
                        if (empty($line))
3701 6414 acydburn
                        {
3702 6414 acydburn
                                continue;
3703 6414 acydburn
                        }
3704 6414 acydburn
3705 10737 git-gate
                        // Squash tabs and multiple whitespaces to a single whitespace.
3706 10737 git-gate
                        $line = preg_replace('/\s+/', ' ', $line);
3707 10737 git-gate
3708 10737 git-gate
                        switch ($type)
3709 6414 acydburn
                        {
3710 10737 git-gate
                                case 'MX':
3711 10737 git-gate
                                        if (stripos($line, "$host MX") === 0)
3712 10737 git-gate
                                        {
3713 10737 git-gate
                                                return true;
3714 10737 git-gate
                                        }
3715 10737 git-gate
                                break;
3716 10737 git-gate
3717 10737 git-gate
                                case 'NS':
3718 10737 git-gate
                                        if (stripos($line, "$host nameserver") === 0)
3719 10737 git-gate
                                        {
3720 10737 git-gate
                                                return true;
3721 10737 git-gate
                                        }
3722 10737 git-gate
                                break;
3723 10737 git-gate
3724 10737 git-gate
                                case 'TXT':
3725 10737 git-gate
                                        if (stripos($line, "$host text") === 0)
3726 10737 git-gate
                                        {
3727 10737 git-gate
                                                return true;
3728 10737 git-gate
                                        }
3729 10737 git-gate
                                break;
3730 10737 git-gate
3731 10737 git-gate
                                case 'CNAME':
3732 10737 git-gate
                                        if (stripos($line, "$host canonical name") === 0)
3733 10737 git-gate
                                        {
3734 10737 git-gate
                                                return true;
3735 10737 git-gate
                                        }
3736 11322 git-gate
                                break;
3737 10737 git-gate
3738 10737 git-gate
                                default:
3739 11322 git-gate
                                case 'AAAA':
3740 11322 git-gate
                                        // AAAA records returned by nslookup on Windows XP/2003 have this format.
3741 11322 git-gate
                                        // Later Windows versions use the A record format below for AAAA records.
3742 11322 git-gate
                                        if (stripos($line, "$host AAAA IPv6 address") === 0)
3743 11322 git-gate
                                        {
3744 11322 git-gate
                                                return true;
3745 11322 git-gate
                                        }
3746 11322 git-gate
                                // No break
3747 11322 git-gate
3748 10737 git-gate
                                case 'A':
3749 10737 git-gate
                                        if (!empty($host_matches))
3750 10737 git-gate
                                        {
3751 10737 git-gate
                                                // Second line
3752 10737 git-gate
                                                if (stripos($line, "Address: ") === 0)
3753 10737 git-gate
                                                {
3754 10737 git-gate
                                                        return true;
3755 10737 git-gate
                                                }
3756 10737 git-gate
                                                else
3757 10737 git-gate
                                                {
3758 10737 git-gate
                                                        $host_matches = false;
3759 10737 git-gate
                                                }
3760 10737 git-gate
                                        }
3761 10737 git-gate
                                        else if (stripos($line, "Name: $host") === 0)
3762 10737 git-gate
                                        {
3763 10737 git-gate
                                                // First line
3764 10737 git-gate
                                                $host_matches = true;
3765 10737 git-gate
                                        }
3766 10737 git-gate
                                break;
3767 6414 acydburn
                        }
3768 6414 acydburn
                }
3769 6414 acydburn
3770 6414 acydburn
                return false;
3771 6414 acydburn
        }
3772 6414 acydburn
3773 6414 acydburn
        return NULL;
3774 6414 acydburn
}
3775 6414 acydburn
3776 5712 acydburn
// Handler, header and footer
3777 5712 acydburn
3778 5712 acydburn
/**
3779 5114 acydburn
* Error and message handler, call with trigger_error if reqd
3780 5114 acydburn
*/
3781 2942 psotfx
function msg_handler($errno, $msg_text, $errfile, $errline)
3782 2942 psotfx
{
3783 3978 psotfx
        global $cache, $db, $auth, $template, $config, $user;
3784 6729 davidmj
        global $phpEx, $phpbb_root_path, $msg_title, $msg_long_text;
3785 2942 psotfx
3786 8241 acydburn
        // Do not display notices if we suppress them via @
3787 9785 toonarmy
        if (error_reporting() == 0 && $errno != E_USER_ERROR && $errno != E_USER_WARNING && $errno != E_USER_NOTICE)
3788 8241 acydburn
        {
3789 8241 acydburn
                return;
3790 8241 acydburn
        }
3791 8241 acydburn
3792 5556 acydburn
        // Message handler is stripping text. In case we need it, we are possible to define long text...
3793 5556 acydburn
        if (isset($msg_long_text) && $msg_long_text && !$msg_text)
3794 5556 acydburn
        {
3795 5556 acydburn
                $msg_text = $msg_long_text;
3796 5556 acydburn
        }
3797 5556 acydburn
3798 9776 aptx
        if (!defined('E_DEPRECATED'))
3799 9776 aptx
        {
3800 9776 aptx
                define('E_DEPRECATED', 8192);
3801 9776 aptx
        }
3802 9776 aptx
3803 2997 psotfx
        switch ($errno)
3804 2942 psotfx
        {
3805 4899 acydburn
                case E_NOTICE:
3806 4899 acydburn
                case E_WARNING:
3807 5431 acydburn
3808 5882 acydburn
                        // Check the error reporting level and return if the error level does not match
3809 6629 acydburn
                        // If DEBUG is defined the default level is E_ALL
3810 8241 acydburn
                        if (($errno & ((defined('DEBUG')) ? E_ALL : error_reporting())) == 0)
3811 5882 acydburn
                        {
3812 5882 acydburn
                                return;
3813 5882 acydburn
                        }
3814 5882 acydburn
3815 6629 acydburn
                        if (strpos($errfile, 'cache') === false && strpos($errfile, 'template.') === false)
3816 4899 acydburn
                        {
3817 11420 git-gate
                                $errfile = phpbb_filter_root_path($errfile);
3818 11420 git-gate
                                $msg_text = phpbb_filter_root_path($msg_text);
3819 11261 git-gate
                                $error_name = ($errno === E_WARNING) ? 'PHP Warning' : 'PHP Notice';
3820 11261 git-gate
                                echo '<b>[phpBB Debug] ' . $error_name . '</b>: in file <b>' . $errfile . '</b> on line <b>' . $errline . '</b>: <b>' . $msg_text . '</b><br />' . "\n";
3821 5975 acydburn
3822 9920 Kellanved
                                // we are writing an image - the user won't see the debug, so let's place it in the log
3823 9923 Kellanved
                                if (defined('IMAGE_OUTPUT') || defined('IN_CRON'))
3824 9920 Kellanved
                                {
3825 9920 Kellanved
                                        add_log('critical', 'LOG_IMAGE_GENERATION_ERROR', $errfile, $errline, $msg_text);
3826 9920 Kellanved
                                }
3827 9474 acydburn
                                // echo '<br /><br />BACKTRACE<br />' . get_backtrace() . '<br />' . "\n";
3828 4899 acydburn
                        }
3829 6629 acydburn
3830 7234 acydburn
                        return;
3831 7234 acydburn
3832 5431 acydburn
                break;
3833 4899 acydburn
3834 2942 psotfx
                case E_USER_ERROR:
3835 5431 acydburn
3836 7456 acydburn
                        if (!empty($user) && !empty($user->lang))
3837 7456 acydburn
                        {
3838 7456 acydburn
                                $msg_text = (!empty($user->lang[$msg_text])) ? $user->lang[$msg_text] : $msg_text;
3839 7456 acydburn
                                $msg_title = (!isset($msg_title)) ? $user->lang['GENERAL_ERROR'] : ((!empty($user->lang[$msg_title])) ? $user->lang[$msg_title] : $msg_title);
3840 7456 acydburn
3841 7456 acydburn
                                $l_return_index = sprintf($user->lang['RETURN_INDEX'], '<a href="' . $phpbb_root_path . '">', '</a>');
3842 7456 acydburn
                                $l_notify = '';
3843 7456 acydburn
3844 7456 acydburn
                                if (!empty($config['board_contact']))
3845 7456 acydburn
                                {
3846 7456 acydburn
                                        $l_notify = '<p>' . sprintf($user->lang['NOTIFY_ADMIN_EMAIL'], $config['board_contact']) . '</p>';
3847 7456 acydburn
                                }
3848 7456 acydburn
                        }
3849 7456 acydburn
                        else
3850 7456 acydburn
                        {
3851 7456 acydburn
                                $msg_title = 'General Error';
3852 7456 acydburn
                                $l_return_index = '<a href="' . $phpbb_root_path . '">Return to index page</a>';
3853 7456 acydburn
                                $l_notify = '';
3854 7456 acydburn
3855 7456 acydburn
                                if (!empty($config['board_contact']))
3856 7456 acydburn
                                {
3857 7456 acydburn
                                        $l_notify = '<p>Please notify the board administrator or webmaster: <a href="mailto:' . $config['board_contact'] . '">' . $config['board_contact'] . '</a></p>';
3858 7456 acydburn
                                }
3859 7456 acydburn
                        }
3860 9965 acydburn
3861 11660 git-gate
                        $log_text = $msg_text;
3862 11660 git-gate
                        $backtrace = get_backtrace();
3863 11660 git-gate
                        if ($backtrace)
3864 11660 git-gate
                        {
3865 11660 git-gate
                                $log_text .= '<br /><br />BACKTRACE<br />' . $backtrace;
3866 11660 git-gate
                        }
3867 11660 git-gate
3868 11660 git-gate
                        if (defined('IN_INSTALL') || defined('DEBUG_EXTRA') || isset($auth) && $auth->acl_get('a_'))
3869 11660 git-gate
                        {
3870 11660 git-gate
                                $msg_text = $log_text;
3871 11660 git-gate
                        }
3872 11660 git-gate
3873 10518 toonarmy
                        if ((defined('DEBUG') || defined('IN_CRON') || defined('IMAGE_OUTPUT')) && isset($db))
3874 9924 Kellanved
                        {
3875 9924 Kellanved
                                // let's avoid loops
3876 9924 Kellanved
                                $db->sql_return_on_error(true);
3877 11660 git-gate
                                add_log('critical', 'LOG_GENERAL_ERROR', $msg_title, $log_text);
3878 9924 Kellanved
                                $db->sql_return_on_error(false);
3879 9924 Kellanved
                        }
3880 7456 acydburn
3881 10061 acydburn
                        // Do not send 200 OK, but service unavailable on errors
3882 10788 git-gate
                        send_status_line(503, 'Service Unavailable');
3883 10061 acydburn
3884 6149 acydburn
                        garbage_collection();
3885 3969 psotfx
3886 7052 acydburn
                        // Try to not call the adm page data...
3887 7052 acydburn
3888 5491 grahamje
                        echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
3889 5491 grahamje
                        echo '<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">';
3890 5491 grahamje
                        echo '<head>';
3891 5491 grahamje
                        echo '<meta http-equiv="content-type" content="text/html; charset=utf-8" />';
3892 5491 grahamje
                        echo '<title>' . $msg_title . '</title>';
3893 8350 acydburn
                        echo '<style type="text/css">' . "\n" . '/* <![CDATA[ */' . "\n";
3894 7052 acydburn
                        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; } ';
3895 7052 acydburn
                        echo 'a:link, a:active, a:visited { color: #006699; text-decoration: none; } a:hover { color: #DD6900; text-decoration: underline; } ';
3896 7052 acydburn
                        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; } ';
3897 7052 acydburn
                        echo '.panel { margin: 4px 0; background-color: #FFFFFF; border: solid 1px  #A9B8C2; } ';
3898 7053 acydburn
                        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; } ';
3899 7053 acydburn
                        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; } ';
3900 8350 acydburn
                        echo "\n" . '/* ]]> */' . "\n";
3901 7052 acydburn
                        echo '</style>';
3902 5491 grahamje
                        echo '</head>';
3903 5491 grahamje
                        echo '<body id="errorpage">';
3904 5491 grahamje
                        echo '<div id="wrap">';
3905 5491 grahamje
                        echo '        <div id="page-header">';
3906 7456 acydburn
                        echo '                ' . $l_return_index;
3907 5491 grahamje
                        echo '        </div>';
3908 7483 shs
                        echo '        <div id="acp">';
3909 7052 acydburn
                        echo '        <div class="panel">';
3910 7052 acydburn
                        echo '                <div id="content">';
3911 7456 acydburn
                        echo '                        <h1>' . $msg_title . '</h1>';
3912 8348 acydburn
3913 7053 acydburn
                        echo '                        <div>' . $msg_text . '</div>';
3914 8348 acydburn
3915 7456 acydburn
                        echo $l_notify;
3916 7456 acydburn
3917 5430 subblue
                        echo '                </div>';
3918 5430 subblue
                        echo '        </div>';
3919 7483 shs
                        echo '        </div>';
3920 5430 subblue
                        echo '        <div id="page-footer">';
3921 11281 git-gate
                        echo '                Powered by <a href="http://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group';
3922 5430 subblue
                        echo '        </div>';
3923 5430 subblue
                        echo '</div>';
3924 5430 subblue
                        echo '</body>';
3925 5430 subblue
                        echo '</html>';
3926 8348 acydburn
3927 8072 acydburn
                        exit_handler();
3928 8957 acydburn
3929 8957 acydburn
                        // On a fatal error (and E_USER_ERROR *is* fatal) we never want other scripts to continue and force an exit here.
3930 8957 acydburn
                        exit;
3931 5431 acydburn
                break;
3932 2942 psotfx
3933 5877 acydburn
                case E_USER_WARNING:
3934 2942 psotfx
                case E_USER_NOTICE:
3935 5240 acydburn
3936 5240 acydburn
                        define('IN_ERROR_HANDLER', true);
3937 6320 acydburn
3938 3772 psotfx
                        if (empty($user->data))
3939 2997 psotfx
                        {
3940 5240 acydburn
                                $user->session_begin();
3941 2997 psotfx
                        }
3942 5431 acydburn
3943 6000 acydburn
                        // We re-init the auth array to get correct results on login/logout
3944 6000 acydburn
                        $auth->acl($user->data);
3945 6000 acydburn
3946 2997 psotfx
                        if (empty($user->lang))
3947 2997 psotfx
                        {
3948 2997 psotfx
                                $user->setup();
3949 2997 psotfx
                        }
3950 2942 psotfx
3951 10664 git-gate
                        if ($msg_text == 'ERROR_NO_ATTACHMENT' || $msg_text == 'NO_FORUM' || $msg_text == 'NO_TOPIC' || $msg_text == 'NO_USER')
3952 10661 git-gate
                        {
3953 10664 git-gate
                                send_status_line(404, 'Not Found');
3954 10661 git-gate
                        }
3955 10661 git-gate
3956 5319 acydburn
                        $msg_text = (!empty($user->lang[$msg_text])) ? $user->lang[$msg_text] : $msg_text;
3957 5319 acydburn
                        $msg_title = (!isset($msg_title)) ? $user->lang['INFORMATION'] : ((!empty($user->lang[$msg_title])) ? $user->lang[$msg_title] : $msg_title);
3958 5319 acydburn
3959 2997 psotfx
                        if (!defined('HEADER_INC'))
3960 2942 psotfx
                        {
3961 8591 Kellanved
                                if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin'])
3962 2942 psotfx
                                {
3963 5319 acydburn
                                        adm_page_header($msg_title);
3964 2942 psotfx
                                }
3965 2942 psotfx
                                else
3966 2942 psotfx
                                {
3967 10000 nickvergessen
                                        page_header($msg_title, false);
3968 2942 psotfx
                                }
3969 2942 psotfx
                        }
3970 2942 psotfx
3971 5272 acydburn
                        $template->set_filenames(array(
3972 5272 acydburn
                                'body' => 'message_body.html')
3973 5272 acydburn
                        );
3974 2942 psotfx
3975 5272 acydburn
                        $template->assign_vars(array(
3976 6320 acydburn
                                'MESSAGE_TITLE'                => $msg_title,
3977 6320 acydburn
                                'MESSAGE_TEXT'                => $msg_text,
3978 6320 acydburn
                                'S_USER_WARNING'        => ($errno == E_USER_WARNING) ? true : false,
3979 6320 acydburn
                                'S_USER_NOTICE'                => ($errno == E_USER_NOTICE) ? true : false)
3980 5272 acydburn
                        );
3981 2942 psotfx
3982 5272 acydburn
                        // We do not want the cron script to be called on error messages
3983 5272 acydburn
                        define('IN_CRON', true);
3984 8348 acydburn
3985 8591 Kellanved
                        if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin'])
3986 5319 acydburn
                        {
3987 5319 acydburn
                                adm_page_footer();
3988 5319 acydburn
                        }
3989 5319 acydburn
                        else
3990 5319 acydburn
                        {
3991 5319 acydburn
                                page_footer();
3992 5319 acydburn
                        }
3993 5272 acydburn
3994 8072 acydburn
                        exit_handler();
3995 5431 acydburn
                break;
3996 9907 acydburn
3997 9923 Kellanved
                // PHP4 compatibility
3998 9776 aptx
                case E_DEPRECATED:
3999 9776 aptx
                        return true;
4000 9776 aptx
                break;
4001 7218 acydburn
        }
4002 7216 acydburn
4003 7218 acydburn
        // If we notice an error not handled here we pass this back to PHP by returning false
4004 7218 acydburn
        // This may not work for all php versions
4005 7218 acydburn
        return false;
4006 2942 psotfx
}
4007 3969 psotfx
4008 5114 acydburn
/**
4009 11420 git-gate
* Removes absolute path to phpBB root directory from error messages
4010 11420 git-gate
* and converts backslashes to forward slashes.
4011 11420 git-gate
*
4012 11420 git-gate
* @param string $errfile        Absolute file path
4013 11420 git-gate
*                                                        (e.g. /var/www/phpbb3/phpBB/includes/functions.php)
4014 11420 git-gate
*                                                        Please note that if $errfile is outside of the phpBB root,
4015 11420 git-gate
*                                                        the root path will not be found and can not be filtered.
4016 11420 git-gate
* @return string                        Relative file path
4017 11420 git-gate
*                                                        (e.g. /includes/functions.php)
4018 11420 git-gate
*/
4019 11420 git-gate
function phpbb_filter_root_path($errfile)
4020 11420 git-gate
{
4021 11420 git-gate
        static $root_path;
4022 11420 git-gate
4023 11420 git-gate
        if (empty($root_path))
4024 11420 git-gate
        {
4025 11420 git-gate
                $root_path = phpbb_realpath(dirname(__FILE__) . '/../');
4026 11420 git-gate
        }
4027 11420 git-gate
4028 11420 git-gate
        return str_replace(array($root_path, '\\'), array('[ROOT]', '/'), $errfile);
4029 11420 git-gate
}
4030 11420 git-gate
4031 11420 git-gate
/**
4032 8436 Kellanved
* Queries the session table to get information about online guests
4033 9638 nickvergessen
* @param int $item_id Limits the search to the item with this id
4034 9638 nickvergessen
* @param string $item The name of the item which is stored in the session table as session_{$item}_id
4035 8436 Kellanved
* @return int The number of active distinct guest sessions
4036 5114 acydburn
*/
4037 9638 nickvergessen
function obtain_guest_count($item_id = 0, $item = 'forum')
4038 3961 psotfx
{
4039 8436 Kellanved
        global $db, $config;
4040 8636 acydburn
4041 9638 nickvergessen
        if ($item_id)
4042 5319 acydburn
        {
4043 9638 nickvergessen
                $reading_sql = ' AND s.session_' . $item . '_id = ' . (int) $item_id;
4044 8636 acydburn
        }
4045 8436 Kellanved
        else
4046 3961 psotfx
        {
4047 8436 Kellanved
                $reading_sql = '';
4048 3961 psotfx
        }
4049 8636 acydburn
        $time = (time() - (intval($config['load_online_time']) * 60));
4050 3961 psotfx
4051 8475 acydburn
        // Get number of online guests
4052 8475 acydburn
4053 8436 Kellanved
        if ($db->sql_layer === 'sqlite')
4054 3961 psotfx
        {
4055 8436 Kellanved
                $sql = 'SELECT COUNT(session_ip) as num_guests
4056 8436 Kellanved
                        FROM (
4057 8436 Kellanved
                                SELECT DISTINCT s.session_ip
4058 8436 Kellanved
                                FROM ' . SESSIONS_TABLE . ' s
4059 8436 Kellanved
                                WHERE s.session_user_id = ' . ANONYMOUS . '
4060 8436 Kellanved
                                        AND s.session_time >= ' . ($time - ((int) ($time % 60))) .
4061 8436 Kellanved
                                $reading_sql .
4062 8436 Kellanved
                        ')';
4063 3961 psotfx
        }
4064 3961 psotfx
        else
4065 3961 psotfx
        {
4066 8436 Kellanved
                $sql = 'SELECT COUNT(DISTINCT s.session_ip) as num_guests
4067 8436 Kellanved
                        FROM ' . SESSIONS_TABLE . ' s
4068 8436 Kellanved
                        WHERE s.session_user_id = ' . ANONYMOUS . '
4069 8436 Kellanved
                                AND s.session_time >= ' . ($time - ((int) ($time % 60))) .
4070 8436 Kellanved
                        $reading_sql;
4071 3961 psotfx
        }
4072 9308 acydburn
        $result = $db->sql_query($sql);
4073 8436 Kellanved
        $guests_online = (int) $db->sql_fetchfield('num_guests');
4074 8436 Kellanved
        $db->sql_freeresult($result);
4075 8636 acydburn
4076 8436 Kellanved
        return $guests_online;
4077 8436 Kellanved
}
4078 3961 psotfx
4079 8436 Kellanved
/**
4080 8436 Kellanved
* Queries the session table to get information about online users
4081 9638 nickvergessen
* @param int $item_id Limits the search to the item with this id
4082 9638 nickvergessen
* @param string $item The name of the item which is stored in the session table as session_{$item}_id
4083 8436 Kellanved
* @return array An array containing the ids of online, hidden and visible users, as well as statistical info
4084 8436 Kellanved
*/
4085 9638 nickvergessen
function obtain_users_online($item_id = 0, $item = 'forum')
4086 8436 Kellanved
{
4087 8436 Kellanved
        global $db, $config, $user;
4088 8439 acydburn
4089 8438 acydburn
        $reading_sql = '';
4090 9958 Kellanved
        if ($item_id !== 0)
4091 8436 Kellanved
        {
4092 9638 nickvergessen
                $reading_sql = ' AND s.session_' . $item . '_id = ' . (int) $item_id;
4093 8436 Kellanved
        }
4094 8443 acydburn
4095 8436 Kellanved
        $online_users = array(
4096 8436 Kellanved
                'online_users'                        => array(),
4097 8436 Kellanved
                'hidden_users'                        => array(),
4098 8436 Kellanved
                'total_online'                        => 0,
4099 8436 Kellanved
                'visible_online'                => 0,
4100 8436 Kellanved
                'hidden_online'                        => 0,
4101 8436 Kellanved
                'guests_online'                        => 0,
4102 8436 Kellanved
        );
4103 8438 acydburn
4104 8436 Kellanved
        if ($config['load_online_guests'])
4105 8436 Kellanved
        {
4106 9638 nickvergessen
                $online_users['guests_online'] = obtain_guest_count($item_id, $item);
4107 8436 Kellanved
        }
4108 8636 acydburn
4109 8436 Kellanved
        // a little discrete magic to cache this for 30 seconds
4110 8636 acydburn
        $time = (time() - (intval($config['load_online_time']) * 60));
4111 8438 acydburn
4112 8436 Kellanved
        $sql = 'SELECT s.session_user_id, s.session_ip, s.session_viewonline
4113 8436 Kellanved
                FROM ' . SESSIONS_TABLE . ' s
4114 8436 Kellanved
                WHERE s.session_time >= ' . ($time - ((int) ($time % 30))) .
4115 8436 Kellanved
                        $reading_sql .
4116 8436 Kellanved
                ' AND s.session_user_id <> ' . ANONYMOUS;
4117 8636 acydburn
        $result = $db->sql_query($sql);
4118 4717 psotfx
4119 8436 Kellanved
        while ($row = $db->sql_fetchrow($result))
4120 3961 psotfx
        {
4121 8436 Kellanved
                // Skip multiple sessions for one user
4122 8436 Kellanved
                if (!isset($online_users['online_users'][$row['session_user_id']]))
4123 3961 psotfx
                {
4124 8442 acydburn
                        $online_users['online_users'][$row['session_user_id']] = (int) $row['session_user_id'];
4125 8436 Kellanved
                        if ($row['session_viewonline'])
4126 6503 davidmj
                        {
4127 8436 Kellanved
                                $online_users['visible_online']++;
4128 6503 davidmj
                        }
4129 6503 davidmj
                        else
4130 6503 davidmj
                        {
4131 8442 acydburn
                                $online_users['hidden_users'][$row['session_user_id']] = (int) $row['session_user_id'];
4132 8436 Kellanved
                                $online_users['hidden_online']++;
4133 6503 davidmj
                        }
4134 5091 acydburn
                }
4135 8436 Kellanved
        }
4136 8436 Kellanved
        $online_users['total_online'] = $online_users['guests_online'] + $online_users['visible_online'] + $online_users['hidden_online'];
4137 8436 Kellanved
        $db->sql_freeresult($result);
4138 8636 acydburn
4139 8436 Kellanved
        return $online_users;
4140 8436 Kellanved
}
4141 5091 acydburn
4142 8436 Kellanved
/**
4143 8436 Kellanved
* Uses the result of obtain_users_online to generate a localized, readable representation.
4144 8436 Kellanved
* @param mixed $online_users result of obtain_users_online - array with user_id lists for total, hidden and visible users, and statistics
4145 9638 nickvergessen
* @param int $item_id Indicate that the data is limited to one item and not global
4146 9638 nickvergessen
* @param string $item The name of the item which is stored in the session table as session_{$item}_id
4147 8436 Kellanved
* @return array An array containing the string for output to the template
4148 8436 Kellanved
*/
4149 9638 nickvergessen
function obtain_users_online_string($online_users, $item_id = 0, $item = 'forum')
4150 8436 Kellanved
{
4151 8474 Kellanved
        global $config, $db, $user, $auth;
4152 8439 acydburn
4153 8436 Kellanved
        $user_online_link = $online_userlist = '';
4154 9638 nickvergessen
        // Need caps version of $item for language-strings
4155 9638 nickvergessen
        $item_caps = strtoupper($item);
4156 8439 acydburn
4157 8438 acydburn
        if (sizeof($online_users['online_users']))
4158 8436 Kellanved
        {
4159 8442 acydburn
                $sql = 'SELECT username, username_clean, user_id, user_type, user_allow_viewonline, user_colour
4160 8442 acydburn
                                FROM ' . USERS_TABLE . '
4161 8442 acydburn
                                WHERE ' . $db->sql_in_set('user_id', $online_users['online_users']) . '
4162 8442 acydburn
                                ORDER BY username_clean ASC';
4163 8442 acydburn
                $result = $db->sql_query($sql);
4164 3961 psotfx
4165 3961 psotfx
                while ($row = $db->sql_fetchrow($result))
4166 3961 psotfx
                {
4167 8442 acydburn
                        // User is logged in and therefore not a guest
4168 8442 acydburn
                        if ($row['user_id'] != ANONYMOUS)
4169 3961 psotfx
                        {
4170 8436 Kellanved
                                if (isset($online_users['hidden_users'][$row['user_id']]))
4171 3961 psotfx
                                {
4172 8436 Kellanved
                                        $row['username'] = '<em>' . $row['username'] . '</em>';
4173 3961 psotfx
                                }
4174 3961 psotfx
4175 8436 Kellanved
                                if (!isset($online_users['hidden_users'][$row['user_id']]) || $auth->acl_get('u_viewonline'))
4176 3961 psotfx
                                {
4177 8436 Kellanved
                                        $user_online_link = get_username_string(($row['user_type'] <> USER_IGNORE) ? 'full' : 'no_profile', $row['user_id'], $row['username'], $row['user_colour']);
4178 8436 Kellanved
                                        $online_userlist .= ($online_userlist != '') ? ', ' . $user_online_link : $user_online_link;
4179 3961 psotfx
                                }
4180 3961 psotfx
                        }
4181 3961 psotfx
                }
4182 5037 acydburn
                $db->sql_freeresult($result);
4183 8436 Kellanved
        }
4184 3961 psotfx
4185 8436 Kellanved
        if (!$online_userlist)
4186 8436 Kellanved
        {
4187 8436 Kellanved
                $online_userlist = $user->lang['NO_ONLINE_USERS'];
4188 8436 Kellanved
        }
4189 8436 Kellanved
4190 9638 nickvergessen
        if ($item_id === 0)
4191 8436 Kellanved
        {
4192 8436 Kellanved
                $online_userlist = $user->lang['REGISTERED_USERS'] . ' ' . $online_userlist;
4193 8436 Kellanved
        }
4194 8474 Kellanved
        else if ($config['load_online_guests'])
4195 8436 Kellanved
        {
4196 9638 nickvergessen
                $l_online = ($online_users['guests_online'] === 1) ? $user->lang['BROWSING_' . $item_caps . '_GUEST'] : $user->lang['BROWSING_' . $item_caps . '_GUESTS'];
4197 8436 Kellanved
                $online_userlist = sprintf($l_online, $online_userlist, $online_users['guests_online']);
4198 8436 Kellanved
        }
4199 8474 Kellanved
        else
4200 8474 Kellanved
        {
4201 9638 nickvergessen
                $online_userlist = sprintf($user->lang['BROWSING_' . $item_caps], $online_userlist);
4202 8474 Kellanved
        }
4203 8436 Kellanved
        // Build online listing
4204 8436 Kellanved
        $vars_online = array(
4205 8474 Kellanved
                'ONLINE'        => array('total_online', 'l_t_user_s', 0),
4206 8474 Kellanved
                'REG'                => array('visible_online', 'l_r_user_s', !$config['load_online_guests']),
4207 8474 Kellanved
                'HIDDEN'        => array('hidden_online', 'l_h_user_s', $config['load_online_guests']),
4208 8474 Kellanved
                'GUEST'                => array('guests_online', 'l_g_user_s', 0)
4209 8436 Kellanved
        );
4210 8436 Kellanved
4211 8436 Kellanved
        foreach ($vars_online as $l_prefix => $var_ary)
4212 8436 Kellanved
        {
4213 8474 Kellanved
                if ($var_ary[2])
4214 8474 Kellanved
                {
4215 8474 Kellanved
                        $l_suffix = '_AND';
4216 8474 Kellanved
                }
4217 8474 Kellanved
                else
4218 8474 Kellanved
                {
4219 8474 Kellanved
                        $l_suffix = '';
4220 8474 Kellanved
                }
4221 8436 Kellanved
                switch ($online_users[$var_ary[0]])
4222 3961 psotfx
                {
4223 8436 Kellanved
                        case 0:
4224 8474 Kellanved
                                ${$var_ary[1]} = $user->lang[$l_prefix . '_USERS_ZERO_TOTAL' . $l_suffix];
4225 8436 Kellanved
                        break;
4226 8436 Kellanved
4227 8436 Kellanved
                        case 1:
4228 8474 Kellanved
                                ${$var_ary[1]} = $user->lang[$l_prefix . '_USER_TOTAL' . $l_suffix];
4229 8436 Kellanved
                        break;
4230 8436 Kellanved
4231 8436 Kellanved
                        default:
4232 8474 Kellanved
                                ${$var_ary[1]} = $user->lang[$l_prefix . '_USERS_TOTAL' . $l_suffix];
4233 8436 Kellanved
                        break;
4234 3961 psotfx
                }
4235 8436 Kellanved
        }
4236 8436 Kellanved
        unset($vars_online);
4237 3961 psotfx
4238 8436 Kellanved
        $l_online_users = sprintf($l_t_user_s, $online_users['total_online']);
4239 8436 Kellanved
        $l_online_users .= sprintf($l_r_user_s, $online_users['visible_online']);
4240 8436 Kellanved
        $l_online_users .= sprintf($l_h_user_s, $online_users['hidden_online']);
4241 8436 Kellanved
4242 8474 Kellanved
        if ($config['load_online_guests'])
4243 8474 Kellanved
        {
4244 8474 Kellanved
                $l_online_users .= sprintf($l_g_user_s, $online_users['guests_online']);
4245 8474 Kellanved
        }
4246 8474 Kellanved
4247 8474 Kellanved
4248 8474 Kellanved
4249 8436 Kellanved
        return array(
4250 8436 Kellanved
                'online_userlist'        => $online_userlist,
4251 8436 Kellanved
                'l_online_users'        => $l_online_users,
4252 8436 Kellanved
        );
4253 8436 Kellanved
}
4254 8436 Kellanved
4255 9965 acydburn
/**
4256 9965 acydburn
* Get option bitfield from custom data
4257 9965 acydburn
*
4258 9965 acydburn
* @param int        $bit                The bit/value to get
4259 9965 acydburn
* @param int        $data                Current bitfield to check
4260 9965 acydburn
* @return bool        Returns true if value of constant is set in bitfield, else false
4261 9965 acydburn
*/
4262 9965 acydburn
function phpbb_optionget($bit, $data)
4263 9965 acydburn
{
4264 9965 acydburn
        return ($data & 1 << (int) $bit) ? true : false;
4265 9965 acydburn
}
4266 8436 Kellanved
4267 8436 Kellanved
/**
4268 9965 acydburn
* Set option bitfield
4269 9965 acydburn
*
4270 9965 acydburn
* @param int        $bit                The bit/value to set/unset
4271 9965 acydburn
* @param bool        $set                True if option should be set, false if option should be unset.
4272 9965 acydburn
* @param int        $data                Current bitfield to change
4273 9965 acydburn
*
4274 9965 acydburn
* @return int        The new bitfield
4275 9965 acydburn
*/
4276 9965 acydburn
function phpbb_optionset($bit, $set, $data)
4277 9965 acydburn
{
4278 9965 acydburn
        if ($set && !($data & 1 << $bit))
4279 9965 acydburn
        {
4280 9965 acydburn
                $data += 1 << $bit;
4281 9965 acydburn
        }
4282 9965 acydburn
        else if (!$set && ($data & 1 << $bit))
4283 9965 acydburn
        {
4284 9965 acydburn
                $data -= 1 << $bit;
4285 9965 acydburn
        }
4286 9965 acydburn
4287 9965 acydburn
        return $data;
4288 9965 acydburn
}
4289 9965 acydburn
4290 9965 acydburn
/**
4291 10430 bantu
* Login using http authenticate.
4292 10430 bantu
*
4293 10430 bantu
* @param array        $param                Parameter array, see $param_defaults array.
4294 10430 bantu
*
4295 10430 bantu
* @return void
4296 10430 bantu
*/
4297 10430 bantu
function phpbb_http_login($param)
4298 10430 bantu
{
4299 10430 bantu
        global $auth, $user;
4300 10430 bantu
        global $config;
4301 10430 bantu
4302 10430 bantu
        $param_defaults = array(
4303 10430 bantu
                'auth_message'        => '',
4304 10430 bantu
4305 10430 bantu
                'autologin'                => false,
4306 10430 bantu
                'viewonline'        => true,
4307 10430 bantu
                'admin'                        => false,
4308 10430 bantu
        );
4309 10430 bantu
4310 10430 bantu
        // Overwrite default values with passed values
4311 10430 bantu
        $param = array_merge($param_defaults, $param);
4312 10430 bantu
4313 10430 bantu
        // User is already logged in
4314 10430 bantu
        // We will not overwrite his session
4315 10430 bantu
        if (!empty($user->data['is_registered']))
4316 10430 bantu
        {
4317 10430 bantu
                return;
4318 10430 bantu
        }
4319 10430 bantu
4320 10430 bantu
        // $_SERVER keys to check
4321 10430 bantu
        $username_keys = array(
4322 10430 bantu
                'PHP_AUTH_USER',
4323 10430 bantu
                'Authorization',
4324 10430 bantu
                'REMOTE_USER', 'REDIRECT_REMOTE_USER',
4325 10430 bantu
                'HTTP_AUTHORIZATION', 'REDIRECT_HTTP_AUTHORIZATION',
4326 10430 bantu
                'REMOTE_AUTHORIZATION', 'REDIRECT_REMOTE_AUTHORIZATION',
4327 10430 bantu
                'AUTH_USER',
4328 10430 bantu
        );
4329 10430 bantu
4330 10430 bantu
        $password_keys = array(
4331 10430 bantu
                'PHP_AUTH_PW',
4332 10430 bantu
                'REMOTE_PASSWORD',
4333 10430 bantu
                'AUTH_PASSWORD',
4334 10430 bantu
        );
4335 10430 bantu
4336 10430 bantu
        $username = null;
4337 10430 bantu
        foreach ($username_keys as $k)
4338 10430 bantu
        {
4339 10430 bantu
                if (isset($_SERVER[$k]))
4340 10430 bantu
                {
4341 10430 bantu
                        $username = $_SERVER[$k];
4342 10430 bantu
                        break;
4343 10430 bantu
                }
4344 10430 bantu
        }
4345 10430 bantu
4346 10430 bantu
        $password = null;
4347 10430 bantu
        foreach ($password_keys as $k)
4348 10430 bantu
        {
4349 10430 bantu
                if (isset($_SERVER[$k]))
4350 10430 bantu
                {
4351 10430 bantu
                        $password = $_SERVER[$k];
4352 10430 bantu
                        break;
4353 10430 bantu
                }
4354 10430 bantu
        }
4355 10430 bantu
4356 10430 bantu
        // Decode encoded information (IIS, CGI, FastCGI etc.)
4357 10430 bantu
        if (!is_null($username) && is_null($password) && strpos($username, 'Basic ') === 0)
4358 10430 bantu
        {
4359 10430 bantu
                list($username, $password) = explode(':', base64_decode(substr($username, 6)), 2);
4360 11061 git-gate
        }
4361 10430 bantu
4362 10430 bantu
        if (!is_null($username) && !is_null($password))
4363 10430 bantu
        {
4364 10430 bantu
                set_var($username, $username, 'string', true);
4365 10430 bantu
                set_var($password, $password, 'string', true);
4366 10430 bantu
4367 10430 bantu
                $auth_result = $auth->login($username, $password, $param['autologin'], $param['viewonline'], $param['admin']);
4368 10430 bantu
4369 10430 bantu
                if ($auth_result['status'] == LOGIN_SUCCESS)
4370 10430 bantu
                {
4371 10430 bantu
                        return;
4372 10430 bantu
                }
4373 10432 bantu
                else if ($auth_result['status'] == LOGIN_ERROR_ATTEMPTS)
4374 10432 bantu
                {
4375 10788 git-gate
                        send_status_line(401, 'Unauthorized');
4376 10788 git-gate
4377 10432 bantu
                        trigger_error('NOT_AUTHORISED');
4378 10432 bantu
                }
4379 10430 bantu
        }
4380 10430 bantu
4381 10430 bantu
        // Prepend sitename to auth_message
4382 10430 bantu
        $param['auth_message'] = ($param['auth_message'] === '') ? $config['sitename'] : $config['sitename'] . ' - ' . $param['auth_message'];
4383 10430 bantu
4384 10430 bantu
        // We should probably filter out non-ASCII characters - RFC2616
4385 10430 bantu
        $param['auth_message'] = preg_replace('/[\x80-\xFF]/', '?', $param['auth_message']);
4386 10430 bantu
4387 10430 bantu
        header('WWW-Authenticate: Basic realm="' . $param['auth_message'] . '"');
4388 10788 git-gate
        send_status_line(401, 'Unauthorized');
4389 10430 bantu
4390 10430 bantu
        trigger_error('NOT_AUTHORISED');
4391 10430 bantu
}
4392 10430 bantu
4393 10430 bantu
/**
4394 8436 Kellanved
* Generate page header
4395 8436 Kellanved
*/
4396 9991 nickvergessen
function page_header($page_title = '', $display_online_list = true, $item_id = 0, $item = 'forum')
4397 8436 Kellanved
{
4398 11619 git-gate
        global $db, $config, $template, $SID, $_SID, $_EXTRA_URL, $user, $auth, $phpEx, $phpbb_root_path;
4399 8436 Kellanved
4400 8436 Kellanved
        if (defined('HEADER_INC'))
4401 8436 Kellanved
        {
4402 8436 Kellanved
                return;
4403 8436 Kellanved
        }
4404 8436 Kellanved
4405 8436 Kellanved
        define('HEADER_INC', true);
4406 8436 Kellanved
4407 8436 Kellanved
        // gzip_compression
4408 8436 Kellanved
        if ($config['gzip_compress'])
4409 8436 Kellanved
        {
4410 11268 git-gate
                // to avoid partially compressed output resulting in blank pages in
4411 11268 git-gate
                // the browser or error messages, compression is disabled in a few cases:
4412 11268 git-gate
                //
4413 11268 git-gate
                // 1) if headers have already been sent, this indicates plaintext output
4414 11268 git-gate
                //    has been started so further content must not be compressed
4415 11268 git-gate
                // 2) the length of the current output buffer is non-zero. This means
4416 11268 git-gate
                //    there is already some uncompressed content in this output buffer
4417 11268 git-gate
                //    so further output must not be compressed
4418 11268 git-gate
                // 3) if more than one level of output buffering is used because we
4419 11268 git-gate
                //    cannot test all output buffer level content lengths. One level
4420 11268 git-gate
                //    could be caused by php.ini output_buffering. Anything
4421 11268 git-gate
                //    beyond that is manual, so the code wrapping phpBB in output buffering
4422 11268 git-gate
                //    can easily compress the output itself.
4423 11268 git-gate
                //
4424 11268 git-gate
                if (@extension_loaded('zlib') && !headers_sent() && ob_get_level() <= 1 && ob_get_length() == 0)
4425 3961 psotfx
                {
4426 8436 Kellanved
                        ob_start('ob_gzhandler');
4427 3961 psotfx
                }
4428 8436 Kellanved
        }
4429 3961 psotfx
4430 8436 Kellanved
        // Generate logged in/logged out status
4431 8436 Kellanved
        if ($user->data['user_id'] != ANONYMOUS)
4432 8436 Kellanved
        {
4433 8436 Kellanved
                $u_login_logout = append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=logout', true, $user->session_id);
4434 8436 Kellanved
                $l_login_logout = sprintf($user->lang['LOGOUT_USER'], $user->data['username']);
4435 8436 Kellanved
        }
4436 8436 Kellanved
        else
4437 8436 Kellanved
        {
4438 8436 Kellanved
                $u_login_logout = append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login');
4439 8436 Kellanved
                $l_login_logout = $user->lang['LOGIN'];
4440 8436 Kellanved
        }
4441 3961 psotfx
4442 8436 Kellanved
        // Last visit date/time
4443 8436 Kellanved
        $s_last_visit = ($user->data['user_id'] != ANONYMOUS) ? $user->format_date($user->data['session_last_visit']) : '';
4444 8436 Kellanved
4445 8436 Kellanved
        // Get users online list ... if required
4446 10266 nickvergessen
        $l_online_users = $online_userlist = $l_online_record = $l_online_time = '';
4447 8436 Kellanved
4448 8436 Kellanved
        if ($config['load_online'] && $config['load_online_time'] && $display_online_list)
4449 8436 Kellanved
        {
4450 9638 nickvergessen
                /**
4451 9638 nickvergessen
                * Load online data:
4452 9991 nickvergessen
                * For obtaining another session column use $item and $item_id in the function-parameter, whereby the column is session_{$item}_id.
4453 9638 nickvergessen
                */
4454 9991 nickvergessen
                $item_id = max($item_id, 0);
4455 9965 acydburn
4456 9638 nickvergessen
                $online_users = obtain_users_online($item_id, $item);
4457 9638 nickvergessen
                $user_online_strings = obtain_users_online_string($online_users, $item_id, $item);
4458 9638 nickvergessen
4459 8436 Kellanved
                $l_online_users = $user_online_strings['l_online_users'];
4460 8436 Kellanved
                $online_userlist = $user_online_strings['online_userlist'];
4461 8436 Kellanved
                $total_online_users = $online_users['total_online'];
4462 8436 Kellanved
4463 3961 psotfx
                if ($total_online_users > $config['record_online_users'])
4464 3961 psotfx
                {
4465 5315 acydburn
                        set_config('record_online_users', $total_online_users, true);
4466 5315 acydburn
                        set_config('record_online_date', time(), true);
4467 3961 psotfx
                }
4468 3961 psotfx
4469 10266 nickvergessen
                $l_online_record = sprintf($user->lang['RECORD_ONLINE_USERS'], $config['record_online_users'], $user->format_date($config['record_online_date'], false, true));
4470 4717 psotfx
4471 3961 psotfx
                $l_online_time = ($config['load_online_time'] == 1) ? 'VIEW_ONLINE_TIME' : 'VIEW_ONLINE_TIMES';
4472 3961 psotfx
                $l_online_time = sprintf($user->lang[$l_online_time], $config['load_online_time']);
4473 3961 psotfx
        }
4474 3961 psotfx
4475 4899 acydburn
        $l_privmsgs_text = $l_privmsgs_text_unread = '';
4476 4899 acydburn
        $s_privmsg_new = false;
4477 4899 acydburn
4478 5296 acydburn
        // Obtain number of new private messages if user is logged in
4479 8956 acydburn
        if (!empty($user->data['is_registered']))
4480 3961 psotfx
        {
4481 3961 psotfx
                if ($user->data['user_new_privmsg'])
4482 3961 psotfx
                {
4483 4717 psotfx
                        $l_message_new = ($user->data['user_new_privmsg'] == 1) ? $user->lang['NEW_PM'] : $user->lang['NEW_PMS'];
4484 3961 psotfx
                        $l_privmsgs_text = sprintf($l_message_new, $user->data['user_new_privmsg']);
4485 3961 psotfx
4486 4883 acydburn
                        if (!$user->data['user_last_privmsg'] || $user->data['user_last_privmsg'] > $user->data['session_last_visit'])
4487 3961 psotfx
                        {
4488 3969 psotfx
                                $sql = 'UPDATE ' . USERS_TABLE . '
4489 3969 psotfx
                                        SET user_last_privmsg = ' . $user->data['session_last_visit'] . '
4490 3969 psotfx
                                        WHERE user_id = ' . $user->data['user_id'];
4491 3961 psotfx
                                $db->sql_query($sql);
4492 3961 psotfx
4493 4717 psotfx
                                $s_privmsg_new = true;
4494 3961 psotfx
                        }
4495 3961 psotfx
                        else
4496 3961 psotfx
                        {
4497 4717 psotfx
                                $s_privmsg_new = false;
4498 3961 psotfx
                        }
4499 3961 psotfx
                }
4500 3961 psotfx
                else
4501 3961 psotfx
                {
4502 4578 psotfx
                        $l_privmsgs_text = $user->lang['NO_NEW_PM'];
4503 4717 psotfx
                        $s_privmsg_new = false;
4504 3961 psotfx
                }
4505 3961 psotfx
4506 4883 acydburn
                $l_privmsgs_text_unread = '';
4507 4883 acydburn
4508 4883 acydburn
                if ($user->data['user_unread_privmsg'] && $user->data['user_unread_privmsg'] != $user->data['user_new_privmsg'])
4509 3961 psotfx
                {
4510 4578 psotfx
                        $l_message_unread = ($user->data['user_unread_privmsg'] == 1) ? $user->lang['UNREAD_PM'] : $user->lang['UNREAD_PMS'];
4511 3961 psotfx
                        $l_privmsgs_text_unread = sprintf($l_message_unread, $user->data['user_unread_privmsg']);
4512 3961 psotfx
                }
4513 3961 psotfx
        }
4514 3961 psotfx
4515 9575 acydburn
        $forum_id = request_var('f', 0);
4516 9575 acydburn
        $topic_id = request_var('t', 0);
4517 9575 acydburn
4518 9965 acydburn
        $s_feed_news = false;
4519 9965 acydburn
4520 9965 acydburn
        // Get option for news
4521 9965 acydburn
        if ($config['feed_enable'])
4522 9965 acydburn
        {
4523 9965 acydburn
                $sql = 'SELECT forum_id
4524 9965 acydburn
                        FROM ' . FORUMS_TABLE . '
4525 9965 acydburn
                        WHERE ' . $db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0');
4526 9965 acydburn
                $result = $db->sql_query_limit($sql, 1, 0, 600);
4527 9965 acydburn
                $s_feed_news = (int) $db->sql_fetchfield('forum_id');
4528 9965 acydburn
                $db->sql_freeresult($result);
4529 9965 acydburn
        }
4530 9965 acydburn
4531 10008 acydburn
        // Determine board url - we may need it later
4532 10008 acydburn
        $board_url = generate_board_url() . '/';
4533 10010 acydburn
        $web_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? $board_url : $phpbb_root_path;
4534 10008 acydburn
4535 10149 acydburn
        // Which timezone?
4536 10149 acydburn
        $tz = ($user->data['user_id'] != ANONYMOUS) ? strval(doubleval($user->data['user_timezone'])) : strval(doubleval($config['board_timezone']));
4537 10149 acydburn
4538 10149 acydburn
        // Send a proper content-language to the output
4539 10149 acydburn
        $user_lang = $user->lang['USER_LANG'];
4540 10149 acydburn
        if (strpos($user_lang, '-x-') !== false)
4541 10149 acydburn
        {
4542 10149 acydburn
                $user_lang = substr($user_lang, 0, strpos($user_lang, '-x-'));
4543 10149 acydburn
        }
4544 10149 acydburn
4545 11187 git-gate
        $s_search_hidden_fields = array();
4546 11187 git-gate
        if ($_SID)
4547 11187 git-gate
        {
4548 11187 git-gate
                $s_search_hidden_fields['sid'] = $_SID;
4549 11187 git-gate
        }
4550 11187 git-gate
4551 11619 git-gate
        if (!empty($_EXTRA_URL))
4552 11619 git-gate
        {
4553 11619 git-gate
                foreach ($_EXTRA_URL as $url_param)
4554 11619 git-gate
                {
4555 11619 git-gate
                        $url_param = explode('=', $url_param, 2);
4556 11682 git-gate
                        $s_search_hidden_fields[$url_param[0]] = $url_param[1];
4557 11619 git-gate
                }
4558 11619 git-gate
        }
4559 11619 git-gate
4560 6015 acydburn
        // The following assigns all _common_ variables that may be used at any point in a template.
4561 3961 psotfx
        $template->assign_vars(array(
4562 6015 acydburn
                'SITENAME'                                                => $config['sitename'],
4563 6015 acydburn
                'SITE_DESCRIPTION'                                => $config['site_desc'],
4564 6015 acydburn
                'PAGE_TITLE'                                        => $page_title,
4565 5902 acydburn
                'SCRIPT_NAME'                                        => str_replace('.' . $phpEx, '', $user->page['page_name']),
4566 6015 acydburn
                'LAST_VISIT_DATE'                                => sprintf($user->lang['YOU_LAST_VISIT'], $s_last_visit),
4567 7273 davidmj
                'LAST_VISIT_YOU'                                => $s_last_visit,
4568 6015 acydburn
                'CURRENT_TIME'                                        => sprintf($user->lang['CURRENT_TIME'], $user->format_date(time(), false, true)),
4569 6015 acydburn
                'TOTAL_USERS_ONLINE'                        => $l_online_users,
4570 6015 acydburn
                'LOGGED_IN_USER_LIST'                        => $online_userlist,
4571 6015 acydburn
                'RECORD_USERS'                                        => $l_online_record,
4572 6015 acydburn
                'PRIVATE_MESSAGE_INFO'                        => $l_privmsgs_text,
4573 6015 acydburn
                'PRIVATE_MESSAGE_INFO_UNREAD'        => $l_privmsgs_text_unread,
4574 3961 psotfx
4575 7245 acydburn
                'S_USER_NEW_PRIVMSG'                        => $user->data['user_new_privmsg'],
4576 7245 acydburn
                'S_USER_UNREAD_PRIVMSG'                        => $user->data['user_unread_privmsg'],
4577 9636 acydburn
                'S_USER_NEW'                                        => $user->data['user_new'],
4578 7245 acydburn
4579 6015 acydburn
                'SID'                                => $SID,
4580 6015 acydburn
                '_SID'                                => $_SID,
4581 6015 acydburn
                'SESSION_ID'                => $user->session_id,
4582 6015 acydburn
                'ROOT_PATH'                        => $phpbb_root_path,
4583 10008 acydburn
                'BOARD_URL'                        => $board_url,
4584 6015 acydburn
4585 6015 acydburn
                'L_LOGIN_LOGOUT'        => $l_login_logout,
4586 6015 acydburn
                'L_INDEX'                        => $user->lang['FORUM_INDEX'],
4587 4970 psotfx
                'L_ONLINE_EXPLAIN'        => $l_online_time,
4588 3961 psotfx
4589 6015 acydburn
                'U_PRIVATEMSGS'                        => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=inbox'),
4590 6015 acydburn
                'U_RETURN_INBOX'                => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=inbox'),
4591 6015 acydburn
                'U_POPUP_PM'                        => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;mode=popup'),
4592 8099 acydburn
                'UA_POPUP_PM'                        => addslashes(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;mode=popup')),
4593 6015 acydburn
                'U_MEMBERLIST'                        => append_sid("{$phpbb_root_path}memberlist.$phpEx"),
4594 7889 acydburn
                'U_VIEWONLINE'                        => ($auth->acl_gets('u_viewprofile', 'a_user', 'a_useradd', 'a_userdel')) ? append_sid("{$phpbb_root_path}viewonline.$phpEx") : '',
4595 4236 psotfx
                'U_LOGIN_LOGOUT'                => $u_login_logout,
4596 6015 acydburn
                'U_INDEX'                                => append_sid("{$phpbb_root_path}index.$phpEx"),
4597 6015 acydburn
                'U_SEARCH'                                => append_sid("{$phpbb_root_path}search.$phpEx"),
4598 6015 acydburn
                'U_REGISTER'                        => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register'),
4599 6015 acydburn
                'U_PROFILE'                                => append_sid("{$phpbb_root_path}ucp.$phpEx"),
4600 6015 acydburn
                'U_MODCP'                                => append_sid("{$phpbb_root_path}mcp.$phpEx", false, true, $user->session_id),
4601 6015 acydburn
                'U_FAQ'                                        => append_sid("{$phpbb_root_path}faq.$phpEx"),
4602 6015 acydburn
                'U_SEARCH_SELF'                        => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=egosearch'),
4603 6015 acydburn
                'U_SEARCH_NEW'                        => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=newposts'),
4604 6015 acydburn
                'U_SEARCH_UNANSWERED'        => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unanswered'),
4605 9755 rxu
                'U_SEARCH_UNREAD'                => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unreadposts'),
4606 6015 acydburn
                'U_SEARCH_ACTIVE_TOPICS'=> append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=active_topics'),
4607 6015 acydburn
                'U_DELETE_COOKIES'                => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=delete_cookies'),
4608 8987 acydburn
                'U_TEAM'                                => ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile')) ? '' : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=leaders'),
4609 9668 acydburn
                'U_TERMS_USE'                        => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=terms'),
4610 9668 acydburn
                'U_PRIVACY'                                => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy'),
4611 6015 acydburn
                'U_RESTORE_PERMISSIONS'        => ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=restore_perm') : '',
4612 9575 acydburn
                'U_FEED'                                => generate_board_url() . "/feed.$phpEx",
4613 3961 psotfx
4614 6015 acydburn
                'S_USER_LOGGED_IN'                => ($user->data['user_id'] != ANONYMOUS) ? true : false,
4615 7874 acydburn
                'S_AUTOLOGIN_ENABLED'        => ($config['allow_autologin']) ? true : false,
4616 6702 acydburn
                'S_BOARD_DISABLED'                => ($config['board_disable']) ? true : false,
4617 8956 acydburn
                'S_REGISTERED_USER'                => (!empty($user->data['is_registered'])) ? true : false,
4618 8956 acydburn
                'S_IS_BOT'                                => (!empty($user->data['is_bot'])) ? true : false,
4619 6015 acydburn
                'S_USER_PM_POPUP'                => $user->optionget('popuppm'),
4620 8312 vic_delfant
                'S_USER_LANG'                        => $user_lang,
4621 6015 acydburn
                'S_USER_BROWSER'                => (isset($user->data['session_browser'])) ? $user->data['session_browser'] : $user->lang['UNKNOWN_BROWSER'],
4622 6345 acydburn
                'S_USERNAME'                        => $user->data['username'],
4623 6015 acydburn
                'S_CONTENT_DIRECTION'        => $user->lang['DIRECTION'],
4624 7090 shs
                'S_CONTENT_FLOW_BEGIN'        => ($user->lang['DIRECTION'] == 'ltr') ? 'left' : 'right',
4625 7090 shs
                'S_CONTENT_FLOW_END'        => ($user->lang['DIRECTION'] == 'ltr') ? 'right' : 'left',
4626 6380 naderman
                'S_CONTENT_ENCODING'        => 'UTF-8',
4627 6015 acydburn
                '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], ''),
4628 6364 acydburn
                'S_DISPLAY_ONLINE_LIST'        => ($l_online_time) ? 1 : 0,
4629 6039 grahamje
                'S_DISPLAY_SEARCH'                => (!$config['load_search']) ? 0 : (isset($auth) ? ($auth->acl_get('u_search') && $auth->acl_getf_global('f_search')) : 1),
4630 8956 acydburn
                'S_DISPLAY_PM'                        => ($config['allow_privmsg'] && !empty($user->data['is_registered']) && ($auth->acl_get('u_readpm') || $auth->acl_get('u_sendpm'))) ? true : false,
4631 4970 psotfx
                'S_DISPLAY_MEMBERLIST'        => (isset($auth)) ? $auth->acl_get('u_viewprofile') : 0,
4632 4883 acydburn
                'S_NEW_PM'                                => ($s_privmsg_new) ? 1 : 0,
4633 8350 acydburn
                'S_REGISTER_ENABLED'        => ($config['require_activation'] != USER_ACTIVATION_DISABLE) ? true : false,
4634 9575 acydburn
                'S_FORUM_ID'                        => $forum_id,
4635 9575 acydburn
                'S_TOPIC_ID'                        => $topic_id,
4636 3961 psotfx
4637 10332 Kellanved
                'S_LOGIN_ACTION'                => ((!defined('ADMIN_START')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login') : append_sid("index.$phpEx", false, true, $user->session_id)),
4638 10585 git-gate
                'S_LOGIN_REDIRECT'                => build_hidden_fields(array('redirect' => build_url())),
4639 10067 acydburn
4640 9575 acydburn
                'S_ENABLE_FEEDS'                        => ($config['feed_enable']) ? true : false,
4641 10363 bantu
                'S_ENABLE_FEEDS_OVERALL'        => ($config['feed_overall']) ? true : false,
4642 9575 acydburn
                'S_ENABLE_FEEDS_FORUMS'                => ($config['feed_overall_forums']) ? true : false,
4643 10382 bantu
                'S_ENABLE_FEEDS_TOPICS'                => ($config['feed_topics_new']) ? true : false,
4644 10382 bantu
                'S_ENABLE_FEEDS_TOPICS_ACTIVE'        => ($config['feed_topics_active']) ? true : false,
4645 9965 acydburn
                'S_ENABLE_FEEDS_NEWS'                => ($s_feed_news) ? true : false,
4646 9575 acydburn
4647 10818 git-gate
                'S_LOAD_UNREADS'                        => ($config['load_unreads_search'] && ($config['load_anon_lastread'] || $user->data['is_registered'])) ? true : false,
4648 10790 git-gate
4649 11187 git-gate
                'S_SEARCH_HIDDEN_FIELDS'        => build_hidden_fields($s_search_hidden_fields),
4650 11187 git-gate
4651 11633 git-gate
                'T_THEME_PATH'                        => "{$web_path}styles/" . rawurlencode($user->theme['theme_path']) . '/theme',
4652 11633 git-gate
                'T_TEMPLATE_PATH'                => "{$web_path}styles/" . rawurlencode($user->theme['template_path']) . '/template',
4653 11633 git-gate
                'T_SUPER_TEMPLATE_PATH'        => (isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? "{$web_path}styles/" . rawurlencode($user->theme['template_inherit_path']) . '/template' : "{$web_path}styles/" . rawurlencode($user->theme['template_path']) . '/template',
4654 11633 git-gate
                'T_IMAGESET_PATH'                => "{$web_path}styles/" . rawurlencode($user->theme['imageset_path']) . '/imageset',
4655 11633 git-gate
                'T_IMAGESET_LANG_PATH'        => "{$web_path}styles/" . rawurlencode($user->theme['imageset_path']) . '/imageset/' . $user->lang_name,
4656 10008 acydburn
                'T_IMAGES_PATH'                        => "{$web_path}images/",
4657 10008 acydburn
                'T_SMILIES_PATH'                => "{$web_path}{$config['smilies_path']}/",
4658 10008 acydburn
                'T_AVATAR_PATH'                        => "{$web_path}{$config['avatar_path']}/",
4659 10008 acydburn
                'T_AVATAR_GALLERY_PATH'        => "{$web_path}{$config['avatar_gallery_path']}/",
4660 10008 acydburn
                'T_ICONS_PATH'                        => "{$web_path}{$config['icons_path']}/",
4661 10008 acydburn
                'T_RANKS_PATH'                        => "{$web_path}{$config['ranks_path']}/",
4662 10008 acydburn
                'T_UPLOAD_PATH'                        => "{$web_path}{$config['upload_path']}/",
4663 11633 git-gate
                'T_STYLESHEET_LINK'                => (!$user->theme['theme_storedb']) ? "{$web_path}styles/" . rawurlencode($user->theme['theme_path']) . '/theme/stylesheet.css' : append_sid("{$phpbb_root_path}style.$phpEx", 'id=' . $user->theme['style_id'] . '&amp;lang=' . $user->lang_name),
4664 5372 acydburn
                'T_STYLESHEET_NAME'                => $user->theme['theme_name'],
4665 5544 davidmj
4666 11633 git-gate
                'T_THEME_NAME'                        => rawurlencode($user->theme['theme_path']),
4667 11633 git-gate
                'T_TEMPLATE_NAME'                => rawurlencode($user->theme['template_path']),
4668 11633 git-gate
                'T_SUPER_TEMPLATE_NAME'        => rawurlencode((isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? $user->theme['template_inherit_path'] : $user->theme['template_path']),
4669 11633 git-gate
                'T_IMAGESET_NAME'                => rawurlencode($user->theme['imageset_path']),
4670 10008 acydburn
                'T_IMAGESET_LANG_NAME'        => $user->data['user_lang'],
4671 10008 acydburn
                'T_IMAGES'                                => 'images',
4672 10008 acydburn
                'T_SMILIES'                                => $config['smilies_path'],
4673 10008 acydburn
                'T_AVATAR'                                => $config['avatar_path'],
4674 10008 acydburn
                'T_AVATAR_GALLERY'                => $config['avatar_gallery_path'],
4675 10008 acydburn
                'T_ICONS'                                => $config['icons_path'],
4676 10008 acydburn
                'T_RANKS'                                => $config['ranks_path'],
4677 10008 acydburn
                'T_UPLOAD'                                => $config['upload_path'],
4678 10008 acydburn
4679 8874 acydburn
                'SITE_LOGO_IMG'                        => $user->img('site_logo'),
4680 3961 psotfx
4681 8874 acydburn
                'A_COOKIE_SETTINGS'                => addslashes('; path=' . $config['cookie_path'] . ((!$config['cookie_domain'] || $config['cookie_domain'] == 'localhost' || $config['cookie_domain'] == '127.0.0.1') ? '' : '; domain=' . $config['cookie_domain']) . ((!$config['cookie_secure']) ? '' : '; secure')),
4682 8874 acydburn
        ));
4683 8874 acydburn
4684 6816 acydburn
        // application/xhtml+xml not used because of IE
4685 6816 acydburn
        header('Content-type: text/html; charset=UTF-8');
4686 6816 acydburn
4687 6114 acydburn
        header('Cache-Control: private, no-cache="set-cookie"');
4688 4325 psotfx
        header('Expires: 0');
4689 4325 psotfx
        header('Pragma: no-cache');
4690 3961 psotfx
4691 11387 git-gate
        if (!empty($user->data['is_bot']))
4692 11387 git-gate
        {
4693 11387 git-gate
                // Let reverse proxies know we detected a bot.
4694 11387 git-gate
                header('X-PHPBB-IS-BOT: yes');
4695 11387 git-gate
        }
4696 11387 git-gate
4697 3961 psotfx
        return;
4698 3961 psotfx
}
4699 3961 psotfx
4700 5114 acydburn
/**
4701 5114 acydburn
* Generate page footer
4702 5114 acydburn
*/
4703 6521 grahamje
function page_footer($run_cron = true)
4704 3961 psotfx
{
4705 6729 davidmj
        global $db, $config, $template, $user, $auth, $cache, $starttime, $phpbb_root_path, $phpEx;
4706 3961 psotfx
4707 3961 psotfx
        // Output page creation time
4708 3961 psotfx
        if (defined('DEBUG'))
4709 3961 psotfx
        {
4710 3961 psotfx
                $mtime = explode(' ', microtime());
4711 3961 psotfx
                $totaltime = $mtime[0] + $mtime[1] - $starttime;
4712 3961 psotfx
4713 5877 acydburn
                if (!empty($_REQUEST['explain']) && $auth->acl_get('a_') && defined('DEBUG_EXTRA') && method_exists($db, 'sql_report'))
4714 3961 psotfx
                {
4715 4448 ludovic_arnaud
                        $db->sql_report('display');
4716 3961 psotfx
                }
4717 3961 psotfx
4718 9737 rxu
                $debug_output = sprintf('Time : %.3fs | ' . $db->sql_num_queries() . ' Queries | GZIP : ' . (($config['gzip_compress'] && @extension_loaded('zlib')) ? 'On' : 'Off') . (($user->load) ? ' | Load : ' . $user->load : ''), $totaltime);
4719 3961 psotfx
4720 4984 acydburn
                if ($auth->acl_get('a_') && defined('DEBUG_EXTRA'))
4721 3961 psotfx
                {
4722 4983 acydburn
                        if (function_exists('memory_get_usage'))
4723 4983 acydburn
                        {
4724 4983 acydburn
                                if ($memory_usage = memory_get_usage())
4725 4983 acydburn
                                {
4726 4984 acydburn
                                        global $base_memory_usage;
4727 4984 acydburn
                                        $memory_usage -= $base_memory_usage;
4728 8389 acydburn
                                        $memory_usage = get_formatted_filesize($memory_usage);
4729 4990 psotfx
4730 4990 psotfx
                                        $debug_output .= ' | Memory Usage: ' . $memory_usage;
4731 4983 acydburn
                                }
4732 4983 acydburn
                        }
4733 4983 acydburn
4734 5902 acydburn
                        $debug_output .= ' | <a href="' . build_url() . '&amp;explain=1">Explain</a>';
4735 3961 psotfx
                }
4736 3961 psotfx
        }
4737 3961 psotfx
4738 3961 psotfx
        $template->assign_vars(array(
4739 6584 acydburn
                'DEBUG_OUTPUT'                        => (defined('DEBUG')) ? $debug_output : '',
4740 6584 acydburn
                'TRANSLATION_INFO'                => (!empty($user->lang['TRANSLATION_INFO'])) ? $user->lang['TRANSLATION_INFO'] : '',
4741 4702 psotfx
4742 8956 acydburn
                'U_ACP' => ($auth->acl_get('a_') && !empty($user->data['is_registered'])) ? append_sid("{$phpbb_root_path}adm/index.$phpEx", false, true, $user->session_id) : '')
4743 3961 psotfx
        );
4744 3961 psotfx
4745 5135 acydburn
        // Call cron-type script
4746 10082 acydburn
        $call_cron = false;
4747 11052 git-gate
        if (!defined('IN_CRON') && $run_cron && !$config['board_disable'] && !$user->data['is_bot'])
4748 5135 acydburn
        {
4749 10082 acydburn
                $call_cron = true;
4750 10087 bantu
                $time_now = (!empty($user->time_now) && is_int($user->time_now)) ? $user->time_now : time();
4751 10082 acydburn
4752 10082 acydburn
                // Any old lock present?
4753 10082 acydburn
                if (!empty($config['cron_lock']))
4754 10082 acydburn
                {
4755 10082 acydburn
                        $cron_time = explode(' ', $config['cron_lock']);
4756 10082 acydburn
4757 10082 acydburn
                        // If 1 hour lock is present we do not call cron.php
4758 10087 bantu
                        if ($cron_time[0] + 3600 >= $time_now)
4759 10082 acydburn
                        {
4760 10082 acydburn
                                $call_cron = false;
4761 10082 acydburn
                        }
4762 10082 acydburn
                }
4763 10082 acydburn
        }
4764 10082 acydburn
4765 10082 acydburn
        // Call cron job?
4766 10082 acydburn
        if ($call_cron)
4767 10082 acydburn
        {
4768 5135 acydburn
                $cron_type = '';
4769 8348 acydburn
4770 10087 bantu
                if ($time_now - $config['queue_interval'] > $config['last_queue_run'] && !defined('IN_ADMIN') && file_exists($phpbb_root_path . 'cache/queue.' . $phpEx))
4771 5135 acydburn
                {
4772 5135 acydburn
                        // Process email queue
4773 5135 acydburn
                        $cron_type = 'queue';
4774 5135 acydburn
                }
4775 10087 bantu
                else if (method_exists($cache, 'tidy') && $time_now - $config['cache_gc'] > $config['cache_last_gc'])
4776 5135 acydburn
                {
4777 5135 acydburn
                        // Tidy the cache
4778 5135 acydburn
                        $cron_type = 'tidy_cache';
4779 5135 acydburn
                }
4780 10087 bantu
                else if ($config['warnings_expire_days'] && ($time_now - $config['warnings_gc'] > $config['warnings_last_gc']))
4781 5602 grahamje
                {
4782 5602 grahamje
                        $cron_type = 'tidy_warnings';
4783 5602 grahamje
                }
4784 10087 bantu
                else if ($time_now - $config['database_gc'] > $config['database_last_gc'])
4785 5135 acydburn
                {
4786 5929 acydburn
                        // Tidy the database
4787 5135 acydburn
                        $cron_type = 'tidy_database';
4788 5135 acydburn
                }
4789 10087 bantu
                else if ($time_now - $config['search_gc'] > $config['search_last_gc'])
4790 5441 naderman
                {
4791 5486 acydburn
                        // Tidy the search
4792 5441 naderman
                        $cron_type = 'tidy_search';
4793 5441 naderman
                }
4794 10087 bantu
                else if ($time_now - $config['session_gc'] > $config['session_last_gc'])
4795 5272 acydburn
                {
4796 5272 acydburn
                        $cron_type = 'tidy_sessions';
4797 5272 acydburn
                }
4798 5272 acydburn
4799 5135 acydburn
                if ($cron_type)
4800 5135 acydburn
                {
4801 6584 acydburn
                        $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" />');
4802 5135 acydburn
                }
4803 5135 acydburn
        }
4804 5135 acydburn
4805 3961 psotfx
        $template->display('body');
4806 4343 psotfx
4807 6055 acydburn
        garbage_collection();
4808 8072 acydburn
        exit_handler();
4809 6055 acydburn
}
4810 6055 acydburn
4811 6055 acydburn
/**
4812 6055 acydburn
* Closing the cache object and the database
4813 6055 acydburn
* Cool function name, eh? We might want to add operations to it later
4814 6055 acydburn
*/
4815 6055 acydburn
function garbage_collection()
4816 6055 acydburn
{
4817 6055 acydburn
        global $cache, $db;
4818 6055 acydburn
4819 4365 ludovic_arnaud
        // Unload cache, must be done before the DB connection if closed
4820 4343 psotfx
        if (!empty($cache))
4821 4343 psotfx
        {
4822 4343 psotfx
                $cache->unload();
4823 4343 psotfx
        }
4824 4365 ludovic_arnaud
4825 4365 ludovic_arnaud
        // Close our DB connection.
4826 6342 acydburn
        if (!empty($db))
4827 6342 acydburn
        {
4828 6342 acydburn
                $db->sql_close();
4829 6342 acydburn
        }
4830 3961 psotfx
}
4831 3961 psotfx
4832 6224 acydburn
/**
4833 8100 acydburn
* Handler for exit calls in phpBB.
4834 8100 acydburn
* This function supports hooks.
4835 8072 acydburn
*
4836 8100 acydburn
* Note: This function is called after the template has been outputted.
4837 8072 acydburn
*/
4838 8072 acydburn
function exit_handler()
4839 8072 acydburn
{
4840 8519 acydburn
        global $phpbb_hook, $config;
4841 8100 acydburn
4842 8118 acydburn
        if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__))
4843 8072 acydburn
        {
4844 8100 acydburn
                if ($phpbb_hook->hook_return(__FUNCTION__))
4845 8100 acydburn
                {
4846 8100 acydburn
                        return $phpbb_hook->hook_return_result(__FUNCTION__);
4847 8100 acydburn
                }
4848 8072 acydburn
        }
4849 8072 acydburn
4850 8491 acydburn
        // As a pre-caution... some setups display a blank page if the flush() is not there.
4851 11154 git-gate
        (ob_get_level() > 0) ? @ob_flush() : @flush();
4852 8491 acydburn
4853 8072 acydburn
        exit;
4854 8072 acydburn
}
4855 8072 acydburn
4856 8072 acydburn
/**
4857 8100 acydburn
* Handler for init calls in phpBB. This function is called in user::setup();
4858 8100 acydburn
* This function supports hooks.
4859 8100 acydburn
*/
4860 8100 acydburn
function phpbb_user_session_handler()
4861 8100 acydburn
{
4862 8100 acydburn
        global $phpbb_hook;
4863 8100 acydburn
4864 8131 acydburn
        if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__))
4865 8100 acydburn
        {
4866 8100 acydburn
                if ($phpbb_hook->hook_return(__FUNCTION__))
4867 8100 acydburn
                {
4868 8100 acydburn
                        return $phpbb_hook->hook_return_result(__FUNCTION__);
4869 8100 acydburn
                }
4870 8100 acydburn
        }
4871 8100 acydburn
4872 8100 acydburn
        return;
4873 8100 acydburn
}
4874 8100 acydburn
4875 5114 acydburn
?>