You are here

maintenance_exempt.module in Maintenance Exempt 7

Same filename and directory in other branches
  1. 8 maintenance_exempt.module

Allow exemption of maintenance mode based on either certain set IP addresses or matching a set query string value.

File

maintenance_exempt.module
View source
<?php

/**
 * @file
 * Allow exemption of maintenance mode based on either certain set IP
 * addresses or matching a set query string value.
 */

/**
 * Implements hook_menu_site_status_alter().
 */
function maintenance_exempt_menu_site_status_alter(&$menu_site_status, $path) {
  if ($menu_site_status == MENU_SITE_ONLINE) {

    // No need to check for exemption.
    return;
  }
  if (in_array($_SERVER['REQUEST_URI'], maintenance_exempt_get_urls())) {
    $menu_site_status = MENU_SITE_ONLINE;
    return;
  }
  if (maintenance_exempt_ip_match()) {
    $menu_site_status = MENU_SITE_ONLINE;
    return;
  }

  // Fetch the query string exemption key if there is one.
  $key = variable_get('maintenance_exempt_query_key', '');
  if ($key && isset($_GET[$key])) {

    // Grant exemption.
    $menu_site_status = MENU_SITE_ONLINE;
    $_SESSION['maintenance_exempt'] = $key;
    return;
  }

  // Exemption status may be stored in the session.
  if (isset($_SESSION['maintenance_exempt']) && $_SESSION['maintenance_exempt'] == $key) {
    $menu_site_status = MENU_SITE_ONLINE;
    return;
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function maintenance_exempt_form_system_site_maintenance_mode_alter(&$form, &$form_state) {
  $form['maintenance_exempt_by_url'] = array(
    '#type' => 'fieldset',
    '#title' => t('Set Exemption by URL'),
    '#weight' => 1,
    '#collapsible' => TRUE,
    '#collapsed' => variable_get('maintenance_exempt_urls', '') ? FALSE : TRUE,
  );
  $form['maintenance_exempt_by_url']['maintenance_exempt_urls'] = array(
    '#type' => 'textarea',
    '#title' => t('Exempt URLs'),
    '#default_value' => variable_get('maintenance_exempt_urls'),
    '#description' => t('Enter a newline-separated list of URLs addresses who should be exempt from maintenance mode. For example "/api/get_info/'),
  );
  $form['maintenance_exempt_by_ip'] = array(
    '#type' => 'fieldset',
    '#title' => t('Set Exemption by IP'),
    '#weight' => 2,
    '#collapsible' => TRUE,
    '#collapsed' => variable_get('maintenance_exempt_ips', '') ? FALSE : TRUE,
  );
  $form['maintenance_exempt_by_ip']['maintenance_exempt_ips'] = array(
    '#type' => 'textarea',
    '#title' => t('Exempt IPs'),
    '#default_value' => variable_get('maintenance_exempt_ips'),
    '#description' => t('Enter a newline-separated list of IP addresses who should be exempt from maintenance mode. !cidr_notation is allowed.', array(
      '!cidr_notation' => l(t('CIDR Notation'), 'http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing'),
    )),
    '#suffix' => t('Your current IP address is %current', array(
      '%current' => ip_address(),
    )),
  );
  $form['maintenance_exempt_by_query_string'] = array(
    '#type' => 'fieldset',
    '#title' => t('Set Exemption by query string'),
    '#weight' => 3,
    '#collapsible' => TRUE,
    '#collapsed' => variable_get('maintenance_exempt_query_key', '') ? FALSE : TRUE,
  );
  $form['maintenance_exempt_by_query_string']['maintenance_exempt_query_key'] = array(
    '#type' => 'textfield',
    '#title' => t('Exempt query string'),
    '#default_value' => variable_get('maintenance_exempt_query_key'),
    '#description' => t('Enter a string which can be used as a variable in the !query_string to exempt a visitor from maintenance mode. !current_url', array(
      '!query_string' => l(t('query string'), 'http://en.wikipedia.org/wiki/Query_string'),
      '!current_url' => variable_get('maintenance_exempt_query_key', '') ? "<br /><br />" . l('Hyperlink to exempt a visitor', '', array(
        'query' => array(
          variable_get('maintenance_exempt_query_key', '') => '',
        ),
      )) : '',
    )),
  );
  $form['#submit'][] = 'maintenance_exempt_form_system_site_maintenance_mode_submit';
}

/**
 * Helper function to process submit callback.
 */
function maintenance_exempt_form_system_site_maintenance_mode_submit(&$form) {
  if (variable_get('maintenance_mode', '')) {
    if (variable_get('maintenance_exempt_query_key', '')) {
      drupal_set_message(t('Maintenance mode exemptions by query string are in place!') . ' ' . l(t('Hyperlink to exempt a visitor'), '', array(
        'query' => array(
          variable_get('maintenance_exempt_query_key', '') => '',
        ),
      )));
    }
    if (variable_get('maintenance_exempt_ips', '')) {
      drupal_set_message(t('Maintenance mode exemptions by IP are in place!'));
    }
  }
}

/**
 * Check whether an IP address should be exempt from maintenance mode.
 *
 * @return bool
 *   TRUE if the address is in the IP list, either directly or in CIDR notation.
 */
function maintenance_exempt_ip_match() {
  $address = ip_address();
  if (in_array($address, maintenance_exempt_get_ips())) {
    return TRUE;
  }
  if (maintenance_exempt_by_cidr_notation($address)) {
    return TRUE;
  }
  return FALSE;
}

/**
 * Helper function to extract an array of IPs from the settings form.
 */
function maintenance_exempt_get_ips() {
  $allowed_ips = variable_get('maintenance_exempt_ips');
  return array_map('trim', explode("\n", $allowed_ips));
}

/**
 * Extract an array of URL paths from the settings.
 */
function maintenance_exempt_get_urls() {
  $allowed_urls = variable_get('maintenance_exempt_urls');
  return array_map('trim', explode("\n", $allowed_urls));
}

/**
 * Helper function to go through array looking in an attempt to match netmask.
 */
function maintenance_exempt_by_cidr_notation($ip) {
  $exploded_entries = maintenance_exempt_get_ips();
  foreach ($exploded_entries as $entry) {
    if (strstr($entry, "/")) {
      if (maintenance_exempt_ipCIDRCheck($ip, $entry)) {
        return TRUE;
      }
    }
  }
  return FALSE;
}

/**
 * Helper function to check against CIDR.
 *
 * Thanks claudiu - http://www.php.net/manual/en/ref.network.php#74656
 */
function maintenance_exempt_ipCIDRCheck($IP, $CIDR) {
  list($net, $mask) = explode("/", $CIDR);
  $ip_net = ip2long($net);
  $ip_mask = ~((1 << 32 - $mask) - 1);
  $ip_ip = ip2long($IP);
  $ip_ip_net = $ip_ip & $ip_mask;
  return $ip_ip_net == $ip_net;
}

Functions

Namesort descending Description
maintenance_exempt_by_cidr_notation Helper function to go through array looking in an attempt to match netmask.
maintenance_exempt_form_system_site_maintenance_mode_alter Implements hook_form_FORM_ID_alter().
maintenance_exempt_form_system_site_maintenance_mode_submit Helper function to process submit callback.
maintenance_exempt_get_ips Helper function to extract an array of IPs from the settings form.
maintenance_exempt_get_urls Extract an array of URL paths from the settings.
maintenance_exempt_ipCIDRCheck Helper function to check against CIDR.
maintenance_exempt_ip_match Check whether an IP address should be exempt from maintenance mode.
maintenance_exempt_menu_site_status_alter Implements hook_menu_site_status_alter().