diff options
Diffstat (limited to 'phpBB/includes/functions.php')
| -rw-r--r-- | phpBB/includes/functions.php | 619 |
1 files changed, 500 insertions, 119 deletions
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 476565452c..092a5d5d86 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -71,12 +71,13 @@ function request_var($var_name, $default, $multibyte = false, $cookie = false) $_REQUEST[$var_name] = isset($_POST[$var_name]) ? $_POST[$var_name] : $_GET[$var_name]; } - if (!isset($_REQUEST[$var_name]) || (is_array($_REQUEST[$var_name]) && !is_array($default)) || (is_array($default) && !is_array($_REQUEST[$var_name]))) + $super_global = ($cookie) ? '_COOKIE' : '_REQUEST'; + if (!isset($GLOBALS[$super_global][$var_name]) || is_array($GLOBALS[$super_global][$var_name]) != is_array($default)) { return (is_array($default)) ? array() : $default; } - $var = $_REQUEST[$var_name]; + $var = $GLOBALS[$super_global][$var_name]; if (!is_array($default)) { $type = gettype($default); @@ -174,7 +175,7 @@ function set_config_count($config_name, $increment, $is_dynamic = false) switch ($db->sql_layer) { case 'firebird': - $sql_update = 'CAST(CAST(config_value as integer) + ' . (int) $increment . ' as CHAR)'; + $sql_update = 'CAST(CAST(config_value as integer) + ' . (int) $increment . ' as VARCHAR(255))'; break; case 'postgres': @@ -231,27 +232,82 @@ function unique_id($extra = 'c') /** * Return formatted string for filesizes +* +* @param int $value filesize in bytes +* @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 +* @author bantu */ -function get_formatted_filesize($bytes, $add_size_lang = true) +function get_formatted_filesize($value, $string_only = true, $allowed_units = false) { global $user; - if ($bytes >= pow(2, 30)) + $available_units = array( + '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) { - return ($add_size_lang) ? round($bytes / 1024 / 1024 / 1024, 2) . ' ' . $user->lang['GIB'] : round($bytes / 1024 / 1024 / 1024, 2); + 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); - if ($bytes >= pow(2, 20)) + for ($i = 0; $i < $unit_info['index']; $i++) { - return ($add_size_lang) ? round($bytes / 1024 / 1024, 2) . ' ' . $user->lang['MIB'] : round($bytes / 1024 / 1024, 2); + $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']; - if ($bytes >= pow(2, 10)) + // Default to IEC + $unit_info['unit'] = $unit_info['iec_unit']; + + if (!$string_only) { - return ($add_size_lang) ? round($bytes / 1024, 2) . ' ' . $user->lang['KIB'] : round($bytes / 1024, 2); + $unit_info['value'] = $value; + + return $unit_info; } - return ($add_size_lang) ? ($bytes) . ' ' . $user->lang['BYTES'] : ($bytes); + return $value . ' ' . $unit_info['unit']; } /** @@ -496,6 +552,18 @@ function _hash_crypt_private($password, $setting, &$itoa64) } /** +* Hashes an email address to a big integer +* +* @param string $email Email address +* +* @return string Big Integer +*/ +function phpbb_email_hash($email) +{ + return crc32(strtolower($email)) . strlen($email); +} + +/** * Global function for chmodding directories and files for internal use * * This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions. @@ -669,6 +737,67 @@ function phpbb_chmod($filename, $perms = CHMOD_READ) return $result; } +/** +* Test if a file/directory is writable +* +* This function calls the native is_writable() when not running under +* Windows and it is not disabled. +* +* @param string $file Path to perform write test on +* @return bool True when the path is writable, otherwise false. +*/ +function phpbb_is_writable($file) +{ + if (strtolower(substr(PHP_OS, 0, 3)) === 'win' || !function_exists('is_writable')) + { + if (file_exists($file)) + { + // Canonicalise path to absolute path + $file = phpbb_realpath($file); + + if (is_dir($file)) + { + // Test directory by creating a file inside the directory + $result = @tempnam($file, 'i_w'); + + if (is_string($result) && file_exists($result)) + { + unlink($result); + + // Ensure the file is actually in the directory (returned realpathed) + return (strpos($result, $file) === 0) ? true : false; + } + } + else + { + $handle = @fopen($file, 'r+'); + + if (is_resource($handle)) + { + fclose($handle); + return true; + } + } + } + else + { + // file does not exist test if we can write to the directory + $dir = dirname($file); + + if (file_exists($dir) && is_dir($dir) && phpbb_is_writable($dir)) + { + return true; + } + } + + return false; + } + else + { + return is_writable($file); + } +} + // Compatibility functions if (!function_exists('array_combine')) @@ -1047,7 +1176,7 @@ function tz_select($default = '', $truncate = false) if (is_numeric($offset)) { $selected = ($offset == $default) ? ' selected="selected"' : ''; - $tz_select .= '<option title="'.$zone.'" value="' . $offset . '"' . $selected . '>' . $zone_trunc . '</option>'; + $tz_select .= '<option title="' . $zone . '" value="' . $offset . '"' . $selected . '>' . $zone_trunc . '</option>'; } } @@ -1110,7 +1239,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ } // Add 0 to forums array to mark global announcements correctly - $forum_id[] = 0; + // $forum_id[] = 0; if ($config['load_db_lastread'] && $user->data['is_registered']) { @@ -1528,6 +1657,135 @@ function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_lis } /** +* 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 +* +* @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) +{ + global $config, $db, $user; + + $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'; + } + + if ($config['load_db_lastread'] && $user->data['is_registered']) + { + // Get list of the unread topics + $last_mark = $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 AND tt.mark_time > $last_mark", + ), + array( + 'FROM' => array(FORUMS_TRACK_TABLE => 'ft'), + 'ON' => "ft.user_id = $user_id AND t.forum_id = ft.forum_id AND ft.mark_time > $last_mark", + ), + ), + + 'WHERE' => " + ( + (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) OR (tt.mark_time < $last_mark AND ft.mark_time < $last_mark)) + AND t.topic_last_post_time > $last_mark + ) + ) + $sql_extra + $sql_sort", + ); + + $sql = $db->sql_build_query('SELECT', $sql_array); + $result = $db->sql_query_limit($sql, $sql_limit); + + 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_var($config['cookie_name'] . '_track', '', false, true); + $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); + + 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 @@ -1777,7 +2035,7 @@ function generate_pagination($base_url, $num_items, $per_page, $start_item, $add } $on_page = floor($start_item / $per_page) + 1; - $url_delim = (strpos($base_url, '?') === false) ? '?' : '&'; + $url_delim = (strpos($base_url, '?') === false) ? '?' : ((strpos($base_url, '?') === strlen($base_url) - 1) ? '' : '&'); $page_string = ($on_page == 1) ? '<strong>1</strong>' : '<a href="' . $base_url . '">1</a>'; @@ -2056,7 +2314,7 @@ function redirect($url, $return = false, $disable_cd_check = false) $url = str_replace('&', '&', $url); // Determine which type of redirect we need to handle... - $url_parts = parse_url($url); + $url_parts = @parse_url($url); if ($url_parts === false) { @@ -2200,17 +2458,12 @@ function reapply_sid($url) } // Remove previously added sid - if (strpos($url, '?sid=') !== false) - { - $url = preg_replace('/(\?)sid=[a-z0-9]+(&|&)?/', '\1', $url); - } - else if (strpos($url, '&sid=') !== false) + if (strpos($url, 'sid=') !== false) { - $url = preg_replace('/&sid=[a-z0-9]+(&)?/', '\1', $url); - } - else if (strpos($url, '&sid=') !== false) - { - $url = preg_replace('/&sid=[a-z0-9]+(&)?/', '\1', $url); + // All kind of links + $url = preg_replace('/(\?)?(&|&)?sid=[a-z0-9]+/', '', $url); + // if the sid was the first param, make the old second as first ones + $url = preg_replace("/$phpEx(&|&)+?/", "$phpEx?", $url); } return append_sid($url); @@ -2274,6 +2527,18 @@ 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('&', '&', $redirect); + } + return $phpbb_root_path . str_replace('&', '&', $redirect); } @@ -2435,7 +2700,7 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo if ($check && $confirm) { - $user_id = request_var('user_id', 0); + $user_id = request_var('confirm_uid', 0); $session_id = request_var('sess', ''); $confirm_key = request_var('confirm_key', ''); @@ -2457,10 +2722,10 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo } $s_hidden_fields = build_hidden_fields(array( - 'user_id' => $user->data['user_id'], - 'sess' => $user->session_id, - 'sid' => $user->session_id) - ); + 'confirm_uid' => $user->data['user_id'], + 'sess' => $user->session_id, + 'sid' => $user->session_id, + )); // generate activation key $confirm_key = gen_rand_string(10); @@ -2471,7 +2736,7 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo } else { - page_header((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]); + page_header(((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]), false); } $template->set_filenames(array( @@ -2520,6 +2785,11 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa { global $db, $user, $template, $auth, $phpEx, $phpbb_root_path, $config; + if (!class_exists('phpbb_captcha_factory')) + { + include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); + } + $err = ''; // Make sure user->setup() has been called @@ -2630,38 +2900,15 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa { case LOGIN_ERROR_ATTEMPTS: - // Show confirm image - $sql = 'DELETE FROM ' . CONFIRM_TABLE . " - WHERE session_id = '" . $db->sql_escape($user->session_id) . "' - AND confirm_type = " . CONFIRM_LOGIN; - $db->sql_query($sql); - - // Generate code - $code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)); - $confirm_id = md5(unique_id($user->ip)); - $seed = hexdec(substr(unique_id(), 4, 10)); - - // compute $seed % 0x7fffffff - $seed -= 0x7fffffff * floor($seed / 0x7fffffff); - - $sql = 'INSERT INTO ' . CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array( - 'confirm_id' => (string) $confirm_id, - 'session_id' => (string) $user->session_id, - 'confirm_type' => (int) CONFIRM_LOGIN, - 'code' => (string) $code, - 'seed' => (int) $seed) - ); - $db->sql_query($sql); + $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $captcha->init(CONFIRM_LOGIN); + // $captcha->reset(); $template->assign_vars(array( - 'S_CONFIRM_CODE' => true, - 'CONFIRM_ID' => $confirm_id, - 'CONFIRM_IMAGE' => '<img src="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=confirm&id=' . $confirm_id . '&type=' . CONFIRM_LOGIN) . '" alt="" title="" />', - 'L_LOGIN_CONFIRM_EXPLAIN' => sprintf($user->lang['LOGIN_CONFIRM_EXPLAIN'], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'), + 'CAPTCHA_TEMPLATE' => $captcha->get_template(), )); $err = $user->lang[$result['error_msg']]; - break; case LOGIN_ERROR_PASSWORD_CONVERT: @@ -2688,28 +2935,18 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa } } - if (!$redirect) - { - // We just use what the session code determined... - // If we are not within the admin directory we use the page dir... - $redirect = ''; - - if (!$admin) - { - $redirect .= ($user->page['page_dir']) ? $user->page['page_dir'] . '/' : ''; - } - - $redirect .= $user->page['page_name'] . (($user->page['query_string']) ? '?' . htmlspecialchars($user->page['query_string']) : ''); - } - // Assign credential for username/password pair $credential = ($admin) ? md5(unique_id()) : false; $s_hidden_fields = array( - 'redirect' => $redirect, 'sid' => $user->session_id, ); + if ($redirect) + { + $s_hidden_fields['redirect'] = $redirect; + } + if ($admin) { $s_hidden_fields['credential'] = $credential; @@ -2722,12 +2959,11 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa 'LOGIN_EXPLAIN' => $l_explain, 'U_SEND_PASSWORD' => ($config['email_enable']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=sendpassword') : '', - 'U_RESEND_ACTIVATION' => ($config['require_activation'] != USER_ACTIVATION_NONE && $config['email_enable']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=resend_act') : '', + 'U_RESEND_ACTIVATION' => ($config['require_activation'] == USER_ACTIVATION_SELF && $config['email_enable']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=resend_act') : '', 'U_TERMS_USE' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=terms'), 'U_PRIVACY' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy'), 'S_DISPLAY_FULL_LOGIN' => ($s_display) ? true : false, - 'S_LOGIN_ACTION' => (!$admin) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login') : append_sid("index.$phpEx", false, true, $user->session_id), // Needs to stay index.$phpEx because we are within the admin directory 'S_HIDDEN_FIELDS' => $s_hidden_fields, 'S_ADMIN_AUTH' => $admin, @@ -2811,7 +3047,7 @@ function login_forum_box($forum_data) $template->assign_var('LOGIN_ERROR', $user->lang['WRONG_PASSWORD']); } - page_header($user->lang['LOGIN']); + page_header($user->lang['LOGIN'], false); $template->assign_vars(array( 'S_HIDDEN_FIELDS' => build_hidden_fields(array('f' => $forum_data['forum_id']))) @@ -2933,6 +3169,14 @@ 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; + } + $args = func_get_args(); $mode = array_shift($args); @@ -3200,7 +3444,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) global $phpEx, $phpbb_root_path, $msg_title, $msg_long_text; // Do not display notices if we suppress them via @ - if (error_reporting() == 0) + if (error_reporting() == 0 && $errno != E_USER_ERROR && $errno != E_USER_WARNING && $errno != E_USER_NOTICE) { return; } @@ -3211,6 +3455,11 @@ function msg_handler($errno, $msg_text, $errfile, $errline) $msg_text = $msg_long_text; } + if (!defined('E_DEPRECATED')) + { + define('E_DEPRECATED', 8192); + } + switch ($errno) { case E_NOTICE: @@ -3243,8 +3492,13 @@ function msg_handler($errno, $msg_text, $errfile, $errline) // remove complete path to installation, with the risk of changing backslashes meant to be there $errfile = str_replace(array(phpbb_realpath($phpbb_root_path), '\\'), array('', '/'), $errfile); $msg_text = str_replace(array(phpbb_realpath($phpbb_root_path), '\\'), array('', '/'), $msg_text); - echo '<b>[phpBB Debug] PHP Notice</b>: in file <b>' . $errfile . '</b> on line <b>' . $errline . '</b>: <b>' . $msg_text . '</b><br />' . "\n"; + + // we are writing an image - the user won't see the debug, so let's place it in the log + if (defined('IMAGE_OUTPUT') || defined('IN_CRON')) + { + add_log('critical', 'LOG_IMAGE_GENERATION_ERROR', $errfile, $errline, $msg_text); + } // echo '<br /><br />BACKTRACE<br />' . get_backtrace() . '<br />' . "\n"; } @@ -3279,6 +3533,17 @@ function msg_handler($errno, $msg_text, $errfile, $errline) } } + if (defined('DEBUG') || defined('IN_CRON') || defined('IMAGE_OUTPUT')) + { + // let's avoid loops + $db->sql_return_on_error(true); + add_log('critical', 'LOG_GENERAL_ERROR', $msg_title, $msg_text); + $db->sql_return_on_error(false); + } + + // Do not send 200 OK, but service unavailable on errors + header('HTTP/1.1 503 Service Unavailable'); + garbage_collection(); // Try to not call the adm page data... @@ -3357,7 +3622,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) } else { - page_header($msg_title); + page_header($msg_title, false); } } @@ -3386,6 +3651,11 @@ function msg_handler($errno, $msg_text, $errfile, $errline) exit_handler(); break; + + // PHP4 compatibility + case E_DEPRECATED: + return true; + break; } // If we notice an error not handled here we pass this back to PHP by returning false @@ -3395,16 +3665,17 @@ function msg_handler($errno, $msg_text, $errfile, $errline) /** * Queries the session table to get information about online guests -* @param int $forum_id Limits the search to the forum with this id +* @param int $item_id Limits the search to the item with this id +* @param string $item The name of the item which is stored in the session table as session_{$item}_id * @return int The number of active distinct guest sessions */ -function obtain_guest_count($forum_id = 0) +function obtain_guest_count($item_id = 0, $item = 'forum') { global $db, $config; - if ($forum_id) + if ($item_id) { - $reading_sql = ' AND s.session_forum_id = ' . (int) $forum_id; + $reading_sql = ' AND s.session_' . $item . '_id = ' . (int) $item_id; } else { @@ -3442,17 +3713,18 @@ function obtain_guest_count($forum_id = 0) /** * Queries the session table to get information about online users -* @param int $forum_id Limits the search to the forum with this id +* @param int $item_id Limits the search to the item with this id +* @param string $item The name of the item which is stored in the session table as session_{$item}_id * @return array An array containing the ids of online, hidden and visible users, as well as statistical info */ -function obtain_users_online($forum_id = 0) +function obtain_users_online($item_id = 0, $item = 'forum') { global $db, $config, $user; $reading_sql = ''; - if ($forum_id !== 0) + if ($item_id !== 0) { - $reading_sql = ' AND s.session_forum_id = ' . (int) $forum_id; + $reading_sql = ' AND s.session_' . $item . '_id = ' . (int) $item_id; } $online_users = array( @@ -3466,7 +3738,7 @@ function obtain_users_online($forum_id = 0) if ($config['load_online_guests']) { - $online_users['guests_online'] = obtain_guest_count($forum_id); + $online_users['guests_online'] = obtain_guest_count($item_id, $item); } // a little discrete magic to cache this for 30 seconds @@ -3505,14 +3777,17 @@ function obtain_users_online($forum_id = 0) /** * Uses the result of obtain_users_online to generate a localized, readable representation. * @param mixed $online_users result of obtain_users_online - array with user_id lists for total, hidden and visible users, and statistics -* @param int $forum_id Indicate that the data is limited to one forum and not global. +* @param int $item_id Indicate that the data is limited to one item and not global +* @param string $item The name of the item which is stored in the session table as session_{$item}_id * @return array An array containing the string for output to the template */ -function obtain_users_online_string($online_users, $forum_id = 0) +function obtain_users_online_string($online_users, $item_id = 0, $item = 'forum') { global $config, $db, $user, $auth; $user_online_link = $online_userlist = ''; + // Need caps version of $item for language-strings + $item_caps = strtoupper($item); if (sizeof($online_users['online_users'])) { @@ -3547,18 +3822,18 @@ function obtain_users_online_string($online_users, $forum_id = 0) $online_userlist = $user->lang['NO_ONLINE_USERS']; } - if ($forum_id === 0) + if ($item_id === 0) { $online_userlist = $user->lang['REGISTERED_USERS'] . ' ' . $online_userlist; } else if ($config['load_online_guests']) { - $l_online = ($online_users['guests_online'] === 1) ? $user->lang['BROWSING_FORUM_GUEST'] : $user->lang['BROWSING_FORUM_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']); } else { - $online_userlist = sprintf($user->lang['BROWSING_FORUM'], $online_userlist); + $online_userlist = sprintf($user->lang['BROWSING_' . $item_caps], $online_userlist); } // Build online listing $vars_online = array( @@ -3612,11 +3887,45 @@ function obtain_users_online_string($online_users, $forum_id = 0) ); } +/** +* Get option bitfield from custom data +* +* @param int $bit The bit/value to get +* @param int $data Current bitfield to check +* @return bool Returns true if value of constant is set in bitfield, else false +*/ +function phpbb_optionget($bit, $data) +{ + return ($data & 1 << (int) $bit) ? true : false; +} + +/** +* Set option bitfield +* +* @param int $bit The bit/value to set/unset +* @param bool $set True if option should be set, false if option should be unset. +* @param int $data Current bitfield to change +* +* @return int The new bitfield +*/ +function phpbb_optionset($bit, $set, $data) +{ + if ($set && !($data & 1 << $bit)) + { + $data += 1 << $bit; + } + else if (!$set && ($data & 1 << $bit)) + { + $data -= 1 << $bit; + } + + return $data; +} /** * Generate page header */ -function page_header($page_title = '', $display_online_list = true) +function page_header($page_title = '', $display_online_list = true, $item_id = 0, $item = 'forum') { global $db, $config, $template, $SID, $_SID, $user, $auth, $phpEx, $phpbb_root_path; @@ -3656,10 +3965,14 @@ function page_header($page_title = '', $display_online_list = true) if ($config['load_online'] && $config['load_online_time'] && $display_online_list) { - $f = request_var('f', 0); - $f = max($f, 0); - $online_users = obtain_users_online($f); - $user_online_strings = obtain_users_online_string($online_users, $f); + /** + * Load online data: + * For obtaining another session column use $item and $item_id in the function-parameter, whereby the column is session_{$item}_id. + */ + $item_id = max($item_id, 0); + + $online_users = obtain_users_online($item_id, $item); + $user_online_strings = obtain_users_online_string($online_users, $item_id, $item); $l_online_users = $user_online_strings['l_online_users']; $online_userlist = $user_online_strings['online_userlist']; @@ -3731,6 +4044,26 @@ function page_header($page_title = '', $display_online_list = true) $user_lang = substr($user_lang, 0, strpos($user_lang, '-x-')); } + $forum_id = request_var('f', 0); + $topic_id = request_var('t', 0); + + $s_feed_news = false; + + // Get option for news + if ($config['feed_enable']) + { + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0'); + $result = $db->sql_query_limit($sql, 1, 0, 600); + $s_feed_news = (int) $db->sql_fetchfield('forum_id'); + $db->sql_freeresult($result); + } + + // 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; + // The following assigns all _common_ variables that may be used at any point in a template. $template->assign_vars(array( 'SITENAME' => $config['sitename'], @@ -3748,11 +4081,13 @@ function page_header($page_title = '', $display_online_list = true) 'S_USER_NEW_PRIVMSG' => $user->data['user_new_privmsg'], 'S_USER_UNREAD_PRIVMSG' => $user->data['user_unread_privmsg'], + 'S_USER_NEW' => $user->data['user_new'], 'SID' => $SID, '_SID' => $_SID, 'SESSION_ID' => $user->session_id, 'ROOT_PATH' => $phpbb_root_path, + 'BOARD_URL' => $board_url, 'L_LOGIN_LOGOUT' => $l_login_logout, 'L_INDEX' => $user->lang['FORUM_INDEX'], @@ -3774,10 +4109,14 @@ function page_header($page_title = '', $display_online_list = true) 'U_SEARCH_SELF' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=egosearch'), 'U_SEARCH_NEW' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=newposts'), 'U_SEARCH_UNANSWERED' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unanswered'), + 'U_SEARCH_UNREAD' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unreadposts'), 'U_SEARCH_ACTIVE_TOPICS'=> append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=active_topics'), 'U_DELETE_COOKIES' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=delete_cookies'), 'U_TEAM' => ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile')) ? '' : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=leaders'), + 'U_TERMS_USE' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=terms'), + 'U_PRIVACY' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy'), 'U_RESTORE_PERMISSIONS' => ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=restore_perm') : '', + 'U_FEED' => generate_board_url() . "/feed.$phpEx", 'S_USER_LOGGED_IN' => ($user->data['user_id'] != ANONYMOUS) ? true : false, 'S_AUTOLOGIN_ENABLED' => ($config['allow_autologin']) ? true : false, @@ -3799,22 +4138,44 @@ function page_header($page_title = '', $display_online_list = true) 'S_DISPLAY_MEMBERLIST' => (isset($auth)) ? $auth->acl_get('u_viewprofile') : 0, 'S_NEW_PM' => ($s_privmsg_new) ? 1 : 0, 'S_REGISTER_ENABLED' => ($config['require_activation'] != USER_ACTIVATION_DISABLE) ? true : false, - - 'T_THEME_PATH' => "{$phpbb_root_path}styles/" . $user->theme['theme_path'] . '/theme', - 'T_TEMPLATE_PATH' => "{$phpbb_root_path}styles/" . $user->theme['template_path'] . '/template', - 'T_SUPER_TEMPLATE_PATH' => (isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? "{$phpbb_root_path}styles/" . $user->theme['template_inherit_path'] . '/template' : "{$phpbb_root_path}styles/" . $user->theme['template_path'] . '/template', - 'T_IMAGESET_PATH' => "{$phpbb_root_path}styles/" . $user->theme['imageset_path'] . '/imageset', - 'T_IMAGESET_LANG_PATH' => "{$phpbb_root_path}styles/" . $user->theme['imageset_path'] . '/imageset/' . $user->data['user_lang'], - 'T_IMAGES_PATH' => "{$phpbb_root_path}images/", - 'T_SMILIES_PATH' => "{$phpbb_root_path}{$config['smilies_path']}/", - 'T_AVATAR_PATH' => "{$phpbb_root_path}{$config['avatar_path']}/", - 'T_AVATAR_GALLERY_PATH' => "{$phpbb_root_path}{$config['avatar_gallery_path']}/", - 'T_ICONS_PATH' => "{$phpbb_root_path}{$config['icons_path']}/", - 'T_RANKS_PATH' => "{$phpbb_root_path}{$config['ranks_path']}/", - 'T_UPLOAD_PATH' => "{$phpbb_root_path}{$config['upload_path']}/", - 'T_STYLESHEET_LINK' => (!$user->theme['theme_storedb']) ? "{$phpbb_root_path}styles/" . $user->theme['theme_path'] . '/theme/stylesheet.css' : "{$phpbb_root_path}style.$phpEx?sid=$user->session_id&id=" . $user->theme['style_id'] . '&lang=' . $user->data['user_lang'], + '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') . '&redirect=' . urlencode(str_replace('&', '&', build_url())) : append_sid("index.$phpEx", false, true, $user->session_id) . '&redirect=' . urlencode(str_replace('&', '&', build_url())), + + 'S_ENABLE_FEEDS' => ($config['feed_enable']) ? true : false, + 'S_ENABLE_FEEDS_FORUMS' => ($config['feed_overall_forums']) ? true : false, + 'S_ENABLE_FEEDS_TOPICS' => ($config['feed_overall_topics']) ? true : false, + 'S_ENABLE_FEEDS_NEWS' => ($s_feed_news) ? true : false, + + 'T_THEME_PATH' => "{$web_path}styles/" . $user->theme['theme_path'] . '/theme', + 'T_TEMPLATE_PATH' => "{$web_path}styles/" . $user->theme['template_path'] . '/template', + 'T_SUPER_TEMPLATE_PATH' => (isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? "{$web_path}styles/" . $user->theme['template_inherit_path'] . '/template' : "{$web_path}styles/" . $user->theme['template_path'] . '/template', + 'T_IMAGESET_PATH' => "{$web_path}styles/" . $user->theme['imageset_path'] . '/imageset', + 'T_IMAGESET_LANG_PATH' => "{$web_path}styles/" . $user->theme['imageset_path'] . '/imageset/' . $user->data['user_lang'], + 'T_IMAGES_PATH' => "{$web_path}images/", + 'T_SMILIES_PATH' => "{$web_path}{$config['smilies_path']}/", + 'T_AVATAR_PATH' => "{$web_path}{$config['avatar_path']}/", + 'T_AVATAR_GALLERY_PATH' => "{$web_path}{$config['avatar_gallery_path']}/", + '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/" . $user->theme['theme_path'] . '/theme/stylesheet.css' : append_sid("{$phpbb_root_path}style.$phpEx", 'id=' . $user->theme['style_id'] . '&lang=' . $user->data['user_lang']), 'T_STYLESHEET_NAME' => $user->theme['theme_name'], + 'T_THEME_NAME' => $user->theme['theme_path'], + 'T_TEMPLATE_NAME' => $user->theme['template_path'], + 'T_SUPER_TEMPLATE_NAME' => (isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? $user->theme['template_inherit_path'] : $user->theme['template_path'], + 'T_IMAGESET_NAME' => $user->theme['imageset_path'], + 'T_IMAGESET_LANG_NAME' => $user->data['user_lang'], + 'T_IMAGES' => 'images', + 'T_SMILIES' => $config['smilies_path'], + 'T_AVATAR' => $config['avatar_path'], + 'T_AVATAR_GALLERY' => $config['avatar_gallery_path'], + 'T_ICONS' => $config['icons_path'], + 'T_RANKS' => $config['ranks_path'], + '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')), @@ -3848,7 +4209,7 @@ function page_footer($run_cron = true) $db->sql_report('display'); } - $debug_output = sprintf('Time : %.3fs | ' . $db->sql_num_queries() . ' Queries | GZIP : ' . (($config['gzip_compress']) ? 'On' : 'Off') . (($user->load) ? ' | Load : ' . $user->load : ''), $totaltime); + $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')) { @@ -3876,35 +4237,55 @@ function page_footer($run_cron = true) ); // Call cron-type script + $call_cron = false; if (!defined('IN_CRON') && $run_cron && !$config['board_disable']) { + $call_cron = true; + $time_now = (!empty($user->time_now) && is_int($user->time_now)) ? $user->time_now : time(); + + // Any old lock present? + if (!empty($config['cron_lock'])) + { + $cron_time = explode(' ', $config['cron_lock']); + + // If 1 hour lock is present we do not call cron.php + if ($cron_time[0] + 3600 >= $time_now) + { + $call_cron = false; + } + } + } + + // Call cron job? + if ($call_cron) + { $cron_type = ''; - if (time() - $config['queue_interval'] > $config['last_queue_run'] && !defined('IN_ADMIN') && file_exists($phpbb_root_path . 'cache/queue.' . $phpEx)) + 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() - $config['cache_gc'] > $config['cache_last_gc']) + else if (method_exists($cache, 'tidy') && $time_now - $config['cache_gc'] > $config['cache_last_gc']) { // Tidy the cache $cron_type = 'tidy_cache'; } - else if (time() - $config['warnings_gc'] > $config['warnings_last_gc']) + else if ($config['warnings_expire_days'] && ($time_now - $config['warnings_gc'] > $config['warnings_last_gc'])) { $cron_type = 'tidy_warnings'; } - else if (time() - $config['database_gc'] > $config['database_last_gc']) + else if ($time_now - $config['database_gc'] > $config['database_last_gc']) { // Tidy the database $cron_type = 'tidy_database'; } - else if (time() - $config['search_gc'] > $config['search_last_gc']) + else if ($time_now - $config['search_gc'] > $config['search_last_gc']) { // Tidy the search $cron_type = 'tidy_search'; } - else if (time() - $config['session_gc'] > $config['session_last_gc']) + else if ($time_now - $config['session_gc'] > $config['session_last_gc']) { $cron_type = 'tidy_sessions'; } |
