BioTorrents.de’s version of Gazelle
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

thread.php 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. <?php
  2. # todo: Go through line by line
  3. // todo: Normalize thread_*_info don't need to waste all that ram on things that are already in other caches
  4. /**********|| Page to show individual threads || ********************************\
  5. Things to expect in $_GET:
  6. ThreadID: ID of the forum curently being browsed
  7. page: The page the user's on.
  8. page = 1 is the same as no page
  9. ********************************************************************************/
  10. //---------- Things to sort out before it can start printing/generating content
  11. // Check for lame SQL injection attempts
  12. if (!isset($_GET['threadid']) || !is_number($_GET['threadid'])) {
  13. if (isset($_GET['topicid']) && is_number($_GET['topicid'])) {
  14. $ThreadID = $_GET['topicid'];
  15. } elseif (isset($_GET['postid']) && is_number($_GET['postid'])) {
  16. $DB->query("
  17. SELECT TopicID
  18. FROM forums_posts
  19. WHERE ID = $_GET[postid]");
  20. list($ThreadID) = $DB->next_record();
  21. if ($ThreadID) {
  22. // Redirect postid to threadid when necessary
  23. header("Location: ajax.php?action=forum&type=viewthread&threadid=$ThreadID&postid=$_GET[postid]");
  24. error();
  25. } else {
  26. echo json_encode(array('status' => 'failure'));
  27. error();
  28. }
  29. } else {
  30. echo json_encode(array('status' => 'failure'));
  31. error();
  32. }
  33. } else {
  34. $ThreadID = $_GET['threadid'];
  35. }
  36. if (isset($_GET['pp'])) {
  37. $PerPage = $_GET['pp'];
  38. } elseif (isset($LoggedUser['PostsPerPage'])) {
  39. $PerPage = $LoggedUser['PostsPerPage'];
  40. } else {
  41. $PerPage = POSTS_PER_PAGE;
  42. }
  43. //---------- Get some data to start processing
  44. // Thread information, constant across all pages
  45. $ThreadInfo = Forums::get_thread_info($ThreadID, true, true);
  46. if ($ThreadInfo === null) {
  47. json_die('failure', 'no such thread exists');
  48. }
  49. $ForumID = $ThreadInfo['ForumID'];
  50. // Make sure they're allowed to look at the page
  51. if (!Forums::check_forumperm($ForumID)) {
  52. echo json_encode(array('status' => 'failure'));
  53. error();
  54. }
  55. // Post links utilize the catalogue & key params to prevent issues with custom posts per page
  56. if ($ThreadInfo['Posts'] > $PerPage) {
  57. if (isset($_GET['post']) && is_number($_GET['post'])) {
  58. $PostNum = $_GET['post'];
  59. } elseif (isset($_GET['postid']) && is_number($_GET['postid'])) {
  60. $DB->query("
  61. SELECT COUNT(ID)
  62. FROM forums_posts
  63. WHERE TopicID = $ThreadID
  64. AND ID <= $_GET[postid]");
  65. list($PostNum) = $DB->next_record();
  66. } else {
  67. $PostNum = 1;
  68. }
  69. } else {
  70. $PostNum = 1;
  71. }
  72. list($Page, $Limit) = Format::page_limit($PerPage, min($ThreadInfo['Posts'], $PostNum));
  73. if (($Page - 1) * $PerPage > $ThreadInfo['Posts']) {
  74. $Page = ceil($ThreadInfo['Posts'] / $PerPage);
  75. }
  76. list($CatalogueID, $CatalogueLimit) = Format::catalogue_limit($Page, $PerPage, THREAD_CATALOGUE);
  77. // Cache catalogue from which the page is selected, allows block caches and future ability to specify posts per page
  78. if (!$Catalogue = $Cache->get_value("thread_$ThreadID"."_catalogue_$CatalogueID")) {
  79. $DB->query("
  80. SELECT
  81. p.ID,
  82. p.AuthorID,
  83. p.AddedTime,
  84. p.Body,
  85. p.EditedUserID,
  86. p.EditedTime
  87. FROM forums_posts AS p
  88. WHERE p.TopicID = '$ThreadID'
  89. AND p.ID != '".$ThreadInfo['StickyPostID']."'
  90. LIMIT $CatalogueLimit");
  91. $Catalogue = $DB->to_array(false, MYSQLI_ASSOC);
  92. if (!$ThreadInfo['IsLocked'] || $ThreadInfo['IsSticky']) {
  93. $Cache->cache_value("thread_$ThreadID"."_catalogue_$CatalogueID", $Catalogue, 0);
  94. }
  95. }
  96. $Thread = Format::catalogue_select($Catalogue, $Page, $PerPage, THREAD_CATALOGUE);
  97. if ($_GET['updatelastread'] !== '0') {
  98. $LastPost = end($Thread);
  99. $LastPost = $LastPost['ID'];
  100. reset($Thread);
  101. if ($ThreadInfo['Posts'] <= $PerPage * $Page && $ThreadInfo['StickyPostID'] > $LastPost) {
  102. $LastPost = $ThreadInfo['StickyPostID'];
  103. }
  104. // Handle last read
  105. if (!$ThreadInfo['IsLocked'] || $ThreadInfo['IsSticky']) {
  106. $DB->query("
  107. SELECT PostID
  108. FROM forums_last_read_topics
  109. WHERE UserID = '$LoggedUser[ID]'
  110. AND TopicID = '$ThreadID'");
  111. list($LastRead) = $DB->next_record();
  112. if ($LastRead < $LastPost) {
  113. $DB->query("
  114. INSERT INTO forums_last_read_topics
  115. (UserID, TopicID, PostID)
  116. VALUES
  117. ('$LoggedUser[ID]', '$ThreadID', '".db_string($LastPost)."')
  118. ON DUPLICATE KEY UPDATE
  119. PostID = '$LastPost'");
  120. }
  121. }
  122. }
  123. // Handle subscriptions
  124. $UserSubscriptions = Subscriptions::get_subscriptions();
  125. if (empty($UserSubscriptions)) {
  126. $UserSubscriptions = [];
  127. }
  128. if (in_array($ThreadID, $UserSubscriptions)) {
  129. $Cache->delete_value('subscriptions_user_new_'.$LoggedUser['ID']);
  130. }
  131. $JsonPoll = [];
  132. if ($ThreadInfo['NoPoll'] === 0) {
  133. if (!list($Question, $Answers, $Votes, $Featured, $Closed) = $Cache->get_value("polls_$ThreadID")) {
  134. $DB->query("
  135. SELECT Question, Answers, Featured, Closed
  136. FROM forums_polls
  137. WHERE TopicID = '$ThreadID'");
  138. list($Question, $Answers, $Featured, $Closed) = $DB->next_record(MYSQLI_NUM, array(1));
  139. $Answers = unserialize($Answers);
  140. $DB->query("
  141. SELECT Vote, COUNT(UserID)
  142. FROM forums_polls_votes
  143. WHERE TopicID = '$ThreadID'
  144. GROUP BY Vote");
  145. $VoteArray = $DB->to_array(false, MYSQLI_NUM);
  146. $Votes = [];
  147. foreach ($VoteArray as $VoteSet) {
  148. list($Key, $Value) = $VoteSet;
  149. $Votes[$Key] = $Value;
  150. }
  151. foreach (array_keys($Answers) as $i) {
  152. if (!isset($Votes[$i])) {
  153. $Votes[$i] = 0;
  154. }
  155. }
  156. $Cache->cache_value("polls_$ThreadID", array($Question, $Answers, $Votes, $Featured, $Closed), 0);
  157. }
  158. if (!empty($Votes)) {
  159. $TotalVotes = array_sum($Votes);
  160. $MaxVotes = max($Votes);
  161. } else {
  162. $TotalVotes = 0;
  163. $MaxVotes = 0;
  164. }
  165. #$RevealVoters = in_array($ForumID, FORUMS_TO_REVEAL_VOTERS);
  166. // Polls lose the you voted arrow thingy
  167. $DB->query("
  168. SELECT Vote
  169. FROM forums_polls_votes
  170. WHERE UserID = '".$LoggedUser['ID']."'
  171. AND TopicID = '$ThreadID'");
  172. list($UserResponse) = $DB->next_record();
  173. if (!empty($UserResponse) && $UserResponse !== 0) {
  174. $Answers[$UserResponse] = '&rsaquo; '.$Answers[$UserResponse];
  175. } /* else {
  176. if (!empty($UserResponse) && $RevealVoters) {
  177. $Answers[$UserResponse] = '&rsaquo; '.$Answers[$UserResponse];
  178. }
  179. }
  180. */
  181. $JsonPoll['closed'] = ($Closed === 1);
  182. $JsonPoll['featured'] = $Featured;
  183. $JsonPoll['question'] = $Question;
  184. $JsonPoll['maxVotes'] = (int)$MaxVotes;
  185. $JsonPoll['totalVotes'] = $TotalVotes;
  186. $JsonPollAnswers = [];
  187. foreach ($Answers as $i => $Answer) {
  188. if (!empty($Votes[$i]) && $TotalVotes > 0) {
  189. $Ratio = $Votes[$i] / $MaxVotes;
  190. $Percent = $Votes[$i] / $TotalVotes;
  191. } else {
  192. $Ratio = 0;
  193. $Percent = 0;
  194. }
  195. $JsonPollAnswers[] = array(
  196. 'answer' => $Answer,
  197. 'ratio' => $Ratio,
  198. 'percent' => $Percent
  199. );
  200. }
  201. if ($UserResponse !== null || $Closed || $ThreadInfo['IsLocked'] || $LoggedUser['Class'] < $Forums[$ForumID]['MinClassWrite']) {
  202. $JsonPoll['voted'] = true;
  203. } else {
  204. $JsonPoll['voted'] = false;
  205. }
  206. $JsonPoll['answers'] = $JsonPollAnswers;
  207. }
  208. // Sqeeze in stickypost
  209. if ($ThreadInfo['StickyPostID']) {
  210. if ($ThreadInfo['StickyPostID'] !== $Thread[0]['ID']) {
  211. array_unshift($Thread, $ThreadInfo['StickyPost']);
  212. }
  213. if ($ThreadInfo['StickyPostID'] !== $Thread[count($Thread) - 1]['ID']) {
  214. $Thread[] = $ThreadInfo['StickyPost'];
  215. }
  216. }
  217. $JsonPosts = [];
  218. foreach ($Thread as $Key => $Post) {
  219. list($PostID, $AuthorID, $AddedTime, $Body, $EditedUserID, $EditedTime) = array_values($Post);
  220. list($AuthorID, $Username, $PermissionID, $Paranoia, $Artist, $Donor, $Warned, $Avatar, $Enabled, $UserTitle) = array_values(Users::user_info($AuthorID));
  221. $UserInfo = Users::user_info($EditedUserID);
  222. $JsonPosts[] = [
  223. 'postId' => (int)$PostID,
  224. 'addedTime' => $AddedTime,
  225. 'bbBody' => $Body,
  226. 'body' => Text::full_format($Body),
  227. 'editedUserId' => (int)$EditedUserID,
  228. 'editedTime' => $EditedTime,
  229. 'editedUsername' => $UserInfo['Username'],
  230. 'author' => [
  231. 'authorId' => (int)$AuthorID,
  232. 'authorName' => $Username,
  233. 'paranoia' => $Paranoia,
  234. 'artist' => $Artist === '1',
  235. 'donor' => $Donor === '1',
  236. 'warned' => (bool)$Warned,
  237. 'avatar' => $Avatar,
  238. 'enabled' => $Enabled === '2' ? false : true,
  239. 'userTitle' => $UserTitle
  240. ]
  241. ];
  242. }
  243. echo json_encode([
  244. 'status' => 'success',
  245. 'response' => [
  246. 'forumId' => (int)$ForumID,
  247. 'forumName' => $Forums[$ForumID]['Name'],
  248. 'threadId' => (int)$ThreadID,
  249. 'threadTitle' => display_str($ThreadInfo['Title']),
  250. 'subscribed' => in_array($ThreadID, $UserSubscriptions),
  251. 'locked' => $ThreadInfo['IsLocked'] === 1,
  252. 'sticky' => $ThreadInfo['IsSticky'] === 1,
  253. 'currentPage' => (int)$Page,
  254. 'pages' => ceil($ThreadInfo['Posts'] / $PerPage),
  255. 'poll' => empty($JsonPoll) ? null : $JsonPoll,
  256. 'posts' => $JsonPosts
  257. ]
  258. ]);