Browse Source

Clean up forum posting

- Check post size
- Use prepared queries
- Remove now-pointless injection protection
spaghetti 1 year ago
parent
commit
2cf5334b4c
2 changed files with 83 additions and 98 deletions
  1. 14
    20
      classes/forums.class.php
  2. 69
    78
      sections/forums/take_reply.php

+ 14
- 20
classes/forums.class.php View File

@@ -3,12 +3,9 @@ class Forums {
3 3
   /**
4 4
    * Get information on a thread.
5 5
    *
6
-   * @param int $ThreadID
7
-   *          the thread ID.
8
-   * @param boolean $Return
9
-   *          indicates whether thread info should be returned.
10
-   * @param Boolean $SelectiveCache
11
-   *          cache thread info/
6
+   * @param int $ThreadID the thread ID.
7
+   * @param boolean $Return indicates whether thread info should be returned.
8
+   * @param Boolean $SelectiveCache cache thread info.
12 9
    * @return array holding thread information.
13 10
    */
14 11
   public static function get_thread_info($ThreadID, $Return = true, $SelectiveCache = false) {
@@ -29,8 +26,8 @@ class Forums {
29 26
         FROM forums_topics AS t
30 27
           JOIN forums_posts AS fp ON fp.TopicID = t.ID
31 28
           LEFT JOIN forums_polls AS p ON p.TopicID = t.ID
32
-        WHERE t.ID = '$ThreadID'
33
-        GROUP BY fp.TopicID");
29
+        WHERE t.ID = ?
30
+        GROUP BY fp.TopicID", $ThreadID);
34 31
       if (!G::$DB->has_results()) {
35 32
         G::$DB->set_query_id($QueryID);
36 33
         return null;
@@ -49,8 +46,8 @@ class Forums {
49 46
             ed.Username
50 47
             FROM forums_posts AS p
51 48
               LEFT JOIN users_main AS ed ON ed.ID = p.EditedUserID
52
-            WHERE p.TopicID = '$ThreadID'
53
-              AND p.ID = '" . $ThreadInfo['StickyPostID'] . "'");
49
+            WHERE p.TopicID = ?
50
+              AND p.ID = ?", $ThreadID, $ThreadInfo['StickyPostID']);
54 51
         list ($ThreadInfo['StickyPost']) = G::$DB->to_array(false, MYSQLI_ASSOC);
55 52
       }
56 53
       G::$DB->set_query_id($QueryID);
@@ -66,10 +63,8 @@ class Forums {
66 63
   /**
67 64
    * Checks whether user has permissions on a forum.
68 65
    *
69
-   * @param int $ForumID
70
-   *          the forum ID.
71
-   * @param string $Perm
72
-   *          the permissision to check, defaults to 'Read'
66
+   * @param int $ForumID the forum ID.
67
+   * @param string $Perm the permissision to check, defaults to 'Read'
73 68
    * @return boolean true if user has permission
74 69
    */
75 70
   public static function check_forumperm($ForumID, $Perm = 'Read') {
@@ -92,8 +87,7 @@ class Forums {
92 87
   /**
93 88
    * Gets basic info on a forum.
94 89
    *
95
-   * @param int $ForumID
96
-   *          the forum ID.
90
+   * @param int $ForumID the forum ID.
97 91
    */
98 92
   public static function get_forum_info($ForumID) {
99 93
     $Forum = G::$Cache->get_value("ForumInfo_$ForumID");
@@ -108,8 +102,8 @@ class Forums {
108 102
           COUNT(forums_topics.ID) AS Topics
109 103
         FROM forums
110 104
           LEFT JOIN forums_topics ON forums_topics.ForumID = forums.ID
111
-        WHERE forums.ID = '$ForumID'
112
-        GROUP BY ForumID");
105
+        WHERE forums.ID = ?
106
+        GROUP BY ForumID", $ForumID);
113 107
       if (!G::$DB->has_results()) {
114 108
         return false;
115 109
       }
@@ -251,11 +245,11 @@ class Forums {
251 245
               FROM forums_posts AS p
252 246
               WHERE p.TopicID = l.TopicID
253 247
                 AND p.ID <= l.PostID
254
-            ) / $PerPage
248
+            ) / ?
255 249
           ) AS Page
256 250
         FROM forums_last_read_topics AS l
257 251
         WHERE l.TopicID IN(" . implode(',', $TopicIDs) . ") AND
258
-          l.UserID = '" . G::$LoggedUser['ID'] . "'");
252
+          l.UserID = ?", $PerPage, G::$LoggedUser['ID']);
259 253
       $LastRead = G::$DB->to_array('TopicID', MYSQLI_ASSOC);
260 254
       G::$DB->set_query_id($QueryID);
261 255
     } else {

+ 69
- 78
sections/forums/take_reply.php View File

@@ -5,7 +5,7 @@ authorize();
5 5
 /*********************************************************************\
6 6
 //--------------Take Post--------------------------------------------//
7 7
 
8
-This page takes a forum post submission, validates it (TODO), and
8
+This page takes a forum post submission, validates it, and
9 9
 enters it into the database. The user is then redirected to their
10 10
 post.
11 11
 
@@ -19,33 +19,18 @@ $_POST['action'] is what the user is trying to do. It can be:
19 19
 
20 20
 \*********************************************************************/
21 21
 
22
-// Quick SQL injection checks
23
-
24
-if (isset($LoggedUser['PostsPerPage'])) {
25
-  $PerPage = $LoggedUser['PostsPerPage'];
26
-} else {
27
-  $PerPage = POSTS_PER_PAGE;
28
-}
29
-
30
-if (isset($_POST['thread']) && !is_number($_POST['thread'])) {
31
-  error(0);
32
-}
33
-if (isset($_POST['forum']) && !is_number($_POST['forum'])) {
34
-  error(0);
35
-}
36
-
37 22
 // If you're not sending anything, go back
38 23
 if ($_POST['body'] === '' || !isset($_POST['body'])) {
39 24
   header('Location: '.$_SERVER['HTTP_REFERER']);
40 25
   die();
41 26
 }
42 27
 
43
-$Body = $_POST['body'];
44
-
45 28
 if (!empty($LoggedUser['DisablePosting'])) {
46 29
   error('Your posting privileges have been removed.');
47 30
 }
48 31
 
32
+$PerPage = $LoggedUser['PostsPerPage'] ?? POSTS_PER_PAGE;
33
+$Body = $_POST['body'];
49 34
 $TopicID = $_POST['thread'];
50 35
 $ThreadInfo = Forums::get_thread_info($TopicID);
51 36
 if ($ThreadInfo === null) {
@@ -60,6 +45,9 @@ if (!Forums::check_forumperm($ForumID)) {
60 45
 if (!Forums::check_forumperm($ForumID, 'Write') || $LoggedUser['DisablePosting'] || $ThreadInfo['IsLocked'] == '1' && !check_perms('site_moderate_forums')) {
61 46
   error(403);
62 47
 }
48
+if (strlen($Body) > 500000) {
49
+  error('Your post is too large');
50
+}
63 51
 
64 52
 if (isset($_POST['subscribe']) && Subscriptions::has_subscribed($TopicID) === false) {
65 53
   Subscriptions::subscribe($TopicID);
@@ -71,27 +59,27 @@ if ($ThreadInfo['LastPostAuthorID'] == $LoggedUser['ID'] && ((!check_perms('site
71 59
   $DB->query("
72 60
     SELECT ID, Body
73 61
     FROM forums_posts
74
-    WHERE TopicID = '$TopicID'
75
-      AND AuthorID = '".$LoggedUser['ID']."'
62
+    WHERE TopicID = ?
63
+      AND AuthorID = ?
76 64
     ORDER BY ID DESC
77
-    LIMIT 1");
65
+    LIMIT 1", $TopicID, $LoggedUser['ID']);
78 66
   list($PostID, $OldBody) = $DB->next_record(MYSQLI_NUM, false);
79 67
 
80 68
   //Edit the post
81 69
   $DB->query("
82 70
     UPDATE forums_posts
83 71
     SET
84
-      Body = CONCAT(Body,'\n\n".db_string($Body)."'),
85
-      EditedUserID = '".$LoggedUser['ID']."',
86
-      EditedTime = '$SQLTime'
87
-    WHERE ID = '$PostID'");
72
+      Body = CONCAT(Body, '\n\n', ?),
73
+      EditedUserID = ?,
74
+      EditedTime = ?
75
+    WHERE ID = ?", $Body, $LoggedUser['ID'], $SQLTime, $PostID);
88 76
 
89 77
   //Store edit history
90 78
   $DB->query("
91 79
     INSERT INTO comments_edits
92 80
       (Page, PostID, EditUser, EditTime, Body)
93 81
     VALUES
94
-      ('forums', $PostID, ".$LoggedUser['ID'].", '$SQLTime', '".db_string($OldBody)."')");
82
+      ('forums', ?, ?, ?, ?)", $PostID, $LoggedUser['ID'], $SQLTime, $OldBody);
95 83
   $Cache->delete_value("forums_edits_$PostID");
96 84
 
97 85
   //Get the catalogue it is in
@@ -104,7 +92,7 @@ if ($ThreadInfo['LastPostAuthorID'] == $LoggedUser['ID'] && ((!check_perms('site
104 92
     $Key = ($ThreadInfo['Posts'] % THREAD_CATALOGUE) - 1;
105 93
   }
106 94
   if ($ThreadInfo['StickyPostID'] == $PostID) {
107
-    $ThreadInfo['StickyPost']['Body'] .= "\n\n$Body";
95
+    $ThreadInfo['StickyPost']['Body'] .= "\n\n".$Body;
108 96
     $ThreadInfo['StickyPost']['EditedUserID'] = $LoggedUser['ID'];
109 97
     $ThreadInfo['StickyPost']['EditedTime'] = $SQLTime;
110 98
     $Cache->cache_value("thread_$TopicID".'_info', $ThreadInfo, 0);
@@ -112,12 +100,12 @@ if ($ThreadInfo['LastPostAuthorID'] == $LoggedUser['ID'] && ((!check_perms('site
112 100
 
113 101
   //Edit the post in the cache
114 102
   $Cache->begin_transaction("thread_$TopicID"."_catalogue_$CatalogueID");
115
-  $Cache->update_row($Key, array(
116
-      'Body' => $Cache->MemcacheDBArray[$Key]['Body']."\n\n$Body",
117
-      'EditedUserID' => $LoggedUser['ID'],
118
-      'EditedTime' => $SQLTime,
119
-      'Username' => $LoggedUser['Username']
120
-      ));
103
+  $Cache->update_row($Key, [
104
+    'Body' => $Cache->MemcacheDBArray[$Key]['Body']."\n\n$Body",
105
+    'EditedUserID' => $LoggedUser['ID'],
106
+    'EditedTime' => $SQLTime,
107
+    'Username' => $LoggedUser['Username']
108
+  ]);
121 109
   $Cache->commit_transaction(0);
122 110
 
123 111
 //Now we're dealing with a normal post
@@ -125,7 +113,8 @@ if ($ThreadInfo['LastPostAuthorID'] == $LoggedUser['ID'] && ((!check_perms('site
125 113
   //Insert the post into the posts database
126 114
   $DB->query("
127 115
     INSERT INTO forums_posts (TopicID, AuthorID, AddedTime, Body)
128
-    VALUES ('$TopicID', '".$LoggedUser['ID']."', '$SQLTime', '".db_string($Body)."')");
116
+    VALUES (?, ?, ?, ?)",
117
+    $TopicID, $LoggedUser['ID'], $SQLTime, $Body);
129 118
 
130 119
   $PostID = $DB->inserted_id();
131 120
 
@@ -134,21 +123,21 @@ if ($ThreadInfo['LastPostAuthorID'] == $LoggedUser['ID'] && ((!check_perms('site
134 123
     UPDATE forums
135 124
     SET
136 125
       NumPosts = NumPosts + 1,
137
-      LastPostID = '$PostID',
138
-      LastPostAuthorID = '".$LoggedUser['ID']."',
139
-      LastPostTopicID = '$TopicID',
140
-      LastPostTime = '$SQLTime'
141
-    WHERE ID = '$ForumID'");
126
+      LastPostID = ?,
127
+      LastPostAuthorID = ?,
128
+      LastPostTopicID = ?,
129
+      LastPostTime = ?
130
+    WHERE ID = ?", $PostID, $LoggedUser['ID'], $TopicID, $SQLTime, $ForumID);
142 131
 
143 132
   //Update the topic
144 133
   $DB->query("
145 134
     UPDATE forums_topics
146 135
     SET
147 136
       NumPosts = NumPosts + 1,
148
-      LastPostID = '$PostID',
149
-      LastPostAuthorID = '".$LoggedUser['ID']."',
150
-      LastPostTime = '$SQLTime'
151
-    WHERE ID = '$TopicID'");
137
+      LastPostID = ?,
138
+      LastPostAuthorID = ?,
139
+      LastPostTime = ?
140
+    WHERE ID = ?", $PostID, $LoggedUser['ID'], $SQLTime, $TopicID);
152 141
 
153 142
   // if cache exists modify it, if not, then it will be correct when selected next, and we can skip this block
154 143
   if ($Forum = $Cache->get_value("forums_$ForumID")) {
@@ -162,7 +151,7 @@ if ($ThreadInfo['LastPostAuthorID'] == $LoggedUser['ID'] && ((!check_perms('site
162 151
       $Thread['LastPostID'] = $PostID; // Set post ID for read/unread
163 152
       $Thread['LastPostTime'] = $SQLTime; // Time of last post
164 153
       $Thread['LastPostAuthorID'] = $LoggedUser['ID']; // Last poster ID
165
-      $Part2 = array($TopicID => $Thread); // Bumped thread
154
+      $Part2 = [$TopicID => $Thread]; // Bumped thread
166 155
 
167 156
     // if we're bumping from an older page
168 157
     } else {
@@ -182,20 +171,22 @@ if ($ThreadInfo['LastPostAuthorID'] == $LoggedUser['ID'] && ((!check_perms('site
182 171
             ISNULL(p.TopicID) AS NoPoll
183 172
           FROM forums_topics AS f
184 173
             LEFT JOIN forums_polls AS p ON p.TopicID = f.ID
185
-          WHERE f.ID = '$TopicID'");
174
+          WHERE f.ID = ?", $TopicID);
186 175
         list($AuthorID, $IsLocked, $IsSticky, $NumPosts, $NoPoll) = $DB->next_record();
187
-        $Part2 = array($TopicID => array(
188
-          'ID' => $TopicID,
189
-          'Title' => $ThreadInfo['Title'],
190
-          'AuthorID' => $AuthorID,
191
-          'IsLocked' => $IsLocked,
192
-          'IsSticky' => $IsSticky,
193
-          'NumPosts' => $NumPosts,
194
-          'LastPostID' => $PostID,
195
-          'LastPostTime' => $SQLTime,
196
-          'LastPostAuthorID' => $LoggedUser['ID'],
197
-          'NoPoll' => $NoPoll
198
-        )); //Bumped
176
+        $Part2 = [
177
+          $TopicID => [
178
+            'ID'               => $TopicID,
179
+            'Title'            => $ThreadInfo['Title'],
180
+            'AuthorID'         => $AuthorID,
181
+            'IsLocked'         => $IsLocked,
182
+            'IsSticky'         => $IsSticky,
183
+            'NumPosts'         => $NumPosts,
184
+            'LastPostID'       => $PostID,
185
+            'LastPostTime'     => $SQLTime,
186
+            'LastPostAuthorID' => $LoggedUser['ID'],
187
+            'NoPoll'           => $NoPoll
188
+          ]
189
+        ]; //Bumped
199 190
       } else {
200 191
         $Part2 = [];
201 192
       }
@@ -218,20 +209,20 @@ if ($ThreadInfo['LastPostAuthorID'] == $LoggedUser['ID'] && ((!check_perms('site
218 209
     } else {
219 210
       $Forum = $Part1 + $Part2 + $Part3; //Merge it
220 211
     }
221
-    $Cache->cache_value("forums_$ForumID", array($Forum, '', 0, $Stickies), 0);
212
+    $Cache->cache_value("forums_$ForumID", [$Forum, '', 0, $Stickies], 0);
222 213
 
223 214
     //Update the forum root
224 215
     $Cache->begin_transaction('forums_list');
225
-    $Cache->update_row($ForumID, array(
226
-      'NumPosts'=>'+1',
227
-      'LastPostID'=>$PostID,
228
-      'LastPostAuthorID'=>$LoggedUser['ID'],
229
-      'LastPostTopicID'=>$TopicID,
230
-      'LastPostTime'=>$SQLTime,
231
-      'Title'=>$ThreadInfo['Title'],
232
-      'IsLocked'=>$ThreadInfo['IsLocked'],
233
-      'IsSticky'=>$ThreadInfo['IsSticky']
234
-      ));
216
+    $Cache->update_row($ForumID, [
217
+      'NumPosts'         => '+1',
218
+      'LastPostID'       => $PostID,
219
+      'LastPostAuthorID' => $LoggedUser['ID'],
220
+      'LastPostTopicID'  => $TopicID,
221
+      'LastPostTime'     => $SQLTime,
222
+      'Title'            => $ThreadInfo['Title'],
223
+      'IsLocked'         => $ThreadInfo['IsLocked'],
224
+      'IsSticky'         => $ThreadInfo['IsSticky']
225
+    ]);
235 226
     $Cache->commit_transaction(0);
236 227
   } else {
237 228
     //If there's no cache, we have no data, and if there's no data
@@ -244,20 +235,20 @@ if ($ThreadInfo['LastPostAuthorID'] == $LoggedUser['ID'] && ((!check_perms('site
244 235
 
245 236
   //Insert the post into the thread catalogue (block of 500 posts)
246 237
   $Cache->begin_transaction("thread_$TopicID"."_catalogue_$CatalogueID");
247
-  $Cache->insert('', array(
248
-    'ID'=>$PostID,
249
-    'AuthorID'=>$LoggedUser['ID'],
250
-    'AddedTime'=>$SQLTime,
251
-    'Body'=>$Body,
252
-    'EditedUserID'=>0,
253
-    'EditedTime'=>NULL,
254
-    'Username'=>$LoggedUser['Username'] //TODO: Remove, it's never used?
255
-    ));
238
+  $Cache->insert('', [
239
+    'ID'           => $PostID,
240
+    'AuthorID'     => $LoggedUser['ID'],
241
+    'AddedTime'    => $SQLTime,
242
+    'Body'         => $Body,
243
+    'EditedUserID' => 0,
244
+    'EditedTime'   => NULL,
245
+    'Username'     => $LoggedUser['Username'] //TODO: Remove, it's never used?
246
+  ]);
256 247
   $Cache->commit_transaction(0);
257 248
 
258 249
   //Update the thread info
259 250
   $Cache->begin_transaction("thread_$TopicID".'_info');
260
-  $Cache->update_row(false, array('Posts' => '+1', 'LastPostAuthorID' => $LoggedUser['ID']));
251
+  $Cache->update_row(false, ['Posts' => '+1', 'LastPostAuthorID' => $LoggedUser['ID']]);
261 252
   $Cache->commit_transaction(0);
262 253
 
263 254
   //Increment this now to make sure we redirect to the correct page

Loading…
Cancel
Save