File Coverage

blib/lib/WWW/Honeypot/httpBL.pm
Criterion Covered Total %
statement 21 104 20.1
branch 0 38 0.0
condition 0 37 0.0
subroutine 7 21 33.3
pod 7 9 77.7
total 35 209 16.7


line stmt bran cond sub pod time code
1             package WWW::Honeypot::httpBL;
2              
3 3     3   67921 use 5.008008;
  3         9  
  3         103  
4 3     3   18 use strict;
  3         14  
  3         97  
5 3     3   15 use warnings;
  3         8  
  3         81  
6              
7 3     3   14 use Carp;
  3         5  
  3         292  
8 3     3   2615 use Net::hostent;
  3         17782  
  3         79  
9 3     3   3670 use Socket;
  3         11930  
  3         1812  
10              
11 3     3   22 use constant 'LOOKUP_DOMAIN' => 'dnsbl.httpbl.org';
  3         5  
  3         3030  
12              
13             our $VERSION = '0.01';
14              
15             my $search_engines = {
16             '0' => 'Undocumented',
17             '1' => 'Alta Vista',
18             '2' => 'Ask',
19             '3' => 'Baidu',
20             '4' => 'Excite',
21             '5' => 'Google',
22             '6' => 'Looksmart',
23             '7' => 'Lycos',
24             '8' => 'MSN',
25             '9' => 'Yahoo',
26             '10' => 'InfoSeek',
27             '11' => 'Miscellaneous'
28             };
29              
30             sub new {
31 0     0 0   my $pkg = shift;
32              
33 0           my $self = {};
34 0           bless $self, $pkg;
35              
36 0 0         if (! $self->_init(@_)) {
37 0           return undef;
38             }
39              
40 0           return $self;
41             }
42              
43             sub _init {
44 0     0     my $self = shift;
45 0 0         my $args = (ref($_[0]) eq "HASH") ? shift : {@_};
46              
47 0           $self->{'_debug'} = $args->{'debug'};
48 0           $self->{'_key'} = $args->{'access_key'};
49 0           $self->{'_current_ip'} = '';
50 0           $self->{'_current_response'} = '';
51 0           $self->{'_current_response_octets'} = [];
52              
53 0           return 1;
54             }
55              
56             sub access_key {
57 0     0 0   my $self = shift;
58 0           my $key = shift;
59              
60 0 0         if ($key) {
61 0           $self->{'_key'} = $key;
62             }
63              
64 0           return $self->{'_key'};
65             }
66              
67             sub fetch {
68 0     0 1   my $self = shift;
69 0           my $ip = shift;
70              
71 0           $self->_reset();
72              
73 0 0 0       carp("No Access Key!") && return unless $self->access_key();
74 0 0 0       carp("Nothing to fetch!") && return unless $ip;
75              
76 0 0         unless ($ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
77 0           my $err_str = "That doesn't look like an IP address!";
78 0 0         carp($err_str) && return $err_str;
79             }
80              
81 0           $self->_lookup($self->_reverse_IP($ip));
82            
83 0 0         return $self->{_current_response} ? ($self->_parse_response()) : undef;
84             }
85              
86             sub threat_score {
87 0     0 1   my $self = shift;
88              
89 0           return ( $self->{_current_response} && !$self->is_search_engine() ) ?
90 0 0 0       ${$self->{_current_response_octets}}[2] : undef;
91             }
92              
93             sub days_since_last_actvity {
94 0     0 1   my $self = shift;
95              
96 0           return ( $self->{_current_response} && !$self->is_search_engine() ) ?
97 0 0 0       ${$self->{_current_response_octets}}[1] : undef;
98             }
99              
100             sub is_search_engine {
101 0     0 1   my $self = shift;
102              
103 0 0         return undef unless $self->{_current_response};
104              
105 0 0         if ( ${$self->{_current_response_octets}}[3] == 0 ) {
  0            
106 0           my $serial_number = ${$self->{_current_response_octets}}[2];
  0            
107 0           return $search_engines->{$serial_number};
108             } else {
109 0           return;
110             }
111             }
112              
113             sub is_suspicious {
114 0     0 1   my $self = shift;
115              
116 0 0         return undef unless $self->{_current_response};
117              
118 0           my $c = ${$self->{_current_response_octets}}[3];
  0            
119 0 0 0       if ($c == 1 || $c == 3 || $c == 5 || $c == 7) {
      0        
      0        
120 0           return 1;
121             } else {
122 0           return undef;
123             }
124             }
125              
126             sub is_harvester {
127 0     0 1   my $self = shift;
128              
129 0 0         return undef unless $self->{_current_response};
130              
131 0           my $c = ${$self->{_current_response_octets}}[3];
  0            
132 0 0 0       if ($c == 2 || $c == 3 || $c == 6 || $c == 7) {
      0        
      0        
133 0           return 1;
134             } else {
135 0           return undef;
136             }
137             }
138              
139             sub is_comment_spammer {
140 0     0 1   my $self = shift;
141              
142 0 0         return undef unless $self->{_current_response};
143              
144 0           my $c = ${$self->{_current_response_octets}}[3];
  0            
145              
146 0 0 0       if ($c == 4 || $c == 5 || $c == 6 || $c == 7) {
      0        
      0        
147 0           return 1;
148             } else {
149 0           return undef;
150             }
151             }
152              
153             # Internal methods below
154              
155             sub _lookup {
156 0     0     my $self = shift;
157 0           my $reversed_ip = shift;
158              
159 0           my $str = join('.', $self->access_key(), $reversed_ip, LOOKUP_DOMAIN);
160              
161 0           my $h = gethost($str);
162              
163 0 0         return unless $h;
164              
165 0           $self->{_current_response} = inet_ntoa($h->addr);
166             }
167              
168             sub _reverse_IP {
169 0     0     my $self = shift;
170 0           my $ip = shift;
171              
172 0           my @parts = split(/\./, $ip);
173 0           return join('.', reverse(@parts));
174             }
175              
176             sub _parse_response {
177 0     0     my $self = shift;
178              
179 0           my @octets = split(/\./, $self->{_current_response});
180 0           push(@{$self->{_current_response_octets}}, @octets);
  0            
181 0           return @octets;
182             }
183              
184             sub _reset {
185 0     0     my $self = shift;
186              
187 0           $self->{'_current_ip'} = '';
188 0           $self->{'_current_response'} = '';
189 0           $self->{'_current_response_octets'} = [];
190             }
191              
192             1;
193             __END__