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