uid) {
$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();
if (!empty($track)) {
// A record for this IP exists. Update accessed timestamp.
db_update('troll_ip_track')
->fields(array(
'accessed' => REQUEST_TIME,
'uid' => $user->uid,
'ip_address' => ip_address(),
))
->condition(db_and()->condition('uid', $user->uid)->condition('ip_address', ip_address()))
->execute();
}
else {
// Insert new IP record for user.
db_insert('troll_ip_track')
->fields(array(
'uid' => $user->uid,
'ip_address' => ip_address(),
'created' => REQUEST_TIME,
'accessed' => REQUEST_TIME
))
->execute();
}
}
if (variable_get('troll_enable_ip_ban', 1)) {
$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();
if (!empty($ban->ip_address)) {
global $base_url;
watchdog('troll', 'IP Ban: !addr', array('!addr' => ip_address()), WATCHDOG_NOTICE);
$troll_ip_ban_redirect = variable_get('troll_ip_ban_redirect', '');
if (empty($troll_ip_ban_redirect)) {
include_once('includes/common.inc');
$page = drupal_get_path('module', 'troll') . '/blocked.html';
}
else {
$page = $troll_ip_ban_redirect;
}
header('Location: ' . $base_url . '/' . $page);
die();
}
}
}
/**
* Implementation of hook_help().
*/
function troll_help($path, $arg) {
switch ($path) {
case 'admin/user/troll/ip_ban':
if (!variable_get('troll_enable_ip_ban', 1)) {
return '
' . t('IP banning is currently disabled. You can enable it in the !settings page.', array('!settings' => l(t('settings'), 'admin/user/troll/settings')));
}
break;
}
}
/**
* Implementation of hook_perm().
*/
function troll_perm() {
return array(
'administer troll' => array(
'title' => t('Administer Troll'),
'description' => t('Set which IP addresses are blocked or whitelisted and which blacklists to use.')
)
);
}
/**
* Implementation of hook_menu().
*
* @return array
*/
function troll_menu() {
$items['admin/user/troll'] = array(
'title' => 'Troll',
'description' => 'Manage visitor IP banning.',
'page callback' => 'drupal_get_form',
'page arguments' => array('troll_search_form'),
'access arguments' => array('administer troll'),
'weight' => 0
);
$items['admin/user/troll/search'] = array(
'title' => 'Search Users',
'page callback' => 'drupal_get_form',
'page arguments' => array('troll_search_form'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'access arguments' => array('administer troll'),
'weight' => 0
);
$items['admin/user/troll/search/view'] = array(
'title' => 'Search Users',
'page callback' => 'troll_search_user_detail',
'access arguments' => array('administer troll'),
'type' => MENU_CALLBACK
);
$items['admin/user/troll/search/block'] = array(
'title' => 'Block User',
'page callback' => 'drupal_get_form',
'page arguments' => array('troll_confirm_block_user_form'),
'access arguments' => array('administer troll'),
'type' => MENU_CALLBACK
);
$items['admin/user/troll/ip_ban'] = array(
'title' => 'IP Banning',
'page callback' => 'drupal_get_form',
'page arguments' => array('troll_ip_ban'),
'access arguments' => array('administer troll'),
'type' => MENU_LOCAL_TASK,
'weight' => 1
);
$items['admin/user/troll/ip_ban/edit'] = array(
'title' => 'IP Ban Form',
'page callback' => 'drupal_get_form',
'page arguments' => array('troll_ip_ban_form'),
'access arguments' => array('administer troll'),
'type' => MENU_CALLBACK
);
$items['admin/user/troll/ip_ban/user'] = array(
'title' => 'IP Ban Form',
'page callback' => 'drupal_get_form',
'page arguments' => array('troll_confirm_ban_ip_form'),
'access arguments' => array('administer troll'),
'type' => MENU_CALLBACK
);
$items['admin/user/troll/ip_ban/delete'] = array(
'title' => 'Remove Ban',
'page callback' => 'drupal_get_form',
'page arguments' => array('troll_confirm_delete_ip_form'),
'access arguments' => array('administer troll'),
'type' => MENU_CALLBACK
);
$items['admin/user/troll/ip_blacklist'] = array(
'title' => 'Blacklists',
'page callback' => 'troll_blacklist_summary',
'access arguments' => array('administer troll'),
'type' => MENU_LOCAL_TASK,
'weight' => 2
);
$items['admin/user/troll/ip_blacklist/summary'] = array(
'title' => 'Summary',
'page callback' => 'troll_blacklist_summary',
'access arguments' => array('administer troll'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => 0
);
$items['admin/user/troll/ip_blacklist/punishment'] = array(
'title' => 'Visitor Punishment',
'page callback' => 'drupal_get_form',
'page arguments' => array('troll_blacklist_punishment_form'),
'access arguments' => array('administer troll'),
'type' => MENU_LOCAL_TASK,
'weight' => 1
);
$items['admin/user/troll/ip_blacklist/import'] = array(
'title' => 'Import Blacklist',
'page callback' => 'drupal_get_form',
'page arguments' => array('troll_blacklist_import_form'),
'access arguments' => array('administer troll'),
'type' => MENU_LOCAL_TASK,
'weight' => 2
);
$items['admin/user/troll/ip_blacklist/search'] = array(
'title' => 'Search Blacklisted IPs',
'page callback' => 'drupal_get_form',
'page arguments' => array('troll_blacklist_search_form'),
'access arguments' => array('administer troll'),
'type' => MENU_LOCAL_TASK,
'weight' => 3
);
$items['admin/user/troll/ip_blacklist/deleteblack'] = array(
'title' => 'Delete Blacklisted IPs',
'page callback' => 'drupal_get_form',
'page arguments' => array('troll_confirm_delete_black_block_form'),
'access arguments' => array('administer troll'),
'type' => MENU_CALLBACK
);
$items['admin/user/troll/ip_blacklist/whitelist'] = array(
'title' => 'Whitelist',
'page callback' => 'drupal_get_form',
'page arguments' => array('troll_whitelist_form'),
'access arguments' => array('administer troll'),
'type' => MENU_LOCAL_TASK,
'weight' => 4
);
$items['admin/user/troll/ip_blacklist/deletewhite'] = array(
'title' => 'Delete Whitelisted IPs',
'page callback' => 'drupal_get_form',
'page arguments' => array('troll_confirm_delete_white_block_form'),
'access arguments' => array('administer troll'),
'type' => MENU_CALLBACK
);
$items['admin/user/troll/dnsbl'] = array(
'title' => 'DNS Blacklist',
'page callback' => 'drupal_get_form',
'page arguments' => array('troll_dnsbl_settings'),
'access arguments' => array('administer troll'),
'weight' => 5,
'type' => MENU_LOCAL_TASK
);
$items['admin/user/troll/dnsbl/test'] = array(
'title' => 'IP test',
'page callback' => 'drupal_get_form',
'page arguments' => array('troll_dnsbl_test_form'),
'access arguments' => array('administer troll'),
'type' => MENU_CALLBACK
);
$items['admin/user/troll/settings'] = array(
'title' => 'Settings',
'page callback' => 'drupal_get_form',
'page arguments' => array('troll_admin_settings'),
'access arguments' => array('administer site configuration'),
'type' => MENU_LOCAL_TASK,
'weight' => 6
);
$items['user/%troll_user/troll'] = array(
'title' => 'Troll Track',
'page callback' => 'troll_search_user_detail',
'page arguments' => array(1),
'access arguments' => array('administer troll'),
'type' => MENU_LOCAL_TASK,
'file' => 'troll.admin.inc',
);
return $items;
}
function troll_user_load($arg) {
$user = user_load($arg);
if (!empty($user)) {
return $user->uid;
}
}
/**
* Helper function to lookup the last known IP Address for a given user.
*/
function _troll_last_ip($uid) {
$query = db_select('troll_ip_track', 't');
$query->addField('t', 'ip_address', 'ip_address');
$query->condition('uid', $uid, '=');
$query->orderBy('accessed', 'DESC');
$query->range(0, 1);
$result = $query->execute();
return $result->fetchField(0);
}
/**
* Implementation of hook_comment_view().
*/
function troll_comment_view(&$comment) {
$comment->troll_last_ip = _troll_last_ip($comment->uid);
}
/**
* Convert dotted decimal IP to long integer and check for validity
*
* @param $ip string
* @return integer
*/
function _troll_longip($ip) {
$longip = ip2long($ip);
if ($longip === FALSE || $longip == -1) {
drupal_set_message(t('IP %ip not valid!', array('%ip' => $ip)));
drupal_goto('admin/user/troll/ip_blacklist');
}
return $longip;
}
/**
* Removes an IP ban from the database.
*/
function troll_remove_ip($iid) {
$deleted = db_delete('troll_ip_ban')
->condition('iid', $iid)
->execute();
if ($deleted) {
drupal_set_message(t('IP ban removed.'));
}
else {
drupal_set_message(t('An error occurred. IP ban not removed.'));
}
}
/**
* Removes IP block from the blacklist
*
* @param $edit array
*/
function troll_remove_blacklist($net, $bcast) {
$deleted = db_delete('troll_blacklist')
->condition(db_and()->condition('net', $net)->condition('bcast', $bcast))
->execute();
if ($deleted) {
drupal_set_message(t('Blacklist block removed.'));
}
else {
drupal_set_message(t('An error occurred. Blacklist block not removed.'));
}
}
/**
* Removes IP block from the whitelist.
*
* @param $edit array
*/
function troll_remove_whitelist($net, $bcast) {
$deleted = db_delete('troll_whitelist')
->condition(db_and()->condition('net', $net)->condition('bcast', $bcast))
->execute();
if ($deleted) {
drupal_set_message(t('IP whitelist removed.'));
}
else {
drupal_set_message(t('An error occurred, IP whitelist not removed.'));
}
}
/**
* Inserts an IP ban into the database.
*
* @param $edit array
*/
function troll_insert_ip($edit) {
global $user;
$expires = ($edit['expires'] == 1) ? mktime(23, 59, 0, $edit['month'], $edit['day'], $edit['year']) : 0;
db_delete('troll_ip_ban')
->condition('ip_address', $edit['ip_address'])
->execute();
$insert = db_insert('troll_ip_ban')
->fields(array(
'ip_address' => $edit['ip_address'],
'domain_name' => $edit['domain_name'],
'created' => REQUEST_TIME,
'expires' => $expires,
'uid' => $user->uid
))
->execute();
if ($insert) {
drupal_set_message(t('IP ban added: %ip', array('%ip' => $edit['ip_address'])));
}
else {
drupal_set_message(t('An error occurred. IP ban not created.'));
}
}
/**
* Updates an IP ban in the database.
*
* @param $edit array
*/
function troll_update_ip($edit) {
global $user;
$expires = ($edit['expires'] == 1) ? mktime(23, 59, 0, $edit['month'], $edit['day'], $edit['year']) : 0;
$num_updated = db_update('troll_ip_ban')
->fields(array(
'ip_address' => $edit['ip_address'],
'domain_name' => $edit['domain_name'],
'expires' => $expires,
'uid' => $user->uid
))
->condition('iid', $edit['iid'])
->execute();
if ($num_updated) {
drupal_set_message(t('%num record(s) updated for IP ban: %ip', array('%num' => $num_updated, '%ip' => $edit['ip_address'])));
}
else {
drupal_set_message(t('An error occurred. IP ban not updated.'));
}
}
/**
* Logs IP information for users in the database.
*/
function troll_check_ip() {
global $user;
$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();
if (!empty($check)) {
db_insert('troll_ip_track')
->fields(array(
'uid' => $user->uid,
'ip_address' => ip_address(),
'created' => REQUEST_TIME
))
->execute();
}
}
/**
* Checks remote IP to see if it is blacklisted.
*
* @return integer zero if whitelisted or not blacklisted, otherwise the number of IP blacklist block matches
*/
function troll_is_blacklisted() {
static $blacklisted, $whitelisted;
if (isset($blacklisted) && isset($whitelisted)) {
return $whitelisted ? FALSE : $blacklisted;
}
$longip = ip2long(ip_address());
if ($longip === FALSE || $longip == -1) {
return FALSE;
}
else {
$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();
if ($whitelisted) {
return FALSE;
}
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();
}
}
/**
* Bans a user.
*
* @param $uid int
*/
function troll_block_user($uid) {
// block them
$user_edit['status'] = 0;
// remove all their permissions roles
$user_edit['roles'] = array();
$user = user_load($uid);
user_save($user, $user_edit);
sess_destroy_uid($uid);
if (variable_get('troll_block_role', NULL)) {
$name = db_query_range('SELECT name FROM {users} WHERE uid = :uid', array(':uid' => $uid), 0, 1)->fetchField();
$role = db_query_range('SELECT name FROM {role} WHERE rid = :rid', array(':rid' => variable_get('troll_block_role', 0)), 0, 1)->fetchField();
db_insert('users_roles')
->fields(array(
'uid' => $uid,
'rid' => variable_get('troll_block_role', '0')
))
->execute();
drupal_set_message(t('Blocked user !link and assigned role %role.', array('!link' => l($name, "admin/user/troll/search/view/$uid"), '%role' => $role)));
}
else {
drupal_set_message(t('Blocked user !link.', array('!link' => l($name, "admin/user/troll/search/view/$uid"))));
}
}
/**
* Implementation of hook_comment().
*/
function troll_comment($comment, $op) {
if (variable_get('troll_dnsbl_active', 0) != 1) {
return;
}
switch ($op) {
case 'insert':
case 'update':
$comment = (object)$comment;
$ip = ip_address();
$blacklisted = _troll_dnsbl_blacklisted($ip);
if ($blacklisted == TRUE) {
$operation = comment_operations('unpublish');
$query = $operation['unpublish'][1];
db_query($query, $comment->cid);
drupal_set_message(t('Your comment has been queued for moderation by site administrators and will be published after approval.'));
watchdog('troll', 'Comment unpublished for DNSBL: %subject.', array('%subject' => $comment->subject), WATCHDOG_INFO, l(t('view'), 'node/'. $comment->nid, array('fragment' => 'comment-'. $comment->cid)));
}
else {
watchdog('troll', 'IP %ip is not DNS blacklisted.', array('%ip' => $ip), WATCHDOG_INFO, l(t('view'), 'node/'. $comment->nid, array('fragment' => 'comment-'. $comment->cid)));
}
return;
default:
return;
}
}
/**
* Check if an IP is blacklisted or not.
*
* @param $ip the IP to check.
* @return true if blacklisted or false
*/
function _troll_dnsbl_blacklisted($ip) {
$servers = _troll_dnsbl_default_servers();
$servers = explode("\n", $servers);
$threshold = variable_get('troll_dnsbl_threshold', 1);
foreach ($servers as $server) {
// we trim because we end up with a new line at the end of each server
// for an obscure reason!
if (_troll_dnsbl_check($ip, trim($server))) {
$threshold--;
}
if ($threshold == 0) {
return TRUE;
}
}
return FALSE;
}
/**
* Perform a DNS query
*
* @param $ip the IP to check
* @param $server the DNS to check.
* @return true if the entry is there otherise false even if there's an error.
*/
function _troll_dnsbl_check($ip, $server) {
// Let's reverse the IP
$ip = implode('.', array_reverse(explode('.', $ip)));
$request = implode('.', array($ip, $server));
$result = gethostbyname($request);
if ($request == $result) {
// No domain
return FALSE;
}
else {
$octats = explode('.', $result);
return $octats[0] == 127;
}
}
/**
* Return the list of default DNSBL servers
*
* @return the list of default servers.
*/
function _troll_dnsbl_default_servers() {
return variable_get('troll_dnsbl_list', implode("\n", array(
'dnsbl.sorbs.net',
'bl.spamcop.net',
'dnsbl.njabl.org',
'cbl.abuseat.org',
'sbl-xbl.spamhaus.org'
)));
}