/[drupal]/contributions/modules/troll/troll.module
ViewVC logotype

Contents of /contributions/modules/troll/troll.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.40 - (show annotations) (download) (as text)
Mon Aug 3 19:10:22 2009 UTC (3 months, 3 weeks ago) by deekayen
Branch: MAIN
CVS Tags: HEAD
Changes since 1.39: +3 -2 lines
File MIME type: text/x-php
#538942 by roderik: boostrap needs common.inc for t()
1 <?php
2 // $Id: troll.module,v 1.39 2009/06/13 03:12:24 deekayen Exp $
3
4 /**
5 * @file
6 * Search users by IP address, banning IP addresses, advanced user
7 * searching, blocking user by role, and blacklisting by IP block.
8 *
9 * @author David Kent Norman
10 * @author Aaron Welch
11 * @link http://deekayen.net/
12 * @link http://advomatic.com/
13 */
14
15 /**
16 * Implementation of hook_boot().
17 */
18 function troll_boot() {
19 if (troll_is_blacklisted()) {
20 $alt_page = variable_get('troll_blacklist_alt_page', 0);
21 if ($alt_page) {
22 switch ($alt_page) {
23 case 'blank':
24 exit;
25 break;
26 case '404':
27 // drupal_not_found() can make a mess in admin logs with watchdog()
28 drupal_set_header('HTTP/1.0 404 Not Found');
29 drupal_set_title(t('Page not found'));
30 print theme('page', '');
31 exit;
32 break;
33 case 'redirect':
34 // The default value of troll_blacklist_alt_url should not be an
35 // empty string because then we redirect to ourselves; so use 127.0.0.1.
36 header('Location: ' . variable_get('troll_blacklist_alt_url', 'http://127.0.0.1'));
37 exit;
38 break;
39 }
40 }
41
42 $req_mod = variable_get('troll_blacklist_mod_requests', 0);
43 if ($req_mod == 'notice_post_drop' && !empty($_POST)) {
44 $_POST = array();
45 include_once('includes/common.inc');
46 drupal_set_message(t('Your data submission was ignored because you are visiting from a blacklisted location.'), 'warning');
47 }
48 else if ($req_mod == 'silent_post_drop') {
49 $_POST = array();
50 }
51
52 if (variable_get('troll_blacklist_stutter', 0)) {
53 sleep(rand(1, 5));
54 }
55 }
56
57 global $user;
58
59 if ($user->uid) {
60 $track = db_query("SELECT COUNT(ip_address) FROM {troll_ip_track} WHERE uid = :uid AND ip_address = :ip_address", array(':uid' => $user->uid, ':ip_address' => ip_address()))->fetchField();
61 if (!empty($track)) {
62 // A record for this IP exists. Update accessed timestamp.
63 db_update('troll_ip_track')
64 ->fields(array(
65 'accessed' => REQUEST_TIME,
66 'uid' => $user->uid,
67 'ip_address' => ip_address(),
68 ))
69 ->condition(db_and()->condition('uid', $user->uid)->condition('ip_address', ip_address()))
70 ->execute();
71 }
72 else {
73 // Insert new IP record for user.
74 db_insert('troll_ip_track')
75 ->fields(array(
76 'uid' => $user->uid,
77 'ip_address' => ip_address(),
78 'created' => REQUEST_TIME,
79 'accessed' => REQUEST_TIME
80 ))
81 ->execute();
82 }
83 }
84
85 if (variable_get('troll_enable_ip_ban', 1)) {
86 $ban = db_query('SELECT COUNT(ip_address) FROM {troll_ip_ban} WHERE (expires > :expires OR expires = 0) AND ip_address = :ip_address', array(':expires' => time(), ':ip_address' => ip_address()))->fetchField();
87 if (!empty($ban->ip_address)) {
88 global $base_url;
89 watchdog('troll', 'IP Ban: !addr', array('!addr' => ip_address()), WATCHDOG_NOTICE);
90 $troll_ip_ban_redirect = variable_get('troll_ip_ban_redirect', '');
91 if (empty($troll_ip_ban_redirect)) {
92 include_once('includes/common.inc');
93 $page = drupal_get_path('module', 'troll') . '/blocked.html';
94 }
95 else {
96 $page = $troll_ip_ban_redirect;
97 }
98 header('Location: ' . $base_url . '/' . $page);
99 die();
100 }
101 }
102 }
103
104 /**
105 * Implementation of hook_help().
106 */
107 function troll_help($path, $arg) {
108 switch ($path) {
109 case 'admin/user/troll/ip_ban':
110 if (!variable_get('troll_enable_ip_ban', 1)) {
111 return '<div class="messages error">' . t('IP banning is currently disabled. You can enable it in the !settings page.', array('!settings' => l(t('settings'), 'admin/user/troll/settings')));
112 }
113 break;
114 }
115 }
116
117 /**
118 * Implementation of hook_perm().
119 */
120 function troll_perm() {
121 return array(
122 'administer troll' => array(
123 'title' => t('Administer Troll'),
124 'description' => t('Set which IP addresses are blocked or whitelisted and which blacklists to use.')
125 )
126 );
127 }
128
129 /**
130 * Implementation of hook_menu().
131 *
132 * @return array
133 */
134 function troll_menu() {
135 $items['admin/user/troll'] = array(
136 'title' => 'Troll',
137 'description' => 'Manage visitor IP banning.',
138 'page callback' => 'drupal_get_form',
139 'page arguments' => array('troll_search_form'),
140 'access arguments' => array('administer troll'),
141 'weight' => 0
142 );
143 $items['admin/user/troll/search'] = array(
144 'title' => 'Search Users',
145 'page callback' => 'drupal_get_form',
146 'page arguments' => array('troll_search_form'),
147 'type' => MENU_DEFAULT_LOCAL_TASK,
148 'access arguments' => array('administer troll'),
149 'weight' => 0
150 );
151 $items['admin/user/troll/search/view'] = array(
152 'title' => 'Search Users',
153 'page callback' => 'troll_search_user_detail',
154 'access arguments' => array('administer troll'),
155 'type' => MENU_CALLBACK
156 );
157 $items['admin/user/troll/search/block'] = array(
158 'title' => 'Block User',
159 'page callback' => 'drupal_get_form',
160 'page arguments' => array('troll_confirm_block_user_form'),
161 'access arguments' => array('administer troll'),
162 'type' => MENU_CALLBACK
163 );
164 $items['admin/user/troll/ip_ban'] = array(
165 'title' => 'IP Banning',
166 'page callback' => 'drupal_get_form',
167 'page arguments' => array('troll_ip_ban'),
168 'access arguments' => array('administer troll'),
169 'type' => MENU_LOCAL_TASK,
170 'weight' => 1
171 );
172 $items['admin/user/troll/ip_ban/edit'] = array(
173 'title' => 'IP Ban Form',
174 'page callback' => 'drupal_get_form',
175 'page arguments' => array('troll_ip_ban_form'),
176 'access arguments' => array('administer troll'),
177 'type' => MENU_CALLBACK
178 );
179 $items['admin/user/troll/ip_ban/user'] = array(
180 'title' => 'IP Ban Form',
181 'page callback' => 'drupal_get_form',
182 'page arguments' => array('troll_confirm_ban_ip_form'),
183 'access arguments' => array('administer troll'),
184 'type' => MENU_CALLBACK
185 );
186 $items['admin/user/troll/ip_ban/delete'] = array(
187 'title' => 'Remove Ban',
188 'page callback' => 'drupal_get_form',
189 'page arguments' => array('troll_confirm_delete_ip_form'),
190 'access arguments' => array('administer troll'),
191 'type' => MENU_CALLBACK
192 );
193 $items['admin/user/troll/ip_blacklist'] = array(
194 'title' => 'Blacklists',
195 'page callback' => 'troll_blacklist_summary',
196 'access arguments' => array('administer troll'),
197 'type' => MENU_LOCAL_TASK,
198 'weight' => 2
199 );
200 $items['admin/user/troll/ip_blacklist/summary'] = array(
201 'title' => 'Summary',
202 'page callback' => 'troll_blacklist_summary',
203 'access arguments' => array('administer troll'),
204 'type' => MENU_DEFAULT_LOCAL_TASK,
205 'weight' => 0
206 );
207 $items['admin/user/troll/ip_blacklist/punishment'] = array(
208 'title' => 'Visitor Punishment',
209 'page callback' => 'drupal_get_form',
210 'page arguments' => array('troll_blacklist_punishment_form'),
211 'access arguments' => array('administer troll'),
212 'type' => MENU_LOCAL_TASK,
213 'weight' => 1
214 );
215 $items['admin/user/troll/ip_blacklist/import'] = array(
216 'title' => 'Import Blacklist',
217 'page callback' => 'drupal_get_form',
218 'page arguments' => array('troll_blacklist_import_form'),
219 'access arguments' => array('administer troll'),
220 'type' => MENU_LOCAL_TASK,
221 'weight' => 2
222 );
223 $items['admin/user/troll/ip_blacklist/search'] = array(
224 'title' => 'Search Blacklisted IPs',
225 'page callback' => 'drupal_get_form',
226 'page arguments' => array('troll_blacklist_search_form'),
227 'access arguments' => array('administer troll'),
228 'type' => MENU_LOCAL_TASK,
229 'weight' => 3
230 );
231 $items['admin/user/troll/ip_blacklist/deleteblack'] = array(
232 'title' => 'Delete Blacklisted IPs',
233 'page callback' => 'drupal_get_form',
234 'page arguments' => array('troll_confirm_delete_black_block_form'),
235 'access arguments' => array('administer troll'),
236 'type' => MENU_CALLBACK
237 );
238 $items['admin/user/troll/ip_blacklist/whitelist'] = array(
239 'title' => 'Whitelist',
240 'page callback' => 'drupal_get_form',
241 'page arguments' => array('troll_whitelist_form'),
242 'access arguments' => array('administer troll'),
243 'type' => MENU_LOCAL_TASK,
244 'weight' => 4
245 );
246 $items['admin/user/troll/ip_blacklist/deletewhite'] = array(
247 'title' => 'Delete Whitelisted IPs',
248 'page callback' => 'drupal_get_form',
249 'page arguments' => array('troll_confirm_delete_white_block_form'),
250 'access arguments' => array('administer troll'),
251 'type' => MENU_CALLBACK
252 );
253 $items['admin/user/troll/dnsbl'] = array(
254 'title' => 'DNS Blacklist',
255 'page callback' => 'drupal_get_form',
256 'page arguments' => array('troll_dnsbl_settings'),
257 'access arguments' => array('administer troll'),
258 'weight' => 5,
259 'type' => MENU_LOCAL_TASK
260 );
261 $items['admin/user/troll/dnsbl/test'] = array(
262 'title' => 'IP test',
263 'page callback' => 'drupal_get_form',
264 'page arguments' => array('troll_dnsbl_test_form'),
265 'access arguments' => array('administer troll'),
266 'type' => MENU_CALLBACK
267 );
268 $items['admin/user/troll/settings'] = array(
269 'title' => 'Settings',
270 'page callback' => 'drupal_get_form',
271 'page arguments' => array('troll_admin_settings'),
272 'access arguments' => array('administer site configuration'),
273 'type' => MENU_LOCAL_TASK,
274 'weight' => 6
275 );
276 $items['user/%troll_user/troll'] = array(
277 'title' => 'Troll Track',
278 'page callback' => 'troll_search_user_detail',
279 'page arguments' => array(1),
280 'access arguments' => array('administer troll'),
281 'type' => MENU_LOCAL_TASK,
282 'file' => 'troll.admin.inc',
283 );
284 return $items;
285 }
286
287 function troll_user_load($arg) {
288 $user = user_load($arg);
289 if (!empty($user)) {
290 return $user->uid;
291 }
292 }
293
294 /**
295 * Helper function to lookup the last known IP Address for a given user.
296 */
297 function _troll_last_ip($uid) {
298 $query = db_select('troll_ip_track', 't');
299 $query->addField('t', 'ip_address', 'ip_address');
300 $query->condition('uid', $uid, '=');
301 $query->orderBy('accessed', 'DESC');
302 $query->range(0, 1);
303 $result = $query->execute();
304 return $result->fetchField(0);
305 }
306
307 /**
308 * Implementation of hook_comment_view().
309 */
310 function troll_comment_view(&$comment) {
311 $comment->troll_last_ip = _troll_last_ip($comment->uid);
312 }
313
314 /**
315 * Convert dotted decimal IP to long integer and check for validity
316 *
317 * @param $ip string
318 * @return integer
319 */
320 function _troll_longip($ip) {
321 $longip = ip2long($ip);
322 if ($longip === FALSE || $longip == -1) {
323 drupal_set_message(t('IP %ip not valid!', array('%ip' => $ip)));
324 drupal_goto('admin/user/troll/ip_blacklist');
325 }
326 return $longip;
327 }
328
329 /**
330 * Removes an IP ban from the database.
331 */
332 function troll_remove_ip($iid) {
333 $deleted = db_delete('troll_ip_ban')
334 ->condition('iid', $iid)
335 ->execute();
336 if ($deleted) {
337 drupal_set_message(t('IP ban removed.'));
338 }
339 else {
340 drupal_set_message(t('An error occurred. IP ban not removed.'));
341 }
342 }
343
344 /**
345 * Removes IP block from the blacklist
346 *
347 * @param $edit array
348 */
349 function troll_remove_blacklist($net, $bcast) {
350 $deleted = db_delete('troll_blacklist')
351 ->condition(db_and()->condition('net', $net)->condition('bcast', $bcast))
352 ->execute();
353 if ($deleted) {
354 drupal_set_message(t('Blacklist block removed.'));
355 }
356 else {
357 drupal_set_message(t('An error occurred. Blacklist block not removed.'));
358 }
359 }
360
361 /**
362 * Removes IP block from the whitelist.
363 *
364 * @param $edit array
365 */
366 function troll_remove_whitelist($net, $bcast) {
367 $deleted = db_delete('troll_whitelist')
368 ->condition(db_and()->condition('net', $net)->condition('bcast', $bcast))
369 ->execute();
370 if ($deleted) {
371 drupal_set_message(t('IP whitelist removed.'));
372 }
373 else {
374 drupal_set_message(t('An error occurred, IP whitelist not removed.'));
375 }
376 }
377
378 /**
379 * Inserts an IP ban into the database.
380 *
381 * @param $edit array
382 */
383 function troll_insert_ip($edit) {
384 global $user;
385
386 $expires = ($edit['expires'] == 1) ? mktime(23, 59, 0, $edit['month'], $edit['day'], $edit['year']) : 0;
387
388 db_delete('troll_ip_ban')
389 ->condition('ip_address', $edit['ip_address'])
390 ->execute();
391 $insert = db_insert('troll_ip_ban')
392 ->fields(array(
393 'ip_address' => $edit['ip_address'],
394 'domain_name' => $edit['domain_name'],
395 'created' => REQUEST_TIME,
396 'expires' => $expires,
397 'uid' => $user->uid
398 ))
399 ->execute();
400 if ($insert) {
401 drupal_set_message(t('IP ban added: %ip', array('%ip' => $edit['ip_address'])));
402 }
403 else {
404 drupal_set_message(t('An error occurred. IP ban not created.'));
405 }
406 }
407
408 /**
409 * Updates an IP ban in the database.
410 *
411 * @param $edit array
412 */
413 function troll_update_ip($edit) {
414 global $user;
415
416 $expires = ($edit['expires'] == 1) ? mktime(23, 59, 0, $edit['month'], $edit['day'], $edit['year']) : 0;
417 $num_updated = db_update('troll_ip_ban')
418 ->fields(array(
419 'ip_address' => $edit['ip_address'],
420 'domain_name' => $edit['domain_name'],
421 'expires' => $expires,
422 'uid' => $user->uid
423 ))
424 ->condition('iid', $edit['iid'])
425 ->execute();
426
427 if ($num_updated) {
428 drupal_set_message(t('%num record(s) updated for IP ban: %ip', array('%num' => $num_updated, '%ip' => $edit['ip_address'])));
429 }
430 else {
431 drupal_set_message(t('An error occurred. IP ban not updated.'));
432 }
433 }
434
435
436 /**
437 * Logs IP information for users in the database.
438 */
439 function troll_check_ip() {
440 global $user;
441 $check = db_query("SELECT COUNT(uid) FROM {troll_ip_track} WHERE ip_address = :ip_address AND uid = :uid", array(':ip_address' => ip_address(), ':uid' => $user->uid))->fetchField();
442 if (!empty($check)) {
443 db_insert('troll_ip_track')
444 ->fields(array(
445 'uid' => $user->uid,
446 'ip_address' => ip_address(),
447 'created' => REQUEST_TIME
448 ))
449 ->execute();
450 }
451 }
452
453 /**
454 * Checks remote IP to see if it is blacklisted.
455 *
456 * @return integer zero if whitelisted or not blacklisted, otherwise the number of IP blacklist block matches
457 */
458 function troll_is_blacklisted() {
459 static $blacklisted, $whitelisted;
460
461 if (isset($blacklisted) && isset($whitelisted)) {
462 return $whitelisted ? FALSE : $blacklisted;
463 }
464
465 $longip = ip2long(ip_address());
466 if ($longip === FALSE || $longip == -1) {
467 return FALSE;
468 }
469 else {
470 $whitelisted = (bool)db_query_range('SELECT 1 FROM {troll_whitelist} w WHERE w.net <= :longip AND w.bcast >= :longip', array(':longip' => $longip), 0, 1)->fetchField();
471 if ($whitelisted) {
472 return FALSE;
473 }
474 return (bool)db_query_range('SELECT 1 FROM {troll_blacklist} b WHERE b.net <= :longip AND b.bcast >= :longip', array(':longip' => $longip), 0, 1)->fetchField();
475 }
476 }
477
478 /**
479 * Bans a user.
480 *
481 * @param $uid int
482 */
483 function troll_block_user($uid) {
484 // block them
485 $user_edit['status'] = 0;
486 // remove all their permissions roles
487 $user_edit['roles'] = array();
488 $user = user_load($uid);
489 user_save($user, $user_edit);
490 sess_destroy_uid($uid);
491
492 if (variable_get('troll_block_role', NULL)) {
493 $name = db_query_range('SELECT name FROM {users} WHERE uid = :uid', array(':uid' => $uid), 0, 1)->fetchField();
494 $role = db_query_range('SELECT name FROM {role} WHERE rid = :rid', array(':rid' => variable_get('troll_block_role', 0)), 0, 1)->fetchField();
495 db_insert('users_roles')
496 ->fields(array(
497 'uid' => $uid,
498 'rid' => variable_get('troll_block_role', '0')
499 ))
500 ->execute();
501 drupal_set_message(t('Blocked user !link and assigned role %role.', array('!link' => l($name, "admin/user/troll/search/view/$uid"), '%role' => $role)));
502 }
503 else {
504 drupal_set_message(t('Blocked user !link.', array('!link' => l($name, "admin/user/troll/search/view/$uid"))));
505 }
506 }
507
508 /**
509 * Implementation of hook_comment().
510 */
511 function troll_comment($comment, $op) {
512 if (variable_get('troll_dnsbl_active', 0) != 1) {
513 return;
514 }
515
516 switch ($op) {
517 case 'insert':
518 case 'update':
519 $comment = (object)$comment;
520
521 $ip = ip_address();
522 $blacklisted = _troll_dnsbl_blacklisted($ip);
523
524 if ($blacklisted == TRUE) {
525 $operation = comment_operations('unpublish');
526 $query = $operation['unpublish'][1];
527 db_query($query, $comment->cid);
528 drupal_set_message(t('Your comment has been queued for moderation by site administrators and will be published after approval.'));
529 watchdog('troll', 'Comment unpublished for DNSBL: %subject.', array('%subject' => $comment->subject), WATCHDOG_INFO, l(t('view'), 'node/'. $comment->nid, array('fragment' => 'comment-'. $comment->cid)));
530 }
531 else {
532 watchdog('troll', 'IP %ip is not DNS blacklisted.', array('%ip' => $ip), WATCHDOG_INFO, l(t('view'), 'node/'. $comment->nid, array('fragment' => 'comment-'. $comment->cid)));
533 }
534 return;
535 default:
536 return;
537 }
538 }
539
540 /**
541 * Check if an IP is blacklisted or not.
542 *
543 * @param $ip the IP to check.
544 * @return true if blacklisted or false
545 */
546 function _troll_dnsbl_blacklisted($ip) {
547 $servers = _troll_dnsbl_default_servers();
548 $servers = explode("\n", $servers);
549
550 $threshold = variable_get('troll_dnsbl_threshold', 1);
551
552 foreach ($servers as $server) {
553 // we trim because we end up with a new line at the end of each server
554 // for an obscure reason!
555 if (_troll_dnsbl_check($ip, trim($server))) {
556 $threshold--;
557 }
558
559 if ($threshold == 0) {
560 return TRUE;
561 }
562 }
563
564 return FALSE;
565 }
566
567 /**
568 * Perform a DNS query
569 *
570 * @param $ip the IP to check
571 * @param $server the DNS to check.
572 * @return true if the entry is there otherise false even if there's an error.
573 */
574 function _troll_dnsbl_check($ip, $server) {
575 // Let's reverse the IP
576 $ip = implode('.', array_reverse(explode('.', $ip)));
577
578 $request = implode('.', array($ip, $server));
579
580 $result = gethostbyname($request);
581
582 if ($request == $result) {
583 // No domain
584 return FALSE;
585 }
586 else {
587 $octats = explode('.', $result);
588 return $octats[0] == 127;
589 }
590 }
591
592 /**
593 * Return the list of default DNSBL servers
594 *
595 * @return the list of default servers.
596 */
597 function _troll_dnsbl_default_servers() {
598 return variable_get('troll_dnsbl_list', implode("\n", array(
599 'dnsbl.sorbs.net',
600 'bl.spamcop.net',
601 'dnsbl.njabl.org',
602 'cbl.abuseat.org',
603 'sbl-xbl.spamhaus.org'
604 )));
605 }

  ViewVC Help
Powered by ViewVC 1.1.2