ip2country.module in IP-based Determination of a Visitor's Country 7
Same filename and directory in other branches
Determination of user's Country based on IP.
This module uses the IP Address that a user is connected from to deduce the Country where the user is located. This method is not foolproof, because a user may connect through an anonymizing proxy, or may be in an unusual case, such as getting service from a neighboring country, or using an IP block leased from a company in another country. Additionally, users accessing a server on a local network may be using an IP that is not assigned to any country (e.g. 192.168.x.x).
Country determination occurs upon user login. If a country can be determined from the IP address, the ISO 3166 2-character country code is stored in the Drupal $user object as $user->country_iso_code_2. If no country can be determined, this member is left unset.
The database used is maintained by ARIN, the American Registry for Internet Numbers (http://www.arin.net/about_us/index.html), which is one of the 5 official Regional Internet Registries (RIR) responsible for assigning IP addresses. The claim is the database is 98% accurate, with most of the problems coming from users in less-developed countries. Regardless, there's no more-authoritative source of this information.
@author Tim Rohaly. <http://drupal.org/user/202830>
File
ip2country.moduleView source
<?php
/**
* @file
* Determination of user's Country based on IP.
*
* This module uses the IP Address that a user is connected from to deduce
* the Country where the user is located. This method is not foolproof,
* because a user may connect through an anonymizing proxy, or may be in
* an unusual case, such as getting service from a neighboring country,
* or using an IP block leased from a company in another country.
* Additionally, users accessing a server on a local network may be using
* an IP that is not assigned to any country (e.g. 192.168.x.x).
*
* Country determination occurs upon user login. If a country can be
* determined from the IP address, the ISO 3166 2-character country code
* is stored in the Drupal $user object as $user->country_iso_code_2.
* If no country can be determined, this member is left unset.
*
* The database used is maintained by ARIN, the American Registry for
* Internet Numbers (http://www.arin.net/about_us/index.html), which is
* one of the 5 official Regional Internet Registries (RIR) responsible
* for assigning IP addresses. The claim is the database is 98% accurate,
* with most of the problems coming from users in less-developed countries.
* Regardless, there's no more-authoritative source of this information.
*
* @author Tim Rohaly. <http://drupal.org/user/202830>
*/
/**
* Implements hook_help().
*/
function ip2country_help($path = 'admin/help#ip2country', $arg = NULL) {
switch ($path) {
case 'admin/help#ip2country':
case 'admin/help/ip2country':
//module_load_include('inc', 'ip2country', 'ip2country.help');
return t('Determines the Country where the user is located based on the IP address used.');
case 'admin/config/people/ip2country':
return t('Configuration settings for the ip2country module.');
}
}
/**
* Implements hook_permission().
*/
function ip2country_permission() {
return array(
'administer ip2country' => array(
'title' => t('Administer IP lookup settings'),
'description' => t('Configure IP database and module test settings.'),
),
);
}
/**
* Implements hook_cron().
*
* Updates the IP to Country database automatically on a periodic
* basis. Default period is 1 week.
*/
function ip2country_cron() {
// Utility functions for fetching and loading IP/Country DB from RIR.
module_load_include('inc', 'ip2country');
// Automatic database updates are disabled when $update_interval == 0.
$update_interval = variable_get('ip2country_update_interval', 604800);
if ($update_interval && variable_get('ip2country_last_update', 0) <= REQUEST_TIME - $update_interval) {
$status = ip2country_update_database(variable_get('ip2country_rir', 'arin'));
// Log to watchdog if requested.
if (variable_get('ip2country_watchdog', TRUE)) {
if ($status != FALSE) {
// Success.
watchdog('ip2country', 'Database updated from @registry server. Table contains @rows rows.', array(
'@registry' => drupal_strtoupper(variable_get('ip2country_rir', 'arin')),
'@rows' => $status,
), WATCHDOG_NOTICE);
}
else {
// Failure.
watchdog('ip2country', 'Database update from @registry server FAILED.', array(
'@registry' => drupal_strtoupper(variable_get('ip2country_rir', 'arin')),
), WATCHDOG_WARNING);
}
}
}
}
/**
* Implements hook_menu().
*/
function ip2country_menu() {
$items = array();
$items['admin/config/people/ip2country'] = array(
'title' => 'User location',
'description' => 'Settings for determining user location from IP address.',
'access arguments' => array(
'administer ip2country',
),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'ip2country_admin_settings',
),
'type' => MENU_NORMAL_ITEM,
'file' => 'ip2country.admin.inc',
);
$items['admin/config/people/ip2country/update'] = array(
'title' => 'Update database',
'access arguments' => array(
'administer ip2country',
),
'page callback' => '_ip2country_update',
'type' => MENU_CALLBACK,
'file' => 'ip2country.admin.inc',
);
$items['admin/config/people/ip2country/lookup'] = array(
'title' => 'Lookup IP address in database',
'access arguments' => array(
'administer ip2country',
),
'page callback' => '_ip2country_lookup',
'type' => MENU_CALLBACK,
'file' => 'ip2country.admin.inc',
);
return $items;
}
/**
* Implements hook_date_formats().
*/
function ip2country_date_formats() {
// Implementation is kept separate because it only needs to be loaded
// when module is enabled.
module_load_include('inc', 'ip2country', 'ip2country.formats');
return ip2country_get_date_formats();
}
/**
* Implements hook_date_format_types().
*/
function ip2country_date_format_types() {
return array(
'ip2country_date' => t('Date only (ip2country)'),
'ip2country_time' => t('Time only (ip2country)'),
);
}
/**
* Implements hook_user_login().
*
* Detects IP and determines country upon user login.
*/
function ip2country_user_login(&$edit, &$account) {
// Successful login. First determine user's country based on IP.
$ip = ip_address();
$country_code = ip2country_get_country($ip);
// Now check to see if this user has "administer ip2country" permission
// and if debug mode set. If both are TRUE, use debug information
// instead of real information.
if (user_access('administer ip2country') && variable_get('ip2country_debug', FALSE)) {
$type = variable_get('ip2country_test_type', 0);
if ($type == 0) {
// Debug Country entered.
$country_code = variable_get('ip2country_test_country', 'US');
}
else {
// Debug IP entered.
$ip = variable_get('ip2country_test_ip_address', $ip);
$country_code = ip2country_get_country($ip);
}
drupal_set_message(t('Using DEBUG value for Country - @country', array(
'@country' => $country_code,
)));
}
// Finally, save country, if it has been determined.
if ($country_code) {
// Store the ISO country code in the $user object.
user_save($account, array(
'country_iso_code_2' => $country_code,
));
}
}
/**
* Implements hook_user_presave().
*
* Takes care of storing country data into {users}.data.
*/
function ip2country_user_presave(&$edit, $account, $category) {
if (isset($edit['country_iso_code_2'])) {
$edit['data']['country_iso_code_2'] = $edit['country_iso_code_2'];
}
}
/**
* Implements hook_user_load().
*
* Takes care of restoring country data from {users}.data.
*/
function ip2country_user_load($users) {
foreach ($users as $user) {
if (isset($user->data['country_iso_code_2'])) {
$users[$user->uid]->country_iso_code_2 = $user->data['country_iso_code_2'];
}
}
}
/**
* Gets the ISO 3166 2-character country code from the IP address.
*
* @param string|int $ip_address
* IP address either as a dotted quad string (e.g. "127.0.0.1") or
* as a 32-bit unsigned long integer.
*
* @return string|false
* ISO 3166-1 2-character country code for this IP address, or
* FALSE if the lookup failed to find a country.
*/
function ip2country_get_country($ip_address) {
$ipl = ip2long($ip_address);
if (is_int($ip_address)) {
$ipl = $ip_address;
}
// Locate IP within range.
$sql = "SELECT country FROM {ip2country}\n WHERE (:start >= ip_range_first AND :end <= ip_range_last) LIMIT 1";
$result = db_query($sql, array(
':start' => $ipl,
':end' => $ipl,
))
->fetchField();
return $result;
}
/**
* Gets the total count of IP ranges in database.
*/
function ip2country_get_count() {
$sql = "SELECT COUNT(*) FROM {ip2country}";
$count = db_query($sql)
->fetchField();
return (int) $count;
}
/**
* Implements hook_form_FORM_ID_alter().
*
* Alters Ubercart's uc_cart_checkout_form() to use ip2country's country
* determination as the default billing and delivery country. If the user's
* country hasn't been determined, the store country will be used instead.
*/
function ip2country_form_uc_cart_checkout_form_alter(&$form, &$form_state) {
global $user;
if (isset($user->data['country_iso_code_2'])) {
if (module_exists('uc_store')) {
$country_id = db_query('SELECT country_id from {uc_countries} WHERE country_iso_code_2 = :iso2', array(
':iso2' => $user->data['country_iso_code_2'],
))
->fetchField();
if (!$country_id) {
$country_id = uc_store_default_country();
}
$form['panes']['billing']['billing_country']['#default_value'] = $form['panes']['delivery']['delivery_country']['#default_value'] = $country_id;
}
}
}
/**
* Implements hook_form_FORM_ID_alter().
*
* Alters Ubercart's uc_cart_pane_quotes() form to use ip2country's country
* determination as the default billing and delivery country. If the user's
* country hasn't been determined, the store country will be used instead.
*/
function ip2country_form_uc_cart_pane_quotes_alter(&$form, &$form_state) {
global $user;
if (isset($user->data['country_iso_code_2'])) {
if (module_exists('uc_store')) {
$country_id = db_query('SELECT country_id from {uc_countries} WHERE country_iso_code_2 = :iso2', array(
':iso2' => $user->data['country_iso_code_2'],
))
->fetchField();
if (!$country_id) {
$country_id = uc_store_default_country();
}
$form['delivery_country']['#default_value'] = $country_id;
}
}
}
Functions
Name | Description |
---|---|
ip2country_cron | Implements hook_cron(). |
ip2country_date_formats | Implements hook_date_formats(). |
ip2country_date_format_types | Implements hook_date_format_types(). |
ip2country_form_uc_cart_checkout_form_alter | Implements hook_form_FORM_ID_alter(). |
ip2country_form_uc_cart_pane_quotes_alter | Implements hook_form_FORM_ID_alter(). |
ip2country_get_count | Gets the total count of IP ranges in database. |
ip2country_get_country | Gets the ISO 3166 2-character country code from the IP address. |
ip2country_help | Implements hook_help(). |
ip2country_menu | Implements hook_menu(). |
ip2country_permission | Implements hook_permission(). |
ip2country_user_load | Implements hook_user_load(). |
ip2country_user_login | Implements hook_user_login(). |
ip2country_user_presave | Implements hook_user_presave(). |