phpBB
Statistics
| Revision:

root / trunk / phpBB / includes / functions.php

History | View | Annotate | Download (140.3 kB)

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