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