aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/includes/functions.php
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB/includes/functions.php')
-rw-r--r--phpBB/includes/functions.php2326
1 files changed, 1344 insertions, 982 deletions
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php
index eef4ade4e7..689a682de3 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -2,9 +2,8 @@
/**
*
* @package phpBB3
-* @version $Id$
* @copyright (c) 2005 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
@@ -17,123 +16,82 @@ if (!defined('IN_PHPBB'))
}
// Common global functions
-
/**
-* set_var
-*
-* Set variable, used by {@link request_var the request_var function}
+* Casts a variable to the given type.
*
-* @access private
+* @deprecated
*/
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;
- }
+ // no need for dependency injection here, if you have the object, call the method yourself!
+ $type_cast_helper = new \phpbb\request\type_cast_helper();
+ $type_cast_helper->set_var($result, $var, $type, $multibyte);
}
/**
-* request_var
+* Wrapper function of \phpbb\request\request::variable which exists for backwards compatability.
+* See {@link \phpbb\request\request_interface::variable \phpbb\request\request_interface::variable} for
+* documentation of this function's use.
*
-* Used to get passed variable
+* @deprecated
+* @param mixed $var_name The form variable's name from which data shall be retrieved.
+* If the value is an array this may be an array of indizes which will give
+* direct access to a value at any depth. E.g. if the value of "var" is array(1 => "a")
+* then specifying array("var", 1) as the name will return "a".
+* If you pass an instance of {@link \phpbb\request\request_interface phpbb_request_interface}
+* as this parameter it will overwrite the current request class instance. If you do
+* not do so, it will create its own instance (but leave superglobals enabled).
+* @param mixed $default A default value that is returned if the variable was not set.
+* This function will always return a value of the same type as the default.
+* @param bool $multibyte If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters
+* Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks
+* @param bool $cookie This param is mapped to \phpbb\request\request_interface::COOKIE as the last param for
+* \phpbb\request\request_interface::variable for backwards compatability reasons.
+* @param \phpbb\request\request_interface|null|false If an instance of \phpbb\request\request_interface is given the instance is stored in
+* a static variable and used for all further calls where this parameters is null. Until
+* the function is called with an instance it automatically creates a new \phpbb\request\request
+* instance on every call. By passing false this per-call instantiation can be restored
+* after having passed in a \phpbb\request\request_interface instance.
+*
+* @return mixed The value of $_REQUEST[$var_name] run through {@link set_var set_var} to ensure that the type is the
+* the same as that of $default. If the variable is not set $default is returned.
*/
-function request_var($var_name, $default, $multibyte = false, $cookie = false)
+function request_var($var_name, $default, $multibyte = false, $cookie = false, $request = null)
{
- 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];
- }
+ // This is all just an ugly hack to add "Dependency Injection" to a function
+ // the only real code is the function call which maps this function to a method.
+ static $static_request = null;
- $super_global = ($cookie) ? '_COOKIE' : '_REQUEST';
- if (!isset($GLOBALS[$super_global][$var_name]) || is_array($GLOBALS[$super_global][$var_name]) != is_array($default))
+ if ($request instanceof \phpbb\request\request_interface)
{
- return (is_array($default)) ? array() : $default;
- }
+ $static_request = $request;
- $var = $GLOBALS[$super_global][$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')
+ if (empty($var_name))
{
- 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);
+ return;
}
}
-
- if (is_array($var))
+ else if ($request === false)
{
- $_var = $var;
- $var = array();
+ $static_request = null;
- foreach ($_var as $k => $v)
+ if (empty($var_name))
{
- 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, $multibyte);
- 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);
- }
+ return;
}
}
- else
+
+ $tmp_request = $static_request;
+
+ // no request class set, create a temporary one ourselves to keep backwards compatability
+ if ($tmp_request === null)
{
- set_var($var, $var, $type, $multibyte);
+ // false param: enable super globals, so the created request class does not
+ // make super globals inaccessible everywhere outside this function.
+ $tmp_request = new \phpbb\request\request(new \phpbb\request\type_cast_helper(), false);
}
- return $var;
+ return $tmp_request->variable($var_name, $default, $multibyte, ($cookie) ? \phpbb\request\request_interface::COOKIE : \phpbb\request\request_interface::REQUEST);
}
/**
@@ -149,31 +107,24 @@ function request_var($var_name, $default, $multibyte = false, $cookie = false)
* efficiently cached.
*
* @return null
+*
+* @deprecated
*/
-function set_config($config_name, $config_value, $is_dynamic = false)
+function set_config($config_name, $config_value, $is_dynamic = false, \phpbb\config\config $set_config = null)
{
- global $db, $cache, $config;
+ static $config = null;
- $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]))
+ if ($set_config !== null)
{
- $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;
+ $config = $set_config;
- if (!$is_dynamic)
- {
- $cache->destroy('config');
+ if (empty($config_name))
+ {
+ return;
+ }
}
+
+ $config->set($config_name, $config_value, !$is_dynamic);
}
/**
@@ -186,35 +137,24 @@ function set_config($config_name, $config_value, $is_dynamic = false)
* efficiently cached.
*
* @return null
+*
+* @deprecated
*/
-function set_config_count($config_name, $increment, $is_dynamic = false)
+function set_config_count($config_name, $increment, $is_dynamic = false, \phpbb\config\config $set_config = null)
{
- global $db, $cache;
+ static $config = null;
- switch ($db->sql_layer)
+ if ($set_config !== null)
{
- case 'firebird':
- // Precision must be from 1 to 18
- $sql_update = 'CAST(CAST(config_value as DECIMAL(18, 0)) + ' . (int) $increment . ' as VARCHAR(255))';
- break;
+ $config = $set_config;
- case 'postgres':
- // Need to cast to text first for PostgreSQL 7.x
- $sql_update = 'CAST(CAST(config_value::text as DECIMAL(255, 0)) + ' . (int) $increment . ' as VARCHAR(255))';
- break;
-
- // MySQL, SQlite, mssql, mssql_odbc, oracle
- default:
- $sql_update = 'config_value + ' . (int) $increment;
- break;
+ if (empty($config_name))
+ {
+ return;
+ }
}
- $db->sql_query('UPDATE ' . CONFIG_TABLE . ' SET config_value = ' . $sql_update . " WHERE config_name = '" . $db->sql_escape($config_name) . "'");
-
- if (!$is_dynamic)
- {
- $cache->destroy('config');
- }
+ $config->increment($config_name, $increment, !$is_dynamic);
}
/**
@@ -428,73 +368,27 @@ function still_on_time($extra_time = 15)
}
/**
+* Hash the password
*
-* @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.
+* @deprecated 3.1.0-a2 (To be removed: 3.3.0)
*
+* @param string $password Password to be hashed
*
-* Hash the password
+* @return string|bool Password hash or false if something went wrong during hashing
*/
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);
- }
+ global $phpbb_container;
- 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);
+ $passwords_manager = $phpbb_container->get('passwords.manager');
+ return $passwords_manager->hash($password);
}
/**
* Check for correct password
*
+* @deprecated 3.1.0-a2 (To be removed: 3.3.0)
+*
* @param string $password The password in plain text
* @param string $hash The stored password hash
*
@@ -502,142 +396,10 @@ function phpbb_hash($password)
*/
function phpbb_check_hash($password, $hash)
{
- if (strlen($password) > 4096)
- {
- // If the password is too huge, we will simply reject it
- // and not let the server try to hash it.
- return false;
- }
-
- $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
- if (strlen($hash) == 34)
- {
- return (_hash_crypt_private($password, $hash, $itoa64) === $hash) ? true : false;
- }
+ global $phpbb_container;
- 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$' && substr($setting, 0, 3) != '$P$')
- {
- 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;
+ $passwords_manager = $phpbb_container->get('passwords.manager');
+ return $passwords_manager->check($password, $hash);
}
/**
@@ -915,102 +677,13 @@ function phpbb_is_writable($file)
}
}
-// 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)
+function phpbb_is_absolute($path)
{
return (isset($path[0]) && $path[0] == '/' || preg_match('#^[a-z]:[/\\\]#i', $path)) ? true : false;
}
@@ -1023,6 +696,8 @@ function is_absolute($path)
*/
function phpbb_own_realpath($path)
{
+ global $request;
+
// Now to perform funky shizzle
// Switch to use UNIX slashes
@@ -1030,7 +705,7 @@ function phpbb_own_realpath($path)
$path_prefix = '';
// Determine what sort of path we have
- if (is_absolute($path))
+ if (phpbb_is_absolute($path))
{
$absolute = true;
@@ -1066,11 +741,12 @@ function phpbb_own_realpath($path)
$path_prefix = '';
}
}
- else if (isset($_SERVER['SCRIPT_FILENAME']) && !empty($_SERVER['SCRIPT_FILENAME']))
+ else if ($request->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;
+ $filename = htmlspecialchars_decode($request->server('SCRIPT_FILENAME'));
+ $path = str_replace(DIRECTORY_SEPARATOR, '/', dirname($filename)) . '/' . $path;
$absolute = true;
$path_prefix = '';
}
@@ -1212,43 +888,41 @@ else
/**
* Eliminates useless . and .. components from specified path.
*
+* Deprecated, use filesystem class instead
+*
* @param string $path Path to clean
* @return string Cleaned path
+*
+* @deprecated
*/
function phpbb_clean_path($path)
{
- $exploded = explode('/', $path);
- $filtered = array();
- foreach ($exploded as $part)
+ global $phpbb_path_helper, $phpbb_container;
+
+ if (!$phpbb_path_helper && $phpbb_container)
{
- if ($part === '.' && !empty($filtered))
+ $phpbb_path_helper = $phpbb_container->get('path_helper');
+ }
+ else if (!$phpbb_path_helper)
+ {
+ // The container is not yet loaded, use a new instance
+ if (!class_exists('\phpbb\path_helper'))
{
- continue;
+ global $phpbb_root_path, $phpEx;
+ require($phpbb_root_path . 'phpbb/path_helper.' . $phpEx);
}
- if ($part === '..' && !empty($filtered) && $filtered[sizeof($filtered) - 1] !== '..')
- {
- array_pop($filtered);
- }
- else
- {
- $filtered[] = $part;
- }
+ $phpbb_path_helper = new phpbb\path_helper(
+ new phpbb\symfony_request(
+ new phpbb\request\request()
+ ),
+ new phpbb\filesystem(),
+ $phpbb_root_path,
+ $phpEx
+ );
}
- $path = implode('/', $filtered);
- return $path;
-}
-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)));
- }
+ return $phpbb_path_helper->clean_path($path);
}
// functions used for building option fields
@@ -1302,32 +976,203 @@ function style_select($default = '', $all = false)
}
/**
+* Format the timezone offset with hours and minutes
+*
+* @param int $tz_offset Timezone offset in seconds
+* @return string Normalized offset string: -7200 => -02:00
+* 16200 => +04:30
+*/
+function phpbb_format_timezone_offset($tz_offset)
+{
+ $sign = ($tz_offset < 0) ? '-' : '+';
+ $time_offset = abs($tz_offset);
+
+ $offset_seconds = $time_offset % 3600;
+ $offset_minutes = $offset_seconds / 60;
+ $offset_hours = ($time_offset - $offset_seconds) / 3600;
+
+ $offset_string = sprintf("%s%02d:%02d", $sign, $offset_hours, $offset_minutes);
+ return $offset_string;
+}
+
+/**
+* Compares two time zone labels.
+* Arranges them in increasing order by timezone offset.
+* Places UTC before other timezones in the same offset.
+*/
+function phpbb_tz_select_compare($a, $b)
+{
+ $a_sign = $a[3];
+ $b_sign = $b[3];
+ if ($a_sign != $b_sign)
+ {
+ return $a_sign == '-' ? -1 : 1;
+ }
+
+ $a_offset = substr($a, 4, 5);
+ $b_offset = substr($b, 4, 5);
+ if ($a_offset == $b_offset)
+ {
+ $a_name = substr($a, 12);
+ $b_name = substr($b, 12);
+ if ($a_name == $b_name)
+ {
+ return 0;
+ }
+ else if ($a_name == 'UTC')
+ {
+ return -1;
+ }
+ else if ($b_name == 'UTC')
+ {
+ return 1;
+ }
+ else
+ {
+ return $a_name < $b_name ? -1 : 1;
+ }
+ }
+ else
+ {
+ if ($a_sign == '-')
+ {
+ return $a_offset > $b_offset ? -1 : 1;
+ }
+ else
+ {
+ return $a_offset < $b_offset ? -1 : 1;
+ }
+ }
+}
+
+/**
+* Return list of timezone identifiers
+* We also add the selected timezone if we can create an object with it.
+* DateTimeZone::listIdentifiers seems to not add all identifiers to the list,
+* because some are only kept for backward compatible reasons. If the user has
+* a deprecated value, we add it here, so it can still be kept. Once the user
+* changed his value, there is no way back to deprecated values.
+*
+* @param string $selected_timezone Additional timezone that shall
+* be added to the list of identiers
+* @return array DateTimeZone::listIdentifiers and additional
+* selected_timezone if it is a valid timezone.
+*/
+function phpbb_get_timezone_identifiers($selected_timezone)
+{
+ $timezones = DateTimeZone::listIdentifiers();
+
+ if (!in_array($selected_timezone, $timezones))
+ {
+ try
+ {
+ // Add valid timezones that are currently selected but not returned
+ // by DateTimeZone::listIdentifiers
+ $validate_timezone = new DateTimeZone($selected_timezone);
+ $timezones[] = $selected_timezone;
+ }
+ catch (Exception $e)
+ {
+ }
+ }
+
+ return $timezones;
+}
+
+/**
* Pick a timezone
+*
+* @param string $default A timezone to select
+* @param boolean $truncate Shall we truncate the options text
+*
+* @return string Returns the options for timezone selector only
+*
+* @deprecated
*/
function tz_select($default = '', $truncate = false)
{
global $user;
- $tz_select = '';
- foreach ($user->lang['tz_zones'] as $offset => $zone)
+ $timezone_select = phpbb_timezone_select($user, $default, $truncate);
+ return $timezone_select['tz_select'];
+}
+
+/**
+* Options to pick a timezone and date/time
+*
+* @param \phpbb\user $user Object of the current user
+* @param string $default A timezone to select
+* @param boolean $truncate Shall we truncate the options text
+*
+* @return array Returns an array, also containing the options for the time selector.
+*/
+function phpbb_timezone_select($user, $default = '', $truncate = false)
+{
+ static $timezones;
+
+ $default_offset = '';
+ if (!isset($timezones))
{
- if ($truncate)
+ $unsorted_timezones = phpbb_get_timezone_identifiers($default);
+
+ $timezones = array();
+ foreach ($unsorted_timezones as $timezone)
{
- $zone_trunc = truncate_string($zone, 50, 255, false, '...');
+ $tz = new DateTimeZone($timezone);
+ $dt = new \phpbb\datetime($user, 'now', $tz);
+ $offset = $dt->getOffset();
+ $current_time = $dt->format($user->lang['DATETIME_FORMAT'], true);
+ $offset_string = phpbb_format_timezone_offset($offset);
+ $timezones['GMT' . $offset_string . ' - ' . $timezone] = array(
+ 'tz' => $timezone,
+ 'offest' => 'GMT' . $offset_string,
+ 'current' => $current_time,
+ );
+ if ($timezone === $default)
+ {
+ $default_offset = 'GMT' . $offset_string;
+ }
}
- else
+ unset($unsorted_timezones);
+
+ uksort($timezones, 'phpbb_tz_select_compare');
+ }
+
+ $tz_select = $tz_dates = $opt_group = '';
+
+ foreach ($timezones as $timezone)
+ {
+ if ($opt_group != $timezone['offest'])
+ {
+ $tz_select .= ($opt_group) ? '</optgroup>' : '';
+ $tz_select .= '<optgroup label="' . $timezone['offest'] . ' - ' . $timezone['current'] . '">';
+ $opt_group = $timezone['offest'];
+
+ $selected = ($default_offset == $timezone['offest']) ? ' selected="selected"' : '';
+ $tz_dates .= '<option value="' . $timezone['offest'] . ' - ' . $timezone['current'] . '"' . $selected . '>' . $timezone['offest'] . ' - ' . $timezone['current'] . '</option>';
+ }
+
+ $label = $timezone['tz'];
+ if (isset($user->lang['timezones'][$label]))
{
- $zone_trunc = $zone;
+ $label = $user->lang['timezones'][$label];
}
+ $title = $timezone['offest'] . ' - ' . $label;
- if (is_numeric($offset))
+ if ($truncate)
{
- $selected = ($offset == $default) ? ' selected="selected"' : '';
- $tz_select .= '<option title="' . $zone . '" value="' . $offset . '"' . $selected . '>' . $zone_trunc . '</option>';
+ $label = truncate_string($label, 50, 255, false, '...');
}
+
+ $selected = ($timezone['tz'] === $default) ? ' selected="selected"' : '';
+ $tz_select .= '<option title="' . $title . '" value="' . $timezone['tz'] . '"' . $selected . '>' . $label . '</option>';
}
+ $tz_select .= '</optgroup>';
- return $tz_select;
+ return array(
+ 'tz_select' => $tz_select,
+ 'tz_dates' => $tz_dates,
+ );
}
// Functions handling topic/post tracking/marking
@@ -1336,41 +1181,77 @@ function tz_select($default = '', $truncate = false)
* Marks a topic/forum as read
* Marks a topic as posted to
*
+* @param string $mode (all, topics, topic, post)
+* @param int|bool $forum_id Used in all, topics, and topic mode
+* @param int|bool $topic_id Used in topic and post mode
+* @param int $post_time 0 means current time(), otherwise to set a specific mark time
* @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;
+ global $request, $phpbb_container;
+
+ $post_time = ($post_time === 0 || $post_time > time()) ? time() : (int) $post_time;
if ($mode == 'all')
{
if ($forum_id === false || !sizeof($forum_id))
{
+ // Mark all forums read (index page)
+
+ $phpbb_notifications = $phpbb_container->get('notification_manager');
+
+ // Mark all topic notifications read for this user
+ $phpbb_notifications->mark_notifications_read(array(
+ 'topic',
+ 'quote',
+ 'bookmark',
+ 'post',
+ 'approve_topic',
+ 'approve_post',
+ ), false, $user->data['user_id'], $post_time);
+
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']}");
+ $tables = array(TOPICS_TRACK_TABLE, FORUMS_TRACK_TABLE);
+ foreach ($tables as $table)
+ {
+ $sql = 'DELETE FROM ' . $table . "
+ WHERE user_id = {$user->data['user_id']}
+ AND mark_time < $post_time";
+ $db->sql_query($sql);
+ }
+
+ $sql = 'UPDATE ' . USERS_TABLE . "
+ SET user_lastmark = $post_time
+ WHERE user_id = {$user->data['user_id']}
+ AND user_lastmark < $post_time";
+ $db->sql_query($sql);
}
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 = $request->variable($config['cookie_name'] . '_track', '', true, \phpbb\request\request_interface::COOKIE);
$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);
+ $tracking_topics['l'] = base_convert($post_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);
+ $user->set_cookie('track', tracking_serialize($tracking_topics), $post_time + 31536000);
+ $request->overwrite($config['cookie_name'] . '_track', tracking_serialize($tracking_topics), \phpbb\request\request_interface::COOKIE);
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']}");
+ $sql = 'UPDATE ' . USERS_TABLE . "
+ SET user_lastmark = $post_time
+ WHERE user_id = {$user->data['user_id']}
+ AND user_lastmark < $post_time";
+ $db->sql_query($sql);
}
}
}
@@ -1385,6 +1266,32 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
$forum_id = array($forum_id);
}
+ $phpbb_notifications = $phpbb_container->get('notification_manager');
+
+ $phpbb_notifications->mark_notifications_read_by_parent(array(
+ 'topic',
+ 'approve_topic',
+ ), $forum_id, $user->data['user_id'], $post_time);
+
+ // Mark all post/quote notifications read for this user in this forum
+ $topic_ids = array();
+ $sql = 'SELECT topic_id
+ FROM ' . TOPICS_TABLE . '
+ WHERE ' . $db->sql_in_set('forum_id', $forum_id);
+ $result = $db->sql_query($sql);
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $topic_ids[] = $row['topic_id'];
+ }
+ $db->sql_freeresult($result);
+
+ $phpbb_notifications->mark_notifications_read_by_parent(array(
+ 'quote',
+ 'bookmark',
+ 'post',
+ 'approve_post',
+ ), $topic_ids, $user->data['user_id'], $post_time);
+
// Add 0 to forums array to mark global announcements correctly
// $forum_id[] = 0;
@@ -1392,6 +1299,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
{
$sql = 'DELETE FROM ' . TOPICS_TRACK_TABLE . "
WHERE user_id = {$user->data['user_id']}
+ AND mark_time < $post_time
AND " . $db->sql_in_set('forum_id', $forum_id);
$db->sql_query($sql);
@@ -1410,9 +1318,10 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
if (sizeof($sql_update))
{
- $sql = 'UPDATE ' . FORUMS_TRACK_TABLE . '
- SET mark_time = ' . time() . "
+ $sql = 'UPDATE ' . FORUMS_TRACK_TABLE . "
+ SET mark_time = $post_time
WHERE user_id = {$user->data['user_id']}
+ AND mark_time < $post_time
AND " . $db->sql_in_set('forum_id', $sql_update);
$db->sql_query($sql);
}
@@ -1425,7 +1334,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
$sql_ary[] = array(
'user_id' => (int) $user->data['user_id'],
'forum_id' => (int) $f_id,
- 'mark_time' => time()
+ 'mark_time' => $post_time,
);
}
@@ -1434,7 +1343,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
}
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 = $request->variable($config['cookie_name'] . '_track', '', true, \phpbb\request\request_interface::COOKIE);
$tracking = ($tracking) ? tracking_unserialize($tracking) : array();
foreach ($forum_id as $f_id)
@@ -1456,7 +1365,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
unset($tracking['f'][$f_id]);
}
- $tracking['f'][$f_id] = base_convert(time() - $config['board_startdate'], 10, 36);
+ $tracking['f'][$f_id] = base_convert($post_time - $config['board_startdate'], 10, 36);
}
if (isset($tracking['tf']) && empty($tracking['tf']))
@@ -1464,8 +1373,8 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
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);
+ $user->set_cookie('track', tracking_serialize($tracking), $post_time + 31536000);
+ $request->overwrite($config['cookie_name'] . '_track', tracking_serialize($tracking), \phpbb\request\request_interface::COOKIE);
unset($tracking);
}
@@ -1479,11 +1388,27 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
return;
}
+ $phpbb_notifications = $phpbb_container->get('notification_manager');
+
+ // Mark post notifications read for this user in this topic
+ $phpbb_notifications->mark_notifications_read(array(
+ 'topic',
+ 'approve_topic',
+ ), $topic_id, $user->data['user_id'], $post_time);
+
+ $phpbb_notifications->mark_notifications_read_by_parent(array(
+ 'quote',
+ 'bookmark',
+ 'post',
+ 'approve_post',
+ ), $topic_id, $user->data['user_id'], $post_time);
+
if ($config['load_db_lastread'] && $user->data['is_registered'])
{
- $sql = 'UPDATE ' . TOPICS_TRACK_TABLE . '
- SET mark_time = ' . (($post_time) ? $post_time : time()) . "
+ $sql = 'UPDATE ' . TOPICS_TRACK_TABLE . "
+ SET mark_time = $post_time
WHERE user_id = {$user->data['user_id']}
+ AND mark_time < $post_time
AND topic_id = $topic_id";
$db->sql_query($sql);
@@ -1496,7 +1421,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
'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(),
+ 'mark_time' => $post_time,
);
$db->sql_query('INSERT INTO ' . TOPICS_TRACK_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
@@ -1506,7 +1431,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
}
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 = $request->variable($config['cookie_name'] . '_track', '', true, \phpbb\request\request_interface::COOKIE);
$tracking = ($tracking) ? tracking_unserialize($tracking) : array();
$topic_id36 = base_convert($topic_id, 10, 36);
@@ -1516,12 +1441,11 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
$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)
+ if (strlen($request->variable($config['cookie_name'] . '_track', '', true, \phpbb\request\request_interface::COOKIE)) > 10000)
{
//echo 'Cookie grown too large' . print_r($tracking, true);
@@ -1552,7 +1476,12 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
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']}");
+
+ $sql = 'UPDATE ' . USERS_TABLE . "
+ SET user_lastmark = $post_time
+ WHERE user_id = {$user->data['user_id']}
+ AND mark_time < $post_time";
+ $db->sql_query($sql);
}
else
{
@@ -1560,8 +1489,8 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
}
}
- $user->set_cookie('track', tracking_serialize($tracking), time() + 31536000);
- $_COOKIE[$config['cookie_name'] . '_track'] = (STRIP) ? addslashes(tracking_serialize($tracking)) : tracking_serialize($tracking);
+ $user->set_cookie('track', tracking_serialize($tracking), $post_time + 31536000);
+ $request->overwrite($config['cookie_name'] . '_track', tracking_serialize($tracking), \phpbb\request\request_interface::COOKIE);
}
return;
@@ -1582,7 +1511,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
$sql_ary = array(
'user_id' => (int) $use_user_id,
'topic_id' => (int) $topic_id,
- 'topic_posted' => 1
+ 'topic_posted' => 1,
);
$db->sql_query('INSERT INTO ' . TOPICS_POSTED_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
@@ -1622,35 +1551,6 @@ function get_topic_tracking($forum_id, $topic_ids, &$rowset, $forum_mark_time, $
{
$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];
@@ -1660,14 +1560,7 @@ function get_topic_tracking($forum_id, $topic_ids, &$rowset, $forum_mark_time, $
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;
- }
+ $last_read[$topic_id] = $user_lastmark;
}
}
@@ -1679,7 +1572,7 @@ function get_topic_tracking($forum_id, $topic_ids, &$rowset, $forum_mark_time, $
*/
function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_list = false)
{
- global $config, $user;
+ global $config, $user, $request;
$last_read = array();
@@ -1711,8 +1604,7 @@ function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_lis
$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");
+ AND forum_id = $forum_id";
$result = $db->sql_query($sql);
$mark_time = array();
@@ -1726,14 +1618,7 @@ function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_lis
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;
- }
+ $last_read[$topic_id] = $user_lastmark;
}
}
}
@@ -1743,7 +1628,7 @@ function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_lis
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 = $request->variable($config['cookie_name'] . '_track', '', true, \phpbb\request\request_interface::COOKIE);
$tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
}
@@ -1771,13 +1656,6 @@ function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_lis
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]))
{
@@ -1788,14 +1666,7 @@ function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_lis
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;
- }
+ $last_read[$topic_id] = $user_lastmark;
}
}
}
@@ -1943,7 +1814,7 @@ function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $s
*/
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, $auth;
+ global $db, $tracking_topics, $user, $config, $auth, $request, $phpbb_container;
// Determine the users last forum mark time if not given.
if ($mark_time_forum === false)
@@ -1954,7 +1825,7 @@ function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_ti
}
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 = $request->variable($config['cookie_name'] . '_track', '', true, \phpbb\request\request_interface::COOKIE);
$tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
if (!$user->data['is_registered'])
@@ -1968,7 +1839,7 @@ function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_ti
// Handle update of unapproved topics info.
// Only update for moderators having m_approve permission for the forum.
- $sql_update_unapproved = ($auth->acl_get('m_approve', $forum_id)) ? '': 'AND t.topic_approved = 1';
+ $phpbb_content_visibility = $phpbb_container->get('content.visibility');
// Check the forum for any left unread topics.
// If there are none, we mark the forum as read.
@@ -1988,8 +1859,8 @@ function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_ti
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 ' .
- $sql_update_unapproved . '
+ AND t.topic_moved_id = 0
+ AND ' . $phpbb_content_visibility->get_visibility_sql('topic', $forum_id, 't.') . '
AND (tt.topic_id IS NULL
OR tt.mark_time < t.topic_last_post_time)';
$result = $db->sql_query_limit($sql, 1);
@@ -2013,8 +1884,8 @@ function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_ti
FROM ' . TOPICS_TABLE . ' t
WHERE t.forum_id = ' . $forum_id . '
AND t.topic_last_post_time > ' . $mark_time_forum . '
- AND t.topic_moved_id = 0 ' .
- $sql_update_unapproved;
+ AND t.topic_moved_id = 0
+ AND ' . $phpbb_content_visibility->get_visibility_sql('topic', $forum_id, 't.');
$result = $db->sql_query($sql);
$check_forum = $tracking_topics['tf'][$forum_id];
@@ -2168,111 +2039,6 @@ function tracking_unserialize($string, $max_depth = 3)
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) ? '?' : ((strpos($base_url, '?') === strlen($base_url) - 1) ? '' : '&amp;');
-
- $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) ? '<span class="page-dots"> ... </span>' : $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) ? '<span class="page-dots"> ... </span>' : $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>&nbsp;&nbsp;' . $page_string;
- }
-
- if ($on_page != $total_pages)
- {
- $page_string .= '&nbsp;&nbsp;<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...)
/**
@@ -2295,7 +2061,8 @@ function on_page($num_items, $per_page, $start)
*/
function append_sid($url, $params = false, $is_amp = true, $session_id = false)
{
- global $_SID, $_EXTRA_URL, $phpbb_hook;
+ global $_SID, $_EXTRA_URL, $phpbb_hook, $phpbb_path_helper;
+ global $phpbb_dispatcher;
if ($params === '' || (is_array($params) && empty($params)))
{
@@ -2303,6 +2070,45 @@ function append_sid($url, $params = false, $is_amp = true, $session_id = false)
$params = false;
}
+ // Update the root path with the correct relative web path
+ if ($phpbb_path_helper instanceof \phpbb\path_helper)
+ {
+ $url = $phpbb_path_helper->update_web_root_path($url);
+ }
+
+ $append_sid_overwrite = false;
+
+ /**
+ * This event can either supplement or override the append_sid() function
+ *
+ * To override this function, the event must set $append_sid_overwrite to
+ * the new URL value, which will be returned following the event
+ *
+ * @event core.append_sid
+ * @var string url The url the session id needs
+ * to be appended to (can have
+ * params)
+ * @var mixed params String or array of additional
+ * url parameters
+ * @var bool is_amp Is url using &amp; (true) or
+ * & (false)
+ * @var bool|string session_id Possibility to use a custom
+ * session id (string) instead of
+ * the global one (false)
+ * @var bool|string append_sid_overwrite Overwrite function (string
+ * URL) or not (false)
+ * @since 3.1-A1
+ */
+ $vars = array('url', 'params', 'is_amp', 'session_id', 'append_sid_overwrite');
+ extract($phpbb_dispatcher->trigger_event('core.append_sid', compact($vars)));
+
+ if ($append_sid_overwrite)
+ {
+ return $append_sid_overwrite;
+ }
+
+ // The following hook remains for backwards compatibility, though use of
+ // the event above is preferred.
// Developers using the hook function need to globalise the $_SID and $_EXTRA_URL on their own and also handle it appropriately.
// They could mimic most of what is within this function
if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__, $url, $params, $is_amp, $session_id))
@@ -2404,10 +2210,10 @@ function append_sid($url, $params = false, $is_amp = true, $session_id = false)
*/
function generate_board_url($without_script_path = false)
{
- global $config, $user;
+ global $config, $user, $request;
$server_name = $user->host;
- $server_port = (!empty($_SERVER['SERVER_PORT'])) ? (int) $_SERVER['SERVER_PORT'] : (int) getenv('SERVER_PORT');
+ $server_port = $request->server('SERVER_PORT', 0);
// Forcing server vars is the only way to specify/override the protocol
if ($config['force_server_vars'] || !$server_name)
@@ -2423,7 +2229,7 @@ function generate_board_url($without_script_path = false)
else
{
// Do not rely on cookie_secure, users seem to think that it means a secured cookie instead of an encrypted connection
- $cookie_secure = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 1 : 0;
+ $cookie_secure = $request->is_secure() ? 1 : 0;
$url = (($cookie_secure) ? 'https://' : 'http://') . $server_name;
$script_path = $user->page['root_script_path'];
@@ -2462,7 +2268,7 @@ function generate_board_url($without_script_path = false)
*/
function redirect($url, $return = false, $disable_cd_check = false)
{
- global $db, $cache, $config, $user, $phpbb_root_path;
+ global $db, $cache, $config, $user, $phpbb_root_path, $phpbb_filesystem, $phpbb_path_helper, $phpEx;
$failover_flag = false;
@@ -2505,84 +2311,40 @@ function redirect($url, $return = false, $disable_cd_check = false)
// Relative uri
$pathinfo = pathinfo($url);
- if (!$disable_cd_check && !file_exists($pathinfo['dirname'] . '/'))
+ // Is the uri pointing to the current directory?
+ if ($pathinfo['dirname'] == '.')
{
- $url = str_replace('../', '', $url);
- $pathinfo = pathinfo($url);
+ $url = str_replace('./', '', $url);
- if (!file_exists($pathinfo['dirname'] . '/'))
+ // Strip / from the beginning
+ if ($url && substr($url, 0, 1) == '/')
{
- // fallback to "last known user page"
- // at least this way we know the user does not leave the phpBB root
- $url = generate_board_url() . '/' . $user->page['page'];
- $failover_flag = true;
+ $url = substr($url, 1);
}
}
- if (!$failover_flag)
- {
- // Is the uri pointing to the current directory?
- if ($pathinfo['dirname'] == '.')
- {
- $url = str_replace('./', '', $url);
+ $url = $phpbb_path_helper->remove_web_root_path($url);
- // Strip / from the beginning
- if ($url && substr($url, 0, 1) == '/')
- {
- $url = substr($url, 1);
- }
-
- if ($user->page['page_dir'])
- {
- $url = generate_board_url() . '/' . $user->page['page_dir'] . '/' . $url;
- }
- else
- {
- $url = generate_board_url() . '/' . $url;
- }
- }
- else
- {
- // Used ./ before, but $phpbb_root_path is working better with urls within another root path
- $root_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($phpbb_root_path)));
- $page_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($pathinfo['dirname'])));
- $intersection = array_intersect_assoc($root_dirs, $page_dirs);
-
- $root_dirs = array_diff_assoc($root_dirs, $intersection);
- $page_dirs = array_diff_assoc($page_dirs, $intersection);
-
- $dir = str_repeat('../', sizeof($root_dirs)) . implode('/', $page_dirs);
-
- // Strip / from the end
- if ($dir && substr($dir, -1, 1) == '/')
- {
- $dir = substr($dir, 0, -1);
- }
-
- // Strip / from the beginning
- if ($dir && substr($dir, 0, 1) == '/')
- {
- $dir = substr($dir, 1);
- }
+ if ($user->page['page_dir'])
+ {
+ $url = $user->page['page_dir'] . '/' . $url;
+ }
- $url = str_replace($pathinfo['dirname'] . '/', '', $url);
+ $url = generate_board_url() . '/' . $url;
+ }
- // Strip / from the beginning
- if (substr($url, 0, 1) == '/')
- {
- $url = substr($url, 1);
- }
+ // Clean URL and check if we go outside the forum directory
+ $url = $phpbb_path_helper->clean_url($url);
- $url = (!empty($dir) ? $dir . '/' : '') . $url;
- $url = generate_board_url() . '/' . $url;
- }
- }
+ if (!$disable_cd_check && strpos($url, generate_board_url(true)) === false)
+ {
+ trigger_error('INSECURE_REDIRECT', E_USER_ERROR);
}
// Make sure no linebreaks are there... to prevent http response splitting for PHP < 4.4.2
if (strpos(urldecode($url), "\n") !== false || strpos(urldecode($url), "\r") !== false || strpos($url, ';') !== false)
{
- trigger_error('Tried to redirect to potentially insecure url.', E_USER_ERROR);
+ trigger_error('INSECURE_REDIRECT', E_USER_ERROR);
}
// Now, also check the protocol and for a valid url the last time...
@@ -2591,7 +2353,7 @@ function redirect($url, $return = false, $disable_cd_check = false)
if ($url_parts === false || empty($url_parts['scheme']) || !in_array($url_parts['scheme'], $allowed_protocols))
{
- trigger_error('Tried to redirect to potentially insecure url.', E_USER_ERROR);
+ trigger_error('INSECURE_REDIRECT', E_USER_ERROR);
}
if ($return)
@@ -2604,10 +2366,10 @@ function redirect($url, $return = false, $disable_cd_check = false)
{
header('Refresh: 0; URL=' . $url);
- echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
- echo '<html xmlns="http://www.w3.org/1999/xhtml" dir="' . $user->lang['DIRECTION'] . '" lang="' . $user->lang['USER_LANG'] . '" xml:lang="' . $user->lang['USER_LANG'] . '">';
+ echo '<!DOCTYPE html>';
+ echo '<html dir="' . $user->lang['DIRECTION'] . '" lang="' . $user->lang['USER_LANG'] . '">';
echo '<head>';
- echo '<meta http-equiv="content-type" content="text/html; charset=utf-8" />';
+ echo '<meta charset="utf-8">';
echo '<meta http-equiv="refresh" content="0; url=' . str_replace('&', '&amp;', $url) . '" />';
echo '<title>' . $user->lang['REDIRECT'] . '</title>';
echo '</head>';
@@ -2659,8 +2421,22 @@ function build_url($strip_vars = false)
{
global $user, $phpbb_root_path;
+ $page = $user->page['page'];
+
+ // We need to be cautious here.
+ // On some situations, the redirect path is an absolute URL, sometimes a relative path
+ // For a relative path, let's prefix it with $phpbb_root_path to point to the correct location,
+ // else we use the URL directly.
+ $url_parts = parse_url($page);
+
+ // URL
+ if ($url_parts === false || empty($url_parts['scheme']) || empty($url_parts['host']))
+ {
+ $page = $phpbb_root_path . $page;
+ }
+
// Append SID
- $redirect = append_sid($user->page['page'], false, false);
+ $redirect = append_sid($page, false, false);
// Add delimiter if not there...
if (strpos($redirect, '?') === false)
@@ -2715,19 +2491,7 @@ function build_url($strip_vars = false)
$redirect .= ($query) ? '?' . $query : '';
}
- // We need to be cautious here.
- // On some situations, the redirect path is an absolute URL, sometimes a relative path
- // For a relative path, let's prefix it with $phpbb_root_path to point to the correct location,
- // else we use the URL directly.
- $url_parts = @parse_url($redirect);
-
- // URL
- if ($url_parts !== false && !empty($url_parts['scheme']) && !empty($url_parts['host']))
- {
- return str_replace('&', '&amp;', $redirect);
- }
-
- return $phpbb_root_path . str_replace('&', '&amp;', $redirect);
+ return str_replace('&', '&amp;', $redirect);
}
/**
@@ -2740,15 +2504,25 @@ function build_url($strip_vars = false)
*/
function meta_refresh($time, $url, $disable_cd_check = false)
{
- global $template;
+ global $template, $refresh_data, $request;
- $url = redirect($url, true, $disable_cd_check);
- $url = str_replace('&', '&amp;', $url);
+ if ($request->is_ajax())
+ {
+ $refresh_data = array(
+ 'time' => $time,
+ 'url' => str_replace('&amp;', '&', $url)
+ );
+ }
+ else
+ {
+ $url = redirect($url, true, $disable_cd_check);
+ $url = str_replace('&', '&amp;', $url);
- // For XHTML compatibility we change back & to &amp;
- $template->assign_vars(array(
- 'META' => '<meta http-equiv="refresh" content="' . $time . '; url=' . $url . '" />')
- );
+ // For XHTML compatibility we change back & to &amp;
+ $template->assign_vars(array(
+ 'META' => '<meta http-equiv="refresh" content="' . $time . '; url=' . $url . '" />')
+ );
+ }
return $url;
}
@@ -2782,18 +2556,35 @@ function send_status_line($code, $message)
}
else
{
- if (!empty($_SERVER['SERVER_PROTOCOL']))
- {
- $version = $_SERVER['SERVER_PROTOCOL'];
- }
- else
- {
- $version = 'HTTP/1.0';
- }
+ $version = phpbb_request_http_version();
header("$version $code $message", true, $code);
}
}
+/**
+* Returns the HTTP version used in the current request.
+*
+* Handles the case of being called before $request is present,
+* in which case it falls back to the $_SERVER superglobal.
+*
+* @return string HTTP version
+*/
+function phpbb_request_http_version()
+{
+ global $request;
+
+ if ($request && $request->server('SERVER_PROTOCOL'))
+ {
+ return $request->server('SERVER_PROTOCOL');
+ }
+ else if (isset($_SERVER['SERVER_PROTOCOL']))
+ {
+ return $_SERVER['SERVER_PROTOCOL'];
+ }
+
+ return 'HTTP/1.0';
+}
+
//Form validation
@@ -2909,23 +2700,15 @@ function check_form_key($form_name, $timespan = false, $return_page = '', $trigg
*/
function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_body.html', $u_action = '')
{
- global $user, $template, $db;
- global $phpEx, $phpbb_root_path;
+ global $user, $template, $db, $request;
+ global $phpEx, $phpbb_root_path, $request;
if (isset($_POST['cancel']))
{
return false;
}
- $confirm = false;
- if (isset($_POST['confirm']))
- {
- // language frontier
- if ($_POST['confirm'] === $user->lang['YES'])
- {
- $confirm = true;
- }
- }
+ $confirm = ($user->lang['YES'] === $request->variable('confirm', '', true, \phpbb\request\request_interface::POST));
if ($check && $confirm)
{
@@ -2990,13 +2773,30 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo
'YES_VALUE' => $user->lang['YES'],
'S_CONFIRM_ACTION' => $u_action,
- 'S_HIDDEN_FIELDS' => $hidden . $s_hidden_fields)
- );
+ 'S_HIDDEN_FIELDS' => $hidden . $s_hidden_fields,
+ 'S_AJAX_REQUEST' => $request->is_ajax(),
+ ));
$sql = 'UPDATE ' . USERS_TABLE . " SET user_last_confirm_key = '" . $db->sql_escape($confirm_key) . "'
WHERE user_id = " . $user->data['user_id'];
$db->sql_query($sql);
+
+ if ($request->is_ajax())
+ {
+ $u_action .= '&confirm_uid=' . $user->data['user_id'] . '&sess=' . $user->session_id . '&sid=' . $user->session_id;
+ $json_response = new \phpbb\json_response;
+ $json_response->send(array(
+ 'MESSAGE_BODY' => $template->assign_display('body'),
+ 'MESSAGE_TITLE' => (!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title],
+ 'MESSAGE_TEXT' => (!isset($user->lang[$title . '_CONFIRM'])) ? $title : $user->lang[$title . '_CONFIRM'],
+
+ 'YES_VALUE' => $user->lang['YES'],
+ 'S_CONFIRM_ACTION' => str_replace('&amp;', '&', $u_action), //inefficient, rewrite whole function
+ 'S_HIDDEN_FIELDS' => $hidden . $s_hidden_fields
+ ));
+ }
+
if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin'])
{
adm_page_footer();
@@ -3013,8 +2813,9 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo
function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = false, $s_display = true)
{
global $db, $user, $template, $auth, $phpEx, $phpbb_root_path, $config;
+ global $request, $phpbb_container;
- if (!class_exists('phpbb_captcha_factory'))
+ if (!class_exists('phpbb_captcha_factory', false))
{
include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx);
}
@@ -3039,7 +2840,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
trigger_error('NO_AUTH_ADMIN');
}
- if (isset($_POST['login']))
+ if ($request->is_set_post('login') || ($request->is_set('login') && $request->variable('login', '') == 'external'))
{
// Get credential
if ($admin)
@@ -3055,16 +2856,16 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
trigger_error('NO_AUTH_ADMIN');
}
- $password = request_var('password_' . $credential, '', true);
+ $password = $request->untrimmed_variable('password_' . $credential, '', true);
}
else
{
- $password = request_var('password', '', true);
+ $password = $request->untrimmed_variable('password', '', true);
}
$username = request_var('username', '', true);
- $autologin = (!empty($_POST['autologin'])) ? true : false;
- $viewonline = (!empty($_POST['viewonline'])) ? 0 : 1;
+ $autologin = $request->is_set_post('autologin');
+ $viewonline = (int) !$request->is_set_post('viewonline');
$admin = ($admin) ? 1 : 0;
$viewonline = ($admin) ? $user->data['session_viewonline'] : $viewonline;
@@ -3114,8 +2915,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
return;
}
- $redirect = meta_refresh(3, $redirect);
- trigger_error($message . '<br /><br />' . sprintf($l_redirect, '<a href="' . $redirect . '">', '</a>'));
+ redirect($redirect);
}
// Something failed, determine what...
@@ -3181,6 +2981,29 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
$s_hidden_fields['credential'] = $credential;
}
+ $auth_provider = $phpbb_container->get('auth.provider.' . $config['auth_method']);
+
+ $auth_provider_data = $auth_provider->get_login_data();
+ if ($auth_provider_data)
+ {
+ if (isset($auth_provider_data['VARS']))
+ {
+ $template->assign_vars($auth_provider_data['VARS']);
+ }
+
+ if (isset($auth_provider_data['BLOCK_VAR_NAME']))
+ {
+ foreach ($auth_provider_data['BLOCK_VARS'] as $block_vars)
+ {
+ $template->assign_block_vars($auth_provider_data['BLOCK_VAR_NAME'], $block_vars);
+ }
+ }
+
+ $template->assign_vars(array(
+ 'PROVIDER_TEMPLATE_FILE' => $auth_provider_data['TEMPLATE_FILE'],
+ ));
+ }
+
$s_hidden_fields = build_hidden_fields($s_hidden_fields);
$template->assign_vars(array(
@@ -3217,9 +3040,9 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
*/
function login_forum_box($forum_data)
{
- global $db, $config, $user, $template, $phpEx;
+ global $db, $phpbb_container, $request, $template, $user;
- $password = request_var('password', '', true);
+ $password = $request->variable('password', '', true);
$sql = 'SELECT forum_id
FROM ' . FORUMS_ACCESS_TABLE . '
@@ -3260,7 +3083,9 @@ function login_forum_box($forum_data)
}
$db->sql_freeresult($result);
- if (phpbb_check_hash($password, $forum_data['forum_password']))
+ $passwords_manager = $phpbb_container->get('passwords.manager');
+
+ if ($passwords_manager->check($password, $forum_data['forum_password']))
{
$sql_ary = array(
'forum_id' => (int) $forum_data['forum_id'],
@@ -3389,79 +3214,59 @@ function parse_cfg_file($filename, $lines = false)
$parsed_items[$key] = $value;
}
-
- if (isset($parsed_items['inherit_from']) && isset($parsed_items['name']) && $parsed_items['inherit_from'] == $parsed_items['name'])
+
+ if (isset($parsed_items['parent']) && isset($parsed_items['name']) && $parsed_items['parent'] == $parsed_items['name'])
{
- unset($parsed_items['inherit_from']);
+ unset($parsed_items['parent']);
}
return $parsed_items;
}
/**
-* Add log event
+* Add log entry
+*
+* @param string $mode The mode defines which log_type is used and from which log the entry is retrieved
+* @param int $forum_id Mode 'mod' ONLY: forum id of the related item, NOT INCLUDED otherwise
+* @param int $topic_id Mode 'mod' ONLY: topic id of the related item, NOT INCLUDED otherwise
+* @param int $reportee_id Mode 'user' ONLY: user id of the reportee, NOT INCLUDED otherwise
+* @param string $log_operation Name of the operation
+* @param array $additional_data More arguments can be added, depending on the log_type
+*
+* @return int|bool Returns the log_id, if the entry was added to the database, false otherwise.
+*
+* @deprecated Use $phpbb_log->add() instead
*/
function add_log()
{
- global $db, $user;
-
- // In phpBB 3.1.x i want to have logging in a class to be able to control it
- // For now, we need a quite hakish approach to circumvent logging for some actions
- // @todo implement cleanly
- if (!empty($GLOBALS['skip_add_log']))
- {
- return false;
- }
+ global $phpbb_log, $user;
$args = func_get_args();
+ $mode = array_shift($args);
- $mode = array_shift($args);
- $reportee_id = ($mode == 'user') ? intval(array_shift($args)) : '';
- $forum_id = ($mode == 'mod') ? intval(array_shift($args)) : '';
- $topic_id = ($mode == 'mod') ? intval(array_shift($args)) : '';
- $action = array_shift($args);
- $data = (!sizeof($args)) ? '' : serialize($args);
-
- $sql_ary = array(
- 'user_id' => (empty($user->data)) ? ANONYMOUS : $user->data['user_id'],
- 'log_ip' => $user->ip,
- 'log_time' => time(),
- 'log_operation' => $action,
- 'log_data' => $data,
- );
-
+ // This looks kind of dirty, but add_log has some additional data before the log_operation
+ $additional_data = array();
switch ($mode)
{
case 'admin':
- $sql_ary['log_type'] = LOG_ADMIN;
+ case 'critical':
break;
-
case 'mod':
- $sql_ary += array(
- 'log_type' => LOG_MOD,
- 'forum_id' => $forum_id,
- 'topic_id' => $topic_id
- );
+ $additional_data['forum_id'] = array_shift($args);
+ $additional_data['topic_id'] = array_shift($args);
break;
-
case 'user':
- $sql_ary += array(
- 'log_type' => LOG_USERS,
- 'reportee_id' => $reportee_id
- );
- break;
-
- case 'critical':
- $sql_ary['log_type'] = LOG_CRITICAL;
+ $additional_data['reportee_id'] = array_shift($args);
break;
-
- default:
- return false;
}
- $db->sql_query('INSERT INTO ' . LOG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
+ $log_operation = array_shift($args);
+ $additional_data = array_merge($additional_data, $args);
- return $db->sql_nextid();
+ $user_id = (empty($user->data)) ? ANONYMOUS : $user->data['user_id'];
+ $user_ip = (empty($user->ip)) ? '' : $user->ip;
+
+ return $phpbb_log->add($mode, $user_id, $user_ip, $log_operation, time(), $additional_data);
}
/**
@@ -3584,18 +3389,10 @@ function get_preg_expression($mode)
*/
function get_censor_preg_expression($word, $use_unicode = true)
{
- static $unicode_support = null;
-
- // Check whether PHP version supports unicode properties
- if (is_null($unicode_support))
- {
- $unicode_support = ((version_compare(PHP_VERSION, '5.1.0', '>=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.0', '>='))) && @preg_match('/\p{L}/u', 'a') !== false) ? true : false;
- }
-
// Unescape the asterisk to simplify further conversions
$word = str_replace('\*', '*', preg_quote($word, '#'));
- if ($use_unicode && $unicode_support)
+ if ($use_unicode && phpbb_pcre_utf8_support())
{
// Replace asterisk(s) inside the pattern, at the start and at the end of it with regexes
$word = preg_replace(array('#(?<=[\p{Nd}\p{L}_])\*+(?=[\p{Nd}\p{L}_])#iu', '#^\*+#', '#\*+$#'), array('([\x20]*?|[\p{Nd}\p{L}_-]*?)', '[\p{Nd}\p{L}_-]*?', '[\p{Nd}\p{L}_-]*?'), $word);
@@ -3647,6 +3444,188 @@ function short_ipv6($ip, $length)
}
/**
+* Normalises an internet protocol address,
+* also checks whether the specified address is valid.
+*
+* IPv4 addresses are returned 'as is'.
+*
+* IPv6 addresses are normalised according to
+* A Recommendation for IPv6 Address Text Representation
+* http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-07
+*
+* @param string $address IP address
+*
+* @return mixed false if specified address is not valid,
+* string otherwise
+*
+* @author bantu
+*/
+function phpbb_ip_normalise($address)
+{
+ $address = trim($address);
+
+ if (empty($address) || !is_string($address))
+ {
+ return false;
+ }
+
+ if (preg_match(get_preg_expression('ipv4'), $address))
+ {
+ return $address;
+ }
+
+ return phpbb_inet_ntop(phpbb_inet_pton($address));
+}
+
+/**
+* Wrapper for inet_ntop()
+*
+* Converts a packed internet address to a human readable representation
+* inet_ntop() is supported by PHP since 5.1.0, since 5.3.0 also on Windows.
+*
+* @param string $in_addr A 32bit IPv4, or 128bit IPv6 address.
+*
+* @return mixed false on failure,
+* string otherwise
+*
+* @author APTX
+*/
+function phpbb_inet_ntop($in_addr)
+{
+ $in_addr = bin2hex($in_addr);
+
+ switch (strlen($in_addr))
+ {
+ case 8:
+ return implode('.', array_map('hexdec', str_split($in_addr, 2)));
+
+ case 32:
+ if (substr($in_addr, 0, 24) === '00000000000000000000ffff')
+ {
+ return phpbb_inet_ntop(pack('H*', substr($in_addr, 24)));
+ }
+
+ $parts = str_split($in_addr, 4);
+ $parts = preg_replace('/^0+(?!$)/', '', $parts);
+ $ret = implode(':', $parts);
+
+ $matches = array();
+ preg_match_all('/(?<=:|^)(?::?0){2,}/', $ret, $matches, PREG_OFFSET_CAPTURE);
+ $matches = $matches[0];
+
+ if (empty($matches))
+ {
+ return $ret;
+ }
+
+ $longest_match = '';
+ $longest_match_offset = 0;
+ foreach ($matches as $match)
+ {
+ if (strlen($match[0]) > strlen($longest_match))
+ {
+ $longest_match = $match[0];
+ $longest_match_offset = $match[1];
+ }
+ }
+
+ $ret = substr_replace($ret, '', $longest_match_offset, strlen($longest_match));
+
+ if ($longest_match_offset == strlen($ret))
+ {
+ $ret .= ':';
+ }
+
+ if ($longest_match_offset == 0)
+ {
+ $ret = ':' . $ret;
+ }
+
+ return $ret;
+
+ default:
+ return false;
+ }
+}
+
+/**
+* Wrapper for inet_pton()
+*
+* Converts a human readable IP address to its packed in_addr representation
+* inet_pton() is supported by PHP since 5.1.0, since 5.3.0 also on Windows.
+*
+* @param string $address A human readable IPv4 or IPv6 address.
+*
+* @return mixed false if address is invalid,
+* in_addr representation of the given address otherwise (string)
+*
+* @author APTX
+*/
+function phpbb_inet_pton($address)
+{
+ $ret = '';
+ if (preg_match(get_preg_expression('ipv4'), $address))
+ {
+ foreach (explode('.', $address) as $part)
+ {
+ $ret .= ($part <= 0xF ? '0' : '') . dechex($part);
+ }
+
+ return pack('H*', $ret);
+ }
+
+ if (preg_match(get_preg_expression('ipv6'), $address))
+ {
+ $parts = explode(':', $address);
+ $missing_parts = 8 - sizeof($parts) + 1;
+
+ if (substr($address, 0, 2) === '::')
+ {
+ ++$missing_parts;
+ }
+
+ if (substr($address, -2) === '::')
+ {
+ ++$missing_parts;
+ }
+
+ $embedded_ipv4 = false;
+ $last_part = end($parts);
+
+ if (preg_match(get_preg_expression('ipv4'), $last_part))
+ {
+ $parts[sizeof($parts) - 1] = '';
+ $last_part = phpbb_inet_pton($last_part);
+ $embedded_ipv4 = true;
+ --$missing_parts;
+ }
+
+ foreach ($parts as $i => $part)
+ {
+ if (strlen($part))
+ {
+ $ret .= str_pad($part, 4, '0', STR_PAD_LEFT);
+ }
+ else if ($i && $i < sizeof($parts) - 1)
+ {
+ $ret .= str_repeat('0000', $missing_parts);
+ }
+ }
+
+ $ret = pack('H*', $ret);
+
+ if ($embedded_ipv4)
+ {
+ $ret .= $last_part;
+ }
+
+ return $ret;
+ }
+
+ return false;
+}
+
+/**
* Wrapper for php's checkdnsrr function.
*
* @param string $host Fully-Qualified Domain Name
@@ -3843,11 +3822,11 @@ function phpbb_checkdnsrr($host, $type = 'MX')
// Handler, header and footer
/**
-* Error and message handler, call with trigger_error if reqd
+* Error and message handler, call with trigger_error if read
*/
function msg_handler($errno, $msg_text, $errfile, $errline)
{
- global $cache, $db, $auth, $template, $config, $user;
+ global $cache, $db, $auth, $template, $config, $user, $request;
global $phpEx, $phpbb_root_path, $msg_title, $msg_long_text;
// Do not display notices if we suppress them via @
@@ -3932,12 +3911,12 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
$log_text .= '<br /><br />BACKTRACE<br />' . $backtrace;
}
- if (defined('IN_INSTALL') || defined('DEBUG_EXTRA') || isset($auth) && $auth->acl_get('a_'))
+ if (defined('IN_INSTALL') || defined('DEBUG') || isset($auth) && $auth->acl_get('a_'))
{
$msg_text = $log_text;
}
- if ((defined('DEBUG') || defined('IN_CRON') || defined('IMAGE_OUTPUT')) && isset($db))
+ if ((defined('IN_CRON') || defined('IMAGE_OUTPUT')) && isset($db))
{
// let's avoid loops
$db->sql_return_on_error(true);
@@ -3952,10 +3931,10 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
// Try to not call the adm page data...
- echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
- echo '<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">';
+ echo '<!DOCTYPE html>';
+ echo '<html dir="ltr">';
echo '<head>';
- echo '<meta http-equiv="content-type" content="text/html; charset=utf-8" />';
+ echo '<meta charset="utf-8">';
echo '<title>' . $msg_title . '</title>';
echo '<style type="text/css">' . "\n" . '/* <![CDATA[ */' . "\n";
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; } ';
@@ -4046,6 +4025,20 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
'S_USER_NOTICE' => ($errno == E_USER_NOTICE) ? true : false)
);
+ if ($request->is_ajax())
+ {
+ global $refresh_data;
+
+ $json_response = new \phpbb\json_response;
+ $json_response->send(array(
+ 'MESSAGE_TITLE' => $msg_title,
+ 'MESSAGE_TEXT' => $msg_text,
+ 'S_USER_WARNING' => ($errno == E_USER_WARNING) ? true : false,
+ 'S_USER_NOTICE' => ($errno == E_USER_NOTICE) ? true : false,
+ 'REFRESH_DATA' => (!empty($refresh_data)) ? $refresh_data : null
+ ));
+ }
+
// We do not want the cron script to be called on error messages
define('IN_CRON', true);
@@ -4260,59 +4253,26 @@ function obtain_users_online_string($online_users, $item_id = 0, $item = 'forum'
}
else if ($config['load_online_guests'])
{
- $l_online = ($online_users['guests_online'] === 1) ? $user->lang['BROWSING_' . $item_caps . '_GUEST'] : $user->lang['BROWSING_' . $item_caps . '_GUESTS'];
- $online_userlist = sprintf($l_online, $online_userlist, $online_users['guests_online']);
+ $online_userlist = $user->lang('BROWSING_' . $item_caps . '_GUESTS', $online_users['guests_online'], $online_userlist);
}
else
{
$online_userlist = sprintf($user->lang['BROWSING_' . $item_caps], $online_userlist);
}
// Build online listing
- $vars_online = array(
- 'ONLINE' => array('total_online', 'l_t_user_s', 0),
- 'REG' => array('visible_online', 'l_r_user_s', !$config['load_online_guests']),
- 'HIDDEN' => array('hidden_online', 'l_h_user_s', $config['load_online_guests']),
- 'GUEST' => array('guests_online', 'l_g_user_s', 0)
- );
+ $visible_online = $user->lang('REG_USERS_TOTAL', (int) $online_users['visible_online']);
+ $hidden_online = $user->lang('HIDDEN_USERS_TOTAL', (int) $online_users['hidden_online']);
- foreach ($vars_online as $l_prefix => $var_ary)
+ if ($config['load_online_guests'])
{
- if ($var_ary[2])
- {
- $l_suffix = '_AND';
- }
- else
- {
- $l_suffix = '';
- }
- switch ($online_users[$var_ary[0]])
- {
- case 0:
- ${$var_ary[1]} = $user->lang[$l_prefix . '_USERS_ZERO_TOTAL' . $l_suffix];
- break;
-
- case 1:
- ${$var_ary[1]} = $user->lang[$l_prefix . '_USER_TOTAL' . $l_suffix];
- break;
-
- default:
- ${$var_ary[1]} = $user->lang[$l_prefix . '_USERS_TOTAL' . $l_suffix];
- break;
- }
+ $guests_online = $user->lang('GUEST_USERS_TOTAL', (int) $online_users['guests_online']);
+ $l_online_users = $user->lang('ONLINE_USERS_TOTAL_GUESTS', (int) $online_users['total_online'], $visible_online, $hidden_online, $guests_online);
}
- unset($vars_online);
-
- $l_online_users = sprintf($l_t_user_s, $online_users['total_online']);
- $l_online_users .= sprintf($l_r_user_s, $online_users['visible_online']);
- $l_online_users .= sprintf($l_h_user_s, $online_users['hidden_online']);
-
- if ($config['load_online_guests'])
+ else
{
- $l_online_users .= sprintf($l_g_user_s, $online_users['guests_online']);
+ $l_online_users = $user->lang('ONLINE_USERS_TOTAL', (int) $online_users['total_online'], $visible_online, $hidden_online);
}
-
-
return array(
'online_userlist' => $online_userlist,
'l_online_users' => $l_online_users,
@@ -4355,6 +4315,178 @@ function phpbb_optionset($bit, $set, $data)
}
/**
+* Determine which plural form we should use.
+* For some languages this is not as simple as for English.
+*
+* @param $rule int ID of the plural rule we want to use, see http://wiki.phpbb.com/Plural_Rules#Plural_Rules
+* @param $number int|float The number we want to get the plural case for. Float numbers are floored.
+* @return int The plural-case we need to use for the number plural-rule combination
+*/
+function phpbb_get_plural_form($rule, $number)
+{
+ $number = (int) $number;
+
+ if ($rule > 15 || $rule < 0)
+ {
+ trigger_error('INVALID_PLURAL_RULE');
+ }
+
+ /**
+ * The following plural rules are based on a list published by the Mozilla Developer Network
+ * https://developer.mozilla.org/en/Localization_and_Plurals
+ */
+ switch ($rule)
+ {
+ case 0:
+ /**
+ * Families: Asian (Chinese, Japanese, Korean, Vietnamese), Persian, Turkic/Altaic (Turkish), Thai, Lao
+ * 1 - everything: 0, 1, 2, ...
+ */
+ return 1;
+
+ case 1:
+ /**
+ * Families: Germanic (Danish, Dutch, English, Faroese, Frisian, German, Norwegian, Swedish), Finno-Ugric (Estonian, Finnish, Hungarian), Language isolate (Basque), Latin/Greek (Greek), Semitic (Hebrew), Romanic (Italian, Portuguese, Spanish, Catalan)
+ * 1 - 1
+ * 2 - everything else: 0, 2, 3, ...
+ */
+ return ($number == 1) ? 1 : 2;
+
+ case 2:
+ /**
+ * Families: Romanic (French, Brazilian Portuguese)
+ * 1 - 0, 1
+ * 2 - everything else: 2, 3, ...
+ */
+ return (($number == 0) || ($number == 1)) ? 1 : 2;
+
+ case 3:
+ /**
+ * Families: Baltic (Latvian)
+ * 1 - 0
+ * 2 - ends in 1, not 11: 1, 21, ... 101, 121, ...
+ * 3 - everything else: 2, 3, ... 10, 11, 12, ... 20, 22, ...
+ */
+ return ($number == 0) ? 1 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 2 : 3);
+
+ case 4:
+ /**
+ * Families: Celtic (Scottish Gaelic)
+ * 1 - is 1 or 11: 1, 11
+ * 2 - is 2 or 12: 2, 12
+ * 3 - others between 3 and 19: 3, 4, ... 10, 13, ... 18, 19
+ * 4 - everything else: 0, 20, 21, ...
+ */
+ return ($number == 1 || $number == 11) ? 1 : (($number == 2 || $number == 12) ? 2 : (($number >= 3 && $number <= 19) ? 3 : 4));
+
+ case 5:
+ /**
+ * Families: Romanic (Romanian)
+ * 1 - 1
+ * 2 - is 0 or ends in 01-19: 0, 2, 3, ... 19, 101, 102, ... 119, 201, ...
+ * 3 - everything else: 20, 21, ...
+ */
+ return ($number == 1) ? 1 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 2 : 3);
+
+ case 6:
+ /**
+ * Families: Baltic (Lithuanian)
+ * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ...
+ * 2 - ends in 0 or ends in 10-20: 0, 10, 11, 12, ... 19, 20, 30, 40, ...
+ * 3 - everything else: 2, 3, ... 8, 9, 22, 23, ... 29, 32, 33, ...
+ */
+ return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 < 2) || (($number % 100 >= 10) && ($number % 100 < 20))) ? 2 : 3);
+
+ case 7:
+ /**
+ * Families: Slavic (Croatian, Serbian, Russian, Ukrainian)
+ * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ...
+ * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ...
+ * 3 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 26, ...
+ */
+ return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 2 : 3);
+
+ case 8:
+ /**
+ * Families: Slavic (Slovak, Czech)
+ * 1 - 1
+ * 2 - 2, 3, 4
+ * 3 - everything else: 0, 5, 6, 7, ...
+ */
+ return ($number == 1) ? 1 : ((($number >= 2) && ($number <= 4)) ? 2 : 3);
+
+ case 9:
+ /**
+ * Families: Slavic (Polish)
+ * 1 - 1
+ * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... 104, 122, ...
+ * 3 - everything else: 0, 5, 6, ... 11, 12, 13, 14, 15, ... 20, 21, 25, ...
+ */
+ return ($number == 1) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 2 : 3);
+
+ case 10:
+ /**
+ * Families: Slavic (Slovenian, Sorbian)
+ * 1 - ends in 01: 1, 101, 201, ...
+ * 2 - ends in 02: 2, 102, 202, ...
+ * 3 - ends in 03-04: 3, 4, 103, 104, 203, 204, ...
+ * 4 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, ...
+ */
+ return ($number % 100 == 1) ? 1 : (($number % 100 == 2) ? 2 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 3 : 4));
+
+ case 11:
+ /**
+ * Families: Celtic (Irish Gaeilge)
+ * 1 - 1
+ * 2 - 2
+ * 3 - is 3-6: 3, 4, 5, 6
+ * 4 - is 7-10: 7, 8, 9, 10
+ * 5 - everything else: 0, 11, 12, ...
+ */
+ return ($number == 1) ? 1 : (($number == 2) ? 2 : (($number >= 3 && $number <= 6) ? 3 : (($number >= 7 && $number <= 10) ? 4 : 5)));
+
+ case 12:
+ /**
+ * Families: Semitic (Arabic)
+ * 1 - 1
+ * 2 - 2
+ * 3 - ends in 03-10: 3, 4, ... 10, 103, 104, ... 110, 203, 204, ...
+ * 4 - ends in 11-99: 11, ... 99, 111, 112, ...
+ * 5 - everything else: 100, 101, 102, 200, 201, 202, ...
+ * 6 - 0
+ */
+ return ($number == 1) ? 1 : (($number == 2) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : (($number != 0) ? 5 : 6))));
+
+ case 13:
+ /**
+ * Families: Semitic (Maltese)
+ * 1 - 1
+ * 2 - is 0 or ends in 01-10: 0, 2, 3, ... 9, 10, 101, 102, ...
+ * 3 - ends in 11-19: 11, 12, ... 18, 19, 111, 112, ...
+ * 4 - everything else: 20, 21, ...
+ */
+ return ($number == 1) ? 1 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 2 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 3 : 4));
+
+ case 14:
+ /**
+ * Families: Slavic (Macedonian)
+ * 1 - ends in 1: 1, 11, 21, ...
+ * 2 - ends in 2: 2, 12, 22, ...
+ * 3 - everything else: 0, 3, 4, ... 10, 13, 14, ... 20, 23, ...
+ */
+ return ($number % 10 == 1) ? 1 : (($number % 10 == 2) ? 2 : 3);
+
+ case 15:
+ /**
+ * Families: Icelandic
+ * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, 131, ...
+ * 2 - everything else: 0, 2, 3, ... 10, 11, 12, ... 20, 22, ...
+ */
+ return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2;
+ }
+}
+
+/**
* Login using http authenticate.
*
* @param array $param Parameter array, see $param_defaults array.
@@ -4363,7 +4495,7 @@ function phpbb_optionset($bit, $set, $data)
*/
function phpbb_http_login($param)
{
- global $auth, $user;
+ global $auth, $user, $request;
global $config;
$param_defaults = array(
@@ -4403,9 +4535,9 @@ function phpbb_http_login($param)
$username = null;
foreach ($username_keys as $k)
{
- if (isset($_SERVER[$k]))
+ if ($request->is_set($k, \phpbb\request\request_interface::SERVER))
{
- $username = $_SERVER[$k];
+ $username = htmlspecialchars_decode($request->server($k));
break;
}
}
@@ -4413,9 +4545,9 @@ function phpbb_http_login($param)
$password = null;
foreach ($password_keys as $k)
{
- if (isset($_SERVER[$k]))
+ if ($request->is_set($k, \phpbb\request\request_interface::SERVER))
{
- $password = $_SERVER[$k];
+ $password = htmlspecialchars_decode($request->server($k));
break;
}
}
@@ -4458,11 +4590,107 @@ function phpbb_http_login($param)
}
/**
+* Escapes and quotes a string for use as an HTML/XML attribute value.
+*
+* This is a port of Python xml.sax.saxutils quoteattr.
+*
+* The function will attempt to choose a quote character in such a way as to
+* avoid escaping quotes in the string. If this is not possible the string will
+* be wrapped in double quotes and double quotes will be escaped.
+*
+* @param string $data The string to be escaped
+* @param array $entities Associative array of additional entities to be escaped
+* @return string Escaped and quoted string
+*/
+function phpbb_quoteattr($data, $entities = null)
+{
+ $data = str_replace('&', '&amp;', $data);
+ $data = str_replace('>', '&gt;', $data);
+ $data = str_replace('<', '&lt;', $data);
+
+ $data = str_replace("\n", '&#10;', $data);
+ $data = str_replace("\r", '&#13;', $data);
+ $data = str_replace("\t", '&#9;', $data);
+
+ if (!empty($entities))
+ {
+ $data = str_replace(array_keys($entities), array_values($entities), $data);
+ }
+
+ if (strpos($data, '"') !== false)
+ {
+ if (strpos($data, "'") !== false)
+ {
+ $data = '"' . str_replace('"', '&quot;', $data) . '"';
+ }
+ else
+ {
+ $data = "'" . $data . "'";
+ }
+ }
+ else
+ {
+ $data = '"' . $data . '"';
+ }
+
+ return $data;
+}
+
+/**
+* Converts query string (GET) parameters in request into hidden fields.
+*
+* Useful for forwarding GET parameters when submitting forms with GET method.
+*
+* It is possible to omit some of the GET parameters, which is useful if
+* they are specified in the form being submitted.
+*
+* sid is always omitted.
+*
+* @param \phpbb\request\request $request Request object
+* @param array $exclude A list of variable names that should not be forwarded
+* @return string HTML with hidden fields
+*/
+function phpbb_build_hidden_fields_for_query_params($request, $exclude = null)
+{
+ $names = $request->variable_names(\phpbb\request\request_interface::GET);
+ $hidden = '';
+ foreach ($names as $name)
+ {
+ // Sessions are dealt with elsewhere, omit sid always
+ if ($name == 'sid')
+ {
+ continue;
+ }
+
+ // Omit any additional parameters requested
+ if (!empty($exclude) && in_array($name, $exclude))
+ {
+ continue;
+ }
+
+ $escaped_name = phpbb_quoteattr($name);
+
+ // Note: we might retrieve the variable from POST or cookies
+ // here. To avoid exposing cookies, skip variables that are
+ // overwritten somewhere other than GET entirely.
+ $value = $request->variable($name, '', true);
+ $get_value = $request->variable($name, '', true, \phpbb\request\request_interface::GET);
+ if ($value === $get_value)
+ {
+ $escaped_value = phpbb_quoteattr($value);
+ $hidden .= "<input type='hidden' name=$escaped_name value=$escaped_value />";
+ }
+ }
+ return $hidden;
+}
+
+/**
* Generate page header
*/
function page_header($page_title = '', $display_online_list = true, $item_id = 0, $item = 'forum')
{
global $db, $config, $template, $SID, $_SID, $_EXTRA_URL, $user, $auth, $phpEx, $phpbb_root_path;
+ global $phpbb_dispatcher, $request, $phpbb_container, $phpbb_admin_path;
if (defined('HEADER_INC'))
{
@@ -4471,6 +4699,31 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
define('HEADER_INC', true);
+ // A listener can set this variable to `true` when it overrides this function
+ $page_header_override = false;
+
+ /**
+ * Execute code and/or overwrite page_header()
+ *
+ * @event core.page_header
+ * @var string page_title Page title
+ * @var bool display_online_list Do we display online users list
+ * @var string item Restrict online users to a certain
+ * session item, e.g. forum for
+ * session_forum_id
+ * @var int item_id Restrict online users to item id
+ * @var bool page_header_override Shall we return instead of running
+ * the rest of page_header()
+ * @since 3.1-A1
+ */
+ $vars = array('page_title', 'display_online_list', 'item_id', 'item', 'page_header_override');
+ extract($phpbb_dispatcher->trigger_event('core.page_header', compact($vars)));
+
+ if ($page_header_override)
+ {
+ return;
+ }
+
// gzip_compression
if ($config['gzip_compress'])
{
@@ -4533,23 +4786,18 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
set_config('record_online_date', time(), true);
}
- $l_online_record = sprintf($user->lang['RECORD_ONLINE_USERS'], $config['record_online_users'], $user->format_date($config['record_online_date'], false, true));
+ $l_online_record = $user->lang('RECORD_ONLINE_USERS', (int) $config['record_online_users'], $user->format_date($config['record_online_date'], false, true));
- $l_online_time = ($config['load_online_time'] == 1) ? 'VIEW_ONLINE_TIME' : 'VIEW_ONLINE_TIMES';
- $l_online_time = sprintf($user->lang[$l_online_time], $config['load_online_time']);
+ $l_online_time = $user->lang('VIEW_ONLINE_TIMES', (int) $config['load_online_time']);
}
- $l_privmsgs_text = $l_privmsgs_text_unread = '';
$s_privmsg_new = false;
- // Obtain number of new private messages if user is logged in
+ // Check for new private messages if user is logged in
if (!empty($user->data['is_registered']))
{
if ($user->data['user_new_privmsg'])
{
- $l_message_new = ($user->data['user_new_privmsg'] == 1) ? $user->lang['NEW_PM'] : $user->lang['NEW_PMS'];
- $l_privmsgs_text = sprintf($l_message_new, $user->data['user_new_privmsg']);
-
if (!$user->data['user_last_privmsg'] || $user->data['user_last_privmsg'] > $user->data['session_last_visit'])
{
$sql = 'UPDATE ' . USERS_TABLE . '
@@ -4566,17 +4814,8 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
}
else
{
- $l_privmsgs_text = $user->lang['NO_NEW_PM'];
$s_privmsg_new = false;
}
-
- $l_privmsgs_text_unread = '';
-
- if ($user->data['user_unread_privmsg'] && $user->data['user_unread_privmsg'] != $user->data['user_new_privmsg'])
- {
- $l_message_unread = ($user->data['user_unread_privmsg'] == 1) ? $user->lang['UNREAD_PM'] : $user->lang['UNREAD_PMS'];
- $l_privmsgs_text_unread = sprintf($l_message_unread, $user->data['user_unread_privmsg']);
- }
}
$forum_id = request_var('f', 0);
@@ -4597,10 +4836,12 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
// Determine board url - we may need it later
$board_url = generate_board_url() . '/';
- $web_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? $board_url : $phpbb_root_path;
-
- // Which timezone?
- $tz = ($user->data['user_id'] != ANONYMOUS) ? strval(doubleval($user->data['user_timezone'])) : strval(doubleval($config['board_timezone']));
+ // This path is sent with the base template paths in the assign_vars()
+ // call below. We need to correct it in case we are accessing from a
+ // controller because the web paths will be incorrect otherwise.
+ $phpbb_path_helper = $phpbb_container->get('path_helper');
+ $corrected_path = $phpbb_path_helper->get_web_root_path();
+ $web_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? $board_url : $corrected_path;
// Send a proper content-language to the output
$user_lang = $user->lang['USER_LANG'];
@@ -4624,6 +4865,34 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
}
}
+ $dt = new \phpbb\datetime($user, 'now', $user->timezone);
+ $timezone_offset = 'GMT' . phpbb_format_timezone_offset($dt->getOffset());
+ $timezone_name = $user->timezone->getName();
+ if (isset($user->lang['timezones'][$timezone_name]))
+ {
+ $timezone_name = $user->lang['timezones'][$timezone_name];
+ }
+
+ // Output the notifications
+ $notifications = false;
+ if ($config['load_notifications'] && $user->data['user_id'] != ANONYMOUS && $user->data['user_type'] != USER_IGNORE)
+ {
+ $phpbb_notifications = $phpbb_container->get('notification_manager');
+
+ $notifications = $phpbb_notifications->load_notifications(array(
+ 'all_unread' => true,
+ 'limit' => 5,
+ ));
+
+ foreach ($notifications['notifications'] as $notification)
+ {
+ $template->assign_block_vars('notifications', $notification->prepare_for_display());
+ }
+ }
+
+ $hidden_fields_for_jumpbox = phpbb_build_hidden_fields_for_query_params($request, array('f'));
+ $notification_mark_hash = generate_link_hash('mark_all_notifications_read');
+
// The following assigns all _common_ variables that may be used at any point in a template.
$template->assign_vars(array(
'SITENAME' => $config['sitename'],
@@ -4636,8 +4905,15 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'TOTAL_USERS_ONLINE' => $l_online_users,
'LOGGED_IN_USER_LIST' => $online_userlist,
'RECORD_USERS' => $l_online_record,
- 'PRIVATE_MESSAGE_INFO' => $l_privmsgs_text,
- 'PRIVATE_MESSAGE_INFO_UNREAD' => $l_privmsgs_text_unread,
+ 'PRIVATE_MESSAGE_COUNT' => (!empty($user->data['user_unread_privmsg'])) ? $user->data['user_unread_privmsg'] : 0,
+ 'HIDDEN_FIELDS_FOR_JUMPBOX' => $hidden_fields_for_jumpbox,
+
+ 'UNREAD_NOTIFICATIONS_COUNT' => ($notifications !== false) ? $notifications['unread_count'] : '',
+ 'NOTIFICATIONS_COUNT' => ($notifications !== false) ? $notifications['unread_count'] : '',
+ 'U_VIEW_ALL_NOTIFICATIONS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_notifications'),
+ 'U_MARK_ALL_NOTIFICATIONS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_notifications&amp;mode=notification_list&amp;mark=all&amp;token=' . $notification_mark_hash),
+ 'U_NOTIFICATION_SETTINGS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_notifications&amp;mode=notification_options'),
+ 'S_NOTIFICATIONS_DISPLAY' => $config['load_notifications'],
'S_USER_NEW_PRIVMSG' => $user->data['user_new_privmsg'],
'S_USER_UNREAD_PRIVMSG' => $user->data['user_unread_privmsg'],
@@ -4646,22 +4922,22 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'SID' => $SID,
'_SID' => $_SID,
'SESSION_ID' => $user->session_id,
- 'ROOT_PATH' => $phpbb_root_path,
+ 'ROOT_PATH' => $web_path,
'BOARD_URL' => $board_url,
'L_LOGIN_LOGOUT' => $l_login_logout,
- 'L_INDEX' => $user->lang['FORUM_INDEX'],
+ 'L_INDEX' => ($config['board_index_text'] !== '') ? $config['board_index_text'] : $user->lang['FORUM_INDEX'],
+ 'L_SITE_HOME' => ($config['site_home_text'] !== '') ? $config['site_home_text'] : $user->lang['HOME'],
'L_ONLINE_EXPLAIN' => $l_online_time,
'U_PRIVATEMSGS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=inbox'),
'U_RETURN_INBOX' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=inbox'),
- 'U_POPUP_PM' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;mode=popup'),
- 'UA_POPUP_PM' => addslashes(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;mode=popup')),
'U_MEMBERLIST' => append_sid("{$phpbb_root_path}memberlist.$phpEx"),
'U_VIEWONLINE' => ($auth->acl_gets('u_viewprofile', 'a_user', 'a_useradd', 'a_userdel')) ? append_sid("{$phpbb_root_path}viewonline.$phpEx") : '',
'U_LOGIN_LOGOUT' => $u_login_logout,
'U_INDEX' => append_sid("{$phpbb_root_path}index.$phpEx"),
'U_SEARCH' => append_sid("{$phpbb_root_path}search.$phpEx"),
+ 'U_SITE_HOME' => $config['site_home_url'],
'U_REGISTER' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register'),
'U_PROFILE' => append_sid("{$phpbb_root_path}ucp.$phpEx"),
'U_MODCP' => append_sid("{$phpbb_root_path}mcp.$phpEx", false, true, $user->session_id),
@@ -4683,7 +4959,6 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'S_BOARD_DISABLED' => ($config['board_disable']) ? true : false,
'S_REGISTERED_USER' => (!empty($user->data['is_registered'])) ? true : false,
'S_IS_BOT' => (!empty($user->data['is_bot'])) ? true : false,
- 'S_USER_PM_POPUP' => $user->optionget('popuppm'),
'S_USER_LANG' => $user_lang,
'S_USER_BROWSER' => (isset($user->data['session_browser'])) ? $user->data['session_browser'] : $user->lang['UNKNOWN_BROWSER'],
'S_USERNAME' => $user->data['username'],
@@ -4691,7 +4966,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'S_CONTENT_FLOW_BEGIN' => ($user->lang['DIRECTION'] == 'ltr') ? 'left' : 'right',
'S_CONTENT_FLOW_END' => ($user->lang['DIRECTION'] == 'ltr') ? 'right' : 'left',
'S_CONTENT_ENCODING' => 'UTF-8',
- '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], ''),
+ 'S_TIMEZONE' => sprintf($user->lang['ALL_TIMES'], $timezone_offset, $timezone_name),
'S_DISPLAY_ONLINE_LIST' => ($l_online_time) ? 1 : 0,
'S_DISPLAY_SEARCH' => (!$config['load_search']) ? 0 : (isset($auth) ? ($auth->acl_get('u_search') && $auth->acl_getf_global('f_search')) : 1),
'S_DISPLAY_PM' => ($config['allow_privmsg'] && !empty($user->data['is_registered']) && ($auth->acl_get('u_readpm') || $auth->acl_get('u_sendpm'))) ? true : false,
@@ -4701,7 +4976,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'S_FORUM_ID' => $forum_id,
'S_TOPIC_ID' => $topic_id,
- 'S_LOGIN_ACTION' => ((!defined('ADMIN_START')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login') : append_sid("index.$phpEx", false, true, $user->session_id)),
+ 'S_LOGIN_ACTION' => ((!defined('ADMIN_START')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login') : append_sid("{$phpbb_admin_path}index.$phpEx", false, true, $user->session_id)),
'S_LOGIN_REDIRECT' => build_hidden_fields(array('redirect' => build_url())),
'S_ENABLE_FEEDS' => ($config['feed_enable']) ? true : false,
@@ -4715,11 +4990,11 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'S_SEARCH_HIDDEN_FIELDS' => build_hidden_fields($s_search_hidden_fields),
- 'T_THEME_PATH' => "{$web_path}styles/" . rawurlencode($user->theme['theme_path']) . '/theme',
- 'T_TEMPLATE_PATH' => "{$web_path}styles/" . rawurlencode($user->theme['template_path']) . '/template',
- 'T_SUPER_TEMPLATE_PATH' => (isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? "{$web_path}styles/" . rawurlencode($user->theme['template_inherit_path']) . '/template' : "{$web_path}styles/" . rawurlencode($user->theme['template_path']) . '/template',
- 'T_IMAGESET_PATH' => "{$web_path}styles/" . rawurlencode($user->theme['imageset_path']) . '/imageset',
- 'T_IMAGESET_LANG_PATH' => "{$web_path}styles/" . rawurlencode($user->theme['imageset_path']) . '/imageset/' . $user->lang_name,
+ 'T_ASSETS_VERSION' => $config['assets_version'],
+ 'T_ASSETS_PATH' => "{$web_path}assets",
+ 'T_THEME_PATH' => "{$web_path}styles/" . rawurlencode($user->style['style_path']) . '/theme',
+ 'T_TEMPLATE_PATH' => "{$web_path}styles/" . rawurlencode($user->style['style_path']) . '/template',
+ 'T_SUPER_TEMPLATE_PATH' => "{$web_path}styles/" . rawurlencode($user->style['style_path']) . '/template',
'T_IMAGES_PATH' => "{$web_path}images/",
'T_SMILIES_PATH' => "{$web_path}{$config['smilies_path']}/",
'T_AVATAR_PATH' => "{$web_path}{$config['avatar_path']}/",
@@ -4727,14 +5002,15 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'T_ICONS_PATH' => "{$web_path}{$config['icons_path']}/",
'T_RANKS_PATH' => "{$web_path}{$config['ranks_path']}/",
'T_UPLOAD_PATH' => "{$web_path}{$config['upload_path']}/",
- 'T_STYLESHEET_LINK' => (!$user->theme['theme_storedb']) ? "{$web_path}styles/" . rawurlencode($user->theme['theme_path']) . '/theme/stylesheet.css' : append_sid("{$phpbb_root_path}style.$phpEx", 'id=' . $user->theme['style_id'] . '&amp;lang=' . $user->lang_name),
- 'T_STYLESHEET_NAME' => $user->theme['theme_name'],
-
- 'T_THEME_NAME' => rawurlencode($user->theme['theme_path']),
- 'T_TEMPLATE_NAME' => rawurlencode($user->theme['template_path']),
- 'T_SUPER_TEMPLATE_NAME' => rawurlencode((isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? $user->theme['template_inherit_path'] : $user->theme['template_path']),
- 'T_IMAGESET_NAME' => rawurlencode($user->theme['imageset_path']),
- 'T_IMAGESET_LANG_NAME' => $user->data['user_lang'],
+ 'T_STYLESHEET_LINK' => "{$web_path}styles/" . rawurlencode($user->style['style_path']) . '/theme/stylesheet.css?assets_version=' . $config['assets_version'],
+ 'T_STYLESHEET_LANG_LINK' => "{$web_path}styles/" . rawurlencode($user->style['style_path']) . '/theme/' . $user->lang_name . '/stylesheet.css?assets_version=' . $config['assets_version'],
+ 'T_JQUERY_LINK' => !empty($config['allow_cdn']) && !empty($config['load_jquery_url']) ? $config['load_jquery_url'] : "{$web_path}assets/javascript/jquery.js?assets_version=" . $config['assets_version'],
+ 'S_ALLOW_CDN' => !empty($config['allow_cdn']),
+
+ 'T_THEME_NAME' => rawurlencode($user->style['style_path']),
+ 'T_THEME_LANG_NAME' => $user->data['user_lang'],
+ 'T_TEMPLATE_NAME' => $user->style['style_path'],
+ 'T_SUPER_TEMPLATE_NAME' => rawurlencode((isset($user->style['style_parent_tree']) && $user->style['style_parent_tree']) ? $user->style['style_parent_tree'] : $user->style['style_path']),
'T_IMAGES' => 'images',
'T_SMILIES' => $config['smilies_path'],
'T_AVATAR' => $config['avatar_path'],
@@ -4744,8 +5020,6 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'T_UPLOAD' => $config['upload_path'],
'SITE_LOGO_IMG' => $user->img('site_logo'),
-
- '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')),
));
// application/xhtml+xml not used because of IE
@@ -4766,10 +5040,35 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
/**
* Generate page footer
+*
+* @param bool $run_cron Whether or not to run the cron
+* @param bool $display_template Whether or not to display the template
+* @param bool $exit_handler Whether or not to run the exit_handler()
*/
-function page_footer($run_cron = true)
+function page_footer($run_cron = true, $display_template = true, $exit_handler = true)
{
global $db, $config, $template, $user, $auth, $cache, $starttime, $phpbb_root_path, $phpEx;
+ global $request, $phpbb_dispatcher, $phpbb_admin_path;
+
+ // A listener can set this variable to `true` when it overrides this function
+ $page_footer_override = false;
+
+ /**
+ * Execute code and/or overwrite page_footer()
+ *
+ * @event core.page_footer
+ * @var bool run_cron Shall we run cron tasks
+ * @var bool page_footer_override Shall we return instead of running
+ * the rest of page_footer()
+ * @since 3.1-A1
+ */
+ $vars = array('run_cron', 'page_footer_override');
+ extract($phpbb_dispatcher->trigger_event('core.page_footer', compact($vars)));
+
+ if ($page_footer_override)
+ {
+ return;
+ }
// Output page creation time
if (defined('DEBUG'))
@@ -4777,24 +5076,22 @@ function page_footer($run_cron = true)
$mtime = explode(' ', microtime());
$totaltime = $mtime[0] + $mtime[1] - $starttime;
- if (!empty($_REQUEST['explain']) && $auth->acl_get('a_') && defined('DEBUG_EXTRA') && method_exists($db, 'sql_report'))
+ if ($request->variable('explain', false) && $auth->acl_get('a_') && defined('DEBUG') && method_exists($db, 'sql_report'))
{
$db->sql_report('display');
}
$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);
- if ($auth->acl_get('a_') && defined('DEBUG_EXTRA'))
+ if ($auth->acl_get('a_') && defined('DEBUG'))
{
- if (function_exists('memory_get_usage'))
+ if (function_exists('memory_get_peak_usage'))
{
- if ($memory_usage = memory_get_usage())
+ if ($memory_usage = memory_get_peak_usage())
{
- global $base_memory_usage;
- $memory_usage -= $base_memory_usage;
$memory_usage = get_formatted_filesize($memory_usage);
- $debug_output .= ' | Memory Usage: ' . $memory_usage;
+ $debug_output .= ' | Peak Memory Usage: ' . $memory_usage;
}
}
@@ -4807,12 +5104,12 @@ function page_footer($run_cron = true)
'TRANSLATION_INFO' => (!empty($user->lang['TRANSLATION_INFO'])) ? $user->lang['TRANSLATION_INFO'] : '',
'CREDIT_LINE' => $user->lang('POWERED_BY', '<a href="https://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group'),
- 'U_ACP' => ($auth->acl_get('a_') && !empty($user->data['is_registered'])) ? append_sid("{$phpbb_root_path}adm/index.$phpEx", false, true, $user->session_id) : '')
+ 'U_ACP' => ($auth->acl_get('a_') && !empty($user->data['is_registered'])) ? append_sid("{$phpbb_admin_path}index.$phpEx", false, true, $user->session_id) : '')
);
// Call cron-type script
$call_cron = false;
- if (!defined('IN_CRON') && $run_cron && !$config['board_disable'] && !$user->data['is_bot'])
+ if (!defined('IN_CRON') && !$config['use_system_cron'] && $run_cron && !$config['board_disable'] && !$user->data['is_bot'])
{
$call_cron = true;
$time_now = (!empty($user->time_now) && is_int($user->time_now)) ? $user->time_now : time();
@@ -4833,47 +5130,27 @@ function page_footer($run_cron = true)
// Call cron job?
if ($call_cron)
{
- $cron_type = '';
+ global $cron;
+ $task = $cron->find_one_ready_task();
- if ($time_now - $config['queue_interval'] > $config['last_queue_run'] && !defined('IN_ADMIN') && file_exists($phpbb_root_path . 'cache/queue.' . $phpEx))
- {
- // Process email queue
- $cron_type = 'queue';
- }
- else if (method_exists($cache, 'tidy') && $time_now - $config['cache_gc'] > $config['cache_last_gc'])
- {
- // Tidy the cache
- $cron_type = 'tidy_cache';
- }
- else if ($config['warnings_expire_days'] && ($time_now - $config['warnings_gc'] > $config['warnings_last_gc']))
+ if ($task)
{
- $cron_type = 'tidy_warnings';
- }
- else if ($time_now - $config['database_gc'] > $config['database_last_gc'])
- {
- // Tidy the database
- $cron_type = 'tidy_database';
- }
- else if ($time_now - $config['search_gc'] > $config['search_last_gc'])
- {
- // Tidy the search
- $cron_type = 'tidy_search';
- }
- else if ($time_now - $config['session_gc'] > $config['session_last_gc'])
- {
- $cron_type = 'tidy_sessions';
- }
-
- if ($cron_type)
- {
- $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" />');
+ $url = $task->get_url();
+ $template->assign_var('RUN_CRON_TASK', '<img src="' . $url . '" width="1" height="1" alt="cron" />');
}
}
- $template->display('body');
+ if ($display_template)
+ {
+ $template->display('body');
+ }
garbage_collection();
- exit_handler();
+
+ if ($exit_handler)
+ {
+ exit_handler();
+ }
}
/**
@@ -4883,6 +5160,18 @@ function page_footer($run_cron = true)
function garbage_collection()
{
global $cache, $db;
+ global $phpbb_dispatcher;
+
+ if (!empty($phpbb_dispatcher))
+ {
+ /**
+ * Unload some objects, to free some memory, before we finish our task
+ *
+ * @event core.garbage_collection
+ * @since 3.1-A1
+ */
+ $phpbb_dispatcher->dispatch('core.garbage_collection');
+ }
// Unload cache, must be done before the DB connection if closed
if (!empty($cache))
@@ -4922,7 +5211,7 @@ function exit_handler()
}
/**
-* Handler for init calls in phpBB. This function is called in user::setup();
+* Handler for init calls in phpBB. This function is called in \phpbb\user::setup();
* This function supports hooks.
*/
function phpbb_user_session_handler()
@@ -4940,4 +5229,77 @@ function phpbb_user_session_handler()
return;
}
-?> \ No newline at end of file
+/**
+* Check if PCRE has UTF-8 support
+* PHP may not be linked with the bundled PCRE lib and instead with an older version
+*
+* @return bool Returns true if PCRE (the regular expressions library) supports UTF-8 encoding
+*/
+function phpbb_pcre_utf8_support()
+{
+ static $utf8_pcre_properties = null;
+ if (is_null($utf8_pcre_properties))
+ {
+ $utf8_pcre_properties = (@preg_match('/\p{L}/u', 'a') !== false);
+ }
+ return $utf8_pcre_properties;
+}
+
+/**
+* Casts a numeric string $input to an appropriate numeric type (i.e. integer or float)
+*
+* @param string $input A numeric string.
+*
+* @return int|float Integer $input if $input fits integer,
+* float $input otherwise.
+*/
+function phpbb_to_numeric($input)
+{
+ return ($input > PHP_INT_MAX) ? (float) $input : (int) $input;
+}
+
+/**
+* Convert either 3.0 dbms or 3.1 db driver class name to 3.1 db driver class name.
+*
+* If $dbms is a valid 3.1 db driver class name, returns it unchanged.
+* Otherwise prepends phpbb\db\driver\ to the dbms to convert a 3.0 dbms
+* to 3.1 db driver class name.
+*
+* @param string $dbms dbms parameter
+* @return db driver class
+*/
+function phpbb_convert_30_dbms_to_31($dbms)
+{
+ // Note: this check is done first because mysqli extension
+ // supplies a mysqli class, and class_exists($dbms) would return
+ // true for mysqli class.
+ // However, per the docblock any valid 3.1 driver name should be
+ // recognized by this function, and have priority over 3.0 dbms.
+ if (class_exists('phpbb\db\driver\\' . $dbms))
+ {
+ return 'phpbb\db\driver\\' . $dbms;
+ }
+
+ if (class_exists($dbms))
+ {
+ // Additionally we could check that $dbms extends phpbb\db\driver\driver.
+ // http://php.net/manual/en/class.reflectionclass.php
+ // Beware of possible performance issues:
+ // http://stackoverflow.com/questions/294582/php-5-reflection-api-performance
+ // We could check for interface implementation in all paths or
+ // only when we do not prepend phpbb\db\driver\.
+
+ /*
+ $reflection = new \ReflectionClass($dbms);
+
+ if ($reflection->isSubclassOf('phpbb\db\driver\driver'))
+ {
+ return $dbms;
+ }
+ */
+
+ return $dbms;
+ }
+
+ throw new \RuntimeException("You have specified an invalid dbms driver: $dbms");
+}