File Coverage

blib/lib/WWW/HostipInfo.pm
Criterion Covered Total %
statement 71 79 89.8
branch 35 44 79.5
condition 12 19 63.1
subroutine 24 29 82.7
pod 6 6 100.0
total 148 177 83.6


line stmt bran cond sub pod time code
1             ##############################################################################
2             package WWW::HostipInfo;
3              
4 2     2   57815 use strict;
  2         6  
  2         74  
5 2     2   10476 use LWP::UserAgent;
  2         158738  
  2         69  
6 2     2   22 use Carp;
  2         11  
  2         210  
7 2     2   13 use vars qw( $VERSION $DEBUG );
  2         4  
  2         3437  
8              
9             $VERSION = '0.14';
10              
11             my $GetAPI = 'http://api.hostip.info/get_html.php?position=true&ip=';
12             my $RoughAPI = 'http://api.hostip.info/get_html.php?position=true&ip=';
13              
14              
15             ## PUBLIC METHOD
16              
17             sub new {
18 3     3 1 37 my ( $class, $ip ) = @_;
19 3 50       19 my $opts = ! defined $ip ? {}
    100          
20             : ref( $ip ) eq 'HASH' ? $ip
21             : { ip => $ip }
22             ;
23              
24 3         16 my $self = {
25             url => $GetAPI,
26             %$opts,
27             };
28              
29 3         9 bless $self, $class;
30              
31 3 50       18 $self->_init() unless ( $self->ua );
32 3         20 $self;
33             }
34              
35              
36             sub _init {
37 3     3   8 my $self = shift;
38 3         41 $self->ua( LWP::UserAgent->new(agent => "WWW::HostipInfo/$VERSION") );
39             }
40              
41              
42             sub ua {
43 7 100   7 1 10459 $_[0]->{ua} = $_[1] if(@_ > 1);
44 7         64 $_[0]->{ua}
45             }
46              
47              
48             sub ip {
49 11 100   11 1 35 $_[0]->{ip} = $_[1] if(@_ > 1);
50 11         203 $_[0]->{ip}
51             }
52              
53             sub url {
54 1 50   1 1 12 $_[0]->{url} = $_[1] if(@_ > 1);
55 1         9 $_[0]->{url}
56             }
57              
58              
59 2     2 1 9 sub recent_info { $_[0]->{_recent_info}; }
60              
61              
62             sub get_info {
63 8     8 1 6419 my $self = shift;
64 8   66     34 my $ip = shift || $self->ip;
65 8   50     43 my $opt = shift || {};
66              
67 8         33 my $chk = $self->_check_ipaddr($ip);
68             # $chk : 0..invalid ip address, 1..class A - C, 2..class D or E, 3..private
69 8 100       37 if(!$chk){
    100          
    100          
70 1         259 croak "IP address is required."
71             }
72             elsif($chk == 2){
73 1         5 return $self->_get_info_as_null;
74             }
75             elsif($chk == 3){
76 5         12 return $self->_get_info_as_private
77             }
78              
79 1         5 $self->ip($ip);
80              
81 1         5 my $url = $self->url;
82 1         5 my $response = $self->ua->get($url . $ip);
83              
84 1 50       392679 return unless($response->is_success);
85              
86 1         21 my $content = $response->content;
87              
88 1 50       17 if($DEBUG){ warn $content; }
  0         0  
89              
90 1         7 return $self->_set_info_to_obj($content);
91             }
92              
93              
94             ## PRIVATE METHOD
95              
96             sub _check_ipaddr {
97 8 100 33 8   62 return 0 if(!defined $_[1] or $_[1] !~ /^(\d{1,3})\.(\d{1,3})\.\d{1,3}\.\d{1,3}$/);
98 7 100       31 return 2 if($1 >= 224); # class D or E
99 6 100 100     89 return ($1 == 127 or $1 == 10) ? 3
    100 66        
    100 66        
100             : ($1 == 192 and $2 == 168) ? 3
101             : ($1 == 172 and $2 >= 16 and $2 <= 31) ? 3 : 1;
102             }
103              
104              
105             sub _set_info_to_obj {
106 1     1   2 my ( $self, $content ) = @_;
107 1         3 my ( $country_code, $city, $lat, $lon, $region, $name, $code );
108              
109 1         6 for my $line ( split/\n/, $content ) {
110 6 100       44 if ( $line =~ /^Country: (.+?) \(([A-Z][A-Z])\)$/ ) {
    100          
    50          
    50          
111 1         4 ( $name, $code ) = ( $1, $2 );
112             }
113             elsif ( $line =~ /^City: ([^,]+)(?:, (\w+))?$/ ) {
114 1         5 ($city, $region) = ( $1, $2 );
115             }
116             elsif ( $line =~ /^Latitude: (.+)$/ ) {
117 0         0 $lat = $1;
118             }
119             elsif ( $line =~ /^Longitude: (.+)$/ ) {
120 0         0 $lon = $1;
121             }
122             }
123              
124 1         14 my ($unknown_city, $unknown_country) = (0,0);
125 1 50       8 if($city =~ /^\([uU]nknown [cC]ity/){
126 1         2 $city = ''; $region = ''; $unknown_city = 1;
  1         2  
  1         3  
127             }
128 1 50       5 if($name =~ /^\([uU]nknown [cC]ountry/){
129 1         1 $name = ''; $unknown_country = 1;
  1         2  
130             }
131              
132 1   50     7 $self->{_recent_info} = bless {
133             _ipaddr => $self->ip,
134             _CountryName => $name,
135             _CountryCode => $code,
136             _City => $city,
137             _Region => ($region || ''),
138             _Latitude => $lat,
139             _Longitude => $lon,
140             _private => 0,
141             _un_city => $unknown_city,
142             _un_country => $unknown_country,
143             }, 'WWW::HostipInfo::Info';
144             }
145              
146              
147             sub _get_info_as_null {
148 1     1   4 $_[0]->{_recent_info} = bless {
149             _ipaddr => $_[0]->ip,
150             _CountryName => '',
151             _CountryCode => 'XX',
152             _City => '',
153             _Region => undef,
154             _Latitude => undef,
155             _Longitude => undef,
156             _private => 0,
157             _un_city => 1,
158             _un_country => 1,
159             }, 'WWW::HostipInfo::Info';
160             }
161              
162              
163             sub _get_info_as_private {
164 5     5   14 $_[0]->{_recent_info} = bless {
165             _ipaddr => $_[0]->ip,
166             _CountryName => '',
167             _CountryCode => 'XX',
168             _City => '',
169             _Region => undef,
170             _Latitude => undef,
171             _Longitude => undef,
172             _private => 1,
173             _un_city => 1,
174             _un_country => 1,
175             }, 'WWW::HostipInfo::Info';
176             }
177              
178              
179             ##############################################################################
180             # Information Class
181             ##############################################################################
182              
183             package WWW::HostipInfo::Info;
184              
185 7     7   66 sub is_private { $_[0]->{_private}; }
186              
187 1     1   8 sub is_guessed { $_[0]->{_guessed}; }
188              
189 1     1   5 sub has_unknown_city { $_[0]->{_un_city}; }
190              
191 2     2   15 sub has_unknown_country { $_[0]->{_un_country}; }
192              
193 4     4   2278 sub ip { $_[0]->{_ipaddr}; }
194              
195 0     0   0 sub name { $_[0]->{_CountryName}; }
196              
197 2     2   15 sub code { $_[0]->{_CountryCode}; }
198              
199 1     1   11 sub country_name { $_[0]->{_CountryName}; }
200              
201 4     4   767 sub country_code { $_[0]->{_CountryCode}; }
202              
203 1     1   7 sub country { $_[0]->{_CountryName}; }
204              
205 0     0     sub city { $_[0]->{_City}; }
206              
207 0     0     sub region { $_[0]->{_Region}; }
208              
209 0     0     sub latitude { $_[0]->{_Latitude}; }
210              
211 0     0     sub longitude { $_[0]->{_Longitude} }
212              
213             ##############################################################################
214             1;
215             __END__