From d798223e32db87a4dc4ade1c34f98710504e871f Mon Sep 17 00:00:00 2001 From: catch Date: Fri, 2 Nov 2012 16:54:42 +0000 Subject: [PATCH] Issue #1794754 by rootatwc, Lars Toomre: Convert ban_boot() to an event listener. --- core/modules/ban/ban.admin.inc | 12 ++-- core/modules/ban/ban.module | 59 +---------------- core/modules/ban/lib/Drupal/ban/BanBundle.php | 31 +++++++++ .../ban/lib/Drupal/ban/BanIpManager.php | 49 ++++++++++++++ .../ban/EventSubscriber/BanSubscriber.php | 65 +++++++++++++++++++ .../Tests/StatisticsBlockVisitorsTest.php | 2 +- sites/default/default.settings.php | 19 ------ 7 files changed, 155 insertions(+), 82 deletions(-) create mode 100644 core/modules/ban/lib/Drupal/ban/BanBundle.php create mode 100644 core/modules/ban/lib/Drupal/ban/BanIpManager.php create mode 100644 core/modules/ban/lib/Drupal/ban/EventSubscriber/BanSubscriber.php diff --git a/core/modules/ban/ban.admin.inc b/core/modules/ban/ban.admin.inc index bccd84eaee6..0ea23fc6b54 100644 --- a/core/modules/ban/ban.admin.inc +++ b/core/modules/ban/ban.admin.inc @@ -6,11 +6,14 @@ */ /** - * Page callback; Displays banned IP addresses. + * 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. + * (optional) IP address to be passed on to drupal_get_form() for use as the + * default value of the IP address form field. + * + * @return array + * A render array. */ function ban_admin_page($default_ip = '') { $rows = array(); @@ -53,7 +56,6 @@ function ban_admin_page($default_ip = '') { * * @see ban_ip_form_validate() * @see ban_ip_form_submit() - * * @ingroup forms */ function ban_ip_form($form, &$form_state, $default_ip) { @@ -119,7 +121,7 @@ function ban_ip_delete_form($form, &$form_state, array $ban_ip) { '#value' => $ban_ip, ); return confirm_form($form, - t('Are you sure you want to delete %ip?', array('%ip' => $ban_ip['ip'])), + t('Are you sure you want to unblock %ip?', array('%ip' => $ban_ip['ip'])), 'admin/config/people/ban', NULL, t('Delete') diff --git a/core/modules/ban/ban.module b/core/modules/ban/ban.module index d8868713e49..12405ba1c9a 100644 --- a/core/modules/ban/ban.module +++ b/core/modules/ban/ban.module @@ -2,7 +2,7 @@ /** * @file - * Enables banning of IP addresses. + * Allows to ban individual IP addresses. */ /** @@ -13,7 +13,7 @@ function ban_help($path, $arg) { case 'admin/help#ban': $output = ''; $output .= '

' . t('About') . '

'; - $output .= '

' . t('The Ban module allows administrators to ban visits to their site from given IP addresses.') . '

'; + $output .= '

' . t('The Ban module allows administrators to ban visits to their site from individual IP addresses.') . '

'; $output .= '

' . t('Uses') . '

'; $output .= '
'; $output .= '
' . t('Banning IP addresses') . '
'; @@ -59,61 +59,6 @@ function ban_menu() { 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('ban_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. * diff --git a/core/modules/ban/lib/Drupal/ban/BanBundle.php b/core/modules/ban/lib/Drupal/ban/BanBundle.php new file mode 100644 index 00000000000..563332c3675 --- /dev/null +++ b/core/modules/ban/lib/Drupal/ban/BanBundle.php @@ -0,0 +1,31 @@ +register('ban.ip_manager', 'Drupal\ban\BanIpManager') + ->addArgument(new Reference('database')); + $container->register('ban.subscriber', 'Drupal\ban\EventSubscriber\BanSubscriber') + ->addArgument(new Reference('ban.ip_manager')) + ->addTag('event_subscriber'); + } +} diff --git a/core/modules/ban/lib/Drupal/ban/BanIpManager.php b/core/modules/ban/lib/Drupal/ban/BanIpManager.php new file mode 100644 index 00000000000..8ee2e0d90fe --- /dev/null +++ b/core/modules/ban/lib/Drupal/ban/BanIpManager.php @@ -0,0 +1,49 @@ +connection = $connection; + } + + /** + * Returns whether an IP address is blocked. + * + * @param string $ip + * The IP address to check. + * + * @return bool + * TRUE if access is denied, FALSE if access is allowed. + */ + public function isDenied($ip) { + $denied = $this->connection + ->query('SELECT 1 FROM {ban_ip} WHERE ip = :ip', array(':ip' => $ip)) + ->fetchField(); + return (bool) $denied; + } +} diff --git a/core/modules/ban/lib/Drupal/ban/EventSubscriber/BanSubscriber.php b/core/modules/ban/lib/Drupal/ban/EventSubscriber/BanSubscriber.php new file mode 100644 index 00000000000..7dc141c3c26 --- /dev/null +++ b/core/modules/ban/lib/Drupal/ban/EventSubscriber/BanSubscriber.php @@ -0,0 +1,65 @@ +manager = $manager; + } + + /** + * Response with 403 if the visitor's IP adress is banned. + * + * @param Symfony\Component\HttpKernel\Event\GetResponseEvent $event + * The Event to process. + */ + public function onKernelRequestBannedIpCheck(GetResponseEvent $event) { + // @todo convert this to Request::getClientIP(). + $ip = ip_address(); + if ($this->manager->isDenied($ip)) { + $response = new Response('Sorry, ' . check_plain($ip) . ' has been banned.', 403); + $event->setResponse($response); + } + } + + /** + * Registers the methods in this class that should be listeners. + * + * @return array + * An array of event listener definitions. + */ + static function getSubscribedEvents() { + $events[KernelEvents::REQUEST][] = array('onKernelRequestBannedIpCheck', 40); + return $events; + } + +} diff --git a/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsBlockVisitorsTest.php b/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsBlockVisitorsTest.php index 4657d10b092..82990e3b7e7 100644 --- a/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsBlockVisitorsTest.php +++ b/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsBlockVisitorsTest.php @@ -50,7 +50,7 @@ class StatisticsBlockVisitorsTest extends StatisticsTestBase { // Unblock the IP address. $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.'); + $this->assertRaw(t('Are you sure you want to unblock %ip?', array('%ip' => $test_ip_address)), 'IP address deletion confirmation found.'); $edit = array(); $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.'); diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php index 9b1c7ceaa80..44993edf165 100755 --- a/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -475,25 +475,6 @@ ini_set('session.cookie_lifetime', 2000000); # '@count min' => '@count minutes', # ); -/** - * IP blocking (Ban module). - * - * To bypass database queries for denied IP addresses, use this setting. - * Ban module queries the {ban_ip} table by default on every page request - * for both authenticated and anonymous users. This allows the system to - * block IP addresses from within the administrative interface and before any - * modules are loaded. However on high traffic websites you may want to avoid - * this query, allowing you to bypass database access altogether for anonymous - * users under certain caching configurations. - * - * If using this setting, you will need to add back any IP addresses which - * you may have blocked via the administrative interface. Each element of this - * array represents a blocked IP address. - * - * Remove the leading hash signs to enable. - */ -# $conf['ban_ips'][] = 'a.b.c.d'; - /** * Fast 404 pages: *