View source
<?php
function rate_bots_is_local($ip) {
if (preg_match('/^([012]?[0-9]{2})\\./', $ip, $match)) {
switch ($match[1]) {
case 10:
case 127:
case 172:
case 192:
return TRUE;
}
}
return FALSE;
}
function rate_bots_is_blocked() {
$ip = ip_address();
$agent = $_SERVER['HTTP_USER_AGENT'];
if (rate_bots_is_local($ip)) {
return rate_bots_check_agent($agent);
}
if (rate_bots_check_ip($ip)) {
return TRUE;
}
if (rate_bots_check_agent($agent)) {
rate_bots_register_bot($ip);
return TRUE;
}
$threshold = variable_get(RATE_VAR_BOT_MINUTE_THRESHOLD, 25);
if ($threshold && rate_bots_check_threshold($ip, 60) > $threshold) {
rate_bots_register_bot($ip);
return TRUE;
}
$threshold = variable_get(RATE_VAR_BOT_HOUR_THRESHOLD, 250);
$count = rate_bots_check_threshold($ip, 3600);
if ($threshold && $count > $threshold) {
rate_bots_register_bot($ip);
return TRUE;
}
if (!$count && rate_bots_check_botscout($ip)) {
rate_bots_register_bot($ip);
return TRUE;
}
return FALSE;
}
function rate_bots_register_bot($ip) {
db_insert('rate_bot_ip')
->fields(array(
'ip' => $ip,
))
->execute();
}
function rate_bots_check_ip($ip) {
return (bool) db_select('rate_bot_ip', 'rbi')
->fields('rbi', array(
'id',
))
->condition('rbi.ip', $ip)
->range(0, 1)
->execute()
->fetchField();
}
function rate_bots_check_agent($agent) {
$sql = 'SELECT 1 FROM {rate_bot_agent} WHERE :agent LIKE pattern LIMIT 1';
return (bool) db_query($sql, array(
':agent' => $agent,
))
->fetchField();
}
function rate_bots_check_threshold($ip, $interval) {
$sql = 'SELECT COUNT(*) FROM {votingapi_vote} WHERE vote_source = :ip AND timestamp > :time';
return db_query($sql, array(
':ip' => $ip,
':time' => REQUEST_TIME - $interval,
))
->fetchField();
}
function rate_bots_check_botscout($ip) {
$key = variable_get(RATE_VAR_BOT_BOTSCOUT_KEY, '');
if ($key) {
$url = "http://botscout.com/test/?ip={$ip}&key={$key}";
$data = drupal_http_request($url, array(
'timeout' => 2,
));
if ($data->code == 200) {
if ($data->data[0] == 'Y') {
return TRUE;
}
}
}
return FALSE;
}
function rate_bots_delete_votes() {
$limit = variable_get(RATE_VAR_CRON_DELETE_LIMIT, 25);
$queue = DrupalQueue::get('rate_delete_votes');
while ($item = $queue
->claimItem()) {
$ip = $item->data;
$votes = db_select('votingapi_vote', 'v')
->fields('v', array(
'vote_id',
'entity_type',
'entity_id',
))
->condition('v.vote_source', $ip)
->range(0, $limit)
->execute()
->fetchAll();
foreach ($votes as $vote) {
db_delete('votingapi_vote')
->condition('vote_id', $vote->vote_id)
->execute();
votingapi_recalculate_results($vote->entity_type, $vote->entity_id, TRUE);
}
$queue
->deleteItem($item);
if (count($votes) == $limit) {
$queue
->createItem($ip);
}
$limit -= count($votes) + 1;
if ($limit <= 0) {
break;
}
}
}