Yoshi2889 /
SMF2.1
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | /** |
||
| 4 | * This is perhaps the most important and probably most accessed file in all |
||
| 5 | * of SMF. This file controls topic, message, and attachment display. |
||
| 6 | * |
||
| 7 | * Simple Machines Forum (SMF) |
||
| 8 | * |
||
| 9 | * @package SMF |
||
| 10 | * @author Simple Machines http://www.simplemachines.org |
||
| 11 | * @copyright 2017 Simple Machines and individual contributors |
||
| 12 | * @license http://www.simplemachines.org/about/smf/license.php BSD |
||
| 13 | * |
||
| 14 | * @version 2.1 Beta 4 |
||
| 15 | */ |
||
| 16 | |||
| 17 | if (!defined('SMF')) |
||
| 18 | die('No direct access...'); |
||
| 19 | |||
| 20 | /** |
||
| 21 | * The central part of the board - topic display. |
||
| 22 | * This function loads the posts in a topic up so they can be displayed. |
||
| 23 | * It uses the main sub template of the Display template. |
||
| 24 | * It requires a topic, and can go to the previous or next topic from it. |
||
| 25 | * It jumps to the correct post depending on a number/time/IS_MSG passed. |
||
| 26 | * It depends on the messages_per_page, defaultMaxMessages and enableAllMessages settings. |
||
| 27 | * It is accessed by ?topic=id_topic.START. |
||
| 28 | * @return void |
||
| 29 | */ |
||
| 30 | function Display() |
||
| 31 | { |
||
| 32 | global $scripturl, $txt, $modSettings, $context, $settings; |
||
| 33 | global $options, $sourcedir, $user_info, $board_info, $topic, $board; |
||
| 34 | global $messages_request, $language, $smcFunc; |
||
| 35 | |||
| 36 | // What are you gonna display if these are empty?! |
||
| 37 | if (empty($topic)) |
||
| 38 | fatal_lang_error('no_board', false); |
||
| 39 | |||
| 40 | // Load the proper template. |
||
| 41 | loadTemplate('Display'); |
||
| 42 | |||
| 43 | // Not only does a prefetch make things slower for the server, but it makes it impossible to know if they read it. |
||
| 44 | if (isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch') |
||
| 45 | { |
||
| 46 | ob_end_clean(); |
||
| 47 | header('HTTP/1.1 403 Prefetch Forbidden'); |
||
| 48 | die; |
||
| 49 | } |
||
| 50 | |||
| 51 | // How much are we sticking on each page? |
||
| 52 | $context['messages_per_page'] = empty($modSettings['disableCustomPerPage']) && !empty($options['messages_per_page']) ? $options['messages_per_page'] : $modSettings['defaultMaxMessages']; |
||
| 53 | |||
| 54 | // Let's do some work on what to search index. |
||
| 55 | View Code Duplication | if (count($_GET) > 2) |
|
| 56 | foreach ($_GET as $k => $v) |
||
| 57 | { |
||
| 58 | if (!in_array($k, array('topic', 'board', 'start', session_name()))) |
||
| 59 | $context['robot_no_index'] = true; |
||
| 60 | } |
||
| 61 | |||
| 62 | View Code Duplication | if (!empty($_REQUEST['start']) && (!is_numeric($_REQUEST['start']) || $_REQUEST['start'] % $context['messages_per_page'] != 0)) |
|
| 63 | $context['robot_no_index'] = true; |
||
| 64 | |||
| 65 | // Find the previous or next topic. Make a fuss if there are no more. |
||
| 66 | if (isset($_REQUEST['prev_next']) && ($_REQUEST['prev_next'] == 'prev' || $_REQUEST['prev_next'] == 'next')) |
||
| 67 | { |
||
| 68 | // No use in calculating the next topic if there's only one. |
||
| 69 | if ($board_info['num_topics'] > 1) |
||
| 70 | { |
||
| 71 | // Just prepare some variables that are used in the query. |
||
| 72 | $gt_lt = $_REQUEST['prev_next'] == 'prev' ? '>' : '<'; |
||
| 73 | $order = $_REQUEST['prev_next'] == 'prev' ? '' : ' DESC'; |
||
| 74 | |||
| 75 | $request = $smcFunc['db_query']('', ' |
||
| 76 | SELECT t2.id_topic |
||
| 77 | FROM {db_prefix}topics AS t |
||
| 78 | INNER JOIN {db_prefix}topics AS t2 ON ( |
||
| 79 | (t2.id_last_msg ' . $gt_lt . ' t.id_last_msg AND t2.is_sticky ' . $gt_lt . '= t.is_sticky) OR t2.is_sticky ' . $gt_lt . ' t.is_sticky) |
||
| 80 | WHERE t.id_topic = {int:current_topic} |
||
| 81 | AND t2.id_board = {int:current_board}' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : ' |
||
| 82 | AND (t2.approved = {int:is_approved} OR (t2.id_member_started != {int:id_member_started} AND t2.id_member_started = {int:current_member}))') . ' |
||
| 83 | ORDER BY t2.is_sticky' . $order . ', t2.id_last_msg' . $order . ' |
||
| 84 | LIMIT 1', |
||
| 85 | array( |
||
| 86 | 'current_board' => $board, |
||
| 87 | 'current_member' => $user_info['id'], |
||
| 88 | 'current_topic' => $topic, |
||
| 89 | 'is_approved' => 1, |
||
| 90 | 'id_member_started' => 0, |
||
| 91 | ) |
||
| 92 | ); |
||
| 93 | |||
| 94 | // No more left. |
||
| 95 | if ($smcFunc['db_num_rows']($request) == 0) |
||
| 96 | { |
||
| 97 | $smcFunc['db_free_result']($request); |
||
| 98 | |||
| 99 | // Roll over - if we're going prev, get the last - otherwise the first. |
||
| 100 | $request = $smcFunc['db_query']('', ' |
||
| 101 | SELECT id_topic |
||
| 102 | FROM {db_prefix}topics |
||
| 103 | WHERE id_board = {int:current_board}' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : ' |
||
| 104 | AND (approved = {int:is_approved} OR (id_member_started != {int:id_member_started} AND id_member_started = {int:current_member}))') . ' |
||
| 105 | ORDER BY is_sticky' . $order . ', id_last_msg' . $order . ' |
||
| 106 | LIMIT 1', |
||
| 107 | array( |
||
| 108 | 'current_board' => $board, |
||
| 109 | 'current_member' => $user_info['id'], |
||
| 110 | 'is_approved' => 1, |
||
| 111 | 'id_member_started' => 0, |
||
| 112 | ) |
||
| 113 | ); |
||
| 114 | } |
||
| 115 | |||
| 116 | // Now you can be sure $topic is the id_topic to view. |
||
| 117 | list ($topic) = $smcFunc['db_fetch_row']($request); |
||
| 118 | $smcFunc['db_free_result']($request); |
||
| 119 | |||
| 120 | $context['current_topic'] = $topic; |
||
| 121 | } |
||
| 122 | |||
| 123 | // Go to the newest message on this topic. |
||
| 124 | $_REQUEST['start'] = 'new'; |
||
| 125 | } |
||
| 126 | |||
| 127 | // Add 1 to the number of views of this topic (except for robots). |
||
| 128 | if (!$user_info['possibly_robot'] && (empty($_SESSION['last_read_topic']) || $_SESSION['last_read_topic'] != $topic)) |
||
| 129 | { |
||
| 130 | $smcFunc['db_query']('', ' |
||
| 131 | UPDATE {db_prefix}topics |
||
| 132 | SET num_views = num_views + 1 |
||
| 133 | WHERE id_topic = {int:current_topic}', |
||
| 134 | array( |
||
| 135 | 'current_topic' => $topic, |
||
| 136 | ) |
||
| 137 | ); |
||
| 138 | |||
| 139 | $_SESSION['last_read_topic'] = $topic; |
||
| 140 | } |
||
| 141 | |||
| 142 | $topic_parameters = array( |
||
| 143 | 'current_member' => $user_info['id'], |
||
| 144 | 'current_topic' => $topic, |
||
| 145 | 'current_board' => $board, |
||
| 146 | ); |
||
| 147 | $topic_selects = array(); |
||
| 148 | $topic_tables = array(); |
||
| 149 | $context['topicinfo'] = array(); |
||
| 150 | call_integration_hook('integrate_display_topic', array(&$topic_selects, &$topic_tables, &$topic_parameters)); |
||
| 151 | |||
| 152 | // @todo Why isn't this cached? |
||
| 153 | // @todo if we get id_board in this query and cache it, we can save a query on posting |
||
| 154 | // Get all the important topic info. |
||
| 155 | $request = $smcFunc['db_query']('', ' |
||
| 156 | SELECT |
||
| 157 | t.num_replies, t.num_views, t.locked, ms.subject, t.is_sticky, t.id_poll, |
||
| 158 | t.id_member_started, t.id_first_msg, t.id_last_msg, t.approved, t.unapproved_posts, t.id_redirect_topic, |
||
| 159 | COALESCE(mem.real_name, ms.poster_name) AS topic_started_name, ms.poster_time AS topic_started_time, |
||
| 160 | ' . ($user_info['is_guest'] ? 't.id_last_msg + 1' : 'COALESCE(lt.id_msg, lmr.id_msg, -1) + 1') . ' AS new_from |
||
| 161 | ' . (!empty($board_info['recycle']) ? ', id_previous_board, id_previous_topic' : '') . ' |
||
| 162 | ' . (!empty($topic_selects) ? (', ' . implode(', ', $topic_selects)) : '') . ' |
||
| 163 | ' . (!$user_info['is_guest'] ? ', COALESCE(lt.unwatched, 0) as unwatched' : '') . ' |
||
| 164 | FROM {db_prefix}topics AS t |
||
| 165 | INNER JOIN {db_prefix}messages AS ms ON (ms.id_msg = t.id_first_msg) |
||
| 166 | LEFT JOIN {db_prefix}members AS mem on (mem.id_member = t.id_member_started)' . ($user_info['is_guest'] ? '' : ' |
||
| 167 | LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = {int:current_topic} AND lt.id_member = {int:current_member}) |
||
| 168 | LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = {int:current_board} AND lmr.id_member = {int:current_member})') . ' |
||
| 169 | ' . (!empty($topic_tables) ? implode("\n\t", $topic_tables) : '') . ' |
||
| 170 | WHERE t.id_topic = {int:current_topic} |
||
| 171 | LIMIT 1', |
||
| 172 | $topic_parameters |
||
| 173 | ); |
||
| 174 | |||
| 175 | if ($smcFunc['db_num_rows']($request) == 0) |
||
| 176 | fatal_lang_error('not_a_topic', false, 404); |
||
| 177 | $context['topicinfo'] = $smcFunc['db_fetch_assoc']($request); |
||
| 178 | $smcFunc['db_free_result']($request); |
||
| 179 | |||
| 180 | // Is this a moved or merged topic that we are redirecting to? |
||
| 181 | if (!empty($context['topicinfo']['id_redirect_topic'])) |
||
| 182 | { |
||
| 183 | // Mark this as read... |
||
| 184 | if (!$user_info['is_guest'] && $context['topicinfo']['new_from'] != $context['topicinfo']['id_first_msg']) |
||
| 185 | { |
||
| 186 | // Mark this as read first |
||
| 187 | $smcFunc['db_insert']($context['topicinfo']['new_from'] == 0 ? 'ignore' : 'replace', |
||
| 188 | '{db_prefix}log_topics', |
||
| 189 | array( |
||
| 190 | 'id_member' => 'int', 'id_topic' => 'int', 'id_msg' => 'int', 'unwatched' => 'int', |
||
| 191 | ), |
||
| 192 | array( |
||
| 193 | $user_info['id'], $topic, $context['topicinfo']['id_first_msg'], $context['topicinfo']['unwatched'], |
||
| 194 | ), |
||
| 195 | array('id_member', 'id_topic') |
||
| 196 | ); |
||
| 197 | } |
||
| 198 | redirectexit('topic=' . $context['topicinfo']['id_redirect_topic'] . '.0', false, true); |
||
| 199 | } |
||
| 200 | |||
| 201 | // Short-cut to know if this user can see unapproved messages. |
||
| 202 | $approve_posts = (allowedTo('approve_posts') || $context['topicinfo']['id_member_started'] == $user_info['id']); |
||
| 203 | |||
| 204 | $context['real_num_replies'] = $context['num_replies'] = $context['topicinfo']['num_replies']; |
||
| 205 | $context['topic_started_time'] = timeformat($context['topicinfo']['topic_started_time']); |
||
| 206 | $context['topic_started_timestamp'] = $context['topicinfo']['topic_started_time']; |
||
| 207 | $context['topic_poster_name'] = $context['topicinfo']['topic_started_name']; |
||
| 208 | $context['topic_first_message'] = $context['topicinfo']['id_first_msg']; |
||
| 209 | $context['topic_last_message'] = $context['topicinfo']['id_last_msg']; |
||
| 210 | $context['topic_unwatched'] = isset($context['topicinfo']['unwatched']) ? $context['topicinfo']['unwatched'] : 0; |
||
| 211 | |||
| 212 | // Add up unapproved replies to get real number of replies... |
||
| 213 | if ($modSettings['postmod_active'] && $approve_posts) |
||
| 214 | $context['real_num_replies'] += $context['topicinfo']['unapproved_posts'] - ($context['topicinfo']['approved'] ? 0 : 1); |
||
| 215 | |||
| 216 | // If this topic has unapproved posts, we need to work out how many posts the user can see, for page indexing. |
||
| 217 | if ($modSettings['postmod_active'] && $context['topicinfo']['unapproved_posts'] && !$user_info['is_guest'] && !$approve_posts) |
||
| 218 | { |
||
| 219 | $request = $smcFunc['db_query']('', ' |
||
| 220 | SELECT COUNT(id_member) AS my_unapproved_posts |
||
| 221 | FROM {db_prefix}messages |
||
| 222 | WHERE id_topic = {int:current_topic} |
||
| 223 | AND id_member = {int:current_member} |
||
| 224 | AND approved = 0', |
||
| 225 | array( |
||
| 226 | 'current_topic' => $topic, |
||
| 227 | 'current_member' => $user_info['id'], |
||
| 228 | ) |
||
| 229 | ); |
||
| 230 | list ($myUnapprovedPosts) = $smcFunc['db_fetch_row']($request); |
||
| 231 | $smcFunc['db_free_result']($request); |
||
| 232 | |||
| 233 | $context['total_visible_posts'] = $context['num_replies'] + $myUnapprovedPosts + ($context['topicinfo']['approved'] ? 1 : 0); |
||
| 234 | } |
||
| 235 | View Code Duplication | elseif ($user_info['is_guest']) |
|
| 236 | $context['total_visible_posts'] = $context['num_replies'] + ($context['topicinfo']['approved'] ? 1 : 0); |
||
| 237 | View Code Duplication | else |
|
| 238 | $context['total_visible_posts'] = $context['num_replies'] + $context['topicinfo']['unapproved_posts'] + ($context['topicinfo']['approved'] ? 1 : 0); |
||
| 239 | |||
| 240 | // The start isn't a number; it's information about what to do, where to go. |
||
| 241 | if (!is_numeric($_REQUEST['start'])) |
||
| 242 | { |
||
| 243 | // Redirect to the page and post with new messages, originally by Omar Bazavilvazo. |
||
| 244 | if ($_REQUEST['start'] == 'new') |
||
| 245 | { |
||
| 246 | // Guests automatically go to the last post. |
||
| 247 | if ($user_info['is_guest']) |
||
| 248 | { |
||
| 249 | $context['start_from'] = $context['total_visible_posts'] - 1; |
||
| 250 | $_REQUEST['start'] = empty($options['view_newest_first']) ? $context['start_from'] : 0; |
||
| 251 | } |
||
| 252 | View Code Duplication | else |
|
| 253 | { |
||
| 254 | // Find the earliest unread message in the topic. (the use of topics here is just for both tables.) |
||
| 255 | $request = $smcFunc['db_query']('', ' |
||
| 256 | SELECT COALESCE(lt.id_msg, lmr.id_msg, -1) + 1 AS new_from |
||
| 257 | FROM {db_prefix}topics AS t |
||
| 258 | LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = {int:current_topic} AND lt.id_member = {int:current_member}) |
||
| 259 | LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = {int:current_board} AND lmr.id_member = {int:current_member}) |
||
| 260 | WHERE t.id_topic = {int:current_topic} |
||
| 261 | LIMIT 1', |
||
| 262 | array( |
||
| 263 | 'current_board' => $board, |
||
| 264 | 'current_member' => $user_info['id'], |
||
| 265 | 'current_topic' => $topic, |
||
| 266 | ) |
||
| 267 | ); |
||
| 268 | list ($new_from) = $smcFunc['db_fetch_row']($request); |
||
| 269 | $smcFunc['db_free_result']($request); |
||
| 270 | |||
| 271 | // Fall through to the next if statement. |
||
| 272 | $_REQUEST['start'] = 'msg' . $new_from; |
||
| 273 | } |
||
| 274 | } |
||
| 275 | |||
| 276 | // Start from a certain time index, not a message. |
||
| 277 | if (substr($_REQUEST['start'], 0, 4) == 'from') |
||
| 278 | { |
||
| 279 | $timestamp = (int) substr($_REQUEST['start'], 4); |
||
| 280 | if ($timestamp === 0) |
||
| 281 | $_REQUEST['start'] = 0; |
||
| 282 | else |
||
| 283 | { |
||
| 284 | // Find the number of messages posted before said time... |
||
| 285 | $request = $smcFunc['db_query']('', ' |
||
| 286 | SELECT COUNT(*) |
||
| 287 | FROM {db_prefix}messages |
||
| 288 | WHERE poster_time < {int:timestamp} |
||
| 289 | AND id_topic = {int:current_topic}' . ($modSettings['postmod_active'] && $context['topicinfo']['unapproved_posts'] && !allowedTo('approve_posts') ? ' |
||
| 290 | AND (approved = {int:is_approved}' . ($user_info['is_guest'] ? '' : ' OR id_member = {int:current_member}') . ')' : ''), |
||
| 291 | array( |
||
| 292 | 'current_topic' => $topic, |
||
| 293 | 'current_member' => $user_info['id'], |
||
| 294 | 'is_approved' => 1, |
||
| 295 | 'timestamp' => $timestamp, |
||
| 296 | ) |
||
| 297 | ); |
||
| 298 | list ($context['start_from']) = $smcFunc['db_fetch_row']($request); |
||
| 299 | $smcFunc['db_free_result']($request); |
||
| 300 | |||
| 301 | // Handle view_newest_first options, and get the correct start value. |
||
| 302 | $_REQUEST['start'] = empty($options['view_newest_first']) ? $context['start_from'] : $context['total_visible_posts'] - $context['start_from'] - 1; |
||
| 303 | } |
||
| 304 | } |
||
| 305 | |||
| 306 | // Link to a message... |
||
| 307 | elseif (substr($_REQUEST['start'], 0, 3) == 'msg') |
||
| 308 | { |
||
| 309 | $virtual_msg = (int) substr($_REQUEST['start'], 3); |
||
| 310 | if (!$context['topicinfo']['unapproved_posts'] && $virtual_msg >= $context['topicinfo']['id_last_msg']) |
||
| 311 | $context['start_from'] = $context['total_visible_posts'] - 1; |
||
| 312 | elseif (!$context['topicinfo']['unapproved_posts'] && $virtual_msg <= $context['topicinfo']['id_first_msg']) |
||
| 313 | $context['start_from'] = 0; |
||
| 314 | else |
||
| 315 | { |
||
| 316 | // Find the start value for that message...... |
||
| 317 | $request = $smcFunc['db_query']('', ' |
||
| 318 | SELECT COUNT(*) |
||
| 319 | FROM {db_prefix}messages |
||
| 320 | WHERE id_msg < {int:virtual_msg} |
||
| 321 | AND id_topic = {int:current_topic}' . ($modSettings['postmod_active'] && $context['topicinfo']['unapproved_posts'] && !allowedTo('approve_posts') ? ' |
||
| 322 | AND (approved = {int:is_approved}' . ($user_info['is_guest'] ? '' : ' OR id_member = {int:current_member}') . ')' : ''), |
||
| 323 | array( |
||
| 324 | 'current_member' => $user_info['id'], |
||
| 325 | 'current_topic' => $topic, |
||
| 326 | 'virtual_msg' => $virtual_msg, |
||
| 327 | 'is_approved' => 1, |
||
| 328 | 'no_member' => 0, |
||
| 329 | ) |
||
| 330 | ); |
||
| 331 | list ($context['start_from']) = $smcFunc['db_fetch_row']($request); |
||
| 332 | $smcFunc['db_free_result']($request); |
||
| 333 | } |
||
| 334 | |||
| 335 | // We need to reverse the start as well in this case. |
||
| 336 | $_REQUEST['start'] = empty($options['view_newest_first']) ? $context['start_from'] : $context['total_visible_posts'] - $context['start_from'] - 1; |
||
| 337 | } |
||
| 338 | } |
||
| 339 | |||
| 340 | // Create a previous next string if the selected theme has it as a selected option. |
||
| 341 | $context['previous_next'] = $modSettings['enablePreviousNext'] ? '<a href="' . $scripturl . '?topic=' . $topic . '.0;prev_next=prev#new">' . $txt['previous_next_back'] . '</a> - <a href="' . $scripturl . '?topic=' . $topic . '.0;prev_next=next#new">' . $txt['previous_next_forward'] . '</a>' : ''; |
||
| 342 | |||
| 343 | // Check if spellchecking is both enabled and actually working. (for quick reply.) |
||
| 344 | $context['show_spellchecking'] = !empty($modSettings['enableSpellChecking']) && (function_exists('pspell_new') || (function_exists('enchant_broker_init') && ($txt['lang_charset'] == 'UTF-8' || function_exists('iconv')))); |
||
| 345 | |||
| 346 | // Do we need to show the visual verification image? |
||
| 347 | $context['require_verification'] = !$user_info['is_mod'] && !$user_info['is_admin'] && !empty($modSettings['posts_require_captcha']) && ($user_info['posts'] < $modSettings['posts_require_captcha'] || ($user_info['is_guest'] && $modSettings['posts_require_captcha'] == -1)); |
||
| 348 | View Code Duplication | if ($context['require_verification']) |
|
| 349 | { |
||
| 350 | require_once($sourcedir . '/Subs-Editor.php'); |
||
| 351 | $verificationOptions = array( |
||
| 352 | 'id' => 'post', |
||
| 353 | ); |
||
| 354 | $context['require_verification'] = create_control_verification($verificationOptions); |
||
| 355 | $context['visual_verification_id'] = $verificationOptions['id']; |
||
| 356 | } |
||
| 357 | |||
| 358 | // Are we showing signatures - or disabled fields? |
||
| 359 | $context['signature_enabled'] = substr($modSettings['signature_settings'], 0, 1) == 1; |
||
| 360 | $context['disabled_fields'] = isset($modSettings['disabled_profile_fields']) ? array_flip(explode(',', $modSettings['disabled_profile_fields'])) : array(); |
||
| 361 | |||
| 362 | // Censor the title... |
||
| 363 | censorText($context['topicinfo']['subject']); |
||
| 364 | $context['page_title'] = $context['topicinfo']['subject']; |
||
| 365 | |||
| 366 | // Default this topic to not marked for notifications... of course... |
||
| 367 | $context['is_marked_notify'] = false; |
||
| 368 | |||
| 369 | // Did we report a post to a moderator just now? |
||
| 370 | $context['report_sent'] = isset($_GET['reportsent']); |
||
| 371 | |||
| 372 | // Let's get nosey, who is viewing this topic? |
||
| 373 | View Code Duplication | if (!empty($settings['display_who_viewing'])) |
|
| 374 | { |
||
| 375 | // Start out with no one at all viewing it. |
||
| 376 | $context['view_members'] = array(); |
||
| 377 | $context['view_members_list'] = array(); |
||
| 378 | $context['view_num_hidden'] = 0; |
||
| 379 | |||
| 380 | // Search for members who have this topic set in their GET data. |
||
| 381 | $request = $smcFunc['db_query']('', ' |
||
| 382 | SELECT |
||
| 383 | lo.id_member, lo.log_time, mem.real_name, mem.member_name, mem.show_online, |
||
| 384 | mg.online_color, mg.id_group, mg.group_name |
||
| 385 | FROM {db_prefix}log_online AS lo |
||
| 386 | LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lo.id_member) |
||
| 387 | LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = CASE WHEN mem.id_group = {int:reg_id_group} THEN mem.id_post_group ELSE mem.id_group END) |
||
| 388 | WHERE INSTR(lo.url, {string:in_url_string}) > 0 OR lo.session = {string:session}', |
||
| 389 | array( |
||
| 390 | 'reg_id_group' => 0, |
||
| 391 | 'in_url_string' => '"topic":' . $topic, |
||
| 392 | 'session' => $user_info['is_guest'] ? 'ip' . $user_info['ip'] : session_id(), |
||
| 393 | ) |
||
| 394 | ); |
||
| 395 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 396 | { |
||
| 397 | if (empty($row['id_member'])) |
||
| 398 | continue; |
||
| 399 | |||
| 400 | if (!empty($row['online_color'])) |
||
| 401 | $link = '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '" style="color: ' . $row['online_color'] . ';">' . $row['real_name'] . '</a>'; |
||
| 402 | else |
||
| 403 | $link = '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>'; |
||
| 404 | |||
| 405 | $is_buddy = in_array($row['id_member'], $user_info['buddies']); |
||
| 406 | if ($is_buddy) |
||
| 407 | $link = '<strong>' . $link . '</strong>'; |
||
| 408 | |||
| 409 | // Add them both to the list and to the more detailed list. |
||
| 410 | if (!empty($row['show_online']) || allowedTo('moderate_forum')) |
||
| 411 | $context['view_members_list'][$row['log_time'] . $row['member_name']] = empty($row['show_online']) ? '<em>' . $link . '</em>' : $link; |
||
| 412 | $context['view_members'][$row['log_time'] . $row['member_name']] = array( |
||
| 413 | 'id' => $row['id_member'], |
||
| 414 | 'username' => $row['member_name'], |
||
| 415 | 'name' => $row['real_name'], |
||
| 416 | 'group' => $row['id_group'], |
||
| 417 | 'href' => $scripturl . '?action=profile;u=' . $row['id_member'], |
||
| 418 | 'link' => $link, |
||
| 419 | 'is_buddy' => $is_buddy, |
||
| 420 | 'hidden' => empty($row['show_online']), |
||
| 421 | ); |
||
| 422 | |||
| 423 | if (empty($row['show_online'])) |
||
| 424 | $context['view_num_hidden']++; |
||
| 425 | } |
||
| 426 | |||
| 427 | // The number of guests is equal to the rows minus the ones we actually used ;). |
||
| 428 | $context['view_num_guests'] = $smcFunc['db_num_rows']($request) - count($context['view_members']); |
||
| 429 | $smcFunc['db_free_result']($request); |
||
| 430 | |||
| 431 | // Sort the list. |
||
| 432 | krsort($context['view_members']); |
||
| 433 | krsort($context['view_members_list']); |
||
| 434 | } |
||
| 435 | |||
| 436 | // If all is set, but not allowed... just unset it. |
||
| 437 | $can_show_all = !empty($modSettings['enableAllMessages']) && $context['total_visible_posts'] > $context['messages_per_page'] && $context['total_visible_posts'] < $modSettings['enableAllMessages']; |
||
| 438 | if (isset($_REQUEST['all']) && !$can_show_all) |
||
| 439 | unset($_REQUEST['all']); |
||
| 440 | // Otherwise, it must be allowed... so pretend start was -1. |
||
| 441 | elseif (isset($_REQUEST['all'])) |
||
| 442 | $_REQUEST['start'] = -1; |
||
| 443 | |||
| 444 | // Construct the page index, allowing for the .START method... |
||
| 445 | $context['page_index'] = constructPageIndex($scripturl . '?topic=' . $topic . '.%1$d', $_REQUEST['start'], $context['total_visible_posts'], $context['messages_per_page'], true); |
||
| 446 | $context['start'] = $_REQUEST['start']; |
||
| 447 | |||
| 448 | // 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..) |
||
| 449 | $context['page_info'] = array( |
||
| 450 | 'current_page' => $_REQUEST['start'] / $context['messages_per_page'] + 1, |
||
| 451 | 'num_pages' => floor(($context['total_visible_posts'] - 1) / $context['messages_per_page']) + 1, |
||
| 452 | ); |
||
| 453 | |||
| 454 | // Figure out all the link to the next/prev/first/last/etc. |
||
| 455 | if (!($can_show_all && isset($_REQUEST['all']))) |
||
| 456 | { |
||
| 457 | $context['links'] = array( |
||
| 458 | 'first' => $_REQUEST['start'] >= $context['messages_per_page'] ? $scripturl . '?topic=' . $topic . '.0' : '', |
||
| 459 | 'prev' => $_REQUEST['start'] >= $context['messages_per_page'] ? $scripturl . '?topic=' . $topic . '.' . ($_REQUEST['start'] - $context['messages_per_page']) : '', |
||
| 460 | 'next' => $_REQUEST['start'] + $context['messages_per_page'] < $context['total_visible_posts'] ? $scripturl . '?topic=' . $topic . '.' . ($_REQUEST['start'] + $context['messages_per_page']) : '', |
||
| 461 | 'last' => $_REQUEST['start'] + $context['messages_per_page'] < $context['total_visible_posts'] ? $scripturl . '?topic=' . $topic . '.' . (floor($context['total_visible_posts'] / $context['messages_per_page']) * $context['messages_per_page']) : '', |
||
| 462 | 'up' => $scripturl . '?board=' . $board . '.0' |
||
| 463 | ); |
||
| 464 | } |
||
| 465 | |||
| 466 | // If they are viewing all the posts, show all the posts, otherwise limit the number. |
||
| 467 | if ($can_show_all) |
||
| 468 | { |
||
| 469 | if (isset($_REQUEST['all'])) |
||
| 470 | { |
||
| 471 | // No limit! (actually, there is a limit, but...) |
||
| 472 | $context['messages_per_page'] = -1; |
||
| 473 | $context['page_index'] .= empty($modSettings['compactTopicPagesEnable']) ? '<strong>' . $txt['all'] . '</strong> ' : '[<strong>' . $txt['all'] . '</strong>] '; |
||
| 474 | |||
| 475 | // Set start back to 0... |
||
| 476 | $_REQUEST['start'] = 0; |
||
| 477 | } |
||
| 478 | // They aren't using it, but the *option* is there, at least. |
||
| 479 | else |
||
| 480 | $context['page_index'] .= ' <a href="' . $scripturl . '?topic=' . $topic . '.0;all">' . $txt['all'] . '</a> '; |
||
| 481 | } |
||
| 482 | |||
| 483 | // Build the link tree. |
||
| 484 | $context['linktree'][] = array( |
||
| 485 | 'url' => $scripturl . '?topic=' . $topic . '.0', |
||
| 486 | 'name' => $context['topicinfo']['subject'], |
||
| 487 | ); |
||
| 488 | |||
| 489 | // Build a list of this board's moderators. |
||
| 490 | $context['moderators'] = &$board_info['moderators']; |
||
| 491 | $context['moderator_groups'] = &$board_info['moderator_groups']; |
||
| 492 | $context['link_moderators'] = array(); |
||
| 493 | View Code Duplication | if (!empty($board_info['moderators'])) |
|
| 494 | { |
||
| 495 | // Add a link for each moderator... |
||
| 496 | foreach ($board_info['moderators'] as $mod) |
||
| 497 | $context['link_moderators'][] = '<a href="' . $scripturl . '?action=profile;u=' . $mod['id'] . '" title="' . $txt['board_moderator'] . '">' . $mod['name'] . '</a>'; |
||
| 498 | } |
||
| 499 | View Code Duplication | if (!empty($board_info['moderator_groups'])) |
|
| 500 | { |
||
| 501 | // Add a link for each moderator group as well... |
||
| 502 | foreach ($board_info['moderator_groups'] as $mod_group) |
||
| 503 | $context['link_moderators'][] = '<a href="' . $scripturl . '?action=groups;sa=viewmemberes;group=' . $mod_group['id'] . '" title="' . $txt['board_moderator'] . '">' . $mod_group['name'] . '</a>'; |
||
| 504 | } |
||
| 505 | |||
| 506 | View Code Duplication | if (!empty($context['link_moderators'])) |
|
| 507 | { |
||
| 508 | // And show it after the board's name. |
||
| 509 | $context['linktree'][count($context['linktree']) - 2]['extra_after'] = '<span class="board_moderators">(' . (count($context['link_moderators']) == 1 ? $txt['moderator'] : $txt['moderators']) . ': ' . implode(', ', $context['link_moderators']) . ')</span>'; |
||
| 510 | } |
||
| 511 | |||
| 512 | // Information about the current topic... |
||
| 513 | $context['is_locked'] = $context['topicinfo']['locked']; |
||
| 514 | $context['is_sticky'] = $context['topicinfo']['is_sticky']; |
||
| 515 | $context['is_approved'] = $context['topicinfo']['approved']; |
||
| 516 | $context['is_poll'] = $context['topicinfo']['id_poll'] > 0 && $modSettings['pollMode'] == '1' && allowedTo('poll_view'); |
||
| 517 | |||
| 518 | // Did this user start the topic or not? |
||
| 519 | $context['user']['started'] = $user_info['id'] == $context['topicinfo']['id_member_started'] && !$user_info['is_guest']; |
||
| 520 | $context['topic_starter_id'] = $context['topicinfo']['id_member_started']; |
||
| 521 | |||
| 522 | // Set the topic's information for the template. |
||
| 523 | $context['subject'] = $context['topicinfo']['subject']; |
||
| 524 | $context['num_views'] = comma_format($context['topicinfo']['num_views']); |
||
| 525 | $context['num_views_text'] = $context['num_views'] == 1 ? $txt['read_one_time'] : sprintf($txt['read_many_times'], $context['num_views']); |
||
| 526 | $context['mark_unread_time'] = !empty($virtual_msg) ? $virtual_msg : $context['topicinfo']['new_from']; |
||
| 527 | |||
| 528 | // Set a canonical URL for this page. |
||
| 529 | $context['canonical_url'] = $scripturl . '?topic=' . $topic . '.' . ($can_show_all ? '0;all' : $context['start']); |
||
| 530 | |||
| 531 | // For quick reply we need a response prefix in the default forum language. |
||
| 532 | View Code Duplication | if (!isset($context['response_prefix']) && !($context['response_prefix'] = cache_get_data('response_prefix', 600))) |
|
| 533 | { |
||
| 534 | if ($language === $user_info['language']) |
||
| 535 | $context['response_prefix'] = $txt['response_prefix']; |
||
| 536 | else |
||
| 537 | { |
||
| 538 | loadLanguage('index', $language, false); |
||
| 539 | $context['response_prefix'] = $txt['response_prefix']; |
||
| 540 | loadLanguage('index'); |
||
| 541 | } |
||
| 542 | cache_put_data('response_prefix', $context['response_prefix'], 600); |
||
| 543 | } |
||
| 544 | |||
| 545 | // If we want to show event information in the topic, prepare the data. |
||
| 546 | if (allowedTo('calendar_view') && !empty($modSettings['cal_showInTopic']) && !empty($modSettings['cal_enabled'])) |
||
| 547 | { |
||
| 548 | require_once($sourcedir . '/Subs-Calendar.php'); |
||
| 549 | |||
| 550 | // Any calendar information for this topic? |
||
| 551 | $request = $smcFunc['db_query']('', ' |
||
| 552 | SELECT cal.id_event, cal.start_date, cal.end_date, cal.title, cal.id_member, mem.real_name, cal.start_time, cal.end_time, cal.timezone, cal.location |
||
| 553 | FROM {db_prefix}calendar AS cal |
||
| 554 | LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = cal.id_member) |
||
| 555 | WHERE cal.id_topic = {int:current_topic} |
||
| 556 | ORDER BY start_date', |
||
| 557 | array( |
||
| 558 | 'current_topic' => $topic, |
||
| 559 | ) |
||
| 560 | ); |
||
| 561 | $context['linked_calendar_events'] = array(); |
||
| 562 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 563 | { |
||
| 564 | // Get the various time and date properties for this event |
||
| 565 | list($start, $end, $allday, $span, $tz, $tz_abbrev) = buildEventDatetimes($row); |
||
| 566 | |||
| 567 | // Sanity check |
||
| 568 | View Code Duplication | if (!empty($start['error_count']) || !empty($start['warning_count']) || !empty($end['error_count']) || !empty($end['warning_count'])) |
|
| 569 | continue; |
||
| 570 | |||
| 571 | $linked_calendar_event = array( |
||
| 572 | 'id' => $row['id_event'], |
||
| 573 | 'title' => $row['title'], |
||
| 574 | 'can_edit' => allowedTo('calendar_edit_any') || ($row['id_member'] == $user_info['id'] && allowedTo('calendar_edit_own')), |
||
| 575 | 'modify_href' => $scripturl . '?action=post;msg=' . $context['topicinfo']['id_first_msg'] . ';topic=' . $topic . '.0;calendar;eventid=' . $row['id_event'] . ';' . $context['session_var'] . '=' . $context['session_id'], |
||
| 576 | 'can_export' => allowedTo('calendar_edit_any') || ($row['id_member'] == $user_info['id'] && allowedTo('calendar_edit_own')), |
||
| 577 | 'export_href' => $scripturl . '?action=calendar;sa=ical;eventid=' . $row['id_event'] . ';' . $context['session_var'] . '=' . $context['session_id'], |
||
| 578 | 'year' => $start['year'], |
||
| 579 | 'month' => $start['month'], |
||
| 580 | 'day' => $start['day'], |
||
| 581 | 'hour' => !$allday ? $start['hour'] : null, |
||
| 582 | 'minute' => !$allday ? $start['minute'] : null, |
||
| 583 | 'second' => !$allday ? $start['second'] : null, |
||
| 584 | 'start_date' => $row['start_date'], |
||
| 585 | 'start_date_local' => $start['date_local'], |
||
| 586 | 'start_date_orig' => $start['date_orig'], |
||
| 587 | 'start_time' => !$allday ? $row['start_time'] : null, |
||
| 588 | 'start_time_local' => !$allday ? $start['time_local'] : null, |
||
| 589 | 'start_time_orig' => !$allday ? $start['time_orig'] : null, |
||
| 590 | 'start_timestamp' => $start['timestamp'], |
||
| 591 | 'start_iso_gmdate' => $start['iso_gmdate'], |
||
| 592 | 'end_year' => $end['year'], |
||
| 593 | 'end_month' => $end['month'], |
||
| 594 | 'end_day' => $end['day'], |
||
| 595 | 'end_hour' => !$allday ? $end['hour'] : null, |
||
| 596 | 'end_minute' => !$allday ? $end['minute'] : null, |
||
| 597 | 'end_second' => !$allday ? $end['second'] : null, |
||
| 598 | 'end_date' => $row['end_date'], |
||
| 599 | 'end_date_local' => $end['date_local'], |
||
| 600 | 'end_date_orig' => $end['date_orig'], |
||
| 601 | 'end_time' => !$allday ? $row['end_time'] : null, |
||
| 602 | 'end_time_local' => !$allday ? $end['time_local'] : null, |
||
| 603 | 'end_time_orig' => !$allday ? $end['time_orig'] : null, |
||
| 604 | 'end_timestamp' => $end['timestamp'], |
||
| 605 | 'end_iso_gmdate' => $end['iso_gmdate'], |
||
| 606 | 'allday' => $allday, |
||
| 607 | 'tz' => !$allday ? $tz : null, |
||
| 608 | 'tz_abbrev' => !$allday ? $tz_abbrev : null, |
||
| 609 | 'span' => $span, |
||
| 610 | 'location' => $row['location'], |
||
| 611 | 'is_last' => false |
||
| 612 | ); |
||
| 613 | |||
| 614 | $context['linked_calendar_events'][] = $linked_calendar_event; |
||
| 615 | } |
||
| 616 | $smcFunc['db_free_result']($request); |
||
| 617 | |||
| 618 | View Code Duplication | if (!empty($context['linked_calendar_events'])) |
|
| 619 | $context['linked_calendar_events'][count($context['linked_calendar_events']) - 1]['is_last'] = true; |
||
| 620 | } |
||
| 621 | |||
| 622 | // Create the poll info if it exists. |
||
| 623 | if ($context['is_poll']) |
||
| 624 | { |
||
| 625 | // Get the question and if it's locked. |
||
| 626 | $request = $smcFunc['db_query']('', ' |
||
| 627 | SELECT |
||
| 628 | p.question, p.voting_locked, p.hide_results, p.expire_time, p.max_votes, p.change_vote, |
||
| 629 | p.guest_vote, p.id_member, COALESCE(mem.real_name, p.poster_name) AS poster_name, p.num_guest_voters, p.reset_poll |
||
| 630 | FROM {db_prefix}polls AS p |
||
| 631 | LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = p.id_member) |
||
| 632 | WHERE p.id_poll = {int:id_poll} |
||
| 633 | LIMIT 1', |
||
| 634 | array( |
||
| 635 | 'id_poll' => $context['topicinfo']['id_poll'], |
||
| 636 | ) |
||
| 637 | ); |
||
| 638 | $pollinfo = $smcFunc['db_fetch_assoc']($request); |
||
| 639 | $smcFunc['db_free_result']($request); |
||
| 640 | |||
| 641 | $request = $smcFunc['db_query']('', ' |
||
| 642 | SELECT COUNT(DISTINCT id_member) AS total |
||
| 643 | FROM {db_prefix}log_polls |
||
| 644 | WHERE id_poll = {int:id_poll} |
||
| 645 | AND id_member != {int:not_guest}', |
||
| 646 | array( |
||
| 647 | 'id_poll' => $context['topicinfo']['id_poll'], |
||
| 648 | 'not_guest' => 0, |
||
| 649 | ) |
||
| 650 | ); |
||
| 651 | list ($pollinfo['total']) = $smcFunc['db_fetch_row']($request); |
||
| 652 | $smcFunc['db_free_result']($request); |
||
| 653 | |||
| 654 | // Total voters needs to include guest voters |
||
| 655 | $pollinfo['total'] += $pollinfo['num_guest_voters']; |
||
| 656 | |||
| 657 | // Get all the options, and calculate the total votes. |
||
| 658 | $request = $smcFunc['db_query']('', ' |
||
| 659 | SELECT pc.id_choice, pc.label, pc.votes, COALESCE(lp.id_choice, -1) AS voted_this |
||
| 660 | FROM {db_prefix}poll_choices AS pc |
||
| 661 | LEFT JOIN {db_prefix}log_polls AS lp ON (lp.id_choice = pc.id_choice AND lp.id_poll = {int:id_poll} AND lp.id_member = {int:current_member} AND lp.id_member != {int:not_guest}) |
||
| 662 | WHERE pc.id_poll = {int:id_poll}', |
||
| 663 | array( |
||
| 664 | 'current_member' => $user_info['id'], |
||
| 665 | 'id_poll' => $context['topicinfo']['id_poll'], |
||
| 666 | 'not_guest' => 0, |
||
| 667 | ) |
||
| 668 | ); |
||
| 669 | $pollOptions = array(); |
||
| 670 | $realtotal = 0; |
||
| 671 | $pollinfo['has_voted'] = false; |
||
| 672 | View Code Duplication | while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
| 673 | { |
||
| 674 | censorText($row['label']); |
||
| 675 | $pollOptions[$row['id_choice']] = $row; |
||
| 676 | $realtotal += $row['votes']; |
||
| 677 | $pollinfo['has_voted'] |= $row['voted_this'] != -1; |
||
| 678 | } |
||
| 679 | $smcFunc['db_free_result']($request); |
||
| 680 | |||
| 681 | // Got we multi choice? |
||
| 682 | if ($pollinfo['max_votes'] > 1) |
||
| 683 | $realtotal = $pollinfo['total']; |
||
| 684 | |||
| 685 | // If this is a guest we need to do our best to work out if they have voted, and what they voted for. |
||
| 686 | View Code Duplication | if ($user_info['is_guest'] && $pollinfo['guest_vote'] && allowedTo('poll_vote')) |
|
| 687 | { |
||
| 688 | if (!empty($_COOKIE['guest_poll_vote']) && preg_match('~^[0-9,;]+$~', $_COOKIE['guest_poll_vote']) && strpos($_COOKIE['guest_poll_vote'], ';' . $context['topicinfo']['id_poll'] . ',') !== false) |
||
| 689 | { |
||
| 690 | // ;id,timestamp,[vote,vote...]; etc |
||
| 691 | $guestinfo = explode(';', $_COOKIE['guest_poll_vote']); |
||
| 692 | // Find the poll we're after. |
||
| 693 | foreach ($guestinfo as $i => $guestvoted) |
||
| 694 | { |
||
| 695 | $guestvoted = explode(',', $guestvoted); |
||
| 696 | if ($guestvoted[0] == $context['topicinfo']['id_poll']) |
||
| 697 | break; |
||
| 698 | } |
||
| 699 | // Has the poll been reset since guest voted? |
||
| 700 | if ($pollinfo['reset_poll'] > $guestvoted[1]) |
||
| 701 | { |
||
| 702 | // Remove the poll info from the cookie to allow guest to vote again |
||
| 703 | unset($guestinfo[$i]); |
||
| 704 | if (!empty($guestinfo)) |
||
| 705 | $_COOKIE['guest_poll_vote'] = ';' . implode(';', $guestinfo); |
||
| 706 | else |
||
| 707 | unset($_COOKIE['guest_poll_vote']); |
||
| 708 | } |
||
| 709 | else |
||
| 710 | { |
||
| 711 | // What did they vote for? |
||
| 712 | unset($guestvoted[0], $guestvoted[1]); |
||
| 713 | foreach ($pollOptions as $choice => $details) |
||
| 714 | { |
||
| 715 | $pollOptions[$choice]['voted_this'] = in_array($choice, $guestvoted) ? 1 : -1; |
||
|
0 ignored issues
–
show
|
|||
| 716 | $pollinfo['has_voted'] |= $pollOptions[$choice]['voted_this'] != -1; |
||
| 717 | } |
||
| 718 | unset($choice, $details, $guestvoted); |
||
| 719 | } |
||
| 720 | unset($guestinfo, $guestvoted, $i); |
||
| 721 | } |
||
| 722 | } |
||
| 723 | |||
| 724 | // Set up the basic poll information. |
||
| 725 | $context['poll'] = array( |
||
| 726 | 'id' => $context['topicinfo']['id_poll'], |
||
| 727 | 'image' => 'normal_' . (empty($pollinfo['voting_locked']) ? 'poll' : 'locked_poll'), |
||
| 728 | 'question' => parse_bbc($pollinfo['question']), |
||
| 729 | 'total_votes' => $pollinfo['total'], |
||
| 730 | 'change_vote' => !empty($pollinfo['change_vote']), |
||
| 731 | 'is_locked' => !empty($pollinfo['voting_locked']), |
||
| 732 | 'options' => array(), |
||
| 733 | 'lock' => allowedTo('poll_lock_any') || ($context['user']['started'] && allowedTo('poll_lock_own')), |
||
| 734 | 'edit' => allowedTo('poll_edit_any') || ($context['user']['started'] && allowedTo('poll_edit_own')), |
||
| 735 | 'remove' => allowedTo('poll_remove_any') || ($context['user']['started'] && allowedTo('poll_remove_own')), |
||
| 736 | 'allowed_warning' => $pollinfo['max_votes'] > 1 ? sprintf($txt['poll_options6'], min(count($pollOptions), $pollinfo['max_votes'])) : '', |
||
| 737 | 'is_expired' => !empty($pollinfo['expire_time']) && $pollinfo['expire_time'] < time(), |
||
| 738 | 'expire_time' => !empty($pollinfo['expire_time']) ? timeformat($pollinfo['expire_time']) : 0, |
||
| 739 | 'has_voted' => !empty($pollinfo['has_voted']), |
||
| 740 | 'starter' => array( |
||
| 741 | 'id' => $pollinfo['id_member'], |
||
| 742 | 'name' => $row['poster_name'], |
||
| 743 | 'href' => $pollinfo['id_member'] == 0 ? '' : $scripturl . '?action=profile;u=' . $pollinfo['id_member'], |
||
| 744 | 'link' => $pollinfo['id_member'] == 0 ? $row['poster_name'] : '<a href="' . $scripturl . '?action=profile;u=' . $pollinfo['id_member'] . '">' . $row['poster_name'] . '</a>' |
||
| 745 | ) |
||
| 746 | ); |
||
| 747 | |||
| 748 | // Make the lock, edit and remove permissions defined above more directly accessible. |
||
| 749 | $context['allow_lock_poll'] = $context['poll']['lock']; |
||
| 750 | $context['allow_edit_poll'] = $context['poll']['edit']; |
||
| 751 | $context['can_remove_poll'] = $context['poll']['remove']; |
||
| 752 | |||
| 753 | // You're allowed to vote if: |
||
| 754 | // 1. the poll did not expire, and |
||
| 755 | // 2. you're either not a guest OR guest voting is enabled... and |
||
| 756 | // 3. you're not trying to view the results, and |
||
| 757 | // 4. the poll is not locked, and |
||
| 758 | // 5. you have the proper permissions, and |
||
| 759 | // 6. you haven't already voted before. |
||
| 760 | $context['allow_vote'] = !$context['poll']['is_expired'] && (!$user_info['is_guest'] || ($pollinfo['guest_vote'] && allowedTo('poll_vote'))) && empty($pollinfo['voting_locked']) && allowedTo('poll_vote') && !$context['poll']['has_voted']; |
||
| 761 | |||
| 762 | // You're allowed to view the results if: |
||
| 763 | // 1. you're just a super-nice-guy, or |
||
| 764 | // 2. anyone can see them (hide_results == 0), or |
||
| 765 | // 3. you can see them after you voted (hide_results == 1), or |
||
| 766 | // 4. you've waited long enough for the poll to expire. (whether hide_results is 1 or 2.) |
||
| 767 | $context['allow_results_view'] = allowedTo('moderate_board') || $pollinfo['hide_results'] == 0 || ($pollinfo['hide_results'] == 1 && $context['poll']['has_voted']) || $context['poll']['is_expired']; |
||
| 768 | |||
| 769 | // Show the results if: |
||
| 770 | // 1. You're allowed to see them (see above), and |
||
| 771 | // 2. $_REQUEST['viewresults'] or $_REQUEST['viewResults'] is set |
||
| 772 | $context['poll']['show_results'] = $context['allow_results_view'] && (isset($_REQUEST['viewresults']) || isset($_REQUEST['viewResults'])); |
||
| 773 | |||
| 774 | // Show the button if: |
||
| 775 | // 1. You can vote in the poll (see above), and |
||
| 776 | // 2. Results are visible to everyone (hidden = 0), and |
||
| 777 | // 3. You aren't already viewing the results |
||
| 778 | $context['show_view_results_button'] = $context['allow_vote'] && $context['allow_results_view'] && !$context['poll']['show_results']; |
||
| 779 | |||
| 780 | // You're allowed to change your vote if: |
||
| 781 | // 1. the poll did not expire, and |
||
| 782 | // 2. you're not a guest... and |
||
| 783 | // 3. the poll is not locked, and |
||
| 784 | // 4. you have the proper permissions, and |
||
| 785 | // 5. you have already voted, and |
||
| 786 | // 6. the poll creator has said you can! |
||
| 787 | $context['allow_change_vote'] = !$context['poll']['is_expired'] && !$user_info['is_guest'] && empty($pollinfo['voting_locked']) && allowedTo('poll_vote') && $context['poll']['has_voted'] && $context['poll']['change_vote']; |
||
| 788 | |||
| 789 | // You're allowed to return to voting options if: |
||
| 790 | // 1. you are (still) allowed to vote. |
||
| 791 | // 2. you are currently seeing the results. |
||
| 792 | $context['allow_return_vote'] = $context['allow_vote'] && $context['poll']['show_results']; |
||
| 793 | |||
| 794 | // Calculate the percentages and bar lengths... |
||
| 795 | $divisor = $realtotal == 0 ? 1 : $realtotal; |
||
| 796 | |||
| 797 | // Determine if a decimal point is needed in order for the options to add to 100%. |
||
| 798 | $precision = $realtotal == 100 ? 0 : 1; |
||
| 799 | |||
| 800 | // Now look through each option, and... |
||
| 801 | foreach ($pollOptions as $i => $option) |
||
| 802 | { |
||
| 803 | // First calculate the percentage, and then the width of the bar... |
||
| 804 | $bar = round(($option['votes'] * 100) / $divisor, $precision); |
||
| 805 | $barWide = $bar == 0 ? 1 : floor(($bar * 8) / 3); |
||
| 806 | |||
| 807 | // Now add it to the poll's contextual theme data. |
||
| 808 | $context['poll']['options'][$i] = array( |
||
| 809 | 'id' => 'options-' . $i, |
||
| 810 | 'percent' => $bar, |
||
| 811 | 'votes' => $option['votes'], |
||
| 812 | 'voted_this' => $option['voted_this'] != -1, |
||
| 813 | 'bar_ndt' => $bar > 0 ? '<div class="bar" style="width: ' . $bar . '%;"></div>' : '', |
||
| 814 | 'bar_width' => $barWide, |
||
| 815 | 'option' => parse_bbc($option['label']), |
||
| 816 | 'vote_button' => '<input type="' . ($pollinfo['max_votes'] > 1 ? 'checkbox' : 'radio') . '" name="options[]" id="options-' . $i . '" value="' . $i . '" class="input_' . ($pollinfo['max_votes'] > 1 ? 'check' : 'radio') . '">' |
||
| 817 | ); |
||
| 818 | } |
||
| 819 | |||
| 820 | // Build the poll moderation button array. |
||
| 821 | $context['poll_buttons'] = array(); |
||
| 822 | |||
| 823 | View Code Duplication | if ($context['allow_return_vote']) |
|
| 824 | $context['poll_buttons']['vote'] = array('text' => 'poll_return_vote', 'image' => 'poll_options.png', 'url' => $scripturl . '?topic=' . $context['current_topic'] . '.' . $context['start']); |
||
| 825 | |||
| 826 | View Code Duplication | if ($context['show_view_results_button']) |
|
| 827 | $context['poll_buttons']['results'] = array('text' => 'poll_results', 'image' => 'poll_results.png', 'url' => $scripturl . '?topic=' . $context['current_topic'] . '.' . $context['start'] . ';viewresults'); |
||
| 828 | |||
| 829 | View Code Duplication | if ($context['allow_change_vote']) |
|
| 830 | $context['poll_buttons']['change_vote'] = array('text' => 'poll_change_vote', 'image' => 'poll_change_vote.png', 'url' => $scripturl . '?action=vote;topic=' . $context['current_topic'] . '.' . $context['start'] . ';poll=' . $context['poll']['id'] . ';' . $context['session_var'] . '=' . $context['session_id']); |
||
| 831 | |||
| 832 | View Code Duplication | if ($context['allow_lock_poll']) |
|
| 833 | $context['poll_buttons']['lock'] = array('text' => (!$context['poll']['is_locked'] ? 'poll_lock' : 'poll_unlock'), 'image' => 'poll_lock.png', 'url' => $scripturl . '?action=lockvoting;topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']); |
||
| 834 | |||
| 835 | View Code Duplication | if ($context['allow_edit_poll']) |
|
| 836 | $context['poll_buttons']['edit'] = array('text' => 'poll_edit', 'image' => 'poll_edit.png', 'url' => $scripturl . '?action=editpoll;topic=' . $context['current_topic'] . '.' . $context['start']); |
||
| 837 | |||
| 838 | if ($context['can_remove_poll']) |
||
| 839 | $context['poll_buttons']['remove_poll'] = array('text' => 'poll_remove', 'image' => 'admin_remove_poll.png', 'custom' => 'data-confirm="' . $txt['poll_remove_warn'] . '"', 'class' => 'you_sure', 'url' => $scripturl . '?action=removepoll;topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']); |
||
| 840 | |||
| 841 | // Allow mods to add additional buttons here |
||
| 842 | call_integration_hook('integrate_poll_buttons'); |
||
| 843 | } |
||
| 844 | |||
| 845 | // Calculate the fastest way to get the messages! |
||
| 846 | $ascending = empty($options['view_newest_first']); |
||
| 847 | $start = $_REQUEST['start']; |
||
| 848 | $limit = $context['messages_per_page']; |
||
| 849 | $firstIndex = 0; |
||
| 850 | if ($start >= $context['total_visible_posts'] / 2 && $context['messages_per_page'] != -1) |
||
| 851 | { |
||
| 852 | $ascending = !$ascending; |
||
| 853 | $limit = $context['total_visible_posts'] <= $start + $limit ? $context['total_visible_posts'] - $start : $limit; |
||
| 854 | $start = $context['total_visible_posts'] <= $start + $limit ? 0 : $context['total_visible_posts'] - $start - $limit; |
||
| 855 | $firstIndex = $limit - 1; |
||
| 856 | } |
||
| 857 | |||
| 858 | // Get each post and poster in this topic. |
||
| 859 | $request = $smcFunc['db_query']('', ' |
||
| 860 | SELECT id_msg, id_member, approved |
||
| 861 | FROM {db_prefix}messages |
||
| 862 | WHERE id_topic = {int:current_topic}' . (!$modSettings['postmod_active'] || $approve_posts ? '' : ' |
||
| 863 | AND (approved = {int:is_approved}' . ($user_info['is_guest'] ? '' : ' OR id_member = {int:current_member}') . ')') . ' |
||
| 864 | ORDER BY id_msg ' . ($ascending ? '' : 'DESC') . ($context['messages_per_page'] == -1 ? '' : ' |
||
| 865 | LIMIT {int:start}, {int:max}'), |
||
| 866 | array( |
||
| 867 | 'current_member' => $user_info['id'], |
||
| 868 | 'current_topic' => $topic, |
||
| 869 | 'is_approved' => 1, |
||
| 870 | 'blank_id_member' => 0, |
||
| 871 | 'start' => $start, |
||
| 872 | 'max' => $limit, |
||
| 873 | ) |
||
| 874 | ); |
||
| 875 | |||
| 876 | $messages = array(); |
||
| 877 | $all_posters = array(); |
||
| 878 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 879 | { |
||
| 880 | if (!empty($row['id_member'])) |
||
| 881 | $all_posters[$row['id_msg']] = $row['id_member']; |
||
| 882 | $messages[] = $row['id_msg']; |
||
| 883 | } |
||
| 884 | $smcFunc['db_free_result']($request); |
||
| 885 | $posters = array_unique($all_posters); |
||
| 886 | |||
| 887 | call_integration_hook('integrate_display_message_list', array(&$messages, &$posters)); |
||
| 888 | |||
| 889 | // Guests can't mark topics read or for notifications, just can't sorry. |
||
| 890 | if (!$user_info['is_guest'] && !empty($messages)) |
||
| 891 | { |
||
| 892 | $mark_at_msg = max($messages); |
||
| 893 | if ($mark_at_msg >= $context['topicinfo']['id_last_msg']) |
||
| 894 | $mark_at_msg = $modSettings['maxMsgID']; |
||
| 895 | if ($mark_at_msg >= $context['topicinfo']['new_from']) |
||
| 896 | { |
||
| 897 | $smcFunc['db_insert']($context['topicinfo']['new_from'] == 0 ? 'ignore' : 'replace', |
||
| 898 | '{db_prefix}log_topics', |
||
| 899 | array( |
||
| 900 | 'id_member' => 'int', 'id_topic' => 'int', 'id_msg' => 'int', 'unwatched' => 'int', |
||
| 901 | ), |
||
| 902 | array( |
||
| 903 | $user_info['id'], $topic, $mark_at_msg, $context['topicinfo']['unwatched'], |
||
| 904 | ), |
||
| 905 | array('id_member', 'id_topic') |
||
| 906 | ); |
||
| 907 | } |
||
| 908 | |||
| 909 | // Check for notifications on this topic OR board. |
||
| 910 | $request = $smcFunc['db_query']('', ' |
||
| 911 | SELECT sent, id_topic |
||
| 912 | FROM {db_prefix}log_notify |
||
| 913 | WHERE (id_topic = {int:current_topic} OR id_board = {int:current_board}) |
||
| 914 | AND id_member = {int:current_member} |
||
| 915 | LIMIT 2', |
||
| 916 | array( |
||
| 917 | 'current_board' => $board, |
||
| 918 | 'current_member' => $user_info['id'], |
||
| 919 | 'current_topic' => $topic, |
||
| 920 | ) |
||
| 921 | ); |
||
| 922 | $do_once = true; |
||
| 923 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 924 | { |
||
| 925 | // Find if this topic is marked for notification... |
||
| 926 | if (!empty($row['id_topic'])) |
||
| 927 | $context['is_marked_notify'] = true; |
||
| 928 | |||
| 929 | // Only do this once, but mark the notifications as "not sent yet" for next time. |
||
| 930 | if (!empty($row['sent']) && $do_once) |
||
| 931 | { |
||
| 932 | $smcFunc['db_query']('', ' |
||
| 933 | UPDATE {db_prefix}log_notify |
||
| 934 | SET sent = {int:is_not_sent} |
||
| 935 | WHERE (id_topic = {int:current_topic} OR id_board = {int:current_board}) |
||
| 936 | AND id_member = {int:current_member}', |
||
| 937 | array( |
||
| 938 | 'current_board' => $board, |
||
| 939 | 'current_member' => $user_info['id'], |
||
| 940 | 'current_topic' => $topic, |
||
| 941 | 'is_not_sent' => 0, |
||
| 942 | ) |
||
| 943 | ); |
||
| 944 | $do_once = false; |
||
| 945 | } |
||
| 946 | } |
||
| 947 | |||
| 948 | // Have we recently cached the number of new topics in this board, and it's still a lot? |
||
| 949 | if (isset($_REQUEST['topicseen']) && isset($_SESSION['topicseen_cache'][$board]) && $_SESSION['topicseen_cache'][$board] > 5) |
||
| 950 | $_SESSION['topicseen_cache'][$board]--; |
||
| 951 | // Mark board as seen if this is the only new topic. |
||
| 952 | elseif (isset($_REQUEST['topicseen'])) |
||
| 953 | { |
||
| 954 | // Use the mark read tables... and the last visit to figure out if this should be read or not. |
||
| 955 | $request = $smcFunc['db_query']('', ' |
||
| 956 | SELECT COUNT(*) |
||
| 957 | FROM {db_prefix}topics AS t |
||
| 958 | LEFT JOIN {db_prefix}log_boards AS lb ON (lb.id_board = {int:current_board} AND lb.id_member = {int:current_member}) |
||
| 959 | LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member}) |
||
| 960 | WHERE t.id_board = {int:current_board} |
||
| 961 | AND t.id_last_msg > COALESCE(lb.id_msg, 0) |
||
| 962 | AND t.id_last_msg > COALESCE(lt.id_msg, 0)' . (empty($_SESSION['id_msg_last_visit']) ? '' : ' |
||
| 963 | AND t.id_last_msg > {int:id_msg_last_visit}'), |
||
| 964 | array( |
||
| 965 | 'current_board' => $board, |
||
| 966 | 'current_member' => $user_info['id'], |
||
| 967 | 'id_msg_last_visit' => (int) $_SESSION['id_msg_last_visit'], |
||
| 968 | ) |
||
| 969 | ); |
||
| 970 | list ($numNewTopics) = $smcFunc['db_fetch_row']($request); |
||
| 971 | $smcFunc['db_free_result']($request); |
||
| 972 | |||
| 973 | // If there're no real new topics in this board, mark the board as seen. |
||
| 974 | if (empty($numNewTopics)) |
||
| 975 | $_REQUEST['boardseen'] = true; |
||
| 976 | else |
||
| 977 | $_SESSION['topicseen_cache'][$board] = $numNewTopics; |
||
| 978 | } |
||
| 979 | // Probably one less topic - maybe not, but even if we decrease this too fast it will only make us look more often. |
||
| 980 | elseif (isset($_SESSION['topicseen_cache'][$board])) |
||
| 981 | $_SESSION['topicseen_cache'][$board]--; |
||
| 982 | |||
| 983 | // Mark board as seen if we came using last post link from BoardIndex. (or other places...) |
||
| 984 | if (isset($_REQUEST['boardseen'])) |
||
| 985 | { |
||
| 986 | $smcFunc['db_insert']('replace', |
||
| 987 | '{db_prefix}log_boards', |
||
| 988 | array('id_msg' => 'int', 'id_member' => 'int', 'id_board' => 'int'), |
||
| 989 | array($modSettings['maxMsgID'], $user_info['id'], $board), |
||
| 990 | array('id_member', 'id_board') |
||
| 991 | ); |
||
| 992 | } |
||
| 993 | } |
||
| 994 | |||
| 995 | // Get notification preferences |
||
| 996 | $context['topicinfo']['notify_prefs'] = array(); |
||
| 997 | if (!empty($user_info['id'])) |
||
| 998 | { |
||
| 999 | require_once($sourcedir . '/Subs-Notify.php'); |
||
| 1000 | $prefs = getNotifyPrefs($user_info['id'], array('topic_notify', 'topic_notify_' . $context['current_topic']), true); |
||
| 1001 | $pref = !empty($prefs[$user_info['id']]) && $context['is_marked_notify'] ? $prefs[$user_info['id']] : array(); |
||
| 1002 | $context['topicinfo']['notify_prefs'] = array( |
||
| 1003 | 'is_custom' => isset($pref['topic_notify_' . $topic]), |
||
| 1004 | 'pref' => isset($pref['topic_notify_' . $context['current_topic']]) ? $pref['topic_notify_' . $context['current_topic']] : (!empty($pref['topic_notify']) ? $pref['topic_notify'] : 0), |
||
| 1005 | ); |
||
| 1006 | } |
||
| 1007 | |||
| 1008 | $context['topic_notification'] = !empty($user_info['id']) ? $context['topicinfo']['notify_prefs'] : array(); |
||
| 1009 | // 0 => unwatched, 1 => normal, 2 => receive alerts, 3 => receive emails |
||
| 1010 | $context['topic_notification_mode'] = !$user_info['is_guest'] ? ($context['topic_unwatched'] ? 0 : ($context['topicinfo']['notify_prefs']['pref'] & 0x02 ? 3 : ($context['topicinfo']['notify_prefs']['pref'] & 0x01 ? 2 : 1))) : 0; |
||
| 1011 | |||
| 1012 | $context['loaded_attachments'] = array(); |
||
| 1013 | |||
| 1014 | // If there _are_ messages here... (probably an error otherwise :!) |
||
| 1015 | if (!empty($messages)) |
||
| 1016 | { |
||
| 1017 | // Fetch attachments. |
||
| 1018 | if (!empty($modSettings['attachmentEnable']) && allowedTo('view_attachments')) |
||
| 1019 | { |
||
| 1020 | $request = $smcFunc['db_query']('', ' |
||
| 1021 | SELECT |
||
| 1022 | a.id_attach, a.id_folder, a.id_msg, a.filename, a.file_hash, COALESCE(a.size, 0) AS filesize, a.downloads, a.approved, |
||
| 1023 | a.width, a.height' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : ', |
||
| 1024 | COALESCE(thumb.id_attach, 0) AS id_thumb, thumb.width AS thumb_width, thumb.height AS thumb_height') . ' |
||
| 1025 | FROM {db_prefix}attachments AS a' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : ' |
||
| 1026 | LEFT JOIN {db_prefix}attachments AS thumb ON (thumb.id_attach = a.id_thumb)') . ' |
||
| 1027 | WHERE a.id_msg IN ({array_int:message_list}) |
||
| 1028 | AND a.attachment_type = {int:attachment_type}', |
||
| 1029 | array( |
||
| 1030 | 'message_list' => $messages, |
||
| 1031 | 'attachment_type' => 0, |
||
| 1032 | 'is_approved' => 1, |
||
| 1033 | ) |
||
| 1034 | ); |
||
| 1035 | $temp = array(); |
||
| 1036 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 1037 | { |
||
| 1038 | View Code Duplication | if (!$row['approved'] && $modSettings['postmod_active'] && !allowedTo('approve_posts') && (!isset($all_posters[$row['id_msg']]) || $all_posters[$row['id_msg']] != $user_info['id'])) |
|
| 1039 | continue; |
||
| 1040 | |||
| 1041 | $temp[$row['id_attach']] = $row; |
||
| 1042 | $temp[$row['id_attach']]['topic'] = $topic; |
||
| 1043 | $temp[$row['id_attach']]['board'] = $board; |
||
| 1044 | |||
| 1045 | if (!isset($context['loaded_attachments'][$row['id_msg']])) |
||
| 1046 | $context['loaded_attachments'][$row['id_msg']] = array(); |
||
| 1047 | } |
||
| 1048 | $smcFunc['db_free_result']($request); |
||
| 1049 | |||
| 1050 | // This is better than sorting it with the query... |
||
| 1051 | ksort($temp); |
||
| 1052 | |||
| 1053 | foreach ($temp as $row) |
||
| 1054 | $context['loaded_attachments'][$row['id_msg']][] = $row; |
||
| 1055 | } |
||
| 1056 | |||
| 1057 | $msg_parameters = array( |
||
| 1058 | 'message_list' => $messages, |
||
| 1059 | 'new_from' => $context['topicinfo']['new_from'], |
||
| 1060 | ); |
||
| 1061 | $msg_selects = array(); |
||
| 1062 | $msg_tables = array(); |
||
| 1063 | call_integration_hook('integrate_query_message', array(&$msg_selects, &$msg_tables, &$msg_parameters)); |
||
| 1064 | |||
| 1065 | // What? It's not like it *couldn't* be only guests in this topic... |
||
| 1066 | loadMemberData($posters); |
||
| 1067 | $messages_request = $smcFunc['db_query']('', ' |
||
| 1068 | SELECT |
||
| 1069 | id_msg, icon, subject, poster_time, poster_ip, id_member, modified_time, modified_name, modified_reason, body, |
||
| 1070 | smileys_enabled, poster_name, poster_email, approved, likes, |
||
| 1071 | id_msg_modified < {int:new_from} AS is_read |
||
| 1072 | ' . (!empty($msg_selects) ? (', ' . implode(', ', $msg_selects)) : '') . ' |
||
| 1073 | FROM {db_prefix}messages |
||
| 1074 | ' . (!empty($msg_tables) ? implode("\n\t", $msg_tables) : '') . ' |
||
| 1075 | WHERE id_msg IN ({array_int:message_list}) |
||
| 1076 | ORDER BY id_msg' . (empty($options['view_newest_first']) ? '' : ' DESC'), |
||
| 1077 | $msg_parameters |
||
| 1078 | ); |
||
| 1079 | |||
| 1080 | // And the likes |
||
| 1081 | if (!empty($modSettings['enable_likes'])) |
||
| 1082 | $context['my_likes'] = $context['user']['is_guest'] ? array() : prepareLikesContext($topic); |
||
| 1083 | |||
| 1084 | // Go to the last message if the given time is beyond the time of the last message. |
||
| 1085 | View Code Duplication | if (isset($context['start_from']) && $context['start_from'] >= $context['topicinfo']['num_replies']) |
|
| 1086 | $context['start_from'] = $context['topicinfo']['num_replies']; |
||
| 1087 | |||
| 1088 | // Since the anchor information is needed on the top of the page we load these variables beforehand. |
||
| 1089 | $context['first_message'] = isset($messages[$firstIndex]) ? $messages[$firstIndex] : $messages[0]; |
||
| 1090 | if (empty($options['view_newest_first'])) |
||
| 1091 | $context['first_new_message'] = isset($context['start_from']) && $_REQUEST['start'] == $context['start_from']; |
||
| 1092 | View Code Duplication | else |
|
| 1093 | $context['first_new_message'] = isset($context['start_from']) && $_REQUEST['start'] == $context['topicinfo']['num_replies'] - $context['start_from']; |
||
| 1094 | } |
||
| 1095 | else |
||
| 1096 | { |
||
| 1097 | $messages_request = false; |
||
| 1098 | $context['first_message'] = 0; |
||
| 1099 | $context['first_new_message'] = false; |
||
| 1100 | |||
| 1101 | $context['likes'] = array(); |
||
| 1102 | } |
||
| 1103 | |||
| 1104 | $context['jump_to'] = array( |
||
| 1105 | 'label' => addslashes(un_htmlspecialchars($txt['jump_to'])), |
||
| 1106 | 'board_name' => $smcFunc['htmlspecialchars'](strtr(strip_tags($board_info['name']), array('&' => '&'))), |
||
| 1107 | 'child_level' => $board_info['child_level'], |
||
| 1108 | ); |
||
| 1109 | |||
| 1110 | // Set the callback. (do you REALIZE how much memory all the messages would take?!?) |
||
| 1111 | // This will be called from the template. |
||
| 1112 | $context['get_message'] = 'prepareDisplayContext'; |
||
| 1113 | |||
| 1114 | // Now set all the wonderful, wonderful permissions... like moderation ones... |
||
| 1115 | $common_permissions = array( |
||
| 1116 | 'can_approve' => 'approve_posts', |
||
| 1117 | 'can_ban' => 'manage_bans', |
||
| 1118 | 'can_sticky' => 'make_sticky', |
||
| 1119 | 'can_merge' => 'merge_any', |
||
| 1120 | 'can_split' => 'split_any', |
||
| 1121 | 'calendar_post' => 'calendar_post', |
||
| 1122 | 'can_send_pm' => 'pm_send', |
||
| 1123 | 'can_report_moderator' => 'report_any', |
||
| 1124 | 'can_moderate_forum' => 'moderate_forum', |
||
| 1125 | 'can_issue_warning' => 'issue_warning', |
||
| 1126 | 'can_restore_topic' => 'move_any', |
||
| 1127 | 'can_restore_msg' => 'move_any', |
||
| 1128 | 'can_see_likes' => 'likes_view', |
||
| 1129 | 'can_like' => 'likes_like', |
||
| 1130 | ); |
||
| 1131 | foreach ($common_permissions as $contextual => $perm) |
||
| 1132 | $context[$contextual] = allowedTo($perm); |
||
| 1133 | |||
| 1134 | // Permissions with _any/_own versions. $context[YYY] => ZZZ_any/_own. |
||
| 1135 | $anyown_permissions = array( |
||
| 1136 | 'can_move' => 'move', |
||
| 1137 | 'can_lock' => 'lock', |
||
| 1138 | 'can_delete' => 'remove', |
||
| 1139 | 'can_add_poll' => 'poll_add', |
||
| 1140 | 'can_remove_poll' => 'poll_remove', |
||
| 1141 | 'can_reply' => 'post_reply', |
||
| 1142 | 'can_reply_unapproved' => 'post_unapproved_replies', |
||
| 1143 | 'can_view_warning' => 'profile_warning', |
||
| 1144 | ); |
||
| 1145 | foreach ($anyown_permissions as $contextual => $perm) |
||
| 1146 | $context[$contextual] = allowedTo($perm . '_any') || ($context['user']['started'] && allowedTo($perm . '_own')); |
||
| 1147 | |||
| 1148 | if (!$user_info['is_admin'] && !$modSettings['topic_move_any']) |
||
| 1149 | { |
||
| 1150 | // We'll use this in a minute |
||
| 1151 | $boards_allowed = array_diff(boardsAllowedTo('post_new'), array($board)); |
||
| 1152 | |||
| 1153 | /* You can't move this unless you have permission |
||
| 1154 | to start new topics on at least one other board */ |
||
| 1155 | $context['can_move'] &= count($boards_allowed) > 1; |
||
| 1156 | } |
||
| 1157 | |||
| 1158 | // If a topic is locked, you can't remove it unless it's yours and you locked it or you can lock_any |
||
| 1159 | if ($context['topicinfo']['locked']) |
||
| 1160 | { |
||
| 1161 | $context['can_delete'] &= (($context['topicinfo']['locked'] == 1 && $context['user']['started']) || allowedTo('lock_any')); |
||
| 1162 | } |
||
| 1163 | |||
| 1164 | // Cleanup all the permissions with extra stuff... |
||
| 1165 | $context['can_mark_notify'] = !$context['user']['is_guest']; |
||
| 1166 | $context['calendar_post'] &= !empty($modSettings['cal_enabled']); |
||
| 1167 | $context['can_add_poll'] &= $modSettings['pollMode'] == '1' && $context['topicinfo']['id_poll'] <= 0; |
||
| 1168 | $context['can_remove_poll'] &= $modSettings['pollMode'] == '1' && $context['topicinfo']['id_poll'] > 0; |
||
| 1169 | $context['can_reply'] &= empty($context['topicinfo']['locked']) || allowedTo('moderate_board'); |
||
| 1170 | $context['can_reply_unapproved'] &= $modSettings['postmod_active'] && (empty($context['topicinfo']['locked']) || allowedTo('moderate_board')); |
||
| 1171 | $context['can_issue_warning'] &= $modSettings['warning_settings'][0] == 1; |
||
| 1172 | // Handle approval flags... |
||
| 1173 | $context['can_reply_approved'] = $context['can_reply']; |
||
| 1174 | $context['can_reply'] |= $context['can_reply_unapproved']; |
||
| 1175 | $context['can_quote'] = $context['can_reply'] && (empty($modSettings['disabledBBC']) || !in_array('quote', explode(',', $modSettings['disabledBBC']))); |
||
| 1176 | $context['can_mark_unread'] = !$user_info['is_guest']; |
||
| 1177 | $context['can_unwatch'] = !$user_info['is_guest']; |
||
| 1178 | $context['can_set_notify'] = !$user_info['is_guest']; |
||
| 1179 | |||
| 1180 | $context['can_print'] = empty($modSettings['disable_print_topic']); |
||
| 1181 | |||
| 1182 | // Start this off for quick moderation - it will be or'd for each post. |
||
| 1183 | $context['can_remove_post'] = allowedTo('delete_any') || (allowedTo('delete_replies') && $context['user']['started']); |
||
| 1184 | |||
| 1185 | // Can restore topic? That's if the topic is in the recycle board and has a previous restore state. |
||
| 1186 | $context['can_restore_topic'] &= !empty($board_info['recycle']) && !empty($context['topicinfo']['id_previous_board']); |
||
| 1187 | $context['can_restore_msg'] &= !empty($board_info['recycle']) && !empty($context['topicinfo']['id_previous_topic']); |
||
| 1188 | |||
| 1189 | // Check if the draft functions are enabled and that they have permission to use them (for quick reply.) |
||
| 1190 | $context['drafts_save'] = !empty($modSettings['drafts_post_enabled']) && allowedTo('post_draft') && $context['can_reply']; |
||
| 1191 | $context['drafts_autosave'] = !empty($context['drafts_save']) && !empty($modSettings['drafts_autosave_enabled']); |
||
| 1192 | if (!empty($context['drafts_save'])) |
||
| 1193 | loadLanguage('Drafts'); |
||
| 1194 | |||
| 1195 | // When was the last time this topic was replied to? Should we warn them about it? |
||
| 1196 | if (!empty($modSettings['oldTopicDays']) && ($context['can_reply'] || $context['can_reply_unapproved']) && empty($context['topicinfo']['is_sticky'])) |
||
| 1197 | { |
||
| 1198 | $request = $smcFunc['db_query']('', ' |
||
| 1199 | SELECT poster_time |
||
| 1200 | FROM {db_prefix}messages |
||
| 1201 | WHERE id_msg = {int:id_last_msg} |
||
| 1202 | LIMIT 1', |
||
| 1203 | array( |
||
| 1204 | 'id_last_msg' => $context['topicinfo']['id_last_msg'], |
||
| 1205 | ) |
||
| 1206 | ); |
||
| 1207 | |||
| 1208 | list ($lastPostTime) = $smcFunc['db_fetch_row']($request); |
||
| 1209 | $smcFunc['db_free_result']($request); |
||
| 1210 | |||
| 1211 | $context['oldTopicError'] = $lastPostTime + $modSettings['oldTopicDays'] * 86400 < time(); |
||
| 1212 | } |
||
| 1213 | |||
| 1214 | // You can't link an existing topic to the calendar unless you can modify the first post... |
||
| 1215 | $context['calendar_post'] &= allowedTo('modify_any') || (allowedTo('modify_own') && $context['user']['started']); |
||
| 1216 | |||
| 1217 | // Load up the "double post" sequencing magic. |
||
| 1218 | checkSubmitOnce('register'); |
||
| 1219 | $context['name'] = isset($_SESSION['guest_name']) ? $_SESSION['guest_name'] : ''; |
||
| 1220 | $context['email'] = isset($_SESSION['guest_email']) ? $_SESSION['guest_email'] : ''; |
||
| 1221 | // Needed for the editor and message icons. |
||
| 1222 | require_once($sourcedir . '/Subs-Editor.php'); |
||
| 1223 | |||
| 1224 | // Now create the editor. |
||
| 1225 | $editorOptions = array( |
||
| 1226 | 'id' => 'quickReply', |
||
| 1227 | 'value' => '', |
||
| 1228 | 'disable_smiley_box' => empty($options['use_editor_quick_reply']), |
||
| 1229 | 'labels' => array( |
||
| 1230 | 'post_button' => $txt['post'], |
||
| 1231 | ), |
||
| 1232 | // add height and width for the editor |
||
| 1233 | 'height' => '250px', |
||
| 1234 | 'width' => '100%', |
||
| 1235 | // We do HTML preview here. |
||
| 1236 | 'preview_type' => 1, |
||
| 1237 | // This is required |
||
| 1238 | 'required' => true, |
||
| 1239 | ); |
||
| 1240 | create_control_richedit($editorOptions); |
||
| 1241 | |||
| 1242 | // Store the ID. |
||
| 1243 | $context['post_box_name'] = $editorOptions['id']; |
||
| 1244 | |||
| 1245 | // Set a flag so the sub template knows what to do... |
||
| 1246 | $context['show_bbc'] = !empty($options['use_editor_quick_reply']); |
||
| 1247 | $modSettings['disable_wysiwyg'] = !empty($options['use_editor_quick_reply']); |
||
| 1248 | $context['attached'] = ''; |
||
| 1249 | $context['make_poll'] = isset($_REQUEST['poll']); |
||
| 1250 | |||
| 1251 | // Message icons - customized icons are off? |
||
| 1252 | $context['icons'] = getMessageIcons($board); |
||
| 1253 | |||
| 1254 | View Code Duplication | if (!empty($context['icons'])) |
|
| 1255 | $context['icons'][count($context['icons']) - 1]['is_last'] = true; |
||
| 1256 | |||
| 1257 | // Build the normal button array. |
||
| 1258 | $context['normal_buttons'] = array(); |
||
| 1259 | |||
| 1260 | if ($context['can_reply']) |
||
| 1261 | $context['normal_buttons']['reply'] = array('text' => 'reply', 'image' => 'reply.png', 'url' => $scripturl . '?action=post;topic=' . $context['current_topic'] . '.' . $context['start'] . ';last_msg=' . $context['topic_last_message'], 'active' => true); |
||
| 1262 | |||
| 1263 | View Code Duplication | if ($context['can_add_poll']) |
|
| 1264 | $context['normal_buttons']['add_poll'] = array('text' => 'add_poll', 'image' => 'add_poll.png', 'url' => $scripturl . '?action=editpoll;add;topic=' . $context['current_topic'] . '.' . $context['start']); |
||
| 1265 | |||
| 1266 | View Code Duplication | if ($context['can_mark_unread']) |
|
| 1267 | $context['normal_buttons']['mark_unread'] = array('text' => 'mark_unread', 'image' => 'markunread.png', 'url' => $scripturl . '?action=markasread;sa=topic;t=' . $context['mark_unread_time'] . ';topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']); |
||
| 1268 | |||
| 1269 | if ($context['can_print']) |
||
| 1270 | $context['normal_buttons']['print'] = array('text' => 'print', 'image' => 'print.png', 'custom' => 'rel="nofollow"', 'url' => $scripturl . '?action=printpage;topic=' . $context['current_topic'] . '.0'); |
||
| 1271 | |||
| 1272 | if ($context['can_set_notify']) |
||
| 1273 | $context['normal_buttons']['notify'] = array( |
||
| 1274 | 'text' => 'notify_topic_' . $context['topic_notification_mode'], |
||
| 1275 | 'sub_buttons' => array( |
||
| 1276 | array( |
||
| 1277 | 'test' => 'can_unwatch', |
||
| 1278 | 'text' => 'notify_topic_0', |
||
| 1279 | 'url' => $scripturl . '?action=notifytopic;topic=' . $context['current_topic'] . ';mode=0;' . $context['session_var'] . '=' . $context['session_id'], |
||
| 1280 | ), |
||
| 1281 | array( |
||
| 1282 | 'text' => 'notify_topic_1', |
||
| 1283 | 'url' => $scripturl . '?action=notifytopic;topic=' . $context['current_topic'] . ';mode=1;' . $context['session_var'] . '=' . $context['session_id'], |
||
| 1284 | ), |
||
| 1285 | array( |
||
| 1286 | 'text' => 'notify_topic_2', |
||
| 1287 | 'url' => $scripturl . '?action=notifytopic;topic=' . $context['current_topic'] . ';mode=2;' . $context['session_var'] . '=' . $context['session_id'], |
||
| 1288 | ), |
||
| 1289 | array( |
||
| 1290 | 'text' => 'notify_topic_3', |
||
| 1291 | 'url' => $scripturl . '?action=notifytopic;topic=' . $context['current_topic'] . ';mode=3;' . $context['session_var'] . '=' . $context['session_id'], |
||
| 1292 | ), |
||
| 1293 | ), |
||
| 1294 | ); |
||
| 1295 | |||
| 1296 | // Build the mod button array |
||
| 1297 | $context['mod_buttons'] = array(); |
||
| 1298 | |||
| 1299 | View Code Duplication | if ($context['can_move']) |
|
| 1300 | $context['mod_buttons']['move'] = array('text' => 'move_topic', 'image' => 'admin_move.png', 'url' => $scripturl . '?action=movetopic;current_board=' . $context['current_board'] . ';topic=' . $context['current_topic'] . '.0'); |
||
| 1301 | |||
| 1302 | View Code Duplication | if ($context['can_delete']) |
|
| 1303 | $context['mod_buttons']['delete'] = array('text' => 'remove_topic', 'image' => 'admin_rem.png', 'custom' => 'data-confirm="' . $txt['are_sure_remove_topic'] . '"', 'class' => 'you_sure', 'url' => $scripturl . '?action=removetopic2;topic=' . $context['current_topic'] . '.0;' . $context['session_var'] . '=' . $context['session_id']); |
||
| 1304 | |||
| 1305 | View Code Duplication | if ($context['can_lock']) |
|
| 1306 | $context['mod_buttons']['lock'] = array('text' => empty($context['is_locked']) ? 'set_lock' : 'set_unlock', 'image' => 'admin_lock.png', 'url' => $scripturl . '?action=lock;topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']); |
||
| 1307 | |||
| 1308 | View Code Duplication | if ($context['can_sticky']) |
|
| 1309 | $context['mod_buttons']['sticky'] = array('text' => empty($context['is_sticky']) ? 'set_sticky' : 'set_nonsticky', 'image' => 'admin_sticky.png', 'url' => $scripturl . '?action=sticky;topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']); |
||
| 1310 | |||
| 1311 | View Code Duplication | if ($context['can_merge']) |
|
| 1312 | $context['mod_buttons']['merge'] = array('text' => 'merge', 'image' => 'merge.png', 'url' => $scripturl . '?action=mergetopics;board=' . $context['current_board'] . '.0;from=' . $context['current_topic']); |
||
| 1313 | |||
| 1314 | View Code Duplication | if ($context['calendar_post']) |
|
| 1315 | $context['mod_buttons']['calendar'] = array('text' => 'calendar_link', 'image' => 'linktocal.png', 'url' => $scripturl . '?action=post;calendar;msg=' . $context['topic_first_message'] . ';topic=' . $context['current_topic'] . '.0'); |
||
| 1316 | |||
| 1317 | // Restore topic. eh? No monkey business. |
||
| 1318 | View Code Duplication | if ($context['can_restore_topic']) |
|
| 1319 | $context['mod_buttons']['restore_topic'] = array('text' => 'restore_topic', 'image' => '', 'url' => $scripturl . '?action=restoretopic;topics=' . $context['current_topic'] . ';' . $context['session_var'] . '=' . $context['session_id']); |
||
| 1320 | |||
| 1321 | // Show a message in case a recently posted message became unapproved. |
||
| 1322 | $context['becomesUnapproved'] = !empty($_SESSION['becomesUnapproved']) ? true : false; |
||
| 1323 | |||
| 1324 | // Don't want to show this forever... |
||
| 1325 | if ($context['becomesUnapproved']) |
||
| 1326 | unset($_SESSION['becomesUnapproved']); |
||
| 1327 | |||
| 1328 | // Allow adding new mod buttons easily. |
||
| 1329 | // Note: $context['normal_buttons'] and $context['mod_buttons'] are added for backward compatibility with 2.0, but are deprecated and should not be used |
||
| 1330 | call_integration_hook('integrate_display_buttons', array(&$context['normal_buttons'])); |
||
| 1331 | // Note: integrate_mod_buttons is no more necessary and deprecated, but is kept for backward compatibility with 2.0 |
||
| 1332 | call_integration_hook('integrate_mod_buttons', array(&$context['mod_buttons'])); |
||
| 1333 | |||
| 1334 | // Load the drafts js file |
||
| 1335 | if ($context['drafts_autosave']) |
||
| 1336 | loadJavaScriptFile('drafts.js', array('defer' => false), 'smf_drafts'); |
||
| 1337 | |||
| 1338 | // Spellcheck |
||
| 1339 | if ($context['show_spellchecking']) |
||
| 1340 | loadJavaScriptFile('spellcheck.js', array('defer' => false), 'smf_spellcheck'); |
||
| 1341 | |||
| 1342 | // topic.js |
||
| 1343 | loadJavaScriptFile('topic.js', array('defer' => false), 'smf_topic'); |
||
| 1344 | |||
| 1345 | // quotedText.js |
||
| 1346 | loadJavaScriptFile('quotedText.js', array('defer' => true), 'smf_quotedText'); |
||
| 1347 | |||
| 1348 | // Mentions |
||
| 1349 | View Code Duplication | if (!empty($modSettings['enable_mentions']) && allowedTo('mention')) |
|
| 1350 | { |
||
| 1351 | loadJavaScriptFile('jquery.atwho.min.js', array('defer' => true), 'smf_atwho'); |
||
| 1352 | loadJavaScriptFile('jquery.caret.min.js', array('defer' => true), 'smf_caret'); |
||
| 1353 | loadJavaScriptFile('mentions.js', array('defer' => true), 'smf_mentions'); |
||
| 1354 | } |
||
| 1355 | } |
||
| 1356 | |||
| 1357 | /** |
||
| 1358 | * Callback for the message display. |
||
| 1359 | * It actually gets and prepares the message context. |
||
| 1360 | * This function will start over from the beginning if reset is set to true, which is |
||
| 1361 | * useful for showing an index before or after the posts. |
||
| 1362 | * |
||
| 1363 | * @param bool $reset Whether or not to reset the db seek pointer |
||
| 1364 | * @return array A large array of contextual data for the posts |
||
| 1365 | */ |
||
| 1366 | function prepareDisplayContext($reset = false) |
||
| 1367 | { |
||
| 1368 | global $settings, $txt, $modSettings, $scripturl, $options, $user_info, $smcFunc; |
||
| 1369 | global $memberContext, $context, $messages_request, $topic, $board_info, $sourcedir; |
||
| 1370 | |||
| 1371 | static $counter = null; |
||
| 1372 | |||
| 1373 | // If the query returned false, bail. |
||
| 1374 | if ($messages_request == false) |
||
| 1375 | return false; |
||
| 1376 | |||
| 1377 | // Remember which message this is. (ie. reply #83) |
||
| 1378 | if ($counter === null || $reset) |
||
| 1379 | $counter = empty($options['view_newest_first']) ? $context['start'] : $context['total_visible_posts'] - $context['start']; |
||
| 1380 | |||
| 1381 | // Start from the beginning... |
||
| 1382 | if ($reset) |
||
| 1383 | return @$smcFunc['db_data_seek']($messages_request, 0); |
||
| 1384 | |||
| 1385 | // Attempt to get the next message. |
||
| 1386 | $message = $smcFunc['db_fetch_assoc']($messages_request); |
||
| 1387 | if (!$message) |
||
| 1388 | { |
||
| 1389 | $smcFunc['db_free_result']($messages_request); |
||
| 1390 | return false; |
||
| 1391 | } |
||
| 1392 | |||
| 1393 | // $context['icon_sources'] says where each icon should come from - here we set up the ones which will always exist! |
||
| 1394 | if (empty($context['icon_sources'])) |
||
| 1395 | { |
||
| 1396 | $context['icon_sources'] = array(); |
||
| 1397 | foreach ($context['stable_icons'] as $icon) |
||
| 1398 | $context['icon_sources'][$icon] = 'images_url'; |
||
| 1399 | } |
||
| 1400 | |||
| 1401 | // Message Icon Management... check the images exist. |
||
| 1402 | if (empty($modSettings['messageIconChecks_disable'])) |
||
| 1403 | { |
||
| 1404 | // If the current icon isn't known, then we need to do something... |
||
| 1405 | View Code Duplication | if (!isset($context['icon_sources'][$message['icon']])) |
|
| 1406 | $context['icon_sources'][$message['icon']] = file_exists($settings['theme_dir'] . '/images/post/' . $message['icon'] . '.png') ? 'images_url' : 'default_images_url'; |
||
| 1407 | } |
||
| 1408 | View Code Duplication | elseif (!isset($context['icon_sources'][$message['icon']])) |
|
| 1409 | $context['icon_sources'][$message['icon']] = 'images_url'; |
||
| 1410 | |||
| 1411 | // If you're a lazy bum, you probably didn't give a subject... |
||
| 1412 | $message['subject'] = $message['subject'] != '' ? $message['subject'] : $txt['no_subject']; |
||
| 1413 | |||
| 1414 | // Are you allowed to remove at least a single reply? |
||
| 1415 | $context['can_remove_post'] |= allowedTo('delete_own') && (empty($modSettings['edit_disable_time']) || $message['poster_time'] + $modSettings['edit_disable_time'] * 60 >= time()) && $message['id_member'] == $user_info['id']; |
||
| 1416 | |||
| 1417 | // If the topic is locked, you might not be able to delete the post... |
||
| 1418 | if ($context['is_locked']) |
||
| 1419 | { |
||
| 1420 | $context['can_remove_post'] &= ($context['user']['started'] && $context['is_locked'] == 1) || allowedTo('lock_any'); |
||
| 1421 | } |
||
| 1422 | |||
| 1423 | // If it couldn't load, or the user was a guest.... someday may be done with a guest table. |
||
| 1424 | if (!loadMemberContext($message['id_member'], true)) |
||
| 1425 | { |
||
| 1426 | // Notice this information isn't used anywhere else.... |
||
| 1427 | $memberContext[$message['id_member']]['name'] = $message['poster_name']; |
||
| 1428 | $memberContext[$message['id_member']]['id'] = 0; |
||
| 1429 | $memberContext[$message['id_member']]['group'] = $txt['guest_title']; |
||
| 1430 | $memberContext[$message['id_member']]['link'] = $message['poster_name']; |
||
| 1431 | $memberContext[$message['id_member']]['email'] = $message['poster_email']; |
||
| 1432 | $memberContext[$message['id_member']]['show_email'] = allowedTo('moderate_forum'); |
||
| 1433 | $memberContext[$message['id_member']]['is_guest'] = true; |
||
| 1434 | } |
||
| 1435 | else |
||
| 1436 | { |
||
| 1437 | // Define this here to make things a bit more readable |
||
| 1438 | $can_view_warning = $context['user']['can_mod'] || allowedTo('view_warning_any') || ($message['id_member'] == $user_info['id'] && allowedTo('view_warning_own')); |
||
| 1439 | |||
| 1440 | $memberContext[$message['id_member']]['can_view_profile'] = allowedTo('profile_view') || ($message['id_member'] == $user_info['id'] && !$user_info['is_guest']); |
||
| 1441 | $memberContext[$message['id_member']]['is_topic_starter'] = $message['id_member'] == $context['topic_starter_id']; |
||
| 1442 | $memberContext[$message['id_member']]['can_see_warning'] = !isset($context['disabled_fields']['warning_status']) && $memberContext[$message['id_member']]['warning_status'] && $can_view_warning; |
||
| 1443 | // Show the email if it's your post... |
||
| 1444 | $memberContext[$message['id_member']]['show_email'] |= ($message['id_member'] == $user_info['id']); |
||
| 1445 | } |
||
| 1446 | |||
| 1447 | $memberContext[$message['id_member']]['ip'] = inet_dtop($message['poster_ip']); |
||
| 1448 | $memberContext[$message['id_member']]['show_profile_buttons'] = !empty($modSettings['show_profile_buttons']) && (!empty($memberContext[$message['id_member']]['can_view_profile']) || (!empty($memberContext[$message['id_member']]['website']['url']) && !isset($context['disabled_fields']['website'])) || $memberContext[$message['id_member']]['show_email'] || $context['can_send_pm']); |
||
| 1449 | |||
| 1450 | // Do the censor thang. |
||
| 1451 | censorText($message['body']); |
||
| 1452 | censorText($message['subject']); |
||
| 1453 | |||
| 1454 | // Run BBC interpreter on the message. |
||
| 1455 | $message['body'] = parse_bbc($message['body'], $message['smileys_enabled'], $message['id_msg']); |
||
| 1456 | |||
| 1457 | // If it's in the recycle bin we need to override whatever icon we did have. |
||
| 1458 | if (!empty($board_info['recycle'])) |
||
| 1459 | $message['icon'] = 'recycled'; |
||
| 1460 | |||
| 1461 | require_once($sourcedir . '/Subs-Attachments.php'); |
||
| 1462 | |||
| 1463 | // Compose the memory eat- I mean message array. |
||
| 1464 | $output = array( |
||
| 1465 | 'attachment' => loadAttachmentContext($message['id_msg'], $context['loaded_attachments']), |
||
| 1466 | 'id' => $message['id_msg'], |
||
| 1467 | 'href' => $scripturl . '?topic=' . $topic . '.msg' . $message['id_msg'] . '#msg' . $message['id_msg'], |
||
| 1468 | 'link' => '<a href="' . $scripturl . '?msg=' . $message['id_msg'] . '" rel="nofollow">' . $message['subject'] . '</a>', |
||
| 1469 | 'member' => &$memberContext[$message['id_member']], |
||
| 1470 | 'icon' => $message['icon'], |
||
| 1471 | 'icon_url' => $settings[$context['icon_sources'][$message['icon']]] . '/post/' . $message['icon'] . '.png', |
||
| 1472 | 'subject' => $message['subject'], |
||
| 1473 | 'time' => timeformat($message['poster_time']), |
||
| 1474 | 'timestamp' => forum_time(true, $message['poster_time']), |
||
| 1475 | 'counter' => $counter, |
||
| 1476 | 'modified' => array( |
||
| 1477 | 'time' => timeformat($message['modified_time']), |
||
| 1478 | 'timestamp' => forum_time(true, $message['modified_time']), |
||
| 1479 | 'name' => $message['modified_name'], |
||
| 1480 | 'reason' => $message['modified_reason'] |
||
| 1481 | ), |
||
| 1482 | 'body' => $message['body'], |
||
| 1483 | 'new' => empty($message['is_read']), |
||
| 1484 | 'approved' => $message['approved'], |
||
| 1485 | 'first_new' => isset($context['start_from']) && $context['start_from'] == $counter, |
||
| 1486 | 'is_ignored' => !empty($modSettings['enable_buddylist']) && !empty($options['posts_apply_ignore_list']) && in_array($message['id_member'], $context['user']['ignoreusers']), |
||
| 1487 | 'can_approve' => !$message['approved'] && $context['can_approve'], |
||
| 1488 | 'can_unapprove' => !empty($modSettings['postmod_active']) && $context['can_approve'] && $message['approved'], |
||
| 1489 | 'can_modify' => (!$context['is_locked'] || allowedTo('moderate_board')) && (allowedTo('modify_any') || (allowedTo('modify_replies') && $context['user']['started']) || (allowedTo('modify_own') && $message['id_member'] == $user_info['id'] && (empty($modSettings['edit_disable_time']) || !$message['approved'] || $message['poster_time'] + $modSettings['edit_disable_time'] * 60 > time()))), |
||
| 1490 | 'can_remove' => allowedTo('delete_any') || (allowedTo('delete_replies') && $context['user']['started']) || (allowedTo('delete_own') && $message['id_member'] == $user_info['id'] && (empty($modSettings['edit_disable_time']) || $message['poster_time'] + $modSettings['edit_disable_time'] * 60 > time())), |
||
| 1491 | 'can_see_ip' => allowedTo('moderate_forum') || ($message['id_member'] == $user_info['id'] && !empty($user_info['id'])), |
||
| 1492 | 'css_class' => $message['approved'] ? 'windowbg' : 'approvebg', |
||
| 1493 | ); |
||
| 1494 | |||
| 1495 | // Does the file contains any attachments? if so, change the icon. |
||
| 1496 | if (!empty($output['attachment'])) |
||
| 1497 | { |
||
| 1498 | $output['icon'] = 'clip'; |
||
| 1499 | $output['icon_url'] = $settings[$context['icon_sources'][$output['icon']]] . '/post/' . $output['icon'] . '.png'; |
||
| 1500 | } |
||
| 1501 | |||
| 1502 | // Are likes enable? |
||
| 1503 | View Code Duplication | if (!empty($modSettings['enable_likes'])) |
|
| 1504 | $output['likes'] = array( |
||
| 1505 | 'count' => $message['likes'], |
||
| 1506 | 'you' => in_array($message['id_msg'], $context['my_likes']), |
||
| 1507 | 'can_like' => !$context['user']['is_guest'] && $message['id_member'] != $context['user']['id'] && !empty($context['can_like']), |
||
| 1508 | ); |
||
| 1509 | |||
| 1510 | // Is this user the message author? |
||
| 1511 | $output['is_message_author'] = $message['id_member'] == $user_info['id']; |
||
| 1512 | View Code Duplication | if (!empty($output['modified']['name'])) |
|
| 1513 | $output['modified']['last_edit_text'] = sprintf($txt['last_edit_by'], $output['modified']['time'], $output['modified']['name']); |
||
| 1514 | |||
| 1515 | // Did they give a reason for editing? |
||
| 1516 | View Code Duplication | if (!empty($output['modified']['name']) && !empty($output['modified']['reason'])) |
|
| 1517 | $output['modified']['last_edit_text'] .= ' ' . sprintf($txt['last_edit_reason'], $output['modified']['reason']); |
||
| 1518 | |||
| 1519 | // Any custom profile fields? |
||
| 1520 | if (!empty($memberContext[$message['id_member']]['custom_fields'])) |
||
| 1521 | foreach ($memberContext[$message['id_member']]['custom_fields'] as $custom) |
||
| 1522 | $output['custom_fields'][$context['cust_profile_fields_placement'][$custom['placement']]][] = $custom; |
||
| 1523 | |||
| 1524 | if (empty($options['view_newest_first'])) |
||
| 1525 | $counter++; |
||
| 1526 | |||
| 1527 | else |
||
| 1528 | $counter--; |
||
| 1529 | |||
| 1530 | call_integration_hook('integrate_prepare_display_context', array(&$output, &$message, $counter)); |
||
| 1531 | |||
| 1532 | return $output; |
||
| 1533 | } |
||
| 1534 | |||
| 1535 | /** |
||
| 1536 | * Downloads an attachment, and increments the download count. |
||
| 1537 | * It requires the view_attachments permission. |
||
| 1538 | * It disables the session parser, and clears any previous output. |
||
| 1539 | * It depends on the attachmentUploadDir setting being correct. |
||
| 1540 | * It is accessed via the query string ?action=dlattach. |
||
| 1541 | * Views to attachments do not increase hits and are not logged in the "Who's Online" log. |
||
| 1542 | * Legacy code, all attachments are now handled by ShowAttachments.php |
||
| 1543 | */ |
||
| 1544 | function Download() |
||
| 1545 | { |
||
| 1546 | global $txt, $modSettings, $user_info, $context, $topic, $smcFunc; |
||
| 1547 | |||
| 1548 | // Some defaults that we need. |
||
| 1549 | $context['character_set'] = empty($modSettings['global_character_set']) ? (empty($txt['lang_character_set']) ? 'ISO-8859-1' : $txt['lang_character_set']) : $modSettings['global_character_set']; |
||
| 1550 | $context['utf8'] = $context['character_set'] === 'UTF-8'; |
||
| 1551 | $context['no_last_modified'] = true; |
||
| 1552 | |||
| 1553 | // Prevent a preview image from being displayed twice. |
||
| 1554 | if (isset($_GET['action']) && $_GET['action'] == 'dlattach' && isset($_GET['type']) && ($_GET['type'] == 'avatar' || $_GET['type'] == 'preview')) |
||
| 1555 | return; |
||
| 1556 | |||
| 1557 | // Make sure some attachment was requested! |
||
| 1558 | if (!isset($_REQUEST['attach']) && !isset($_REQUEST['id'])) |
||
| 1559 | fatal_lang_error('no_access', false); |
||
| 1560 | |||
| 1561 | $_REQUEST['attach'] = isset($_REQUEST['attach']) ? (int) $_REQUEST['attach'] : (int) $_REQUEST['id']; |
||
| 1562 | |||
| 1563 | // Do we have a hook wanting to use our attachment system? We use $attachRequest to prevent accidental usage of $request. |
||
| 1564 | $attachRequest = null; |
||
| 1565 | call_integration_hook('integrate_download_request', array(&$attachRequest)); |
||
| 1566 | if (!is_null($attachRequest) && $smcFunc['db_is_resource']($attachRequest)) |
||
| 1567 | $request = $attachRequest; |
||
| 1568 | else |
||
| 1569 | { |
||
| 1570 | // This checks only the current board for $board/$topic's permissions. |
||
| 1571 | isAllowedTo('view_attachments'); |
||
| 1572 | |||
| 1573 | // Make sure this attachment is on this board. |
||
| 1574 | // @todo: We must verify that $topic is the attachment's topic, or else the permission check above is broken. |
||
| 1575 | $request = $smcFunc['db_query']('', ' |
||
| 1576 | SELECT a.id_folder, a.filename, a.file_hash, a.fileext, a.id_attach, a.attachment_type, a.mime_type, a.approved, m.id_member |
||
| 1577 | FROM {db_prefix}attachments AS a |
||
| 1578 | INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg AND m.id_topic = {int:current_topic}) |
||
| 1579 | INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board AND {query_see_board}) |
||
| 1580 | WHERE a.id_attach = {int:attach} |
||
| 1581 | LIMIT 1', |
||
| 1582 | array( |
||
| 1583 | 'attach' => $_REQUEST['attach'], |
||
| 1584 | 'current_topic' => $topic, |
||
| 1585 | ) |
||
| 1586 | ); |
||
| 1587 | } |
||
| 1588 | |||
| 1589 | if ($smcFunc['db_num_rows']($request) == 0) |
||
| 1590 | fatal_lang_error('no_access', false); |
||
| 1591 | |||
| 1592 | list ($id_folder, $real_filename, $file_hash, $file_ext, $id_attach, $attachment_type, $mime_type, $is_approved, $id_member) = $smcFunc['db_fetch_row']($request); |
||
| 1593 | $smcFunc['db_free_result']($request); |
||
| 1594 | |||
| 1595 | // If it isn't yet approved, do they have permission to view it? |
||
| 1596 | if (!$is_approved && ($id_member == 0 || $user_info['id'] != $id_member) && ($attachment_type == 0 || $attachment_type == 3)) |
||
| 1597 | isAllowedTo('approve_posts'); |
||
| 1598 | |||
| 1599 | // Update the download counter (unless it's a thumbnail). |
||
| 1600 | if ($attachment_type != 3) |
||
| 1601 | $smcFunc['db_query']('attach_download_increase', ' |
||
| 1602 | UPDATE LOW_PRIORITY {db_prefix}attachments |
||
| 1603 | SET downloads = downloads + 1 |
||
| 1604 | WHERE id_attach = {int:id_attach}', |
||
| 1605 | array( |
||
| 1606 | 'id_attach' => $id_attach, |
||
| 1607 | ) |
||
| 1608 | ); |
||
| 1609 | |||
| 1610 | $filename = getAttachmentFilename($real_filename, $_REQUEST['attach'], $id_folder, false, $file_hash); |
||
| 1611 | |||
| 1612 | // This is done to clear any output that was made before now. |
||
| 1613 | ob_end_clean(); |
||
| 1614 | if (!empty($modSettings['enableCompressedOutput']) && @filesize($filename) <= 4194304 && in_array($file_ext, array('txt', 'html', 'htm', 'js', 'doc', 'docx', 'rtf', 'css', 'php', 'log', 'xml', 'sql', 'c', 'java'))) |
||
| 1615 | @ob_start('ob_gzhandler'); |
||
|
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
|
|||
| 1616 | |||
| 1617 | else |
||
| 1618 | { |
||
| 1619 | ob_start(); |
||
| 1620 | header('Content-Encoding: none'); |
||
| 1621 | } |
||
| 1622 | |||
| 1623 | // No point in a nicer message, because this is supposed to be an attachment anyway... |
||
| 1624 | View Code Duplication | if (!file_exists($filename)) |
|
| 1625 | { |
||
| 1626 | header((preg_match('~HTTP/1\.[01]~i', $_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0') . ' 404 Not Found'); |
||
| 1627 | header('Content-Type: text/plain; charset=' . (empty($context['character_set']) ? 'ISO-8859-1' : $context['character_set'])); |
||
| 1628 | |||
| 1629 | // We need to die like this *before* we send any anti-caching headers as below. |
||
| 1630 | die('File not found.'); |
||
| 1631 | } |
||
| 1632 | |||
| 1633 | // If it hasn't been modified since the last time this attachment was retrieved, there's no need to display it again. |
||
| 1634 | View Code Duplication | if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) |
|
| 1635 | { |
||
| 1636 | list($modified_since) = explode(';', $_SERVER['HTTP_IF_MODIFIED_SINCE']); |
||
| 1637 | if (strtotime($modified_since) >= filemtime($filename)) |
||
| 1638 | { |
||
| 1639 | ob_end_clean(); |
||
| 1640 | |||
| 1641 | // Answer the question - no, it hasn't been modified ;). |
||
| 1642 | header('HTTP/1.1 304 Not Modified'); |
||
| 1643 | exit; |
||
| 1644 | } |
||
| 1645 | } |
||
| 1646 | |||
| 1647 | // Check whether the ETag was sent back, and cache based on that... |
||
| 1648 | $eTag = '"' . substr($_REQUEST['attach'] . $real_filename . filemtime($filename), 0, 64) . '"'; |
||
| 1649 | View Code Duplication | if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && strpos($_SERVER['HTTP_IF_NONE_MATCH'], $eTag) !== false) |
|
| 1650 | { |
||
| 1651 | ob_end_clean(); |
||
| 1652 | |||
| 1653 | header('HTTP/1.1 304 Not Modified'); |
||
| 1654 | exit; |
||
| 1655 | } |
||
| 1656 | |||
| 1657 | // Send the attachment headers. |
||
| 1658 | header('Pragma: '); |
||
| 1659 | |||
| 1660 | if (!isBrowser('gecko')) |
||
| 1661 | header('Content-Transfer-Encoding: binary'); |
||
| 1662 | |||
| 1663 | header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 525600 * 60) . ' GMT'); |
||
| 1664 | header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($filename)) . ' GMT'); |
||
| 1665 | header('Accept-Ranges: bytes'); |
||
| 1666 | header('Connection: close'); |
||
| 1667 | header('ETag: ' . $eTag); |
||
| 1668 | |||
| 1669 | // Make sure the mime type warrants an inline display. |
||
| 1670 | if (isset($_REQUEST['image']) && !empty($mime_type) && strpos($mime_type, 'image/') !== 0) |
||
| 1671 | unset($_REQUEST['image']); |
||
| 1672 | |||
| 1673 | // Does this have a mime type? |
||
| 1674 | elseif (!empty($mime_type) && (isset($_REQUEST['image']) || !in_array($file_ext, array('jpg', 'gif', 'jpeg', 'x-ms-bmp', 'png', 'psd', 'tiff', 'iff')))) |
||
| 1675 | header('Content-Type: ' . strtr($mime_type, array('image/bmp' => 'image/x-ms-bmp'))); |
||
| 1676 | |||
| 1677 | View Code Duplication | else |
|
| 1678 | { |
||
| 1679 | header('Content-Type: ' . (isBrowser('ie') || isBrowser('opera') ? 'application/octetstream' : 'application/octet-stream')); |
||
| 1680 | if (isset($_REQUEST['image'])) |
||
| 1681 | unset($_REQUEST['image']); |
||
| 1682 | } |
||
| 1683 | |||
| 1684 | // Convert the file to UTF-8, cuz most browsers dig that. |
||
| 1685 | $utf8name = !$context['utf8'] && function_exists('iconv') ? iconv($context['character_set'], 'UTF-8', $real_filename) : (!$context['utf8'] && function_exists('mb_convert_encoding') ? mb_convert_encoding($real_filename, 'UTF-8', $context['character_set']) : $real_filename); |
||
| 1686 | $disposition = !isset($_REQUEST['image']) ? 'attachment' : 'inline'; |
||
| 1687 | |||
| 1688 | // Different browsers like different standards... |
||
| 1689 | View Code Duplication | if (isBrowser('firefox')) |
|
| 1690 | header('Content-Disposition: ' . $disposition . '; filename*=UTF-8\'\'' . rawurlencode(preg_replace_callback('~&#(\d{3,8});~', 'fixchar__callback', $utf8name))); |
||
| 1691 | |||
| 1692 | elseif (isBrowser('opera')) |
||
| 1693 | header('Content-Disposition: ' . $disposition . '; filename="' . preg_replace_callback('~&#(\d{3,8});~', 'fixchar__callback', $utf8name) . '"'); |
||
| 1694 | |||
| 1695 | elseif (isBrowser('ie')) |
||
| 1696 | header('Content-Disposition: ' . $disposition . '; filename="' . urlencode(preg_replace_callback('~&#(\d{3,8});~', 'fixchar__callback', $utf8name)) . '"'); |
||
| 1697 | |||
| 1698 | else |
||
| 1699 | header('Content-Disposition: ' . $disposition . '; filename="' . $utf8name . '"'); |
||
| 1700 | |||
| 1701 | // If this has an "image extension" - but isn't actually an image - then ensure it isn't cached cause of silly IE. |
||
| 1702 | View Code Duplication | if (!isset($_REQUEST['image']) && in_array($file_ext, array('gif', 'jpg', 'bmp', 'png', 'jpeg', 'tiff'))) |
|
| 1703 | header('Cache-Control: no-cache'); |
||
| 1704 | else |
||
| 1705 | header('Cache-Control: max-age=' . (525600 * 60) . ', private'); |
||
| 1706 | |||
| 1707 | header('Content-Length: ' . filesize($filename)); |
||
| 1708 | |||
| 1709 | // Try to buy some time... |
||
| 1710 | @set_time_limit(600); |
||
|
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
|
|||
| 1711 | |||
| 1712 | // Recode line endings for text files, if enabled. |
||
| 1713 | if (!empty($modSettings['attachmentRecodeLineEndings']) && !isset($_REQUEST['image']) && in_array($file_ext, array('txt', 'css', 'htm', 'html', 'php', 'xml'))) |
||
| 1714 | { |
||
| 1715 | if (strpos($_SERVER['HTTP_USER_AGENT'], 'Windows') !== false) |
||
| 1716 | $callback = function($buffer) |
||
| 1717 | { |
||
| 1718 | return preg_replace('~[\r]?\n~', "\r\n", $buffer); |
||
| 1719 | }; |
||
| 1720 | elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Mac') !== false) |
||
| 1721 | $callback = function($buffer) |
||
| 1722 | { |
||
| 1723 | return preg_replace('~[\r]?\n~', "\r", $buffer); |
||
| 1724 | }; |
||
| 1725 | else |
||
| 1726 | $callback = function($buffer) |
||
| 1727 | { |
||
| 1728 | return preg_replace('~[\r]?\n~', "\n", $buffer); |
||
| 1729 | }; |
||
| 1730 | } |
||
| 1731 | |||
| 1732 | // Since we don't do output compression for files this large... |
||
| 1733 | if (filesize($filename) > 4194304) |
||
| 1734 | { |
||
| 1735 | // Forcibly end any output buffering going on. |
||
| 1736 | while (@ob_get_level() > 0) |
||
| 1737 | @ob_end_clean(); |
||
|
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
|
|||
| 1738 | |||
| 1739 | $fp = fopen($filename, 'rb'); |
||
| 1740 | while (!feof($fp)) |
||
| 1741 | { |
||
| 1742 | if (isset($callback)) |
||
| 1743 | echo $callback(fread($fp, 8192)); |
||
| 1744 | else |
||
| 1745 | echo fread($fp, 8192); |
||
| 1746 | flush(); |
||
| 1747 | } |
||
| 1748 | fclose($fp); |
||
| 1749 | } |
||
| 1750 | // 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. |
||
| 1751 | elseif (isset($callback) || @readfile($filename) === null) |
||
| 1752 | echo isset($callback) ? $callback(file_get_contents($filename)) : file_get_contents($filename); |
||
| 1753 | |||
| 1754 | obExit(false); |
||
| 1755 | } |
||
| 1756 | |||
| 1757 | /** |
||
| 1758 | * A sort function for putting unapproved attachments first. |
||
| 1759 | * @param array $a An array of info about one attachment |
||
| 1760 | * @param array $b An array of info about a second attachment |
||
| 1761 | * @return int -1 if $a is approved but $b isn't, 0 if both are approved/unapproved, 1 if $b is approved but a isn't |
||
| 1762 | */ |
||
| 1763 | function approved_attach_sort($a, $b) |
||
| 1764 | { |
||
| 1765 | if ($a['is_approved'] == $b['is_approved']) |
||
| 1766 | return 0; |
||
| 1767 | |||
| 1768 | return $a['is_approved'] > $b['is_approved'] ? -1 : 1; |
||
| 1769 | } |
||
| 1770 | |||
| 1771 | /** |
||
| 1772 | * In-topic quick moderation. |
||
| 1773 | */ |
||
| 1774 | function QuickInTopicModeration() |
||
| 1775 | { |
||
| 1776 | global $sourcedir, $topic, $board, $user_info, $smcFunc, $modSettings, $context; |
||
| 1777 | |||
| 1778 | // Check the session = get or post. |
||
| 1779 | checkSession('request'); |
||
| 1780 | |||
| 1781 | require_once($sourcedir . '/RemoveTopic.php'); |
||
| 1782 | |||
| 1783 | if (empty($_REQUEST['msgs'])) |
||
| 1784 | redirectexit('topic=' . $topic . '.' . $_REQUEST['start']); |
||
| 1785 | |||
| 1786 | $messages = array(); |
||
| 1787 | foreach ($_REQUEST['msgs'] as $dummy) |
||
| 1788 | $messages[] = (int) $dummy; |
||
| 1789 | |||
| 1790 | // We are restoring messages. We handle this in another place. |
||
| 1791 | View Code Duplication | if (isset($_REQUEST['restore_selected'])) |
|
| 1792 | redirectexit('action=restoretopic;msgs=' . implode(',', $messages) . ';' . $context['session_var'] . '=' . $context['session_id']); |
||
| 1793 | if (isset($_REQUEST['split_selection'])) |
||
| 1794 | { |
||
| 1795 | $request = $smcFunc['db_query']('', ' |
||
| 1796 | SELECT subject |
||
| 1797 | FROM {db_prefix}messages |
||
| 1798 | WHERE id_msg = {int:message} |
||
| 1799 | LIMIT 1', |
||
| 1800 | array( |
||
| 1801 | 'message' => min($messages), |
||
| 1802 | ) |
||
| 1803 | ); |
||
| 1804 | list($subname) = $smcFunc['db_fetch_row']($request); |
||
| 1805 | $smcFunc['db_free_result']($request); |
||
| 1806 | $_SESSION['split_selection'][$topic] = $messages; |
||
| 1807 | redirectexit('action=splittopics;sa=selectTopics;topic=' . $topic . '.0;subname_enc=' . urlencode($subname) . ';' . $context['session_var'] . '=' . $context['session_id']); |
||
| 1808 | } |
||
| 1809 | |||
| 1810 | // Allowed to delete any message? |
||
| 1811 | if (allowedTo('delete_any')) |
||
| 1812 | $allowed_all = true; |
||
| 1813 | // Allowed to delete replies to their messages? |
||
| 1814 | View Code Duplication | elseif (allowedTo('delete_replies')) |
|
| 1815 | { |
||
| 1816 | $request = $smcFunc['db_query']('', ' |
||
| 1817 | SELECT id_member_started |
||
| 1818 | FROM {db_prefix}topics |
||
| 1819 | WHERE id_topic = {int:current_topic} |
||
| 1820 | LIMIT 1', |
||
| 1821 | array( |
||
| 1822 | 'current_topic' => $topic, |
||
| 1823 | ) |
||
| 1824 | ); |
||
| 1825 | list ($starter) = $smcFunc['db_fetch_row']($request); |
||
| 1826 | $smcFunc['db_free_result']($request); |
||
| 1827 | |||
| 1828 | $allowed_all = $starter == $user_info['id']; |
||
| 1829 | } |
||
| 1830 | else |
||
| 1831 | $allowed_all = false; |
||
| 1832 | |||
| 1833 | // Make sure they're allowed to delete their own messages, if not any. |
||
| 1834 | if (!$allowed_all) |
||
| 1835 | isAllowedTo('delete_own'); |
||
| 1836 | |||
| 1837 | // Allowed to remove which messages? |
||
| 1838 | $request = $smcFunc['db_query']('', ' |
||
| 1839 | SELECT id_msg, subject, id_member, poster_time |
||
| 1840 | FROM {db_prefix}messages |
||
| 1841 | WHERE id_msg IN ({array_int:message_list}) |
||
| 1842 | AND id_topic = {int:current_topic}' . (!$allowed_all ? ' |
||
| 1843 | AND id_member = {int:current_member}' : '') . ' |
||
| 1844 | LIMIT {int:limit}', |
||
| 1845 | array( |
||
| 1846 | 'current_member' => $user_info['id'], |
||
| 1847 | 'current_topic' => $topic, |
||
| 1848 | 'message_list' => $messages, |
||
| 1849 | 'limit' => count($messages), |
||
| 1850 | ) |
||
| 1851 | ); |
||
| 1852 | $messages = array(); |
||
| 1853 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 1854 | { |
||
| 1855 | if (!$allowed_all && !empty($modSettings['edit_disable_time']) && $row['poster_time'] + $modSettings['edit_disable_time'] * 60 < time()) |
||
| 1856 | continue; |
||
| 1857 | |||
| 1858 | $messages[$row['id_msg']] = array($row['subject'], $row['id_member']); |
||
| 1859 | } |
||
| 1860 | $smcFunc['db_free_result']($request); |
||
| 1861 | |||
| 1862 | // Get the first message in the topic - because you can't delete that! |
||
| 1863 | $request = $smcFunc['db_query']('', ' |
||
| 1864 | SELECT id_first_msg, id_last_msg |
||
| 1865 | FROM {db_prefix}topics |
||
| 1866 | WHERE id_topic = {int:current_topic} |
||
| 1867 | LIMIT 1', |
||
| 1868 | array( |
||
| 1869 | 'current_topic' => $topic, |
||
| 1870 | ) |
||
| 1871 | ); |
||
| 1872 | list ($first_message, $last_message) = $smcFunc['db_fetch_row']($request); |
||
| 1873 | $smcFunc['db_free_result']($request); |
||
| 1874 | |||
| 1875 | // Delete all the messages we know they can delete. ($messages) |
||
| 1876 | foreach ($messages as $message => $info) |
||
| 1877 | { |
||
| 1878 | // Just skip the first message - if it's not the last. |
||
| 1879 | if ($message == $first_message && $message != $last_message) |
||
| 1880 | continue; |
||
| 1881 | // If the first message is going then don't bother going back to the topic as we're effectively deleting it. |
||
| 1882 | elseif ($message == $first_message) |
||
| 1883 | $topicGone = true; |
||
| 1884 | |||
| 1885 | removeMessage($message); |
||
| 1886 | |||
| 1887 | // Log this moderation action ;). |
||
| 1888 | View Code Duplication | if (allowedTo('delete_any') && (!allowedTo('delete_own') || $info[1] != $user_info['id'])) |
|
| 1889 | logAction('delete', array('topic' => $topic, 'subject' => $info[0], 'member' => $info[1], 'board' => $board)); |
||
| 1890 | } |
||
| 1891 | |||
| 1892 | redirectexit(!empty($topicGone) ? 'board=' . $board : 'topic=' . $topic . '.' . $_REQUEST['start']); |
||
| 1893 | } |
||
| 1894 | |||
| 1895 | ?> |
If you define a variable conditionally, it can happen that it is not defined for all execution paths.
Let’s take a look at an example:
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.
Available Fixes
Check for existence of the variable explicitly:
Define a default value for the variable:
Add a value for the missing path: