-
Notifications
You must be signed in to change notification settings - Fork 7.6k
GeoIP plugin for CI
Derek Jones edited this page Jul 5, 2012
·
7 revisions
Category:Plugin::Data Conversion
Plugin to Geo locate users based on IP
<?php (defined('BASEPATH') OR defined('SYSPATH')) or die('No direct access allowed.');
/*
* GeoIP Plugin for CodeIgniter/Blueflame - Version 1
* Writted By Paul Trippett (paul_at_techxpert_co_uk)
*
* To use this plugin you must create a table in your database with
* the following schema: -
*
* CREATE TABLE `geoip` (
* `id` int(10) unsigned NOT NULL auto_increment,
* `ip_start` varchar(15) NOT NULL,
* `ip_end` varchar(15) NOT NULL,
* `ipnum_start` float NOT NULL,
* `ipnum_end` float NOT NULL,
* `country_code` char(2) NOT NULL,
* PRIMARY KEY (`id`),
* KEY `geoip_lookup` USING BTREE (`ipnum_start`,`ipnum_end`)
* ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
*
*
* Place this file in your application/plugins/ directory and download the
* following files in to the {ci_root}/updates/geoip/ directory.
*
* ftp://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-latest
* ftp://ftp.apnic.net/pub/stats/apnic/delegated-apnic-latest
* ftp://ftp.arin.net/pub/stats/arin/delegated-arin-latest
* ftp://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-latest
* ftp://ftp.ripe.net/ripe/stats/delegated-ripencc-latest
* ftp://ftp.apnic.net/pub/stats/iana/delegated-iana-latest
*
* You should then be able to use the following code in your controller: -
*
* $this->load->plugin('geoip');
*
* geoip_update();
* geoip_lookup('xxx.xxx.xxx.xxx');
*
* geoip_update() needs only to be called _once_ after you update the files
* from the RIR FTP sites.
*
* Should you wish to place the files in a different directory or use a
* different table name you can put the following code in your
* /application/config/config.php file: -
*
* define('GEOIP_TABLENAME', 'geoip');
* define('GEOIP_FILESOURCE', 'updates/geoip/');
*
*/
if (!defined('GEOIP_TABLENAME')) define('GEOIP_TABLENAME', 'geoip');
if (!defined('GEOIP_FILESOURCE')) define('GEOIP_FILESOURCE', 'updates/geoip/');
/**
* geoip_lookup
*
* Looks up GeoIP data from database.
*
* @access public
* @param string $ip The either a dotted decimal or integer or the ip address to lookup
* @return string The two letter country code of the ip address.
*/
function geoip_lookup($ip) {
// If we are passed a string ip address convert it to a Long Integer
$data = (is_string($ip)) ? ip2long($ip) : $ip;
$CI =& get_instance();
// WisePass
$CI->db->cache_off();
$query = $CI->db->query('SELECT * FROM ' . GEOIP_TABLENAME . ' WHERE ' . $data . ' BETWEEN ipnum_start AND ipnum_end');
return (string) ($query->num_rows() > 0) ? $query->row()->country_code : '';
}
/**
* geoip_update
*
* Imports GeoIP data from RIR Data
*
* @access public
* @param null
* @return null
*/
function geoip_update() {
// Prevent script timing out
set_time_limit(0);
// Get instance to CodeIgniter
$CI =& get_instance();
// Load Required Helpers
$CI->load->helper('file');
$CI->benchmark->mark('geoip_update_start');
// Start a Transaction and clear out the old data.
$CI->db->trans_start();
$CI->db->simple_query(sprintf('DELETE FROM %s;', GEOIP_TABLENAME));
// Process each file
$source_files = get_filenames(GEOIP_FILESOURCE);
if (empty($source_files)) show_error(sprintf('No RIR Data was found in the directory %s', GEOIP_FILESOURCE));
foreach($source_files as $file) {
echo sprintf('Importing %s... ', $file);
geoip_update_file(GEOIP_FILESOURCE . $file);
echo 'Done.<br />';
}
// Commit the changes
$CI->db->trans_complete();
$CI->benchmark->mark('geoip_update_end');
echo sprintf('GeoIP update completed. Processed %d files in %d seconds', count($source_files), $CI->benchmark->elapsed_time('geoip_update_start', 'geoip_update_end'));
}
/**
* geoip_update_file
*
* Imports GeoIP data from a particular text file.
*
*/
function geoip_update_file($file) {
// Get instance to CodeIgniter
$CI =& get_instance();
$current_file = file($file);
$query_start = sprintf('INSERT INTO %s VALUES ', GEOIP_TABLENAME);
$query = '';
$count = 0;
for ( $line = 1; $line < count($current_file); $line++ ) {
$data = split('[\|]', rtrim($current_file[$line]));
if (count($data) == 7) {
list($registry, $cc, $type, $start, $value, $date, $status) = $data;
} elseif (count($data) == 8) {
list($registry, $cc, $type, $start, $value, $date, $status, $exception) = $data;
}
if ($type == 'ipv4') {
$ip_start = $start;
$ip_end = long2ip(ip2long($ip_start) + $value);
$ipnum_start = ip2long($ip_start);
$ipnum_end = ip2long($ip_end);
if (!$count == 0) $query .= ',';
$query .= sprintf("(0,'%s','%s',%d,%d,'%s')", $ip_start, $ip_end, $ipnum_start, $ipnum_end, $cc);
$count++;
if ($count == 50) {
$CI->db->simple_query($query_start . $query);
$count = 0;
$query = '';
}
}
}
// The number of records will probably not divide equally by 50
// so we execute any remainder here.
if ($count > 0) {
$CI->db->simple_query($query_start . $query);
}
}
?>