ban.module 4.38 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
<?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.
86
  $blocked_ips = variable_get('ban_ips');
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
  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();
151
  db_insert('ban_ip')
152 153 154 155
    ->fields(array('ip' => $ip))
    ->execute();
  watchdog('action', 'Banned IP address %ip', array('%ip' => $ip));
}