1<?php 2/** 3 * MyBB 1.8 4 * Copyright 2014 MyBB Group, All Rights Reserved 5 * 6 * Website: http://www.mybb.com 7 * License: http://www.mybb.com/about/license 8 * 9 */ 10 11define("IN_MYBB", 1); 12define('THIS_SCRIPT', 'showthread.php'); 13 14$templatelist = "showthread,postbit,postbit_author_user,postbit_author_guest,showthread_newthread,showthread_newreply,showthread_newreply_closed,postbit_avatar,postbit_find,postbit_pm,postbit_www,postbit_email,postbit_edit,postbit_quote,postbit_report"; 15$templatelist .= ",multipage,multipage_breadcrumb,multipage_end,multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage,multipage_start,showthread_inlinemoderation_softdelete,showthread_poll_editpoll"; 16$templatelist .= ",postbit_editedby,showthread_similarthreads,showthread_similarthreads_bit,postbit_iplogged_show,postbit_iplogged_hiden,postbit_profilefield,showthread_quickreply,showthread_printthread,showthread_add_poll,showthread_send_thread,showthread_inlinemoderation_restore"; 17$templatelist .= ",forumjump_advanced,forumjump_special,forumjump_bit,postbit_attachments,postbit_attachments_attachment,postbit_attachments_thumbnails,postbit_attachments_images_image,postbit_attachments_images,showthread_quickreply_options_stick,postbit_status"; 18$templatelist .= ",postbit_inlinecheck,showthread_inlinemoderation,postbit_attachments_thumbnails_thumbnail,postbit_ignored,postbit_multiquote,showthread_moderationoptions_custom_tool,showthread_moderationoptions_custom,showthread_inlinemoderation_custom_tool"; 19$templatelist .= ",showthread_usersbrowsing,showthread_usersbrowsing_user,showthread_poll_option,showthread_poll,showthread_quickreply_options_signature,showthread_threaded_bitactive,showthread_threaded_bit,postbit_attachments_attachment_unapproved"; 20$templatelist .= ",showthread_moderationoptions_openclose,showthread_moderationoptions_stickunstick,showthread_moderationoptions_delete,showthread_moderationoptions_threadnotes,showthread_moderationoptions_manage,showthread_moderationoptions_deletepoll"; 21$templatelist .= ",postbit_userstar,postbit_reputation_formatted_link,postbit_warninglevel_formatted,postbit_quickrestore,forumdisplay_password,forumdisplay_password_wrongpass,postbit_purgespammer,showthread_inlinemoderation_approve,forumdisplay_thread_icon"; 22$templatelist .= ",showthread_moderationoptions_softdelete,showthread_moderationoptions_restore,post_captcha,post_captcha_recaptcha_invisible,post_captcha_nocaptcha,post_captcha_hcaptcha_invisible,post_captcha_hcaptcha,showthread_moderationoptions,showthread_inlinemoderation_standard,showthread_inlinemoderation_manage"; 23$templatelist .= ",showthread_ratethread,postbit_posturl,postbit_icon,postbit_editedby_editreason,attachment_icon,global_moderation_notice,showthread_poll_option_multiple,postbit_gotopost,postbit_rep_button,postbit_warninglevel,showthread_threadnoteslink"; 24$templatelist .= ",showthread_moderationoptions_approve,showthread_moderationoptions_unapprove,showthread_inlinemoderation_delete,showthread_moderationoptions_standard,showthread_quickreply_options_close,showthread_inlinemoderation_custom,showthread_search"; 25$templatelist .= ",postbit_profilefield_multiselect_value,postbit_profilefield_multiselect,showthread_subscription,postbit_deleted_member,postbit_away,postbit_warn,postbit_classic,postbit_reputation,postbit_deleted,postbit_offline,postbit_online,postbit_signature"; 26$templatelist .= ",postbit_editreason,postbit_quickdelete,showthread_threadnotes_viewnotes,showthread_threadedbox,showthread_poll_resultbit,showthread_poll_results,showthread_threadnotes,showthread_classic_header,showthread_poll_undovote,postbit_groupimage"; 27 28require_once "./global.php"; 29require_once MYBB_ROOT."inc/functions_post.php"; 30require_once MYBB_ROOT."inc/functions_indicators.php"; 31require_once MYBB_ROOT."inc/class_parser.php"; 32$parser = new postParser; 33 34// Load global language phrases 35$lang->load("showthread"); 36 37// If there is no tid but a pid, trick the system into thinking there was a tid anyway. 38if(!empty($mybb->input['pid']) && !isset($mybb->input['tid'])) 39{ 40 // see if we already have the post information 41 if(isset($style) && $style['pid'] == $mybb->get_input('pid', MyBB::INPUT_INT) && $style['tid']) 42 { 43 $mybb->input['tid'] = $style['tid']; 44 unset($style['tid']); // stop the thread caching code from being tricked 45 } 46 else 47 { 48 $options = array( 49 "limit" => 1 50 ); 51 $query = $db->simple_select("posts", "fid,tid,visible", "pid=".$mybb->get_input('pid', MyBB::INPUT_INT), $options); 52 $post = $db->fetch_array($query); 53 54 if( 55 empty($post) || 56 ( 57 $post['visible'] == 0 && !( 58 is_moderator($post['fid'], 'canviewunapprove') || 59 ($mybb->user['uid'] && $post['uid'] == $mybb->user['uid'] && $mybb->settings['showownunapproved']) 60 ) 61 ) || 62 ($post['visible'] == -1 && !is_moderator($post['fid'], 'canviewdeleted')) 63 ) 64 { 65 // post does not exist --> show corresponding error 66 error($lang->error_invalidpost); 67 } 68 69 $mybb->input['tid'] = $post['tid']; 70 } 71} 72 73// Get the thread details from the database. 74$thread = get_thread($mybb->get_input('tid', MyBB::INPUT_INT)); 75 76if(!$thread || substr($thread['closed'], 0, 6) == "moved|") 77{ 78 error($lang->error_invalidthread); 79} 80 81// Get thread prefix if there is one. 82$thread['threadprefix'] = ''; 83$thread['displayprefix'] = ''; 84if($thread['prefix'] != 0) 85{ 86 $threadprefix = build_prefixes($thread['prefix']); 87 88 if(!empty($threadprefix['prefix'])) 89 { 90 $thread['threadprefix'] = htmlspecialchars_uni($threadprefix['prefix']).' '; 91 $thread['displayprefix'] = $threadprefix['displaystyle'].' '; 92 } 93} 94 95$reply_subject = $parser->parse_badwords($thread['subject']); 96$thread['subject'] = htmlspecialchars_uni($reply_subject); 97// Subject too long? Shorten it to avoid error message 98if(my_strlen($reply_subject) > 85) 99{ 100 $reply_subject = my_substr($reply_subject, 0, 82).'...'; 101} 102$reply_subject = htmlspecialchars_uni($reply_subject); 103$tid = $thread['tid']; 104$fid = $thread['fid']; 105 106if(!$thread['username']) 107{ 108 $thread['username'] = $lang->guest; 109} 110$thread['username'] = htmlspecialchars_uni($thread['username']); 111 112$forumpermissions = forum_permissions($thread['fid']); 113 114// Set here to fetch only approved/deleted posts (and then below for a moderator we change this). 115$visible_states = array("1"); 116 117if($forumpermissions['canviewdeletionnotice'] != 0) 118{ 119 $visible_states[] = "-1"; 120} 121 122// Is the currently logged in user a moderator of this forum? 123if(is_moderator($fid)) 124{ 125 $ismod = true; 126 if(is_moderator($fid, "canviewdeleted") == true) 127 { 128 $visible_states[] = "-1"; 129 } 130 if(is_moderator($fid, "canviewunapprove") == true) 131 { 132 $visible_states[] = "0"; 133 } 134} 135else 136{ 137 $ismod = false; 138} 139 140$visible_condition = "visible IN (".implode(',', array_unique($visible_states)).")"; 141 142// Allow viewing own unapproved threads for logged in users 143if($mybb->user['uid'] && $mybb->settings['showownunapproved']) 144{ 145 $own_unapproved = ' AND (%1$s'.$visible_condition.' OR (%1$svisible=0 AND %1$suid='.(int)$mybb->user['uid'].'))'; 146 147 $visibleonly = sprintf($own_unapproved, null); 148 $visibleonly_p = sprintf($own_unapproved, 'p.'); 149 $visibleonly_p_t = sprintf($own_unapproved, 'p.').sprintf($own_unapproved, 't.'); 150} 151else 152{ 153 $visibleonly = " AND ".$visible_condition; 154 $visibleonly_p = " AND p.".$visible_condition; 155 $visibleonly_p_t = "AND p.".$visible_condition." AND t.".$visible_condition; 156} 157 158// Make sure we are looking at a real thread here. 159if(($thread['visible'] != 1 && $ismod == false) || ($thread['visible'] == 0 && !is_moderator($fid, "canviewunapprove")) || ($thread['visible'] == -1 && !is_moderator($fid, "canviewdeleted"))) 160{ 161 // Allow viewing own unapproved thread 162 if (!($mybb->user['uid'] && $mybb->settings['showownunapproved'] && $thread['visible'] == 0 && ($thread['uid'] == $mybb->user['uid']))) 163 { 164 error($lang->error_invalidthread); 165 } 166} 167 168// Does the user have permission to view this thread? 169if($forumpermissions['canview'] != 1 || $forumpermissions['canviewthreads'] != 1) 170{ 171 error_no_permission(); 172} 173 174if(isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] == 1 && $thread['uid'] != $mybb->user['uid']) 175{ 176 error_no_permission(); 177} 178 179$archive_url = build_archive_link("thread", $tid); 180 181// Does the thread belong to a valid forum? 182$forum = get_forum($fid); 183if(!$forum || $forum['type'] != "f") 184{ 185 error($lang->error_invalidforum); 186} 187 188$threadnoteslink = ''; 189if(is_moderator($fid, "canmanagethreads") && !empty($thread['notes'])) 190{ 191 eval('$threadnoteslink = "'.$templates->get('showthread_threadnoteslink').'";'); 192} 193 194// Check if this forum is password protected and we have a valid password 195check_forum_password($forum['fid']); 196 197// If there is no specific action, we must be looking at the thread. 198if(!$mybb->get_input('action')) 199{ 200 $mybb->input['action'] = "thread"; 201} 202 203// Jump to the unread posts. 204if($mybb->input['action'] == "newpost") 205{ 206 // First, figure out what time the thread or forum were last read 207 $query = $db->simple_select("threadsread", "dateline", "uid='{$mybb->user['uid']}' AND tid='{$thread['tid']}'"); 208 $thread_read = $db->fetch_field($query, "dateline"); 209 210 if($mybb->settings['threadreadcut'] > 0 && $mybb->user['uid']) 211 { 212 $query = $db->simple_select("forumsread", "dateline", "fid='{$fid}' AND uid='{$mybb->user['uid']}'"); 213 $forum_read = $db->fetch_field($query, "dateline"); 214 215 $read_cutoff = TIME_NOW-$mybb->settings['threadreadcut']*60*60*24; 216 if($forum_read == 0 || $forum_read < $read_cutoff) 217 { 218 $forum_read = $read_cutoff; 219 } 220 } 221 else 222 { 223 $forum_read = (int)my_get_array_cookie("forumread", $fid); 224 } 225 226 if($mybb->settings['threadreadcut'] > 0 && $mybb->user['uid'] && $thread['lastpost'] > $forum_read) 227 { 228 $cutoff = TIME_NOW-$mybb->settings['threadreadcut']*60*60*24; 229 if($thread['lastpost'] > $cutoff) 230 { 231 if($thread_read) 232 { 233 $lastread = $thread_read; 234 } 235 else 236 { 237 // Set $lastread to zero to make sure 'lastpost' is invoked in the last IF 238 $lastread = 0; 239 } 240 } 241 } 242 243 if(!$lastread) 244 { 245 $readcookie = $threadread = (int)my_get_array_cookie("threadread", $thread['tid']); 246 if($readcookie > $forum_read) 247 { 248 $lastread = $readcookie; 249 } 250 else 251 { 252 $lastread = $forum_read; 253 } 254 } 255 256 if($cutoff && $lastread < $cutoff) 257 { 258 $lastread = $cutoff; 259 } 260 261 // Next, find the proper pid to link to. 262 $options = array( 263 "limit_start" => 0, 264 "limit" => 1, 265 "order_by" => "dateline, pid", 266 ); 267 268 $lastread = (int)$lastread; 269 $query = $db->simple_select("posts", "pid", "tid='{$tid}' AND dateline > '{$lastread}' {$visibleonly}", $options); 270 $newpost = $db->fetch_array($query); 271 272 if($newpost['pid'] && $lastread) 273 { 274 $highlight = ''; 275 if($mybb->get_input('highlight')) 276 { 277 $string = "&"; 278 if($mybb->seo_support == true) 279 { 280 $string = "?"; 281 } 282 283 $highlight = $string."highlight=".$mybb->get_input('highlight'); 284 } 285 286 header("Location: ".htmlspecialchars_decode(get_post_link($newpost['pid'], $tid)).$highlight."#pid{$newpost['pid']}"); 287 } 288 else 289 { 290 // show them to the last post 291 $mybb->input['action'] = "lastpost"; 292 } 293} 294 295// Jump to the last post. 296if($mybb->input['action'] == "lastpost") 297{ 298 if(my_strpos($thread['closed'], "moved|")) 299 { 300 $query = $db->query(" 301 SELECT p.pid 302 FROM ".TABLE_PREFIX."posts p 303 LEFT JOIN ".TABLE_PREFIX."threads t ON(p.tid=t.tid) 304 WHERE t.fid='".$thread['fid']."' AND t.closed NOT LIKE 'moved|%' {$visibleonly_p_t} 305 ORDER BY p.dateline DESC, p.pid DESC 306 LIMIT 1 307 "); 308 $pid = $db->fetch_field($query, "pid"); 309 } 310 else 311 { 312 $options = array( 313 'order_by' => 'dateline DESC, pid DESC', 314 'limit_start' => 0, 315 'limit' => 1 316 ); 317 $query = $db->simple_select('posts', 'pid', "tid={$tid} {$visibleonly}", $options); 318 $pid = $db->fetch_field($query, "pid"); 319 } 320 header("Location: ".htmlspecialchars_decode(get_post_link($pid, $tid))."#pid{$pid}"); 321 exit; 322} 323 324// Jump to the next newest posts. 325if($mybb->input['action'] == "nextnewest") 326{ 327 $options = array( 328 "limit_start" => 0, 329 "limit" => 1, 330 "order_by" => "lastpost" 331 ); 332 $query = $db->simple_select('threads', '*', "fid={$thread['fid']} AND lastpost > {$thread['lastpost']} {$visibleonly} AND closed NOT LIKE 'moved|%'", $options); 333 $nextthread = $db->fetch_array($query); 334 335 // Are there actually next newest posts? 336 if(!$nextthread['tid']) 337 { 338 error($lang->error_nonextnewest); 339 } 340 $options = array( 341 "limit_start" => 0, 342 "limit" => 1, 343 "order_by" => "dateline DESC, pid DESC", 344 ); 345 $query = $db->simple_select('posts', 'pid', "tid='{$nextthread['tid']}'", $options); 346 347 // Redirect to the proper page. 348 $pid = $db->fetch_field($query, "pid"); 349 header("Location: ".htmlspecialchars_decode(get_post_link($pid, $nextthread['tid']))."#pid{$pid}"); 350 exit; 351} 352 353// Jump to the next oldest posts. 354if($mybb->input['action'] == "nextoldest") 355{ 356 $options = array( 357 "limit" => 1, 358 "limit_start" => 0, 359 "order_by" => "lastpost", 360 "order_dir" => "desc" 361 ); 362 $query = $db->simple_select("threads", "*", "fid=".$thread['fid']." AND lastpost < ".$thread['lastpost']." {$visibleonly} AND closed NOT LIKE 'moved|%'", $options); 363 $nextthread = $db->fetch_array($query); 364 365 // Are there actually next oldest posts? 366 if(!$nextthread['tid']) 367 { 368 error($lang->error_nonextoldest); 369 } 370 $options = array( 371 "limit_start" => 0, 372 "limit" => 1, 373 "order_by" => "dateline DESC, pid DESC", 374 ); 375 $query = $db->simple_select("posts", "pid", "tid='".$nextthread['tid']."'", $options); 376 377 // Redirect to the proper page. 378 $pid = $db->fetch_field($query, "pid"); 379 header("Location: ".htmlspecialchars_decode(get_post_link($pid, $nextthread['tid']))."#pid{$pid}"); 380 exit; 381} 382 383$pid = $mybb->input['pid'] = $mybb->get_input('pid', MyBB::INPUT_INT); 384 385// Forumdisplay cache 386$forum_stats = $cache->read("forumsdisplay"); 387 388$breadcrumb_multipage = array(); 389if($mybb->settings['showforumpagesbreadcrumb']) 390{ 391 // How many pages are there? 392 if(!$mybb->settings['threadsperpage'] || (int)$mybb->settings['threadsperpage'] < 1) 393 { 394 $mybb->settings['threadsperpage'] = 20; 395 } 396 397 $query = $db->simple_select("forums", "threads, unapprovedthreads, deletedthreads", "fid = '{$fid}'", array('limit' => 1)); 398 $forum_threads = $db->fetch_array($query); 399 $threadcount = $forum_threads['threads']; 400 401 402 if(is_moderator($fid, "canviewdeleted") == true || is_moderator($fid, "canviewunapprove") == true) 403 { 404 if(is_moderator($fid, "canviewdeleted") == true) 405 { 406 $threadcount += $forum_threads['deletedthreads']; 407 } 408 if(is_moderator($fid, "canviewunapprove") == true) 409 { 410 $threadcount += $forum_threads['unapprovedthreads']; 411 } 412 } 413 elseif($forumpermissions['canviewdeletionnotice'] != 0) 414 { 415 $threadcount += $forum_threads['deletedthreads']; 416 } 417 418 // Limit to only our own threads 419 $uid_only = ''; 420 if(isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] == 1) 421 { 422 $uid_only = " AND uid = '".$mybb->user['uid']."'"; 423 424 $query = $db->simple_select("threads", "COUNT(tid) AS threads", "fid = '$fid' $visibleonly $uid_only", array('limit' => 1)); 425 $threadcount = $db->fetch_field($query, "threads"); 426 } 427 428 // If we have 0 threads double check there aren't any "moved" threads 429 if($threadcount == 0) 430 { 431 $query = $db->simple_select("threads", "COUNT(tid) AS threads", "fid = '$fid' $visibleonly $uid_only", array('limit' => 1)); 432 $threadcount = $db->fetch_field($query, "threads"); 433 } 434 435 $stickybit = " OR sticky=1"; 436 if($thread['sticky'] == 1) 437 { 438 $stickybit = " AND sticky=1"; 439 } 440 441 // Figure out what page the thread is actually on 442 switch($db->type) 443 { 444 case "pgsql": 445 $query = $db->query(" 446 SELECT COUNT(tid) as threads 447 FROM ".TABLE_PREFIX."threads 448 WHERE fid = '$fid' AND (lastpost >= '".(int)$thread['lastpost']."'{$stickybit}) {$visibleonly} {$uid_only} 449 GROUP BY lastpost 450 ORDER BY lastpost DESC 451 "); 452 break; 453 default: 454 $query = $db->simple_select("threads", "COUNT(tid) as threads", "fid = '$fid' AND (lastpost >= '".(int)$thread['lastpost']."'{$stickybit}) {$visibleonly} {$uid_only}", array('order_by' => 'lastpost', 'order_dir' => 'desc')); 455 } 456 457 $thread_position = $db->fetch_field($query, "threads"); 458 $thread_page = ceil(($thread_position/$mybb->settings['threadsperpage'])); 459 460 $breadcrumb_multipage = array( 461 "num_threads" => $threadcount, 462 "current_page" => $thread_page 463 ); 464} 465 466// Build the navigation. 467build_forum_breadcrumb($fid, $breadcrumb_multipage); 468add_breadcrumb($thread['displayprefix'].$thread['subject'], get_thread_link($thread['tid'])); 469 470$plugins->run_hooks("showthread_start"); 471 472// Show the entire thread (taking into account pagination). 473if($mybb->input['action'] == "thread") 474{ 475 // This is a workaround to fix threads which data may get "corrupted" due to lag or other still unknown reasons 476 if($thread['firstpost'] == 0 || $thread['dateline'] == 0) 477 { 478 update_first_post($tid); 479 } 480 481 // Does this thread have a poll? 482 if($thread['poll']) 483 { 484 $options = array( 485 "limit" => 1 486 ); 487 $query = $db->simple_select("polls", "*", "pid='".$thread['poll']."'", $options); 488 $poll = $db->fetch_array($query); 489 $poll['timeout'] = $poll['timeout']*60*60*24; 490 $expiretime = $poll['dateline'] + $poll['timeout']; 491 $now = TIME_NOW; 492 493 // If the poll or the thread is closed or if the poll is expired, show the results. 494 if($poll['closed'] == 1 || $thread['closed'] == 1 || ($expiretime < $now && $poll['timeout'] > 0) || $forumpermissions['canvotepolls'] != 1) 495 { 496 $showresults = 1; 497 } 498 499 if($forumpermissions['canvotepolls'] != 1) 500 { 501 $nopermission = 1; 502 } 503 504 // Check if the user has voted before... 505 if($mybb->user['uid']) 506 { 507 $user_check = "uid='{$mybb->user['uid']}'"; 508 } 509 else 510 { 511 $user_check = "uid='0' AND ipaddress=".$db->escape_binary($session->packedip); 512 } 513 514 $query = $db->simple_select("pollvotes", "*", "{$user_check} AND pid='".$poll['pid']."'"); 515 while($votecheck = $db->fetch_array($query)) 516 { 517 $alreadyvoted = 1; 518 $votedfor[$votecheck['voteoption']] = 1; 519 } 520 521 $optionsarray = explode("||~|~||", $poll['options']); 522 $votesarray = explode("||~|~||", $poll['votes']); 523 $poll['question'] = htmlspecialchars_uni($poll['question']); 524 $polloptions = ''; 525 $totalvotes = 0; 526 $poll['totvotes'] = 0; 527 528 for($i = 1; $i <= $poll['numoptions']; ++$i) 529 { 530 $poll['totvotes'] = $poll['totvotes'] + $votesarray[$i-1]; 531 } 532 533 // Loop through the poll options. 534 for($i = 1; $i <= $poll['numoptions']; ++$i) 535 { 536 // Set up the parser options. 537 $parser_options = array( 538 "allow_html" => $forum['allowhtml'], 539 "allow_mycode" => $forum['allowmycode'], 540 "allow_smilies" => $forum['allowsmilies'], 541 "allow_imgcode" => $forum['allowimgcode'], 542 "allow_videocode" => $forum['allowvideocode'], 543 "filter_badwords" => 1 544 ); 545 546 if($mybb->user['uid'] != 0 && $mybb->user['showimages'] != 1 || $mybb->settings['guestimages'] != 1 && $mybb->user['uid'] == 0) 547 { 548 $parser_options['allow_imgcode'] = 0; 549 } 550 551 if($mybb->user['uid'] != 0 && $mybb->user['showvideos'] != 1 || $mybb->settings['guestvideos'] != 1 && $mybb->user['uid'] == 0) 552 { 553 $parser_options['allow_videocode'] = 0; 554 } 555 556 $option = $parser->parse_message($optionsarray[$i-1], $parser_options); 557 $votes = $votesarray[$i-1]; 558 $totalvotes += $votes; 559 $number = $i; 560 561 // Mark the option the user voted for. 562 if(!empty($votedfor[$number])) 563 { 564 $optionbg = "trow2 poll_votedfor"; 565 $votestar = "*"; 566 } 567 else 568 { 569 $optionbg = "trow1"; 570 $votestar = ""; 571 } 572 573 // If the user already voted or if the results need to be shown, do so; else show voting screen. 574 if(isset($alreadyvoted) || isset($showresults)) 575 { 576 if((int)$votes == "0") 577 { 578 $percent = "0"; 579 } 580 else 581 { 582 $percent = number_format($votes / $poll['totvotes'] * 100, 2); 583 } 584 $imagewidth = round($percent); 585 eval("\$polloptions .= \"".$templates->get("showthread_poll_resultbit")."\";"); 586 } 587 else 588 { 589 if($poll['multiple'] == 1) 590 { 591 eval("\$polloptions .= \"".$templates->get("showthread_poll_option_multiple")."\";"); 592 } 593 else 594 { 595 eval("\$polloptions .= \"".$templates->get("showthread_poll_option")."\";"); 596 } 597 } 598 } 599 600 // If there are any votes at all, all votes together will be 100%; if there are no votes, all votes together will be 0%. 601 if($poll['totvotes']) 602 { 603 $totpercent = "100%"; 604 } 605 else 606 { 607 $totpercent = "0%"; 608 } 609 610 // Check if user is allowed to edit posts; if so, show "edit poll" link. 611 $edit_poll = ''; 612 if(is_moderator($fid, 'canmanagepolls')) 613 { 614 eval("\$edit_poll = \"".$templates->get("showthread_poll_editpoll")."\";"); 615 } 616 617 // Decide what poll status to show depending on the status of the poll and whether or not the user voted already. 618 if(isset($alreadyvoted) || isset($showresults) || isset($nopermission)) 619 { 620 $undovote = ''; 621 622 if(isset($alreadyvoted)) 623 { 624 $pollstatus = $lang->already_voted; 625 626 if($mybb->usergroup['canundovotes'] == 1) 627 { 628 eval("\$undovote = \"".$templates->get("showthread_poll_undovote")."\";"); 629 } 630 } 631 elseif(isset($nopermission)) 632 { 633 $pollstatus = $lang->no_voting_permission; 634 } 635 else 636 { 637 $pollstatus = $lang->poll_closed; 638 } 639 640 $lang->total_votes = $lang->sprintf($lang->total_votes, $totalvotes); 641 eval("\$pollbox = \"".$templates->get("showthread_poll_results")."\";"); 642 $plugins->run_hooks("showthread_poll_results"); 643 } 644 else 645 { 646 $closeon = ' '; 647 if($poll['timeout'] != 0) 648 { 649 $closeon = $lang->sprintf($lang->poll_closes, my_date($mybb->settings['dateformat'], $expiretime)); 650 } 651 652 $publicnote = ' '; 653 if($poll['public'] == 1) 654 { 655 $publicnote = $lang->public_note; 656 } 657 658 eval("\$pollbox = \"".$templates->get("showthread_poll")."\";"); 659 $plugins->run_hooks("showthread_poll"); 660 } 661 662 } 663 else 664 { 665 $pollbox = ""; 666 } 667 668 // Create the forum jump dropdown box. 669 if($mybb->settings['enableforumjump'] != 0) 670 { 671 $forumjump = build_forum_jump("", $fid, 1); 672 } 673 674 // Fetch some links 675 $next_oldest_link = get_thread_link($tid, 0, "nextoldest"); 676 $next_newest_link = get_thread_link($tid, 0, "nextnewest"); 677 678 // Mark this thread as read 679 mark_thread_read($tid, $fid); 680 681 // If the forum is not open, show closed newreply button unless the user is a moderator of this forum. 682 $newthread = $newreply = ''; 683 if($forum['open'] != 0 && $forum['type'] == "f") 684 { 685 if($forumpermissions['canpostthreads'] != 0 && $mybb->user['suspendposting'] != 1) 686 { 687 eval("\$newthread = \"".$templates->get("showthread_newthread")."\";"); 688 } 689 690 // Show the appropriate reply button if this thread is open or closed 691 if($forumpermissions['canpostreplys'] != 0 && $mybb->user['suspendposting'] != 1 && ($thread['closed'] != 1 || is_moderator($fid, "canpostclosedthreads")) && ($thread['uid'] == $mybb->user['uid'] || empty($forumpermissions['canonlyreplyownthreads']))) 692 { 693 eval("\$newreply = \"".$templates->get("showthread_newreply")."\";"); 694 } 695 elseif($thread['closed'] == 1) 696 { 697 eval("\$newreply = \"".$templates->get("showthread_newreply_closed")."\";"); 698 } 699 } 700 701 // Create the admin tools dropdown box. 702 if($ismod == true) 703 { 704 $closeoption = $closelinkch = $stickch = ''; 705 706 if($thread['closed'] == 1) 707 { 708 $closelinkch = ' checked="checked"'; 709 } 710 711 if($thread['sticky']) 712 { 713 $stickch = ' checked="checked"'; 714 } 715 716 if(is_moderator($thread['fid'], "canopenclosethreads")) 717 { 718 eval("\$closeoption .= \"".$templates->get("showthread_quickreply_options_close")."\";"); 719 } 720 721 if(is_moderator($thread['fid'], "canstickunstickthreads")) 722 { 723 eval("\$closeoption .= \"".$templates->get("showthread_quickreply_options_stick")."\";"); 724 } 725 726 $inlinecount = "0"; 727 $inlinecookie = "inlinemod_thread".$tid; 728 729 $plugins->run_hooks("showthread_ismod"); 730 } 731 else 732 { 733 $modoptions = " "; 734 $inlinemod = $closeoption = ''; 735 } 736 737 // Increment the thread view. 738 if( 739 ( 740 $mybb->user['uid'] == 0 && 741 ( 742 ($session->is_spider == true && $mybb->settings['threadviews_countspiders'] == 1) || 743 ($session->is_spider == false && $mybb->settings['threadviews_countguests'] == 1) 744 ) 745 ) || 746 ( 747 $mybb->user['uid'] != 0 && 748 ($mybb->settings['threadviews_countthreadauthor'] == 1 || $mybb->user['uid'] != $thread['uid']) 749 ) 750 ) 751 { 752 if($mybb->settings['delayedthreadviews'] == 1) 753 { 754 $db->shutdown_query("INSERT INTO ".TABLE_PREFIX."threadviews (tid) VALUES('{$tid}')"); 755 } 756 else 757 { 758 $db->shutdown_query("UPDATE ".TABLE_PREFIX."threads SET views=views+1 WHERE tid='{$tid}'"); 759 } 760 ++$thread['views']; 761 } 762 763 // Work out the thread rating for this thread. 764 $rating = $ratethread = ''; 765 if($mybb->settings['allowthreadratings'] != 0 && $forum['allowtratings'] != 0) 766 { 767 $rated = 0; 768 $lang->load("ratethread"); 769 if($thread['numratings'] <= 0) 770 { 771 $thread['width'] = 0; 772 $thread['averagerating'] = 0; 773 $thread['numratings'] = 0; 774 } 775 else 776 { 777 $thread['averagerating'] = (float)round($thread['totalratings']/$thread['numratings'], 2); 778 $thread['width'] = (int)round($thread['averagerating'])*20; 779 $thread['numratings'] = (int)$thread['numratings']; 780 } 781 782 if($thread['numratings']) 783 { 784 // At least >someone< has rated this thread, was it me? 785 // Check if we have already voted on this thread - it won't show hover effect then. 786 $query = $db->simple_select("threadratings", "uid", "tid='{$tid}' AND uid='{$mybb->user['uid']}'"); 787 $rated = $db->fetch_field($query, 'uid'); 788 } 789 790 $not_rated = ''; 791 if(!$rated) 792 { 793 $not_rated = ' star_rating_notrated'; 794 } 795 796 $ratingvotesav = $lang->sprintf($lang->rating_average, $thread['numratings'], $thread['averagerating']); 797 eval("\$ratethread = \"".$templates->get("showthread_ratethread")."\";"); 798 } 799 800 // Can this user perform searches? If so, we can show them the "Search thread" form 801 if($forumpermissions['cansearch'] != 0) 802 { 803 eval("\$search_thread = \"".$templates->get("showthread_search")."\";"); 804 } 805 806 // Fetch the ignore list for the current user if they have one 807 $ignored_users = array(); 808 if($mybb->user['uid'] > 0 && $mybb->user['ignorelist'] != "") 809 { 810 $ignore_list = explode(',', $mybb->user['ignorelist']); 811 foreach($ignore_list as $uid) 812 { 813 $ignored_users[$uid] = 1; 814 } 815 } 816 817 // Which thread mode is our user using by default? 818 if(!empty($mybb->user['threadmode'])) 819 { 820 $defaultmode = $mybb->user['threadmode']; 821 } 822 else if($mybb->settings['threadusenetstyle'] == 1) 823 { 824 $defaultmode = 'threaded'; 825 } 826 else 827 { 828 $defaultmode = 'linear'; 829 } 830 831 // If mode is unset, set the default mode 832 if(!isset($mybb->input['mode'])) 833 { 834 $mybb->input['mode'] = $defaultmode; 835 } 836 837 // Threaded or linear display? 838 $threadexbox = ''; 839 if($mybb->get_input('mode') == 'threaded') 840 { 841 $thread_toggle = 'linear'; 842 $isfirst = 1; 843 844 // Are we linked to a specific pid? 845 if($mybb->input['pid']) 846 { 847 $where = "AND p.pid='".$mybb->input['pid']."'"; 848 } 849 else 850 { 851 $where = " ORDER BY dateline, pid LIMIT 0, 1"; 852 } 853 $query = $db->query(" 854 SELECT u.*, u.username AS userusername, p.*, f.*, r.reporters, eu.username AS editusername 855 FROM ".TABLE_PREFIX."posts p 856 LEFT JOIN ".TABLE_PREFIX."reportedcontent r ON (r.id=p.pid AND r.type='post' AND r.reportstatus != 1) 857 LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) 858 LEFT JOIN ".TABLE_PREFIX."userfields f ON (f.ufid=u.uid) 859 LEFT JOIN ".TABLE_PREFIX."users eu ON (eu.uid=p.edituid) 860 WHERE p.tid='$tid' $visibleonly_p $where 861 "); 862 $showpost = $db->fetch_array($query); 863 864 // Choose what pid to display. 865 if(!$mybb->input['pid']) 866 { 867 $mybb->input['pid'] = $showpost['pid']; 868 } 869 870 // Is there actually a pid to display? 871 if(!$showpost['pid']) 872 { 873 error($lang->error_invalidpost); 874 } 875 876 $attachcache = array(); 877 if($mybb->settings['enableattachments'] == 1 && $thread['attachmentcount'] > 0 || is_moderator($fid, 'caneditposts')) 878 { 879 // Get the attachments for this post. 880 $query = $db->simple_select("attachments", "*", "pid=".$mybb->input['pid']); 881 while($attachment = $db->fetch_array($query)) 882 { 883 $attachcache[$attachment['pid']][$attachment['aid']] = $attachment; 884 } 885 } 886 887 $multipage = ''; 888 889 // Build the threaded post display tree. 890 $query = $db->query(" 891 SELECT p.username, p.uid, p.pid, p.replyto, p.subject, p.dateline 892 FROM ".TABLE_PREFIX."posts p 893 WHERE p.tid='$tid' 894 $visibleonly_p 895 ORDER BY p.dateline, p.pid 896 "); 897 $postsdone = array(); 898 while($post = $db->fetch_array($query)) 899 { 900 if(empty($postsdone[$post['pid']])) 901 { 902 if($post['pid'] == $mybb->input['pid'] || ($isfirst && !$mybb->input['pid'])) 903 { 904 $postcounter = count($postsdone); 905 $isfirst = 0; 906 } 907 $tree[$post['replyto']][$post['pid']] = $post; 908 $postsdone[$post['pid']] = 1; 909 } 910 } 911 912 $threadedbits = buildtree(); 913 $posts = build_postbit($showpost); 914 eval("\$threadexbox = \"".$templates->get("showthread_threadedbox")."\";"); 915 $plugins->run_hooks("showthread_threaded"); 916 } 917 else // Linear display 918 { 919 $thread_toggle = 'threaded'; 920 $threadexbox = ''; 921 if(!$mybb->settings['postsperpage'] || (int)$mybb->settings['postsperpage'] < 1) 922 { 923 $mybb->settings['postsperpage'] = 20; 924 } 925 926 // Figure out if we need to display multiple pages. 927 $page = 1; 928 $perpage = $mybb->settings['postsperpage']; 929 if($mybb->get_input('page', MyBB::INPUT_INT) && $mybb->get_input('page') != "last") 930 { 931 $page = $mybb->get_input('page', MyBB::INPUT_INT); 932 } 933 934 if(!empty($mybb->input['pid'])) 935 { 936 $post = get_post($mybb->input['pid']); 937 if( 938 empty($post) || 939 ( 940 $post['visible'] == 0 && !( 941 is_moderator($post['fid'], 'canviewunapprove') || 942 ($mybb->user['uid'] && $post['uid'] == $mybb->user['uid'] && $mybb->settings['showownunapproved']) 943 ) 944 ) || 945 ($post['visible'] == -1 && !is_moderator($post['fid'], 'canviewdeleted') && $forumpermissions['canviewdeletionnotice'] == 0) 946 ) 947 { 948 $footer .= '<script type="text/javascript">$(function() { $.jGrowl(\''.$lang->error_invalidpost.'\', {theme: \'jgrowl_error\'}); });</script>'; 949 } 950 else 951 { 952 $query = $db->query(" 953 SELECT COUNT(p.dateline) AS count FROM ".TABLE_PREFIX."posts p 954 WHERE p.tid = '{$tid}' 955 AND p.dateline <= '{$post['dateline']}' 956 {$visibleonly_p} 957 "); 958 $result = $db->fetch_field($query, "count"); 959 if(($result % $perpage) == 0) 960 { 961 $page = $result / $perpage; 962 } 963 else 964 { 965 $page = (int)($result / $perpage) + 1; 966 } 967 } 968 } 969 970 // Recount replies if user is a moderator or can see the deletion notice to take into account unapproved/deleted posts. 971 if($visible_states != array("1")) 972 { 973 $cached_replies = $thread['replies']+$thread['unapprovedposts']+$thread['deletedposts']; 974 975 $query = $db->simple_select("posts p", "COUNT(*) AS replies", "p.tid='$tid' $visibleonly_p"); 976 $thread['replies'] = $db->fetch_field($query, 'replies')-1; 977 978 if(in_array('-1', $visible_states) && in_array('0', $visible_states)) 979 { 980 // The counters are wrong? Rebuild them 981 // This doesn't cover all cases however it is a good addition to the manual rebuild function 982 if($thread['replies'] != $cached_replies) 983 { 984 require_once MYBB_ROOT."/inc/functions_rebuild.php"; 985 rebuild_thread_counters($thread['tid']); 986 } 987 } 988 } 989 990 $postcount = (int)$thread['replies']+1; 991 $pages = $postcount / $perpage; 992 $pages = ceil($pages); 993 994 if($mybb->get_input('page') == "last") 995 { 996 $page = $pages; 997 } 998 999 if($page > $pages || $page <= 0) 1000 { 1001 $page = 1; 1002 } 1003 1004 if($page) 1005 { 1006 $start = ($page-1) * $perpage; 1007 } 1008 else 1009 { 1010 $start = 0; 1011 $page = 1; 1012 } 1013 $upper = $start+$perpage; 1014 1015 // Work out if we have terms to highlight 1016 $highlight = ""; 1017 $threadmode = ""; 1018 if($mybb->seo_support == true) 1019 { 1020 if($mybb->get_input('highlight')) 1021 { 1022 $highlight = "?highlight=".urlencode($mybb->get_input('highlight')); 1023 } 1024 1025 if($defaultmode != "linear") 1026 { 1027 if($mybb->get_input('highlight')) 1028 { 1029 $threadmode = "&mode=linear"; 1030 } 1031 else 1032 { 1033 $threadmode = "?mode=linear"; 1034 } 1035 } 1036 } 1037 else 1038 { 1039 if(!empty($mybb->input['highlight'])) 1040 { 1041 if(is_array($mybb->input['highlight'])) 1042 { 1043 foreach($mybb->input['highlight'] as $highlight_word) 1044 { 1045 $highlight .= "&highlight[]=".urlencode($highlight_word); 1046 } 1047 } 1048 else 1049 { 1050 $highlight = "&highlight=".urlencode($mybb->get_input('highlight')); 1051 } 1052 } 1053 1054 if($defaultmode != "linear") 1055 { 1056 $threadmode = "&mode=linear"; 1057 } 1058 } 1059 1060 $multipage = multipage($postcount, $perpage, $page, str_replace("{tid}", $tid, THREAD_URL_PAGED.$highlight.$threadmode)); 1061 1062 // Lets get the pids of the posts on this page. 1063 $pids = ""; 1064 $comma = ''; 1065 $query = $db->simple_select("posts p", "p.pid", "p.tid='$tid' $visibleonly_p", array('order_by' => 'p.dateline, p.pid', 'limit_start' => $start, 'limit' => $perpage)); 1066 while($getid = $db->fetch_array($query)) 1067 { 1068 // Set the ID of the first post on page to $pid if it doesn't hold any value 1069 // to allow this value to be used for Thread Mode/Linear Mode links 1070 // and ensure the user lands on the correct page after changing view mode 1071 if(empty($pid)) 1072 { 1073 $pid = $getid['pid']; 1074 } 1075 // Gather a comma separated list of post IDs 1076 $pids .= "$comma'{$getid['pid']}'"; 1077 $comma = ","; 1078 } 1079 if($pids) 1080 { 1081 $pids = "pid IN($pids)"; 1082 1083 $attachcache = array(); 1084 if($mybb->settings['enableattachments'] == 1 && $thread['attachmentcount'] > 0 || is_moderator($fid, 'caneditposts')) 1085 { 1086 // Now lets fetch all of the attachments for these posts. 1087 $query = $db->simple_select("attachments", "*", $pids); 1088 while($attachment = $db->fetch_array($query)) 1089 { 1090 $attachcache[$attachment['pid']][$attachment['aid']] = $attachment; 1091 } 1092 } 1093 } 1094 else 1095 { 1096 // If there are no pid's the thread is probably awaiting approval. 1097 error($lang->error_invalidthread); 1098 } 1099 1100 // Get the actual posts from the database here. 1101 $posts = ''; 1102 $query = $db->query(" 1103 SELECT u.*, u.username AS userusername, p.*, f.*, r.reporters, eu.username AS editusername 1104 FROM ".TABLE_PREFIX."posts p 1105 LEFT JOIN ".TABLE_PREFIX."reportedcontent r ON (r.id=p.pid AND r.type='post' AND r.reportstatus != 1) 1106 LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) 1107 LEFT JOIN ".TABLE_PREFIX."userfields f ON (f.ufid=u.uid) 1108 LEFT JOIN ".TABLE_PREFIX."users eu ON (eu.uid=p.edituid) 1109 WHERE $pids 1110 ORDER BY p.dateline, p.pid 1111 "); 1112 while($post = $db->fetch_array($query)) 1113 { 1114 if($thread['firstpost'] == $post['pid'] && $thread['visible'] == 0) 1115 { 1116 $post['visible'] = 0; 1117 } 1118 $posts .= build_postbit($post); 1119 $post = ''; 1120 } 1121 $plugins->run_hooks("showthread_linear"); 1122 } 1123 $lang->thread_toggle = $lang->{$thread_toggle}; 1124 1125 // Show the similar threads table if wanted. 1126 $similarthreads = ''; 1127 if($mybb->settings['showsimilarthreads'] != 0) 1128 { 1129 $own_perm = ''; 1130 if($forumpermissions['canonlyviewownthreads'] == 1) 1131 { 1132 $own_perm = " AND t.uid={$mybb->user['uid']}"; 1133 } 1134 1135 switch($db->type) 1136 { 1137 case "pgsql": 1138 $query = $db->query(" 1139 SELECT t.*, t.username AS threadusername, u.username 1140 FROM ".TABLE_PREFIX."threads t 1141 LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid = t.uid), plainto_tsquery ('".$db->escape_string($thread['subject'])."') AS query 1142 WHERE t.fid='{$thread['fid']}' AND t.tid!='{$thread['tid']}' AND t.visible='1' AND t.closed NOT LIKE 'moved|%' AND t.subject @@ query{$own_perm} 1143 ORDER BY t.lastpost DESC 1144 OFFSET 0 LIMIT {$mybb->settings['similarlimit']} 1145 "); 1146 break; 1147 default: 1148 $query = $db->query(" 1149 SELECT t.*, t.username AS threadusername, u.username, MATCH (t.subject) AGAINST ('".$db->escape_string($thread['subject'])."') AS relevance 1150 FROM ".TABLE_PREFIX."threads t 1151 LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid = t.uid) 1152 WHERE t.fid='{$thread['fid']}' AND t.tid!='{$thread['tid']}' AND t.visible='1' AND t.closed NOT LIKE 'moved|%'{$own_perm} AND MATCH (t.subject) AGAINST ('".$db->escape_string($thread['subject'])."') >= '{$mybb->settings['similarityrating']}' 1153 ORDER BY t.lastpost DESC 1154 LIMIT 0, {$mybb->settings['similarlimit']} 1155 "); 1156 } 1157 1158 $count = 0; 1159 $similarthreadbits = ''; 1160 $icon_cache = $cache->read("posticons"); 1161 while($similar_thread = $db->fetch_array($query)) 1162 { 1163 ++$count; 1164 $trow = alt_trow(); 1165 if($similar_thread['icon'] > 0 && $icon_cache[$similar_thread['icon']]) 1166 { 1167 $icon = $icon_cache[$similar_thread['icon']]; 1168 $icon['path'] = str_replace("{theme}", $theme['imgdir'], $icon['path']); 1169 $icon['path'] = htmlspecialchars_uni($icon['path']); 1170 $icon['name'] = htmlspecialchars_uni($icon['name']); 1171 eval("\$icon = \"".$templates->get("forumdisplay_thread_icon")."\";"); 1172 } 1173 else 1174 { 1175 $icon = " "; 1176 } 1177 if(!$similar_thread['username']) 1178 { 1179 $similar_thread['username'] = $similar_thread['profilelink'] = htmlspecialchars_uni($similar_thread['threadusername']); 1180 } 1181 else 1182 { 1183 $similar_thread['username'] = htmlspecialchars_uni($similar_thread['username']); 1184 $similar_thread['profilelink'] = build_profile_link($similar_thread['username'], $similar_thread['uid']); 1185 } 1186 1187 // If this thread has a prefix, insert a space between prefix and subject 1188 if($similar_thread['prefix'] != 0) 1189 { 1190 $prefix = build_prefixes($similar_thread['prefix']); 1191 if(!empty($prefix)) 1192 { 1193 $similar_thread['threadprefix'] = $prefix['displaystyle'].' '; 1194 } 1195 } 1196 else 1197 { 1198 $similar_thread['threadprefix'] = ''; 1199 } 1200 1201 $similar_thread['subject'] = $parser->parse_badwords($similar_thread['subject']); 1202 $similar_thread['subject'] = htmlspecialchars_uni($similar_thread['subject']); 1203 $similar_thread['threadlink'] = get_thread_link($similar_thread['tid']); 1204 $similar_thread['lastpostlink'] = get_thread_link($similar_thread['tid'], 0, "lastpost"); 1205 1206 $lastpostdate = my_date('relative', $similar_thread['lastpost']); 1207 $lastposter = $similar_thread['lastposter']; 1208 $lastposteruid = $similar_thread['lastposteruid']; 1209 1210 // Don't link to guest's profiles (they have no profile). 1211 if($lastposteruid == 0) 1212 { 1213 $lastposterlink = $lastposter; 1214 } 1215 else 1216 { 1217 $lastposterlink = build_profile_link($lastposter, $lastposteruid); 1218 } 1219 $similar_thread['replies'] = my_number_format($similar_thread['replies']); 1220 $similar_thread['views'] = my_number_format($similar_thread['views']); 1221 eval("\$similarthreadbits .= \"".$templates->get("showthread_similarthreads_bit")."\";"); 1222 } 1223 if($count) 1224 { 1225 eval("\$similarthreads = \"".$templates->get("showthread_similarthreads")."\";"); 1226 } 1227 } 1228 1229 // Decide whether or not to show quick reply. 1230 $quickreply = ''; 1231 if($forumpermissions['canpostreplys'] != 0 && $mybb->user['suspendposting'] != 1 && ($thread['closed'] != 1 || is_moderator($fid, "canpostclosedthreads")) && $mybb->settings['quickreply'] != 0 && $mybb->user['showquickreply'] != '0' && $forum['open'] != 0 && ($thread['uid'] == $mybb->user['uid'] || empty($forumpermissions['canonlyreplyownthreads']))) 1232 { 1233 $query = $db->simple_select("posts", "pid", "tid='{$tid}'", array("order_by" => "pid", "order_dir" => "desc", "limit" => 1)); 1234 $last_pid = $db->fetch_field($query, "pid"); 1235 1236 // Show captcha image for guests if enabled 1237 $captcha = ''; 1238 if($mybb->settings['captchaimage'] && !$mybb->user['uid']) 1239 { 1240 require_once MYBB_ROOT.'inc/class_captcha.php'; 1241 $post_captcha = new captcha(true, "post_captcha"); 1242 1243 if($post_captcha->html) 1244 { 1245 $captcha = $post_captcha->html; 1246 } 1247 } 1248 1249 $postoptionschecked = array('signature' => '', 'emailnotify' => ''); 1250 if($mybb->user['signature']) 1251 { 1252 $postoptionschecked['signature'] = 'checked="checked"'; 1253 } 1254 1255 // Hide signature option if no permission 1256 $option_signature = ''; 1257 if($mybb->usergroup['canusesig'] && !$mybb->user['suspendsignature']) 1258 { 1259 eval("\$option_signature = \"".$templates->get('showthread_quickreply_options_signature')."\";"); 1260 } 1261 1262 if(isset($mybb->user['emailnotify']) && $mybb->user['emailnotify'] == 1) 1263 { 1264 $postoptionschecked['emailnotify'] = 'checked="checked"'; 1265 } 1266 1267 $trow = alt_trow(); 1268 if($thread['closed'] == 1) 1269 { 1270 $trow = 'trow_shaded'; 1271 } 1272 1273 $moderation_notice = ''; 1274 if(!is_moderator($forum['fid'], "canapproveunapproveposts")) 1275 { 1276 if($forumpermissions['modposts'] == 1) 1277 { 1278 $moderation_text = $lang->moderation_forum_posts; 1279 eval('$moderation_notice = "'.$templates->get('global_moderation_notice').'";'); 1280 } 1281 1282 if($mybb->user['moderateposts'] == 1) 1283 { 1284 $moderation_text = $lang->moderation_user_posts; 1285 eval('$moderation_notice = "'.$templates->get('global_moderation_notice').'";'); 1286 } 1287 } 1288 1289 $posthash = md5($mybb->user['uid'].random_str()); 1290 1291 if(!isset($collapsedthead['quickreply'])) 1292 { 1293 $collapsedthead['quickreply'] = ''; 1294 } 1295 if(!isset($collapsedimg['quickreply'])) 1296 { 1297 $collapsedimg['quickreply'] = ''; 1298 } 1299 if(!isset($collapsed['quickreply_e'])) 1300 { 1301 $collapsed['quickreply_e'] = ''; 1302 } 1303 1304 $expaltext = (in_array("quickreply", $collapse)) ? $lang->expcol_expand : $lang->expcol_collapse; 1305 eval("\$quickreply = \"".$templates->get("showthread_quickreply")."\";"); 1306 } 1307 1308 $moderationoptions = ''; 1309 $threadnotesbox = $viewnotes = ''; 1310 1311 // If the user is a moderator, show the moderation tools. 1312 if($ismod) 1313 { 1314 $customthreadtools = $customposttools = $standardthreadtools = $standardposttools = ''; 1315 1316 if(!empty($thread['notes'])) 1317 { 1318 $thread['notes'] = nl2br(htmlspecialchars_uni($thread['notes'])); 1319 1320 if(strlen($thread['notes']) > 200) 1321 { 1322 eval("\$viewnotes = \"".$templates->get("showthread_threadnotes_viewnotes")."\";"); 1323 $thread['notes'] = my_substr($thread['notes'], 0, 200)."... {$viewnotes}"; 1324 } 1325 1326 $expaltext = (in_array("threadnotes", $collapse)) ? $lang->expcol_expand : $lang->expcol_collapse; 1327 eval("\$threadnotesbox = \"".$templates->get("showthread_threadnotes")."\";"); 1328 } 1329 1330 if(is_moderator($forum['fid'], "canusecustomtools") && (!empty($forum_stats[-1]['modtools']) || !empty($forum_stats[$forum['fid']]['modtools']))) 1331 { 1332 $gids = explode(',', $mybb->user['additionalgroups']); 1333 $gids[] = $mybb->user['usergroup']; 1334 $gids = array_filter(array_unique($gids)); 1335 $gidswhere = ''; 1336 switch($db->type) 1337 { 1338 case "pgsql": 1339 case "sqlite": 1340 foreach($gids as $gid) 1341 { 1342 $gid = (int)$gid; 1343 $gidswhere .= " OR ','||groups||',' LIKE '%,{$gid},%'"; 1344 } 1345 $query = $db->simple_select("modtools", 'tid, name, type', "(','||forums||',' LIKE '%,$fid,%' OR ','||forums||',' LIKE '%,-1,%' OR forums='') AND (groups='' OR ','||groups||',' LIKE '%,-1,%'{$gidswhere})"); 1346 break; 1347 default: 1348 foreach($gids as $gid) 1349 { 1350 $gid = (int)$gid; 1351 $gidswhere .= " OR CONCAT(',',`groups`,',') LIKE '%,{$gid},%'"; 1352 } 1353 $query = $db->simple_select("modtools", 'tid, name, type', "(CONCAT(',',forums,',') LIKE '%,$fid,%' OR CONCAT(',',forums,',') LIKE '%,-1,%' OR forums='') AND (`groups`='' OR CONCAT(',',`groups`,',') LIKE '%,-1,%'{$gidswhere})"); 1354 break; 1355 } 1356 1357 while($tool = $db->fetch_array($query)) 1358 { 1359 $tool['name'] = htmlspecialchars_uni($tool['name']); 1360 if($tool['type'] == 'p') 1361 { 1362 eval("\$customposttools .= \"".$templates->get("showthread_inlinemoderation_custom_tool")."\";"); 1363 } 1364 else 1365 { 1366 eval("\$customthreadtools .= \"".$templates->get("showthread_moderationoptions_custom_tool")."\";"); 1367 } 1368 } 1369 1370 // Build inline moderation dropdown 1371 if(!empty($customposttools)) 1372 { 1373 eval("\$customposttools = \"".$templates->get("showthread_inlinemoderation_custom")."\";"); 1374 } 1375 } 1376 1377 $inlinemodsoftdelete = $inlinemodrestore = $inlinemoddelete = $inlinemodmanage = $inlinemodapprove = ''; 1378 1379 if(is_moderator($forum['fid'], "cansoftdeleteposts")) 1380 { 1381 eval("\$inlinemodsoftdelete = \"".$templates->get("showthread_inlinemoderation_softdelete")."\";"); 1382 } 1383 1384 if(is_moderator($forum['fid'], "canrestoreposts")) 1385 { 1386 eval("\$inlinemodrestore = \"".$templates->get("showthread_inlinemoderation_restore")."\";"); 1387 } 1388 1389 if(is_moderator($forum['fid'], "candeleteposts")) 1390 { 1391 eval("\$inlinemoddelete = \"".$templates->get("showthread_inlinemoderation_delete")."\";"); 1392 } 1393 1394 if(is_moderator($forum['fid'], "canmanagethreads")) 1395 { 1396 eval("\$inlinemodmanage = \"".$templates->get("showthread_inlinemoderation_manage")."\";"); 1397 } 1398 1399 if(is_moderator($forum['fid'], "canapproveunapproveposts")) 1400 { 1401 eval("\$inlinemodapprove = \"".$templates->get("showthread_inlinemoderation_approve")."\";"); 1402 } 1403 1404 if(!empty($inlinemodsoftdelete) || !empty($inlinemodrestore) || !empty($inlinemoddelete) || !empty($inlinemodmanage) || !empty($inlinemodapprove)) 1405 { 1406 eval("\$standardposttools = \"".$templates->get("showthread_inlinemoderation_standard")."\";"); 1407 } 1408 1409 // Only show inline mod menu if there's options to show 1410 if(!empty($standardposttools) || !empty($customposttools)) 1411 { 1412 eval("\$inlinemod = \"".$templates->get("showthread_inlinemoderation")."\";"); 1413 } 1414 1415 // Build thread moderation dropdown 1416 if(!empty($customthreadtools)) 1417 { 1418 eval("\$customthreadtools = \"".$templates->get("showthread_moderationoptions_custom")."\";"); 1419 } 1420 1421 $openclosethread = $stickunstickthread = $deletethread = $threadnotes = $managethread = $adminpolloptions = $approveunapprovethread = $softdeletethread = ''; 1422 1423 if(is_moderator($forum['fid'], "canopenclosethreads")) 1424 { 1425 eval("\$openclosethread = \"".$templates->get("showthread_moderationoptions_openclose")."\";"); 1426 } 1427 1428 if(is_moderator($forum['fid'], "canstickunstickthreads")) 1429 { 1430 eval("\$stickunstickthread = \"".$templates->get("showthread_moderationoptions_stickunstick")."\";"); 1431 } 1432 1433 if(is_moderator($forum['fid'], "candeletethreads")) 1434 { 1435 eval("\$deletethread = \"".$templates->get("showthread_moderationoptions_delete")."\";"); 1436 } 1437 1438 if(is_moderator($forum['fid'], "canmanagethreads")) 1439 { 1440 eval("\$threadnotes = \"".$templates->get("showthread_moderationoptions_threadnotes")."\";"); 1441 eval("\$managethread = \"".$templates->get("showthread_moderationoptions_manage")."\";"); 1442 } 1443 1444 if($pollbox && is_moderator($forum['fid'], "canmanagepolls")) 1445 { 1446 eval("\$adminpolloptions = \"".$templates->get("showthread_moderationoptions_deletepoll")."\";"); 1447 } 1448 1449 if(is_moderator($forum['fid'], "canapproveunapprovethreads")) 1450 { 1451 if($thread['visible'] == 0) 1452 { 1453 eval("\$approveunapprovethread = \"".$templates->get("showthread_moderationoptions_approve")."\";"); 1454 } 1455 else 1456 { 1457 eval("\$approveunapprovethread = \"".$templates->get("showthread_moderationoptions_unapprove")."\";"); 1458 } 1459 } 1460 1461 if(is_moderator($forum['fid'], "cansoftdeletethreads") && $thread['visible'] != -1) 1462 { 1463 eval("\$softdeletethread = \"".$templates->get("showthread_moderationoptions_softdelete")."\";"); 1464 } 1465 elseif(is_moderator($forum['fid'], "canrestorethreads") && $thread['visible'] == -1) 1466 { 1467 eval("\$softdeletethread = \"".$templates->get("showthread_moderationoptions_restore")."\";"); 1468 } 1469 1470 if(!empty($openclosethread) || !empty($stickunstickthread) || !empty($deletethread) || !empty($managethread) || !empty($adminpolloptions) || !empty($approveunapprovethread) || !empty($softdeletethread)) 1471 { 1472 eval("\$standardthreadtools = \"".$templates->get("showthread_moderationoptions_standard")."\";"); 1473 } 1474 1475 // Only show mod menu if there's any options to show 1476 if(!empty($standardthreadtools) || !empty($customthreadtools)) 1477 { 1478 eval("\$moderationoptions = \"".$templates->get("showthread_moderationoptions")."\";"); 1479 } 1480 } 1481 1482 eval("\$printthread = \"".$templates->get("showthread_printthread")."\";"); 1483 1484 // Display 'send thread' link if permissions allow 1485 $sendthread = ''; 1486 if($mybb->usergroup['cansendemail'] == 1) 1487 { 1488 eval("\$sendthread = \"".$templates->get("showthread_send_thread")."\";"); 1489 } 1490 1491 // Display 'add poll' link to thread creator (or mods) if thread doesn't have a poll already 1492 $addpoll = ''; 1493 $time = TIME_NOW; 1494 if(!$thread['poll'] && ($thread['uid'] == $mybb->user['uid'] || $ismod == true) && $forumpermissions['canpostpolls'] == 1 && $forum['open'] != 0 && $thread['closed'] != 1 && ($ismod == true || $thread['dateline'] > ($time-($mybb->settings['polltimelimit']*60*60)) || $mybb->settings['polltimelimit'] == 0)) 1495 { 1496 eval("\$addpoll = \"".$templates->get("showthread_add_poll")."\";"); 1497 } 1498 1499 // Subscription status 1500 $add_remove_subscription = 'add'; 1501 $add_remove_subscription_text = $lang->subscribe_thread; 1502 1503 if($mybb->user['uid']) 1504 { 1505 $query = $db->simple_select("threadsubscriptions", "tid", "tid='".(int)$tid."' AND uid='".(int)$mybb->user['uid']."'", array('limit' => 1)); 1506 1507 if($db->num_rows($query) > 0) 1508 { 1509 $add_remove_subscription = 'remove'; 1510 $add_remove_subscription_text = $lang->unsubscribe_thread; 1511 } 1512 1513 eval("\$addremovesubscription = \"".$templates->get("showthread_subscription")."\";"); 1514 } 1515 else 1516 { 1517 $addremovesubscription = ''; 1518 } 1519 1520 $classic_header = ''; 1521 if($mybb->settings['postlayout'] == "classic") 1522 { 1523 eval("\$classic_header = \"".$templates->get("showthread_classic_header")."\";"); 1524 } 1525 1526 // Get users viewing this thread 1527 if($mybb->settings['browsingthisthread'] != 0) 1528 { 1529 $timecut = TIME_NOW - $mybb->settings['wolcutoff']; 1530 1531 $comma = ''; 1532 $guestcount = 0; 1533 $membercount = 0; 1534 $inviscount = 0; 1535 $onlinemembers = ''; 1536 $doneusers = array(); 1537 1538 $query = $db->simple_select("sessions", "COUNT(DISTINCT ip) AS guestcount", "uid = 0 AND time > $timecut AND location2 = $tid AND nopermission != 1"); 1539 $guestcount = $db->fetch_field($query, 'guestcount'); 1540 1541 $query = $db->query(" 1542 SELECT 1543 s.ip, s.uid, s.time, u.username, u.invisible, u.usergroup, u.displaygroup 1544 FROM 1545 ".TABLE_PREFIX."sessions s 1546 LEFT JOIN ".TABLE_PREFIX."users u ON (s.uid=u.uid) 1547 WHERE s.uid != 0 AND s.time > '$timecut' AND location2='$tid' AND nopermission != 1 1548 ORDER BY u.username ASC, s.time DESC 1549 "); 1550 1551 while($user = $db->fetch_array($query)) 1552 { 1553 if(empty($doneusers[$user['uid']]) || $doneusers[$user['uid']] < $user['time']) 1554 { 1555 ++$membercount; 1556 $doneusers[$user['uid']] = $user['time']; 1557 1558 $invisiblemark = ''; 1559 if($user['invisible'] == 1 && $mybb->usergroup['canbeinvisible'] == 1) 1560 { 1561 $invisiblemark = "*"; 1562 ++$inviscount; 1563 } 1564 1565 if($user['invisible'] != 1 || $mybb->usergroup['canviewwolinvis'] == 1 || $user['uid'] == $mybb->user['uid']) 1566 { 1567 $user['profilelink'] = get_profile_link($user['uid']); 1568 $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); 1569 $user['reading'] = my_date($mybb->settings['timeformat'], $user['time']); 1570 1571 eval("\$onlinemembers .= \"".$templates->get("showthread_usersbrowsing_user", 1, 0)."\";"); 1572 $comma = $lang->comma; 1573 } 1574 } 1575 } 1576 1577 $guestsonline = ''; 1578 if($guestcount) 1579 { 1580 $guestsonline = $lang->sprintf($lang->users_browsing_thread_guests, $guestcount); 1581 } 1582 1583 $invisonline = ''; 1584 if($mybb->user['invisible'] == 1) 1585 { 1586 // the user was counted as invisible user --> correct the inviscount 1587 $inviscount -= 1; 1588 } 1589 if($inviscount && $mybb->usergroup['canviewwolinvis'] != 1) 1590 { 1591 $invisonline = $lang->sprintf($lang->users_browsing_thread_invis, $inviscount); 1592 } 1593 1594 $onlinesep = ''; 1595 if($invisonline != '' && $onlinemembers) 1596 { 1597 $onlinesep = $lang->comma; 1598 } 1599 1600 $onlinesep2 = ''; 1601 if($invisonline != '' && $guestcount || $onlinemembers && $guestcount) 1602 { 1603 $onlinesep2 = $lang->comma; 1604 } 1605 1606 eval("\$usersbrowsing = \"".$templates->get("showthread_usersbrowsing")."\";"); 1607 } 1608 1609 $thread_deleted = 0; 1610 if($thread['visible'] == -1) 1611 { 1612 $thread_deleted = 1; 1613 } 1614 1615 $plugins->run_hooks("showthread_end"); 1616 1617 eval("\$showthread = \"".$templates->get("showthread")."\";"); 1618 output_page($showthread); 1619} 1620 1621/** 1622 * Build a navigation tree for threaded display. 1623 * 1624 * @param int $replyto 1625 * @param int $indent 1626 * @return string 1627 */ 1628function buildtree($replyto=0, $indent=0) 1629{ 1630 global $tree, $mybb, $theme, $mybb, $pid, $tid, $templates, $parser, $lang; 1631 1632 $indentsize = 13 * $indent; 1633 1634 ++$indent; 1635 $posts = ''; 1636 if(is_array($tree[$replyto])) 1637 { 1638 foreach($tree[$replyto] as $key => $post) 1639 { 1640 $postdate = my_date('relative', $post['dateline']); 1641 $post['subject'] = htmlspecialchars_uni($parser->parse_badwords($post['subject'])); 1642 1643 if(!$post['subject']) 1644 { 1645 $post['subject'] = "[".$lang->no_subject."]"; 1646 } 1647 1648 $post['username'] = htmlspecialchars_uni($post['username']); 1649 $post['profilelink'] = build_profile_link($post['username'], $post['uid']); 1650 1651 if($mybb->input['pid'] == $post['pid']) 1652 { 1653 eval("\$posts .= \"".$templates->get("showthread_threaded_bitactive")."\";"); 1654 } 1655 else 1656 { 1657 eval("\$posts .= \"".$templates->get("showthread_threaded_bit")."\";"); 1658 } 1659 1660 if(!empty($tree[$post['pid']])) 1661 { 1662 $posts .= buildtree($post['pid'], $indent); 1663 } 1664 } 1665 --$indent; 1666 } 1667 return $posts; 1668} 1669