File Coverage

blib/lib/IP/Country/DB_File.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package IP::Country::DB_File;
2             $IP::Country::DB_File::VERSION = '3.03';
3 1     1   22835 use strict;
  1         2  
  1         45  
4 1     1   5 use warnings;
  1         2  
  1         30  
5              
6             # ABSTRACT: IPv4 and IPv6 to country translation using DB_File
7              
8 1     1   503 use DB_File ();
  0            
  0            
9             use Fcntl ();
10             use Socket 1.94 ();
11              
12             sub new {
13             my ($class, $db_file) = @_;
14             $db_file = 'ipcc.db' unless defined($db_file);
15              
16             my $this = {};
17             my %db;
18              
19             $this->{db} = tie(%db, 'DB_File', $db_file, Fcntl::O_RDONLY, 0666,
20             $DB_File::DB_BTREE)
21             or die("Can't open database $db_file: $!");
22              
23             return bless($this, $class);
24             }
25              
26             sub inet_ntocc {
27             my ($this, $addr) = @_;
28              
29             my ($key, $data);
30             $this->{db}->seq($key = "4$addr", $data, DB_File::R_CURSOR()) == 0
31             or return undef;
32             # Verify that key starts with '4' and isn't from IPv6 range.
33             return undef if ord($key) != 52;
34              
35             my $start = substr($data, 0, 4);
36             my $cc = substr($data, 4, 2);
37              
38             return $addr ge $start ? $cc : undef;
39             }
40              
41             sub inet_atocc {
42             my ($this, $ip) = @_;
43              
44             my $addr = Socket::inet_aton($ip);
45             return undef unless defined($addr);
46              
47             my ($key, $data);
48             $this->{db}->seq($key = "4$addr", $data, DB_File::R_CURSOR()) == 0
49             or return undef;
50             # Verify that key starts with '4' and isn't from IPv6 range.
51             return undef if ord($key) != 52;
52              
53             my $start = substr($data, 0, 4);
54             my $cc = substr($data, 4, 2);
55              
56             return $addr ge $start ? $cc : undef;
57             }
58              
59             sub inet6_ntocc {
60             my ($this, $addr) = @_;
61              
62             $addr = substr($addr, 0, 8);
63              
64             my ($key, $data);
65             $this->{db}->seq($key = "6$addr", $data, DB_File::R_CURSOR()) == 0
66             or return undef;
67             my $start = substr($data, 0, 4);
68             my $cc = substr($data, 4, 2);
69              
70             return $addr ge $start ? $cc : undef;
71             }
72              
73             sub inet6_atocc {
74             my ($this, $host) = @_;
75              
76             my ($err, $result) = Socket::getaddrinfo($host, undef, {
77             family => Socket::AF_INET6,
78             socktype => Socket::SOCK_STREAM,
79             });
80             return undef if $err || !$result;
81             my (undef, $addr) = Socket::unpack_sockaddr_in6($result->{addr});
82              
83             $addr = substr($addr, 0, 8);
84              
85             my ($key, $data);
86             $this->{db}->seq($key = "6$addr", $data, DB_File::R_CURSOR()) == 0
87             or return undef;
88             my $start = substr($data, 0, 8);
89             my $cc = substr($data, 8, 2);
90              
91             return $addr ge $start ? $cc : undef;
92             }
93              
94             sub db_time {
95             my $this = shift;
96              
97             my $file;
98             my $fd = $this->{db}->fd();
99             open($file, "<&$fd")
100             or die("Can't dup DB file descriptor: $!\n");
101             my @stat = stat($file)
102             or die("Can't stat DB file descriptor: $!\n");
103             close($file);
104              
105             return $stat[9]; # mtime
106             }
107              
108             1;
109              
110             __END__