updated webform localization and phone, uuid, term_merge, spambot, performance

This commit is contained in:
Bachir Soussi Chiadmi
2016-11-05 17:14:57 +01:00
parent fdefc824d8
commit 0521608bb7
57 changed files with 3592 additions and 1629 deletions

View File

@@ -0,0 +1,60 @@
CONTENTS OF THIS FILE
---------------------
* Introduction
* Recommended modules
* Installation
* Configuration
* Maintainers
INTRODUCTION
------------
Spambot protects the user registration form from spammers and spambots by
verifying registration attempts against the Stop Forum Spam
(www.stopforumspam.com) online database.
It also adds some useful features to help deal with spam accounts.
This module works well for sites which require user registration
before posting is allowed (which is most forums).
RECOMMENDED MODULES
-------------------
* User Stats (https://www.drupal.org/project/user_stats):
Allow to use a bit more statistics of users by IP address.
* Statistics (built-in core)
Allow to use a bit more statistics of users by IP address.
INSTALLATION
------------
* Install as you would normally install a contributed Drupal module. See:
https://drupal.org/documentation/install/modules-themes/modules-7
for further information.
CONFIGURATION
-------------
* Configure user permissions in Administration » People » Permissions:
- Protected from spambot scans
Users in roles with the "Protected from spambot scans" permission would not
be scanned by cron.
* Go to the '/admin/config/system/spambot' page and check additional settings.
MAINTAINERS
-----------
Current maintainers:
* bengtan (bengtan) - https://www.drupal.org/u/bengtan
* Michael Moritz (miiimooo) - https://www.drupal.org/u/miiimooo
* Dmitry Kiselev (kala4ek) - https://www.drupal.org/u/kala4ek

View File

@@ -1,70 +1,110 @@
<?php
function spambot_settings_form($form, &$form_state) {
$numbers = array(0 => t('Never'), 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, 7 => 7, 8 => 8, 9 => 9, 10 => 10, 15 => 15, 20 => 20, 30 => 30, 40 => 40, 50 => 50, 60 => 60, 70 => 70, 80 => 80, 90 => 90, 100 => 100, 150 => 150, 200 => 200);
/**
* @file
* Administration part (forms and pages) for Spambot module.
*/
/**
* Form builder for settings form.
*/
function spambot_settings_form() {
$numbers = array(
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
7 => 7,
8 => 8,
9 => 9,
10 => 10,
15 => 15,
20 => 20,
30 => 30,
40 => 40,
50 => 50,
60 => 60,
70 => 70,
80 => 80,
90 => 90,
100 => 100,
150 => 150,
200 => 200,
);
// Fieldset for set up spam criteria.
$form['criteria'] = array(
'#type' => 'fieldset',
'#title' => t('Spammer criteria'),
'#description' => t('A user account or an attempted user registration will be deemed a spammer if the email, username, or IP address has been reported to www.stopforumspam.com more times than the following thresholds.'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['criteria']['spambot_criteria_email'] = array(
'#type' => 'select',
'#title' => t('Number of times the email has been reported is equal to or more than'),
'#description' => t('If the email address for a user or user registration has been reported to www.stopforumspam.com this many times, then it is deemed as a spammer.'),
'#options' => array(0 => t('Don\'t use email as a criteria')) + $numbers,
'#default_value' => variable_get('spambot_criteria_email', 1),
'#options' => array(0 => t("Don't use email as a criteria")) + $numbers,
'#default_value' => variable_get('spambot_criteria_email', SPAMBOT_DEFAULT_CRITERIA_EMAIL),
);
$form['criteria']['spambot_criteria_username'] = array(
'#type' => 'select',
'#title' => t('Number of times the username has been reported is equal to or more than'),
'#description' => t('If the username for a user or user registration has been reported to www.stopforumspam.com this many times, then it is deemed as a spammer. Be careful about using this option as you may accidentally block genuine users who happen to choose the same username as a known spammer.'),
'#options' => array(0 => t('Don\'t use username as a criteria')) + $numbers,
'#default_value' => variable_get('spambot_criteria_username', 0),
'#options' => array(0 => t("Don't use username as a criteria")) + $numbers,
'#default_value' => variable_get('spambot_criteria_username', SPAMBOT_DEFAULT_CRITERIA_USERNAME),
);
$form['criteria']['spambot_criteria_ip'] = array(
'#type' => 'select',
'#title' => t('Number of times the IP address has been reported is equal to or more than'),
'#description' => t('If the IP address for a user or user registration has been reported to www.stopforumspam.com this many times, then it is deemed as a spammer. Be careful about setting this threshold too low as IP addresses can change.'),
'#options' => array(0 => t('Don\'t use IP address as a criteria')) + $numbers,
'#default_value' => variable_get('spambot_criteria_ip', 20),
'#options' => array(0 => t("Don't use IP address as a criteria")) + $numbers,
'#default_value' => variable_get('spambot_criteria_ip', SPAMBOT_DEFAULT_CRITERIA_IP),
);
// White lists.
$form['spambot_whitelist'] = array(
'#type' => 'fieldset',
'#title' => t('Whitelists'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['spambot_whitelist']['spambot_whitelist_email'] = array(
'#type' => 'textarea',
'#title' => t('Allowed email addresses'),
'#description' => t('Enter email addresses, one per line.'),
'#default_value' => variable_get('spambot_whitelist_email', ''),
);
$form['spambot_whitelist']['spambot_whitelist_username'] = array(
'#type' => 'textarea',
'#title' => t('Allowed usernames'),
'#description' => t('Enter usernames, one per line.'),
'#default_value' => variable_get('spambot_whitelist_username', ''),
);
$form['spambot_whitelist']['spambot_whitelist_ip'] = array(
'#type' => 'textarea',
'#title' => t('Allowed IP addresses'),
'#description' => t('Enter IP addresses, one per line.'),
'#default_value' => variable_get('spambot_whitelist_ip', ''),
);
// Fieldset for configure protecting at user register form.
$form['register'] = array(
'#type' => 'fieldset',
'#title' => t('User registration'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['register']['spambot_user_register_protect'] = array(
'#type' => 'checkbox',
'#title' => t('Protect the user registration form'),
'#description' => t('If ticked, new user registrations will be tested if they match any known spammers and blacklisted.'),
'#default_value' => variable_get('spambot_user_register_protect', TRUE),
);
$form['register']['spambot_blocked_message_email'] = array(
'#type' => 'textarea',
'#title' => t('User registration blocked message (blocked email address)'),
'#rows' => 1,
'#default_value' => variable_get('spambot_blocked_message_email', t(SPAMBOT_DEFAULT_BLOCKED_MESSAGE)),
'#description' => t('Message to display when user registration is blocked due to email address. <br />Showing a specific reason why registration was blocked may make spambot easier to circumvent.<br />The following tokens are available: @email %email @username %username @ip %ip'),
);
$form['register']['spambot_blocked_message_username'] = array(
'#type' => 'textarea',
'#title' => t('User registration blocked message (blocked username)'),
'#rows' => 1,
'#default_value' => variable_get('spambot_blocked_message_username', t(SPAMBOT_DEFAULT_BLOCKED_MESSAGE)),
'#description' => t('Message to display when user registration is blocked due to username.'),
);
$form['register']['spambot_blocked_message_ip'] = array(
'#type' => 'textarea',
'#title' => t('User registration blocked message (blocked ip address)'),
'#rows' => 1,
'#default_value' => variable_get('spambot_blocked_message_ip', t(SPAMBOT_DEFAULT_BLOCKED_MESSAGE)),
'#description' => t('Message to display when user registration is blocked due to ip address.'),
);
$sleep_options = array(0 => t('Don\'t delay'), 1 => t('1 second'));
$sleep_options = array(t("Don't delay"), t('1 second'));
foreach (array(2, 3, 4, 5, 10, 20, 30) as $num) {
$sleep_options[$num] = t('@num seconds', array('@num' => $num));
}
@@ -73,21 +113,23 @@ function spambot_settings_form($form, &$form_state) {
'#title' => t('If blacklisted, delay for'),
'#description' => t('If an attempted user registration is blacklisted, you can choose to deliberately delay the request. This can be useful for slowing them down if they continually try to register.<br />Be careful about choosing too large a value for this as it may exceed your PHP max_execution_time.'),
'#options' => $sleep_options,
'#default_value' => variable_get('spambot_blacklisted_delay', 0),
'#default_value' => variable_get('spambot_blacklisted_delay', SPAMBOT_DEFAULT_DELAY),
);
// Fieldset for set up scanning of existing accounts.
$form['existing'] = array(
'#type' => 'fieldset',
'#title' => t('Scan existing accounts'),
'#description' => t('This module can also scan existing user accounts to see if they are known spammers. It works by checking user accounts with increasing uid\'s ie. user id 2, 3, 4 etc during cron.'),
'#description' => t("This module can also scan existing user accounts to see if they are known spammers. It works by checking user accounts with increasing uid's ie. user id 2, 3, 4 etc during cron."),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['existing']['spambot_cron_user_limit'] = array(
'#type' => 'textfield',
'#title' => t('Maximum number of user accounts to scan per cron'),
'#description' => t('Enter the number of user accounts to scan for each cron. If you do not want to scan existing user accounts, leave this as 0.<br />Be careful not to make this value too large, as it will slow your cron execution down and may cause your site to query www.stopforumspam.com more times than allowed each day.'),
'#size' => 10,
'#default_value' => variable_get('spambot_cron_user_limit', 0),
'#default_value' => variable_get('spambot_cron_user_limit', SPAMBOT_DEFAULT_CRON_USER_LIMIT),
);
$form['existing']['spambot_check_blocked_accounts'] = array(
'#type' => 'checkbox',
@@ -107,39 +149,57 @@ function spambot_settings_form($form, &$form_state) {
'#default_value' => variable_get('spambot_spam_account_action', SPAMBOT_ACTION_NONE),
);
// Show scan status
$last_uid = variable_get('spambot_last_checked_uid', 0);
// Get scan status.
$suffix = '';
if ($last_uid) {
$num_checked = db_select('users')->fields('users')
->condition('uid', '1', '>')->condition('uid', $last_uid, '<=')
->countQuery()->execute()->fetchField();
if ($last_uid = variable_get('spambot_last_checked_uid', 0)) {
$num_checked = db_select('users', 'u')
->fields('u', array('uid'))
->condition('u.uid', 1, '>')
->condition('u.uid', $last_uid, '<=')
->countQuery()
->execute()
->fetchField();
$num_left = db_select('users')->fields('users')
->condition('uid', '1', '>')->condition('uid', $last_uid, '>')
->countQuery()->execute()->fetchField();
$num_left = db_select('users', 'u')
->fields('u', array('uid'))
->condition('u.uid', 1, '>')
->condition('u.uid', $last_uid, '>')
->countQuery()
->execute()
->fetchField();
$last_uid = db_select('users')->fields('users', array('uid'))
->condition('uid', '1', '>')->condition('uid', $last_uid, '<=')
->orderBy('uid', 'DESC')->range(0, 1)
->execute()->fetchField();
$account = user_load((int) $last_uid);
$suffix = '<br />' . t('The last checked user account is: !account (uid @uid)', array('!account' => l(check_plain($account->name), 'user/' . $account->uid), '@uid' => $account->uid));
$last_uid = db_select('users', 'u')
->fields('u', array('uid'))
->condition('u.uid', 1, '>=')
->condition('u.uid', $last_uid, '<=')
->orderBy('u.uid', 'DESC')
->range(0, 1)
->execute()
->fetchField();
$account = user_load($last_uid);
$suffix = '<br />';
$suffix .= t('The last checked user account is: !account (uid %uid)', array(
'!account' => l($account->name, 'user/' . $account->uid),
'%uid' => $account->uid,
));
}
else {
$num_checked = 0;
$num_left = db_select('users')->fields('users')->condition('uid', 1, '>')
->countQuery()->execute()->fetchField();
$num_left = db_select('users')
->fields('users')
->condition('uid', 1, '>')
->countQuery()
->execute()
->fetchField();
}
$text = t('Accounts checked: @checked, Accounts remaining: @remaining', array('@checked' => $num_checked, '@remaining' => $num_left));
$text = t('Accounts checked: %checked, Accounts remaining: %remaining', array('%checked' => $num_checked, '%remaining' => $num_left));
$form['existing']['message'] = array(
'#type' => 'fieldset',
'#title' => t('Scan status'),
'#description' => $text . $suffix,
);
$form['existing']['spambot_last_checked_uid'] = array(
'#type' => 'textfield',
'#title' => t('Continue scanning after this user id'),
@@ -148,6 +208,49 @@ function spambot_settings_form($form, &$form_state) {
'#default_value' => $last_uid,
);
// Fieldset for set up messages which will be displayed for blocked users.
$form['messages'] = array(
'#type' => 'fieldset',
'#title' => t('Blocked messages'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['messages']['spambot_blocked_message_email'] = array(
'#type' => 'textarea',
'#title' => t('User registration blocked message (blocked email address)'),
'#rows' => 1,
'#default_value' => variable_get('spambot_blocked_message_email', SPAMBOT_DEFAULT_BLOCKED_MESSAGE),
'#description' => t('Message to display when user action is blocked due to email address. <br />Showing a specific reason why registration was blocked may make spambot easier to circumvent.<br />The following tokens are available: <em>@email %email @username %username @ip %ip</em>'),
);
$form['messages']['spambot_blocked_message_username'] = array(
'#type' => 'textarea',
'#title' => t('User registration blocked message (blocked username)'),
'#rows' => 1,
'#default_value' => variable_get('spambot_blocked_message_username', SPAMBOT_DEFAULT_BLOCKED_MESSAGE),
'#description' => t('Message to display when user action is blocked due to username.<br />The following tokens are available: <em>@email %email @username %username @ip %ip</em>'),
);
$form['messages']['spambot_blocked_message_ip'] = array(
'#type' => 'textarea',
'#title' => t('User registration blocked message (blocked ip address)'),
'#rows' => 1,
'#default_value' => variable_get('spambot_blocked_message_ip', SPAMBOT_DEFAULT_BLOCKED_MESSAGE),
'#description' => t('Message to display when user action is blocked due to ip address.<br />The following tokens are available: <em>@email %email @username %username @ip %ip</em>'),
);
// Fieldset for configure log rules.
$form['logging'] = array(
'#type' => 'fieldset',
'#title' => t('Log information'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['logging']['spambot_log_blocked_registration'] = array(
'#type' => 'checkbox',
'#title' => t('Log information about blocked registrations into Drupal log'),
'#default_value' => variable_get('spambot_log_blocked_registration', TRUE),
);
// StopFormSpam API key.
$form['spambot_sfs_api_key'] = array(
'#type' => 'textfield',
'#title' => t('www.stopforumspam.com API key'),

View File

@@ -1,12 +1,14 @@
name = Spambot
description = Anti-spam module that uses data from www.stopforumspam.com to protect the user registration form against known spammers and spambots.
description = Anti-spam module that uses data from www.stopforumspam.com to protect the user registration form against known spammers and spambots.
package = "Spam control"
configure = admin/config/system/spambot
core = 7.x
; Information added by drupal.org packaging script on 2013-01-11
version = "7.x-1.3"
; Information added by Drupal.org packaging script on 2016-09-06
version = "7.x-1.5"
core = "7.x"
project = "spambot"
datestamp = "1357872222"
datestamp = "1473137640"

View File

@@ -1,67 +1,56 @@
<?php
/**
* Implementation of hook_schema().
* @file
* Install and update hooks for Spambot module.
*/
/**
* Implements hook_schema().
*/
function spambot_schema() {
$schema = array();
$schema['node_spambot'] = array(
'description' => t('Node table to track author IP addresses. For use by spambot only.'),
'description' => 'Node table to track author IP addresses. For use by spambot only.',
'fields' => array(
'nid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
'uid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
'hostname' => array( 'type' => 'varchar', 'length' => 128, 'not null' => FALSE),
'nid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'uid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'hostname' => array(
'type' => 'varchar',
'length' => 128,
'not null' => FALSE,
),
),
'primary key' => array('nid'),
'indexes' => array(
'uid' => array('uid'),
),
);
return $schema;
}
/**
* Implementation of hook_uninstall().
* Implements hook_uninstall().
*/
function spambot_uninstall() {
db_query("DELETE FROM {variable} WHERE name LIKE 'spambot_%'");
db_delete('variable')
->condition('name', 'spambot_%', 'LIKE')
->execute();
}
/**
* Migrate settings from previous version of spambot (6.x-2.0)
* Update variables, create new table 'node_spambot'.
*/
function spambot_update_6300() {
$ret = array();
// In previous versions of spambot, the default message was 'Blacklisted. Now go away!'
// If no custom message was configured, then configure it to 'Blacklisted. Now go away!'
$message = variable_get('spambot_blocked_message', FALSE);
if (!$message) {
variable_set('spambot_blocked_message', t('Blacklisted. Now go away!'));
}
// Previous versions of spambot blacklisted on any of the three criteria
variable_set('spambot_criteria_email', TRUE);
variable_set('spambot_criteria_username', TRUE);
variable_set('spambot_criteria_ip', TRUE);
return $ret;
}
function spambot_update_6301() {
$ret = array();
// Change criteria settings from booleans to numbers
if (variable_set('spambot_criteria_email', TRUE)) {
variable_set('spambot_criteria_email', 1);
}
if (variable_set('spambot_criteria_username', FALSE)) {
variable_set('spambot_criteria_username', 1);
}
if (variable_set('spambot_criteria_ip', FALSE)) {
variable_set('spambot_criteria_ip', 1);
}
return $ret;
}
function spambot_update_7101() {
$messages = array();
@@ -77,24 +66,37 @@ function spambot_update_7101() {
$messages[] = t('Transferred user registration blocked message to new format.');
}
// Create new table node_spambot
// Create new table node_spambot.
if (!db_table_exists('node_spambot')) {
$schema = array();
$schema['node_spambot'] = array(
$node_spambot = array(
'description' => t('Node table to track author IP addresses. For use by spambot only.'),
'fields' => array(
'nid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
'uid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
'hostname' => array( 'type' => 'varchar', 'length' => 128, 'not null' => FALSE),
'nid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'uid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'hostname' => array(
'type' => 'varchar',
'length' => 128,
'not null' => FALSE,
),
),
'primary key' => array('nid'),
'indexes' => array(
'uid' => array('uid'),
),
);
db_create_table('node_spambot', $schema['node_spambot']);
db_create_table('node_spambot', $node_spambot);
$messages[] = t('Created new table <em>node_spambot</em>.');
}
return join('<br />', $messages);
return implode('<br />', $messages);
}

View File

@@ -1,32 +1,28 @@
<?php
/**
* @file
* Anti-spam module that uses data from www.stopforumspam.com to protect the user registration form against known spammers and spambots.
*
*/
* @file
* Main module file.
*
* Anti-spam module that uses data from www.stopforumspam.com
* to protect the user registration form against known spammers and spambots.
*/
define('SPAMBOT_ACTION_NONE', 0);
define('SPAMBOT_ACTION_BLOCK', 1);
define('SPAMBOT_ACTION_DELETE', 2);
define('SPAMBOT_DEFAULT_CRITERIA_EMAIL', 1);
define('SPAMBOT_DEFAULT_CRITERIA_USERNAME', 0);
define('SPAMBOT_DEFAULT_CRITERIA_IP', 20);
define('SPAMBOT_DEFAULT_DELAY', 0);
define('SPAMBOT_DEFAULT_CRON_USER_LIMIT', 0);
define('SPAMBOT_DEFAULT_BLOCKED_MESSAGE', 'Your email address or username or IP address is blacklisted.');
/**
* Implements hook_permission()
*/
function spambot_permission() {
return array(
'protected from spambot scans' => array(
'title' => t('Protected from spambot scans')
),
);
}
define('SPAMBOT_MAX_EVIDENCE_LENGTH', 1024);
/**
* Implements hook_menu().
*/
function spambot_menu() {
$items = array();
$items['admin/config/system/spambot'] = array(
'title' => 'Spambot',
'description' => 'Configure the spambot module',
@@ -38,159 +34,179 @@ function spambot_menu() {
$items['user/%user/spambot'] = array(
'title' => 'Spam',
'page callback' => 'drupal_get_form',
'page arguments' => array('spambot_user_spam_admin_form', 1),
'page callback' => 'spambot_user_spam',
'page arguments' => array(1),
'access arguments' => array('administer users'),
'type' => MENU_LOCAL_TASK,
'file' => 'spambot.pages.inc',
);
return $items;
}
/**
* Implementation of hook_form_FORM_ID_alter()
* Implements hook_permission().
*/
function spambot_form_user_register_form_alter(&$form, &$form_state, $form_id) {
if (variable_get('spambot_user_register_protect', TRUE) && !user_access('administer users')) {
$form['#validate'][] = 'spambot_user_register_validate';
function spambot_permission() {
return array(
'protected from spambot scans' => array(
'title' => t('Protected from spambot scans'),
'description' => t('Roles with this access permission would not be checked for spammer'),
),
);
}
/**
* Implements hook_admin_paths().
*/
function spambot_admin_paths() {
$paths = array(
'user/*/spambot' => TRUE,
);
return $paths;
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function spambot_form_user_register_form_alter(&$form, &$form_state) {
if (variable_get('spambot_user_register_protect', TRUE)) {
spambot_add_form_protection(
$form,
array(
'mail' => 'mail',
'name' => 'name',
'ip' => TRUE,
)
);
}
}
/**
* Validate the user_register form
* Implements hook_form_FORM_ID_alter().
*/
function spambot_user_register_validate($form, &$form_state) {
$email_threshold = variable_get('spambot_criteria_email', 1);
$username_threshold = variable_get('spambot_criteria_username', 0);
$ip_threshold = variable_get('spambot_criteria_ip', 20);
// Build request parameters according to the criteria to use
$request = array();
if (!empty($form_state['values']['mail']) && $email_threshold > 0) {
$request['email'] = $form_state['values']['mail'];
}
if (!empty($form_state['values']['name']) && $username_threshold > 0) {
$request['username'] = $form_state['values']['name'];
}
if ($ip_threshold > 0) {
$ip = ip_address();
// Don't check the loopback interface
if ($ip != '127.0.0.1') {
$request['ip'] = $ip;
}
}
// Only do a remote API request if there is anything to check
if (count($request)) {
$data = array();
if (spambot_sfs_request($request, $data)) {
$substitutions = array(
'@email' => $form_state['values']['mail'], '%email' => $form_state['values']['mail'],
'@username' => $form_state['values']['name'], '%username' => $form_state['values']['name'],
'@ip' => ip_address(), '%ip' => ip_address(),
);
$reasons = array();
if ($email_threshold > 0 && !empty($data['email']['appears']) && $data['email']['frequency'] >= $email_threshold) {
form_set_error('mail', t(variable_get('spambot_blocked_message_email', t(SPAMBOT_DEFAULT_BLOCKED_MESSAGE)), $substitutions));
$reasons[] = t('email=@value', array('@value' => $request['email']));
}
if ($username_threshold > 0 && !empty($data['username']['appears']) && $data['username']['frequency'] >= $username_threshold) {
form_set_error('name', t(variable_get('spambot_blocked_message_username', t(SPAMBOT_DEFAULT_BLOCKED_MESSAGE)), $substitutions));
$reasons[] = t('username=@value', array('@value' => $request['username']));
}
if ($ip_threshold > 0 && !empty($data['ip']['appears']) && $data['ip']['frequency'] >= $ip_threshold) {
form_set_error('', t(variable_get('spambot_blocked_message_ip', t(SPAMBOT_DEFAULT_BLOCKED_MESSAGE)), $substitutions));
$reasons[] = t('ip=@value', array('@value' => $request['ip']));
}
if (count($reasons)) {
watchdog('spambot', 'Blocked registration: @reasons', array('@reasons' => join(',', $reasons)));
// Slow them down if configured
$delay = variable_get('spambot_blacklisted_delay', 0);
if ($delay) {
sleep($delay);
}
}
}
function spambot_form_user_admin_account_alter(&$form, &$form_state, $form_id) {
foreach ($form['accounts']['#options'] as $uid => $user_options) {
// Change $form['accounts']['#options'][$uid]['operations']['data']
// into a multi-item render array so we can append to it.
$form['accounts']['#options'][$uid]['operations']['data'] = array(
'edit' => $form['accounts']['#options'][$uid]['operations']['data'],
);
$form['accounts']['#options'][$uid]['operations']['data']['spam'] = array(
'#type' => 'link',
'#title' => t('spam'),
'#href' => "user/$uid/spambot",
// Ugly hack to insert a space.
'#prefix' => ' ',
);
}
}
/**
* Implementation of hook_node_insert
*
* Keeps table node_spambot up to date
* Implements hook_node_insert().
*/
function spambot_node_insert($node) {
db_insert('node_spambot')->fields(array('nid' => $node->nid, 'uid' => $node->uid, 'hostname' => ip_address()))->execute();
db_insert('node_spambot')
->fields(array(
'nid' => $node->nid,
'uid' => $node->uid,
'hostname' => ip_address(),
))
->execute();
}
/**
* Implementation of hook_node_delete
*
* Keeps table node_spambot up to date
* Implements hook_node_delete().
*/
function spambot_node_delete($node) {
db_delete('node_spambot')->condition('nid', $node->nid)->execute();
db_delete('node_spambot')
->condition('nid', $node->nid)
->execute();
}
/**
* Implementation of hook_cron
* Implements hook_cron().
*/
function spambot_cron() {
$limit = variable_get('spambot_cron_user_limit', 0);
if ($limit) {
if ($limit = variable_get('spambot_cron_user_limit', SPAMBOT_DEFAULT_CRON_USER_LIMIT)) {
$last_uid = variable_get('spambot_last_checked_uid', 0);
if ($last_uid < 1) {
// Skip scanning the first account
// Skip scanning the anonymous and superadmin users.
$last_uid = 1;
}
$uids = db_select('users')->fields('users', array('uid'))
->condition('uid', $last_uid, '>')->orderBy('uid')
->range(0, $limit)->execute()->fetchCol();
$query = db_select('users')
->fields('users', array('uid'))
->condition('uid', $last_uid, '>')
->orderBy('uid')
->range(0, $limit);
if (!variable_get('spambot_check_blocked_accounts', FALSE)) {
$query->condition('status', 1);
}
$action = variable_get('spambot_spam_account_action', SPAMBOT_ACTION_NONE);
foreach ($uids as $uid) {
$account = user_load($uid);
if ($account->status || variable_get('spambot_check_blocked_accounts', FALSE)) {
$uids = $query
->execute()
->fetchCol();
if ($uids) {
$action = variable_get('spambot_spam_account_action', SPAMBOT_ACTION_NONE);
$accounts = user_load_multiple($uids);
foreach ($accounts as $account) {
$result = spambot_account_is_spammer($account);
if ($result > 0) {
$link = l(t('spammer'), 'user/' . $account->uid);
switch (user_access('protected from spambot scans', $account) ? SPAMBOT_ACTION_NONE : $action) {
case SPAMBOT_ACTION_BLOCK:
if ($account->status) {
user_save($account, array('status' => 0));
watchdog('spambot', 'Blocked spam account: @name &lt;@email&gt; (uid @uid)', array('@name' => $account->name, '@email' => $account->mail, '@uid' => $account->uid), WATCHDOG_NOTICE, $link);
// Block spammer's account.
$account->status = 0;
user_save($account);
watchdog('spambot', 'Blocked spam account: @name &lt;@email&gt; (uid @uid)', array(
'@name' => $account->name,
'@email' => $account->mail,
'@uid' => $account->uid,
), WATCHDOG_NOTICE, $link);
}
else {
// Don't block an already blocked account
watchdog('spambot', t('Spam account already blocked: @name &lt;@email&gt; (uid @uid)', array('@name' => $account->name, '@email' => $account->mail, '@uid' => $account->uid)), array(), WATCHDOG_NOTICE, $link);
// Don't block an already blocked account.
watchdog('spambot', 'Spam account already blocked: @name &lt;@email&gt; (uid @uid)', array(
'@name' => $account->name,
'@email' => $account->mail,
'@uid' => $account->uid,
), WATCHDOG_NOTICE, $link);
}
break;
case SPAMBOT_ACTION_DELETE:
user_delete($account->uid);
watchdog('spambot', 'Deleted spam account: @name &lt;@email&gt; (uid @uid)', array('@name' => $account->name, '@email' => $account->mail, '@uid' => $account->uid), WATCHDOG_NOTICE, $link);
watchdog('spambot', 'Deleted spam account: @name &lt;@email&gt; (uid @uid)', array(
'@name' => $account->name,
'@email' => $account->mail,
'@uid' => $account->uid,
), WATCHDOG_NOTICE, $link);
break;
default:
watchdog('spambot', 'Found spam account: @name &lt;@email&gt; (uid @uid)', array('@name' => $account->name, '@email' => $account->mail, '@uid' => $account->uid), WATCHDOG_NOTICE, $link);
watchdog('spambot', 'Found spam account: @name &lt;@email&gt; (uid @uid)', array(
'@name' => $account->name,
'@email' => $account->mail,
'@uid' => $account->uid,
), WATCHDOG_NOTICE, $link);
break;
}
// Mark this uid as successfully checked
variable_set('spambot_last_checked_uid', $uid);
// Mark this uid as successfully checked.
variable_set('spambot_last_checked_uid', $account->uid);
}
else if ($result == 0) {
// Mark this uid as successfully checked
variable_set('spambot_last_checked_uid', $uid);
elseif ($result == 0) {
// Mark this uid as successfully checked.
variable_set('spambot_last_checked_uid', $account->uid);
}
else if ($result < 0) {
// Error contacting service, so pause processing
elseif ($result < 0) {
// Error contacting service, so pause processing.
break;
}
}
@@ -199,42 +215,104 @@ function spambot_cron() {
}
/**
* Invoke www.stopforumspam.com's api
*
* @param $query
* A keyed array of url parameters ie. array('email' => 'blah@blah.com')
* @param $data
* An array that will be filled with the data from www.stopforumspam.com.
*
* @return
* TRUE on successful request (and $data will contain the data), FALSE if error
*
* $data should be an array of the following form:
* Array
* (
* [success] => 1
* [email] => Array
* (
* [lastseen] => 2010-01-10 08:41:26
* [frequency] => 2
* [appears] => 1
* )
*
* [username] => Array
* (
* [frequency] => 0
* [appears] => 0
* )
* )
*
* Validate callback for user_register form.
*/
function spambot_sfs_request($query, &$data) {
// An empty request results in no match
function spambot_user_register_form_validate(&$form, &$form_state) {
$validation_field_names = $form['#spambot_validation'];
$values = $form_state['values'];
$form_errors = form_get_errors();
$email_threshold = variable_get('spambot_criteria_email', SPAMBOT_DEFAULT_CRITERIA_EMAIL);
$username_threshold = variable_get('spambot_criteria_username', SPAMBOT_DEFAULT_CRITERIA_USERNAME);
$ip_threshold = variable_get('spambot_criteria_ip', SPAMBOT_DEFAULT_CRITERIA_IP);
// Build request parameters according to the criteria to use.
$request = array();
if (!empty($values[$validation_field_names['mail']]) && $email_threshold > 0 && !spambot_check_whitelist('email', $values[$validation_field_names['mail']])) {
$request['email'] = $values[$validation_field_names['mail']];
}
if (!empty($values[$validation_field_names['name']]) && $username_threshold > 0 && !spambot_check_whitelist('username', $values[$validation_field_names['name']])) {
$request['username'] = $values[$validation_field_names['name']];
}
$ip = ip_address();
if ($ip_threshold > 0 && $ip != '127.0.0.1' && $validation_field_names['ip'] && !spambot_check_whitelist('ip', $ip)) {
// Make sure we have a valid IPv4 address (API doesn't support IPv6 yet).
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === FALSE) {
watchdog('spambot', 'Invalid IP address on registration: @ip. Spambot will not rely on it.', array('@ip' => $ip));
}
else {
$request['ip'] = $ip;
}
}
// Only do a remote API request if there is anything to check.
if ($request && !$form_errors) {
$data = array();
if (spambot_sfs_request($request, $data)) {
$substitutions = array(
'@email' => $values[$validation_field_names['mail']],
'%email' => $values[$validation_field_names['mail']],
'@username' => $values[$validation_field_names['name']],
'%username' => $values[$validation_field_names['name']],
'@ip' => $ip,
'%ip' => $ip,
);
$reasons = array();
if ($email_threshold > 0 && !empty($data['email']['appears']) && $data['email']['frequency'] >= $email_threshold) {
form_set_error('mail', format_string(variable_get('spambot_blocked_message_email', SPAMBOT_DEFAULT_BLOCKED_MESSAGE), $substitutions));
$reasons[] = t('email=@value', array('@value' => $request['email']));
}
if ($username_threshold > 0 && !empty($data['username']['appears']) && $data['username']['frequency'] >= $username_threshold) {
form_set_error('name', format_string(variable_get('spambot_blocked_message_username', SPAMBOT_DEFAULT_BLOCKED_MESSAGE), $substitutions));
$reasons[] = t('username=@value', array('@value' => $request['username']));
}
if ($ip_threshold > 0 && !empty($data['ip']['appears']) && $data['ip']['frequency'] >= $ip_threshold) {
form_set_error('', format_string(variable_get('spambot_blocked_message_ip', SPAMBOT_DEFAULT_BLOCKED_MESSAGE), $substitutions));
$reasons[] = t('ip=@value', array('@value' => $request['ip']));
}
if ($reasons) {
if (variable_get('spambot_log_blocked_registration', TRUE)) {
watchdog('spambot', 'Blocked registration: @reasons', array('@reasons' => implode(',', $reasons)));
$hook_args = array(
'request' => $request,
'reasons' => $reasons,
);
module_invoke_all('spambot_registration_blocked', $hook_args);
}
// Slow them down if configured.
if ($delay = variable_get('spambot_blacklisted_delay', SPAMBOT_DEFAULT_DELAY)) {
sleep($delay);
}
}
}
}
}
/**
* Invoke www.stopforumspam.com's api.
*
* @param array $query
* A keyed array of url parameters ie. array('email' => 'blah@blah.com').
* @param array $data
* An array that will be filled with the data from www.stopforumspam.com.
*
* @return bool
* TRUE on successful request (and $data will contain the data)
* FALSE otherwise.
*/
function spambot_sfs_request(array $query, array &$data) {
// An empty request results in no match.
if (empty($query)) {
return FALSE;
}
// Use php serialisation format
// Use php serialisation format.
$query['f'] = 'serial';
$url = 'http://www.stopforumspam.com/api?' . http_build_query($query, '', '&');
@@ -245,11 +323,17 @@ function spambot_sfs_request($query, &$data) {
return TRUE;
}
else {
watchdog('spambot', "Request unsuccessful: @url <pre>\n@dump</pre>", array('@url' => $url, '@dump' => print_r($data, TRUE)));
watchdog('spambot', "Request unsuccessful: %url <pre>\n@dump</pre>", array(
'%url' => $url,
'@dump' => print_r($data, TRUE),
));
}
}
else {
watchdog('spambot', "Error contacting service: @url <pre>\n@dump</pre>", array('@url' => $url, '@dump' => print_r($result, TRUE)));
watchdog('spambot', "Error contacting service: %url <pre>\n@dump</pre>", array(
'%url' => $url,
'@dump' => print_r($result, TRUE),
));
}
return FALSE;
@@ -257,51 +341,69 @@ function spambot_sfs_request($query, &$data) {
/**
* Checks an account to see if it's a spammer.
* This one uses configurable automated criteria checking of email and username only
*
* @return
* positive if spammer, 0 if not spammer, negative if error
* This one uses configurable automated criteria checking
* of email and username only.
*
* @param object $account
* User account.
*
* @return int
* Positive if spammer, 0 if not spammer, negative if error.
*/
function spambot_account_is_spammer($account) {
$email_threshold = variable_get('spambot_criteria_email', 1);
$username_threshold = variable_get('spambot_criteria_username', 0);
$ip_threshold = variable_get('spambot_criteria_ip', 20);
// Build request parameters according to the criteria to use
$email_threshold = variable_get('spambot_criteria_email', SPAMBOT_DEFAULT_CRITERIA_EMAIL);
$username_threshold = variable_get('spambot_criteria_username', SPAMBOT_DEFAULT_CRITERIA_USERNAME);
$ip_threshold = variable_get('spambot_criteria_ip', SPAMBOT_DEFAULT_CRITERIA_IP);
// Build request parameters according to the criteria to use.
$request = array();
if (!empty($account->mail) && $email_threshold > 0) {
if (!empty($account->mail) && $email_threshold > 0 && !spambot_check_whitelist('email', $account->mail)) {
$request['email'] = $account->mail;
}
if (!empty($account->name) && $username_threshold > 0) {
if (!empty($account->name) && $username_threshold > 0 && !spambot_check_whitelist('username', $account->name)) {
$request['username'] = $account->name;
}
}
// Only do a remote API request if there is anything to check
if (count($request)) {
// Only do a remote API request if there is anything to check.
if ($request) {
$data = array();
if (spambot_sfs_request($request, $data)) {
if (($email_threshold > 0 && !empty($data['email']['appears']) && $data['email']['frequency'] >= $email_threshold) ||
($username_threshold > 0 && !empty($data['username']['appears']) && $data['username']['frequency'] >= $username_threshold)) {
if (($email_threshold > 0 && !empty($data['email']['appears']) && $data['email']['frequency'] >= $email_threshold)
|| ($username_threshold > 0 && !empty($data['username']['appears']) && $data['username']['frequency'] >= $username_threshold)) {
return 1;
}
}
else {
// Return error
// Return error.
return -1;
}
}
// Now check IP's
// If any IP matches the threshold, then flag as a spammer
// If any IP matches the threshold, then flag as a spammer.
if ($ip_threshold > 0) {
$ips = spambot_account_ip_addresses($account);
foreach ($ips as $ip) {
// Skip the loopback interface
// Skip the loopback interface.
if ($ip == '127.0.0.1') {
continue;
}
// Make sure we have a valid IPv4 address
// (the API doesn't support IPv6 yet).
elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === FALSE) {
$link = l(t('user'), 'user/' . $account->uid);
watchdog('spambot', 'Invalid IP address: %ip (uid=%uid, name=%name, email=%email). Spambot will not rely on it.', array(
'%ip' => $ip,
'%name' => $account->name,
'%email' => $account->mail,
'%uid' => $account->uid,
), WATCHDOG_NOTICE, $link);
continue;
}
$request = array('ip' => $ip);
$data = array();
if (spambot_sfs_request($request, $data)) {
@@ -310,56 +412,76 @@ function spambot_account_is_spammer($account) {
}
}
else {
// Abort on error
// Abort on error.
return -1;
}
}
}
// Return no match
// Return no match.
return 0;
}
/**
* Retrieves a list of IP addresses for an account
* Retrieves a list of IP addresses for an account.
*
* @param $account
* Account to retrieve IP addresses for
* @param object $account
* Account to retrieve IP addresses for.
*
* @return
* @return array
* An array of IP addresses, or an empty array if none found
*/
function spambot_account_ip_addresses($account) {
$hostnames = array();
// Retrieve IPs from node_spambot table
$items = db_select('node_spambot')->fields('node_spambot', array('hostname'))
->condition('uid', $account->uid, '=')->distinct()->execute()->fetchCol();
// Retrieve IPs from node_spambot table.
$items = db_select('node_spambot')
->distinct()
->fields('node_spambot', array('hostname'))
->condition('uid', $account->uid, '=')
->execute()
->fetchCol();
$hostnames = array_merge($hostnames, $items);
// Retrieve IPs from any sessions which may still exist
$items = db_select('sessions')->fields('sessions', array('hostname'))
->condition('uid', $account->uid, '=')->distinct()->execute()->fetchCol();
// Retrieve IPs from any sessions which may still exist.
$items = db_select('sessions')
->distinct()
->fields('sessions', array('hostname'))
->condition('uid', $account->uid, '=')
->execute()
->fetchCol();
$hostnames = array_merge($hostnames, $items);
// Retrieve IPs from comments
// Retrieve IPs from comments.
if (module_exists('comment')) {
$items = db_select('comment')->fields('comment', array('hostname'))
->condition('uid', $account->uid, '=')->distinct()->execute()->fetchCol();
$items = db_select('comment')
->distinct()
->fields('comment', array('hostname'))
->condition('uid', $account->uid, '=')
->execute()
->fetchCol();
$hostnames = array_merge($hostnames, $items);
}
// Retrieve IPs from statistics
// Retrieve IPs from statistics.
if (module_exists('statistics')) {
$items = db_select('accesslog')->fields('accesslog', array('hostname'))
->condition('uid', $account->uid, '=')->distinct()->execute()->fetchCol();
$items = db_select('accesslog')
->distinct()
->fields('accesslog', array('hostname'))
->condition('uid', $account->uid, '=')
->execute()
->fetchCol();
$hostnames = array_merge($hostnames, $items);
}
// Retrieve IPs from user stats
// Retrieve IPs from user stats.
if (module_exists('user_stats')) {
$items = db_select('user_stats_ips')->fields('user_stats_ips', array('ip_address'))
->condition('uid', $account->uid, '=')->distinct()->execute()->fetchCol();
$items = db_select('user_stats_ips')
->distinct()
->fields('user_stats_ips', array('ip_address'))
->condition('uid', $account->uid, '=')
->execute()
->fetchCol();
$hostnames = array_merge($hostnames, $items);
}
@@ -368,43 +490,111 @@ function spambot_account_ip_addresses($account) {
}
/**
* Reports an account as a spammer. Requires ip address and evidence of a single incident
* Reports an account as a spammer.
*
* @param $account
* Account to report
* @param $ip
* IP address to report
* @param $evidence
* Evidence to report
* Requires ip address and evidence of a single incident.
*
* @return
* @param object $account
* Account to report.
* @param string $ip
* IP address to report.
* @param string $evidence
* Evidence to report.
*
* @return bool
* TRUE if successful, FALSE if error
*/
function spambot_report_account($account, $ip, $evidence) {
$success = FALSE;
$key = variable_get('spambot_sfs_api_key', FALSE);
if ($key) {
if ($key = variable_get('spambot_sfs_api_key', FALSE)) {
$query['api_key'] = $key;
$query['email'] = $account->mail;
$query['username'] = $account->name;
$query['ip_addr'] = $ip;
$query['evidence'] = $evidence;
$query['evidence'] = truncate_utf8($evidence, SPAMBOT_MAX_EVIDENCE_LENGTH);
$url = 'http://www.stopforumspam.com/add.php';
$options = array(
'headers' => array('Content-type' => 'application/x-www-form-urlencoded'),
'method' => 'POST',
'data' => http_build_query($query, '', '&'),
);
$result = drupal_http_request($url, $options);
$url = 'http://www.stopforumspam.com/add.php?' . http_build_query($query, '', '&');
$result = drupal_http_request($url);
if (!empty($result->code) && $result->code == 200 && !empty($result->data) && stripos($result->data, 'data submitted successfully') !== FALSE) {
$success = TRUE;
}
else if (stripos($result->data, 'duplicate') !== FALSE) {
// www.stopforumspam.com can return a 503 code with data = '<p>recent duplicate entry</p>'
// which we will treat as successful.
elseif (stripos($result->data, 'duplicate') !== FALSE) {
// www.stopforumspam.com can return a 503 code
// with data = '<p>recent duplicate entry</p>'
// which we will treat as successful.
$success = TRUE;
}
else {
watchdog('spambot', "Error reporting account: @url <pre>\n@dump</pre>", array('@url' => $url, '@dump' => print_r($result, TRUE)));
watchdog('spambot', "Error reporting account: %url <pre>\n@dump</pre>", array(
'%url' => $url,
'@dump' => print_r($result, TRUE),
));
}
}
return $success;
}
/**
* Check if current data $type is whitelisted.
*
* @param string $type
* Type can be one of these three values: 'ip', 'email' or 'username'.
* @param string $value
* Value to be checked.
*
* @return bool
* TRUE if data is whitelisted, FALSE otherwise.
*/
function spambot_check_whitelist($type, $value) {
switch ($type) {
case 'ip':
$whitelist_ips = variable_get('spambot_whitelist_ip', '');
$result = strpos($whitelist_ips, $value) !== FALSE;
break;
case 'email':
$whitelist_usernames = variable_get('spambot_whitelist_email', '');
$result = strpos($whitelist_usernames, $value) !== FALSE;
break;
case 'username':
$whitelist_emails = variable_get('spambot_whitelist_username', '');
$result = strpos($whitelist_emails, $value) !== FALSE;
break;
default:
$result = FALSE;
break;
}
return $result;
}
/**
* Form builder function to add spambot validations.
*
* @param array $form
* Form array on which will be added spambot validation.
* @param array $options
* Array of options to be added to form.
*/
function spambot_add_form_protection(array &$form, array $options = array()) {
// Don't add any protections if the user can bypass the Spambot.
if (!user_access('protected from spambot scans')) {
// Allow other modules to alter the protections applied to this form.
drupal_alter('spambot_form_protections', $options, $form);
$form['#spambot_validation']['name'] = !empty($options['name']) ? $options['name'] : '';
$form['#spambot_validation']['mail'] = !empty($options['mail']) ? $options['mail'] : '';
$form['#spambot_validation']['ip'] = isset($options['ip']) && is_bool($options['ip']) ? $options['ip'] : TRUE;
$form['#validate'][] = 'spambot_user_register_form_validate';
}
}

View File

@@ -1,16 +1,47 @@
<?php
function spambot_user_spam_admin_form($form, &$form_state, $account) {
$node_count = db_select('node')->condition('uid', $account->uid, '=')
->countQuery()->execute()->fetchField();
if (module_exists('comment')) {
$comment_count = db_select('comment')->condition('uid', $account->uid, '=')
->countQuery()->execute()->fetchField();
$status = t('This account has @n nodes and @c comments.', array('@n' => $node_count, '@c' => $comment_count));
/**
* @file
* User available pages from Spambot module.
*/
/**
* Page callback for 'user/%user/spambot' path.
*/
function spambot_user_spam($account) {
// Check if current user isn't anonymous user.
if (!$account->uid) {
drupal_set_message(t("The Anonymous user account can't be reported for spam. If you intended to block a user account verify that the URL is /user/XXXX/spambot where XXXX is a valid UID"), 'warning');
return MENU_NOT_FOUND;
}
else {
$status = t('This account has @n nodes.', array('@n' => $node_count));
return drupal_get_form('spambot_user_spam_admin_form', $account);
}
/**
* Form builder for spambot_user_spam_admin_form form.
*/
function spambot_user_spam_admin_form($form, &$form_state, $account) {
$key = variable_get('spambot_sfs_api_key', FALSE);
$comments_enabled = module_exists('comment');
$node_count = db_select('node', 'n')
->fields('n', array('nid'))
->condition('uid', $account->uid)
->countQuery()
->execute()
->fetchField();
$status = t('This account has @n nodes.', array('@n' => $node_count));
if ($comments_enabled) {
$comment_count = db_select('comment', 'c')
->fields('c', array('cid'))
->condition('uid', $account->uid)
->countQuery()
->execute()
->fetchField();
$status = t('This account has @n nodes and @c comments.', array('@n' => $node_count, '@c' => $comment_count));
}
$form['check'] = array(
@@ -40,47 +71,88 @@ function spambot_user_spam_admin_form($form, &$form_state, $account) {
'#title' => t('Report this account to www.stopforumspam.com'),
'#tree' => TRUE,
'#collapsible' => TRUE,
'#description' => t('An API key from <a href="http://www.stopforumspam.com">www.stopforumspam.com</a> is required to report spammers.<br />Select one or more posts below to report them to www.stopforumspam.com.'),
);
// Fetch a list of reportable nodes
// Fetch a list of reportable nodes.
$form['action']['report']['nids'] = array();
$result = db_select('node_spambot')->fields('node_spambot', array('nid', 'hostname'))->condition('uid', $account->uid)->orderBy('nid', 'DESC')->range(0, 20)->execute();
$result = db_select('node_spambot', 'ns')
->fields('ns', array('nid', 'hostname'))
->condition('ns.uid', $account->uid)
->orderBy('ns.nid', 'DESC')
->range(0, 20)
->execute();
$nid_hostnames = array();
foreach ($result as $record) {
$nid_hostnames[$record->nid] = $record->hostname;
}
foreach ($nid_hostnames as $nid => $hostname) {
$node = node_load($nid);
if (!empty($node->nid)) {
if ($node = node_load($nid)) {
$title = truncate_utf8(check_plain($node->title), 128, TRUE, TRUE);
$form['action']['report']['nids'][$nid] = array(
'#type' => 'checkbox',
'#title' => l(mb_strimwidth($node->title, 0, 128, '...'), 'node/' . $nid, array('attributes' => array('title' => mb_strimwidth($node->body['und'][0]['summary'] . "\n\n" . $node->body['und'][0]['value'], 0, 256, '...')))) . ' ' . t('(node, ip=@ip)', array('@ip' => $hostname)),
'#title' => l(
$title,
"node/$nid",
array(
'attributes' => array(
'title' => $title,
),
)
) . ' ' . t('(node, ip=@ip)', array('@ip' => $hostname)),
'#disabled' => !$key,
);
}
}
// Fetch a list of reportable comments
if (module_exists('comment')) {
// Fetch a list of reportable comments.
if ($comments_enabled) {
$form['action']['report']['cids'] = array();
$result = db_select('comment')->fields('comment', array('cid'))->condition('uid', $account->uid)->orderBy('cid', 'DESC')->range(0, 20)->execute();
$result = db_select('comment')
->fields('comment', array('cid'))
->condition('uid', $account->uid)
->orderBy('cid', 'DESC')
->range(0, 20)
->execute();
$cids = array();
foreach ($result as $record) {
$cids[$record->cid] = $record->cid;
}
foreach ($cids as $cid) {
$comment = comment_load($cid);
if (!empty($comment->cid)) {
if ($comment = comment_load($cid)) {
$subject = truncate_utf8(check_plain($comment->subject), 128, TRUE, TRUE);
$form['action']['report']['cids'][$cid] = array(
'#type' => 'checkbox',
'#title' => l(mb_strimwidth($comment->subject, 0, 128, '...'), 'node/' . $comment->nid, array('fragment' => 'comment-'. $comment->cid, 'attributes' => array('title' => mb_strimwidth($comment->comment_body['und'][0]['value'], 0, 256, '...')))) . ' ' . t('(comment, ip=@ip)', array('@ip' => $comment->hostname)),
'#title' => l(
$subject,
"node/$comment->nid",
array(
'fragment' => "comment-$comment->cid",
'attributes' => array(
'title' => $subject,
),
)
) . ' ' . t('(comment, ip=@ip)', array('@ip' => $comment->hostname)),
'#disabled' => !$key,
);
}
}
}
if ($key) {
$comment_cids = $comments_enabled ? count($form['action']['report']['cids']) : 0;
$evidence_count = count($form['action']['report']['nids']) + $comment_cids;
$form['action']['report']['#description'] = $evidence_count ? t('Select one or more posts below to report them to www.stopforumspam.com.') : t('This account cannot be reported because no evidence or IP address is available.');
}
else {
$form['action']['report']['#description'] = t('An API key from <a href="http://www.stopforumspam.com">www.stopforumspam.com</a> must <a href="!admin-url">be configured</a> to report spammers.', array('!admin-url' => url('admin/config/system/spambot')));
}
$form['action']['block_user'] = array(
'#type' => 'checkbox',
'#title' => t('Block this account'),
@@ -90,175 +162,273 @@ function spambot_user_spam_admin_form($form, &$form_state, $account) {
'#type' => 'checkbox',
'#title' => t('Delete this account'),
'#default_value' => FALSE,
);
);
$form['action']['action'] = array(
'#type' => 'submit',
'#value' => t('Take action'),
);
$form['uid'] = array('#type' => 'value', '#value' => $account->uid);
$form['uid'] = array(
'#type' => 'value',
'#value' => $account->uid,
);
$form['#validate'][] = 'spambot_user_spam_admin_form_validate';
$form['#submit'][] = 'spambot_user_spam_admin_form_submit';
return $form;
}
function spambot_user_spam_admin_form_validate($form, &$form_state) {
$key_required = (!empty($form_state['values']['report']['nids']) && count(array_filter($form_state['values']['report']['nids']))) ? TRUE : FALSE;
/**
* Validate handler for spambot_user_spam_admin_form() form.
*/
function spambot_user_spam_admin_form_validate(&$form, &$form_state) {
$key_required = (!empty($form_state['values']['report']['nids']) && count(array_filter($form_state['values']['report']['nids']))) ? TRUE : FALSE;
if (module_exists('comment')) {
$key_required = (!empty($form_state['values']['report']['cids']) && count(array_filter($form_state['values']['report']['cids']))) || $key_required;
}
if ($key_required && (!variable_get('spambot_sfs_api_key', FALSE))) {
form_set_error('', t('To report spammers to www.stopforumspam.com, you need to register for an API key at <a href="http://www.stopforumspam.com">www.stopforumspam.com</a> and enter it into the !page.', array('!page' => l('spambot settings', 'admin/config/system/spambot'))));
if ($key_required && !variable_get('spambot_sfs_api_key', FALSE)) {
form_set_error('', t('To report spammers to www.stopforumspam.com, you need to register for an API key at <a href="http://www.stopforumspam.com">www.stopforumspam.com</a> and enter it into the !page.', array(
'!page' => l(t('spambot settings'), 'admin/config/system/spambot'),
)));
}
}
function spambot_user_spam_admin_form_submit($form, &$form_state) {
/**
* Submit handler for spambot_user_spam_admin_form() form.
*/
function spambot_user_spam_admin_form_submit(&$form, &$form_state) {
$account = user_load($form_state['values']['uid']);
if ($form_state['values']['op'] == $form_state['values']['check']) {
// This is a more comprehensive check than the automated criteria checks.
// This tests everything.
$messages = array();
$service_down = FALSE;
_spambot_user_spam_admin_form_submit_check($form, $form_state, $account);
}
elseif ($form_state['values']['op'] == $form_state['values']['action']) {
_spambot_user_spam_admin_form_submit_action($form, $form_state, $account);
}
}
// Check email and username
$request = array('email' => $account->mail, 'username' => $account->name);
$data = array();
if (spambot_sfs_request($request, $data)) {
if (!empty($data['email']['appears'])) {
$messages[] = t('This account\'s email address matches @num times: !link', array('!link' => l($request['email'], 'http://www.stopforumspam.com/search?q=' . $request['email']), '@num' => $data['email']['frequency']));
}
/**
* Do complex checking at this user account.
*/
function _spambot_user_spam_admin_form_submit_check(&$form, &$form_state, $account) {
$messages = array();
$service_down = FALSE;
if (!empty($data['username']['appears'])) {
$messages[] = t('This account\'s username matches @num times: !link', array('!link' => l($request['username'], 'http://www.stopforumspam.com/search?q=' . $request['username']), '@num' => $data['username']['frequency']));
}
}
else {
drupal_set_message(t('Error contacting service.'), 'warning');
$service_down = TRUE;
// Check email and username.
$data = array();
$request = array(
'email' => $account->mail,
'username' => $account->name,
);
if (spambot_sfs_request($request, $data)) {
if (!empty($data['email']['appears'])) {
$messages[] = array(
'text' => t("This account's email address matches %num times: !link", array(
'!link' => l($request['email'], 'http://www.stopforumspam.com/search?q=' . $request['email']),
'%num' => $data['email']['frequency'],
)),
'type' => 'warning',
);
}
// Check IP addresses
if (!$service_down) {
$ips = spambot_account_ip_addresses($account);
foreach ($ips as $ip) {
// Skip the loopback interface
if ($ip == '127.0.0.1') {
continue;
}
$request = array('ip' => $ip);
$data = array();
if (spambot_sfs_request($request, $data)) {
if (!empty($data['ip']['appears'])) {
$messages[] = t('An IP address !ip used by this account matches @num times.', array('!ip' => l($ip, 'http://www.stopforumspam.com/search?q=' . $ip), '@num' => $data['ip']['frequency']));
}
}
else {
drupal_set_message(t('Error contacting service.'), 'warning');
$service_down = TRUE;
break;
}
}
if (!empty($data['username']['appears'])) {
$messages[] = array(
'text' => t("This account's username matches %num times: !link", array(
'!link' => l($request['username'], 'http://www.stopforumspam.com/search?q=' . $request['username']),
'%num' => $data['username']['frequency'],
)),
'type' => 'warning',
);
}
if (count($messages)) {
foreach ($messages as $message) {
drupal_set_message($message);
}
// Check data at whitelist.
if (spambot_check_whitelist('email', $account->mail)) {
$messages[] = array(
'text' => t("This account's email address placed at your whitelist."),
'type' => 'status',
);
}
else {
drupal_set_message(t('No matches against known spammers found.'));
if (spambot_check_whitelist('username', $account->name)) {
$messages[] = array(
'text' => t("This account's username placed at your whitelist."),
'type' => 'status',
);
}
}
else if ($form_state['values']['op'] == $form_state['values']['action']) {
if ($account->uid == 1) {
drupal_set_message(t('Sorry, taking action against uid 1 is not allowed.'));
return;
}
else {
drupal_set_message(t('Error contacting service.'), 'warning');
$service_down = TRUE;
}
// Block account
if (!empty($form_state['values']['block_user'])) {
if ($account->status) {
user_save($account, array('status' => 0));
drupal_set_message(t('Account blocked.'));
// Check IP addresses.
if (!$service_down) {
$ips = spambot_account_ip_addresses($account);
foreach ($ips as $ip) {
// Skip the loopback interface.
if ($ip == '127.0.0.1') {
continue;
}
elseif (spambot_check_whitelist('ip', $ip)) {
$whitelist_ips[] = $ip;
continue;
}
// Make sure we have a valid IPv4 address
// (the API doesn't support IPv6 yet).
elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === FALSE) {
$messages[] = array(
'text' => t('Invalid IP address: @ip. Spambot will not rely on it.', array('@ip' => $ip)),
'type' => 'warning',
);
continue;
}
$request = array('ip' => $ip);
$data = array();
if (spambot_sfs_request($request, $data)) {
if (!empty($data['ip']['appears'])) {
$messages[] = array(
'text' => t('An IP address !ip used by this account matches %num times.', array(
'!ip' => l($ip, 'http://www.stopforumspam.com/search?q=' . $ip),
'%num' => $data['ip']['frequency'],
)),
'type' => 'warning',
);
}
}
else {
drupal_set_message(t('This account is already blocked.'));
drupal_set_message(t('Error contacting service.'), 'warning');
break;
}
}
// Prepare some data
$nodes = db_select('node')->fields('node', array('nid'))
->condition('uid', $account->uid, '=')->orderBy('nid')->execute()->fetchCol();
$node_hostnames = array();
$result = db_select('node_spambot')->fields('node_spambot', array('nid', 'hostname'))->condition('uid', $account->uid)->orderBy('nid', 'DESC')->execute();
foreach ($result as $record) {
$node_hostnames[$record->nid] = $record->hostname;
}
$comments = array();
if (module_exists('comment')) {
$comments = db_select('comment')->fields('comment', array('cid'))
->condition('uid', $account->uid, '=')->orderBy('cid')->execute()->fetchCol();
}
// Report posts to www.stopforumspam.com
if (!empty($form_state['values']['report']['nids'])) {
foreach (array_filter($form_state['values']['report']['nids']) as $nid => $unused) {
$node = node_load($nid);
if (!empty($node->nid)) {
if (spambot_report_account($account, $node_hostnames[$nid], $node->title . "\n\n" . $node->body['und'][0]['summary'] . "\n\n" . $node->body['und'][0]['value'])) {
drupal_set_message(t('Node %title has been reported.', array('%title' => $node->title)));
}
else {
drupal_set_message(t('There was a problem reporting node %title.', array('%title' => $node->title)));
}
}
}
}
if (module_exists('comment') && !empty($form_state['values']['report']['cids'])) {
foreach (array_filter($form_state['values']['report']['cids']) as $cid => $unused) {
$comment = comment_load($cid);
if (!empty($comment->cid)) {
if (spambot_report_account($account, $comment->hostname, $comment->subject . "\n\n" . $comment->comment_body['und'][0]['value'])) {
drupal_set_message(t('Comment %title has been reported.', array('%title' => $comment->subject)));
}
else {
drupal_set_message(t('There was a problem reporting comment %title.', array('%title' => $comment->subject)));
}
}
}
}
// Delete nodes and content
if (!empty($form_state['values']['delete_content'])) {
node_delete_multiple($nodes);
if (count($comments)) {
comment_delete_multiple($comments);
}
drupal_set_message(t('Nodes and comments have been deleted.'));
}
else if (!empty($form_state['values']['unpublish_content'])) {
// Unpublish nodes and content
if (count($nodes)) {
module_load_include('inc', 'node', 'node.admin');
node_mass_update($nodes, array('status' => 0));
}
if (count($comments)) {
db_update('comment')->fields(array('status' => COMMENT_NOT_PUBLISHED))
->condition('uid', $account->uid)->execute();
cache_clear_all();
}
drupal_set_message(t('Nodes and comments have been unpublished.'));
}
// Delete user
if (!empty($form_state['values']['delete_user'])) {
// Redirect to user delete form
$form_state['redirect'] = 'user/' . $account->uid . '/cancel';
if (!empty($whitelist_ips)) {
$messages[] = array(
'text' => t('These IP addresses placed at your whitelist: %ips', array('%ips' => implode(', ', $whitelist_ips))),
'type' => 'status',
);
}
}
if ($messages) {
foreach ($messages as $message) {
drupal_set_message($message['text'], $message['type']);
}
}
else {
drupal_set_message(t('No matches against known spammers found.'));
}
}
/**
* Take action under this user account.
*/
function _spambot_user_spam_admin_form_submit_action(&$form, &$form_state, $account) {
$comments_enabled = module_exists('comment');
if ($account->uid == 1) {
drupal_set_message(t('Sorry, taking action against uid 1 is not allowed.'), 'warning');
return;
}
// Block account.
if (!empty($form_state['values']['block_user'])) {
if ($account->status) {
user_save($account, array('status' => 0));
drupal_set_message(t('Account blocked.'));
}
else {
drupal_set_message(t('This account is already blocked.'));
}
}
// Prepare some data.
$nodes = db_select('node')
->fields('node', array('nid'))
->condition('uid', $account->uid, '=')
->orderBy('nid')
->execute()
->fetchCol();
$node_hostnames = array();
$result = db_select('node_spambot')
->fields('node_spambot', array('nid', 'hostname'))
->condition('uid', $account->uid)
->orderBy('nid', 'DESC')
->execute();
foreach ($result as $record) {
$node_hostnames[$record->nid] = $record->hostname;
}
$comments = array();
if ($comments_enabled) {
$comments = db_select('comment')
->fields('comment', array('cid'))
->condition('uid', $account->uid, '=')
->orderBy('cid')
->execute()
->fetchCol();
}
// Report posts to www.stopforumspam.com.
if (!empty($form_state['values']['report']['nids'])) {
foreach (array_filter($form_state['values']['report']['nids']) as $nid => $unused) {
$node = node_load($nid);
if (!empty($node->nid)) {
if (spambot_report_account($account, $node_hostnames[$nid], $node->title . "\n\n" . $node->body[LANGUAGE_NONE][0]['summary'] . "\n\n" . $node->body[LANGUAGE_NONE][0]['value'])) {
drupal_set_message(t('Node %title has been reported.', array('%title' => $node->title)));
}
else {
drupal_set_message(t('There was a problem reporting node %title.', array('%title' => $node->title)));
}
}
}
}
if ($comments_enabled && !empty($form_state['values']['report']['cids'])) {
foreach (array_filter($form_state['values']['report']['cids']) as $cid => $unused) {
$comment = comment_load($cid);
if (!empty($comment->cid)) {
if (spambot_report_account($account, $comment->hostname, $comment->subject . "\n\n" . $comment->comment_body[LANGUAGE_NONE][0]['value'])) {
drupal_set_message(t('Comment %title has been reported.', array('%title' => $comment->subject)));
}
else {
drupal_set_message(t('There was a problem reporting comment %title.', array('%title' => $comment->subject)));
}
}
}
}
// Delete nodes and content.
if (!empty($form_state['values']['delete_content'])) {
node_delete_multiple($nodes);
if ($comments) {
comment_delete_multiple($comments);
}
drupal_set_message(t('Nodes and comments have been deleted.'));
}
elseif (!empty($form_state['values']['unpublish_content'])) {
// Unpublish nodes and content.
if ($nodes) {
module_load_include('inc', 'node', 'node.admin');
node_mass_update($nodes, array('status' => 0));
}
if ($comments) {
db_update('comment')
->fields(array('status' => COMMENT_NOT_PUBLISHED))
->condition('uid', $account->uid)
->execute();
}
drupal_set_message(t('Nodes and comments have been unpublished.'));
}
// Delete user.
if (!empty($form_state['values']['delete_user'])) {
// Redirect to user delete form.
$form_state['redirect'] = "user/$account->uid/cancel";
}
}