weekly release 4.0dev
[moodle.git] / admin / tool / spamcleaner / index.php
1 <?php
3 /**
4  * Spam Cleaner
5  *
6  * Helps an admin to clean up spam in Moodle
7  *
8  * @author Dongsheng Cai
9  * @author Martin Dougiamas
10  * @author Amr Hourani
11  * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
12  */
14 // List of known spammy keywords, please add more here
16 /////////////////////////////////////////////////////////////////////////////////
18 require_once('../../../config.php');
19 require_once($CFG->libdir.'/adminlib.php');
22 // Configuration
24 $autokeywords = array(
25                     "<img",
26                     "fuck",
27                     "casino",
28                     "porn",
29                     "xxx",
30                     "cialis",
31                     "viagra",
32                     "poker",
33                     "warcraft"
34                 );
36 $keyword = optional_param('keyword', '', PARAM_RAW);
37 $autodetect = optional_param('autodetect', '', PARAM_RAW);
38 $del = optional_param('del', '', PARAM_RAW);
39 $delall = optional_param('delall', '', PARAM_RAW);
40 $ignore = optional_param('ignore', '', PARAM_RAW);
41 $reset = optional_param('reset', '', PARAM_RAW);
42 $id = optional_param('id', '', PARAM_INT);
44 admin_externalpage_setup('toolspamcleaner');
46 // Delete one user
47 if (!empty($del) && confirm_sesskey() && ($id != $USER->id)) {
48     if (isset($SESSION->users_result[$id])) {
49         $user = $SESSION->users_result[$id];
50         if (delete_user($user)) {
51             unset($SESSION->users_result[$id]);
52             echo json_encode(true);
53         } else {
54             echo json_encode(false);
55         }
56     } else {
57         echo json_encode(false);
58     }
59     exit;
60 }
62 // Delete lots of users
63 if (!empty($delall) && confirm_sesskey()) {
64     if (!empty($SESSION->users_result)) {
65         foreach ($SESSION->users_result as $userid => $user) {
66             if ($userid != $USER->id) {
67                 if (delete_user($user)) {
68                     unset($SESSION->users_result[$userid]);
69                 }
70             }
71         }
72     }
73     echo json_encode(true);
74     exit;
75 }
77 if (!empty($ignore) && confirm_sesskey()) {
78     unset($SESSION->users_result[$id]);
79     echo json_encode(true);
80     exit;
81 }
83 $PAGE->requires->js_init_call('M.tool_spamcleaner.init', array(me()), true);
84 $strings = Array('spaminvalidresult','spamdeleteallconfirm','spamcannotdelete','spamdeleteconfirm');
85 $PAGE->requires->strings_for_js($strings, 'tool_spamcleaner');
87 echo $OUTPUT->header();
89 // Print headers and things
90 echo $OUTPUT->box(get_string('spamcleanerintro', 'tool_spamcleaner'));
92 echo $OUTPUT->box_start();     // The forms section at the top
94 ?>
96 <div class="mdl-align">
98 <form method="post" action="index.php" class="form-inline spamcleanerform">
99   <div>
100     <label class="accesshide" for="keyword_el"><?php print_string('spamkeyword', 'tool_spamcleaner') ?></label>
101     <input type="text" class="form-control" name="keyword" id="keyword_el" value="<?php p($keyword) ?>" />
102     <input type="hidden" name="sesskey" value="<?php echo sesskey();?>" />
103     <input type="submit" class="btn btn-primary" value="<?php echo get_string('spamsearch', 'tool_spamcleaner')?>" />
104   </div>
105 </form>
106 <p><?php echo get_string('spameg', 'tool_spamcleaner');?></p>
108 <hr />
110 <form method="post"  action="index.php">
111   <div>
112     <input type="submit" class="btn btn-primary" name="autodetect"
113            value="<?php echo get_string('spamauto', 'tool_spamcleaner');?>" />
114   </div>
115 </form>
118 </div>
120 <?php
121 echo $OUTPUT->box_end();
123 echo '<div id="result" class="mdl-align">';
125 // Print list of resulting profiles
127 if (!empty($keyword)) {               // Use the keyword(s) supplied by the user
128     $keywords = explode(',', $keyword);
129     foreach ($keywords as $key => $keyword) {
130         $keywords[$key] = trim($keyword);
131     }
132     search_spammers($keywords);
134 } else if (!empty($autodetect)) {     // Use the inbuilt keyword list to detect users
135     search_spammers($autokeywords);
138 echo '</div>';
140 /////////////////////////////////////////////////////////////////////////////////
143 ///  Functions
146 function search_spammers($keywords) {
148     global $CFG, $USER, $DB, $OUTPUT;
150     if (!is_array($keywords)) {
151         $keywords = array($keywords);    // Make it into an array
152     }
154     $params = array('userid'=>$USER->id);
156     $keywordfull = array();
157     $i = 0;
158     foreach ($keywords as $keyword) {
159         $keywordfull[] = $DB->sql_like('description', ':descpat'.$i, false);
160         $params['descpat'.$i] = "%$keyword%";
161         $keywordfull2[] = $DB->sql_like('p.summary', ':sumpat'.$i, false);
162         $params['sumpat'.$i] = "%$keyword%";
163         $keywordfull3[] = $DB->sql_like('p.subject', ':subpat'.$i, false);
164         $params['subpat'.$i] = "%$keyword%";
165         $keywordfull4[] = $DB->sql_like('c.content', ':contpat'.$i, false);
166         $params['contpat'.$i] = "%$keyword%";
167         $keywordfull5[] = $DB->sql_like('m.fullmessage', ':msgpat'.$i, false);
168         $params['msgpat'.$i] = "%$keyword%";
169         $keywordfull6[] = $DB->sql_like('fp.message', ':forumpostpat'.$i, false);
170         $params['forumpostpat'.$i] = "%$keyword%";
171         $keywordfull7[] = $DB->sql_like('fp.subject', ':forumpostsubpat'.$i, false);
172         $params['forumpostsubpat'.$i] = "%$keyword%";
173         $i++;
174     }
175     $conditions = '( '.implode(' OR ', $keywordfull).' )';
176     $conditions2 = '( '.implode(' OR ', $keywordfull2).' )';
177     $conditions3 = '( '.implode(' OR ', $keywordfull3).' )';
178     $conditions4 = '( '.implode(' OR ', $keywordfull4).' )';
179     $conditions5 = '( '.implode(' OR ', $keywordfull5).' )';
180     $conditions6 = '( '.implode(' OR ', $keywordfull6).' )';
181     $conditions7 = '( '.implode(' OR ', $keywordfull7).' )';
183     $sql  = "SELECT *
184                FROM {user}
185               WHERE deleted = 0
186                     AND id <> :userid
187                     AND $conditions";  // Exclude oneself
188     $sql2 = "SELECT u.*, p.summary
189                FROM {user} u, {post} p
190               WHERE $conditions2
191                     AND u.deleted = 0
192                     AND u.id=p.userid
193                     AND u.id <> :userid";
194     $sql3 = "SELECT u.*, p.subject AS postsubject
195                FROM {user} u, {post} p
196               WHERE $conditions3
197                     AND u.deleted = 0
198                     AND u.id=p.userid
199                     AND u.id <> :userid";
200     $sql4 = "SELECT u.*, c.content
201                FROM {user} u, {comments} c
202                WHERE $conditions4
203                     AND u.deleted = 0
204                     AND u.id=c.userid
205                     AND u.id <> :userid";
206     $sql5 = "SELECT u.*, m.fullmessage
207                FROM {user} u, {message} m
208               WHERE $conditions5
209                     AND u.deleted = 0
210                     AND u.id=m.useridfrom
211                     AND u.id <> :userid";
212     $sql6 = "SELECT u.*, fp.message
213                FROM {user} u, {forum_posts} fp
214               WHERE $conditions6
215                     AND u.deleted = 0
216                     AND u.id=fp.userid
217                     AND u.id <> :userid";
218     $sql7 = "SELECT u.*, fp.subject
219                FROM {user} u, {forum_posts} fp
220               WHERE $conditions7
221                     AND u.deleted = 0
222                     AND u.id=fp.userid
223                     AND u.id <> :userid";
225     $spamusers_desc = $DB->get_recordset_sql($sql, $params);
226     $spamusers_blog = $DB->get_recordset_sql($sql2, $params);
227     $spamusers_blogsub = $DB->get_recordset_sql($sql3, $params);
228     $spamusers_comment = $DB->get_recordset_sql($sql4, $params);
229     $spamusers_message = $DB->get_recordset_sql($sql5, $params);
230     $spamusers_forumpost = $DB->get_recordset_sql($sql6, $params);
231     $spamusers_forumpostsub = $DB->get_recordset_sql($sql7, $params);
233     $keywordlist = implode(', ', $keywords);
234     echo $OUTPUT->box(get_string('spamresult', 'tool_spamcleaner').s($keywordlist)).' ...';
236     $recordsets = [
237         $spamusers_desc,
238         $spamusers_blog,
239         $spamusers_blogsub,
240         $spamusers_comment,
241         $spamusers_message,
242         $spamusers_forumpost,
243         $spamusers_forumpostsub
244     ];
245     print_user_list($recordsets, $keywords);
246     foreach ($recordsets as $rs) {
247         $rs->close();
248     }
253 function print_user_list($users_rs, $keywords) {
254     global $CFG, $SESSION;
256     // reset session everytime this function is called
257     $SESSION->users_result = array();
258     $count = 0;
260     foreach ($users_rs as $rs){
261         foreach ($rs as $user) {
262             if (!$count) {
263                 echo '<table class="table table-bordered" border="1" width="100%" id="data-grid"><tr><th>&nbsp;</th>
264                     <th>'.get_string('user', 'admin').'</th><th>'.get_string('spamdesc', 'tool_spamcleaner').'</th>
265                     <th>'.get_string('spamoperation', 'tool_spamcleaner').'</th></tr>';
266             }
267             $count++;
268             filter_user($user, $keywords, $count);
269         }
270     }
272     if (!$count) {
273         echo get_string('spamcannotfinduser', 'tool_spamcleaner');
275     } else {
276         echo '</table>';
277         echo '<div class="mld-align">
278               <button id="removeall_btn" class="btn btn-secondary">'.get_string('spamdeleteall', 'tool_spamcleaner').'</button>
279               </div>';
280     }
282 function filter_user($user, $keywords, $count) {
283     global $CFG;
284     $image_search = false;
285     if (in_array('<img', $keywords)) {
286         $image_search = true;
287     }
288     if (isset($user->summary)) {
289         $user->description = '<h3>'.get_string('spamfromblog', 'tool_spamcleaner').'</h3>'.$user->summary;
290         unset($user->summary);
291     } else if (isset($user->postsubject)) {
292         $user->description = '<h3>'.get_string('spamfromblog', 'tool_spamcleaner').'</h3>'.$user->postsubject;
293         unset($user->postsubject);
294     } else if (isset($user->content)) {
295         $user->description = '<h3>'.get_string('spamfromcomments', 'tool_spamcleaner').'</h3>'.$user->content;
296         unset($user->content);
297     } else if (isset($user->fullmessage)) {
298         $user->description = '<h3>'.get_string('spamfrommessages', 'tool_spamcleaner').'</h3>'.$user->fullmessage;
299         unset($user->fullmessage);
300     } else if (isset($user->message)) {
301         $user->description = '<h3>'.get_string('spamfromforumpost', 'tool_spamcleaner').'</h3>'.$user->message;
302         unset($user->message);
303     } else if (isset($user->subject)) {
304         $user->description = '<h3>'.get_string('spamfromforumpost', 'tool_spamcleaner').'</h3>'.$user->subject;
305         unset($user->subject);
306     }
308     if (preg_match('#<img.*src=[\"\']('.$CFG->wwwroot.')#', $user->description, $matches)
309         && $image_search) {
310         $result = false;
311         foreach ($keywords as $keyword) {
312             if (preg_match('#'.$keyword.'#', $user->description)
313                 && ($keyword != '<img')) {
314                 $result = true;
315             }
316         }
317         if ($result) {
318             echo print_user_entry($user, $keywords, $count);
319         } else {
320             unset($user);
321         }
322     } else {
323         echo print_user_entry($user, $keywords, $count);
324     }
328 function print_user_entry($user, $keywords, $count) {
330     global $SESSION, $CFG;
332     $smalluserobject = new stdClass();      // All we need to delete them later
333     $smalluserobject->id = $user->id;
334     $smalluserobject->email = $user->email;
335     $smalluserobject->auth = $user->auth;
336     $smalluserobject->firstname = $user->firstname;
337     $smalluserobject->lastname = $user->lastname;
338     $smalluserobject->username = $user->username;
340     if (empty($SESSION->users_result[$user->id])) {
341         $SESSION->users_result[$user->id] = $smalluserobject;
342         $html = '<tr valign="top" id="row-'.$user->id.'" class="result-row">';
343         $html .= '<td width="10">'.$count.'</td>';
344         $html .= '<td width="30%" align="left"><a href="'.$CFG->wwwroot."/user/view.php?course=1&amp;id=".$user->id.'" title="'.s($user->username).'">'.fullname($user).'</a>';
346         $html .= "<ul>";
347         $profile_set = array('city'=>true, 'country'=>true, 'email'=>true);
348         foreach ($profile_set as $key=>$value) {
349             if (isset($user->$key)){
350                 $html .= '<li>'.$user->$key.'</li>';
351             }
352         }
353         $html .= "</ul>";
354         $html .= '</td>';
356         foreach ($keywords as $keyword) {
357             $user->description = highlight($keyword, $user->description);
358         }
360         if (!isset($user->descriptionformat)) {
361             $user->descriptionformat = FORMAT_MOODLE;
362         }
364         $html .= '<td align="left">'.format_text($user->description, $user->descriptionformat, array('overflowdiv'=>true)).'</td>';
365         $html .= '<td width="100px" align="center">';
366         $html .= '<button class="btn btn-primary" onclick="M.tool_spamcleaner.del_user(this,'.$user->id.')">'.
367             get_string('deleteuser', 'admin').'</button><br />';
368         $html .= '<button class="btn btn-secondary" onclick="M.tool_spamcleaner.ignore_user(this,'.$user->id.')">'.
369             get_string('ignore', 'admin').'</button>';
370         $html .= '</td>';
371         $html .= '</tr>';
372         return $html;
373     } else {
374         return null;
375     }
380 echo $OUTPUT->footer();