ip2country.module in IP-based Determination of a Visitor's Country 6
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>
*/
/******************************************************************************
* Drupal Hooks *
******************************************************************************/
/**
* Implements hook_help().
*/
function ip2country_help($path, $arg) {
switch ($path) {
case 'admin/help#ip2country':
return t('Determines the Country where the user is located based on the IP address used.');
break;
case 'admin/settings/ip2country':
return t('Configuration settings for the ip2country module.');
break;
}
}
/**
* Implements hook_perm().
*/
function ip2country_perm() {
return array(
'administer ip2country',
);
}
/**
* 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) <= 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/settings/ip2country'] = array(
'title' => 'IP to Country settings',
'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/settings/ip2country/update'] = array(
'title' => 'Update database',
'access arguments' => array(
'administer ip2country',
),
'page callback' => '_ip2country_update',
'type' => MENU_CALLBACK,
'file' => 'ip2country.admin.inc',
);
$items['admin/settings/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_user().
*
* Detects IP and determines country upon user login.
*/
function ip2country_user($op, &$edit, &$account, $category = NULL) {
switch ($op) {
case 'login':
// 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,
));
}
break;
}
}
/******************************************************************************
* Module Functions *
******************************************************************************/
/**
* Gets the ISO 3166 2-character country Code from the IP address.
*
* @param $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
* FALSE if the lookup failed to find a country for this IP.
*/
function ip2country_get_country($ip_address) {
$ipl = ip2long($ip_address);
if (is_long($ip_address)) {
$ipl = $ip_address;
}
// Locate IP within range.
$sql = "SELECT country FROM {ip2country}\n WHERE (%d >= ip_range_first AND %d <= ip_range_last) LIMIT 1";
$country_code = db_result(db_query($sql, $ipl, $ipl));
return $country_code;
}
/**
* Gets the total count of IP ranges in database.
*/
function ip2country_get_count() {
$sql = "SELECT COUNT(*) FROM {ip2country}";
$count = db_result(db_query($sql));
return (int) $count;
}
/******************************************************************************
* Ubercart Integration *
******************************************************************************/
/**
* 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->country_iso_code_2)) {
if (module_exists('uc_store')) {
$country_id = db_result(db_query("SELECT country_id from {uc_countries} WHERE country_iso_code_2 = '%s'", $user->country_iso_code_2));
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->country_iso_code_2)) {
if (module_exists('uc_store')) {
$country_id = db_result(db_query("SELECT country_id from {uc_countries} WHERE country_iso_code_2 = '%s'", $user->country_iso_code_2));
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_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_perm | Implements hook_perm(). |
ip2country_user | Implements hook_user(). |