# ==================================================================== # Gossamer Threads Module Library - http://gossamer-threads.com/ # # GT::IPCountry # Author: Jason Rhinelander # CVS Info : 087,071,086,086,085 # $Id: IPCountry.pm,v 1.1 2006/01/31 00:45:04 jagerman Exp $ # # Copyright (c) 2006 Gossamer Threads Inc. All Rights Reserved. # ==================================================================== # # Description: # Attempts to look up an IP's country using a variety of common CPAN modules. # package GT::IPCountry; use strict; require Exporter; use vars qw/@EXPORT @ISA %MODULE/; @ISA = 'Exporter'; @EXPORT = 'ip_to_country'; sub lookup_possible () { _load_module() if not defined $MODULE{loaded}; return $MODULE{loaded}; } sub ip_to_country ($) { my $ip = shift; lookup_possible or return (undef, undef); my $country; if ($MODULE{geoip}) { # Geo::IP $country = $MODULE{geoip}->country_name_by_addr($ip); } elsif ($MODULE{ipc}) { # IP::Country & Geography::Countries $country = $MODULE{ipc}->inet_ntocc(Socket::inet_aton($ip)); my %special = ( # Special codes returned that G::C can't handle: AP => 'non-specific Asia-Pacific location', CS => 'Czechoslovakia (former)', EU => 'non-specific European Union location', FX => 'France, Metropolitan', PS => 'Palestinian Territory, Occupied', '**' => 'Intranet address' ); if ($special{$country}) { $country = $special{$country} } elsif ($MODULE{geoc}) { $country = Geography::Countries::country($country) || $country; } } elsif ($MODULE{geoipfree}) { # Geo::IPfree $country = ($MODULE{geoipfree}->LookUp($ip))[1]; } return wantarray ? ($country, 1) : $country; } # Attempts to load various CPAN modules capable of going the IP -> country # lookup. Sets $MODULE{loaded} to 1 if at least one of the modules was found, # sets to 0 if none were loadable. sub _load_module { if (!defined $MODULE{geoip}) { $MODULE{geoip} = eval { require Geo::IP; Geo::IP->new(Geo::IP::GEOIP_STANDARD()) } || 0; if (!$MODULE{geoip}) { $MODULE{geoipfree} = 0 && eval { require Geo::IPfree; Geo::IPfree->new } || 0; } if (!$MODULE{geoip}) { $MODULE{ipc} = eval { require IP::Country::Fast; IP::Country::Fast->new } || 0; } if ($MODULE{ipc}) { require Socket; $MODULE{geoc} = eval { require Geography::Countries } || 0; } if (!$MODULE{ipc} and !$MODULE{geoipfree}) { $MODULE{geoipfree} = 0 && eval { require Geo::IPfree; Geo::IPfree->new } || 0; } } $MODULE{loaded} = $MODULE{geoip} || $MODULE{geoipfree} || $MODULE{ipc} ? 1 : 0; } 1; __END__ =head1 NAME GT::IPCountry - Attempts to look up an IP's country using a variety of common CPAN modules. =head1 SYNOPSIS use GT::IPCountry; my $country = ip_to_country("209.139.239.160"); my ($country, $lookup_okay) = ip_to_country("209.139.239.160"); my $can_lookup = GT::IPCountry::lookup_possible(); =head1 DESCRIPTION This module takes an IP address and returns the country name the IP is reserved for. This module itself does no actual lookup, but is simply a wrapper around serveral CPAN modules. If none of the modules are available, it simply returns the value C. =head1 FUNCTIONS =head2 ip_to_country This method takes a country name and returns two elements: the country name, and a true/false value indicating whether one of the lookup modules was available. In scalar context just the country name is returned. A country name of C indicates that either the IP wasn't found, or no lookup module was available. C is exported by default. =head2 lookup_possible This method returns a true/false value indicating whether or not an IP -> Country lookup can be done. It corresponds directly to the second return value of C. =head1 MODULES GT::IPCountry attempts to use the following modules, in order, to perform a country lookup: =over 4 =item Geo::IP Uses Geo::IP for the lookup. =item IP::Country Uses IP::Country for the lookup. Note that because IP::Country only returns a country code, this module will attempt to use Geography::Countries to determine the country name. If Geography::Countries isn't installed, you'll just get a country code. =item Geo::IPfree Uses Geo::IPfree for the lookup. =back =head1 SEE ALSO L L L =head1 COPYRIGHT Copyright (c) 2006 Gossamer Threads Inc. All Rights Reserved. http://www.gossamer-threads.com/ =head1 VERSION Revision: $Id: IPCountry.pm,v 1.1 2006/01/31 00:45:04 jagerman Exp $ =cut