You are here

session_limit.module in Session Limit 6.2

Limits multiple sessions per user.

File

session_limit.module
View source
<?php

/**
 * @file
 * Limits multiple sessions per user.
 */

/**
 * Do nothing if the session limit is exceeded.
 */
define('SESSION_LIMIT_DO_NOTHING', 0);

/**
 * Automatically drop sessions that would exceed the limit.
 */
define('SESSION_LIMIT_DROP', 1);

/**
 * Disallow sessions that would exceed the limit.
 */
define('SESSION_LIMIT_DISALLOW_NEW', 2);

/**
 * Default drupal_set_message type for logout message.
 */
define('SESSION_LIMIT_LOGGED_OUT_MESSAGE_SEVERITY', 'error');

/**
 * Default message displayed when a user is logged out.
 */
define('SESSION_LIMIT_LOGGED_OUT_MESSAGE', 'You have been automatically logged out. Someone else has logged in with your username and password and the maximum number of @number simultaneous sessions was exceeded. This may indicate that your account has been compromised or that account sharing is not allowed on this site. Please contact the site administrator if you suspect your account has been compromised.');

/**
 * Implementation of hook_help().
 */
function session_limit_help($path, $args) {
  switch ($path) {
    case 'admin/help#session_limit':
      $output = '<p>' . t("The two major notice messages to users are passed through Drupal's t() function. This maintains locale support, allowing you to override strings in any language, but such text is also available to be changed through other modules like !stringoverridesurl.", array(
        '!stringoverridesurl' => l('String Overrides', 'http://drupal.org/project/stringoverrides'),
      )) . '</p>';
      $output .= '<p>' . t("The two major strings are as follows:") . '</p>';
      $output .= '<p><blockquote>';
      $output .= 'The maximum number of simultaneous sessions (@number) for your account has been reached. You did not log off from a previous session or someone else is logged on to your account. This may indicate that your account has been compromised or that account sharing is limited on this site. Please contact the site administrator if you suspect your account has been compromised.';
      $output .= '</blockquote></p><p><blockquote>';
      $output .= 'You have been automatically logged out. Someone else has logged in with your username and password and the maximum number of @number simultaneous sessions was exceeded. This may indicate that your account has been compromised or that account sharing is not allowed on this site. Please contact the site administrator if you suspect your account has been compromised.';
      $output .= '</blockquote></p>';
      return $output;
    case 'session/limit':
      return t('The maximum number of simultaneous sessions (@number) for your account has been reached. You did not log off from a previous session or someone else is logged on to your account. This may indicate that your account has been compromised or that account sharing is limited on this site. Please contact the site administrator if you suspect your account has been compromised.', array(
        '@number' => session_limit_user_max_sessions(),
      ));
  }
}

/**
 * Implementation of hook_perm().
 */
function session_limit_perm() {
  return array(
    'administer session limits by role',
    'administer session limits per user',
  );
}

/**
 * Implementation of hook_menu().
 */
function session_limit_menu() {
  $items['session/limit'] = array(
    'title' => 'Session limit exceeded',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'session_limit_page',
    ),
    'access callback' => 'user_is_logged_in',
    'type' => MENU_CALLBACK,
  );
  $items['mysessions'] = array(
    'title' => 'My sessions',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'session_limit_page',
    ),
    'access callback' => 'user_is_logged_in',
    'type' => MENU_SUGGESTED_ITEM,
  );
  $items['admin/user/session_limit'] = array(
    'title' => 'Session limit',
    'description' => 'Configure session limits.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'session_limit_settings',
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'administer site configuration',
    ),
    'type' => MENU_NORMAL_ITEM,
  );
  $items['admin/user/session_limit/defaults'] = array(
    'title' => 'Defaults',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'session_limit_settings',
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'administer site configuration',
    ),
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );
  $items['admin/user/session_limit/roles'] = array(
    'title' => 'Role limits',
    'description' => 'Configure session limits by role.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'session_limit_settings_byrole',
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'administer session limits by role',
    ),
    'type' => MENU_LOCAL_TASK,
  );
  $items['user/%user/session_limit'] = array(
    'title' => 'Session limit',
    'description' => 'Configure session limit for one user.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'session_limit_user_settings',
      1,
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'administer session limits per user',
    ),
    'type' => MENU_LOCAL_TASK,
  );
  return $items;
}

