Browse Source

Clean up forum posting

- Check post size
- Use prepared queries
- Remove now-pointless injection protection
spaghetti 7 years 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
   /**
3
   /**
4
    * Get information on a thread.
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
    * @return array holding thread information.
9
    * @return array holding thread information.
13
    */
10
    */
14
   public static function get_thread_info($ThreadID, $Return = true, $SelectiveCache = false) {
11
   public static function get_thread_info($ThreadID, $Return = true, $SelectiveCache = false) {
29
         FROM forums_topics AS t
26
         FROM forums_topics AS t
30
           JOIN forums_posts AS fp ON fp.TopicID = t.ID
27
           JOIN forums_posts AS fp ON fp.TopicID = t.ID
31
           LEFT JOIN forums_polls AS p ON p.TopicID = t.ID
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
       if (!G::$DB->has_results()) {
31
       if (!G::$DB->has_results()) {
35
         G::$DB->set_query_id($QueryID);
32
         G::$DB->set_query_id($QueryID);
36
         return null;
33
         return null;
49
             ed.Username
46
             ed.Username
50
             FROM forums_posts AS p
47
             FROM forums_posts AS p
51
               LEFT JOIN users_main AS ed ON ed.ID = p.EditedUserID
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
         list ($ThreadInfo['StickyPost']) = G::$DB->to_array(false, MYSQLI_ASSOC);
51
         list ($ThreadInfo['StickyPost']) = G::$DB->to_array(false, MYSQLI_ASSOC);
55
       }
52
       }
56
       G::$DB->set_query_id($QueryID);
53
       G::$DB->set_query_id($QueryID);
66
   /**
63
   /**
67
    * Checks whether user has permissions on a forum.
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
    * @return boolean true if user has permission
68
    * @return boolean true if user has permission
74
    */
69
    */
75
   public static function check_forumperm($ForumID, $Perm = 'Read') {
70
   public static function check_forumperm($ForumID, $Perm = 'Read') {
92
   /**
87
   /**
93
    * Gets basic info on a forum.
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
   public static function get_forum_info($ForumID) {
92
   public static function get_forum_info($ForumID) {
99
     $Forum = G::$Cache->get_value("ForumInfo_$ForumID");
93
     $Forum = G::$Cache->get_value("ForumInfo_$ForumID");
108
           COUNT(forums_topics.ID) AS Topics
102
           COUNT(forums_topics.ID) AS Topics
109
         FROM forums
103
         FROM forums
110
           LEFT JOIN forums_topics ON forums_topics.ForumID = forums.ID
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
       if (!G::$DB->has_results()) {
107
       if (!G::$DB->has_results()) {
114
         return false;
108
         return false;
115
       }
109
       }
251
               FROM forums_posts AS p
245
               FROM forums_posts AS p
252
               WHERE p.TopicID = l.TopicID
246
               WHERE p.TopicID = l.TopicID
253
                 AND p.ID <= l.PostID
247
                 AND p.ID <= l.PostID
254
-            ) / $PerPage
248
+            ) / ?
255
           ) AS Page
249
           ) AS Page
256
         FROM forums_last_read_topics AS l
250
         FROM forums_last_read_topics AS l
257
         WHERE l.TopicID IN(" . implode(',', $TopicIDs) . ") AND
251
         WHERE l.TopicID IN(" . implode(',', $TopicIDs) . ") AND
258
-          l.UserID = '" . G::$LoggedUser['ID'] . "'");
252
+          l.UserID = ?", $PerPage, G::$LoggedUser['ID']);
259
       $LastRead = G::$DB->to_array('TopicID', MYSQLI_ASSOC);
253
       $LastRead = G::$DB->to_array('TopicID', MYSQLI_ASSOC);
260
       G::$DB->set_query_id($QueryID);
254
       G::$DB->set_query_id($QueryID);
261
     } else {
255
     } else {

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

5
 /*********************************************************************\
5
 /*********************************************************************\
6
 //--------------Take Post--------------------------------------------//
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
 enters it into the database. The user is then redirected to their
9
 enters it into the database. The user is then redirected to their
10
 post.
10
 post.
11
 
11
 
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
 // If you're not sending anything, go back
22
 // If you're not sending anything, go back
38
 if ($_POST['body'] === '' || !isset($_POST['body'])) {
23
 if ($_POST['body'] === '' || !isset($_POST['body'])) {
39
   header('Location: '.$_SERVER['HTTP_REFERER']);
24
   header('Location: '.$_SERVER['HTTP_REFERER']);
40
   die();
25
   die();
41
 }
26
 }
42
 
27
 
43
-$Body = $_POST['body'];
44
-
45
 if (!empty($LoggedUser['DisablePosting'])) {
28
 if (!empty($LoggedUser['DisablePosting'])) {
46
   error('Your posting privileges have been removed.');
29
   error('Your posting privileges have been removed.');
47
 }
30
 }
48
 
31
 
32
+$PerPage = $LoggedUser['PostsPerPage'] ?? POSTS_PER_PAGE;
33
+$Body = $_POST['body'];
49
 $TopicID = $_POST['thread'];
34
 $TopicID = $_POST['thread'];
50
 $ThreadInfo = Forums::get_thread_info($TopicID);
35
 $ThreadInfo = Forums::get_thread_info($TopicID);
51
 if ($ThreadInfo === null) {
36
 if ($ThreadInfo === null) {
60
 if (!Forums::check_forumperm($ForumID, 'Write') || $LoggedUser['DisablePosting'] || $ThreadInfo['IsLocked'] == '1' && !check_perms('site_moderate_forums')) {
45
 if (!Forums::check_forumperm($ForumID, 'Write') || $LoggedUser['DisablePosting'] || $ThreadInfo['IsLocked'] == '1' && !check_perms('site_moderate_forums')) {
61
   error(403);
46
   error(403);
62
 }
47
 }
48
+if (strlen($Body) > 500000) {
49
+  error('Your post is too large');
50
+}
63
 
51
 
64
 if (isset($_POST['subscribe']) && Subscriptions::has_subscribed($TopicID) === false) {
52
 if (isset($_POST['subscribe']) && Subscriptions::has_subscribed($TopicID) === false) {
65
   Subscriptions::subscribe($TopicID);
53
   Subscriptions::subscribe($TopicID);
71
   $DB->query("
59
   $DB->query("
72
     SELECT ID, Body
60
     SELECT ID, Body
73
     FROM forums_posts
61
     FROM forums_posts
74
-    WHERE TopicID = '$TopicID'
75
-      AND AuthorID = '".$LoggedUser['ID']."'
62
+    WHERE TopicID = ?
63
+      AND AuthorID = ?
76
     ORDER BY ID DESC
64
     ORDER BY ID DESC
77
-    LIMIT 1");
65
+    LIMIT 1", $TopicID, $LoggedUser['ID']);
78
   list($PostID, $OldBody) = $DB->next_record(MYSQLI_NUM, false);
66
   list($PostID, $OldBody) = $DB->next_record(MYSQLI_NUM, false);
79
 
67
 
80
   //Edit the post
68
   //Edit the post
81
   $DB->query("
69
   $DB->query("
82
     UPDATE forums_posts
70
     UPDATE forums_posts
83
     SET
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
   //Store edit history
77
   //Store edit history
90
   $DB->query("
78
   $DB->query("
91
     INSERT INTO comments_edits
79
     INSERT INTO comments_edits
92
       (Page, PostID, EditUser, EditTime, Body)
80
       (Page, PostID, EditUser, EditTime, Body)
93
     VALUES
81
     VALUES
94
-      ('forums', $PostID, ".$LoggedUser['ID'].", '$SQLTime', '".db_string($OldBody)."')");
82
+      ('forums', ?, ?, ?, ?)", $PostID, $LoggedUser['ID'], $SQLTime, $OldBody);
95
   $Cache->delete_value("forums_edits_$PostID");
83
   $Cache->delete_value("forums_edits_$PostID");
96
 
84
 
97
   //Get the catalogue it is in
85
   //Get the catalogue it is in
104
     $Key = ($ThreadInfo['Posts'] % THREAD_CATALOGUE) - 1;
92
     $Key = ($ThreadInfo['Posts'] % THREAD_CATALOGUE) - 1;
105
   }
93
   }
106
   if ($ThreadInfo['StickyPostID'] == $PostID) {
94
   if ($ThreadInfo['StickyPostID'] == $PostID) {
107
-    $ThreadInfo['StickyPost']['Body'] .= "\n\n$Body";
95
+    $ThreadInfo['StickyPost']['Body'] .= "\n\n".$Body;
108
     $ThreadInfo['StickyPost']['EditedUserID'] = $LoggedUser['ID'];
96
     $ThreadInfo['StickyPost']['EditedUserID'] = $LoggedUser['ID'];
109
     $ThreadInfo['StickyPost']['EditedTime'] = $SQLTime;
97
     $ThreadInfo['StickyPost']['EditedTime'] = $SQLTime;
110
     $Cache->cache_value("thread_$TopicID".'_info', $ThreadInfo, 0);
98
     $Cache->cache_value("thread_$TopicID".'_info', $ThreadInfo, 0);
112
 
100
 
113
   //Edit the post in the cache
101
   //Edit the post in the cache
114
   $Cache->begin_transaction("thread_$TopicID"."_catalogue_$CatalogueID");
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
   $Cache->commit_transaction(0);
109
   $Cache->commit_transaction(0);
122
 
110
 
123
 //Now we're dealing with a normal post
111
 //Now we're dealing with a normal post
125
   //Insert the post into the posts database
113
   //Insert the post into the posts database
126
   $DB->query("
114
   $DB->query("
127
     INSERT INTO forums_posts (TopicID, AuthorID, AddedTime, Body)
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
   $PostID = $DB->inserted_id();
119
   $PostID = $DB->inserted_id();
131
 
120
 
134
     UPDATE forums
123
     UPDATE forums
135
     SET
124
     SET
136
       NumPosts = NumPosts + 1,
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
   //Update the topic
132
   //Update the topic
144
   $DB->query("
133
   $DB->query("
145
     UPDATE forums_topics
134
     UPDATE forums_topics
146
     SET
135
     SET
147
       NumPosts = NumPosts + 1,
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
   // if cache exists modify it, if not, then it will be correct when selected next, and we can skip this block
142
   // if cache exists modify it, if not, then it will be correct when selected next, and we can skip this block
154
   if ($Forum = $Cache->get_value("forums_$ForumID")) {
143
   if ($Forum = $Cache->get_value("forums_$ForumID")) {
162
       $Thread['LastPostID'] = $PostID; // Set post ID for read/unread
151
       $Thread['LastPostID'] = $PostID; // Set post ID for read/unread
163
       $Thread['LastPostTime'] = $SQLTime; // Time of last post
152
       $Thread['LastPostTime'] = $SQLTime; // Time of last post
164
       $Thread['LastPostAuthorID'] = $LoggedUser['ID']; // Last poster ID
153
       $Thread['LastPostAuthorID'] = $LoggedUser['ID']; // Last poster ID
165
-      $Part2 = array($TopicID => $Thread); // Bumped thread
154
+      $Part2 = [$TopicID => $Thread]; // Bumped thread
166
 
155
 
167
     // if we're bumping from an older page
156
     // if we're bumping from an older page
168
     } else {
157
     } else {
182
             ISNULL(p.TopicID) AS NoPoll
171
             ISNULL(p.TopicID) AS NoPoll
183
           FROM forums_topics AS f
172
           FROM forums_topics AS f
184
             LEFT JOIN forums_polls AS p ON p.TopicID = f.ID
173
             LEFT JOIN forums_polls AS p ON p.TopicID = f.ID
185
-          WHERE f.ID = '$TopicID'");
174
+          WHERE f.ID = ?", $TopicID);
186
         list($AuthorID, $IsLocked, $IsSticky, $NumPosts, $NoPoll) = $DB->next_record();
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
       } else {
190
       } else {
200
         $Part2 = [];
191
         $Part2 = [];
201
       }
192
       }
218
     } else {
209
     } else {
219
       $Forum = $Part1 + $Part2 + $Part3; //Merge it
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
     //Update the forum root
214
     //Update the forum root
224
     $Cache->begin_transaction('forums_list');
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
     $Cache->commit_transaction(0);
226
     $Cache->commit_transaction(0);
236
   } else {
227
   } else {
237
     //If there's no cache, we have no data, and if there's no data
228
     //If there's no cache, we have no data, and if there's no data
244
 
235
 
245
   //Insert the post into the thread catalogue (block of 500 posts)
236
   //Insert the post into the thread catalogue (block of 500 posts)
246
   $Cache->begin_transaction("thread_$TopicID"."_catalogue_$CatalogueID");
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
   $Cache->commit_transaction(0);
247
   $Cache->commit_transaction(0);
257
 
248
 
258
   //Update the thread info
249
   //Update the thread info
259
   $Cache->begin_transaction("thread_$TopicID".'_info');
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
   $Cache->commit_transaction(0);
252
   $Cache->commit_transaction(0);
262
 
253
 
263
   //Increment this now to make sure we redirect to the correct page
254
   //Increment this now to make sure we redirect to the correct page

Loading…
Cancel
Save