rock->ignorelists->findOne(array('user' => (int) $ID_MEMBER), array ("ignores" => 1)); $ignores == NULL ? $context['ignore_list'] = array() : $context['ignore_list'] = $ignores['ignores']; // Find the previous or next topic. Make a fuss if there are no more. if (isset($_REQUEST['prev_next']) && ($_REQUEST['prev_next'] == 'prev' || $_REQUEST['prev_next'] == 'next')) { // Just prepare some variables that are used in the query. $gt_lt = $_REQUEST['prev_next'] == 'prev' ? '>' : '<'; $order = $_REQUEST['prev_next'] == 'prev' ? '' : ' DESC'; $request = db_query(" SELECT t2.ID_TOPIC FROM {$db_prefix}topics AS t, {$db_prefix}topics AS t2, {$db_prefix}messages AS m, {$db_prefix}messages AS m2 WHERE m.ID_MSG = t.ID_LAST_MSG AND t.ID_TOPIC = $topic" . (empty($modSettings['enableStickyTopics']) ? " AND m2.posterTime $gt_lt m.posterTime" : " AND ((m2.posterTime $gt_lt m.posterTime AND t2.isSticky $gt_lt= t.isSticky) OR t2.isSticky $gt_lt t.isSticky)") . " AND t2.ID_LAST_MSG = m2.ID_MSG AND t2.ID_BOARD = $board ORDER BY" . (empty($modSettings['enableStickyTopics']) ? '' : " t2.isSticky$order,") . " m2.posterTime$order LIMIT 1", __FILE__, __LINE__); // No more left. if (mysql_num_rows($request) == 0) fatal_lang_error('previous_next_end', false); // Now you can be sure $topic is the ID_TOPIC to view. list ($topic) = mysql_fetch_row($request); mysql_free_result($request); $context['current_topic'] = $topic; // Go to the newest message on this topic. $_REQUEST['start'] = 'new'; } $request=db_query(" SELECT t.ID_TOPIC AS id, msg.subject AS subj FROM {$db_prefix}related_topics rt INNER JOIN {$db_prefix}topics t ON (t.ID_TOPIC=rt.ID_slave) INNER JOIN {$db_prefix}messages msg ON (msg.ID_MSG=t.ID_FIRST_MSG) WHERE rt.ID_master={$context['current_topic']}", __FILE__, __LINE__); if(mysql_num_rows($request)==0) $context['related_topics']=array(); else while($context['related_topics'][]=mysql_fetch_assoc($request)); // Add 1 to the number of views of this topic. if (empty($_SESSION['last_read_topic']) || $_SESSION['last_read_topic'] != $topic) { db_query(" UPDATE {$db_prefix}topics SET numViews = numViews + 1 WHERE ID_TOPIC = $topic LIMIT 1", __FILE__, __LINE__); $_SESSION['last_read_topic'] = $topic; } // Get all the important topic info. $request = db_query(" SELECT t.numReplies, t.numViews, t.locked, ms.subject, t.isSticky, t.isFirstSticky, t.ID_POLL, t.ID_MEMBER_STARTED, IFNULL(lt.logTime, 0) AS logTime, t.ID_FIRST_MSG, t.subtitle AS subtitle FROM ({$db_prefix}topics AS t, {$db_prefix}messages AS ms) LEFT JOIN {$db_prefix}log_topics AS lt ON (lt.ID_TOPIC = $topic AND lt.ID_MEMBER = $ID_MEMBER) WHERE t.ID_TOPIC = $topic AND ms.ID_MSG = t.ID_FIRST_MSG LIMIT 1", __FILE__, __LINE__); if (mysql_num_rows($request) == 0) fatal_lang_error(472, false); $topicinfo = mysql_fetch_assoc($request); mysql_free_result($request); // The start isn't a number; it's information about what to do, where to go. if (!is_numeric($_REQUEST['start'])) { // Redirect to the page and post with new messagesm, originally by Omar Bazavilvazo. if ($_REQUEST['start'] == 'new') { // Guests automatically go to the last topic. if ($user_info['is_guest']) $logTime = time(); else { // Find the earliest unread message in the topic. (the use of topics here is just for both tables.) $request = db_query(" SELECT IFNULL(lt.logTime, IFNULL(lmr.logTime, 0)) AS logTime FROM {$db_prefix}topics AS t LEFT JOIN {$db_prefix}log_topics AS lt ON (lt.ID_TOPIC = $topic AND lt.ID_MEMBER = $ID_MEMBER) LEFT JOIN {$db_prefix}log_mark_read AS lmr ON (lmr.ID_BOARD = $board AND lmr.ID_MEMBER = $ID_MEMBER) WHERE t.ID_TOPIC = $topic LIMIT 1", __FILE__, __LINE__); list ($logTime) = mysql_fetch_row($request); mysql_free_result($request); } // Fall through to the next if statement. $_REQUEST['start'] = 'from' . $logTime; } // Start from a certain time index, not a message. if (substr($_REQUEST['start'], 0, 4) == 'from') { // Find the number of messages posted before said time... $request = db_query(" SELECT COUNT(ID_MSG) FROM {$db_prefix}messages WHERE posterTime < " . (int) substr($_REQUEST['start'], 4) . " AND ID_TOPIC = $topic", __FILE__, __LINE__); list ($context['start_from']) = mysql_fetch_row($request); mysql_free_result($request); // Handle view_newest_first options, and get the correct start value. $_REQUEST['start'] = empty($options['view_newest_first']) ? $context['start_from'] : $topicinfo['numReplies'] - $context['start_from']; } // Link to a message... elseif (substr($_REQUEST['start'], 0, 3) == 'msg') { // Find the start value for that message...... $request = db_query(" SELECT COUNT(ID_MSG) FROM {$db_prefix}messages WHERE ID_MSG < " . (int) substr($_REQUEST['start'], 3) . " AND ID_TOPIC = $topic", __FILE__, __LINE__); list ($_REQUEST['start']) = mysql_fetch_row($request); mysql_free_result($request); // We need to reverse the start as well in this case. if (!empty($options['view_newest_first'])) $_REQUEST['start'] = $topicinfo['numReplies'] - $_REQUEST['start']; } } // Create a previous next string if the selected theme has it as a selected option. $context['previous_next'] = $modSettings['enablePreviousNext'] ? '' . $txt['previous_next_back'] . ' ' . $txt['previous_next_forward'] . '' : ''; // Check if spellchecking is both enabled and actually working. (for quick reply.) $context['show_spellchecking'] = $modSettings['enableSpellChecking'] && function_exists('pspell_new'); // Censor the title... censorText($topicinfo['subject']); $context['page_title'] = $topicinfo['subject']; $context['subtitle'] = $topicinfo['subtitle']; $context['num_replies'] = $topicinfo['numReplies']; $context['topic_first_message'] = $topicinfo['ID_FIRST_MSG']; // Is this topic sticky, or can it even be? $topicinfo['isSticky'] = empty($modSettings['enableStickyTopics']) ? '0' : $topicinfo['isSticky']; // Default this topic to not marked for notifications... of course... $context['is_marked_notify'] = false; // Guests can't mark topics read or for notifications, just can't sorry. if (!$user_info['is_guest']) { // Mark the topic as read :) db_query(" REPLACE INTO {$db_prefix}log_topics (logTime, ID_MEMBER, ID_TOPIC) VALUES (" . time() . ", $ID_MEMBER, $topic)", __FILE__, __LINE__); // Check for notifications on this topic OR board. $request = db_query(" SELECT sent, ID_TOPIC FROM {$db_prefix}log_notify WHERE (ID_TOPIC = $topic OR ID_BOARD = $board) AND ID_MEMBER = $ID_MEMBER LIMIT 2", __FILE__, __LINE__); $do_once = true; while ($row = mysql_fetch_assoc($request)) { // Find if this topic is marked for notification... if (!empty($row['ID_TOPIC'])) $context['is_marked_notify'] = true; // Only do this once, but mark the notifications as "not sent yet" for next time. if (!empty($row['sent']) && $do_once) { db_query(" UPDATE {$db_prefix}log_notify SET sent = 0 WHERE (ID_TOPIC = $topic OR ID_BOARD = $board) AND ID_MEMBER = $ID_MEMBER LIMIT 1", __FILE__, __LINE__); $do_once = false; } } // Mark board as seen if this is the only new topic. if (isset($_REQUEST['topicseen'])) { // Use the mark read tables... and the last visit to figure out if this should be read or not. $request = db_query(" SELECT COUNT(t.ID_TOPIC) FROM ({$db_prefix}topics AS t, {$db_prefix}messages AS m) LEFT JOIN {$db_prefix}log_boards AS lb ON (lb.ID_BOARD = $board AND lb.ID_MEMBER = $ID_MEMBER) LEFT JOIN {$db_prefix}log_topics AS lt ON (lt.ID_TOPIC = t.ID_TOPIC AND lt.ID_MEMBER = $ID_MEMBER) WHERE t.ID_BOARD = $board AND m.ID_MSG = t.ID_LAST_MSG AND m.posterTime > IFNULL(lt.logTime, IFNULL(lb.logTime, 0))" . (empty($_SESSION['ID_MSG_LAST_VISIT']) ? '' : " AND t.ID_LAST_MSG > $_SESSION[ID_MSG_LAST_VISIT]"), __FILE__, __LINE__); list ($numNewTopics) = mysql_fetch_row($request); mysql_free_result($request); // If there're no real new topics in this board, mark the board as seen. if (empty($numNewTopics)) $_REQUEST['boardseen'] = true; } // Mark board as seen if we came using last post link from BoardIndex. (or other places...) if (isset($_REQUEST['boardseen'])) { db_query(" REPLACE INTO {$db_prefix}log_boards (logTime, ID_MEMBER, ID_BOARD) VALUES (" . time() . ", $ID_MEMBER, $board)", __FILE__, __LINE__); } } // Let's get nosey, who is viewing this topic? if (!empty($settings['display_who_viewing'])) { // Start out with no one at all viewing it. $context['view_members'] = array(); $context['view_members_list'] = array(); $context['view_num_hidden'] = 0; // Search for members who have this topic set in their GET data. $request = db_query(" SELECT mem.ID_MEMBER, IFNULL(mem.realName, 0) AS realName, mem.showOnline FROM {$db_prefix}log_online AS lo LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = lo.ID_MEMBER) WHERE lo.url LIKE '%s:5:\"topic\";i:$topic;%'", __FILE__, __LINE__); while ($row = mysql_fetch_assoc($request)) if (!empty($row['ID_MEMBER'])) { // Add them both to the list and to the more detailed list. if (!empty($row['showOnline']) || allowedTo('moderate_forum')) $context['view_members_list'][] = empty($row['showOnline']) ? '' . $row['realName'] . '' : '' . $row['realName'] . ''; $context['view_members'][] = array( 'id' => $row['ID_MEMBER'], 'name' => $row['realName'], 'href' => $scripturl . '?action=profile;u=' . $row['ID_MEMBER'], 'link' => '' . $row['realName'] . '', 'hidden' => empty($row['showOnline']), ); if (empty($row['showOnline'])) $context['view_num_hidden']++; } // The number of guests is equal to the rows minus the ones we actually used ;). $context['view_num_guests'] = mysql_num_rows($request) - count($context['view_members']); mysql_free_result($request); } // If all is set, but not allowed... just unset it. if (isset($_REQUEST['all']) && empty($modSettings['enableAllMessages'])) unset($_REQUEST['all']); // Otherwise, it must be allowed... so pretend start was -1. elseif (isset($_REQUEST['all'])) $_REQUEST['start'] = -1; // Construct the page index, allowing for the .START method... $context['page_index'] = constructPageIndex($scripturl . '?topic=' . $topic, $_REQUEST['start'], $topicinfo['numReplies'] + 1, $modSettings['defaultMaxMessages'], true); $context['start'] = $_REQUEST['start']; // This is information about which page is current, and which page we're on - in case you don't like the constructed page index. (again, wireles..) $context['page_info'] = array( 'current_page' => floor($_REQUEST['start'] / $modSettings['defaultMaxMessages']) + 1, 'num_pages' => floor($topicinfo['numReplies'] / $modSettings['defaultMaxMessages']) + 1, ); if (isset ($_REQUEST['topicname'])) { $context['canonical_url'] = "/forum/{$_REQUEST['topicname']}?start={$_REQUEST['start']}"; } else { $context['canonical_url'] = $scripturl . '?topic=' . $topic . '.' . $_REQUEST['start']; } // Figure out all the link to the next/prev/first/last/etc. for wireless mainly. $context['links'] = array( 'first' => $_REQUEST['start'] >= $modSettings['defaultMaxMessages'] ? $scripturl . '?topic=' . $topic . '.0' : '', 'prev' => $_REQUEST['start'] >= $modSettings['defaultMaxMessages'] ? $scripturl . '?topic=' . $topic . '.' . ($_REQUEST['start'] - $modSettings['defaultMaxMessages']) : '', 'next' => $_REQUEST['start'] + $modSettings['defaultMaxMessages'] < $topicinfo['numReplies'] + 1 ? $scripturl . '?topic=' . $topic. '.' . ($_REQUEST['start'] + $modSettings['defaultMaxMessages']) : '', 'last' => $_REQUEST['start'] + $modSettings['defaultMaxMessages'] < $topicinfo['numReplies'] + 1 ? $scripturl . '?topic=' . $topic. '.' . (floor($topicinfo['numReplies'] / $modSettings['defaultMaxMessages']) * $modSettings['defaultMaxMessages']) : '', 'up' => $scripturl . '?board=' . $board . '.0' ); // If they are viewing all the posts, show all the posts, otherwise limit the number. if (!empty($modSettings['enableAllMessages']) && $topicinfo['numReplies'] + 1 > $modSettings['defaultMaxMessages'] && $topicinfo['numReplies'] + 1 < $modSettings['enableAllMessages']) { if (isset($_REQUEST['all'])) { // No limit! (actually, there is a limit, but...) $modSettings['defaultMaxMessages'] = -1; $context['page_index'] .= '

