| 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 | ?>
|
|---|