File Coverage

blib/lib/AnyEvent/Whois/Raw.pm
Criterion Covered Total %
statement 96 174 55.1
branch 23 52 44.2
condition 7 29 24.1
subroutine 18 26 69.2
pod 2 10 20.0
total 146 291 50.1


line stmt bran cond sub pod time code
1             package AnyEvent::Whois::Raw;
2              
3 6     6   76508 use base 'Exporter';
  6         12  
  6         819  
4 6     6   6970 use AnyEvent;
  6         25283  
  6         172  
5 6     6   3206 use AnyEvent::Socket;
  6         128889  
  6         771  
6 6     6   4316 use AnyEvent::Handle;
  6         38272  
  6         197  
7 6     6   3606 use AnyEvent::HTTP;
  6         45444  
  6         564  
8 6     6   57 use strict;
  6         6  
  6         196  
9 6     6   19 no warnings 'redefine';
  6         6  
  6         1412  
10              
11             our $VERSION = '0.06';
12             our @EXPORT = qw(whois get_whois);
13             our $stash;
14              
15             BEGIN {
16             sub Net::Whois::Raw::smart_eval(&) {
17 0     0 0 0 my @rv = eval {
18 0         0 $_[0]->();
19             };
20 0 0 0     0 if ($@ && $@ =~ /^Call me later/) {
21 0         0 die $@;
22             }
23            
24 0         0 return @rv;
25             }
26            
27             sub require_hook {
28 163     163 0 634522 my ($self, $fname) = @_;
29            
30 163 100       125784 return if $fname ne 'Net/Whois/Raw.pm';
31 6         12 for my $i (1..$#INC) {
32 48 100       703 if (-e (my $tname = $INC[$i] . '/Net/Whois/Raw.pm')) {
33 6 50       306 open(my $fh, $tname) or next;
34 6         198 return ($fh, \&eval_filter);
35             }
36             }
37 0         0 return;
38             }
39            
40             sub eval_filter {
41 2754 50   2754 0 40250 return 0 if $_ eq '';
42 2754         2754 s/\beval\s*{/smart_eval{/;
43 2754         27295 return 1;
44             }
45            
46 6     6   22 unshift @INC, \&require_hook;
47 6         63 require Net::Whois::Raw;
48             }
49              
50             sub _extract_known_params {
51 5     5   10 my $args = shift;
52 5         34 my %known_params = (
53             timeout => 1,
54             on_prepare => 1,
55             );
56            
57 5         11 my %params;
58 5         8 eval {
59 5         13 for my $i (-2, -2) {
60 6 100       25 if (exists($known_params{$args->[$i-1]})) {
61 1         3 $params{$args->[$i-1]} = $args->[$i];
62 1         2 delete $known_params{$args->[$i-1]};
63 1         3 splice @$args, $i-1, 2;
64             }
65             else {
66 5         10 last;
67             }
68             }
69             };
70            
71 5         47 return \%params;
72             }
73              
74             sub whois {
75 5     5 1 1148 local $stash = {
76             caller => \&_whois,
77             params => _extract_known_params(\@_),
78             args => [@_],
79             };
80            
81 5         14 &_whois;
82             }
83              
84             sub _whois {
85 9     9   16 my $cb = pop;
86            
87 9         20 my ($res_text, $res_srv);
88 9         14 eval {
89 9         48 ($res_text, $res_srv) = Net::Whois::Raw::whois(@_);
90             };
91 9 100       112080 if (!$@) {
    50          
92 4         23 $cb->($res_text, $res_srv);
93             }
94             elsif ($@ !~ /^Call me later/) {
95 0         0 $cb->('', $@);
96             }
97             }
98              
99             sub get_whois {
100 0     0 1 0 local $stash = {
101             caller => \&_get_whois,
102             params => _extract_known_params(\@_),
103             args => [@_],
104             };
105            
106 0         0 &_get_whois;
107             }
108              
109             sub _get_whois {
110 0     0   0 my $cb = pop;
111            
112 0         0 my ($res_text, $res_srv);
113 0         0 eval {
114 0         0 ($res_text, $res_srv) = Net::Whois::Raw::get_whois(@_);
115             };
116 0 0       0 if (!$@) {
    0          
117 0         0 $cb->($res_text, $res_srv);
118             }
119             elsif ($@ !~ /^Call me later/) {
120 0         0 $cb->('', $@);
121             }
122             }
123              
124             sub Net::Whois::Raw::whois_query {
125 9     9 0 392 my $call = $stash->{calls}{whois_query}++;
126 9 100       12 if ($call <= $#{$stash->{results}{whois_query}}) {
  9         53  
127 4         16 return $stash->{results}{whois_query}[$call];
128             }
129            
130 5         17 whois_query_ae(@_);
131 5         1156 die "Call me later";
132             }
133              
134             sub whois_query_ae {
135 5     5 0 10 my ($dom, $srv_and_port, $is_ns) = @_;
136              
137            
138 5         18 my $whoisquery = Net::Whois::Raw::Common::get_real_whois_query($dom, $srv_and_port, $is_ns);
139 5         102 my $stash_ref = $stash;
140              
141 5         23 my ($srv, $port) = split /:/, $srv_and_port;
142            
143             tcp_connect $srv, $port || 43, sub {
144 5     5   812 my $fh = shift;
145 5 50       19 unless ($fh) {
146 0         0 $stash_ref->{args}->[-1]->('', "Connection to $srv failed: $!");
147 0         0 return;
148             }
149            
150 5         5 my @lines;
151             my $handle;
152             my $timer = AnyEvent->timer(
153             after => exists $stash_ref->{params}{timeout} ?
154             $stash_ref->{params}{timeout} :
155             $Net::Whois::Raw::TIMEOUT||30,
156             cb => sub {
157 1 50 33     970489 if ($handle && !$handle->destroyed) {
158 1         28 $handle->destroy();
159 1         165 $stash_ref->{args}->[-1]->('', "Connection to $srv timed out");
160             }
161             }
162 5 100 50     63 );
163             $handle = AnyEvent::Handle->new(
164             fh => $fh,
165             on_read => sub {
166 4         1945241 my @l = split /(?<=\n)/, $_[0]->{rbuf};
167 4 50 33     37 if (@lines && substr($lines[-1], -1) ne "\n") {
168 0         0 $lines[-1] .= shift(@l);
169             }
170 4         9 push @lines, @l;
171 4         15 $_[0]->{rbuf} = '';
172             },
173             on_error => sub {
174 0         0 undef $timer;
175 0         0 $handle->destroy();
176 0         0 $stash_ref->{args}->[-1]->('', "Read error form $srv: $!");
177             },
178             on_eof => sub {
179 4         219 undef $timer;
180 4         48 local $stash = $stash_ref;
181 4         24 $handle->destroy();
182 4         130 $stash->{calls}{whois_query} = 0;
183 4         8 push @{$stash->{results}{whois_query}}, \@lines;
  4         20  
184 4         9 $stash->{caller}->(@{$stash->{args}});
  4         23  
185             }
186 5         111 );
187            
188 5         386 $handle->push_write($whoisquery."\015\012");
189             }, sub {
190 5     5   1362 my $fh = shift;
191 5         9 local $stash = $stash_ref;
192 5         14 _sock_prepare_cb($fh, $dom);
193 5   50     81 };
194             }
195              
196             sub _sock_prepare_cb {
197 5     5   6 my ($fh, $dom) = @_;
198            
199 5         18 my $sockname = getsockname($fh);
200 5   50     33 my $timeout = $Net::Whois::Raw::TIMEOUT||30;
201            
202 5 50       18 if (exists $stash->{params}{on_prepare}) {
203 0         0 $timeout = $stash->{params}{on_prepare}->($fh);
204             }
205            
206 5         16 my $server4query = Net::Whois::Raw::Common::get_server($dom);
207 5         137932 my $rotate_reference = eval { Net::Whois::Raw::get_ips_for_query($server4query) };
  5         26  
208            
209 5 50 33     92 if (!$rotate_reference && @Net::Whois::Raw::SRC_IPS && $sockname eq getsockname($fh)) {
      33        
210             # we have ip and there was no bind request in on_prepare callback
211 0         0 $rotate_reference = \@Net::Whois::Raw::SRC_IPS;
212             }
213            
214 5 50       13 if ($rotate_reference) {
215 0         0 my $ip = shift @$rotate_reference;
216 0         0 bind $fh, AnyEvent::Socket::pack_sockaddr(0, parse_address($ip));
217 0         0 push @$rotate_reference, $ip; # rotate ips
218             }
219            
220 5 100       51 return exists $stash->{params}{timeout} ?
221             $stash->{params}{timeout} :
222             $timeout;
223             }
224              
225             sub Net::Whois::Raw::www_whois_query {
226 0     0 0   my $call = $stash->{calls}{www_whois_query}++;
227 0 0         if ($call <= $#{$stash->{results}{www_whois_query}}) {
  0            
228 0           return $stash->{results}{www_whois_query}[$call];
229             }
230            
231 0           www_whois_query_ae(@_);
232 0           die "Call me later";
233             }
234              
235             sub www_whois_query_ae {
236 0     0 0   my ($dom) = (lc shift);
237            
238 0           my ($resp, $url);
239 0           my ($name, $tld) = Net::Whois::Raw::Common::split_domain( $dom );
240 0           my @http_query_urls = @{Net::Whois::Raw::Common::get_http_query_url($dom)};
  0            
241            
242 0           www_whois_query_ae_request(\@http_query_urls, $tld, $dom);
243             }
244              
245             sub www_whois_query_ae_request {
246 0     0 0   my ($urls, $tld, $dom) = @_;
247            
248 0           my $qurl = shift @$urls;
249 0 0         unless ($qurl) {
250 0           push @{$stash->{results}{www_whois_query}}, undef;
  0            
251 0           $stash->{calls}{www_whois_query} = 0;
252 0           $stash->{caller}->(@{$stash->{args}});
  0            
253 0           return;
254             }
255            
256 0 0 0       my $referer = delete $qurl->{form}{referer} if $qurl->{form} && defined $qurl->{form}{referer};
257 0 0 0       my $method = ( $qurl->{form} && scalar(keys %{$qurl->{form}}) ) ? 'POST' : 'GET';
258 0           my $stash_ref = $stash;
259            
260             my $cb = sub {
261 0     0     my ($resp, $headers) = @_;
262 0           local $stash = $stash_ref;
263            
264 0 0 0       if (!$resp || $headers->{Status} > 299) {
265 0           www_whois_query_ae_request($urls, $tld, $dom);
266             }
267             else {
268 0           chomp $resp;
269 0           $resp = Net::Whois::Raw::Common::parse_www_content($resp, $tld, $qurl->{url}, $Net::Whois::Raw::CHECK_EXCEED);
270 0           push @{$stash->{results}{www_whois_query}}, $resp;
  0            
271 0           $stash->{calls}{www_whois_query} = 0;
272 0           $stash->{caller}->(@{$stash->{args}});
  0            
273             }
274 0           };
275            
276 0           my $headers = {Referer => $referer};
277 0           my @params;
278             push @params, on_prepare => sub {
279 0     0     my $fh = shift;
280 0           local $stash = $stash_ref;
281 0           _sock_prepare_cb($fh, $dom);
282 0           };
283            
284 0 0         if (exists $stash->{params}{timeout}) {
285 0           push @params, timeout => $stash->{params}{timeout};
286             }
287            
288 0 0         if ($method eq 'POST') {
289 0           require URI::URL;
290            
291 0           my $curl = URI::URL->new("http:");
292 0           $curl->query_form( %{$qurl->{form}} );
  0            
293 0           http_post $qurl->{url}, $curl->equery, headers => $headers, @params, $cb;
294             }
295             else {
296 0           http_get $qurl->{url}, headers => $headers, @params, $cb;
297             }
298             }
299              
300             1;
301              
302             __END__