File Coverage

blib/lib/IP/Authority.pm
Criterion Covered Total %
statement 35 40 87.5
branch 11 16 68.7
condition 2 6 33.3
subroutine 7 8 87.5
pod 3 4 75.0
total 58 74 78.3


line stmt bran cond sub pod time code
1             package IP::Authority;
2 2     2   7459 use strict;
  2         3  
  2         63  
3 2     2   4375 use warnings;
  2         5  
  2         79  
4 2     2   1089 use Socket qw ( inet_aton );
  2         4846  
  2         262  
5              
6 2     2   13 use vars qw ( $VERSION );
  2         4  
  2         1926  
7             $VERSION = '1305.001'; # MAY 2013, version 0.01
8              
9             my $singleton = undef;
10             my $ip_db;
11             my $null = substr(pack('N',0),0,1);
12             my $nullnullnull = $null . $null . $null;
13             my %auth;
14             my $ip_match = qr/^(\d|[01]?\d\d|2[0-4]\d|25[0-5])\.(\d|[01]?\d\d|2[0-4]\d|25[0-5])\.(\d|[01]?\d\d|2[0-4]\d|25[0-5])\.(\d|[01]?\d\d|2[0-4]\d|25[0-5])$/o;
15              
16             my $bit0;
17             my $bit1;
18             my @mask;
19             my @dtoc;
20             {
21             $bit0 = substr(pack('N',2 ** 31),0,1);
22             $bit1 = substr(pack('N',2 ** 30),0,1);
23              
24             for (my $i = 0; $i <= 31; $i++){
25             $mask[$i] = pack('N',2 ** (31 - $i));
26             }
27              
28             for (my $i = 0; $i <= 255; $i++){
29             $dtoc[$i] = substr(pack('N',$i),3,1);
30             }
31             (my $module_dir = __FILE__) =~ s/\.pm$//;
32              
33             local $/; # set it so <> reads all the file at once
34              
35             open (AUTH, "< $module_dir/auth.gif")
36             or die ("couldn't read authority database: $!");
37             binmode AUTH;
38             my $auth_ultra = ; # read in the file
39             close AUTH;
40             my $auth_num = (length $auth_ultra) / 3;
41             for (my $i = 0; $i < $auth_num; $i++){
42             my $auth = substr($auth_ultra,3 * $i + 1,2);
43             $auth = undef if ($auth eq '--');
44             $auth{substr($auth_ultra,3 * $i,1)} = $auth;
45             }
46              
47             open (IP, "< $module_dir/ipauth.gif")
48             or die ("couldn't read IP database: $!");
49             binmode IP;
50             $ip_db = ;
51             close IP;
52             }
53              
54             sub new ()
55             {
56 2     2 0 16 my $caller = shift;
57 2 50       10 unless (defined $singleton){
58 2   33     14 my $class = ref($caller) || $caller;
59 2         8 $singleton = bless {}, $class;
60             }
61 2         7 return $singleton;
62             }
63              
64             sub inet_atoauth
65             {
66 29     29 1 7772 my $inet_a = $_[1];
67 29 50       237 if ($inet_a =~ $ip_match){
68 29         177 return inet_ntoauth($dtoc[$1].$dtoc[$2].$dtoc[$3].$dtoc[$4]);
69             } else {
70 0 0       0 if (defined (my $n = inet_aton($inet_a))){
71 0         0 return inet_ntoauth($n);
72             } else {
73 0         0 return undef;
74             }
75             }
76             }
77              
78             sub db_time
79             {
80 0     0 1 0 return unpack("N",substr($ip_db,0,4));
81             }
82              
83             sub inet_ntoauth
84             {
85 29   33 29 1 86 my $inet_n = $_[1] || $_[0];
86              
87 29         35 my $pos = 4;
88 29         48 my $byte_zero = substr($ip_db,$pos,1);
89             # loop through bits of IP address
90 29         82 for (my $i = 0; $i <= 31; $i++){
91              
92 411 100       2991 if (($inet_n & $mask[$i]) eq $mask[$i]){
93             # bit[$i] is set [binary one]
94             # - jump to next node
95             # (start of child[1] node)
96 198 100       457 if (($byte_zero & $bit1) eq $bit1){
97 61         307 $pos = $pos + 1 + unpack('N', $nullnullnull . ($byte_zero ^ $bit1));
98             } else {
99 137         355 $pos = $pos + 3 + unpack('N', $null . substr($ip_db,$pos,3));
100             }
101             } else {
102             # bit[$i] is unset [binary zero]
103             # jump to end of this node
104             # (start of child[0] node)
105 213 100       519 if (($byte_zero & $bit1) eq $bit1){
106 31         40 $pos = $pos + 1;
107             } else {
108 182         377 $pos = $pos + 3;
109             }
110             }
111            
112             # all terminal nodes of the tree start with zeroth bit
113             # set to zero. the first bit can then be used to indicate
114             # whether we're using the first or second byte to store the
115             # country code
116 411         1058 $byte_zero = substr($ip_db,$pos,1);
117 411 100       1837 if (($byte_zero & $bit0) eq $bit0){ # country code
118 29 50       50 if (($byte_zero & $bit1) eq $bit1){
119             # unpopular country code - stored in second byte
120 0         0 return $auth{substr($ip_db,$pos+1,1)};
121             } else {
122             # popular country code - stored in bits 2-7
123             # (we already know that bit 1 is not set, so
124             # just need to unset bit 1)
125 29         316 return $auth{$byte_zero ^ $bit0};
126             }
127             }
128             }
129             }
130              
131             1;
132             __END__