ip_login.module in IP Login 7.2
Same filename and directory in other branches
Allow user login by IP addresses, ranges or wildcards.
Originally by David W Thomas Major enhancements and 2.x branch by Jim Kirkpatrick Other big contributions from:
- JohnV: Code tidy/refactor & D7 version - http://drupal.org/node/1151458
- PeterX: Many bug fixes and tweaks
File
ip_login.moduleView source
<?php
/**
* @file
* Allow user login by IP addresses, ranges or wildcards.
*
* Originally by David W Thomas
* Major enhancements and 2.x branch by Jim Kirkpatrick
* Other big contributions from:
* - JohnV: Code tidy/refactor & D7 version - http://drupal.org/node/1151458
* - PeterX: Many bug fixes and tweaks
*/
/*
* @todo for security, IP addresses and ranges should really be checked for collisions between existing accounts users
* @todo Check usage of $GLOBALS['conf']['cache'] in ip_login_attempt_login())
*/
define('ATTEMPT_IP_LOGIN', 'user/login_by_ip');
// path for ip login
define('IP_LOGOUT', 'user/logout');
// path for user logout (different between D6/D7)
define('IP_CHECKED', 'ip_login_checked');
// TRUE when IP check has happened
define('IP_UID_MATCH', 'ip_login_uid');
// TRUE when a user account matches the request IP
define('LOGIN_AS_DIFFERENT_USER', 'ip_login_as_different_user');
// TRUE when user wants alternate account
define('CACHE_DISABLED', 0);
// D7 TODO: this is removed from bootstrap.inc, and now in?? --> avoid double definition
/**
* Implementation of hook_boot().
*
* see http://drupal.org/node/509028
*/
function ip_login_boot() {
// skip rest of this if user is logged in
global $user;
if ($user->uid != 0) {
return;
}
// skip rest of this if the admin has disabled IP login
if (!variable_get('ip_login_enabled', 1)) {
return;
}
// Avoid settings cookies if not on an IP Login-enabled page to improve
// external caching support - http://drupal.org/node/1263234 thanks Vacilando
if (ip_login_check_path() === FALSE) {
return;
}
// check the user IP
$matched_uid = ip_login_check(ip_address());
if ($matched_uid > 0) {
$can_login_as_another_user = isset($_COOKIE[LOGIN_AS_DIFFERENT_USER]) ? $_COOKIE[LOGIN_AS_DIFFERENT_USER] : NULL;
// for clarity about every scenario, use extensive logic
if (is_null($can_login_as_another_user)) {
// first time login for user, so log in automatically.
ip_login_login($matched_uid);
drupal_goto(ltrim(request_uri(), '/'));
}
elseif ($can_login_as_another_user == FALSE) {
// user logged out, but is not allowed to use another user, so log in again.
ip_login_login($matched_uid);
drupal_goto(ltrim(request_uri(), '/'));
}
elseif ($can_login_as_another_user == TRUE) {
// user logged out, and is allowed to login as another user,
// so do nothing, just stay on this page and wait for user action.
}
else {
// do automatic login.
ip_login_login($matched_uid);
drupal_goto(ltrim(request_uri(), '/'));
}
}
}
/**
* Implementation of hook_help().
*/
function ip_login_help($path, $arg) {
// @todo use t()
switch ($path) {
case 'admin/config/people/ip_login':
$help = '<p>';
$help .= t("This module allows this site to automatically authenticate and login users arriving with a chosen IP address - optionally at certain pages only.") . '</p> <p>';
$help .= t('It also allows users with the <code>administer ip login</code> and <code>can log in as another user</code> <a href="@permissions-link">permissions</a> to log out and log in as another user, with other users being forced to stay logged in.', array(
'@permissions-link' => '/admin/people/permissions#module-ip_login',
));
$help .= '</p>';
$help .= ip_login_help_ranges();
return $help;
}
}
/**
* Provides help about accepted values of IP ranges etc.
*/
function ip_login_help_ranges($intro = '') {
$help = '<p id="ip_login">' . $intro . ' ' . t('Accepted IP Login match values are:') . '</p>';
$help .= '<ul><li>';
$help .= t("Single IP matches like <code>123.123.123.123</code>");
$help .= '</li><li>';
$help .= t("Wildcards using an asterisk (<code>*</code>) in any quadrant except the first one, for example <code>123.123.123.*</code> or <code>100.*.*.*</code> etc.");
$help .= '</li><li>';
$help .= t("Ranges using a hyphen (<code>-</code>) in any quadrant except the first one, for example <code>123.123.123.100-200</code> etc.");
$help .= '</li><li>';
$help .= t("Any number of comma-separated IP addresses or ranges like <code>10.11.12.13, 123.123.123.100-200, 123.123.124-125.*</code> etc.");
$help .= '</li></ul>';
return $help;
}
/**
* Implementation of hook_menu().
*/
function ip_login_menu() {
$items[ATTEMPT_IP_LOGIN] = array(
'title' => 'Automatically log me in by IP',
'access callback' => 'ip_login_is_possible',
'page callback' => 'ip_login_attempt_login',
'type' => MENU_CALLBACK,
);
$items['admin/config/people/ip_login'] = array(
'title' => 'IP Login',
'description' => 'Configure IP Login settings',
'access callback' => 'user_access',
'access arguments' => array(
'administer ip login',
),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'ip_login_admin_settings',
),
'file' => 'ip_login.admin.inc',
'type' => MENU_NORMAL_ITEM,
);
$items['admin/people/ip_login'] = array(
'title' => 'Users with IP Login',
'description' => 'Lists the users who can auto-login by IP address',
'access callback' => 'user_access',
'access arguments' => array(
'administer ip login',
),
'page callback' => 'ip_login_user_list',
'file' => 'ip_login.admin.inc',
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
/**
* Callback function for hook_menu (menu access)
*
* @return boolean
* TRUE if login by IP can happen because a user match has happened
*/
function ip_login_is_possible() {
// Return TRUE if a matching uid is found.
return !empty($_SESSION[IP_UID_MATCH]);
}
/**
* Checks the request IP and logs user in there's a match by calling
* ip_login_check then ip_login_attempt_login
*
* Callback function for hook_menu
*/
function ip_login_attempt_login() {
$GLOBALS['conf']['cache'] = FALSE;
// don't cache - not sure if this is correct usage
$matched_uid = ip_login_check(ip_address());
if ($matched_uid > 0) {
ip_login_login($matched_uid);
}
drupal_goto(variable_get('ip_login_destination', 'user'));
}
/**
* Implementation of hook_permission().
*/
function ip_login_permission() {
// @todo add perms checks to correct places in module
return array(
'administer ip login' => array(
'title' => t('Administer IP Login module'),
'description' => t('Perform administration tasks for IP Login.'),
),
'can log in as another user' => array(
'title' => t('Can login as other user'),
'description' => t('Allow user to logout and login as another user.'),
),
);
}
/**
* Implementation of hook_form_alter().
*/
function ip_login_form_alter(&$form, &$form_state, $form_id) {
// @todo should call hook_theme ideally
switch ($form_id) {
case 'user_login':
$matched_uid = ip_login_check(ip_address());
if ($matched_uid > 0) {
$link_text = t(variable_get('ip_login_link_login_page', 'Log in automatically'));
if (drupal_strlen($link_text)) {
// hide if no link text
$link_help = t(variable_get('ip_login_link_login_page_help', "Your computer's IP address has been matched and validated."));
$markup = '<br/>';
$markup .= '<ul class="item-list">';
$markup .= '<li><strong>' . l($link_text, ATTEMPT_IP_LOGIN, array(
'query' => array(
'ip_login_override_pages' => 'yes',
),
)) . '</strong>';
if (drupal_strlen($link_help)) {
$markup .= '<br/><small>' . filter_xss_admin($link_help) . '</small>';
}
$markup .= '</li></ul>';
$form['ip_login'] = array(
'#markup' => $markup,
'#weight' => variable_get('ip_login_link_login_page_weight', -10),
);
}
}
break;
case 'user_login_block':
$matched_uid = ip_login_check(ip_address());
if ($matched_uid > 0) {
$link_text = t(variable_get('ip_login_link_login_block', 'Log in automatically'));
if (drupal_strlen($link_text)) {
// hide if no link text
$markup = '<ul class="item-list">';
$markup .= '<li><strong>' . l($link_text, ATTEMPT_IP_LOGIN, array(
'query' => array(
'ip_login_override_pages' => 'yes',
),
)) . '</strong>';
$markup .= '</li></ul>';
$form['ip_login'] = array(
'#markup' => $markup,
'#weight' => variable_get('ip_login_link_login_page_weight', -10),
);
}
}
break;
case 'user_profile_form':
// change user
case 'user_register_form':
//create user
global $user;
if (user_access('administer ip login', $user)) {
$account = $form['#user'];
// set the validation callback
$form['#validate'][] = '_ip_login_user_form_validate';
// wrap in a fieldset
$form['ip_login_matches'] = array(
'#type' => 'fieldset',
'#title' => t('IP Login Settings'),
'#description' => ip_login_help_ranges(t('This user can be automatically logged in by IP address.')),
'#weight' => '-1',
);
$form['ip_login_matches']['ip_login_match'] = array(
'#type' => 'textfield',
'#title' => t('IP address matches'),
'#description' => t('IP matches based in format listed above. Leave blank to disable automatic login by IP for this user.'),
'#default_value' => _ip_login_get_user_range($account->uid),
'#default_value' => _ip_login_get_user_range($account->uid),
'#maxlength' => 255,
);
}
break;
}
}
/**
* Implementation of hook_block_info
*
* Adds the simple 'Automatic login' link block
*/
function ip_login_block_info() {
$blocks = array();
$blocks['ip-login-link'] = array(
'info' => t('Log in by IP link'),
'cache' => DRUPAL_NO_CACHE,
);
return $blocks;
}
/**
* Implementation of hook_block_view
*
* Makes simple a 'Automatic login' link available for those not wanting to use the
* overridden 'User Login' block.
*/
function ip_login_block_view($delta = '') {
// only show for anonymous users who can log in
global $user;
if ($user->uid > 0 || !ip_login_is_possible()) {
return;
}
if ($delta != 'ip-login-link') {
return;
}
// build simple block
// @todo should be a hook_theme call
$link_text = t(variable_get('ip_login_link_login_block', 'Log in automatically'));
$markup = '<div class="ip-login-available"><span class="ip-login-link">';
$markup .= l($link_text, ATTEMPT_IP_LOGIN, array(
'query' => array(
'ip_login_override_pages' => 'yes',
),
));
$markup .= '</span></div>';
$block = array(
'subject' => t('Automatic login'),
'content' => $markup,
);
return $block;
}
/**
* Callback for hook_form_alter().
*/
function _ip_login_user_form_validate($form, &$form_state) {
//TODO: replace with regexp ideally
// validate: replace all non-numeric but legal IP range chars with '|'
$value = $form['ip_login_matches']['ip_login_match']['#value'];
$ip_login_addresses = strtr($value, ' ,.-*', '|||||');
foreach (explode('|', $ip_login_addresses) as $quad) {
if (!empty($quad) && !is_numeric($quad)) {
// bad entry, warn & bail
form_set_error('ip_login_matches', t('Only numbers, spaces, commas, dots, asterisks and hyphens allowed in IP ranges.'));
}
}
}
/**
* Implements hook_user_insert().
*/
function ip_login_user_insert(&$edit, $account, $category) {
_ip_login_set_user_range($account->uid, isset($edit['ip_login_match']) ? trim(check_plain($edit['ip_login_match'])) : NULL);
}
/**
* Implements hook_user_update().
*/
function ip_login_user_update(&$edit, $account, $category) {
// Only update if ip_login_match field returned to avoid issue with Remember Me
// (and others using hook_user update) wiping the field. By PeterX
// http://drupal.org/node/1482934
if (!isset($edit['ip_login_match'])) {
return;
}
// all ok, save the data.
_ip_login_set_user_range($account->uid, isset($edit['ip_login_match']) ? trim(check_plain($edit['ip_login_match'])) : NULL);
}
/**
* Implements hook_user_delete().
*/
function ip_login_user_delete($account) {
_ip_login_set_user_range($account->uid, NULL);
}
function ip_login_user_form_submit(&$edit, $account, $category) {
_ip_login_set_user_range($account->uid, isset($edit['ip_login_match']) ? trim(check_plain($edit['ip_login_match'])) : NULL);
}
/**
* Compares the current request's IP address to the ip_login_user table
* and then does a proper match for each match on exact, ranges and wildcards
*
* @param $ip
* An ip address string, usually from the current user's request
* @return $uid_matched
* The uid of the matching user account
*/
function ip_login_check($ip, $diagnostics = FALSE) {
// have we checked user IP already this session?
if (!empty($_SESSION[IP_CHECKED])) {
return $_SESSION[IP_UID_MATCH];
}
// break up IP for ip address
$addr = explode(".", check_plain($ip));
$matches = FALSE;
$uid_matched = 0;
// Find user ip matches on the first part of the user's IP ANYWHERE except the end.
// Not desperately efficient but works consistently with comma separated IP ranges and spaces,
// and these checks are only done once per session anyway.
$partial_matches = db_query("SELECT uid, ip_match\n FROM {ip_login_user}\n WHERE ip_match LIKE (:addr)\n ORDER by LENGTH(ip_match) ASC", array(
':addr' => '%' . $addr[0] . '.%',
));
foreach ($partial_matches as $row) {
// multiple values are separated with commas so try each in turn
$user_ip_ranges = explode(",", $row->ip_match);
foreach ($user_ip_ranges as $ip_range) {
// clear any whitespace, break into quads, then compare
$ip_range = explode('.', trim($ip_range));
foreach ($ip_range as $index => $quad) {
$matches = ip_login_match_quad($addr[$index], $quad);
if (!$matches) {
break;
}
// no match, escape this foreach and move on to next IP range
}
// if it matches, stop here and do login
if ($matches) {
$uid_matched = $row->uid;
break 2;
// escape the foreach (ranges) and while (db_result)
}
}
}
// if not diagnostic test, set processed session flag, store matching user (if there is one)
if (!$diagnostics) {
$_SESSION[IP_CHECKED] = TRUE;
$_SESSION[IP_UID_MATCH] = $uid_matched;
}
return $uid_matched;
}
/**
* Checks path of current page matches any set as options on the admin page to
* see if IP login should occur. Adapted from core Block module's block_list().
*
* @return $uid_matched
* The uid of the matching user account
*/
function ip_login_check_path() {
if (!isset($_GET['ip_login_override_pages'])) {
$pages = variable_get('ip_login_active_pages', '');
if ($pages) {
$page_match = FALSE;
// first char, if variable set, is 'check_mode' - remainder is paths to match or PHP
$check_mode = substr($pages, 0, 1);
$pages = substr($pages, 1);
if ($check_mode < 2) {
// Compare with the path with allowed pages.
// Since this happens in hook_boot, we cannot call drupal_get_path_alias
// so call our own path matcher code and avoid a DB/alias check
$path = isset($_GET['q']) ? $_GET['q'] : '';
$page_match = ip_login_match_path($path, $pages);
// When $check_mode has a value of 0, the IP check happens on
// all pages except those listed in $pages. When set to 1, IPs
// are checked only on those pages listed in $pages.
$page_match = !($check_mode xor $page_match);
}
else {
// evaluate PHP
$page_match = drupal_eval($pages);
}
// if we don't have a path/PHP match, don't log in
if (!$page_match) {
return FALSE;
}
}
}
// all is well, continue with login.
return TRUE;
}
/**
* Check if a path matches any pattern in a set of patterns. This is a clone of
* drupal_match_path() found in path.inc because the bootstrap hasn't occurred,
* so path.inc isn't available.
*
* See: http://api.drupal.org/api/drupal/includes--path.inc/function/drupal_match_path/6
*/
function ip_login_match_path($path, $patterns) {
static $regexps;
if (!isset($regexps[$patterns])) {
$regexps[$patterns] = '/^(' . preg_replace(array(
'/(\\r\\n?|\\n)/',
'/\\\\\\*/',
'/(^|\\|)\\\\<front\\\\>($|\\|)/',
), array(
'|',
'.*',
'\\1' . preg_quote(variable_get('site_frontpage', 'node'), '/') . '\\2',
), preg_quote($patterns, '/')) . ')$/';
}
return preg_match($regexps[$patterns], $path);
}
/**
* Performs a login for user with $uid and stores IP Login variables for later
*
* @param $uid
* The UID of the account to be logged in
*/
function ip_login_login($uid) {
if ($uid) {
// if a uid is passed in
// check this page's path is ok to login automatically from
if (ip_login_check_path() === FALSE) {
return;
}
// get user module and include some handy functions
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
// get account (reload from db) , bail if no loaded active user
$account = user_load($uid, TRUE);
if (!$account || $account->status != 1) {
return;
}
// login by assigning account to global $user object
global $user;
$user = $account;
if (!variable_get('ip_login_suppress_messages', 0)) {
// notify user - if messages not suppressed
$message = t('Welcome %name. You have been automatically logged into %sitename.', array(
'%name' => $user->name,
'%sitename' => variable_get('site_name', 'this website'),
));
drupal_set_message($message);
// add handy message for those who can log out and then back in as another user
if (_ip_login_can_login_as_another_user($user)) {
$message = t('You may also <a href="@other_user_link">log in as another user</a> if required.', array(
'@other_user_link' => url(IP_LOGOUT),
));
drupal_set_message($message);
}
}
// following borrowed from user_authenticate_finalize(), but with slightly different message
watchdog('user', 'Session opened for %name by IP Login.', array(
'%name' => $user->name,
));
// This is also used to invalidate one-time login links.
$user->login = time();
db_update('users')
->fields(array(
'login' => $user->login,
))
->condition('uid', $user->uid)
->execute();
// Regenerate the session ID to prevent against session fixation attacks.
// This is called before hook_user in case one of those functions fails
// or incorrectly does a redirect which would leave the old session in place.
$edit = NULL;
drupal_session_regenerate();
user_module_invoke('login', $edit, $user);
// following borrowed from ipAuthenticator's login and avoids caching issues
if (variable_get('cache', CACHE_DISABLED) != CACHE_DISABLED && !isset($_GET['ip_login_no_cache'])) {
// make a url to reload page, remove newlines from the URL to avoid header injection attacks.
// use admin settings for destination if set.
$url = variable_get('ip_login_destination', '');
if (drupal_strlen($url) == 0) {
$url = str_replace(array(
"\n",
"\r",
), '', $_GET["q"]);
}
if ($url == 'logout') {
$url = '<front>';
}
$url = url($url, array(
'query' => array(
'ip_login_no_cache=' . md5(time()),
),
'absolute' => TRUE,
));
// Before the redirect, allow modules to react to the end of the page request.
module_invoke_all('exit', $url);
// Even though session_write_close() is registered as a shutdown function, we
// need all session data written to the database before redirecting.
session_write_close();
header('Location: ' . $url, TRUE, 302);
exit;
}
}
}
/**
* Implementation of hook_user_logout
*
* Called from hook_user on logout, most of the code taken from user_logout()
* and _drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION).
* D7-changes: this is now an implementation of a hook, so:
* - Only do a logout, leave the automatic login to ip_login_boot;
* - prevent logging out if needed, just by calling drupal_goto()
* - N.B. check user_logout() in user.pages.inc; this is the calling function;
* - N.B. check devel_switch_user() in devel.module; here users are switched, too;
*/
function ip_login_user_logout() {
// prevent recursive call via user_module_invoke() / module_invoke_all() in user.pages.inc
if (!ip_login_is_possible()) {
return;
}
else {
$_SESSION[IP_CHECKED] = FALSE;
$_SESSION[IP_UID_MATCH] = 0;
}
global $user;
// store whether this user can log back in automatically
$can_login_as_another_user = _ip_login_can_login_as_another_user($user);
// sets indicator to behaviour in hook_boot().
$expire = 0;
// Cookie expires at the end of the session (when the browser closes).
setcookie(LOGIN_AS_DIFFERENT_USER, $can_login_as_another_user, $expire, '/');
if (!$can_login_as_another_user) {
// @todo: it is possible that some other hook_user_logout() has been called already
// does this generate an undetermined state?
$message = t(variable_get('ip_login_logged_back_in', 'This account does not have permission to log out once logged in automatically. You have been logged back in.'));
$message = token_replace($message, array(
'user' => $user,
), array(
'clear' => TRUE,
));
drupal_set_message($message, 'warning');
// show the login page
drupal_goto(variable_get('ip_login_destination', 'user'));
}
}
/**
* Compares a single IP quadrant to a matching quadrant.
*
* The matching quad can contain wildcards (*), ranges (10-12) or exact numbers
* @param $find_value
* A string containing the quadrant value being looked for
* @param $in_range
* String with a quadrant value, range or wildcard to compare to
* @return TRUE
* If $find_value matches an IP address $in_range
*
*/
function ip_login_match_quad($find_value, $in_range) {
// if we've got a wildcard just return TRUE
if ($in_range == '*') {
return TRUE;
}
// check if this quad contains the range character '-'
$range = explode('-', $in_range);
if (isset($range[1])) {
// we've got a range, test upper and lower bounds
if ($find_value >= $range[0] && $find_value <= $range[1]) {
return TRUE;
}
}
else {
// no range, just do normal match
return $range[0] == $find_value;
}
return FALSE;
}
/*
* Returns TRUE if a user has permission to log out and back in as another user
*/
function _ip_login_can_login_as_another_user($user) {
// super user can log in as another user
if ($user->uid == 1) {
return TRUE;
}
// people who can administer this module can
if (user_access('administer ip login', $user)) {
return TRUE;
}
// people running from their own machines can
//if (ip_address() == '127.0.0.1') return TRUE;
// If the user doesn't have a matching IP, then we let them log in normally
if (!ip_login_check(ip_address())) {
return TRUE;
}
// all others check correct permission, making sure only TRUE, FALSE is returned
return user_access('can log in as another user', $user) ? TRUE : FALSE;
}
/**
* Gets a user's IP range match string by uid
* @param $uid
* The user ID
* @return
* The IP range string for the user if one is found, otherwise NULL.
*
*/
function _ip_login_get_user_range($uid) {
if (isset($uid) && is_numeric($uid)) {
$result = db_query('SELECT * FROM {ip_login_user} WHERE uid = :uid', array(
':uid' => $uid,
));
foreach ($result as $record) {
return $record->ip_match;
}
}
return NULL;
}
/**
* Sets the IP range match string for a user.
*
* If $ip_range is NULL, any IP Login record for this user is removed. Otherwise a row is inserted or updated.
* @param $uid
* The user ID
* @param $ip_range
* IP range match string
* @return TRUE
* If an update occured sucessfully.
*/
function _ip_login_set_user_range($uid, $ip_range = NULL) {
if (isset($uid) && is_numeric($uid)) {
if (is_null($ip_range) || empty($ip_range)) {
// null ip range = delete row
db_delete('ip_login_user')
->condition('uid', $uid)
->execute();
}
else {
if (is_null(_ip_login_get_user_range($uid))) {
// no range presently = insert row
db_insert('ip_login_user')
->fields(array(
'uid' => $uid,
'ip_match' => $ip_range,
))
->execute();
}
else {
db_update('ip_login_user')
->fields(array(
'ip_match' => $ip_range,
))
->condition('uid', $uid)
->execute();
}
}
}
return FALSE;
}
Functions
Name![]() |
Description |
---|---|
ip_login_attempt_login | Checks the request IP and logs user in there's a match by calling ip_login_check then ip_login_attempt_login |
ip_login_block_info | Implementation of hook_block_info |
ip_login_block_view | Implementation of hook_block_view |
ip_login_boot | Implementation of hook_boot(). |
ip_login_check | Compares the current request's IP address to the ip_login_user table and then does a proper match for each match on exact, ranges and wildcards |
ip_login_check_path | Checks path of current page matches any set as options on the admin page to see if IP login should occur. Adapted from core Block module's block_list(). |
ip_login_form_alter | Implementation of hook_form_alter(). |
ip_login_help | Implementation of hook_help(). |
ip_login_help_ranges | Provides help about accepted values of IP ranges etc. |
ip_login_is_possible | Callback function for hook_menu (menu access) |
ip_login_login | Performs a login for user with $uid and stores IP Login variables for later |
ip_login_match_path | Check if a path matches any pattern in a set of patterns. This is a clone of drupal_match_path() found in path.inc because the bootstrap hasn't occurred, so path.inc isn't available. |
ip_login_match_quad | Compares a single IP quadrant to a matching quadrant. |
ip_login_menu | Implementation of hook_menu(). |
ip_login_permission | Implementation of hook_permission(). |
ip_login_user_delete | Implements hook_user_delete(). |
ip_login_user_form_submit | |
ip_login_user_insert | Implements hook_user_insert(). |
ip_login_user_logout | Implementation of hook_user_logout |
ip_login_user_update | Implements hook_user_update(). |
_ip_login_can_login_as_another_user | |
_ip_login_get_user_range | Gets a user's IP range match string by uid |
_ip_login_set_user_range | Sets the IP range match string for a user. |
_ip_login_user_form_validate | Callback for hook_form_alter(). |