/phpBB/includes/functions.php
PHP | 4370 lines | 3099 code | 504 blank | 767 comment | 435 complexity | 3f9c5c3c1d37fdfa22144f6c87bea30f MD5 | raw file
Possible License(s): AGPL-1.0
Large files files are truncated, but you can click here to view the full file
- <?php
- /**
- *
- * This file is part of the phpBB Forum Software package.
- *
- * @copyright (c) phpBB Limited <https://www.phpbb.com>
- * @license GNU General Public License, version 2 (GPL-2.0)
- *
- * For full copyright and license information, please see
- * the docs/CREDITS.txt file.
- *
- */
- /**
- * @ignore
- */
- if (!defined('IN_PHPBB'))
- {
- exit;
- }
- // Common global functions
- /**
- * Generates an alphanumeric random string of given length
- *
- * @param int $num_chars Length of random string, defaults to 8.
- * This number should be less or equal than 64.
- *
- * @return string
- */
- function gen_rand_string($num_chars = 8)
- {
- $range = array_merge(range('A', 'Z'), range(0, 9));
- $size = count($range);
- $output = '';
- for ($i = 0; $i < $num_chars; $i++)
- {
- $rand = random_int(0, $size-1);
- $output .= $range[$rand];
- }
- return $output;
- }
- /**
- * Generates a user-friendly alphanumeric random string of given length
- * We remove 0 and O so users cannot confuse those in passwords etc.
- *
- * @param int $num_chars Length of random string, defaults to 8.
- * This number should be less or equal than 64.
- *
- * @return string
- */
- function gen_rand_string_friendly($num_chars = 8)
- {
- $range = array_merge(range('A', 'N'), range('P', 'Z'), range(1, 9));
- $size = count($range);
- $output = '';
- for ($i = 0; $i < $num_chars; $i++)
- {
- $rand = random_int(0, $size-1);
- $output .= $range[$rand];
- }
- return $output;
- }
- /**
- * Return unique id
- */
- function unique_id()
- {
- return strtolower(gen_rand_string(16));
- }
- /**
- * Wrapper for mt_rand() which allows swapping $min and $max parameters.
- *
- * PHP does not allow us to swap the order of the arguments for mt_rand() anymore.
- * (since PHP 5.3.4, see http://bugs.php.net/46587)
- *
- * @param int $min Lowest value to be returned
- * @param int $max Highest value to be returned
- *
- * @return int Random integer between $min and $max (or $max and $min)
- */
- function phpbb_mt_rand($min, $max)
- {
- return ($min > $max) ? mt_rand($max, $min) : mt_rand($min, $max);
- }
- /**
- * Wrapper for getdate() which returns the equivalent array for UTC timestamps.
- *
- * @param int $time Unix timestamp (optional)
- *
- * @return array Returns an associative array of information related to the timestamp.
- * See http://www.php.net/manual/en/function.getdate.php
- */
- function phpbb_gmgetdate($time = false)
- {
- if ($time === false)
- {
- $time = time();
- }
- // getdate() interprets timestamps in local time.
- // What follows uses the fact that getdate() and
- // date('Z') balance each other out.
- return getdate($time - date('Z'));
- }
- /**
- * Return formatted string for filesizes
- *
- * @param mixed $value filesize in bytes
- * (non-negative number; int, float or string)
- * @param bool $string_only true if language string should be returned
- * @param array $allowed_units only allow these units (data array indexes)
- *
- * @return mixed data array if $string_only is false
- */
- function get_formatted_filesize($value, $string_only = true, $allowed_units = false)
- {
- global $user;
- $available_units = array(
- 'tb' => array(
- 'min' => 1099511627776, // pow(2, 40)
- 'index' => 4,
- 'si_unit' => 'TB',
- 'iec_unit' => 'TIB',
- ),
- 'gb' => array(
- 'min' => 1073741824, // pow(2, 30)
- 'index' => 3,
- 'si_unit' => 'GB',
- 'iec_unit' => 'GIB',
- ),
- 'mb' => array(
- 'min' => 1048576, // pow(2, 20)
- 'index' => 2,
- 'si_unit' => 'MB',
- 'iec_unit' => 'MIB',
- ),
- 'kb' => array(
- 'min' => 1024, // pow(2, 10)
- 'index' => 1,
- 'si_unit' => 'KB',
- 'iec_unit' => 'KIB',
- ),
- 'b' => array(
- 'min' => 0,
- 'index' => 0,
- 'si_unit' => 'BYTES', // Language index
- 'iec_unit' => 'BYTES', // Language index
- ),
- );
- foreach ($available_units as $si_identifier => $unit_info)
- {
- if (!empty($allowed_units) && $si_identifier != 'b' && !in_array($si_identifier, $allowed_units))
- {
- continue;
- }
- if ($value >= $unit_info['min'])
- {
- $unit_info['si_identifier'] = $si_identifier;
- break;
- }
- }
- unset($available_units);
- for ($i = 0; $i < $unit_info['index']; $i++)
- {
- $value /= 1024;
- }
- $value = round($value, 2);
- // Lookup units in language dictionary
- $unit_info['si_unit'] = (isset($user->lang[$unit_info['si_unit']])) ? $user->lang[$unit_info['si_unit']] : $unit_info['si_unit'];
- $unit_info['iec_unit'] = (isset($user->lang[$unit_info['iec_unit']])) ? $user->lang[$unit_info['iec_unit']] : $unit_info['iec_unit'];
- // Default to IEC
- $unit_info['unit'] = $unit_info['iec_unit'];
- if (!$string_only)
- {
- $unit_info['value'] = $value;
- return $unit_info;
- }
- return $value . ' ' . $unit_info['unit'];
- }
- /**
- * Determine whether we are approaching the maximum execution time. Should be called once
- * at the beginning of the script in which it's used.
- * @return bool Either true if the maximum execution time is nearly reached, or false
- * if some time is still left.
- */
- function still_on_time($extra_time = 15)
- {
- static $max_execution_time, $start_time;
- $current_time = microtime(true);
- if (empty($max_execution_time))
- {
- $max_execution_time = (function_exists('ini_get')) ? (int) @ini_get('max_execution_time') : (int) @get_cfg_var('max_execution_time');
- // If zero, then set to something higher to not let the user catch the ten seconds barrier.
- if ($max_execution_time === 0)
- {
- $max_execution_time = 50 + $extra_time;
- }
- $max_execution_time = min(max(10, ($max_execution_time - $extra_time)), 50);
- // For debugging purposes
- // $max_execution_time = 10;
- global $starttime;
- $start_time = (empty($starttime)) ? $current_time : $starttime;
- }
- return (ceil($current_time - $start_time) < $max_execution_time) ? true : false;
- }
- /**
- * Wrapper for version_compare() that allows using uppercase A and B
- * for alpha and beta releases.
- *
- * See http://www.php.net/manual/en/function.version-compare.php
- *
- * @param string $version1 First version number
- * @param string $version2 Second version number
- * @param string $operator Comparison operator (optional)
- *
- * @return mixed Boolean (true, false) if comparison operator is specified.
- * Integer (-1, 0, 1) otherwise.
- */
- function phpbb_version_compare($version1, $version2, $operator = null)
- {
- $version1 = strtolower($version1);
- $version2 = strtolower($version2);
- if (is_null($operator))
- {
- return version_compare($version1, $version2);
- }
- else
- {
- return version_compare($version1, $version2, $operator);
- }
- }
- // functions used for building option fields
- /**
- * Pick a language, any language ...
- */
- function language_select($default = '')
- {
- global $db;
- $sql = 'SELECT lang_iso, lang_local_name
- FROM ' . LANG_TABLE . '
- ORDER BY lang_english_name';
- $result = $db->sql_query($sql);
- $lang_options = '';
- while ($row = $db->sql_fetchrow($result))
- {
- $selected = ($row['lang_iso'] == $default) ? ' selected="selected"' : '';
- $lang_options .= '<option value="' . $row['lang_iso'] . '"' . $selected . '>' . $row['lang_local_name'] . '</option>';
- }
- $db->sql_freeresult($result);
- return $lang_options;
- }
- /**
- * Pick a template/theme combo,
- */
- function style_select($default = '', $all = false)
- {
- global $db;
- $sql_where = (!$all) ? 'WHERE style_active = 1 ' : '';
- $sql = 'SELECT style_id, style_name
- FROM ' . STYLES_TABLE . "
- $sql_where
- ORDER BY style_name";
- $result = $db->sql_query($sql);
- $style_options = '';
- while ($row = $db->sql_fetchrow($result))
- {
- $selected = ($row['style_id'] == $default) ? ' selected="selected"' : '';
- $style_options .= '<option value="' . $row['style_id'] . '"' . $selected . '>' . $row['style_name'] . '</option>';
- }
- $db->sql_freeresult($result);
- return $style_options;
- }
- /**
- * Format the timezone offset with hours and minutes
- *
- * @param int $tz_offset Timezone offset in seconds
- * @param bool $show_null Whether null offsets should be shown
- * @return string Normalized offset string: -7200 => -02:00
- * 16200 => +04:30
- */
- function phpbb_format_timezone_offset($tz_offset, $show_null = false)
- {
- $sign = ($tz_offset < 0) ? '-' : '+';
- $time_offset = abs($tz_offset);
- if ($time_offset == 0 && $show_null == false)
- {
- return '';
- }
- $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;
- }
- /**
- * Options to pick a timezone and date/time
- *
- * @param \phpbb\template\template $template phpBB template object
- * @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 containing the options for the time selector.
- */
- function phpbb_timezone_select($template, $user, $default = '', $truncate = false)
- {
- static $timezones;
- $default_offset = '';
- if (!isset($timezones))
- {
- $unsorted_timezones = phpbb_get_timezone_identifiers($default);
- $timezones = array();
- foreach ($unsorted_timezones as $timezone)
- {
- $tz = new DateTimeZone($timezone);
- $dt = $user->create_datetime('now', $tz);
- $offset = $dt->getOffset();
- $current_time = $dt->format($user->lang['DATETIME_FORMAT'], true);
- $offset_string = phpbb_format_timezone_offset($offset, true);
- $timezones['UTC' . $offset_string . ' - ' . $timezone] = array(
- 'tz' => $timezone,
- 'offset' => $offset_string,
- 'current' => $current_time,
- );
- if ($timezone === $default)
- {
- $default_offset = 'UTC' . $offset_string;
- }
- }
- unset($unsorted_timezones);
- uksort($timezones, 'phpbb_tz_select_compare');
- }
- $tz_select = $opt_group = '';
- foreach ($timezones as $key => $timezone)
- {
- if ($opt_group != $timezone['offset'])
- {
- // Generate tz_select for backwards compatibility
- $tz_select .= ($opt_group) ? '</optgroup>' : '';
- $tz_select .= '<optgroup label="' . $user->lang(array('timezones', 'UTC_OFFSET_CURRENT'), $timezone['offset'], $timezone['current']) . '">';
- $opt_group = $timezone['offset'];
- $template->assign_block_vars('timezone_select', array(
- 'LABEL' => $user->lang(array('timezones', 'UTC_OFFSET_CURRENT'), $timezone['offset'], $timezone['current']),
- 'VALUE' => $key . ' - ' . $timezone['current'],
- ));
- $selected = (!empty($default_offset) && strpos($key, $default_offset) !== false) ? ' selected="selected"' : '';
- $template->assign_block_vars('timezone_date', array(
- 'VALUE' => $key . ' - ' . $timezone['current'],
- 'SELECTED' => !empty($selected),
- 'TITLE' => $user->lang(array('timezones', 'UTC_OFFSET_CURRENT'), $timezone['offset'], $timezone['current']),
- ));
- }
- $label = $timezone['tz'];
- if (isset($user->lang['timezones'][$label]))
- {
- $label = $user->lang['timezones'][$label];
- }
- $title = $user->lang(array('timezones', 'UTC_OFFSET_CURRENT'), $timezone['offset'], $label);
- if ($truncate)
- {
- $label = truncate_string($label, 50, 255, false, '...');
- }
- // Also generate timezone_select for backwards compatibility
- $selected = ($timezone['tz'] === $default) ? ' selected="selected"' : '';
- $tz_select .= '<option title="' . $title . '" value="' . $timezone['tz'] . '"' . $selected . '>' . $label . '</option>';
- $template->assign_block_vars('timezone_select.timezone_options', array(
- 'TITLE' => $title,
- 'VALUE' => $timezone['tz'],
- 'SELECTED' => !empty($selected),
- 'LABEL' => $label,
- ));
- }
- $tz_select .= '</optgroup>';
- return $tz_select;
- }
- // Functions handling topic/post tracking/marking
- /**
- * 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, $phpbb_dispatcher;
- $post_time = ($post_time === 0 || $post_time > time()) ? time() : (int) $post_time;
- $should_markread = true;
- /**
- * This event is used for performing actions directly before marking forums,
- * topics or posts as read.
- *
- * It is also possible to prevent the marking. For that, the $should_markread parameter
- * should be set to FALSE.
- *
- * @event core.markread_before
- * @var string mode Variable containing marking mode value
- * @var mixed forum_id Variable containing forum id, or false
- * @var mixed topic_id Variable containing topic id, or false
- * @var int post_time Variable containing post time
- * @var int user_id Variable containing the user id
- * @var bool should_markread Flag indicating if the markread should be done or not.
- * @since 3.1.4-RC1
- */
- $vars = array(
- 'mode',
- 'forum_id',
- 'topic_id',
- 'post_time',
- 'user_id',
- 'should_markread',
- );
- extract($phpbb_dispatcher->trigger_event('core.markread_before', compact($vars)));
- if (!$should_markread)
- {
- return;
- }
- if ($mode == 'all')
- {
- if (empty($forum_id))
- {
- // Mark all forums read (index page)
- /* @var $phpbb_notifications \phpbb\notification\manager */
- $phpbb_notifications = $phpbb_container->get('notification_manager');
- // Mark all topic notifications read for this user
- $phpbb_notifications->mark_notifications(array(
- 'notification.type.topic',
- 'notification.type.quote',
- 'notification.type.bookmark',
- 'notification.type.post',
- 'notification.type.approve_topic',
- 'notification.type.approve_post',
- ), false, $user->data['user_id'], $post_time);
- if ($config['load_db_lastread'] && $user->data['is_registered'])
- {
- // Mark all forums read (index page)
- $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 = $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($post_time - $config['board_startdate'], 10, 36);
- $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'])
- {
- $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 ($mode == 'topics')
- {
- // Mark all topics in forums read
- if (!is_array($forum_id))
- {
- $forum_id = array($forum_id);
- }
- else
- {
- $forum_id = array_unique($forum_id);
- }
- /* @var $phpbb_notifications \phpbb\notification\manager */
- $phpbb_notifications = $phpbb_container->get('notification_manager');
- $phpbb_notifications->mark_notifications_by_parent(array(
- 'notification.type.topic',
- 'notification.type.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_by_parent(array(
- 'notification.type.quote',
- 'notification.type.bookmark',
- 'notification.type.post',
- 'notification.type.approve_post',
- ), $topic_ids, $user->data['user_id'], $post_time);
- // Add 0 to forums array to mark global announcements correctly
- // $forum_id[] = 0;
- if ($config['load_db_lastread'] && $user->data['is_registered'])
- {
- $sql = 'DELETE FROM ' . TOPICS_TRACK_TABLE . "
- WHERE user_id = {$user->data['user_id']}
- AND mark_time < $post_time
- AND " . $db->sql_in_set('forum_id', $forum_id);
- $db->sql_query($sql);
- $sql = 'SELECT forum_id
- FROM ' . FORUMS_TRACK_TABLE . "
- WHERE user_id = {$user->data['user_id']}
- AND " . $db->sql_in_set('forum_id', $forum_id);
- $result = $db->sql_query($sql);
- $sql_update = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $sql_update[] = (int) $row['forum_id'];
- }
- $db->sql_freeresult($result);
- if (count($sql_update))
- {
- $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);
- }
- if ($sql_insert = array_diff($forum_id, $sql_update))
- {
- $sql_ary = array();
- foreach ($sql_insert as $f_id)
- {
- $sql_ary[] = array(
- 'user_id' => (int) $user->data['user_id'],
- 'forum_id' => (int) $f_id,
- 'mark_time' => $post_time,
- );
- }
- $db->sql_multi_insert(FORUMS_TRACK_TABLE, $sql_ary);
- }
- }
- else if ($config['load_anon_lastread'] || $user->data['is_registered'])
- {
- $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)
- {
- $topic_ids36 = (isset($tracking['tf'][$f_id])) ? $tracking['tf'][$f_id] : array();
- if (isset($tracking['tf'][$f_id]))
- {
- unset($tracking['tf'][$f_id]);
- }
- foreach ($topic_ids36 as $topic_id36)
- {
- unset($tracking['t'][$topic_id36]);
- }
- if (isset($tracking['f'][$f_id]))
- {
- unset($tracking['f'][$f_id]);
- }
- $tracking['f'][$f_id] = base_convert($post_time - $config['board_startdate'], 10, 36);
- }
- if (isset($tracking['tf']) && empty($tracking['tf']))
- {
- unset($tracking['tf']);
- }
- $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);
- }
- }
- else if ($mode == 'topic')
- {
- if ($topic_id === false || $forum_id === false)
- {
- return;
- }
- /* @var $phpbb_notifications \phpbb\notification\manager */
- $phpbb_notifications = $phpbb_container->get('notification_manager');
- // Mark post notifications read for this user in this topic
- $phpbb_notifications->mark_notifications(array(
- 'notification.type.topic',
- 'notification.type.approve_topic',
- ), $topic_id, $user->data['user_id'], $post_time);
- $phpbb_notifications->mark_notifications_by_parent(array(
- 'notification.type.quote',
- 'notification.type.bookmark',
- 'notification.type.post',
- 'notification.type.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
- WHERE user_id = {$user->data['user_id']}
- AND mark_time < $post_time
- AND topic_id = $topic_id";
- $db->sql_query($sql);
- // insert row
- if (!$db->sql_affectedrows())
- {
- $db->sql_return_on_error(true);
- $sql_ary = array(
- 'user_id' => (int) $user->data['user_id'],
- 'topic_id' => (int) $topic_id,
- 'forum_id' => (int) $forum_id,
- 'mark_time' => $post_time,
- );
- $db->sql_query('INSERT INTO ' . TOPICS_TRACK_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
- $db->sql_return_on_error(false);
- }
- }
- else if ($config['load_anon_lastread'] || $user->data['is_registered'])
- {
- $tracking = $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);
- if (!isset($tracking['t'][$topic_id36]))
- {
- $tracking['tf'][$forum_id][$topic_id36] = true;
- }
- $tracking['t'][$topic_id36] = base_convert($post_time - (int) $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 (strlen($request->variable($config['cookie_name'] . '_track', '', true, \phpbb\request\request_interface::COOKIE)) > 10000)
- {
- //echo 'Cookie grown too large' . print_r($tracking, true);
- // We get the ten most minimum stored time offsets and its associated topic ids
- $time_keys = array();
- for ($i = 0; $i < 10 && count($tracking['t']); $i++)
- {
- $min_value = min($tracking['t']);
- $m_tkey = array_search($min_value, $tracking['t']);
- unset($tracking['t'][$m_tkey]);
- $time_keys[$m_tkey] = $min_value;
- }
- // Now remove the topic ids from the array...
- foreach ($tracking['tf'] as $f_id => $topic_id_ary)
- {
- foreach ($time_keys as $m_tkey => $min_value)
- {
- if (isset($topic_id_ary[$m_tkey]))
- {
- $tracking['f'][$f_id] = $min_value;
- unset($tracking['tf'][$f_id][$m_tkey]);
- }
- }
- }
- if ($user->data['is_registered'])
- {
- $user->data['user_lastmark'] = intval(base_convert(max($time_keys) + $config['board_startdate'], 36, 10));
- $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
- {
- $tracking['l'] = max($time_keys);
- }
- }
- $user->set_cookie('track', tracking_serialize($tracking), $post_time + 31536000);
- $request->overwrite($config['cookie_name'] . '_track', tracking_serialize($tracking), \phpbb\request\request_interface::COOKIE);
- }
- }
- else if ($mode == 'post')
- {
- if ($topic_id === false)
- {
- return;
- }
- $use_user_id = (!$user_id) ? $user->data['user_id'] : $user_id;
- if ($config['load_db_track'] && $use_user_id != ANONYMOUS)
- {
- $db->sql_return_on_error(true);
- $sql_ary = array(
- 'user_id' => (int) $use_user_id,
- 'topic_id' => (int) $topic_id,
- 'topic_posted' => 1,
- );
- $db->sql_query('INSERT INTO ' . TOPICS_POSTED_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
- $db->sql_return_on_error(false);
- }
- }
- /**
- * This event is used for performing actions directly after forums,
- * topics or posts have been marked as read.
- *
- * @event core.markread_after
- * @var string mode Variable containing marking mode value
- * @var mixed forum_id Variable containing forum id, or false
- * @var mixed topic_id Variable containing topic id, or false
- * @var int post_time Variable containing post time
- * @var int user_id Variable containing the user id
- * @since 3.2.6-RC1
- */
- $vars = array(
- 'mode',
- 'forum_id',
- 'topic_id',
- 'post_time',
- 'user_id',
- );
- extract($phpbb_dispatcher->trigger_event('core.markread_after', compact($vars)));
- }
- /**
- * Get topic tracking info by using already fetched info
- */
- function get_topic_tracking($forum_id, $topic_ids, &$rowset, $forum_mark_time, $global_announce_list = false)
- {
- global $user;
- $last_read = array();
- if (!is_array($topic_ids))
- {
- $topic_ids = array($topic_ids);
- }
- foreach ($topic_ids as $topic_id)
- {
- if (!empty($rowset[$topic_id]['mark_time']))
- {
- $last_read[$topic_id] = $rowset[$topic_id]['mark_time'];
- }
- }
- $topic_ids = array_diff($topic_ids, array_keys($last_read));
- if (count($topic_ids))
- {
- $mark_time = array();
- if (!empty($forum_mark_time[$forum_id]) && $forum_mark_time[$forum_id] !== false)
- {
- $mark_time[$forum_id] = $forum_mark_time[$forum_id];
- }
- $user_lastmark = (isset($mark_time[$forum_id])) ? $mark_time[$forum_id] : $user->data['user_lastmark'];
- foreach ($topic_ids as $topic_id)
- {
- $last_read[$topic_id] = $user_lastmark;
- }
- }
- return $last_read;
- }
- /**
- * Get topic tracking info from db (for cookie based tracking only this function is used)
- */
- function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_list = false)
- {
- global $config, $user, $request;
- $last_read = array();
- if (!is_array($topic_ids))
- {
- $topic_ids = array($topic_ids);
- }
- if ($config['load_db_lastread'] && $user->data['is_registered'])
- {
- global $db;
- $sql = 'SELECT topic_id, mark_time
- FROM ' . TOPICS_TRACK_TABLE . "
- WHERE user_id = {$user->data['user_id']}
- AND " . $db->sql_in_set('topic_id', $topic_ids);
- $result = $db->sql_query($sql);
- while ($row = $db->sql_fetchrow($result))
- {
- $last_read[$row['topic_id']] = $row['mark_time'];
- }
- $db->sql_freeresult($result);
- $topic_ids = array_diff($topic_ids, array_keys($last_read));
- if (count($topic_ids))
- {
- $sql = 'SELECT forum_id, mark_time
- FROM ' . FORUMS_TRACK_TABLE . "
- WHERE user_id = {$user->data['user_id']}
- AND forum_id = $forum_id";
- $result = $db->sql_query($sql);
- $mark_time = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $mark_time[$row['forum_id']] = $row['mark_time'];
- }
- $db->sql_freeresult($result);
- $user_lastmark = (isset($mark_time[$forum_id])) ? $mark_time[$forum_id] : $user->data['user_lastmark'];
- foreach ($topic_ids as $topic_id)
- {
- $last_read[$topic_id] = $user_lastmark;
- }
- }
- }
- else if ($config['load_anon_lastread'] || $user->data['is_registered'])
- {
- global $tracking_topics;
- if (!isset($tracking_topics) || !count($tracking_topics))
- {
- $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'])
- {
- $user_lastmark = (isset($tracking_topics['l'])) ? base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate'] : 0;
- }
- else
- {
- $user_lastmark = $user->data['user_lastmark'];
- }
- foreach ($topic_ids as $topic_id)
- {
- $topic_id36 = base_convert($topic_id, 10, 36);
- if (isset($tracking_topics['t'][$topic_id36]))
- {
- $last_read[$topic_id] = base_convert($tracking_topics['t'][$topic_id36], 36, 10) + $config['board_startdate'];
- }
- }
- $topic_ids = array_diff($topic_ids, array_keys($last_read));
- if (count($topic_ids))
- {
- $mark_time = array();
- if (isset($tracking_topics['f'][$forum_id]))
- {
- $mark_time[$forum_id] = base_convert($tracking_topics['f'][$forum_id], 36, 10) + $config['board_startdate'];
- }
- $user_lastmark = (isset($mark_time[$forum_id])) ? $mark_time[$forum_id] : $user_lastmark;
- foreach ($topic_ids as $topic_id)
- {
- $last_read[$topic_id] = $user_lastmark;
- }
- }
- }
- return $last_read;
- }
- /**
- * Get list of unread topics
- *
- * @param int $user_id User ID (or false for current user)
- * @param string $sql_extra Extra WHERE SQL statement
- * @param string $sql_sort ORDER BY SQL sorting statement
- * @param string $sql_limit Limits the size of unread topics list, 0 for unlimited query
- * @param string $sql_limit_offset Sets the offset of the first row to search, 0 to search from the start
- *
- * @return array[int][int] Topic ids as keys, mark_time of topic as value
- */
- function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $sql_limit = 1001, $sql_limit_offset = 0)
- {
- global $config, $db, $user, $request;
- global $phpbb_dispatcher;
- $user_id = ($user_id === false) ? (int) $user->data['user_id'] : (int) $user_id;
- // Data array we're going to return
- $unread_topics = array();
- if (empty($sql_sort))
- {
- $sql_sort = 'ORDER BY t.topic_last_post_time DESC, t.topic_last_post_id DESC';
- }
- if ($config['load_db_lastread'] && $user->data['is_registered'])
- {
- // Get list of the unread topics
- $last_mark = (int) $user->data['user_lastmark'];
- $sql_array = array(
- 'SELECT' => 't.topic_id, t.topic_last_post_time, tt.mark_time as topic_mark_time, ft.mark_time as forum_mark_time',
- 'FROM' => array(TOPICS_TABLE => 't'),
- 'LEFT_JOIN' => array(
- array(
- 'FROM' => array(TOPICS_TRACK_TABLE => 'tt'),
- 'ON' => "tt.user_id = $user_id AND t.topic_id = tt.topic_id",
- ),
- array(
- 'FROM' => array(FORUMS_TRACK_TABLE => 'ft'),
- 'ON' => "ft.user_id = $user_id AND t.forum_id = ft.forum_id",
- ),
- ),
- 'WHERE' => "
- t.topic_last_post_time > $last_mark AND
- (
- (tt.mark_time IS NOT NULL AND t.topic_last_post_time > tt.mark_time) OR
- (tt.mark_time IS NULL AND ft.mark_time IS NOT NULL AND t.topic_last_post_time > ft.mark_time) OR
- (tt.mark_time IS NULL AND ft.mark_time IS NULL)
- )
- $sql_extra
- $sql_sort",
- );
- /**
- * Change SQL query for fetching unread topics data
- *
- * @event core.get_unread_topics_modify_sql
- * @var array sql_array Fully assembled SQL query with keys SELECT, FROM, LEFT_JOIN, WHERE
- * @var int last_mark User's last_mark time
- * @var string sql_extra Extra WHERE SQL statement
- * @var string sql_sort ORDER BY SQL sorting statement
- * @since 3.1.4-RC1
- */
- $vars = array(
- 'sql_array',
- 'last_mark',
- 'sql_extra',
- 'sql_sort',
- );
- extract($phpbb_dispatcher->trigger_event('core.get_unread_topics_modify_sql', compact($vars)));
- $sql = $db->sql_build_query('SELECT', $sql_array);
- $result = $db->sql_query_limit($sql, $sql_limit, $sql_limit_offset);
- while ($row = $db->sql_fetchrow($result))
- {
- $topic_id = (int) $row['topic_id'];
- $unread_topics[$topic_id] = ($row['topic_mark_time']) ? (int) $row['topic_mark_time'] : (($row['forum_mark_time']) ? (int) $row['forum_mark_time'] : $last_mark);
- }
- $db->sql_freeresult($result);
- }
- else if ($config['load_anon_lastread'] || $user->data['is_registered'])
- {
- global $tracking_topics;
- if (empty($tracking_topics))
- {
- $tracking_topics = $request->variable($config['cookie_name'] . '_track', '', false, \phpbb\request\request_interface::COOKIE);
- $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
- }
- if (!$user->data['is_registered'])
- {
- $user_lastmark = (isset($tracking_topics['l'])) ? base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate'] : 0;
- }
- else
- {
- $user_lastmark = (int) $user->data['user_lastmark'];
- }
- $sql = 'SELECT t.topic_id, t.forum_id, t.topic_last_post_time
- FROM ' . TOPICS_TABLE . ' t
- WHERE t.topic_last_post_time > ' . $user_lastmark . "
- $sql_extra
- $sql_sort";
- $result = $db->sql_query_limit($sql, $sql_limit, $sql_limit_offset);
- while ($row = $db->sql_fetchrow($result))
- {
- $forum_id = (int) $row['forum_id'];
- $topic_id = (int) $row['topic_id'];
- $topic_id36 = base_convert($topic_id, 10, 36);
- if (isset($tracking_topics['t'][$topic_id36]))
- {
- $last_read = base_convert($tracking_topics['t'][$topic_id36], 36, 10) + $config['board_startdate'];
- if ($row['topic_last_post_time'] > $last_read)
- {
- $unread_topics[$topic_id] = $last_read;
- }
- }
- else if (isset($tracking_topics['f'][$forum_id]))
- {
- $mark_time = base_convert($tracking_topics['f'][$forum_id], 36, 10) + $config['board_startdate'];
- if ($row['topic_last_post_time'] > $mark_time)
- {
- $unread_topics[$topic_id] = $mark_time;
- }
- }
- else
- {
- $unread_topics[$topic_id] = $user_lastmark;
- }
- }
- $db->sql_freeresult($result);
- }
- return $unread_topics;
- }
- /**
- * Check for read forums and update topic tracking info accordingly
- *
- * @param int $forum_id the forum id to check
- * @param int $forum_last_post_time the forums last post time
- * @param int $f_mark_time the forums last mark time if user is registered and load_db_lastread enabled
- * @param int $mark_time_forum false if the mark time needs to be obtained, else the last users forum mark time
- *
- * @return true if complete forum got marked read, else false.
- */
- function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time = false, $mark_time_forum = false)
- {
- global $db, $tracking_topics, $user, $config, $request, $phpbb_container;
- // Determine the users last forum mark time if not given.
- if ($mark_time_forum === false)
- {
- if ($config['load_db_lastread'] && $user->data['is_registered'])
- {
- $mark_time_forum = (!empty($f_mark_time)) ? $f_mark_time : $user->data['user_lastmark'];
- }
- else if ($config['load_anon_lastread'] || $user->data['is_registered'])
- {
- $tracking_topics = $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'])
- {
- $user->data['user_lastmark'] = (isset($tracking_topics['l'])) ? (int) (base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate']) : 0;
- }
- $mark_time_forum = (isset($tracking_topics['f'][$forum_id])) ? (int) (base_convert($tracking_topics['f'][$forum_id], 36, 10) + $config['board_startdate']) : $user->data['user_lastmark'];
- }
- }
- // Handle update of unapproved topics info.
- // Only update for moderators having m_approve permission for the forum.
- /* @var $phpbb_content_visibility \phpbb\content_visibility */
- $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.
- if ($config['load_db_lastread'] && $user->data['is_registered'])
- {
- if ($mark_time_forum >= $forum_last_post_time)
- {
- // We do not need to mark read, this happened before. Therefore setting this to true
- $row = true;
- }
- else
- {
- $sql = 'SELECT t.forum_id
- FROM ' . TOPICS_TABLE . ' t
- LEFT JOIN ' . TOPICS_TRACK_TABLE . ' tt
- ON (tt.topic_id = t.topic_id
- AND tt.user_id = ' . $user->data['user_id'] . ')
- WHERE t.forum_id = ' . $forum_id . '
- AND t.topic_last_post_time > ' . $mark_time_forum . '
- AND t.topic_moved_id = 0
- AND ' . $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);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
- }
- }
- else if ($config['load_anon_lastread'] || $user->data['is_registered'])
- {
- // Get information from cookie
- if (!isset($tracking_topics['tf'][$forum_id]))
- {
- // We do not need to mark read, this happened before. Therefore setting this to true
- $row = true;
- }
- else
- {
- $sql = 'SELECT t.topic_id
- 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
- AND ' . $phpbb_content_visibility->get_visibility_sql('topic', $forum_id, 't.');
- $result = $db->sql_query($sql);
- $check_forum = $tracking_topics['tf'][$forum_id];
- $unread = false;
- while ($row = $db->sql_fetchrow($result))
- {
- if (!isset($check_forum[base_convert($row['topic_id'], 10, 36)]))
- {
- $unread = true;
- break;
- }
- }
- $db->sql_freeresult($result);
- $row = $unread;
- }
- }
- else
- {
- $row = true;
- }
- if (!$row)
- {
- markread('topics', $forum_id);
- return true;
- }
- return false;
- }
- /**
- * Transform an array into a serialized format
- */
- function tracking_serialize($input)
- {
- $out = '';
- foreach ($input as $key => $value)
- {
- if (is_array($value))
- {
- $out .= $key . ':(' . tracking_serialize($value) . ');';
- }
- else
- {
- $out .= $key . ':' . $value . ';';
- }
- }
- return $out;
- }
- /**
- * Transform a serialized array into an actual array
- */
- function tracking_unserialize($string, $max_depth = 3)
- {
- $n = strlen($string);
- if ($n > 10010)
- {
- die('Invalid data supplied');
- }
- $data = $stack = array();
- $key = '';
- $mode = 0;
- $level = &$data;
- for ($i = 0; $i < $n; ++$i)
- {
- switch ($mode)
- {
- case 0:
- switch ($string[$i])
- {
- case ':':
- $level[$key] = 0;
- $mode = 1;
- break;
- case ')':
- unset($level);
- $level = array_pop($stack);
- $mode = 3;
- break;
- default:
- $key .= $string[$i];
- }
- break;
- case 1:
- switch ($string[$i])
- {
- case '(':
- if (count($stack) >= $max_depth)
- {
- die('Invalid data supplied');
- }
- $stack[] = &$level;
- $level[$key] = array();
- $level = &$level[$key];
- $key = '';
- $mode = 0;
- break;
- default:
- $level[$key] = $string[$i];
- $mode = 2;
- break;
- }
- break;
- case 2:
- switch ($string[$i])
- {
- case ')':
- unset($level);
- $level = array_pop($stack);
- $mode = 3;
- break;
- case ';':
- $key = '';
- $mode = 0;
- break;
- default:
- $level[$key] .= $string[$i];
- break;
- }
- break;
- case 3:
- switch ($string[$i])
- {
- case ')':
- unset($level);
- $level = array_pop($stack);
- break;
- case ';':
- $key = '';
- $mode = 0;
- break;
- default:
- die('Invalid data supplied');
- break;
- }
- break;
- }
- }
- if (count($stack) != 0 || ($mode != 0 && $mode != 3))
- {
- die('Invalid data supplied');
- }
- return $level;
- }
- // Server functions (building urls, redirecting...)
- /**
- * Append session id to url.
- *
- * @param string $url The url the session id needs to be appended to (can have params)
- * @param mixed $params String or array of additional url parameters
- * @param bool $is_amp Is url using & (true) or & (false)
- * @param string $session_id Possibility to use a custom session id instead of the global one
- * @param bool $is_route Is url generated by a route.
- *
- * @return string The corrected url.
- *
- * Examples:
- * <code>
- * append_sid("{$phpbb_root_path}viewtopic.$phpEx?t=1&f=2");
- * append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=1&f=2');
- * append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=1&f=2', false);
- * append_sid("{$phpbb_root_path}viewtopic.$phpEx", array('t' => 1, 'f' => 2));
- * </code>
- *
- */
- function append_sid($url, $params = false, $is_amp = true, $session_id = false, $is_route = false)
- {
- global $_SID, $_EXTRA_URL, $phpbb_path_helper;
- global $phpbb_dispatcher;
- if ($params === '' || (is_array($params) && empty($params)))
- {
- // Do not append the ? if the param-list is empty anyway.
- $params = false;
- }
- // Update the root path with the correct relative web path
- if (!$is_route && $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 & (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)
- * @var bool is_route Is url generated by a route.
- * @since 3.1.0-a1
- */
- $vars = array('url', 'params', 'is_amp', 'session_id', 'append_sid_overwrite', 'is_route');
- extract($phpbb_dispatcher->trigger_event('core.append_sid', compact($vars)));
- if ($append_sid_overwrite)
- {
- return $append_sid_overwrite;
- }
- $params_is_array = is_array($params);
- // Get anchor
- $anchor = '';
- if (strpos($url, '#') !== false)
- {
- list($url, $anchor) = explode('#', $url, 2);
- $anchor = '#' . $anchor;
- }
- else if (!$params_is_array && strpos($params, '#') !== false)
- {
- list($params, $anchor) = explode('#', $params, 2);
- $anchor = '#' . $anchor;
- }
- // Handle really simple cases quickly
- if ($_SID == '' && $session_id === false && empty($_EXTRA_URL) && !$params_is_array && !$anchor)
- {
- if ($params === false)
- {
- return $url;
- }
- $url_delim = (strpos($url, '?') === false) ? '?' : (($is_amp) ? '&' : '&');
- return $url . ($params !== false ? $url_delim. $params : '');
- }
- // Assign sid if session id is not specified
- if ($session_id === false)
- {
- $session_id = $_SID;
- }
- $amp_delim = ($is_amp) ? '&' : '&';
- $url_delim = (strpos($url, '?') === false) ? '?' : $amp_delim;
- // Appending custom url parameter?
- $append_url = (!empty($_EXTRA_URL)) ? implode($amp_delim, $_EXTRA_URL) : '';
- // Use the short variant if possible ;)
- if ($params === false)
- {
- // Append session id
- if (!$session_id)
- {
- return $url . (($append_url) ? $url_delim . $append_url : '') . $anchor;
- }
- else
- {
- return $url . (($append_url) ? $url_delim . $append_url . $amp_delim : $url_delim) . 'sid=' . $session_id . $anchor;
- }
- }
- // Build string if parameters are specified as array
- if (is_array($params))
- {
- $output = array();
- foreach ($params as $key => $item)
- {
- if ($item === NULL)
- {
- continue;
- }
- if ($key == '#')
- {
- $anchor = '#' . $item;
- continue;
- }
- $output[] = $key . '=' . $item;
- }
- $params = implode($amp_delim, $output);
- }
- // Append session id and parameters (even if they are empty)
- // If parameters are empty, the developer can still append his/her parameters without caring about the delimiter
- return $url . (($append_url) ? $url_delim . $append_url . $amp_delim : $url_delim) . $params . ((!$session_id) ? '' : $amp_delim . 'sid=' . $session_id) . $anchor;
- }
- /**
- * Generate board url (example: http://www.example.com/phpBB)
- *
- * @param bool $without_script_path if set to true the script path gets not appended (example: http://www.example.com)
- *
- * @return string the generated board url
- */
- function generate_board_url($without_script_path = false)
- {
- global $config, $user, $request, $symfony_request;
- $server_name = $user->host;
- // Forcing server vars is the only way to specify/override the protocol
- if ($config['force_server_vars'] || !$server_name)
- {
- $server_protocol = ($config['server_protocol']) ? $config['server_protocol'] : (($config['cookie_secure']) ? 'https://' : 'http://');
- $server_name = $config['server_name'];
- $server_port = (int) $config['server_port'];
- $script_path = $config['script_path'];
- $url = $server_protocol . $server_name;
- $cookie_secure = $config['cookie_secure'];
- }
- else
- {
- $server_port = (int) $symfony_request->getPort();
- $forwarded_proto = $request->server('HTTP_X_FORWARDED_PROTO');
- if (!empty($forwarded_proto) && $forwarded_proto === 'https')
- {
- $server_port = 443;
- }
- // Do not rely on cookie_secure, users seem to think that it means a secured cookie instead of an encrypted connection
- $cookie_secure = $request->is_secure() ? 1 : 0;
- $url = (($cookie_secure) ? 'https://' : 'http://') . $server_name;
- $script_path = $user->page['root_script_path'];
- }
- if ($server_port && (($cookie_secure && $server_port <> 443) || (!$cookie_secure && $server_port <> 80)))
- {
- // HTTP HOST can carry a port number (we fetch $user->host, but for old versions this may be true)
- if (strpos($server_name, ':') === false)
- {
- $url .= ':' . $server_port;
- }
- }
- if (!$without_script_path)
- {
- $url .= $script_path;
- }
- // Strip / from the end
- if (substr($url, -1, 1) == '/')
- {
- $url = substr($url, 0, -1);
- }
- return $url;
- }
- /**
- * Redirects the user to another page then exits the script nicely
- * This function is intended for urls within the board. It's not meant to redirect to cross-domains.
- *
- * @param string $url The url to redirect to
- * @param bool $return If true, do not redirect but return the sanitized URL. Default is no return.
- * @param bool $disable_cd_check If true, redirect() will redirect to an external domain. If false, the redirect point to the boards url if it does not match the current domain. Default is false.
- */
- function redirect($url, $return = false, $disable_cd_check = false)
- {
- global $user, $phpbb_path_helper, $phpbb_dispatcher;
- if (!$user->is_setup())
- {
- $user->add_lang('common');
- }
- // Make sure no &'s are in, this will break the redirect
- $url = str_replace('&', '&', $url);
- // Determine which type of redirect we need to handle...
- $url_parts = @parse_url($url);
- if ($url_parts === false)
- {
- // Malformed url
- trigger_error('INSECURE_REDIRECT', E_USER_WARNING);
- }
- else if (!empty($url_parts['scheme']) && !empty($url_parts['host']))
- {
- // Attention: only able to redirect within the same domain if $disable_cd_check is false (yourdomain.com -> www.yourdomain.com will not work)
- if (!$disable_cd_check && $url_parts['host'] !== $user->host)
- {
- trigger_error('INSECURE_REDIRECT', E_USER_WARNING);
- }
- }
- else if ($url[0] == '/')
- {
- // Absolute uri, prepend direct url...
- $url = generate_board_url(true) . $url;
- }
- else
- {
- // Relative uri
- $pathinfo = pathinfo($url);
- // Is the uri pointing to the current directory?
- if ($pathinfo['dirname'] == '.')
- {
- $url = str_replace('./', '', $url);
- // Strip / from the beginning
- if ($url && substr($url, 0, 1) == '/')
- {
- $url = substr($url, 1);
- }
- }
- $url = $phpbb_path_helper->remove_web_root_path($url);
- if ($user->page['page_dir'])
- {
- $url = $user->page['page_dir'] . '/' . $url;
- }
- $url = generate_board_url() . '/' . $url;
- }
- // Clean URL and check if we go outside the forum directory
- $url = $phpbb_path_helper->clean_url($url);
- if (!$disable_cd_check && strpos($url, generate_board_url(true) . '/') !== 0)
- {
- trigger_error('INSECURE_REDIRECT', E_USER_WARNING);
- }
- // 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('INSECURE_REDIRECT', E_USER_WARNING);
- }
- // Now, also check the protocol and for a valid url the last time...
- $allowed_protocols = array('http', 'https', 'ftp', 'ftps');
- $url_parts = parse_url($url);
- if ($url_parts === false || empty($url_parts['scheme']) || !in_array($url_parts['scheme'], $allowed_protocols))
- {
- trigger_error('INSECURE_REDIRECT', E_USER_WARNING);
- }
- /**
- * Execute code and/or overwrite redirect()
- *
- * @event core.functions.redirect
- * @var string url The url
- * @var bool return If true, do not redirect but return the sanitized URL.
- * @var bool disable_cd_check If true, redirect() will redirect to an external domain. If false, the redirect point to the boards url if it does not match the current domain.
- * @since 3.1.0-RC3
- */
- $vars = array('url', 'return', 'disable_cd_check');
- extract($phpbb_dispatcher->trigger_event('core.functions.redirect', compact($vars)));
- if ($return)
- {
- return $url;
- }
- else
- {
- garbage_collection();
- }
- // Behave as per HTTP/1.1 spec for others
- header('Location: ' . $url);
- exit;
- }
- /**
- * Re-Apply session id after page reloads
- */
- function reapply_sid($url, $is_route = false)
- {
- global $phpEx, $phpbb_root_path;
- if ($url === "index.$phpEx")
- {
- return append_sid("index.$phpEx");
- }
- else if ($url === "{$phpbb_root_path}index.$phpEx")
- {
- return append_sid("{$phpbb_root_path}index.$phpEx");
- }
- // Remove previously added sid
- if (strpos($url, 'sid=') !== false)
- {
- // All kind of links
- $url = preg_replace('/(\?)?(&|&)?sid=[a-z0…
Large files files are truncated, but you can click here to view the full file