1 | <?php |
||
2 | |||
3 | /** |
||
4 | * The functions in this file deal with reporting posts or profiles to mods and admins |
||
5 | * Simple Machines Forum (SMF) |
||
6 | * |
||
7 | * @package SMF |
||
8 | * @author Simple Machines https://www.simplemachines.org |
||
9 | * @copyright 2022 Simple Machines and individual contributors |
||
10 | * @license https://www.simplemachines.org/about/smf/license.php BSD |
||
11 | * |
||
12 | * @version 2.1.0 |
||
13 | */ |
||
14 | |||
15 | if (!defined('SMF')) |
||
16 | die('No direct access...'); |
||
17 | |||
18 | /** |
||
19 | * Report a post or profile to the moderator... ask for a comment. |
||
20 | * Gathers data from the user to report abuse to the moderator(s). |
||
21 | * Uses the ReportToModerator template, main sub template. |
||
22 | * Requires the report_any permission. |
||
23 | * Uses ReportToModerator2() if post data was sent. |
||
24 | * Accessed through ?action=reporttm. |
||
25 | */ |
||
26 | function ReportToModerator() |
||
27 | { |
||
28 | global $txt, $topic, $context, $smcFunc, $scripturl, $sourcedir; |
||
29 | |||
30 | $context['robot_no_index'] = true; |
||
31 | $context['comment_body'] = ''; |
||
32 | |||
33 | // No guests! |
||
34 | is_not_guest(); |
||
35 | |||
36 | // You can't use this if it's off or you are not allowed to do it. |
||
37 | // If we don't have the ID of something to report, we'll die with a no_access error below |
||
38 | if (isset($_REQUEST['msg'])) |
||
39 | isAllowedTo('report_any'); |
||
40 | elseif (isset($_REQUEST['u'])) |
||
41 | isAllowedTo('report_user'); |
||
42 | |||
43 | // Previewing or modifying? |
||
44 | if (isset($_POST['preview']) && !isset($_POST['save'])) |
||
45 | { |
||
46 | require_once($sourcedir . '/Subs-Post.php'); |
||
47 | |||
48 | // Set up the preview message. |
||
49 | $context['preview_message'] = $smcFunc['htmlspecialchars']($_POST['comment'], ENT_QUOTES); |
||
50 | preparsecode($context['preview_message']); |
||
51 | |||
52 | // We censor for your protection... |
||
53 | censorText($context['preview_message']); |
||
54 | } |
||
55 | |||
56 | // If they're posting, it should be processed by ReportToModerator2. |
||
57 | if ((isset($_POST[$context['session_var']]) || isset($_POST['save'])) && empty($context['post_errors']) && !isset($_POST['preview'])) |
||
58 | ReportToModerator2(); |
||
59 | |||
60 | // We need a message ID or user ID to check! |
||
61 | if (empty($_REQUEST['msg']) && empty($_REQUEST['mid']) && empty($_REQUEST['u'])) |
||
62 | fatal_lang_error('no_access', false); |
||
63 | |||
64 | // For compatibility, accept mid, but we should be using msg. (not the flavor kind!) |
||
65 | if (!empty($_REQUEST['msg']) || !empty($_REQUEST['mid'])) |
||
66 | $_REQUEST['msg'] = empty($_REQUEST['msg']) ? (int) $_REQUEST['mid'] : (int) $_REQUEST['msg']; |
||
67 | // msg and mid empty - assume we're reporting a user |
||
68 | elseif (!empty($_REQUEST['u'])) |
||
69 | $_REQUEST['u'] = (int) $_REQUEST['u']; |
||
70 | |||
71 | // Set up some form values |
||
72 | $context['report_type'] = isset($_REQUEST['msg']) ? 'msg' : 'u'; |
||
73 | $context['reported_item'] = isset($_REQUEST['msg']) ? $_REQUEST['msg'] : $_REQUEST['u']; |
||
74 | |||
75 | if (isset($_REQUEST['msg'])) |
||
76 | { |
||
77 | // Check the message's ID - don't want anyone reporting a post they can't even see! |
||
78 | $result = $smcFunc['db_query']('', ' |
||
79 | SELECT m.id_msg, m.id_member, t.id_member_started |
||
80 | FROM {db_prefix}messages AS m |
||
81 | INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic}) |
||
82 | WHERE m.id_msg = {int:id_msg} |
||
83 | AND m.id_topic = {int:current_topic} |
||
84 | LIMIT 1', |
||
85 | array( |
||
86 | 'current_topic' => $topic, |
||
87 | 'id_msg' => $_REQUEST['msg'], |
||
88 | ) |
||
89 | ); |
||
90 | if ($smcFunc['db_num_rows']($result) == 0) |
||
91 | fatal_lang_error('no_board', false); |
||
92 | |||
93 | list ($_REQUEST['msg'], $member, $starter) = $smcFunc['db_fetch_row']($result); |
||
94 | $smcFunc['db_free_result']($result); |
||
95 | |||
96 | // This is here so that the user could, in theory, be redirected back to the topic. |
||
97 | $context['start'] = $_REQUEST['start']; |
||
98 | $context['message_id'] = $_REQUEST['msg']; |
||
99 | |||
100 | // The submit URL is different for users than it is for posts |
||
101 | $context['submit_url'] = $scripturl . '?action=reporttm;msg=' . $_REQUEST['msg'] . ';topic=' . $topic; |
||
102 | } |
||
103 | else |
||
104 | { |
||
105 | // Check the user's ID |
||
106 | $result = $smcFunc['db_query']('', ' |
||
107 | SELECT id_member, real_name, member_name |
||
108 | FROM {db_prefix}members |
||
109 | WHERE id_member = {int:current_user}', |
||
110 | array( |
||
111 | 'current_user' => $_REQUEST['u'], |
||
112 | ) |
||
113 | ); |
||
114 | |||
115 | if ($smcFunc['db_num_rows']($result) == 0) |
||
116 | fatal_lang_error('no_user', false); |
||
117 | list($_REQUEST['u'], $display_name, $username) = $smcFunc['db_fetch_row']($result); |
||
118 | |||
119 | $context['current_user'] = $_REQUEST['u']; |
||
120 | $context['submit_url'] = $scripturl . '?action=reporttm;u=' . $_REQUEST['u']; |
||
121 | } |
||
122 | |||
123 | $context['comment_body'] = $smcFunc['htmlspecialchars']((!isset($_POST['comment']) ? '' : trim($_POST['comment'])), ENT_QUOTES); |
||
124 | |||
125 | $context['page_title'] = $context['report_type'] == 'msg' ? $txt['report_to_mod'] : sprintf($txt['report_profile'], $display_name); |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
![]() |
|||
126 | $context['notice'] = $context['report_type'] == 'msg' ? $txt['report_to_mod_func'] : $txt['report_profile_func']; |
||
127 | |||
128 | // Show the inputs for the comment, etc. |
||
129 | loadLanguage('Post'); |
||
130 | loadTemplate('ReportToMod'); |
||
131 | |||
132 | addInlineJavaScript(' |
||
133 | var error_box = $("#error_box"); |
||
134 | $("#report_comment").keyup(function() { |
||
135 | var post_too_long = $("#error_post_too_long"); |
||
136 | if ($(this).val().length > 254) |
||
137 | { |
||
138 | if (post_too_long.length == 0) |
||
139 | { |
||
140 | error_box.show(); |
||
141 | if ($.trim(error_box.html()) == \'\') |
||
142 | error_box.append("<ul id=\'error_list\'></ul>"); |
||
143 | |||
144 | $("#error_list").append("<li id=\'error_post_too_long\' class=\'error\'>" + ' . JavaScriptEscape($txt['post_too_long']) . ' + "</li>"); |
||
145 | } |
||
146 | } |
||
147 | else |
||
148 | { |
||
149 | post_too_long.remove(); |
||
150 | if ($("#error_list li").length == 0) |
||
151 | error_box.hide(); |
||
152 | } |
||
153 | });', true); |
||
154 | } |
||
155 | |||
156 | /** |
||
157 | * Send the emails. |
||
158 | * Sends off emails to all the moderators. |
||
159 | * Sends to administrators and global moderators. (1 and 2) |
||
160 | * Called by ReportToModerator(), and thus has the same permission and setting requirements as it does. |
||
161 | * Accessed through ?action=reporttm when posting. |
||
162 | */ |
||
163 | function ReportToModerator2() |
||
164 | { |
||
165 | global $txt, $sourcedir, $context, $smcFunc; |
||
166 | |||
167 | // Sorry, no guests allowed... Probably just trying to spam us anyway |
||
168 | is_not_guest(); |
||
169 | |||
170 | // You must have the proper permissions! |
||
171 | if (isset($_REQUEST['msg'])) |
||
172 | isAllowedTo('report_any'); |
||
173 | else |
||
174 | isAllowedTo('report_user'); |
||
175 | |||
176 | // Make sure they aren't spamming. |
||
177 | spamProtection('reporttm'); |
||
178 | |||
179 | require_once($sourcedir . '/Subs-Post.php'); |
||
180 | |||
181 | // Prevent double submission of this form. |
||
182 | checkSubmitOnce('check'); |
||
183 | |||
184 | // No errors, yet. |
||
185 | $post_errors = array(); |
||
186 | |||
187 | // Check their session. |
||
188 | if (checkSession('post', '', false) != '') |
||
189 | $post_errors[] = 'session_timeout'; |
||
190 | |||
191 | // Make sure we have a comment and it's clean. |
||
192 | if (!isset($_POST['comment']) || $smcFunc['htmltrim']($_POST['comment']) === '') |
||
193 | $post_errors[] = 'no_comment'; |
||
194 | |||
195 | $poster_comment = strtr($smcFunc['htmlspecialchars']($_POST['comment']), array("\r" => '', "\t" => '')); |
||
196 | |||
197 | if ($smcFunc['strlen']($poster_comment) > 254) |
||
198 | $post_errors[] = 'post_too_long'; |
||
199 | |||
200 | // Any errors? |
||
201 | if (!empty($post_errors)) |
||
202 | { |
||
203 | loadLanguage('Errors'); |
||
204 | |||
205 | $context['post_errors'] = array(); |
||
206 | foreach ($post_errors as $post_error) |
||
207 | $context['post_errors'][$post_error] = $txt['error_' . $post_error]; |
||
208 | |||
209 | return ReportToModerator(); |
||
210 | } |
||
211 | |||
212 | if (isset($_POST['msg'])) |
||
213 | { |
||
214 | // Handle this elsewhere to keep things from getting too long |
||
215 | reportPost($_POST['msg'], $poster_comment); |
||
216 | } |
||
217 | else |
||
218 | { |
||
219 | reportUser($_POST['u'], $poster_comment); |
||
220 | } |
||
221 | } |
||
222 | |||
223 | /** |
||
224 | * Actually reports a post using information specified from a form |
||
225 | * |
||
226 | * @param int $msg The ID of the post being reported |
||
227 | * @param string $reason The reason specified for reporting the post |
||
228 | */ |
||
229 | function reportPost($msg, $reason) |
||
230 | { |
||
231 | global $context, $smcFunc, $user_info, $topic; |
||
232 | |||
233 | // Get the basic topic information, and make sure they can see it. |
||
234 | $_POST['msg'] = (int) $msg; |
||
235 | |||
236 | $request = $smcFunc['db_query']('', ' |
||
237 | SELECT m.id_topic, m.id_board, m.subject, m.body, m.id_member AS id_poster, m.poster_name, mem.real_name |
||
238 | FROM {db_prefix}messages AS m |
||
239 | LEFT JOIN {db_prefix}members AS mem ON (m.id_member = mem.id_member) |
||
240 | WHERE m.id_msg = {int:id_msg} |
||
241 | AND m.id_topic = {int:current_topic} |
||
242 | LIMIT 1', |
||
243 | array( |
||
244 | 'current_topic' => $topic, |
||
245 | 'id_msg' => $_POST['msg'], |
||
246 | ) |
||
247 | ); |
||
248 | if ($smcFunc['db_num_rows']($request) == 0) |
||
249 | fatal_lang_error('no_board', false); |
||
250 | $message = $smcFunc['db_fetch_assoc']($request); |
||
251 | $smcFunc['db_free_result']($request); |
||
252 | |||
253 | $request = $smcFunc['db_query']('', ' |
||
254 | SELECT id_report, ignore_all |
||
255 | FROM {db_prefix}log_reported |
||
256 | WHERE id_msg = {int:id_msg} |
||
257 | AND (closed = {int:not_closed} OR ignore_all = {int:ignored}) |
||
258 | ORDER BY ignore_all DESC', |
||
259 | array( |
||
260 | 'id_msg' => $_POST['msg'], |
||
261 | 'not_closed' => 0, |
||
262 | 'ignored' => 1, |
||
263 | ) |
||
264 | ); |
||
265 | if ($smcFunc['db_num_rows']($request) != 0) |
||
266 | list ($id_report, $ignore) = $smcFunc['db_fetch_row']($request); |
||
267 | |||
268 | $smcFunc['db_free_result']($request); |
||
269 | |||
270 | // If we're just going to ignore these, then who gives a monkeys... |
||
271 | if (!empty($ignore)) |
||
272 | redirectexit('topic=' . $topic . '.msg' . $_POST['msg'] . '#msg' . $_POST['msg']); |
||
273 | |||
274 | // Already reported? My god, we could be dealing with a real rogue here... |
||
275 | if (!empty($id_report)) |
||
276 | $smcFunc['db_query']('', ' |
||
277 | UPDATE {db_prefix}log_reported |
||
278 | SET num_reports = num_reports + 1, time_updated = {int:current_time} |
||
279 | WHERE id_report = {int:id_report}', |
||
280 | array( |
||
281 | 'current_time' => time(), |
||
282 | 'id_report' => $id_report, |
||
283 | ) |
||
284 | ); |
||
285 | // Otherwise, we shall make one! |
||
286 | else |
||
287 | { |
||
288 | if (empty($message['real_name'])) |
||
289 | $message['real_name'] = $message['poster_name']; |
||
290 | |||
291 | $id_report = $smcFunc['db_insert']('', |
||
292 | '{db_prefix}log_reported', |
||
293 | array( |
||
294 | 'id_msg' => 'int', 'id_topic' => 'int', 'id_board' => 'int', 'id_member' => 'int', 'membername' => 'string', |
||
295 | 'subject' => 'string', 'body' => 'string', 'time_started' => 'int', 'time_updated' => 'int', |
||
296 | 'num_reports' => 'int', 'closed' => 'int', |
||
297 | ), |
||
298 | array( |
||
299 | $_POST['msg'], $message['id_topic'], $message['id_board'], $message['id_poster'], $message['real_name'], |
||
300 | $message['subject'], $message['body'], time(), time(), 1, 0, |
||
301 | ), |
||
302 | array('id_report'), |
||
303 | 1 |
||
304 | ); |
||
305 | } |
||
306 | |||
307 | // Now just add our report... |
||
308 | if ($id_report) |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
309 | { |
||
310 | $id_comment = $smcFunc['db_insert']('', |
||
311 | '{db_prefix}log_reported_comments', |
||
312 | array( |
||
313 | 'id_report' => 'int', 'id_member' => 'int', 'membername' => 'string', |
||
314 | 'member_ip' => 'inet', 'comment' => 'string', 'time_sent' => 'int', |
||
315 | ), |
||
316 | array( |
||
317 | $id_report, $user_info['id'], $user_info['name'], |
||
318 | $user_info['ip'], $reason, time(), |
||
319 | ), |
||
320 | array('id_comment'), |
||
321 | 1 |
||
322 | ); |
||
323 | |||
324 | // And get ready to notify people. |
||
325 | $smcFunc['db_insert']('insert', |
||
326 | '{db_prefix}background_tasks', |
||
327 | array('task_file' => 'string', 'task_class' => 'string', 'task_data' => 'string', 'claimed_time' => 'int'), |
||
328 | array('$sourcedir/tasks/MsgReport-Notify.php', 'MsgReport_Notify_Background', $smcFunc['json_encode'](array( |
||
329 | 'report_id' => $id_report, |
||
330 | 'msg_id' => $_POST['msg'], |
||
331 | 'topic_id' => $message['id_topic'], |
||
332 | 'board_id' => $message['id_board'], |
||
333 | 'sender_id' => $context['user']['id'], |
||
334 | 'sender_name' => $context['user']['name'], |
||
335 | 'time' => time(), |
||
336 | 'comment_id' => $id_comment, |
||
337 | )), 0), |
||
338 | array('id_task') |
||
339 | ); |
||
340 | } |
||
341 | |||
342 | // Keep track of when the mod reports get updated, that way we know when we need to look again. |
||
343 | updateSettings(array('last_mod_report_action' => time())); |
||
344 | |||
345 | // Back to the post we reported! |
||
346 | redirectexit('reportsent;topic=' . $topic . '.msg' . $_POST['msg'] . '#msg' . $_POST['msg']); |
||
347 | } |
||
348 | |||
349 | /** |
||
350 | * Actually reports a user's profile using information specified from a form |
||
351 | * |
||
352 | * @param int $id_member The ID of the member whose profile is being reported |
||
353 | * @param string $reason The reason specified by the reporter for this report |
||
354 | */ |
||
355 | function reportUser($id_member, $reason) |
||
356 | { |
||
357 | global $context, $smcFunc, $user_info; |
||
358 | |||
359 | // Get the basic topic information, and make sure they can see it. |
||
360 | $_POST['u'] = (int) $id_member; |
||
361 | |||
362 | $request = $smcFunc['db_query']('', ' |
||
363 | SELECT id_member, real_name, member_name |
||
364 | FROM {db_prefix}members |
||
365 | WHERE id_member = {int:id_member}', |
||
366 | array( |
||
367 | 'id_member' => $_POST['u'] |
||
368 | ) |
||
369 | ); |
||
370 | if ($smcFunc['db_num_rows']($request) == 0) |
||
371 | fatal_lang_error('no_user', false); |
||
372 | $user = $smcFunc['db_fetch_assoc']($request); |
||
373 | $smcFunc['db_free_result']($request); |
||
374 | |||
375 | $user_name = un_htmlspecialchars($user['real_name']) . ($user['real_name'] != $user['member_name'] ? ' (' . $user['member_name'] . ')' : ''); |
||
376 | |||
377 | $request = $smcFunc['db_query']('', ' |
||
378 | SELECT id_report, ignore_all |
||
379 | FROM {db_prefix}log_reported |
||
380 | WHERE id_member = {int:id_member} |
||
381 | AND id_msg = {int:not_a_reported_post} |
||
382 | AND (closed = {int:not_closed} OR ignore_all = {int:ignored}) |
||
383 | ORDER BY ignore_all DESC', |
||
384 | array( |
||
385 | 'id_member' => $_POST['u'], |
||
386 | 'not_a_reported_post' => 0, |
||
387 | 'not_closed' => 0, |
||
388 | 'ignored' => 1, |
||
389 | ) |
||
390 | ); |
||
391 | if ($smcFunc['db_num_rows']($request) != 0) |
||
392 | list ($id_report, $ignore) = $smcFunc['db_fetch_row']($request); |
||
393 | |||
394 | $smcFunc['db_free_result']($request); |
||
395 | |||
396 | // If we're just going to ignore these, then who gives a monkeys... |
||
397 | if (!empty($ignore)) |
||
398 | redirectexit('action=profile;u=' . $_POST['u']); |
||
399 | |||
400 | // Already reported? My god, we could be dealing with a real rogue here... |
||
401 | if (!empty($id_report)) |
||
402 | $smcFunc['db_query']('', ' |
||
403 | UPDATE {db_prefix}log_reported |
||
404 | SET num_reports = num_reports + 1, time_updated = {int:current_time} |
||
405 | WHERE id_report = {int:id_report}', |
||
406 | array( |
||
407 | 'current_time' => time(), |
||
408 | 'id_report' => $id_report, |
||
409 | ) |
||
410 | ); |
||
411 | // Otherwise, we shall make one! |
||
412 | else |
||
413 | { |
||
414 | $id_report = $smcFunc['db_insert']('', |
||
415 | '{db_prefix}log_reported', |
||
416 | array( |
||
417 | 'id_msg' => 'int', 'id_topic' => 'int', 'id_board' => 'int', 'id_member' => 'int', 'membername' => 'string', |
||
418 | 'subject' => 'string', 'body' => 'string', 'time_started' => 'int', 'time_updated' => 'int', |
||
419 | 'num_reports' => 'int', 'closed' => 'int', |
||
420 | ), |
||
421 | array( |
||
422 | 0, 0, 0, $user['id_member'], $user_name, |
||
423 | '', '', time(), time(), 1, 0, |
||
424 | ), |
||
425 | array('id_report'), |
||
426 | 1 |
||
427 | ); |
||
428 | } |
||
429 | |||
430 | // Now just add our report... |
||
431 | if ($id_report) |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
432 | { |
||
433 | $smcFunc['db_insert']('', |
||
434 | '{db_prefix}log_reported_comments', |
||
435 | array( |
||
436 | 'id_report' => 'int', 'id_member' => 'int', 'membername' => 'string', |
||
437 | 'member_ip' => 'inet', 'comment' => 'string', 'time_sent' => 'int', |
||
438 | ), |
||
439 | array( |
||
440 | $id_report, $user_info['id'], $user_info['name'], |
||
441 | $user_info['ip'], $reason, time(), |
||
442 | ), |
||
443 | array('id_comment') |
||
444 | ); |
||
445 | |||
446 | // And get ready to notify people. |
||
447 | $smcFunc['db_insert']('insert', |
||
448 | '{db_prefix}background_tasks', |
||
449 | array('task_file' => 'string', 'task_class' => 'string', 'task_data' => 'string', 'claimed_time' => 'int'), |
||
450 | array('$sourcedir/tasks/MemberReport-Notify.php', 'MemberReport_Notify_Background', $smcFunc['json_encode'](array( |
||
451 | 'report_id' => $id_report, |
||
452 | 'user_id' => $user['id_member'], |
||
453 | 'user_name' => $user_name, |
||
454 | 'sender_id' => $context['user']['id'], |
||
455 | 'sender_name' => $context['user']['name'], |
||
456 | 'comment' => $reason, |
||
457 | 'time' => time(), |
||
458 | )), 0), |
||
459 | array('id_task') |
||
460 | ); |
||
461 | } |
||
462 | |||
463 | // Keep track of when the mod reports get updated, that way we know when we need to look again. |
||
464 | updateSettings(array('last_mod_report_action' => time())); |
||
465 | |||
466 | // Back to the post we reported! |
||
467 | redirectexit('reportsent;action=profile;u=' . $id_member); |
||
468 | } |
||
469 | |||
470 | ?> |