's) fid: One or more forum IDs (comma-separated). If ignored, topics from all readable forums will be pulled. nfid: One or more forum IDs (comma-separated) that are to be excluded. E.g. the ID of a a test forum. tid: A topic ID from which to show posts. If a tid is supplied, fid and nfid are ignored. show: Any integer value between 1 and 50. The default is 15. order: last_post - show topics ordered by when they were last posted in, giving information about the reply. posted - show topics ordered by when they were first posted, giving information about the original post. -----------------------------------------------------------------------------*/ define('PUN_QUIET_VISIT', 1); if (!defined('PUN_ROOT')) define('PUN_ROOT', dirname(__FILE__).'/'); require PUN_ROOT.'include/common.php'; // The length at which topic subjects will be truncated (for HTML output) if (!defined('FORUM_EXTERN_MAX_SUBJECT_LENGTH')) define('FORUM_EXTERN_MAX_SUBJECT_LENGTH', 30); // If we're a guest and we've sent a username/pass, we can try to authenticate using those details if ($pun_user['is_guest'] && isset($_SERVER['PHP_AUTH_USER'])) authenticate_user($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']); if ($pun_user['g_read_board'] == '0') { http_authenticate_user(); exit($lang_common['No view']); } $action = isset($_GET['action']) ? strtolower($_GET['action']) : 'feed'; // Handle a couple old formats, from FluxBB 1.2 switch ($action) { case 'active': $action = 'feed'; $_GET['order'] = 'last_post'; break; case 'new': $action = 'feed'; $_GET['order'] = 'posted'; break; } // // Sends the proper headers for Basic HTTP Authentication // function http_authenticate_user() { global $pun_config, $pun_user; if (!$pun_user['is_guest']) return; header('WWW-Authenticate: Basic realm="'.$pun_config['o_board_title'].' External Syndication"'); header('HTTP/1.0 401 Unauthorized'); } // // Output $feed as RSS 2.0 // function output_rss($feed) { global $lang_common, $pun_config; // Send XML/no cache headers header('Content-Type: application/xml; charset=utf-8'); header('Expires: '.gmdate('D, d M Y H:i:s').' GMT'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); echo ''."\n"; echo ''."\n"; echo "\t".''."\n"; echo "\t\t".''."\n"; echo "\t\t".'<![CDATA['.escape_cdata($feed['title']).']]>'."\n"; echo "\t\t".''.pun_htmlspecialchars($feed['link']).''."\n"; echo "\t\t".''."\n"; echo "\t\t".''.gmdate('r', count($feed['items']) ? $feed['items'][0]['pubdate'] : time()).''."\n"; if ($pun_config['o_show_version'] == '1') echo "\t\t".'FluxBB '.$pun_config['o_cur_version'].''."\n"; else echo "\t\t".'FluxBB'."\n"; foreach ($feed['items'] as $item) { echo "\t\t".''."\n"; echo "\t\t\t".'<![CDATA['.escape_cdata($item['title']).']]>'."\n"; echo "\t\t\t".''.pun_htmlspecialchars($item['link']).''."\n"; echo "\t\t\t".''."\n"; echo "\t\t\t".''."\n"; echo "\t\t\t".''.gmdate('r', $item['pubdate']).''."\n"; echo "\t\t\t".''.pun_htmlspecialchars($item['link']).''."\n"; echo "\t\t".''."\n"; } echo "\t".''."\n"; echo ''."\n"; } // // Output $feed as Atom 1.0 // function output_atom($feed) { global $lang_common, $pun_config; // Send XML/no cache headers header('Content-Type: application/atom+xml; charset=utf-8'); header('Expires: '.gmdate('D, d M Y H:i:s').' GMT'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); echo ''."\n"; echo ''."\n"; echo "\t".'<![CDATA['.escape_cdata($feed['title']).']]>'."\n"; echo "\t".''."\n"; echo "\t".''."\n"; echo "\t".''.gmdate('Y-m-d\TH:i:s\Z', count($feed['items']) ? $feed['items'][0]['pubdate'] : time()).''."\n"; if ($pun_config['o_show_version'] == '1') echo "\t".'FluxBB'."\n"; else echo "\t".'FluxBB'."\n"; echo "\t".''.pun_htmlspecialchars($feed['link']).''."\n"; $content_tag = ($feed['type'] == 'posts') ? 'content' : 'summary'; foreach ($feed['items'] as $item) { echo "\t".''."\n"; echo "\t\t".'<![CDATA['.escape_cdata($item['title']).']]>'."\n"; echo "\t\t".''."\n"; echo "\t\t".'<'.$content_tag.' type="html">'."\n"; echo "\t\t".''."\n"; echo "\t\t\t".''."\n"; if (isset($item['author']['email'])) echo "\t\t\t".''."\n"; if (isset($item['author']['uri'])) echo "\t\t\t".''.pun_htmlspecialchars($item['author']['uri']).''."\n"; echo "\t\t".''."\n"; echo "\t\t".''.gmdate('Y-m-d\TH:i:s\Z', $item['pubdate']).''."\n"; echo "\t\t".''.pun_htmlspecialchars($item['link']).''."\n"; echo "\t".''."\n"; } echo ''."\n"; } // // Output $feed as XML // function output_xml($feed) { global $lang_common, $pun_config; // Send XML/no cache headers header('Content-Type: application/xml; charset=utf-8'); header('Expires: '.gmdate('D, d M Y H:i:s').' GMT'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); echo ''."\n"; echo ''."\n"; echo "\t".''.pun_htmlspecialchars($feed['link']).''."\n"; $forum_tag = ($feed['type'] == 'posts') ? 'post' : 'topic'; foreach ($feed['items'] as $item) { echo "\t".'<'.$forum_tag.' id="'.$item['id'].'">'."\n"; echo "\t\t".'<![CDATA['.escape_cdata($item['title']).']]>'."\n"; echo "\t\t".''.pun_htmlspecialchars($item['link']).''."\n"; echo "\t\t".''."\n"; echo "\t\t".''."\n"; echo "\t\t\t".''."\n"; if (isset($item['author']['email'])) echo "\t\t\t".''."\n"; if (isset($item['author']['uri'])) echo "\t\t\t".''.pun_htmlspecialchars($item['author']['uri']).''."\n"; echo "\t\t".''."\n"; echo "\t\t".''.gmdate('r', $item['pubdate']).''."\n"; echo "\t".''."\n"; } echo ''."\n"; } // // Output $feed as HTML (using
  • tags) // function output_html($feed) { // Send the Content-type header in case the web server is setup to send something else header('Content-type: text/html; charset=utf-8'); header('Expires: '.gmdate('D, d M Y H:i:s').' GMT'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); foreach ($feed['items'] as $item) { if (utf8_strlen($item['title']) > FORUM_EXTERN_MAX_SUBJECT_LENGTH) $subject_truncated = pun_htmlspecialchars(pun_trim(utf8_substr($item['title'], 0, (FORUM_EXTERN_MAX_SUBJECT_LENGTH - 5)))).' …'; else $subject_truncated = pun_htmlspecialchars($item['title']); echo '
  • '.$subject_truncated.'
  • '."\n"; } } // Show recent discussions if ($action == 'feed') { require PUN_ROOT.'include/parser.php'; // Determine what type of feed to output $type = isset($_GET['type']) ? strtolower($_GET['type']) : 'html'; if (!in_array($type, array('html', 'rss', 'atom', 'xml'))) $type = 'html'; $show = isset($_GET['show']) ? intval($_GET['show']) : 15; if ($show < 1 || $show > 50) $show = 15; // Was a topic ID supplied? if (isset($_GET['tid'])) { $tid = intval($_GET['tid']); // Fetch topic subject $result = $db->query('SELECT t.subject, t.first_post_id FROM '.$db->prefix.'topics AS t LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=t.forum_id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.moved_to IS NULL AND t.id='.$tid) or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error()); if (!$db->num_rows($result)) { http_authenticate_user(); exit($lang_common['Bad request']); } $cur_topic = $db->fetch_assoc($result); if ($pun_config['o_censoring'] == '1') $cur_topic['subject'] = censor_words($cur_topic['subject']); // Setup the feed $feed = array( 'title' => $pun_config['o_board_title'].$lang_common['Title separator'].$cur_topic['subject'], 'link' => get_base_url(true).'/viewtopic.php?id='.$tid, 'description' => sprintf($lang_common['RSS description topic'], $cur_topic['subject']), 'items' => array(), 'type' => 'posts' ); // Fetch $show posts $result = $db->query('SELECT p.id, p.poster, p.message, p.hide_smilies, p.posted, p.poster_id, u.email_setting, u.email, p.poster_email FROM '.$db->prefix.'posts AS p INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id WHERE p.topic_id='.$tid.' ORDER BY p.posted DESC LIMIT '.$show) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error()); while ($cur_post = $db->fetch_assoc($result)) { $cur_post['message'] = parse_message($cur_post['message'], $cur_post['hide_smilies']); $item = array( 'id' => $cur_post['id'], 'title' => $cur_topic['first_post_id'] == $cur_post['id'] ? $cur_topic['subject'] : $lang_common['RSS reply'].$cur_topic['subject'], 'link' => get_base_url(true).'/viewtopic.php?pid='.$cur_post['id'].'#p'.$cur_post['id'], 'description' => $cur_post['message'], 'author' => array( 'name' => $cur_post['poster'], ), 'pubdate' => $cur_post['posted'] ); if ($cur_post['poster_id'] > 1) { if ($cur_post['email_setting'] == '0' && !$pun_user['is_guest']) $item['author']['email'] = $cur_post['email']; $item['author']['uri'] = get_base_url(true).'/profile.php?id='.$cur_post['poster_id']; } else if ($cur_post['poster_email'] != '' && !$pun_user['is_guest']) $item['author']['email'] = $cur_post['poster_email']; $feed['items'][] = $item; } $output_func = 'output_'.$type; $output_func($feed); } else { $order_posted = isset($_GET['order']) && strtolower($_GET['order']) == 'posted'; $forum_name = ''; $forum_sql = ''; // Were any forum IDs supplied? if (isset($_GET['fid']) && is_scalar($_GET['fid']) && $_GET['fid'] != '') { $fids = explode(',', pun_trim($_GET['fid'])); $fids = array_map('intval', $fids); if (!empty($fids)) $forum_sql .= ' AND t.forum_id IN('.implode(',', $fids).')'; if (count($fids) == 1) { // Fetch forum name $result = $db->query('SELECT f.forum_name FROM '.$db->prefix.'forums AS f LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND f.id='.$fids[0]) or error('Unable to fetch forum name', __FILE__, __LINE__, $db->error()); if ($db->num_rows($result)) $forum_name = $lang_common['Title separator'].$db->result($result); } } // Any forum IDs to exclude? if (isset($_GET['nfid']) && is_scalar($_GET['nfid']) && $_GET['nfid'] != '') { $nfids = explode(',', pun_trim($_GET['nfid'])); $nfids = array_map('intval', $nfids); if (!empty($nfids)) $forum_sql .= ' AND t.forum_id NOT IN('.implode(',', $nfids).')'; } // Only attempt to cache if caching is enabled and we have all or a single forum if ($pun_config['o_feed_ttl'] > 0 && ($forum_sql == '' || ($forum_name != '' && !isset($_GET['nfid'])))) $cache_id = 'feed'.sha1($pun_user['g_id'].'|'.$lang_common['lang_identifier'].'|'.($order_posted ? '1' : '0').($forum_name == '' ? '' : '|'.$fids[0])); // Load cached feed if (isset($cache_id) && file_exists(FORUM_CACHE_DIR.'cache_'.$cache_id.'.php')) include FORUM_CACHE_DIR.'cache_'.$cache_id.'.php'; $now = time(); if (!isset($feed) || $cache_expire < $now) { // Setup the feed $feed = array( 'title' => $pun_config['o_board_title'].$forum_name, 'link' => '/index.php', 'description' => sprintf($lang_common['RSS description'], $pun_config['o_board_title']), 'items' => array(), 'type' => 'topics' ); // Fetch $show topics $result = $db->query('SELECT t.id, t.poster, t.subject, t.posted, t.last_post, t.last_poster, p.message, p.hide_smilies, u.email_setting, u.email, p.poster_id, p.poster_email FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'posts AS p ON p.id='.($order_posted ? 't.first_post_id' : 't.last_post_id').' INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=t.forum_id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.moved_to IS NULL'.$forum_sql.' ORDER BY '.($order_posted ? 't.posted' : 't.last_post').' DESC LIMIT '.(isset($cache_id) ? 50 : $show)) or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error()); while ($cur_topic = $db->fetch_assoc($result)) { if ($pun_config['o_censoring'] == '1') $cur_topic['subject'] = censor_words($cur_topic['subject']); $cur_topic['message'] = parse_message($cur_topic['message'], $cur_topic['hide_smilies']); $item = array( 'id' => $cur_topic['id'], 'title' => $cur_topic['subject'], 'link' => '/viewtopic.php?id='.$cur_topic['id'].($order_posted ? '' : '&action=new'), 'description' => $cur_topic['message'], 'author' => array( 'name' => $order_posted ? $cur_topic['poster'] : $cur_topic['last_poster'] ), 'pubdate' => $order_posted ? $cur_topic['posted'] : $cur_topic['last_post'] ); if ($cur_topic['poster_id'] > 1) { if ($cur_topic['email_setting'] == '0' && !$pun_user['is_guest']) $item['author']['email'] = $cur_topic['email']; $item['author']['uri'] = '/profile.php?id='.$cur_topic['poster_id']; } else if ($cur_topic['poster_email'] != '' && !$pun_user['is_guest']) $item['author']['email'] = $cur_topic['poster_email']; $feed['items'][] = $item; } // Output feed as PHP code if (isset($cache_id)) { if (!defined('FORUM_CACHE_FUNCTIONS_LOADED')) require PUN_ROOT.'include/cache.php'; $content = ''; fluxbb_write_cache_file('cache_'.$cache_id.'.php', $content); } } // If we only want to show a few items but due to caching we have too many if (count($feed['items']) > $show) $feed['items'] = array_slice($feed['items'], 0, $show); // Prepend the current base URL onto some links. Done after caching to handle http/https correctly $feed['link'] = get_base_url(true).$feed['link']; foreach ($feed['items'] as $key => $item) { $feed['items'][$key]['link'] = get_base_url(true).$item['link']; if (isset($item['author']['uri'])) $feed['items'][$key]['author']['uri'] = get_base_url(true).$item['author']['uri']; } $output_func = 'output_'.$type; $output_func($feed); } exit; } // Show users online else if ($action == 'online' || $action == 'online_full') { // Load the index.php language file require PUN_ROOT.'lang/'.$pun_config['o_default_lang'].'/index.php'; // Fetch users online info and generate strings for output $num_guests = $num_users = 0; $users = array(); $result = $db->query('SELECT user_id, ident FROM '.$db->prefix.'online WHERE idle=0 ORDER BY ident', true) or error('Unable to fetch online list', __FILE__, __LINE__, $db->error()); while ($pun_user_online = $db->fetch_assoc($result)) { if ($pun_user_online['user_id'] > 1) { $users[] = ($pun_user['g_view_users'] == '1') ? ''.pun_htmlspecialchars($pun_user_online['ident']).'' : pun_htmlspecialchars($pun_user_online['ident']); ++$num_users; } else ++$num_guests; } // Send the Content-type header in case the web server is setup to send something else header('Content-type: text/html; charset=utf-8'); header('Expires: '.gmdate('D, d M Y H:i:s').' GMT'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); echo sprintf($lang_index['Guests online'], forum_number_format($num_guests)).'
    '."\n"; if ($action == 'online_full' && !empty($users)) echo sprintf($lang_index['Users online'], implode(', ', $users)).'
    '."\n"; else echo sprintf($lang_index['Users online'], forum_number_format($num_users)).'
    '."\n"; exit; } // Show board statistics else if ($action == 'stats') { // Load the index.php language file require PUN_ROOT.'lang/'.$pun_config['o_default_lang'].'/index.php'; // Collect some statistics from the database if (file_exists(FORUM_CACHE_DIR.'cache_users_info.php')) include FORUM_CACHE_DIR.'cache_users_info.php'; if (!defined('PUN_USERS_INFO_LOADED')) { if (!defined('FORUM_CACHE_FUNCTIONS_LOADED')) require PUN_ROOT.'include/cache.php'; generate_users_info_cache(); require FORUM_CACHE_DIR.'cache_users_info.php'; } $result = $db->query('SELECT SUM(num_topics), SUM(num_posts) FROM '.$db->prefix.'forums') or error('Unable to fetch topic/post count', __FILE__, __LINE__, $db->error()); list($stats['total_topics'], $stats['total_posts']) = $db->fetch_row($result); // Send the Content-type header in case the web server is setup to send something else header('Content-type: text/html; charset=utf-8'); header('Expires: '.gmdate('D, d M Y H:i:s').' GMT'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); echo sprintf($lang_index['No of users'], forum_number_format($stats['total_users'])).'
    '."\n"; echo sprintf($lang_index['Newest user'], (($pun_user['g_view_users'] == '1') ? ''.pun_htmlspecialchars($stats['last_user']['username']).'' : pun_htmlspecialchars($stats['last_user']['username']))).'
    '."\n"; echo sprintf($lang_index['No of topics'], forum_number_format($stats['total_topics'])).'
    '."\n"; echo sprintf($lang_index['No of posts'], forum_number_format($stats['total_posts'])).'
    '."\n"; exit; } // If we end up here, the script was called with some wacky parameters exit($lang_common['Bad request']);