/phpBB3/includes/functions.php
PHP | 2461 lines | 1670 code | 358 blank | 433 comment | 403 complexity | cd048a42dd93f5f08411884ce552b9c8 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- <?php
- /**
- *
- * @package phpBB3
- * @version $Id: functions.php 9153 2008-12-02 17:02:56Z acydburn $
- * @copyright (c) 2005 phpBB Group
- * @license http://opensource.org/licenses/gpl-license.php GNU Public License
- *
- */
- /**
- * @ignore
- */
- if (!defined('IN_PHPBB'))
- {
- exit;
- }
- // Common global functions
- /**
- * set_var
- *
- * Set variable, used by {@link request_var the request_var function}
- *
- * @access private
- */
- function set_var(&$result, $var, $type, $multibyte = false)
- {
- settype($var, $type);
- $result = $var;
- if ($type == 'string')
- {
- $result = trim(htmlspecialchars(str_replace(array("\r\n", "\r", "\0"), array("\n", "\n", ''), $result), ENT_COMPAT, 'UTF-8'));
- if (!empty($result))
- {
- // Make sure multibyte characters are wellformed
- if ($multibyte)
- {
- if (!preg_match('/^./u', $result))
- {
- $result = '';
- }
- }
- else
- {
- // no multibyte, allow only ASCII (0-127)
- $result = preg_replace('/[\x80-\xFF]/', '?', $result);
- }
- }
- $result = (STRIP) ? stripslashes($result) : $result;
- }
- }
- /**
- * request_var
- *
- * Used to get passed variable
- */
- function request_var($var_name, $default, $multibyte = false, $cookie = false)
- {
- if (!$cookie && isset($_COOKIE[$var_name]))
- {
- if (!isset($_GET[$var_name]) && !isset($_POST[$var_name]))
- {
- return (is_array($default)) ? array() : $default;
- }
- $_REQUEST[$var_name] = isset($_POST[$var_name]) ? $_POST[$var_name] : $_GET[$var_name];
- }
- if (!isset($_REQUEST[$var_name]) || (is_array($_REQUEST[$var_name]) && !is_array($default)) || (is_array($default) && !is_array($_REQUEST[$var_name])))
- {
- return (is_array($default)) ? array() : $default;
- }
- $var = $_REQUEST[$var_name];
- if (!is_array($default))
- {
- $type = gettype($default);
- }
- else
- {
- list($key_type, $type) = each($default);
- $type = gettype($type);
- $key_type = gettype($key_type);
- if ($type == 'array')
- {
- reset($default);
- $default = current($default);
- list($sub_key_type, $sub_type) = each($default);
- $sub_type = gettype($sub_type);
- $sub_type = ($sub_type == 'array') ? 'NULL' : $sub_type;
- $sub_key_type = gettype($sub_key_type);
- }
- }
- if (is_array($var))
- {
- $_var = $var;
- $var = array();
- foreach ($_var as $k => $v)
- {
- set_var($k, $k, $key_type);
- if ($type == 'array' && is_array($v))
- {
- foreach ($v as $_k => $_v)
- {
- if (is_array($_v))
- {
- $_v = null;
- }
- set_var($_k, $_k, $sub_key_type);
- set_var($var[$k][$_k], $_v, $sub_type, $multibyte);
- }
- }
- else
- {
- if ($type == 'array' || is_array($v))
- {
- $v = null;
- }
- set_var($var[$k], $v, $type, $multibyte);
- }
- }
- }
- else
- {
- set_var($var, $var, $type, $multibyte);
- }
- return $var;
- }
- /**
- * Set config value. Creates missing config entry.
- */
- function set_config($config_name, $config_value, $is_dynamic = false)
- {
- global $db, $cache, $config;
- $sql = 'UPDATE ' . CONFIG_TABLE . "
- SET config_value = '" . $db->sql_escape($config_value) . "'
- WHERE config_name = '" . $db->sql_escape($config_name) . "'";
- $db->sql_query($sql);
- if (!$db->sql_affectedrows() && !isset($config[$config_name]))
- {
- $sql = 'INSERT INTO ' . CONFIG_TABLE . ' ' . $db->sql_build_array('INSERT', array(
- 'config_name' => $config_name,
- 'config_value' => $config_value,
- 'is_dynamic' => ($is_dynamic) ? 1 : 0));
- $db->sql_query($sql);
- }
- $config[$config_name] = $config_value;
- if (!$is_dynamic)
- {
- $cache->destroy('config');
- }
- }
- /**
- * Generates an alphanumeric random string of given length
- */
- function gen_rand_string($num_chars = 8)
- {
- $rand_str = unique_id();
- $rand_str = str_replace('0', 'Z', strtoupper(base_convert($rand_str, 16, 35)));
- return substr($rand_str, 0, $num_chars);
- }
- /**
- * Return unique id
- * @param string $extra additional entropy
- */
- function unique_id($extra = 'c')
- {
- static $dss_seeded = false;
- global $config;
- $val = $config['rand_seed'] . microtime();
- $val = md5($val);
- $config['rand_seed'] = md5($config['rand_seed'] . $val . $extra);
- if ($dss_seeded !== true && ($config['rand_seed_last_update'] < time() - rand(1,10)))
- {
- set_config('rand_seed', $config['rand_seed'], true);
- set_config('rand_seed_last_update', time(), true);
- $dss_seeded = true;
- }
- return substr($val, 4, 16);
- }
- /**
- * Return formatted string for filesizes
- */
- function get_formatted_filesize($bytes, $add_size_lang = true)
- {
- global $user;
- if ($bytes >= pow(2, 20))
- {
- return ($add_size_lang) ? round($bytes / 1024 / 1024, 2) . ' ' . $user->lang['MIB'] : round($bytes / 1024 / 1024, 2);
- }
- if ($bytes >= pow(2, 10))
- {
- return ($add_size_lang) ? round($bytes / 1024, 2) . ' ' . $user->lang['KIB'] : round($bytes / 1024, 2);
- }
- return ($add_size_lang) ? ($bytes) . ' ' . $user->lang['BYTES'] : ($bytes);
- }
- /**
- * Determine whether we are approaching the maximum execution time. Should be called once
- * at the beginning of the script in which it's used.
- * @return bool Either true if the maximum execution time is nearly reached, or false
- * if some time is still left.
- */
- function still_on_time($extra_time = 15)
- {
- static $max_execution_time, $start_time;
- $time = explode(' ', microtime());
- $current_time = $time[0] + $time[1];
- if (empty($max_execution_time))
- {
- $max_execution_time = (function_exists('ini_get')) ? (int) @ini_get('max_execution_time') : (int) @get_cfg_var('max_execution_time');
- // If zero, then set to something higher to not let the user catch the ten seconds barrier.
- if ($max_execution_time === 0)
- {
- $max_execution_time = 50 + $extra_time;
- }
- $max_execution_time = min(max(10, ($max_execution_time - $extra_time)), 50);
- // For debugging purposes
- // $max_execution_time = 10;
- global $starttime;
- $start_time = (empty($starttime)) ? $current_time : $starttime;
- }
- return (ceil($current_time - $start_time) < $max_execution_time) ? true : false;
- }
- /**
- *
- * @version Version 0.1 / slightly modified for phpBB 3.0.x (using $H$ as hash type identifier)
- *
- * Portable PHP password hashing framework.
- *
- * Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in
- * the public domain.
- *
- * There's absolutely no warranty.
- *
- * The homepage URL for this framework is:
- *
- * http://www.openwall.com/phpass/
- *
- * Please be sure to update the Version line if you edit this file in any way.
- * It is suggested that you leave the main version number intact, but indicate
- * your project name (after the slash) and add your own revision information.
- *
- * Please do not change the "private" password hashing method implemented in
- * here, thereby making your hashes incompatible. However, if you must, please
- * change the hash type identifier (the "$P$") to something different.
- *
- * Obviously, since this code is in the public domain, the above are not
- * requirements (there can be none), but merely suggestions.
- *
- *
- * Hash the password
- */
- function phpbb_hash($password)
- {
- $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
- $random_state = unique_id();
- $random = '';
- $count = 6;
- if (($fh = @fopen('/dev/urandom', 'rb')))
- {
- $random = fread($fh, $count);
- fclose($fh);
- }
- if (strlen($random) < $count)
- {
- $random = '';
- for ($i = 0; $i < $count; $i += 16)
- {
- $random_state = md5(unique_id() . $random_state);
- $random .= pack('H*', md5($random_state));
- }
- $random = substr($random, 0, $count);
- }
- $hash = _hash_crypt_private($password, _hash_gensalt_private($random, $itoa64), $itoa64);
- if (strlen($hash) == 34)
- {
- return $hash;
- }
- return md5($password);
- }
- /**
- * Check for correct password
- *
- * @param string $password The password in plain text
- * @param string $hash The stored password hash
- *
- * @return bool Returns true if the password is correct, false if not.
- */
- function phpbb_check_hash($password, $hash)
- {
- $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
- if (strlen($hash) == 34)
- {
- return (_hash_crypt_private($password, $hash, $itoa64) === $hash) ? true : false;
- }
- return (md5($password) === $hash) ? true : false;
- }
- /**
- * Generate salt for hash generation
- */
- function _hash_gensalt_private($input, &$itoa64, $iteration_count_log2 = 6)
- {
- if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31)
- {
- $iteration_count_log2 = 8;
- }
- $output = '$H$';
- $output .= $itoa64[min($iteration_count_log2 + ((PHP_VERSION >= 5) ? 5 : 3), 30)];
- $output .= _hash_encode64($input, 6, $itoa64);
- return $output;
- }
- /**
- * Encode hash
- */
- function _hash_encode64($input, $count, &$itoa64)
- {
- $output = '';
- $i = 0;
- do
- {
- $value = ord($input[$i++]);
- $output .= $itoa64[$value & 0x3f];
- if ($i < $count)
- {
- $value |= ord($input[$i]) << 8;
- }
- $output .= $itoa64[($value >> 6) & 0x3f];
- if ($i++ >= $count)
- {
- break;
- }
- if ($i < $count)
- {
- $value |= ord($input[$i]) << 16;
- }
- $output .= $itoa64[($value >> 12) & 0x3f];
- if ($i++ >= $count)
- {
- break;
- }
- $output .= $itoa64[($value >> 18) & 0x3f];
- }
- while ($i < $count);
- return $output;
- }
- /**
- * The crypt function/replacement
- */
- function _hash_crypt_private($password, $setting, &$itoa64)
- {
- $output = '*';
- // Check for correct hash
- if (substr($setting, 0, 3) != '$H$')
- {
- return $output;
- }
- $count_log2 = strpos($itoa64, $setting[3]);
- if ($count_log2 < 7 || $count_log2 > 30)
- {
- return $output;
- }
- $count = 1 << $count_log2;
- $salt = substr($setting, 4, 8);
- if (strlen($salt) != 8)
- {
- return $output;
- }
- /**
- * We're kind of forced to use MD5 here since it's the only
- * cryptographic primitive available in all versions of PHP
- * currently in use. To implement our own low-level crypto
- * in PHP would result in much worse performance and
- * consequently in lower iteration counts and hashes that are
- * quicker to crack (by non-PHP code).
- */
- if (PHP_VERSION >= 5)
- {
- $hash = md5($salt . $password, true);
- do
- {
- $hash = md5($hash . $password, true);
- }
- while (--$count);
- }
- else
- {
- $hash = pack('H*', md5($salt . $password));
- do
- {
- $hash = pack('H*', md5($hash . $password));
- }
- while (--$count);
- }
- $output = substr($setting, 0, 12);
- $output .= _hash_encode64($hash, 16, $itoa64);
- return $output;
- }
- /**
- * Global function for chmodding directories and files for internal use
- * This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions.
- * The function determines owner and group from common.php file and sets the same to the provided file. Permissions are mapped to the group, user always has rw(x) permission.
- * The function uses bit fields to build the permissions.
- * The function sets the appropiate execute bit on directories.
- *
- * Supported constants representing bit fields are:
- *
- * CHMOD_ALL - all permissions (7)
- * CHMOD_READ - read permission (4)
- * CHMOD_WRITE - write permission (2)
- * CHMOD_EXECUTE - execute permission (1)
- *
- * 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.
- *
- * @param $filename The file/directory to be chmodded
- * @param $perms Permissions to set
- * @return true on success, otherwise false
- *
- * @author faw, phpBB Group
- */
- function phpbb_chmod($filename, $perms = CHMOD_READ)
- {
- // Return if the file no longer exists.
- if (!file_exists($filename))
- {
- return false;
- }
- if (!function_exists('fileowner') || !function_exists('filegroup'))
- {
- $file_uid = $file_gid = false;
- $common_php_owner = $common_php_group = false;
- }
- else
- {
- global $phpbb_root_path, $phpEx;
- // Determine owner/group of common.php file and the filename we want to change here
- $common_php_owner = fileowner($phpbb_root_path . 'common.' . $phpEx);
- $common_php_group = filegroup($phpbb_root_path . 'common.' . $phpEx);
- $file_uid = fileowner($filename);
- $file_gid = filegroup($filename);
- // Try to set the owner to the same common.php has
- if ($common_php_owner !== $file_uid && $common_php_owner !== false && $file_uid !== false)
- {
- // Will most likely not work
- if (@chown($filename, $common_php_owner));
- {
- clearstatcache();
- $file_uid = fileowner($filename);
- }
- }
- // Try to set the group to the same common.php has
- if ($common_php_group !== $file_gid && $common_php_group !== false && $file_gid !== false)
- {
- if (@chgrp($filename, $common_php_group));
- {
- clearstatcache();
- $file_gid = filegroup($filename);
- }
- }
- }
- // And the owner and the groups PHP is running under.
- $php_uid = (function_exists('posix_getuid')) ? @posix_getuid() : false;
- $php_gids = (function_exists('posix_getgroups')) ? @posix_getgroups() : false;
- // Who is PHP?
- if ($file_uid === false || $file_gid === false || $php_uid === false || $php_gids === false)
- {
- $php = NULL;
- }
- else if ($file_uid == $php_uid /* && $common_php_owner !== false && $common_php_owner === $file_uid*/)
- {
- $php = 'owner';
- }
- else if (in_array($file_gid, $php_gids))
- {
- $php = 'group';
- }
- else
- {
- $php = 'other';
- }
- // Owner always has read/write permission
- $owner = CHMOD_READ | CHMOD_WRITE;
- if (is_dir($filename))
- {
- $owner |= CHMOD_EXECUTE;
- // Only add execute bit to the permission if the dir needs to be readable
- if ($perms & CHMOD_READ)
- {
- $perms |= CHMOD_EXECUTE;
- }
- }
- switch ($php)
- {
- case null:
- case 'owner':
- /* ATTENTION: if php is owner or NULL we set it to group here. This is the most failsafe combination for the vast majority of server setups.
- $result = @chmod($filename, ($owner << 6) + (0 << 3) + (0 << 0));
- clearstatcache();
- if (!is_null($php) || (is_readable($filename) && is_writable($filename)))
- {
- break;
- }
- */
- case 'group':
- $result = @chmod($filename, ($owner << 6) + ($perms << 3) + (0 << 0));
- clearstatcache();
- if (!is_null($php) || ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename))))
- {
- break;
- }
- case 'other':
- $result = @chmod($filename, ($owner << 6) + ($perms << 3) + ($perms << 0));
- clearstatcache();
- if (!is_null($php) || ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename))))
- {
- break;
- }
- default:
- return false;
- break;
- }
- return $result;
- }
- // Compatibility functions
- if (!function_exists('array_combine'))
- {
- /**
- * A wrapper for the PHP5 function array_combine()
- * @param array $keys contains keys for the resulting array
- * @param array $values contains values for the resulting array
- *
- * @return Returns an array by using the values from the keys array as keys and the
- * values from the values array as the corresponding values. Returns false if the
- * number of elements for each array isn't equal or if the arrays are empty.
- */
- function array_combine($keys, $values)
- {
- $keys = array_values($keys);
- $values = array_values($values);
- $n = sizeof($keys);
- $m = sizeof($values);
- if (!$n || !$m || ($n != $m))
- {
- return false;
- }
- $combined = array();
- for ($i = 0; $i < $n; $i++)
- {
- $combined[$keys[$i]] = $values[$i];
- }
- return $combined;
- }
- }
- if (!function_exists('str_split'))
- {
- /**
- * A wrapper for the PHP5 function str_split()
- * @param array $string contains the string to be converted
- * @param array $split_length contains the length of each chunk
- *
- * @return Converts a string to an array. If the optional split_length parameter is specified,
- * the returned array will be broken down into chunks with each being split_length in length,
- * otherwise each chunk will be one character in length. FALSE is returned if split_length is
- * less than 1. If the split_length length exceeds the length of string, the entire string is
- * returned as the first (and only) array element.
- */
- function str_split($string, $split_length = 1)
- {
- if ($split_length < 1)
- {
- return false;
- }
- else if ($split_length >= strlen($string))
- {
- return array($string);
- }
- else
- {
- preg_match_all('#.{1,' . $split_length . '}#s', $string, $matches);
- return $matches[0];
- }
- }
- }
- if (!function_exists('stripos'))
- {
- /**
- * A wrapper for the PHP5 function stripos
- * Find position of first occurrence of a case-insensitive string
- *
- * @param string $haystack is the string to search in
- * @param string $needle is the string to search for
- *
- * @return mixed Returns the numeric position of the first occurrence of needle in the haystack string. Unlike strpos(), stripos() is case-insensitive.
- * Note that the needle may be a string of one or more characters.
- * If needle is not found, stripos() will return boolean FALSE.
- */
- function stripos($haystack, $needle)
- {
- if (preg_match('#' . preg_quote($needle, '#') . '#i', $haystack, $m))
- {
- return strpos($haystack, $m[0]);
- }
- return false;
- }
- }
- /**
- * Checks if a path ($path) is absolute or relative
- *
- * @param string $path Path to check absoluteness of
- * @return boolean
- */
- function is_absolute($path)
- {
- return ($path[0] == '/' || (DIRECTORY_SEPARATOR == '\\' && preg_match('#^[a-z]:/#i', $path))) ? true : false;
- }
- /**
- * @author Chris Smith <chris@project-minerva.org>
- * @copyright 2006 Project Minerva Team
- * @param string $path The path which we should attempt to resolve.
- * @return mixed
- */
- function phpbb_own_realpath($path)
- {
- // Now to perform funky shizzle
- // Switch to use UNIX slashes
- $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
- $path_prefix = '';
- // Determine what sort of path we have
- if (is_absolute($path))
- {
- $absolute = true;
- if ($path[0] == '/')
- {
- // Absolute path, *NIX style
- $path_prefix = '';
- }
- else
- {
- // Absolute path, Windows style
- // Remove the drive letter and colon
- $path_prefix = $path[0] . ':';
- $path = substr($path, 2);
- }
- }
- else
- {
- // Relative Path
- // Prepend the current working directory
- if (function_exists('getcwd'))
- {
- // This is the best method, hopefully it is enabled!
- $path = str_replace(DIRECTORY_SEPARATOR, '/', getcwd()) . '/' . $path;
- $absolute = true;
- if (preg_match('#^[a-z]:#i', $path))
- {
- $path_prefix = $path[0] . ':';
- $path = substr($path, 2);
- }
- else
- {
- $path_prefix = '';
- }
- }
- else if (isset($_SERVER['SCRIPT_FILENAME']) && !empty($_SERVER['SCRIPT_FILENAME']))
- {
- // Warning: If chdir() has been used this will lie!
- // Warning: This has some problems sometime (CLI can create them easily)
- $path = str_replace(DIRECTORY_SEPARATOR, '/', dirname($_SERVER['SCRIPT_FILENAME'])) . '/' . $path;
- $absolute = true;
- $path_prefix = '';
- }
- else
- {
- // We have no way of getting the absolute path, just run on using relative ones.
- $absolute = false;
- $path_prefix = '.';
- }
- }
- // Remove any repeated slashes
- $path = preg_replace('#/{2,}#', '/', $path);
- // Remove the slashes from the start and end of the path
- $path = trim($path, '/');
- // Break the string into little bits for us to nibble on
- $bits = explode('/', $path);
- // Remove any . in the path, renumber array for the loop below
- $bits = array_values(array_diff($bits, array('.')));
- // Lets get looping, run over and resolve any .. (up directory)
- for ($i = 0, $max = sizeof($bits); $i < $max; $i++)
- {
- // @todo Optimise
- if ($bits[$i] == '..' )
- {
- if (isset($bits[$i - 1]))
- {
- if ($bits[$i - 1] != '..')
- {
- // We found a .. and we are able to traverse upwards, lets do it!
- unset($bits[$i]);
- unset($bits[$i - 1]);
- $i -= 2;
- $max -= 2;
- $bits = array_values($bits);
- }
- }
- else if ($absolute) // ie. !isset($bits[$i - 1]) && $absolute
- {
- // We have an absolute path trying to descend above the root of the filesystem
- // ... Error!
- return false;
- }
- }
- }
- // Prepend the path prefix
- array_unshift($bits, $path_prefix);
- $resolved = '';
- $max = sizeof($bits) - 1;
- // Check if we are able to resolve symlinks, Windows cannot.
- $symlink_resolve = (function_exists('readlink')) ? true : false;
- foreach ($bits as $i => $bit)
- {
- if (@is_dir("$resolved/$bit") || ($i == $max && @is_file("$resolved/$bit")))
- {
- // Path Exists
- if ($symlink_resolve && is_link("$resolved/$bit") && ($link = readlink("$resolved/$bit")))
- {
- // Resolved a symlink.
- $resolved = $link . (($i == $max) ? '' : '/');
- continue;
- }
- }
- else
- {
- // Something doesn't exist here!
- // This is correct realpath() behaviour but sadly open_basedir and safe_mode make this problematic
- // return false;
- }
- $resolved .= $bit . (($i == $max) ? '' : '/');
- }
- // @todo If the file exists fine and open_basedir only has one path we should be able to prepend it
- // because we must be inside that basedir, the question is where...
- // @internal The slash in is_dir() gets around an open_basedir restriction
- if (!@file_exists($resolved) || (!is_dir($resolved . '/') && !is_file($resolved)))
- {
- return false;
- }
- // Put the slashes back to the native operating systems slashes
- $resolved = str_replace('/', DIRECTORY_SEPARATOR, $resolved);
- // Check for DIRECTORY_SEPARATOR at the end (and remove it!)
- if (substr($resolved, -1) == DIRECTORY_SEPARATOR)
- {
- return substr($resolved, 0, -1);
- }
- return $resolved; // We got here, in the end!
- }
- if (!function_exists('realpath'))
- {
- /**
- * A wrapper for realpath
- * @ignore
- */
- function phpbb_realpath($path)
- {
- return phpbb_own_realpath($path);
- }
- }
- else
- {
- /**
- * A wrapper for realpath
- */
- function phpbb_realpath($path)
- {
- $realpath = realpath($path);
- // Strangely there are provider not disabling realpath but returning strange values. :o
- // We at least try to cope with them.
- if ($realpath === $path || $realpath === false)
- {
- return phpbb_own_realpath($path);
- }
- // Check for DIRECTORY_SEPARATOR at the end (and remove it!)
- if (substr($realpath, -1) == DIRECTORY_SEPARATOR)
- {
- $realpath = substr($realpath, 0, -1);
- }
- return $realpath;
- }
- }
- if (!function_exists('htmlspecialchars_decode'))
- {
- /**
- * A wrapper for htmlspecialchars_decode
- * @ignore
- */
- function htmlspecialchars_decode($string, $quote_style = ENT_COMPAT)
- {
- return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
- }
- }
- // functions used for building option fields
- /**
- * Pick a language, any language ...
- */
- function language_select($default = '')
- {
- global $db;
- $sql = 'SELECT lang_iso, lang_local_name
- FROM ' . LANG_TABLE . '
- ORDER BY lang_english_name';
- $result = $db->sql_query($sql);
- $lang_options = '';
- while ($row = $db->sql_fetchrow($result))
- {
- $selected = ($row['lang_iso'] == $default) ? ' selected="selected"' : '';
- $lang_options .= '<option value="' . $row['lang_iso'] . '"' . $selected . '>' . $row['lang_local_name'] . '</option>';
- }
- $db->sql_freeresult($result);
- return $lang_options;
- }
- /**
- * Pick a template/theme combo,
- */
- function style_select($default = '', $all = false)
- {
- global $db;
- $sql_where = (!$all) ? 'WHERE style_active = 1 ' : '';
- $sql = 'SELECT style_id, style_name
- FROM ' . STYLES_TABLE . "
- $sql_where
- ORDER BY style_name";
- $result = $db->sql_query($sql);
- $style_options = '';
- while ($row = $db->sql_fetchrow($result))
- {
- $selected = ($row['style_id'] == $default) ? ' selected="selected"' : '';
- $style_options .= '<option value="' . $row['style_id'] . '"' . $selected . '>' . $row['style_name'] . '</option>';
- }
- $db->sql_freeresult($result);
- return $style_options;
- }
- /**
- * Pick a timezone
- */
- function tz_select($default = '', $truncate = false)
- {
- global $user;
- $tz_select = '';
- foreach ($user->lang['tz_zones'] as $offset => $zone)
- {
- if ($truncate)
- {
- $zone_trunc = truncate_string($zone, 50, 255, false, '...');
- }
- else
- {
- $zone_trunc = $zone;
- }
- if (is_numeric($offset))
- {
- $selected = ($offset == $default) ? ' selected="selected"' : '';
- $tz_select .= '<option title="'.$zone.'" value="' . $offset . '"' . $selected . '>' . $zone_trunc . '</option>';
- }
- }
- return $tz_select;
- }
- // Functions handling topic/post tracking/marking
- /**
- * Marks a topic/forum as read
- * Marks a topic as posted to
- *
- * @param int $user_id can only be used with $mode == 'post'
- */
- function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $user_id = 0)
- {
- global $db, $user, $config;
- if ($mode == 'all')
- {
- if ($forum_id === false || !sizeof($forum_id))
- {
- if ($config['load_db_lastread'] && $user->data['is_registered'])
- {
- // Mark all forums read (index page)
- $db->sql_query('DELETE FROM ' . TOPICS_TRACK_TABLE . " WHERE user_id = {$user->data['user_id']}");
- $db->sql_query('DELETE FROM ' . FORUMS_TRACK_TABLE . " WHERE user_id = {$user->data['user_id']}");
- $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_lastmark = ' . time() . " WHERE user_id = {$user->data['user_id']}");
- }
- else if ($config['load_anon_lastread'] || $user->data['is_registered'])
- {
- $tracking_topics = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : '';
- $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
- unset($tracking_topics['tf']);
- unset($tracking_topics['t']);
- unset($tracking_topics['f']);
- $tracking_topics['l'] = base_convert(time() - $config['board_startdate'], 10, 36);
- $user->set_cookie('track', tracking_serialize($tracking_topics), time() + 31536000);
- $_COOKIE[$config['cookie_name'] . '_track'] = (STRIP) ? addslashes(tracking_serialize($tracking_topics)) : tracking_serialize($tracking_topics);
- unset($tracking_topics);
- if ($user->data['is_registered'])
- {
- $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_lastmark = ' . time() . " WHERE user_id = {$user->data['user_id']}");
- }
- }
- }
- return;
- }
- else if ($mode == 'topics')
- {
- // Mark all topics in forums read
- if (!is_array($forum_id))
- {
- $forum_id = array($forum_id);
- }
- // Add 0 to forums array to mark global announcements correctly
- $forum_id[] = 0;
- if ($config['load_db_lastread'] && $user->data['is_registered'])
- {
- $sql = 'DELETE FROM ' . TOPICS_TRACK_TABLE . "
- WHERE user_id = {$user->data['user_id']}
- AND " . $db->sql_in_set('forum_id', $forum_id);
- $db->sql_query($sql);
- $sql = 'SELECT forum_id
- FROM ' . FORUMS_TRACK_TABLE . "
- WHERE user_id = {$user->data['user_id']}
- AND " . $db->sql_in_set('forum_id', $forum_id);
- $result = $db->sql_query($sql);
- $sql_update = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $sql_update[] = $row['forum_id'];
- }
- $db->sql_freeresult($result);
- if (sizeof($sql_update))
- {
- $sql = 'UPDATE ' . FORUMS_TRACK_TABLE . '
- SET mark_time = ' . time() . "
- WHERE user_id = {$user->data['user_id']}
- AND " . $db->sql_in_set('forum_id', $sql_update);
- $db->sql_query($sql);
- }
- if ($sql_insert = array_diff($forum_id, $sql_update))
- {
- $sql_ary = array();
- foreach ($sql_insert as $f_id)
- {
- $sql_ary[] = array(
- 'user_id' => (int) $user->data['user_id'],
- 'forum_id' => (int) $f_id,
- 'mark_time' => time()
- );
- }
- $db->sql_multi_insert(FORUMS_TRACK_TABLE, $sql_ary);
- }
- }
- else if ($config['load_anon_lastread'] || $user->data['is_registered'])
- {
- $tracking = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : '';
- $tracking = ($tracking) ? tracking_unserialize($tracking) : array();
- foreach ($forum_id as $f_id)
- {
- $topic_ids36 = (isset($tracking['tf'][$f_id])) ? $tracking['tf'][$f_id] : array();
- if (isset($tracking['tf'][$f_id]))
- {
- unset($tracking['tf'][$f_id]);
- }
- foreach ($topic_ids36 as $topic_id36)
- {
- unset($tracking['t'][$topic_id36]);
- }
- if (isset($tracking['f'][$f_id]))
- {
- unset($tracking['f'][$f_id]);
- }
- $tracking['f'][$f_id] = base_convert(time() - $config['board_startdate'], 10, 36);
- }
- if (isset($tracking['tf']) && empty($tracking['tf']))
- {
- unset($tracking['tf']);
- }
- $user->set_cookie('track', tracking_serialize($tracking), time() + 31536000);
- $_COOKIE[$config['cookie_name'] . '_track'] = (STRIP) ? addslashes(tracking_serialize($tracking)) : tracking_serialize($tracking);
- unset($tracking);
- }
- return;
- }
- else if ($mode == 'topic')
- {
- if ($topic_id === false || $forum_id === false)
- {
- return;
- }
- if ($config['load_db_lastread'] && $user->data['is_registered'])
- {
- $sql = 'UPDATE ' . TOPICS_TRACK_TABLE . '
- SET mark_time = ' . (($post_time) ? $post_time : time()) . "
- WHERE user_id = {$user->data['user_id']}
- AND topic_id = $topic_id";
- $db->sql_query($sql);
- // insert row
- if (!$db->sql_affectedrows())
- {
- $db->sql_return_on_error(true);
- $sql_ary = array(
- 'user_id' => (int) $user->data['user_id'],
- 'topic_id' => (int) $topic_id,
- 'forum_id' => (int) $forum_id,
- 'mark_time' => ($post_time) ? (int) $post_time : time(),
- );
- $db->sql_query('INSERT INTO ' . TOPICS_TRACK_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
- $db->sql_return_on_error(false);
- }
- }
- else if ($config['load_anon_lastread'] || $user->data['is_registered'])
- {
- $tracking = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : '';
- $tracking = ($tracking) ? tracking_unserialize($tracking) : array();
- $topic_id36 = base_convert($topic_id, 10, 36);
- if (!isset($tracking['t'][$topic_id36]))
- {
- $tracking['tf'][$forum_id][$topic_id36] = true;
- }
- $post_time = ($post_time) ? $post_time : time();
- $tracking['t'][$topic_id36] = base_convert($post_time - $config['board_startdate'], 10, 36);
- // If the cookie grows larger than 10000 characters we will remove the smallest value
- // This can result in old topics being unread - but most of the time it should be accurate...
- if (isset($_COOKIE[$config['cookie_name'] . '_track']) && strlen($_COOKIE[$config['cookie_name'] . '_track']) > 10000)
- {
- //echo 'Cookie grown too large' . print_r($tracking, true);
- // We get the ten most minimum stored time offsets and its associated topic ids
- $time_keys = array();
- for ($i = 0; $i < 10 && sizeof($tracking['t']); $i++)
- {
- $min_value = min($tracking['t']);
- $m_tkey = array_search($min_value, $tracking['t']);
- unset($tracking['t'][$m_tkey]);
- $time_keys[$m_tkey] = $min_value;
- }
- // Now remove the topic ids from the array...
- foreach ($tracking['tf'] as $f_id => $topic_id_ary)
- {
- foreach ($time_keys as $m_tkey => $min_value)
- {
- if (isset($topic_id_ary[$m_tkey]))
- {
- $tracking['f'][$f_id] = $min_value;
- unset($tracking['tf'][$f_id][$m_tkey]);
- }
- }
- }
- if ($user->data['is_registered'])
- {
- $user->data['user_lastmark'] = intval(base_convert(max($time_keys) + $config['board_startdate'], 36, 10));
- $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_lastmark = ' . $user->data['user_lastmark'] . " WHERE user_id = {$user->data['user_id']}");
- }
- else
- {
- $tracking['l'] = max($time_keys);
- }
- }
- $user->set_cookie('track', tracking_serialize($tracking), time() + 31536000);
- $_COOKIE[$config['cookie_name'] . '_track'] = (STRIP) ? addslashes(tracking_serialize($tracking)) : tracking_serialize($tracking);
- }
- return;
- }
- else if ($mode == 'post')
- {
- if ($topic_id === false)
- {
- return;
- }
- $use_user_id = (!$user_id) ? $user->data['user_id'] : $user_id;
- if ($config['load_db_track'] && $use_user_id != ANONYMOUS)
- {
- $db->sql_return_on_error(true);
- $sql_ary = array(
- 'user_id' => (int) $use_user_id,
- 'topic_id' => (int) $topic_id,
- 'topic_posted' => 1
- );
- $db->sql_query('INSERT INTO ' . TOPICS_POSTED_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
- $db->sql_return_on_error(false);
- }
- return;
- }
- }
- /**
- * Get topic tracking info by using already fetched info
- */
- function get_topic_tracking($forum_id, $topic_ids, &$rowset, $forum_mark_time, $global_announce_list = false)
- {
- global $config, $user;
- $last_read = array();
- if (!is_array($topic_ids))
- {
- $topic_ids = array($topic_ids);
- }
- foreach ($topic_ids as $topic_id)
- {
- if (!empty($rowset[$topic_id]['mark_time']))
- {
- $last_read[$topic_id] = $rowset[$topic_id]['mark_time'];
- }
- }
- $topic_ids = array_diff($topic_ids, array_keys($last_read));
- if (sizeof($topic_ids))
- {
- $mark_time = array();
- // Get global announcement info
- if ($global_announce_list && sizeof($global_announce_list))
- {
- if (!isset($forum_mark_time[0]))
- {
- global $db;
- $sql = 'SELECT mark_time
- FROM ' . FORUMS_TRACK_TABLE . "
- WHERE user_id = {$user->data['user_id']}
- AND forum_id = 0";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
- if ($row)
- {
- $mark_time[0] = $row['mark_time'];
- }
- }
- else
- {
- if ($forum_mark_time[0] !== false)
- {
- $mark_time[0] = $forum_mark_time[0];
- }
- }
- }
- if (!empty($forum_mark_time[$forum_id]) && $forum_mark_time[$forum_id] !== false)
- {
- $mark_time[$forum_id] = $forum_mark_time[$forum_id];
- }
- $user_lastmark = (isset($mark_time[$forum_id])) ? $mark_time[$forum_id] : $user->data['user_lastmark'];
- foreach ($topic_ids as $topic_id)
- {
- if ($global_announce_list && isset($global_announce_list[$topic_id]))
- {
- $last_read[$topic_id] = (isset($mark_time[0])) ? $mark_time[0] : $user_lastmark;
- }
- else
- {
- $last_read[$topic_id] = $user_lastmark;
- }
- }
- }
- return $last_read;
- }
- /**
- * Get topic tracking info from db (for cookie based tracking only this function is used)
- */
- function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_list = false)
- {
- global $config, $user;
- $last_read = array();
- if (!is_array($topic_ids))
- {
- $topic_ids = array($topic_ids);
- }
- if ($config['load_db_lastread'] && $user->data['is_registered'])
- {
- global $db;
- $sql = 'SELECT topic_id, mark_time
- FROM ' . TOPICS_TRACK_TABLE . "
- WHERE user_id = {$user->data['user_id']}
- AND " . $db->sql_in_set('topic_id', $topic_ids);
- $result = $db->sql_query($sql);
- while ($row = $db->sql_fetchrow($result))
- {
- $last_read[$row['topic_id']] = $row['mark_time'];
- }
- $db->sql_freeresult($result);
- $topic_ids = array_diff($topic_ids, array_keys($last_read));
- if (sizeof($topic_ids))
- {
- $sql = 'SELECT forum_id, mark_time
- FROM ' . FORUMS_TRACK_TABLE . "
- WHERE user_id = {$user->data['user_id']}
- AND forum_id " .
- (($global_announce_list && sizeof($global_announce_list)) ? "IN (0, $forum_id)" : "= $forum_id");
- $result = $db->sql_query($sql);
- $mark_time = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $mark_time[$row['forum_id']] = $row['mark_time'];
- }
- $db->sql_freeresult($result);
- $user_lastmark = (isset($mark_time[$forum_id])) ? $mark_time[$forum_id] : $user->data['user_lastmark'];
- foreach ($topic_ids as $topic_id)
- {
- if ($global_announce_list && isset($global_announce_list[$topic_id]))
- {
- $last_read[$topic_id] = (isset($mark_time[0])) ? $mark_time[0] : $user_lastmark;
- }
- else
- {
- $last_read[$topic_id] = $user_lastmark;
- }
- }
- }
- }
- else if ($config['load_anon_lastread'] || $user->data['is_registered'])
- {
- global $tracking_topics;
- if (!isset($tracking_topics) || !sizeof($tracking_topics))
- {
- $tracking_topics = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : '';
- $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
- }
- if (!$user->data['is_registered'])
- {
- $user_lastmark = (isset($tracking_topics['l'])) ? base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate'] : 0;
- }
- else
- {
- $user_lastmark = $user->data['user_lastmark'];
- }
- foreach ($topic_ids as $topic_id)
- {
- $topic_id36 = base_convert($topic_id, 10, 36);
- if (isset($tracking_topics['t'][$topic_id36]))
- {
- $last_read[$topic_id] = base_convert($tracking_topics['t'][$topic_id36], 36, 10) + $config['board_startdate'];
- }
- }
- $topic_ids = array_diff($topic_ids, array_keys($last_read));
- if (sizeof($topic_ids))
- {
- $mark_time = array();
- if ($global_announce_list && sizeof($global_announce_list))
- {
- if (isset($tracking_topics['f'][0]))
- {
- $mark_time[0] = base_convert($tracking_topics['f'][0], 36, 10) + $config['board_startdate'];
- }
- }
- if (isset($tracking_topics['f'][$forum_id]))
- {
- $mark_time[$forum_id] = base_convert($tracking_topics['f'][$forum_id], 36, 10) + $config['board_startdate'];
- }
- $user_lastmark = (isset($mark_time[$forum_id])) ? $mark_time[$forum_id] : $user_lastmark;
- foreach ($topic_ids as $topic_id)
- {
- if ($global_announce_list && isset($global_announce_list[$topic_id]))
- {
- $last_read[$topic_id] = (isset($mark_time[0])) ? $mark_time[0] : $user_lastmark;
- }
- else
- {
- $last_read[$topic_id] = $user_lastmark;
- }
- }
- }
- }
- return $last_read;
- }
- /**
- * Check for read forums and update topic tracking info accordingly
- *
- * @param int $forum_id the forum id to check
- * @param int $forum_last_post_time the forums last post time
- * @param int $f_mark_time the forums last mark time if user is registered and load_db_lastread enabled
- * @param int $mark_time_forum false if the mark time needs to be obtained, else the last users forum mark time
- *
- * @return true if complete forum got marked read, else false.
- */
- function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time = false, $mark_time_forum = false)
- {
- global $db, $tracking_topics, $user, $config;
- // Determine the users last forum mark time if not given.
- if ($mark_time_forum === false)
- {
- if ($config['load_db_lastread'] && $user->data['is_registered'])
- {
- $mark_time_forum = (!empty($f_mark_time)) ? $f_mark_time : $user->data['user_lastmark'];
- }
- else if ($config['load_anon_lastread'] || $user->data['is_registered'])
- {
- $tracking_topics = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : '';
- $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
- if (!$user->data['is_registered'])
- {
- $user->data['user_lastmark'] = (isset($tracking_topics['l'])) ? (int) (base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate']) : 0;
- }
- $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'];
- }
- }
- // Check the forum for any left unread topics.
- // If there are none, we mark the forum as read.
- if ($config['load_db_lastread'] && $user->data['is_registered'])
- {
- if ($mark_time_forum >= $forum_last_post_time)
- {
- // We do not need to mark read, this happened before. Therefore setting this to true
- $row = true;
- }
- else
- {
- $sql = 'SELECT t.forum_id FROM ' . TOPICS_TABLE . ' t
- LEFT JOIN ' . TOPICS_TRACK_TABLE . ' tt ON (tt.topic_id = t.topic_id AND tt.user_id = ' . $user->data['user_id'] . ')
- WHERE t.forum_id = ' . $forum_id . '
- AND t.topic_last_post_time > ' . $mark_time_forum . '
- AND t.topic_moved_id = 0
- AND (tt.topic_id IS NULL OR tt.mark_time < t.topic_last_post_time)
- GROUP BY t.forum_id';
- $result = $db->sql_query_limit($sql, 1);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
- }
- }
- else if ($config['load_anon_lastread'] || $user->data['is_registered'])
- {
- // Get information from cookie
- $row = false;
- if (!isset($tracking_topics['tf'][$forum_id]))
- {
- // We do not need to mark read, this happened before. Therefore setting this to true
- $row = true;
- }
- else
- {
- $sql = 'SELECT topic_id
- FROM ' . TOPICS_TABLE . '
- WHERE forum_id = ' . $forum_id . '
- AND topic_last_post_time > ' . $mark_time_forum . '
- AND topic_moved_id = 0';
- $result = $db->sql_query($sql);
- $check_forum = $tracking_topics['tf'][$forum_id];
- $unread = false;
- while ($row = $db->sql_fetchrow($result))
- {
- if (!isset($check_forum[base_convert($row['topic_id'], 10, 36)]))
- {
- $unread = true;
- break;
- }
- }
- $db->sql_freeresult($result);
- $row = $unread;
- }
- }
- else
- {
- $row = true;
- }
- if (!$row)
- {
- markread('topics', $forum_id);
- return true;
- }
- return false;
- }
- /**
- * Transform an array into a serialized format
- */
- function tracking_serialize($input)
- {
- $out = '';
- foreach ($input as $key => $value)
- {
- if (is_array($value))
- {
- $out .= $key . ':(' . tracking_serialize($value) . ');';
- }
- else
- {
- $out .= $key . ':' . $value . ';';
- }
- }
- return $out;
- }
- /**
- * Transform a serialized array into an actual array
- */
- function tracking_unserialize($string, $max_depth = 3)
- {
- $n = strlen($string);
- if ($n > 10010)
- {
- die('Invalid data supplied');
- }
- $data = $stack = array();
- $key = '';
- $mode = 0;
- $level = &$data;
- for ($i = 0; $i < $n; ++$i)
- {
- switch ($mode)
- {
- case 0:
- switch ($string[$i])
- {
- case ':':
- $level[$key] = 0;
- $mode = 1;
- break;
- case ')':
- unset($level);
- $level = array_pop($stack);
- $mode = 3;
- break;
- default:
- $key .= $string[$i];
- }
- break;
- case 1:
- switch ($string[$i])
- {
- case '(':
- if (sizeof($stack) >= $max_depth)
- {
- die('Invalid data supplied');
- }
- $stack[] = &$level;
- $level[$key] = array();
- $level = &$level[$key];
- $key = '';
- $mode = 0;
- break;
- default:
- $level[$key] = $string[$i];
- $mode = 2;
- break;
- }
- break;
- case 2:
- switch ($string[$i])
- {
- case ')':
- unset($level);
- $level = array_pop($stack);
- $mode = 3;
- break;
- case ';':
- $key = '';
- $mode = 0;
- break;
- default:
- $level[$key] .= $string[$i];
- break;
- }
- break;
- case 3:
- switch ($string[$i])
- {
- case ')':
- unset($level);
- $level = array_pop($stack);
- break;
- case ';':
- $key = '';
- $mode = 0;
- break;
- default:
- die('Invalid data supplied');
- break;
- }
- break;
- }
- }
- if (sizeof($stack) != 0 || ($mode != 0 && $mode != 3))
- {
- die('Invalid data supplied');
- }
- return $level;
- }
- // Pagination functions
- /**
- * Pagination routine, generates page number sequence
- * tpl_prefix is for using different pagination blocks at one page
- */
- function generate_pagination($base_url, $num_items, $per_page, $start_item, $add_prevnext_text = false, $tpl_prefix = '')
- {
- global $template, $user;
- // Make sure $per_page is a valid value
- $per_page = ($per_page <= 0) ? 1 : $per_page;
- $seperator = '<span class="page-sep">' . $user->lang['COMMA_SEPARATOR'] . '</span>';
- $total_pages = ceil($num_items / $per_page);
- if ($total_pages == 1 || !$num_items)
- {
- return false;
- }
- $on_page = floor($start_item / $per_page) + 1;
- $url_delim = (strpos($base_url, '?') === false) ? '?' : '&';
- $page_string = ($on_page == 1) ? '<strong>1</strong>' : '<a href="' . $base_url . '">1</a>';
- if ($total_pages > 5)
- {
- $start_cnt = min(max(1, $on_page - 4), $total_pages - 5);
- $end_cnt = max(min($total_pages, $on_page + 4), 6);
- $page_string .= ($start_cnt > 1) ? ' ... ' : $seperator;
- for ($i = $start_cnt + 1; $i < $end_cnt; $i++)
- {
- $page_string .= ($i == $on_page) ? '<strong>' . $i . '</strong>' : '<a href="' . $base_url . "{$url_delim}start=" . (($i - 1) * $per_page) . '">' . $i . '</a>';
- if ($i < $end_cnt - 1)
- {
- $page_string .= $seperator;
- }
- }
- $page_string .= ($end_cnt < $total_pages) ? ' ... ' : $seperator;
- }
- else
- {
- $page_string .= $seperator;
- for ($i = 2; $i < $total_pages; $i++)
- {
- $page_string .= ($i == $on_page) ? '<strong>' . $i . '</strong>' : '<a href="' . $base_url . "{$url_delim}start=" . (($i - 1) * $per_page) . '">' . $i . '</a>';
- if ($i < $total_pages)
- {
- $page_string .= $seperator;
- }
- }
- }
- $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>';
- if ($add_prevnext_text)
- {
- if ($on_page != 1)
- {
- $page_string = '<a href="' . $base_url . "{$url_delim}start=" . (($on_page - 2) * $per_page) . '">' . $user->lang['PREVIOUS'] . '</a> ' . $page_string;
- }
- if ($on_page != $total_pages)
- {
- $page_string .= ' <a href="' . $base_url . "{$url_delim}start=" . ($on_page * $per_page) . '">' . $user->lang['NEXT'] . '</a>';
- }
- }
- $template->assign_vars(array(
- $tpl_prefix . 'BASE_URL' => $base_url,
- 'A_' . $tpl_prefix . 'BASE_URL' => addslashes($base_url),
- $tpl_prefix . 'PER_PAGE' => $per_page,
- $tpl_prefix . 'PREVIOUS_PAGE' => ($on_page == 1) ? '' : $base_url . "{$url_delim}start=" . (($on_page - 2) * $per_page),
- $tpl_prefix . 'NEXT_PAGE' => ($on_page == $total_pages) ? '' : $base_url . "{$url_delim}start=" . ($on_page * $per_page),
- $tpl_prefix . 'TOTAL_PAGES' => $total_pages,
- ));
- return $page_string;
- }
- /**
- * Return current page (pagination)
- */
- function on_page($num_items, $per_page, $start)
- {
- global $template, $user;
- // Make sure $per_page is a valid value
- $per_page = ($per_page <= 0) ? 1 : $per_page;
- $on_page = floor($start / $per_page) + 1;
- $template->assign_vars(array(
- 'ON_PAGE' => $on_page)
- );
- return sprintf($user->lang['PAGE_OF'], $on_page, max(ceil($num_items / $per_page), 1));
- }
- // Server functions (building urls, redirecting...)
- /**
- * Append session id to url.
- * This function supports hooks.
- *
- * @param string $url The url the session id needs to be appended to (can have params)
- * @param mixed $params String or array of additional url parameters
- * @param bool $is_amp Is url using & (true) or & (false)
- * @param string $session_id Possibility to use a custom session id instead of the global one
- *
- * Examples:
- * <code>
- * append_sid("{$phpbb_root_path}viewtopic.$phpEx?t=1&f=2");
- * append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=1&f=2');
- * append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=1&f=2', false);
- * append_sid("{$phpbb_root_path}viewtopic.$phpEx", array('t' => 1, 'f' => 2));
- * </code>
- *
- */
- function append_sid($url, $params = false, $is_amp = true, $session_id = false)
- {
- global $_SID, $_EXTRA_URL, $phpbb_hook;
- // Developers using the hook function need to globalise the $_SID and $_EXTRA_URL on their own and also handle it appropiatly.
- // They could mimick most of what is within this function
- if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__, $url, $params, $is_amp, $session_id))
- {
- if ($phpbb_hook->hook_return(__FUNCTION__))
- {
- return $phpbb_hook->hook_return_result(__FUNCTION__);
- }
- }
- $params_is_array = is_array($params);
- // Get anchor
- $anchor = '';
- if (strpos($url, '#') !== false)
- {
- list($url, $anchor) = explode('#', $url, 2);
- $anchor = '#' . $anchor;
- }
- else if (!$params_is_array && strpos($params, '#') !== false)
- {
- list($params, $anchor) = explode('#', $params, 2);
- $anchor = '#' . $anchor;
- }
- // Handle really simple cases quickly
- if ($_SID == '' && $session_id === false && empty($_EXTRA_URL) && !$params_is_array && !$anchor)
- {
- if ($params === false)
- {
- return $url;
- }
- $url_delim = (strpos($url, '?') === false) ? '?' : (($is_amp) ? '&' : '&');
- return $url . ($params !== false ? $url_delim. $params : '');
- }
- // Assign sid if session id is not specified
- if ($session_id === false)
- {
- $session_id = $_SID;
- }
- $amp_delim = ($is_amp) ? '&' : '&';
- $url_delim = (strpos($url, '?') === false) ? '?' : $amp_delim;
- // Appending custom url parameter?
- $append_url = (!empty($_EXTRA_URL)) ? implode($amp_delim, $_EXTRA_URL) : '';
- // Use the short variant if possible ;)
- if ($params === false)
- {
- // Append session id
- if (!$session_id)
- {
- return $url . (($append_url) ? $url_delim . $append_url : '') . $anchor;
- }
- else
- {
- return $url . (($append_url) ? $url_delim . $append_url . $amp_delim : $url_delim) . 'sid=' . $session_id . $anchor;
- }
- }
- // Build string if parameters are specified as array
- if (is_array($params))
- {
- $output = array();
- foreach ($params as $key => $item)
- {
- if ($item === NULL)
- {
- continue;
- }
- if ($key == '#')
- {
- $anchor = '#' . $item;
- continue;
- }
- $output[] = $key . '=' . $item;
- }
- $params = implode($amp_delim, $output);
- }
- // Append session id and parameters (even if they are empty)
- // If parameters are empty, the developer can still append his/her parameters without caring about the delimiter
- return $url . (($append_url) ? $url_delim . $append_url . $amp_delim : $url_delim) . $params . ((!$session_id) ? '' : $amp_delim . 'sid=' . $session_id) . $anchor;
- }
- /**
- * Generate board url (example: http://www.example.com/phpBB)
- * @param bool $without_script_path if set to true the script path gets not appended (example: http://www.example.com)
- */
- function generate_board_url($without_script_path = false)
- {
- global $config, $user;
- $server_name = $user->host;
- $server_port = (!empty($_SERVER['SERVER_PORT'])) ? (int) $_SERVER['SERVER_PORT'] : (int) getenv('SERVER_PORT');
- // Forcing server vars is the only way to specify/override the protocol
- if ($config['force_server_vars'] || !$server_name)
- {
- $server_protocol = ($config['server_protocol']) ? $config['server_protocol'] : (($config['cookie_secure']) ? 'https://' : 'http://');
- $serv…
Large files files are truncated, but you can click here to view the full file