ReportToMod.php 14 KB

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