',
'option' => doUBBC($option[0]),
'vote_button' => ''
);
}
}
// Calculate the fastest way to get the messages.
$ascending = empty($options['view_newest_first']);
$start = $_REQUEST['start'];
$limit = $modSettings['defaultMaxMessages'];
$firstIndex = 0;
if ($start > $topicinfo['numReplies'] / 2 && $modSettings['defaultMaxMessages'] != -1)
{
$ascending = !$ascending;
$limit = $topicinfo['numReplies'] < $start + $limit ? $topicinfo['numReplies'] - $start + 1 : $limit;
$start = $topicinfo['numReplies'] < $start + $limit ? 0 : $topicinfo['numReplies'] - $start - $limit + 1;
$firstIndex = $limit - 1;
}
// Get each post and poster in this topic.
$messages = array();
$posters = array();
// always get post number 0 for sticky topics
if ((($start > 0) || !($ascending)) && ($context['is_sticky'] || $context['is_first_sticky'])) {
$request = db_query("
SELECT ID_MSG, ID_MEMBER
FROM {$db_prefix}messages
WHERE ID_TOPIC = $topic
ORDER BY ID_MSG LIMIT 1", __FILE__, __LINE__);
$row = mysql_fetch_assoc($request);
if (!empty($row['ID_MEMBER']))
$posters[] = $row['ID_MEMBER'];
$messages[] = $row['ID_MSG'];
mysql_free_result($request);
}
// now fetch the rest of the posts
$request = db_query("
SELECT ID_MSG, ID_MEMBER
FROM {$db_prefix}messages
WHERE ID_TOPIC = $topic
ORDER BY ID_MSG " . ($ascending ? '' : 'DESC') . ($modSettings['defaultMaxMessages'] == -1 ? '' : "
LIMIT $start, $limit"), __FILE__, __LINE__);
// declarations moved up
while ($row = mysql_fetch_assoc($request))
{
if (!empty($row['ID_MEMBER']))
$posters[] = $row['ID_MEMBER'];
$messages[] = $row['ID_MSG'];
}
mysql_free_result($request);
$posters = array_unique($posters);
$attachments = array();
// If there _are_ messages here... (probably an error otherwise :!)
if (!empty($messages))
{
// Fetch moderatorial comments
$request = db_query("
SELECT
md.ID_MSG as ID_MSG,
m.realName AS username,
md.level AS level,
md.message AS message,
md.timestamp AS timestamp
FROM {$db_prefix}moderatorial md, {$db_prefix}members m
WHERE
m.ID_MEMBER=md.ID_MEMBER AND
md.ID_MSG IN (" . implode(',', $messages) . ");
", __FILE__, __LINE__);
$moderatorial_messages = array();
while ($row = mysql_fetch_assoc($request)) {
$moderatorial_messages[$row['ID_MSG']] = $row;
}
// Fetch attachments.
if (!empty($modSettings['attachmentEnable']))
{
$request = db_query("
SELECT ID_ATTACH, ID_MSG, filename, IFNULL(size, 0) AS filesize, downloads
FROM {$db_prefix}attachments
WHERE ID_MSG IN (" . implode(',', $messages) . ")", __FILE__, __LINE__);
$temp = array();
while ($row = mysql_fetch_assoc($request))
{
$temp[$row['ID_ATTACH']] = $row;
if (!isset($attachments[$row['ID_MSG']]))
$attachments[$row['ID_MSG']] = array();
}
mysql_free_result($request);
// This is better than sorting it with the query...
ksort($temp);
foreach ($temp as $row)
$attachments[$row['ID_MSG']][] = $row;
}
// What? It's not like it *couldn't* be only guests in this topic...
if (!empty($posters))
loadMemberData($posters);
$messages_request = db_query("
SELECT
ID_MSG, icon, subject, posterTime, posterIP, ID_MEMBER, modifiedTime, modifiedName, body,
smileysEnabled, posterName, posterEmail, nowPlaying,
(GREATEST(posterTime, modifiedTime) > $topicinfo[logTime]) AS isRead
FROM {$db_prefix}messages
WHERE ID_MSG IN (" . implode(',', $messages) . ")
ORDER BY ID_MSG" . (empty($options['view_newest_first']) ? '' : ' DESC'), __FILE__, __LINE__);
// Go to the last message if the given time is beyond the time of the last message.
if (isset($context['start_from']) && $context['start_from'] >= $topicinfo['numReplies'])
$context['start_from'] = $topicinfo['numReplies'];
// Since the anchor information is needed on the top of the page we load these variables beforehand.
$context['first_message'] = isset($messages[$firstIndex]) ? $messages[$firstIndex] : $messages[0];
if (empty($options['view_newest_first']))
$context['first_new_message'] = isset($context['start_from']) && $_REQUEST['start'] == $context['start_from'];
else
$context['first_new_message'] = isset($context['start_from']) && $_REQUEST['start'] == $topicinfo['numReplies'] - $context['start_from'];
}
else
{
$messages_request = false;
$context['first_message'] = 0;
$context['first_new_message'] = false;
}
// Set the callback. (do you REALIZE how much memory all the messages would take?!?)
$context['get_message'] = 'prepareDisplayContext';
// Check if the topic is been watched by user
if ($user_info['is_guest']) {
$context['is_watched'] = false;
} else {
$result = db_query("
SELECT watch FROM {$db_prefix}watch_topics
WHERE
ID_MEMBER='{$ID_MEMBER}' AND
ID_TOPIC='{$topic}'",
__FILE__, __LINE__);
if(mysql_num_rows($result) == 0) {
$context['is_watched'] = false;
} else {
list($w) = mysql_fetch_row($result);
$context['is_watched'] = (bool) $w;
}
}
// Basic settings.... may be converted over at some point.
$context['allow_hide_email'] = !empty($modSettings['allow_hideEmail']) || ($user_info['is_guest'] && !empty($modSettings['guest_hideContacts']));
// Now set all the wonderful, wonderful permissions... like moderation ones...
$common_permissions = array(
'can_sticky' => 'make_sticky',
'can_merge' => 'merge_any',
'can_split' => 'split_any',
'calendar_post' => 'calendar_post',
'can_mark_notify' => 'mark_any_notify',
'can_send_topic' => 'send_topic',
'can_send_pm' => 'pm_send',
'can_report_moderator' => 'report_any',
'can_moderate_forum' => 'moderate_forum'
);
foreach ($common_permissions as $contextual => $perm)
$context[$contextual] = allowedTo($perm);
// Permissions with _any/_own versions. $context[YYY] => ZZZ_any/_own.
$anyown_permissions = array(
'can_move' => 'move',
'can_lock' => 'lock',
'can_delete' => 'delete',
'can_add_poll' => 'poll_add',
'can_remove_poll' => 'poll_remove',
'can_reply' => 'post_reply',
);
foreach ($anyown_permissions as $contextual => $perm)
$context[$contextual] = allowedTo($perm . '_any') || ($context['user']['started'] && allowedTo($perm . '_own'));
// Cleanup all the permissions with extra stuff...
$context['can_sticky'] &= !empty($modSettings['enableStickyTopics']);
$context['calendar_post'] &= !empty($modSettings['cal_enabled']);
$context['can_add_poll'] &= $modSettings['pollMode'] == '1' && $topicinfo['ID_POLL'] <= 0;
$context['can_remove_poll'] &= $modSettings['pollMode'] == '1' && $topicinfo['ID_POLL'] > 0;
$context['can_reply'] &= empty($topicinfo['locked']) || allowedTo('moderate_board');
$context['can_warn'] = allowedTo('visual_warn_any');
// Start this off for quick moderation - it will be or'd for each post.
$context['can_remove_post'] = allowedTo('remove_any') || (allowedTo('remove_replies') && $context['user']['started']);
// Load the "Jump to" list...
loadJumpTo();
// Load up the "double post" sequencing magic.
if (!empty($options['display_quick_reply']))
checkSubmitOnce('register');
}
// Callback for the message display.
function prepareDisplayContext($reset = false)
{
global $settings, $txt, $modSettings, $scripturl, $options;
global $themeUser, $context, $messages_request, $topic, $ID_MEMBER, $attachments, $moderatorial_messages;
static $counter = null;
// If the query returned false, bail.
if ($messages_request == false)
return false;
// Remember which message this is. (ie. reply #83)
if ($counter === null || $reset)
$counter = empty($options['view_newest_first']) ? $context['start'] : $context['num_replies'] - $context['start'];
// Start from the beginning...
if ($reset)
return @mysql_data_seek($messages_request, 0);
// Attempt to get the next message.
$message = mysql_fetch_assoc($messages_request);
if (!$message)
return false;
// If you're a lazy bum, you probably didn't give a subject...
$message['subject'] = $message['subject'] != '' ? $message['subject'] : $txt[24];
// Are you allowed to remove at least a single reply?
$context['can_remove_post'] |= allowedTo('remove_own') && $message['ID_MEMBER'] == $ID_MEMBER;
// If it couldn't load, or the user was a guest.... someday may be done with a guest table.
if (!loadMemberContext($message['ID_MEMBER']))
{
// Notice this information isn't used anywhere else....
$themeUser[$message['ID_MEMBER']]['name'] = $message['posterName'];
$themeUser[$message['ID_MEMBER']]['id'] = 0;
$themeUser[$message['ID_MEMBER']]['group'] = $txt[28];
$themeUser[$message['ID_MEMBER']]['link'] = $message['posterName'];
$themeUser[$message['ID_MEMBER']]['email'] = $message['posterEmail'];
$themeUser[$message['ID_MEMBER']]['is_guest'] = true;
}
else
$themeUser[$message['ID_MEMBER']]['can_view_profile'] = allowedTo('profile_view_any') || ($message['ID_MEMBER'] == $ID_MEMBER && allowedTo('profile_view_own'));
$themeUser[$message['ID_MEMBER']]['ip'] = $message['posterIP'];
// Do the censor thang.
censorText($message['body']);
censorText($message['subject']);
censorText($message['nowPlaying']);
// Run BBC interpreter on the message.
$message['body'] = doUBBC($message['body'], $message['smileysEnabled']);
// Compose the memory eat- I mean message array.
$output = array(
'attachment' => loadAttachmentContext($message['ID_MSG']),
'alternate' => $counter % 2,
'id' => $message['ID_MSG'],
'href' => $scripturl . '?topic=' . $topic . '.msg' . $message['ID_MSG'] . '#msg' . $message['ID_MSG'],
'link' => '' . $message['subject'] . '',
'member' => &$themeUser[$message['ID_MEMBER']],
'icon' => $message['icon'],
'subject' => $message['subject'],
'time' => timeformat($message['posterTime']),
'timestamp' => $message['posterTime'],
'counter' => $counter,
'modified' => array(
'time' => timeformat($message['modifiedTime']),
'timestamp' => $message['modifiedTime'],
'name' => $message['modifiedName']
),
'body' => $message['body'],
'nowplaying' => $message['nowPlaying'],
'new' => empty($message['isRead']),
'first_new' => isset($context['start_from']) && $context['start_from'] == $counter,
'can_modify' => allowedTo('modify_any') || (allowedTo('modify_replies') && $context['user']['started']) || (allowedTo('modify_own') && $message['ID_MEMBER'] == $ID_MEMBER && $message['posterTime'] > time() - 3600*24),
'can_remove' => allowedTo('remove_any') || (allowedTo('remove_replies') && $context['user']['started']) || (allowedTo('remove_own') && $message['ID_MEMBER'] == $ID_MEMBER),
'can_see_ip' => allowedTo('moderate_forum') || ($message['ID_MEMBER'] == $ID_MEMBER && !empty($ID_MEMBER)),
'moderatorial' => isset($moderatorial_messages[$message['ID_MSG']]) ? $moderatorial_messages[$message['ID_MSG']] : NULL,
);
if (empty($options['view_newest_first']))
$counter++;
else
$counter--;
return $output;
}
// Download an attachment.
function Download()
{
global $txt, $modSettings, $db_prefix, $user_info, $scripturl, $context;
// Make sure some attachment was requested!
if (!isset($_REQUEST['id']))
fatal_lang_error(1, false);
$_REQUEST['id'] = (int) $_REQUEST['id'];
if (isset($_REQUEST['type']) && $_REQUEST['type'] == 'avatar')
{
$request = db_query("
SELECT filename, ID_ATTACH
FROM {$db_prefix}attachments
WHERE ID_ATTACH = $_REQUEST[id]
AND ID_MEMBER > 0
LIMIT 1", __FILE__, __LINE__);
$_REQUEST['image'] = true;
}
// This is just a regular attachment...
else
{
isAllowedTo('view_attachments');
// Make sure this attachment is on this board.
$request = db_query("
SELECT a.filename, a.ID_ATTACH
FROM {$db_prefix}boards AS b, {$db_prefix}messages AS m, {$db_prefix}attachments AS a
WHERE b.ID_BOARD = m.ID_BOARD
AND $user_info[query_see_board]
AND m.ID_MSG = a.ID_MSG
AND a.ID_ATTACH = $_REQUEST[id]
LIMIT 1", __FILE__, __LINE__);
}
if (mysql_num_rows($request) == 0)
fatal_lang_error(1, false);
list ($real_filename, $ID_ATTACH) = mysql_fetch_row($request);
mysql_free_result($request);
// Update the download counter.
db_query("
UPDATE {$db_prefix}attachments
SET downloads = downloads + 1
WHERE ID_ATTACH = $ID_ATTACH", __FILE__, __LINE__);
// This is done to clear any output that was made before now. (would use ob_clean(), but that's PHP 4.2.0+...)
ob_end_clean();
if (!empty($modSettings['enableCompressedOutput']) && @version_compare(PHP_VERSION, '4.2.0') >= 0)
@ob_start('ob_gzhandler');
else
ob_start();
$filename = getAttachmentFilename($real_filename, $_REQUEST['id']);
$thumb_filename = getThumbnailFilename($real_filename, $_REQUEST['id']);
// No point in a nicer message, because this is supposed to be an attachment anyway...
if (!file_exists($filename))
{
loadLanguage('Errors');
header('HTTP/1.0 404 ' . $txt['attachment_not_found']);
header('Content-Type: text/plain');
die('404 - ' . $txt['attachment_not_found']);
}
// Send the attachment headers.
header('Pragma: ');
header('Cache-Control: max-age=' . (525600 * 60) . ', private');
if (!$context['browser']['is_gecko'])
header('Content-Transfer-Encoding: binary');
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 525600 * 60) . ' GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($filename)) . ' GMT');
header('Accept-Ranges: bytes');
header('Set-Cookie:');
header('Connection: close');
if (!(isset($_REQUEST['image'])||isset($_REQUEST['thumb'])))
{
header('Content-Disposition: attachment; filename="' . $real_filename . '"');
header('Content-Type: application/octet-stream');
}
if (filesize($filename) != 0)
{
$size = @getimagesize($filename);
if (!empty($size) && $size[2] > 0 && $size[2] < 4)
header('Content-Type: image/' . ($size[2] != 1 ? ($size[2] != 2 ? 'png' : 'jpeg') : 'gif'));
}
if (isset($_REQUEST['thumb']))
{
if(!file_exists($thumb_filename))
{
list($width, $height, $type) = @getimagesize($filename);
$type=($type != 1 ? ($type != 2 ? 'png' : 'jpeg') : 'gif');
eval("\$img=imagecreatefrom$type(\$filename);");
$width_orig=$width; $height_orig=$height;
if ($height > 240 || $width > 320)
{
if ($width > 320 )
{
$height = floor(320 / $width * $height);
$width = 320;
if ($height > 240)
{
$width = floor(240 / $height * $width);
$height = 240;
}
}
elseif ($height > 240)
{
$width = floor(240 / $height * $width);
$height = 240;
}
$thumb = imagecreatetruecolor($width, $height);
imagecopyresampled($thumb,$img, 0,0,0,0,$width,$height,$width_orig,$height_orig);
eval("image$type(\$thumb,\$thumb_filename);");
}
}
$filename=$thumb_filename;
}
if (empty($modSettings['enableCompressedOutput']))
header('Content-Length: ' . filesize($filename));
// Try to buy some time...
@set_time_limit(0);
@ini_set('memory_limit', '128M');
// On some of the less-bright hosts, readfile() is disabled. It's just a faster, more byte safe, version of what's in the if.
if (@readfile($filename) === null)
echo implode('', file($filename));
obExit(false);
}
function loadAttachmentContext($ID_MSG)
{
global $attachments, $modSettings, $txt, $scripturl, $topic;
// Set up the attachment info - based on code by Meriadoc.
$attachmentData = array();
if (isset($attachments[$ID_MSG]) && !empty($modSettings['attachmentEnable']))
{
foreach ($attachments[$ID_MSG] as $i => $attachment)
{
$attachmentData[$i] = array(
'name' => $attachment['filename'],
'downloads' => $attachment['downloads'],
'size' => round($attachment['filesize'] / 1024, 2) . ' ' . $txt['smf211'],
'byte_size' => $attachment['filesize'],
'href' => $scripturl . '?action=dlattach;topic=' . $topic . '.0;id=' . $attachment['ID_ATTACH'],
'link' => '' . $attachment['filename'] . '',
'is_image' => false
);
if (empty($modSettings['attachmentShowImages']))
continue;
// Set up the image attachment info.
$filename = getAttachmentFilename($attachment['filename'], $attachment['ID_ATTACH']);
$imageTypes = array('gif' => 1, 'jpeg' => 2, 'png' => 3, 'bmp' => 6);
if (file_exists($filename) && filesize($filename) > 0)
list ($width, $height, $imageType) = @getimagesize($filename);
else
{
$imageType = 0;
$attachmentData[$i]['size'] = '0 ' . $txt['smf211'];
}
// If this isn't an image, we're done.
if (!allowedTo('view_attachments') || !in_array($imageType, $imageTypes))
continue;
/*
if(!file_exists($modSettings['attachmentUploadDir'].'/thumbs/'.
// Start resize/restrict posted images mod by Mostmaster.
if (!(empty($modSettings['maxwidth']) && empty($modSettings['maxheight'])) && ($width > $modSettings['maxwidth'] || $height > $modSettings['maxheight']))
{
if ($width > $modSettings['maxwidth'] && !empty($modSettings['maxwidth']))
{
$height = floor($modSettings['maxwidth'] / $width * $height);
$width = $modSettings['maxwidth'];
if ($height > $modSettings['maxheight'] && !empty($modSettings['maxheight']))
{
$width = floor($modSettings['maxheight'] / $height * $width);
$height = $modSettings['maxheight'];
}
}
elseif ($height > $modSettings['maxheight'] && !empty($modSettings['maxheight']))
{
$width = floor($modSettings['maxheight'] / $height * $width);
$height = $modSettings['maxheight'];
}
$attachmentData[$i]['image'] = '