/**
 * Session Limit settings form.
 */
function session_limit_settings() {
  $form['session_limit_max'] = array(
    '#type' => 'textfield',
    '#title' => t('Default maximum number of active sessions'),
    '#default_value' => variable_get('session_limit_max', 1),
    '#size' => 2,
    '#maxlength' => 3,
    '#description' => t('The maximum number of active sessions a user can have. 0 implies unlimited sessions.'),
  );
  $limit_behaviours = array(
    SESSION_LIMIT_DO_NOTHING => t('Do nothing.'),
    SESSION_LIMIT_DROP => t('Automatically drop the oldest sessions without prompting.'),
    SESSION_LIMIT_DISALLOW_NEW => t('Prevent new session.'),
  );
  $form['session_limit_behaviour'] = array(
    '#type' => 'radios',
    '#title' => t('When the session limit is exceeded'),
    '#default_value' => variable_get('session_limit_behaviour', SESSION_LIMIT_DO_NOTHING),
    '#options' => $limit_behaviours,
  );
  if (module_exists('masquerade')) {
    $form['session_limit_masquerade_ignore'] = array(
      '#type' => 'checkbox',
      '#title' => t('Ignore masqueraded sessions.'),
      '#description' => t("When a user administrator uses the masquerade module to impersonate a different user, it won't count against the session limit counter"),
      '#default_value' => variable_get('session_limit_masquerade_ignore', FALSE),
    );
  }
  $form['session_limit_logged_out_message_severity'] = array(
    '#type' => 'select',
    '#title' => t('Logged out message severity'),
    '#default_value' => variable_get('session_limit_logged_out_message_severity', SESSION_LIMIT_LOGGED_OUT_MESSAGE_SEVERITY),
    '#options' => array(
      'error' => t('Error'),
      'warning' => t('Warning'),
      'status' => t('Status'),
      '_none' => t('No Message'),
    ),
    '#description' => t('The Drupal message type.  Defaults to Error.'),
  );
  $form['session_limit_logged_out_message'] = array(
    '#type' => 'textarea',
    '#title' => t('Logged out message'),
    '#default_value' => variable_get('session_limit_logged_out_message', SESSION_LIMIT_LOGGED_OUT_MESSAGE),
    '#description' => t('The message that is displayed to a user if the workstation has been logged out.<br />
      @number is replaced with the maximum number of simultaneous sessions.'),
  );
  return system_settings_form($form);
}

/**
 * Session limit settings form validation.
 */
function session_limit_settings_validate($form, &$form_state) {
  $maxsessions = $form_state['values']['session_limit_max'];
  if (!is_numeric($maxsessions)) {
    form_set_error('session_limit_max', t('You must enter a number for the maximum number of active sessions'));
  }
  elseif ($maxsessions < 0) {
    form_set_error('session_limit_max', t('Maximum number of active sessions must be positive'));
  }
}

/**
 * Session limit role configuration form.
 */
function session_limit_settings_byrole() {
  $result = db_query("SELECT name, value FROM {variable} WHERE name LIKE 'session_limit_rid_%' ORDER BY name");
  while ($setting = db_fetch_object($result)) {
    $role_limits[$setting->name] = unserialize($setting->value);
  }
  $roles = user_roles(TRUE);
  foreach ($roles as $rid => $role) {
    $form["session_limit_rid_{$rid}"] = array(
      '#type' => 'select',
      '#options' => _session_limit_user_options(),
      '#title' => check_plain($role),
      '#default_value' => empty($role_limits["session_limit_rid_{$rid}"]) ? 0 : $role_limits["session_limit_rid_{$rid}"],
    );
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save permissions'),
  );
  return $form;
}

/**
 * Session limit role configuration form validation.
 */
function session_limit_settings_byrole_submit($form, &$form_state) {
  db_query("DELETE FROM {variable} WHERE name LIKE 'session_limit_rid_%'");
  foreach ($form_state['values'] as $setting_name => $setting_limit) {
    variable_set($setting_name, $setting_limit);
  }
  drupal_set_message(t('Role settings updated.'), 'status');
  watchdog('session_limit', 'Role limits updated.', array(), WATCHDOG_INFO);
}

/**
 * Implementation of hook_init().
 *
 * Determine whether session has been verified. Redirect user if over session
 * limit. Established Sessions do NOT need to verify every page load. The new
 * session must deal w/ determining which connection is cut.
 *
 * This intentionally doesn't use hook_user()'s login feature because that's
 * only really useful if the login event always boots off at least one other
 * active session. Doing it this way makes sure that the newest session can't
 * browse to a different page after their login has validated.
 */
function session_limit_init() {
  global $user;
  if ($user->uid > 1 && !isset($_SESSION['session_limit'])) {

    // Exclude from the redirect.
    if (_session_limit_bypass()) {

      // Bypass the session limitation on this page callback.
      return;
    }
    if (module_exists('masquerade') && variable_get('session_limit_masquerade_ignore', FALSE)) {
      $result = db_query('SELECT COUNT(DISTINCT(s.sid)) AS scount FROM {sessions} AS s
        LEFT JOIN {masquerade} AS m ON s.uid = m.uid_as AND s.sid = m.sid
        WHERE s.uid = %d AND m.sid IS NULL', $user->uid);
    }
    else {
      $result = db_query('SELECT COUNT(DISTINCT(sid)) AS scount FROM {sessions} WHERE uid = %d', $user->uid);
    }
    $max_sessions = session_limit_user_max_sessions();
    $active_sessions = db_result($result);
    if (!empty($max_sessions) && $active_sessions > $max_sessions) {
      session_limit_invoke_session_limit(session_id(), 'collision');
    }
    else {

      // Force checking this twice as there's a race condition around session creation.
      // see issue #1176412.
      if (!isset($_SESSION['session_limit_checkonce'])) {
        $_SESSION['session_limit_checkonce'] = TRUE;
      }
      else {

        // Mark session as verified to bypass this in future.
        $_SESSION['session_limit'] = TRUE;
      }
    }
  }
}

/**
 * Implementation of hook_action_info_alter().
 */
function session_limit_action_info_alter(&$info) {
  if (module_exists('token_actions')) {
    foreach ($info as $type => $data) {
      if (stripos($type, "token_actions_") === 0 || stripos($type, "system_") === 0) {
        if (isset($info[$type]['hooks']['session_limit'])) {
          array_merge($info[$type]['hooks']['session_limit'], array(
            'collision',
            'disconnect',
          ));
        }
        else {
          $info[$type]['hooks']['session_limit'] = array(
            'collision',
            'disconnect',
          );
        }
      }
    }
  }
}

/**
 * Implementation of hook_token_list().
 */
function session_limit_token_list($type = 'all') {
  $tokens = array();
  if ($type == 'session_limit' || $type == 'user' || $type == 'all') {
    $tokens['session_limit']['session-limit-default'] = 'Maximum number of active sessions configured specific to the user.';
    $tokens['session_limit']['session-limit-max'] = 'Maximum number of active sessions allowed, accounting for all configuration possibilities.';
    $tokens['session_limit']['session-limit-role'] = 'Maximum number of active sessions allowed by role.';
    $tokens['session_limit']['session-limit-user'] = 'Maximum number of active sessions configured specific to the user.';
  }
  return $tokens;
}

/**
 * Implementation of hook_token_values().
 */
function session_limit_token_values($type, $object = NULL, $options = array()) {
  if ($object == 'session_limit' || $object == 'system' || $type == 'global') {
    global $user;
    $tokens['session-limit-default'] = variable_get('session_limit_max', 1);
    $tokens['session-limit-max'] = session_limit_user_max_sessions($user);
    $tokens['session-limit-role'] = session_limit_user_max_sessions_byrole($user);
    $tokens['session-limit-user'] = empty($user->session_limit) ? 0 : check_plain($user->session_limit);
    return $tokens;
  }
}

/**
 * Implementation of hook_user().
 */
function session_limit_user($op, &$edit, &$account, $category = NULL) {
  switch ($op) {
    case 'view':
      if (user_access('administer session limits per user')) {
        $account->content['session_limit'] = array(
          '#title' => t('Session limit'),
          '#type' => 'user_profile_category',
          'session_limit' => array(
            '#value' => empty($account->session_limit) ? t('Default') : $account->session_limit,
          ),
        );
      }
      break;
  }
}

/**
 * User settings form.
 */
function session_limit_user_settings($args, $account) {
  $form['account'] = array(
    '#type' => 'value',
    '#value' => $account,
  );
  $form['session_limit'] = array(
    '#type' => 'select',
    '#title' => t('Maximum sessions'),
    '#description' => t('Total number simultaneous active sessions this user may have at one time. The default defers to the limits that apply to each of the user\'s roles.'),
    '#required' => FALSE,
    '#default_value' => empty($account->session_limit) ? 0 : $account->session_limit,
    '#options' => _session_limit_user_options(),
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save configuration'),
  );
  return $form;
}

/**
 * User settings form validation.
 */
function session_limit_user_settings_validate($form, &$form_state) {
  if (!is_numeric($form_state['values']['session_limit'])) {
    form_set_error('session_limit', t('Only numeric submissions are valid.'));
    watchdog('session_limit', 'Invalid session limit submission for @user.', array(
      '@user' => $form_state['values']['account']->name,
    ), WATCHDOG_DEBUG);
  }
}

/**
 * User settings form submission.
 */
function session_limit_user_settings_submit($form, &$form_state) {
  watchdog('session_limit', 'Maximum sessions for @user updated to @count.', array(
    '@user' => $form_state['values']['account']->name,
    '@count' => $form_state['values']['session_limit'],
  ), WATCHDOG_INFO, l(t('view'), "user/{$form_state['values']['account']->uid}"));
  if (empty($form_state['values']['session_limit'])) {
    $form_state['values']['session_limit'] = NULL;
  }
  user_save($form_state['values']['account'], array(
    'session_limit' => $form_state['values']['session_limit'],
  ));
  drupal_set_message(t('Session limit updated for %user.', array(
    '%user' => $form_state['values']['account']->name,
  )), 'status', TRUE);
}

/**
 * Display/Delete sessions.
 */
function session_limit_page() {
  global $user;
  if (variable_get('session_limit_behaviour', SESSION_LIMIT_DO_NOTHING) == SESSION_LIMIT_DISALLOW_NEW) {
    session_destroy();
    $user = drupal_anonymous_user();
    return;
  }
  $result = db_query('SELECT * FROM {sessions} WHERE uid = %d', $user->uid);
  while ($obj = db_fetch_object($result)) {
    $message = $user->sid == $obj->sid ? t('Your current session.') : '';
    $sids[$obj->sid] = t('<strong>Host:</strong> %host (idle: %time) <b>@message</b>', array(
      '%host' => $obj->hostname,
      '@message' => $message,
      '%time' => format_interval(time() - $obj->timestamp),
    ));
  }
  $form['sid'] = array(
    '#type' => 'radios',
    '#title' => t('Select a session to disconnect.'),
    '#options' => $sids,
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Disconnect session'),
  );
  return $form;
}

/**
 * Handler for submissions from session_limit_page().
 */
function session_limit_page_submit($form, &$form_state) {
  global $user;
  if ($user->sid == $form_state['values']['sid']) {
    drupal_goto('logout');
  }
  else {
    session_limit_invoke_session_limit($form_state['values']['sid'], 'disconnect');
    drupal_goto();
  }
}

/**
 * Helper function for formatting the settings option form.
 */
function _session_limit_user_options() {
  $options = drupal_map_assoc(range(0, 250));
  $options[0] = t('Default');
  $options['999999'] = t('Disabled');
  return $options;
}

/**
 * Implementation of hook_hook_info().
 */
function session_limit_hook_info() {
  return array(
    'session_limit' => array(
      'session_limit' => array(
        'collision' => array(
          'runs when' => t('User logs in and has too many active sessions'),
        ),
        'disconnect' => array(
          'runs when' => t('When an active user is logged out by a newer session'),
        ),
      ),
    ),
  );
}

/**
 * Get the maximum number of sessions for a user.
 *
 * @param user $account
 *   (optional) The user account to check. If not
 *   supplied the active user account is used.
 */
function session_limit_user_max_sessions($account = NULL) {
  static $limits = array();
  if (empty($account)) {
    $account = $GLOBALS['user'];
  }
  if (!isset($limits[$account->uid])) {
    $limits[$account->uid] = (int) variable_get('session_limit_max', 1);
    $limit_account = session_limit_user_max_sessions_byuser($account);
    $limit_role = session_limit_user_max_sessions_byrole($account);
    if ($limit_account > 0) {
      $limits[$account->uid] = $limit_account;
    }
    elseif ($limit_role > 0) {
      $limits[$account->uid] = $limit_role;
    }
    $limits[$account->uid] = (int) $limits[$account->uid];
  }
  return $limits[$account->uid];
}

/**
 * Get user specified session limit.
 *
 * @param user $account
 *   The user account to get the session limit for
 *
 * @return int
 *   Maximum number of sessions
 *   A value of 0 means that no user limit is set for the current user
 *   and so the role limit should be used (or default if no role limit either).
 */
function session_limit_user_max_sessions_byuser($account) {
  return (int) empty($account->session_limit) ? 0 : $account->session_limit;
}

/**
 * Get the maximum number of sessions allowed by the roles of an account.
 *
 * @param user $account
 *   The account to check the roles of.
 *
 * @return int
 *   The maximum number of sessions the user is allowed by their roles.
 *   A value of 0 means that no role limit exists for this user and so
 *   the default should be used.
 */
function session_limit_user_max_sessions_byrole($account) {
  $limits = array();
  foreach ($account->roles as $rid => $name) {
    $limits[] = variable_get("session_limit_rid_{$rid}", 0);
  }
  rsort($limits);
  return (int) $limits[0];
}

/**
 * Limit a users access to the sites based on the current session.
 *
 * @param string $session
 *   The session id string which identifies the current session.
 * @param string $op
 *   The action which caused the session limitation event. This is
 *   either 'collision' or 'disconnect'.
 *
 * @return array
 *   The results of all hook_session_limit functions.
 *   Note that in a collision event, a Drupal goto is executed so
 *   this function does not return.
 */
function session_limit_invoke_session_limit($session, $op) {
  $return = array();

  // Execute the hook_session_limit().
  foreach (module_implements('session_limit') as $name) {
    $function = $name . '_session_limit';
    $result = $function($session, $op);
    if (isset($result) && is_array($result)) {
      $return = array_merge($return, $result);
    }
    elseif (isset($result)) {
      $return[] = $result;
    }
  }

  // In the event of a collision, close oldest sessions.
  if ($op == 'collision') {
    if (variable_get('session_limit_behaviour', SESSION_LIMIT_DO_NOTHING) == SESSION_LIMIT_DROP) {
      global $user;

      // Get the number of sessions that should be removed.
      $count = db_result(db_query("SELECT COUNT(DISTINCT(sid)) FROM {sessions} WHERE uid = %d", $user->uid));
      $limit = $count - session_limit_user_max_sessions($user);
      if ($limit > 0) {
        $result = db_query_range("SELECT DISTINCT(sid) as sid FROM {sessions} WHERE uid = %d ORDER BY timestamp", $user->uid, 0, $limit);
        while ($sids = db_fetch_object($result)) {
          session_limit_invoke_session_limit($sids->sid, 'disconnect');
        }
      }
    }
    else {
      drupal_goto('session/limit');
    }
  }
  return $return;
}

/**
 * Implements hook_session_limit().
 */
function session_limit_session_limit($sid, $op) {
  switch ($op) {
    case 'collision':
      watchdog('session_limit', 'Exceeded maximum allowed active sessions.', array(), WATCHDOG_INFO);
      break;
    case 'disconnect':
      $message = variable_get('session_limit_logged_out_message', SESSION_LIMIT_LOGGED_OUT_MESSAGE);
      $message_severity = variable_get('session_limit_logged_out_message_severity', SESSION_LIMIT_LOGGED_OUT_MESSAGE_SEVERITY);
      if ($message_severity != '_none' && !empty($message)) {
        $logout_message = t($message, array(
          '@number' => session_limit_user_max_sessions(),
        ));
        $logout_message = 'messages|' . serialize(array(
          $message_severity => array(
            $logout_message,
          ),
        ));
      }
      db_query("UPDATE {sessions} SET uid = 0, session = '%s' WHERE sid = '%s'", $logout_message, $sid);
      watchdog('session_limit', 'Disconnected for excess active sessions.', array(), WATCHDOG_NOTICE);
      break;
  }
}

/**
 * Implements hook_session_limit().
 *
 * This implements the hook on behalf of the trigger module.
 */
function trigger_session_limit($sid, $op) {
  $aids = _trigger_get_hook_aids('session_limit', $op);
  $context = array(
    'hook' => 'session_limit',
    'op' => $op,
    'sid' => $sid,
  );
  actions_do(array_keys($aids), $user, $context);
}

/**
 * Implements hook_session_limit().
 *
 * This implements the hook on behalf of the rules module.
 */
function rules_session_limit($sid, $op) {
  global $user;
  rules_invoke_event('session_limit_' . $op, $user, $sid);
}

/**
 * Implements hook_session_limit_bypass().
 *
 * @return bool
 *   TRUE if the page request should bypass session limitation restrictions.
 */
function session_limit_session_limit_bypass() {
  if (arg(0) == 'session' && arg(1) == 'limit' || arg(0) == 'logout') {
    return TRUE;
  }
}

/**
 * Execute the session limit bypass hook.
 *
 * Allow other modules to prevent session limits in their own requirements.
 *
 * @return bool
 *   TRUE if session limitation should be bypassed.
 */
function _session_limit_bypass() {
  foreach (module_invoke_all('session_limit_bypass') as $bypass) {
    if (!empty($bypass)) {
      return TRUE;
    }
  }
  return FALSE;
}

Functions

Namesort descending Description
rules_session_limit Implements hook_session_limit().
session_limit_action_info_alter Implementation of hook_action_info_alter().
session_limit_help Implementation of hook_help().
session_limit_hook_info Implementation of hook_hook_info().
session_limit_init Implementation of hook_init().
session_limit_invoke_session_limit Limit a users access to the sites based on the current session.
session_limit_menu Implementation of hook_menu().
session_limit_page Display/Delete sessions.
session_limit_page_submit Handler for submissions from session_limit_page().
session_limit_perm Implementation of hook_perm().
session_limit_session_limit Implements hook_session_limit().
session_limit_session_limit_bypass Implements hook_session_limit_bypass().
session_limit_settings Session Limit settings form.
session_limit_settings_byrole Session limit role configuration form.
session_limit_settings_byrole_submit Session limit role configuration form validation.
session_limit_settings_validate Session limit settings form validation.
session_limit_token_list Implementation of hook_token_list().
session_limit_token_values Implementation of hook_token_values().
session_limit_user Implementation of hook_user().
session_limit_user_max_sessions Get the maximum number of sessions for a user.
session_limit_user_max_sessions_byrole Get the maximum number of sessions allowed by the roles of an account.
session_limit_user_max_sessions_byuser Get user specified session limit.
session_limit_user_settings User settings form.
session_limit_user_settings_submit User settings form submission.
session_limit_user_settings_validate User settings form validation.
trigger_session_limit Implements hook_session_limit().
_session_limit_bypass Execute the session limit bypass hook.
_session_limit_user_options Helper function for formatting the settings option form.

Constants

Namesort descending Description
SESSION_LIMIT_DISALLOW_NEW Disallow sessions that would exceed the limit.
SESSION_LIMIT_DO_NOTHING Do nothing if the session limit is exceeded.
SESSION_LIMIT_DROP Automatically drop sessions that would exceed the limit.
SESSION_LIMIT_LOGGED_OUT_MESSAGE Default message displayed when a user is logged out.
SESSION_LIMIT_LOGGED_OUT_MESSAGE_SEVERITY Default drupal_set_message type for logout message.