Patch #1161486 by rootatwc, sun, andypost, catch, marcingy, aspilicious, cam8001: Move IP blocking into its own module.
parent
2f31f5cee7
commit
4e4ea71e66
core
includes
modules
ban
statistics
lib/Drupal/statistics/Tests
system
|
@ -1888,56 +1888,6 @@ function drupal_set_title($title = NULL, $output = CHECK_PLAIN) {
|
|||
return $stored_title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if an IP address has been blocked.
|
||||
*
|
||||
* Blocked IP addresses are stored in the database by default. However for
|
||||
* performance reasons we allow an override in settings.php. This allows us
|
||||
* to avoid querying the database at this critical stage of the bootstrap if
|
||||
* an administrative interface for IP address blocking is not required.
|
||||
*
|
||||
* @param $ip
|
||||
* IP address to check.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if access is denied, FALSE if access is allowed.
|
||||
*/
|
||||
function drupal_is_denied($ip) {
|
||||
// Because this function is called on every page request, we first check
|
||||
// for an array of IP addresses in settings.php before querying the
|
||||
// database.
|
||||
$blocked_ips = variable_get('blocked_ips');
|
||||
$denied = FALSE;
|
||||
if (isset($blocked_ips) && is_array($blocked_ips)) {
|
||||
$denied = in_array($ip, $blocked_ips);
|
||||
}
|
||||
// Only check if database.inc is loaded already. If
|
||||
// $conf['page_cache_without_database'] = TRUE; is set in settings.php,
|
||||
// then the database won't be loaded here so the IPs in the database
|
||||
// won't be denied. However the user asked explicitly not to use the
|
||||
// database and also in this case it's quite likely that the user relies
|
||||
// on higher performance solutions like a firewall.
|
||||
elseif (class_exists('Drupal\Core\Database\Database', FALSE)) {
|
||||
$denied = (bool)db_query("SELECT 1 FROM {blocked_ips} WHERE ip = :ip", array(':ip' => $ip))->fetchField();
|
||||
}
|
||||
return $denied;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles denied users.
|
||||
*
|
||||
* @param $ip
|
||||
* IP address to check. Prints a message and exits if access is denied.
|
||||
*/
|
||||
function drupal_block_denied($ip) {
|
||||
// Deny access to blocked IP addresses - t() is not yet available.
|
||||
if (drupal_is_denied($ip)) {
|
||||
header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
|
||||
print 'Sorry, ' . check_plain(ip_address()) . ' has been banned.';
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string of highly randomized bytes (over the full 8-bit range).
|
||||
*
|
||||
|
@ -2314,7 +2264,6 @@ function _drupal_bootstrap_page_cache() {
|
|||
$config = config('system.performance');
|
||||
$cache_enabled = $config->get('cache.page.enabled');
|
||||
}
|
||||
drupal_block_denied(ip_address());
|
||||
// If there is no session cookie and cache is enabled (or forced), try
|
||||
// to serve a cached page.
|
||||
if (!isset($_COOKIE[session_name()]) && $cache_enabled) {
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Administrative functionality for the Ban module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Page callback; Displays banned IP addresses.
|
||||
*
|
||||
* @param string $default_ip
|
||||
* (optional) IP address to be passed on to drupal_get_form() for
|
||||
* use as the default value of the IP address form field.
|
||||
*/
|
||||
function ban_admin_page($default_ip = '') {
|
||||
$rows = array();
|
||||
$header = array(t('banned IP addresses'), t('Operations'));
|
||||
$result = db_query('SELECT * FROM {ban_ip}');
|
||||
foreach ($result as $ip) {
|
||||
$rows[] = array(
|
||||
$ip->ip,
|
||||
l(t('delete'), "admin/config/people/ban/delete/$ip->iid"),
|
||||
);
|
||||
}
|
||||
|
||||
$build['ban_ip_form'] = drupal_get_form('ban_ip_form', $default_ip);
|
||||
|
||||
$build['ban_ip_banning_table'] = array(
|
||||
'#theme' => 'table',
|
||||
'#header' => $header,
|
||||
'#rows' => $rows,
|
||||
'#empty' => t('No blocked IP addresses available.'),
|
||||
);
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form constructor for banning an IP address.
|
||||
*
|
||||
* @param string $default_ip
|
||||
* An IP address to ban, used as default value.
|
||||
*
|
||||
* @see ban_ip_form_validate()
|
||||
* @see ban_ip_form_submit()
|
||||
*
|
||||
* @ingroup forms
|
||||
*/
|
||||
function ban_ip_form($form, &$form_state, $default_ip) {
|
||||
$form['ip'] = array(
|
||||
'#title' => t('IP address'),
|
||||
'#type' => 'textfield',
|
||||
'#size' => 48,
|
||||
'#maxlength' => 40,
|
||||
'#default_value' => $default_ip,
|
||||
'#description' => t('Enter a valid IP address.'),
|
||||
);
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
$form['actions']['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Add'),
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form validation handler for ban_ip_form().
|
||||
*
|
||||
* @see ban_ip_form_submit()
|
||||
*/
|
||||
function ban_ip_form_validate($form, &$form_state) {
|
||||
$ip = trim($form_state['values']['ip']);
|
||||
if (db_query("SELECT * FROM {ban_ip} WHERE ip = :ip", array(':ip' => $ip))->fetchField()) {
|
||||
form_set_error('ip', t('This IP address is already banned.'));
|
||||
}
|
||||
elseif ($ip == ip_address()) {
|
||||
form_set_error('ip', t('You may not ban your own IP address.'));
|
||||
}
|
||||
elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE) == FALSE) {
|
||||
form_set_error('ip', t('Enter a valid IP address.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submission handler for ban_ip_form().
|
||||
*
|
||||
* @see ban_ip_form_validate()
|
||||
*/
|
||||
function ban_ip_form_submit($form, &$form_state) {
|
||||
$ip = trim($form_state['values']['ip']);
|
||||
db_insert('ban_ip')
|
||||
->fields(array('ip' => $ip))
|
||||
->execute();
|
||||
drupal_set_message(t('The IP address %ip has been banned.', array('%ip' => $ip)));
|
||||
$form_state['redirect'] = 'admin/config/people/ban';
|
||||
}
|
||||
|
||||
/**
|
||||
* Form constructor to unban an IP address.
|
||||
*
|
||||
* @param array $ban_ip
|
||||
* The IP address record to unban, as provided by ban_ip_load().
|
||||
*
|
||||
* @see ban_ip_delete_submit()
|
||||
*/
|
||||
function ban_ip_delete_form($form, &$form_state, array $ban_ip) {
|
||||
$form['ban_ip'] = array(
|
||||
'#type' => 'value',
|
||||
'#value' => $ban_ip,
|
||||
);
|
||||
return confirm_form($form,
|
||||
t('Are you sure you want to delete %ip?', array('%ip' => $ban_ip['ip'])),
|
||||
'admin/config/people/ban',
|
||||
NULL,
|
||||
t('Delete')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submission handler for ban_ip_delete_form().
|
||||
*/
|
||||
function ban_ip_delete_form_submit($form, &$form_state) {
|
||||
$banned_ip = $form_state['values']['ban_ip'];
|
||||
db_delete('ban_ip')
|
||||
->condition('iid', $banned_ip['iid'])
|
||||
->execute();
|
||||
watchdog('user', 'Deleted %ip', array('%ip' => $banned_ip['ip']));
|
||||
drupal_set_message(t('The IP address %ip was deleted.', array('%ip' => $banned_ip['ip'])));
|
||||
$form_state['redirect'] = 'admin/config/people/ban';
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
name = Ban
|
||||
description = Enables banning of IP addresses.
|
||||
package = Core
|
||||
version = VERSION
|
||||
core = 8.x
|
||||
configure = admin/config/people/ban
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Install, update and uninstall functions for the Ban module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_schema().
|
||||
*/
|
||||
function ban_schema() {
|
||||
$schema['ban_ip'] = array(
|
||||
'description' => 'Stores banned IP addresses.',
|
||||
'fields' => array(
|
||||
'iid' => array(
|
||||
'description' => 'Primary Key: unique ID for IP addresses.',
|
||||
'type' => 'serial',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'ip' => array(
|
||||
'description' => 'IP address',
|
||||
'type' => 'varchar',
|
||||
'length' => 40,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
),
|
||||
'indexes' => array(
|
||||
'ip' => array('ip'),
|
||||
),
|
||||
'primary key' => array('iid'),
|
||||
);
|
||||
return $schema;
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Enables banning of IP addresses.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_help().
|
||||
*/
|
||||
function ban_help($path, $arg) {
|
||||
switch ($path) {
|
||||
case 'admin/help#ban':
|
||||
$output = '';
|
||||
$output .= '<h3>' . t('About') . '</h3>';
|
||||
$output .= '<p>' . t('The Ban module allows administrators to ban visits to their site from given IP addresses.') . '</p>';
|
||||
$output .= '<h3>' . t('Uses') . '</h3>';
|
||||
$output .= '<dl>';
|
||||
$output .= '<dt>' . t('Banning IP addresses') . '</dt>';
|
||||
$output .= '<dd>' . t('Administrators can enter IP addresses to ban on the <a href="@bans">IP address bans</a> page.', array('@bans' => url('admin/config/people/ban'))) . '</dd>';
|
||||
$output .= '</dl>';
|
||||
return $output;
|
||||
|
||||
case 'admin/config/people/ban':
|
||||
return '<p>' . t('IP addresses listed here are banned from your site. Banned addresses are completely forbidden from accessing the site and instead see a brief message explaining the situation.') . '</p>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_permission().
|
||||
*/
|
||||
function ban_permission() {
|
||||
return array(
|
||||
'ban IP addresses' => array(
|
||||
'title' => t('Ban IP addresses'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_menu().
|
||||
*/
|
||||
function ban_menu() {
|
||||
$items['admin/config/people/ban'] = array(
|
||||
'title' => 'IP address bans',
|
||||
'description' => 'Manage banned IP addresses.',
|
||||
'page callback' => 'ban_admin_page',
|
||||
'access arguments' => array('ban IP addresses'),
|
||||
'file' => 'ban.admin.inc',
|
||||
'weight' => 10,
|
||||
);
|
||||
$items['admin/config/people/ban/delete/%ban_ip'] = array(
|
||||
'title' => 'Delete IP address',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('ban_ip_delete_form', 5),
|
||||
'access arguments' => array('ban IP addresses'),
|
||||
'file' => 'ban.admin.inc',
|
||||
);
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_boot().
|
||||
*/
|
||||
function ban_boot() {
|
||||
ban_block_denied(ip_address());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether an IP address is blocked.
|
||||
*
|
||||
* Blocked IP addresses are stored in the database by default. However, for
|
||||
* performance reasons we allow an override in variables.
|
||||
*
|
||||
* @param string $ip
|
||||
* The IP address to check.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if access is denied, FALSE if access is allowed.
|
||||
*/
|
||||
function ban_is_denied($ip) {
|
||||
$denied = FALSE;
|
||||
// Because this function is called on every page request, we first check
|
||||
// for an array of IP addresses in settings.php before querying the
|
||||
// database.
|
||||
$blocked_ips = variable_get('blocked_ips');
|
||||
if (isset($blocked_ips) && is_array($blocked_ips)) {
|
||||
$denied = in_array($ip, $blocked_ips);
|
||||
}
|
||||
// If $conf['page_cache_without_database'] = TRUE; is set in settings.php,
|
||||
// then the database is not available yet, so IPs recorded in the database
|
||||
// won't be denied. However, the user asked explicitly not to use the
|
||||
// database, and in this case it's also quite likely that the user relies
|
||||
// on higher performance solutions like a firewall.
|
||||
elseif (class_exists('Drupal\Core\Database\Database', FALSE) && function_exists('db_query')) {
|
||||
$denied = (bool) db_query("SELECT 1 FROM {ban_ip} WHERE ip = :ip", array(':ip' => $ip))->fetchField();
|
||||
}
|
||||
return $denied;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message and exits if access from a given IP address is denied.
|
||||
*
|
||||
* @param string $ip
|
||||
* The IP address to check.
|
||||
*/
|
||||
function ban_block_denied($ip) {
|
||||
// Check whether the given IP address has been blocked.
|
||||
if (ban_is_denied($ip)) {
|
||||
header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
|
||||
// t() is not yet available.
|
||||
print 'Sorry, ' . check_plain($ip) . ' has been banned.';
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a banned IP address record from the database.
|
||||
*
|
||||
* @param int $iid
|
||||
* The ID of the banned IP address to retrieve.
|
||||
*
|
||||
* @return array
|
||||
* The banned IP address record from the database as an array.
|
||||
*/
|
||||
function ban_ip_load($iid) {
|
||||
return db_query("SELECT * FROM {ban_ip} WHERE iid = :iid", array(':iid' => $iid))->fetchAssoc();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_action_info().
|
||||
*/
|
||||
function ban_action_info() {
|
||||
return array(
|
||||
'ban_ip_action' => array(
|
||||
'type' => 'user',
|
||||
'label' => t('Ban IP address of current user'),
|
||||
'configurable' => FALSE,
|
||||
'triggers' => array('any'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bans the current user's IP address.
|
||||
*
|
||||
* @ingroup actions
|
||||
*/
|
||||
function ban_ip_action() {
|
||||
$ip = ip_address();
|
||||
db_insert('blocked_ips')
|
||||
->fields(array('ip' => $ip))
|
||||
->execute();
|
||||
watchdog('action', 'Banned IP address %ip', array('%ip' => $ip));
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\ban\Tests\IpAddressBlockingTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\ban\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
class IpAddressBlockingTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('ban');
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'IP address banning',
|
||||
'description' => 'Test IP address banning.',
|
||||
'group' => 'Ban'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a variety of user input to confirm correct validation and saving of data.
|
||||
*/
|
||||
function testIPAddressValidation() {
|
||||
// Create user.
|
||||
$admin_user = $this->drupalCreateUser(array('ban IP addresses'));
|
||||
$this->drupalLogin($admin_user);
|
||||
$this->drupalGet('admin/config/people/ban');
|
||||
|
||||
// Ban a valid IP address.
|
||||
$edit = array();
|
||||
$edit['ip'] = '192.168.1.1';
|
||||
$this->drupalPost('admin/config/people/ban', $edit, t('Add'));
|
||||
$ip = db_query("SELECT iid from {ban_ip} WHERE ip = :ip", array(':ip' => $edit['ip']))->fetchField();
|
||||
$this->assertTrue($ip, t('IP address found in database.'));
|
||||
$this->assertRaw(t('The IP address %ip has been banned.', array('%ip' => $edit['ip'])), 'IP address was banned.');
|
||||
|
||||
// Try to block an IP address that's already blocked.
|
||||
$edit = array();
|
||||
$edit['ip'] = '192.168.1.1';
|
||||
$this->drupalPost('admin/config/people/ban', $edit, t('Add'));
|
||||
$this->assertText(t('This IP address is already banned.'));
|
||||
|
||||
// Try to block a reserved IP address.
|
||||
$edit = array();
|
||||
$edit['ip'] = '255.255.255.255';
|
||||
$this->drupalPost('admin/config/people/ban', $edit, t('Add'));
|
||||
$this->assertText(t('Enter a valid IP address.'));
|
||||
|
||||
// Try to block a reserved IP address.
|
||||
$edit = array();
|
||||
$edit['ip'] = 'test.example.com';
|
||||
$this->drupalPost('admin/config/people/ban', $edit, t('Add'));
|
||||
$this->assertText(t('Enter a valid IP address.'));
|
||||
|
||||
// Submit an empty form.
|
||||
$edit = array();
|
||||
$edit['ip'] = '';
|
||||
$this->drupalPost('admin/config/people/ban', $edit, t('Add'));
|
||||
$this->assertText(t('Enter a valid IP address.'));
|
||||
|
||||
// Pass an IP address as a URL parameter and submit it.
|
||||
$submit_ip = '1.2.3.4';
|
||||
$this->drupalPost('admin/config/people/ban/' . $submit_ip, NULL, t('Add'));
|
||||
$ip = db_query("SELECT iid from {ban_ip} WHERE ip = :ip", array(':ip' => $submit_ip))->fetchField();
|
||||
$this->assertTrue($ip, 'IP address found in database');
|
||||
$this->assertRaw(t('The IP address %ip has been banned.', array('%ip' => $submit_ip)), 'IP address was banned.');
|
||||
|
||||
// Submit your own IP address. This fails, although it works when testing
|
||||
// manually.
|
||||
// TODO: on some systems this test fails due to a bug or inconsistency in cURL.
|
||||
// $edit = array();
|
||||
// $edit['ip'] = ip_address();
|
||||
// $this->drupalPost('admin/config/people/ban', $edit, t('Save'));
|
||||
// $this->assertText(t('You may not ban your own IP address.'));
|
||||
}
|
||||
}
|
|
@ -13,8 +13,8 @@ namespace Drupal\statistics\Tests;
|
|||
class StatisticsBlockVisitorsTest extends StatisticsTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Top visitor blocking',
|
||||
'description' => 'Tests blocking of IP addresses via the top visitors report.',
|
||||
'name' => 'Top visitor banning',
|
||||
'description' => 'Tests banning of IP addresses via the top visitors report.',
|
||||
'group' => 'Statistics'
|
||||
);
|
||||
}
|
||||
|
@ -27,32 +27,32 @@ class StatisticsBlockVisitorsTest extends StatisticsTestBase {
|
|||
$test_ip_address = '192.168.1.1';
|
||||
|
||||
// Verify the IP address from accesslog appears on the top visitors page
|
||||
// and that a 'block IP address' link is displayed.
|
||||
// and that a 'ban IP address' link is displayed.
|
||||
$this->drupalLogin($this->blocking_user);
|
||||
$this->drupalGet('admin/reports/visitors');
|
||||
$this->assertText($test_ip_address, t('IP address found.'));
|
||||
$this->assertText(t('block IP address'), t('Block IP link displayed'));
|
||||
$this->assertText($test_ip_address, 'IP address found.');
|
||||
$this->assertText(t('ban IP address'), 'Ban IP link displayed');
|
||||
|
||||
// Block the IP address.
|
||||
$this->clickLink('block IP address');
|
||||
$this->assertText(t('IP address blocking'), t('IP blocking page displayed.'));
|
||||
$this->clickLink('ban IP address');
|
||||
$this->assertText(t('IP address bans'), 'IP banning page displayed.');
|
||||
$edit = array();
|
||||
$edit['ip'] = $test_ip_address;
|
||||
$this->drupalPost('admin/config/people/ip-blocking', $edit, t('Add'));
|
||||
$ip = db_query("SELECT iid from {blocked_ips} WHERE ip = :ip", array(':ip' => $edit['ip']))->fetchField();
|
||||
$this->assertNotEqual($ip, FALSE, t('IP address found in database'));
|
||||
$this->assertRaw(t('The IP address %ip has been blocked.', array('%ip' => $edit['ip'])), t('IP address was blocked.'));
|
||||
$this->drupalPost('admin/config/people/ban', $edit, t('Add'));
|
||||
$ip = db_query("SELECT iid from {ban_ip} WHERE ip = :ip", array(':ip' => $edit['ip']))->fetchField();
|
||||
$this->assertNotEqual($ip, FALSE, 'IP address found in database');
|
||||
$this->assertRaw(t('The IP address %ip has been banned.', array('%ip' => $edit['ip'])), 'IP address was banned.');
|
||||
|
||||
// Verify that the block/unblock link on the top visitors page has been
|
||||
// altered.
|
||||
$this->drupalGet('admin/reports/visitors');
|
||||
$this->assertText(t('unblock IP address'), t('Unblock IP address link displayed'));
|
||||
$this->assertText(t('unban IP address'), 'Unban IP address link displayed');
|
||||
|
||||
// Unblock the IP address.
|
||||
$this->clickLink('unblock IP address');
|
||||
$this->assertRaw(t('Are you sure you want to delete %ip?', array('%ip' => $test_ip_address)), t('IP address deletion confirmation found.'));
|
||||
$this->clickLink('unban IP address');
|
||||
$this->assertRaw(t('Are you sure you want to delete %ip?', array('%ip' => $test_ip_address)), 'IP address deletion confirmation found.');
|
||||
$edit = array();
|
||||
$this->drupalPost('admin/config/people/ip-blocking/delete/1', NULL, t('Delete'));
|
||||
$this->assertRaw(t('The IP address %ip was deleted.', array('%ip' => $test_ip_address)), t('IP address deleted.'));
|
||||
$this->drupalPost('admin/config/people/ban/delete/1', NULL, t('Delete'));
|
||||
$this->assertRaw(t('The IP address %ip was deleted.', array('%ip' => $test_ip_address)), 'IP address deleted.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ abstract class StatisticsTestBase extends WebTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node', 'block', 'statistics');
|
||||
public static $modules = array('node', 'block', 'ban', 'statistics');
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
@ -34,7 +34,7 @@ abstract class StatisticsTestBase extends WebTestBase {
|
|||
'access administration pages',
|
||||
'access site reports',
|
||||
'access statistics',
|
||||
'block IP addresses',
|
||||
'ban IP addresses',
|
||||
'administer blocks',
|
||||
'administer statistics',
|
||||
'administer users',
|
||||
|
|
|
@ -121,17 +121,20 @@ function statistics_top_pages() {
|
|||
* A render array containing the top visitors information.
|
||||
*/
|
||||
function statistics_top_visitors() {
|
||||
$ban_exists = module_exists('ban');
|
||||
|
||||
$header = array(
|
||||
array('data' => t('Hits'), 'field' => 'hits', 'sort' => 'desc'),
|
||||
array('data' => t('Visitor'), 'field' => 'u.name'),
|
||||
array('data' => t('Total page generation time'), 'field' => 'total'),
|
||||
array('data' => user_access('block IP addresses') ? t('Operations') : '', 'colspan' => 2),
|
||||
array('data' => $ban_exists && user_access('ban IP addresses') ? t('Operations') : '', 'colspan' => 2),
|
||||
);
|
||||
$query = db_select('accesslog', 'a', array('target' => 'slave'))
|
||||
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
|
||||
->extend('Drupal\Core\Database\Query\TableSortExtender');
|
||||
$query->leftJoin('blocked_ips', 'bl', 'a.hostname = bl.ip');
|
||||
if ($ban_exists) {
|
||||
$query->leftJoin('ban_ip', 'b', 'a.hostname = b.ip');
|
||||
}
|
||||
$query->leftJoin('users', 'u', 'a.uid = u.uid');
|
||||
|
||||
$query->addExpression('COUNT(a.uid)', 'hits');
|
||||
|
@ -139,13 +142,16 @@ function statistics_top_visitors() {
|
|||
$query
|
||||
->fields('a', array('uid', 'hostname'))
|
||||
->fields('u', array('name'))
|
||||
->fields('bl', array('iid'))
|
||||
->groupBy('a.hostname')
|
||||
->groupBy('a.uid')
|
||||
->groupBy('u.name')
|
||||
->groupBy('bl.iid')
|
||||
->limit(30)
|
||||
->orderByHeader($header);
|
||||
->limit(30);
|
||||
if ($ban_exists) {
|
||||
$query
|
||||
->fields('b', array('iid'))
|
||||
->groupBy('b.iid');
|
||||
}
|
||||
$query->orderByHeader($header);
|
||||
|
||||
$uniques_query = db_select('accesslog')->distinct();
|
||||
$uniques_query->fields('accesslog', array('uid', 'hostname'));
|
||||
|
@ -157,8 +163,20 @@ function statistics_top_visitors() {
|
|||
$rows = array();
|
||||
$destination = drupal_get_destination();
|
||||
foreach ($result as $account) {
|
||||
$ban_link = $account->iid ? l(t('unblock IP address'), "admin/config/people/ip-blocking/delete/$account->iid", array('query' => $destination)) : l(t('block IP address'), "admin/config/people/ip-blocking/$account->hostname", array('query' => $destination));
|
||||
$rows[] = array($account->hits, ($account->uid ? theme('username', array('account' => $account)) : $account->hostname), format_interval(round($account->total / 1000)), (user_access('block IP addresses') && !$account->uid) ? $ban_link : '');
|
||||
if ($ban_exists) {
|
||||
if ($account->iid) {
|
||||
$ban_link = l(t('unban IP address'), "admin/config/people/ban/delete/$account->iid", array('query' => $destination));
|
||||
}
|
||||
else {
|
||||
$ban_link = l(t('ban IP address'), "admin/config/people/ban/$account->hostname", array('query' => $destination));
|
||||
}
|
||||
}
|
||||
$row = array();
|
||||
$row[] = $account->hits;
|
||||
$row[] = ($account->uid ? theme('username', array('account' => $account)) : $account->hostname);
|
||||
$row[] = format_interval(round($account->total / 1000));
|
||||
$row[] = ($ban_exists && user_access('ban IP addresses') && !$account->uid ? $ban_link : '');
|
||||
$rows[] = $row;
|
||||
}
|
||||
|
||||
drupal_set_title(t('Top visitors in the past %interval', array('%interval' => format_interval(config('statistics.settings')->get('access_log.max_lifetime')))), PASS_THROUGH);
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\system\Tests\System\IpAddressBlockingTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\system\Tests\System;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
class IpAddressBlockingTest extends WebTestBase {
|
||||
protected $blocking_user;
|
||||
|
||||
/**
|
||||
* Implement getInfo().
|
||||
*/
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'IP address blocking',
|
||||
'description' => 'Test IP address blocking.',
|
||||
'group' => 'System'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement setUp().
|
||||
*/
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create user.
|
||||
$this->blocking_user = $this->drupalCreateUser(array('block IP addresses'));
|
||||
$this->drupalLogin($this->blocking_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a variety of user input to confirm correct validation and saving of data.
|
||||
*/
|
||||
function testIPAddressValidation() {
|
||||
$this->drupalGet('admin/config/people/ip-blocking');
|
||||
|
||||
// Block a valid IP address.
|
||||
$edit = array();
|
||||
$edit['ip'] = '192.168.1.1';
|
||||
$this->drupalPost('admin/config/people/ip-blocking', $edit, t('Add'));
|
||||
$ip = db_query("SELECT iid from {blocked_ips} WHERE ip = :ip", array(':ip' => $edit['ip']))->fetchField();
|
||||
$this->assertTrue($ip, t('IP address found in database.'));
|
||||
$this->assertRaw(t('The IP address %ip has been blocked.', array('%ip' => $edit['ip'])), t('IP address was blocked.'));
|
||||
|
||||
// Try to block an IP address that's already blocked.
|
||||
$edit = array();
|
||||
$edit['ip'] = '192.168.1.1';
|
||||
$this->drupalPost('admin/config/people/ip-blocking', $edit, t('Add'));
|
||||
$this->assertText(t('This IP address is already blocked.'));
|
||||
|
||||
// Try to block a reserved IP address.
|
||||
$edit = array();
|
||||
$edit['ip'] = '255.255.255.255';
|
||||
$this->drupalPost('admin/config/people/ip-blocking', $edit, t('Add'));
|
||||
$this->assertText(t('Enter a valid IP address.'));
|
||||
|
||||
// Try to block a reserved IP address.
|
||||
$edit = array();
|
||||
$edit['ip'] = 'test.example.com';
|
||||
$this->drupalPost('admin/config/people/ip-blocking', $edit, t('Add'));
|
||||
$this->assertText(t('Enter a valid IP address.'));
|
||||
|
||||
// Submit an empty form.
|
||||
$edit = array();
|
||||
$edit['ip'] = '';
|
||||
$this->drupalPost('admin/config/people/ip-blocking', $edit, t('Add'));
|
||||
$this->assertText(t('Enter a valid IP address.'));
|
||||
|
||||
// Pass an IP address as a URL parameter and submit it.
|
||||
$submit_ip = '1.2.3.4';
|
||||
$this->drupalPost('admin/config/people/ip-blocking/' . $submit_ip, NULL, t('Add'));
|
||||
$ip = db_query("SELECT iid from {blocked_ips} WHERE ip = :ip", array(':ip' => $submit_ip))->fetchField();
|
||||
$this->assertTrue($ip, t('IP address found in database'));
|
||||
$this->assertRaw(t('The IP address %ip has been blocked.', array('%ip' => $submit_ip)), t('IP address was blocked.'));
|
||||
|
||||
// Submit your own IP address. This fails, although it works when testing manually.
|
||||
// TODO: on some systems this test fails due to a bug or inconsistency in cURL.
|
||||
// $edit = array();
|
||||
// $edit['ip'] = ip_address();
|
||||
// $this->drupalPost('admin/config/people/ip-blocking', $edit, t('Save'));
|
||||
// $this->assertText(t('You may not block your own IP address.'));
|
||||
}
|
||||
}
|
|
@ -1371,111 +1371,6 @@ function system_modules_uninstall_submit($form, &$form_state) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback. Display blocked IP addresses.
|
||||
*
|
||||
* @param $default_ip
|
||||
* Optional IP address to be passed on to drupal_get_form() for
|
||||
* use as the default value of the IP address form field.
|
||||
*/
|
||||
function system_ip_blocking($default_ip = '') {
|
||||
$rows = array();
|
||||
$header = array(t('Blocked IP addresses'), t('Operations'));
|
||||
$result = db_query('SELECT * FROM {blocked_ips}');
|
||||
foreach ($result as $ip) {
|
||||
$rows[] = array(
|
||||
$ip->ip,
|
||||
l(t('delete'), "admin/config/people/ip-blocking/delete/$ip->iid"),
|
||||
);
|
||||
}
|
||||
|
||||
$build['system_ip_blocking_form'] = drupal_get_form('system_ip_blocking_form', $default_ip);
|
||||
|
||||
$build['system_ip_blocking_table'] = array(
|
||||
'#theme' => 'table',
|
||||
'#header' => $header,
|
||||
'#rows' => $rows,
|
||||
'#empty' => t('No blocked IP addresses available.'),
|
||||
);
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the form for blocking IP addresses.
|
||||
*
|
||||
* @ingroup forms
|
||||
* @see system_ip_blocking_form_validate()
|
||||
* @see system_ip_blocking_form_submit()
|
||||
*/
|
||||
function system_ip_blocking_form($form, $form_state, $default_ip) {
|
||||
$form['ip'] = array(
|
||||
'#title' => t('IP address'),
|
||||
'#type' => 'textfield',
|
||||
'#size' => 48,
|
||||
'#maxlength' => 40,
|
||||
'#default_value' => $default_ip,
|
||||
'#description' => t('Enter a valid IP address.'),
|
||||
);
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
$form['actions']['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Add'),
|
||||
);
|
||||
$form['#submit'][] = 'system_ip_blocking_form_submit';
|
||||
$form['#validate'][] = 'system_ip_blocking_form_validate';
|
||||
return $form;
|
||||
}
|
||||
|
||||
function system_ip_blocking_form_validate($form, &$form_state) {
|
||||
$ip = trim($form_state['values']['ip']);
|
||||
if (db_query("SELECT * FROM {blocked_ips} WHERE ip = :ip", array(':ip' => $ip))->fetchField()) {
|
||||
form_set_error('ip', t('This IP address is already blocked.'));
|
||||
}
|
||||
elseif ($ip == ip_address()) {
|
||||
form_set_error('ip', t('You may not block your own IP address.'));
|
||||
}
|
||||
elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE) == FALSE) {
|
||||
form_set_error('ip', t('Enter a valid IP address.'));
|
||||
}
|
||||
}
|
||||
|
||||
function system_ip_blocking_form_submit($form, &$form_state) {
|
||||
$ip = trim($form_state['values']['ip']);
|
||||
db_insert('blocked_ips')
|
||||
->fields(array('ip' => $ip))
|
||||
->execute();
|
||||
drupal_set_message(t('The IP address %ip has been blocked.', array('%ip' => $ip)));
|
||||
$form_state['redirect'] = 'admin/config/people/ip-blocking';
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* IP deletion confirm page.
|
||||
*
|
||||
* @see system_ip_blocking_delete_submit()
|
||||
*/
|
||||
function system_ip_blocking_delete($form, &$form_state, $iid) {
|
||||
$form['blocked_ip'] = array(
|
||||
'#type' => 'value',
|
||||
'#value' => $iid,
|
||||
);
|
||||
return confirm_form($form, t('Are you sure you want to delete %ip?', array('%ip' => $iid['ip'])), 'admin/config/people/ip-blocking', t('This action cannot be undone.'), t('Delete'), t('Cancel'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Process system_ip_blocking_delete form submissions.
|
||||
*/
|
||||
function system_ip_blocking_delete_submit($form, &$form_state) {
|
||||
$blocked_ip = $form_state['values']['blocked_ip'];
|
||||
db_delete('blocked_ips')
|
||||
->condition('iid', $blocked_ip['iid'])
|
||||
->execute();
|
||||
watchdog('user', 'Deleted %ip', array('%ip' => $blocked_ip['ip']));
|
||||
drupal_set_message(t('The IP address %ip was deleted.', array('%ip' => $blocked_ip['ip'])));
|
||||
$form_state['redirect'] = 'admin/config/people/ip-blocking';
|
||||
}
|
||||
|
||||
/**
|
||||
* Form builder; The general site information form.
|
||||
*
|
||||
|
|
|
@ -628,29 +628,6 @@ function system_schema() {
|
|||
),
|
||||
);
|
||||
|
||||
$schema['blocked_ips'] = array(
|
||||
'description' => 'Stores blocked IP addresses.',
|
||||
'fields' => array(
|
||||
'iid' => array(
|
||||
'description' => 'Primary Key: unique ID for IP addresses.',
|
||||
'type' => 'serial',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'ip' => array(
|
||||
'description' => 'IP address',
|
||||
'type' => 'varchar',
|
||||
'length' => 40,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
),
|
||||
'indexes' => array(
|
||||
'blocked_ip' => array('ip'),
|
||||
),
|
||||
'primary key' => array('iid'),
|
||||
);
|
||||
|
||||
$schema['cache_tags'] = array(
|
||||
'description' => 'Cache table for tracking cache tags related to the cache bin.',
|
||||
'fields' => array(
|
||||
|
@ -1978,6 +1955,39 @@ function system_update_8019() {
|
|||
db_drop_table('registry_file');
|
||||
}
|
||||
|
||||
/**
|
||||
* Conditionally enable the new Ban module.
|
||||
*/
|
||||
function system_update_8020() {
|
||||
$blocked_ips_exists = db_query_range('SELECT 1 FROM {blocked_ips}', 0, 1)->fetchField();
|
||||
if ($blocked_ips_exists) {
|
||||
// Rename the permission name.
|
||||
db_update('role_permission')
|
||||
->fields(array(
|
||||
'permission' => 'ban IP addresses',
|
||||
'module' => 'ban',
|
||||
))
|
||||
->condition('permission', 'block IP addresses')
|
||||
->execute();
|
||||
// Rename {blocked_ips} table into {ban_ip}.
|
||||
db_rename_table('blocked_ips', 'ban_ip');
|
||||
// Rename the action.
|
||||
db_update('actions')
|
||||
->fields(array(
|
||||
'aid' => 'ban_ip_action',
|
||||
'callback' => 'ban_ip_action',
|
||||
))
|
||||
->condition('aid', 'system_block_ip_action')
|
||||
->execute();
|
||||
// Enable the new Ban module.
|
||||
update_module_enable(array('ban'));
|
||||
}
|
||||
else {
|
||||
// Drop old table.
|
||||
db_drop_table('blocked_ips');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "defgroup updates-7.x-to-8.x".
|
||||
* The next series of updates should start at 9000.
|
||||
|
|
|
@ -138,8 +138,6 @@ function system_help($path, $arg) {
|
|||
return $output;
|
||||
case 'admin/config/system/actions/configure':
|
||||
return t('An advanced action offers additional configuration options which may be filled out below. Changing the <em>Description</em> field is recommended in order to better identify the precise action taking place.');
|
||||
case 'admin/config/people/ip-blocking':
|
||||
return '<p>' . t('IP addresses listed here are blocked from your site. Blocked addresses are completely forbidden from accessing the site and instead see a brief message explaining the situation.') . '</p>';
|
||||
case 'admin/reports/status':
|
||||
return '<p>' . t("Here you can find a short overview of your site's parameters as well as any problems detected with your installation. It may be useful to copy and paste this information into support requests filed on drupal.org's support forums and project issue queues. Before filing a support request, ensure that your web server meets the <a href=\"@system-requirements\">system requirements.</a>", array('@system-requirements' => 'http://drupal.org/requirements')) . '</p>';
|
||||
}
|
||||
|
@ -243,9 +241,6 @@ function system_permission() {
|
|||
'access site reports' => array(
|
||||
'title' => t('View site reports'),
|
||||
),
|
||||
'block IP addresses' => array(
|
||||
'title' => t('Block IP addresses'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -759,23 +754,6 @@ function system_menu() {
|
|||
'file' => 'system.admin.inc',
|
||||
);
|
||||
|
||||
// IP address blocking.
|
||||
$items['admin/config/people/ip-blocking'] = array(
|
||||
'title' => 'IP address blocking',
|
||||
'description' => 'Manage blocked IP addresses.',
|
||||
'page callback' => 'system_ip_blocking',
|
||||
'access arguments' => array('block IP addresses'),
|
||||
'file' => 'system.admin.inc',
|
||||
'weight' => 10,
|
||||
);
|
||||
$items['admin/config/people/ip-blocking/delete/%blocked_ip'] = array(
|
||||
'title' => 'Delete IP address',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('system_ip_blocking_delete', 5),
|
||||
'access arguments' => array('block IP addresses'),
|
||||
'file' => 'system.admin.inc',
|
||||
);
|
||||
|
||||
// Media settings.
|
||||
$items['admin/config/media'] = array(
|
||||
'title' => 'Media',
|
||||
|
@ -2003,19 +1981,6 @@ function system_stream_wrappers() {
|
|||
return $wrappers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a blocked IP address from the database.
|
||||
*
|
||||
* @param $iid integer
|
||||
* The ID of the blocked IP address to retrieve.
|
||||
*
|
||||
* @return
|
||||
* The blocked IP address from the database as an array.
|
||||
*/
|
||||
function blocked_ip_load($iid) {
|
||||
return db_query("SELECT * FROM {blocked_ips} WHERE iid = :iid", array(':iid' => $iid))->fetchAssoc();
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu item access callback - only enabled themes can be accessed.
|
||||
*/
|
||||
|
@ -3540,12 +3505,6 @@ function system_action_info() {
|
|||
'configurable' => TRUE,
|
||||
'triggers' => array('any'),
|
||||
),
|
||||
'system_block_ip_action' => array(
|
||||
'type' => 'user',
|
||||
'label' => t('Ban IP address of current user'),
|
||||
'configurable' => FALSE,
|
||||
'triggers' => array('any'),
|
||||
),
|
||||
'system_goto_action' => array(
|
||||
'type' => 'system',
|
||||
'label' => t('Redirect to URL'),
|
||||
|
@ -3766,19 +3725,6 @@ function system_goto_action($entity, $context) {
|
|||
drupal_goto(token_replace($context['url'], $context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocks the current user's IP address.
|
||||
*
|
||||
* @ingroup actions
|
||||
*/
|
||||
function system_block_ip_action() {
|
||||
$ip = ip_address();
|
||||
db_insert('blocked_ips')
|
||||
->fields(array('ip' => $ip))
|
||||
->execute();
|
||||
watchdog('action', 'Banned IP address %ip', array('%ip' => $ip));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an array of time zones and their local time&date.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue