File Coverage

blib/lib/Net/Whois/Proxy.pm
Criterion Covered Total %
statement 54 164 32.9
branch 13 100 13.0
condition 20 100 20.0
subroutine 12 19 63.1
pod 11 11 100.0
total 110 394 27.9


line stmt bran cond sub pod time code
1             package Net::Whois::Proxy;
2              
3 2     2   21241 use strict;
  2         6  
  2         119  
4 2     2   12613 use IO::Socket;
  2         112613  
  2         15  
5 2     2   2665 use vars qw ($VERSION);
  2         12  
  2         17833  
6              
7             $VERSION = $1 if('$Id: Proxy.pm,v 1.9 2005/05/22 02:40:36 cfaber Exp $' =~ /,v ([\d.]+) /);
8              
9             =head1 NAME
10              
11             Net::Whois::Proxy - an easy to use recursive whois client library
12              
13             =head1 DESCRIPTION
14              
15             The Net::Whois::Proxy library is an easy to use recursive whois client library that does not do any additional parsing of the whois data. It's goal is to quickly track down domain, ipv4, ipv6, and BGP Anonymous System numbers.
16              
17             =head1 SYNOPSIS
18              
19             use Net::Whois::Proxy;
20             my $whois = new Net::Whois::Proxy;
21              
22             my $record = $whois->whois('EXAMPLE.COM');
23              
24             print $record;
25              
26             exit;
27              
28              
29             Also see the whois.pl example script provided with the library distrobution
30              
31             =head1 METHODS
32              
33             =cut
34              
35             =head2 new(option => value)
36              
37             Create a new Net::Whois::Proxy object.
38              
39             Avaliable options:
40              
41             =over
42              
43             =item * debug
44              
45             Accepted values:
46              
47             1 - turn on debugging, 0 - turn off debugging (default), *HANDLE - turn on debugging and send all debugging info to this file handle.
48              
49             Option description:
50              
51             Dump debugging information to STDOUT or a file handle.
52              
53              
54             =item * stacked_results
55              
56             Accepted values:
57              
58             1 - turn on result stacking, 0 - turn off result stacking (default)
59              
60             Option description:
61              
62             Result stacking will result in the data found durning a whois crawl being stacked on top of each other with additional tags QUERY_#: tags beening added above each result chunk.
63              
64             =item * clean_stack
65              
66             Accepted values:
67              
68             1 - turn on clean result stacking (default), 0 - turn off clean result stacking
69              
70             Option description:
71              
72             Using this option will disable the QUERY_#: entries from being added to a result stack. This option is only used if the B option is enabled.
73              
74             =item * master_ip_whois
75              
76             Accepted values:
77              
78             IP or Fully qualified domain name of a valid whois server (default: whois.arin.net)
79              
80             Option description:
81              
82             The master IP whois server to preform initial queries against.
83              
84             =item * master_ip_port
85              
86             Accepted values:
87              
88             Ports 0 - 65535 (default: 43)
89              
90             Option description:
91              
92             The port number to use when querying the master IP whois server when preforming initial queries.
93              
94             =item * master_domain_whois
95              
96             Accepted values:
97              
98             IP or Fully qualified domain name of a valid whois server (default: whois.internet.net)
99              
100             Option description:
101              
102             The master domain whois server to preform initial queries against.
103              
104             =item * master_domain_port
105              
106             Accepted values:
107              
108             Ports 0 - 65535 (default: 43)
109              
110             Option description:
111              
112             The port number to use when querying the master domain whois server when preforming initial queries.
113              
114             =item * master_whois
115              
116             Accepted values:
117              
118             IP or Fully qualified domain name of a valid whois server (default: whois.internic.net)
119              
120             Option description:
121              
122             The master whois server that should be queried if both IP and domain whois queries fail.
123              
124             =item * master_port
125              
126             Accepted values:
127              
128             Ports 0 - 65535 (default: 43)
129              
130             Option description:
131              
132             The port number to use when querying the master whois server.
133              
134              
135             =item * query_timeout
136              
137             Accepted values:
138              
139             Time in seconds (default: 10)
140              
141             Option description:
142              
143             Sets the amount of time allowed to elaspe before assuming the server has timed out.
144              
145             =cut
146              
147             sub new {
148 1     1 1 17 my ($class, %opts) = @_;
149              
150 1   50     37 my $self = bless {
      50        
      50        
      50        
      50        
151             debug => $opts{debug},
152             stacked_results => $opts{stacked_results},
153             clean_stack => $opts{clean_stack},
154             master_ip_whois => $opts{master_ip_whois} || 'whois.arin.net',
155             master_ip_port => $opts{master_ip_port} || 43,
156             master_whois => $opts{master_whois} || 'rs.internic.net',
157             master_port => $opts{master_port} || 43,
158             query_timeout => $opts{query_timeout} || 10
159             }, $class;
160              
161 1   33     14 $self->{master_domain_whois} = ($opts{master_domain_whois} || $self->{master_whois});
162 1   33     11 $self->{master_domain_port} = ($opts{master_domain_port} || $self->{master_port});
163              
164 1         5 return $self;
165             }
166              
167             =head2 whois(BGP AS # or IPv6 addr or IPv4 addr or PTR or FQDN or IPv4 addr to convert)
168              
169             Attempt to preform useful commands on the data provided.
170              
171             If the string provided is: 'AS #' or 'AS#' preform an anonymous system whois query on the IPv4 BGP tree.
172              
173             Example:
174              
175             print $whois->whois("AS 12345");
176              
177             If the string provided is an IPv6 address preform an whois query on it.
178              
179             Example:
180              
181             print $whois->whois("3ffe:b80:138c:1::59");
182              
183             If the string provided is an IPv4 address preform an whois query on it.
184              
185             Example:
186              
187             print $whois->whois("63.224.69.57");
188              
189             If the string provided starts with 'reverse' or 'dns' or 'rdns' and a dotted quad IPv4 address preform a PTR query.
190              
191             Example:
192              
193             print $whois->whois("reverse 63.224.69.57");
194              
195              
196             If the string provided starts with 'convert' and a dotted quad IPv4 address or long integer address, convert the address to a long integer address or a dotted quad address
197              
198             Example:
199              
200             print $whois->whois("convert 63.224.69.57");
201              
202             =cut
203              
204             sub whois {
205 1     1 1 123 my ($self, $in) = @_;
206 1 50       5 if((my $ip = $self->convert_ipv4($in))){
    50          
    50          
    50          
    0          
    0          
207 0         0 return $self->whois_ipv4($ip);
208             } elsif($in =~ /^[a-f0-9][a-f0-9][a-f0-9][a-f0-9]:/){
209 0         0 return $self->whois_ipv6($in);
210             } elsif($in =~ /AS\s*?([0-9\s]+)/i){
211 0         0 return $self->whois_bgp_as("AS$1");
212             } elsif($in =~ /([A-Za-z0-9-]+\.[A-Za-z]{2,4})$/){
213 1         5 return $self->whois_domain($1);
214             } elsif($in =~ /^(rev|r|dns)(erse|dns)?.*?\:?\s?(\d+\.\d+\.\d+\.\d+)/i){
215 0         0 return $self->whois_ptr($3);
216             } elsif($in =~ /^(con|v)(ert|vert)?.*?:?\s?(\d+\.\d+\.\d+\.\d+|\d+)/i){
217 0         0 return $self->convert_ipv4($3);
218             } else {
219 0         0 return $self->_seterrstr("Unknown address type");
220             }
221             }
222              
223             =head2 convert_ipv4(###.###.###.### or long_int)
224              
225             Take an IPv4 "dotted quad" address and convert it to long interger format, or an IPv4 long integer address and convert it to the "dotted quad" format.
226              
227             =cut
228              
229             sub convert_ipv4 {
230 1     1 1 2 my ($self, $int) = @_;
231 1         5 $self->_pd("checking IPv4 for conversion", caller);
232              
233 1 50       11 if($int =~ /^\d+$/){
    50          
234 0         0 $self->_pd("IPv4 is long integer format", caller);
235 0         0 return inet_ntoa(pack "L", $int);
236             } elsif($self->check_ipv4($int)) {
237 0         0 $self->_pd("IPv4 is dotted quad format", caller);
238 0         0 return unpack("L", inet_aton $int);
239             } else {
240 1         4 $self->_pd("address appears to be invalid", caller);
241 1         24 return;
242             }
243             }
244              
245             =head2 whois_ipv4(IPv4_dotted_quad or IPv4_long_integer[, whois, port, timeout])
246              
247             Preform a whois query on an IPv4 address of some type. Optionally query B on port B and timeout after B seconds.
248              
249             =cut
250              
251             sub whois_ipv4 {
252 0     0 1 0 my ($self, $ip, $server, $port) = @_;
253              
254 0 0       0 if($ip =~ /^\d+$/){
255 0   0     0 $ip = $self->convert_ipv4($ip) || return undef;
256             }
257            
258 0 0       0 $self->check_ipv4($ip) || return undef;
259              
260             # This is our hints list to try and figure out where to look for more
261             # ip information. The format is as follows:
262             # whoisd => { port => port, s_flag => 'startflag', e_flag => 'stopflag', regexps => [re,re] }
263             #
264              
265 0         0 my %hints = (
266             # LACNIC hints
267             'whois.lacnic.net' => {
268             port => 43,
269             regexps => ['/LACNIC/'],
270             },
271             # APNIC hints
272             'whois.apnic.net' => {
273             port => 43,
274             regexps => ['/APNIC/'],
275             },
276             # AUNIC hints
277             'whois.aunic.net' => {
278             port => 43,
279             regexps => ['/AUNIC-AU/'],
280             },
281             # RIPE hints
282             'whois.ripe.net' => {
283             port => 43,
284             regexps => ['/(NET)?(BLK)?.*?-RIPE/'],
285             },
286             # Brazilian NIC
287             'whois.nic.br' => {
288             port => 43,
289             regexps => ['/NETBLK-BRAZIL/'],
290             },
291             # Japan's NIC
292             'whois.nic.ad.jp' => {
293             port => 43,
294             regexps => ['/JPNIC/'],
295             e_flag => '/e',
296             },
297             # Telstra NIC
298             'whois.telstra.net' => {
299             port => 43,
300             regexps => ['/whois\.telstra/i'],
301             },
302             # The Korean NIC
303             'whois.nic.or.kr' => {
304             port => 43,
305             regexps => ['/whois.nic.or.kr/i'],
306             },
307             # Some big rwhois servers.
308             # The Exodus rwhois server
309             'rwhois.exodus.net' => {
310             port => 4321,
311             regexps => ['/rwhois\.exodus/i'],
312             },
313             # The DNAI rwhois server
314             'rwhois.dnai.com' => {
315             port => 4321,
316             regexps => ['/rwhois\.dnai/i'],
317             },
318             # The Digex rwhois server
319             'rwhois.digex.net' => {
320             port => 4321,
321             regexps => ['/rwhois\.digex/i'],
322             },
323             # The Internex rwhois server
324             'rwhois.internex.net' => {
325             port => 4321,
326             regexps => ['/rwhois.internex/i'],
327             },
328             # The XO/Concentric rwhois server
329             'rwhois.concentric.net' => {
330             port => 4321,
331             regexps => ['/rwhois\.concentric/i'],
332             },
333             );
334              
335             # If we're not querying ARIN right off the bat then add it to our hints list.
336 0 0       0 $server || ($server = $self->{master_ip_whois});
337              
338 0 0       0 if($server !~ /whois\.arin\.net/i){
339 0         0 $hints{'whois.arin.net'}->{port} = 43;
340 0         0 $hints{'whois.arin.net'}->{regexps} = ['/IANA-NETBLOCK/'];
341             }
342            
343            
344 0   0     0 my $data = $self->_query_whois($ip, $server, $port || $self->{master_ip_port}, $self->{master_timeout}) || return;
345              
346             # See if ``ReferralServer'' exists in the CDIR
347 0 0       0 if($data =~ /ReferralServer\:\s*(?:whois:\/\/)?([A-Za-z0-9:.-]+)/){
348 0         0 my ($wi, $po) = split(/:/, $1, 2);
349 0   0     0 $po ||= ($self->{master_whois_port} || 4321);
      0        
350              
351 0         0 $self->_pd("ReferralServer Match: $wi:$po", caller);
352 0   0     0 my $data2 = $self->_query_whois($ip, $wi, $po, $self->{master_timeout}) || return;
353              
354 0 0       0 if($self->{stacked_results}){
355 0         0 $self->_pd("Stacking results", caller);
356 0 0       0 return (!$self->{clean_stack} ? 'QUERY_0: ' . $server : undef) . "\n" . $data . "\n" . (!$self->{clean_stack} ? 'QUERY_1: ' . "$wi\:$po" : "") . "\n" . $data2;
    0          
357             } else {
358 0 0       0 return ($data2 ? $data2 : $data);
359             }
360             }
361              
362            
363 0         0 WHOIS: for my $whoisd (keys %hints){
364 0         0 $self->_pd($whoisd, caller);
365 0         0 HINT: for my $re (@{$hints{$whoisd}->{regexps}}){
  0         0  
366 0         0 $re = "\$data =~ $re";
367 0         0 $self->_pd("Testing: $re", caller);
368 0 0       0 if(eval $re){
369 0         0 $self->_pd("Match!", caller);
370 0   0     0 my $data2 = $self->_query_whois($hints{$whoisd}->{'s_tag'} . $ip . $hints{$whoisd}->{'e_tag'}, $whoisd, $hints{$whoisd}->{'port'}, $hints{$whoisd}->{'timeout'} || $self->{master_timeout}) ||
371             return undef;
372 0 0       0 if($self->{stacked_results}){
373 0         0 $self->_pd("Stacking results", caller);
374 0 0       0 return (!$self->{clean_stack} ? 'QUERY_0: ' . $server : undef) . "\n" . $data . "\n" . (!$self->{clean_stack} ? 'QUERY_1: ' . $whoisd : undef) . "\n" . $data2;
    0          
375             } else {
376 0 0       0 return ($data2 ? $data2 : $data);
377             }
378             }
379             }
380             }
381 0         0 return $data;
382             }
383              
384             =head2 whois_ipv6(IPv6_address)
385              
386             Preform an IPv6 whois query on B
387              
388             =cut
389              
390             sub whois_ipv6 {
391 0     0 1 0 my ($self, @ip) = (shift, split(/:/, shift, 8));
392             # This is the IPv6 hints data
393             # each regexp# represents a differnt chunk of the ipv6 ip block.
394             # If you know if any pTLA's which aren't in this please
395             # send me an email and ill add them cfaber@fpsn.net
396             #
397 0         0 my %hints = (
398             # The 6bone testbed pTLD
399             'whois.6bone.net' => {
400             port => 43,
401             regexps => ['/^3ffe/i','/^5[fF][0-fF][0-fF]/'],
402             },
403             # The APNIC IPv6 block
404             'whois.apnic.net' => {
405             port => 43,
406             regexps => ['/^2001/','/^2[0-fF][0-fF]/'],
407             },
408             # The ARIN IPv6 block
409             'whois.arin.net' => {
410             port => 43,
411             regexps => ['/^2001/','/^4[0-fF][0-fF]/'],
412             },
413             # The RIPE IPv6 block
414             'whois.ripe.net' => {
415             port => 43,
416             regexps => ['/^2001/','/^6[0-fF][0-fF]/','/^2002/'],
417             },
418             );
419            
420              
421 0         0 WHOIS: for my $whoisd (keys %hints){
422 0         0 $self->_pd($whoisd, caller);
423 0         0 HINT: for my $re (@{$hints{$whoisd}->{regexps}}){
  0         0  
424 0         0 $re = "\$ip[0] =~ $re";
425 0         0 $self->_pd("Testing: $re", caller);
426 0 0       0 if(eval $re){
427 0         0 $self->_pd("Match!", caller);
428 0   0     0 my $data = $self->_query_whois($hints{$whoisd}->{'s_tag'} . join(':', @ip) . $hints{$whoisd}->{'e_tag'}, $whoisd, $hints{$whoisd}->{'port'}, $hints{$whoisd}->{'timeout'} || $self->{master_timeout}) || return undef;
429 0         0 return $data;
430             }
431             }
432             }
433              
434 0         0 return $self->_seterrstr("IPv6 Lookup failure: Unknown mask range.");
435             }
436              
437              
438             =head2 whois_bgp_as(ID)
439              
440             Preform an whois query on an anonymous system number on the IPv4 BGP tree.
441              
442             =cut
443              
444             sub whois_bgp_as {
445 0     0 1 0 my ($self, $id) = @_;
446 0         0 $id =~ s/[^0-9]+//g;
447 0 0       0 return $self->_seterrstr("whois_bgp_as() requires a valid id") if(!$id);
448            
449 0         0 my %as_table = (
450             'whois.arin.net' => {
451             as_table => [
452             [1, 1876],
453             [1902, 2042],
454             [2044, 2046],
455             [2048, 2106],
456             [2137, 2584],
457             [2615, 2772],
458             [2823, 2829],
459             [2880, 3153],
460             [3354, 4607],
461             [4865, 5376],
462             [5632, 6655],
463             [6912, 7466],
464             [7723, 8191],
465             [11264, 12287],
466             [13312, 14335],
467             ],
468             port => 43,
469             's_tag' => 'AS',
470             },
471             'whois.ripe.net' => {
472             as_table => [
473             [1877, 1901],
474             [2043],
475             [2047],
476             [2107, 2136],
477             [2585, 2614],
478             [2773, 2822],
479             [2830, 2879],
480             [3154, 3353],
481             [5377, 5631],
482             [6656, 6911],
483             [8192, 9215],
484             [12288, 13311],
485             ],
486             port => 43,
487             's_tag' => 'AS',
488             },
489             'whois.apnic.net' => {
490             as_table => [
491             [4608, 4864],
492             [7467, 7722],
493             [9216, 10239],
494             ],
495             port => 43,
496             's_tag' => 'AS',
497             },
498             );
499            
500 0         0 for my $whoisd (keys %as_table){
501 0         0 for my $entry (@{$as_table{$whoisd}->{as_table}}){
  0         0  
502 0 0 0     0 if($entry->[0] && $entry->[1]){
    0          
503 0 0 0     0 if($id >= $entry->[0] && $id <= $entry->[1]){
504 0   0     0 my $data = $self->_query_whois($as_table{$whoisd}->{'s_tag'} . $id . $as_table{$whoisd}->{'e_tag'}, $whoisd, $as_table{$whoisd}->{port}, $as_table{$whoisd}->{timeout} || $self->{master_timeout}) ||
505             return undef;
506 0         0 return $data;
507             }
508             } elsif($id == $entry->[0]){
509 0   0     0 my $data = $self->_query_whois($as_table{$whoisd}->{'s_tag'} . $id . $as_table{$whoisd}->{'e_tag'}, $whoisd, $as_table{$whoisd}->{port}, $as_table{$whoisd}->{timeout} || $self->{master_timeout}) ||
510             return undef;
511 0         0 return $data;
512             }
513             }
514             }
515              
516 0         0 return $self->_seterrstr("Unable to lookup entry for AS ID $id");
517             }
518              
519             =head2 whois_domain(FQDN[, whois, port, timeout)
520              
521             Preform a recursive whois lookup on a fully qualified domain name (FQDN), Optionally preform the initial query against the B whois server on port B with the timeout B.
522              
523             =cut
524              
525             sub whois_domain {
526 1     1 1 3 my ($self, $domain, $server, $port, $timeout) = @_;
527 1         4 my $nic;
528              
529 1 50 33     11 if(!$domain || $domain !~ /^[0-9A-Za-z-]+\.[A-Za-z]{2,4}$/){
530 0         0 return $self->_seterrstr("Domain name appears invalid");
531             } else {
532 1   50     29 my $data = $self->_query_whois('=' . $domain, $server || $self->{master_domain_whois}, $port || $self->{master_domain_port}, $timeout || $self->{master_timeout}) || return $self->_seterrstr("_query_whois() failed to return any data. Possible error(s): " . ($self->errstr ? $self->errstr : 'Unknown'));
533              
534 0 0       0 if($data =~ /Whois\s?Server:\s?([A-Za-z0-9.-]+\.[A-Za-z]{2}[A-Za-z]?)/i){
535 0         0 $nic = $1;
536             }
537              
538 0 0 0     0 if(!$nic && $data){
    0          
539 0 0       0 return ($data ? $data : 'Server returned no data');
540             } elsif($nic) {
541 0   0     0 my $data2 = $self->_query_whois($domain, $nic, $port || $self->{master_domain_port}, $timeout || $self->{master_timeout}) || return $self->_seterrstr("_query_whois() failed to return any data. Possible error(s): " . ($self->errstr ? $self->errstr : 'Unknown'));
542              
543 0 0       0 if($self->{stacked_results}){
544 0 0       0 return (!$self->{clean_stack} ? 'QUERY_0: ' . $server : undef) . "\n" . $data . "\n" . (!$self->{clean_stack} ? 'QUERY_1: ' . $nic : undef) . "\n" . $data2;
    0          
545             } else {
546 0 0       0 return ($data2 ? $data2 : 'Server returned no data');
547             }
548             } else {
549 0         0 return $self->_seterrstr("Domain lookup failed.");
550             }
551             }
552             }
553              
554             =head2 check_ipv4(IPv4_dotted_quad)
555              
556             Attempt to determin if an IPv4 address is syntaxually valid.
557              
558             =cut
559              
560             sub check_ipv4 {
561 1     1 1 6 my ($self, @ip) = (shift, split(/\./, shift, 4));
562              
563 1 50 33     12 if(!$ip[0] || $ip[-1] !~ /\d/ || $ip[0] > 255 || $ip[0] !~ /^\d+$/){
      33        
      33        
564 1         6 return $self->_seterrstr("Invalid IPv4 address");
565             } else {
566 0         0 for my $i (1 .. 3){
567 0 0 0     0 if($ip[$i] > 255 || $ip[$i] !~ /^\d+$/){
568 0         0 return $self->_seterrstr("Invalid IPv4 address");
569             }
570             }
571 0         0 return join('.', @ip);
572             }
573             }
574              
575             =head2 errstr()
576              
577             Return the last error message set.
578              
579             =cut
580              
581             sub errstr {
582 5     5 1 6 my ($self, $err) = @_;
583 5 100       14 $self->{errstr} = $err if($err);
584 5         16 return $self->{errstr};
585             }
586              
587             =head2 whois_ptr(IPv4_dotted_quad_address);
588              
589             Return the PTR / Reverse domain name of a dotted quad IPv4 address.
590              
591             =cut
592              
593             sub whois_ptr {
594 0     0 1 0 my ($self, $ip) = @_;
595 0         0 my $name = (gethostbyaddr(pack('C4', split(/\./, $ip, 4)), 2))[0];
596 0 0       0 return ($name ? $name : $self->_seterrstr("The $ip failed to contain a valid PTR record"));
597             }
598              
599             =head2 whois_raw(command, server, port, timeout)
600              
601             Preform a raw whois with B against the whois server B on the port B with the timeout B/
602              
603             =cut
604              
605             sub whois_raw {
606 0     0 1 0 my $self = shift;
607 0         0 return $self->_query_whois(@_);
608             }
609              
610             sub _query_whois {
611 1     1   3 my ($self, $data, $serv, $port, $timeout) = @_;
612 1         2 my $sock;
613              
614 1   50     7 $self->{master_timeout} ||= 10;
615              
616 1   33     12 $port ||= $self->{master_port};
617 1   33     4 $serv ||= $self->{master_serv};
618 1   33     8 $timeout ||= $self->{master_timeout};
619              
620 1         8 $self->_pd("Attempting to connect to: $serv:$port (to: $timeout)", caller);
621              
622 1         3 eval {
623 1     0   33 $SIG{ALRM} = sub { die 'timeout'; };
  0         0  
624 1   33     13 alarm(($timeout || $self->{master_timeout}) + 5);
625 1   50     21 $sock = IO::Socket::INET->new(
626             Proto => 'tcp',
627             PeerAddr => $serv || $self->{master_whois},
628             PeerPort => $port || $self->{master_port},
629             Timeout => $timeout || $self->{master_timeout}
630             ) || die "Unable to create socket $!";
631 0         0 alarm(0);
632             };
633 1 50       10017283 if($@ =~ /timeout/){
    50          
    0          
634 0         0 $self->_pd("Timed out!", caller);
635 0   0     0 return $self->_seterrstr("Connection to " . ($serv || $self->{master_whois}) . ':' . ($port || $self->{master_port}) . " was refused.");
      0        
636             } elsif($@){
637 1         13 $self->_pd("Failure: $@", caller);
638 1   33     16 return $self->_seterrstr("Unknown error while connecting to " . ($serv || $self->{master_whois}) . ':' . ($port || $self->{master_port}) . '.');
      33        
639             } elsif(!$sock){
640 0         0 $self->_pd("Failure: Connection failed", caller);
641 0   0     0 return $self->_seterrstr("Unable to connect to " . ($serv || $self->{master_whois}) . ':' . ($port || $self->{master_port}) . '.');
      0        
642             } else {
643 0         0 $self->_pd("Connected. Sending data: $data", caller, caller);
644 0 0       0 $data .= "\r\n" if($data !~ /[\r\n]+$/);
645 0         0 print $sock $data;
646 0         0 my @data = <$sock>;
647 0 0 0     0 return (@data && wantarray ? @data : (@data ? "@data" : $self->_seterrstr("Query on ``$data'' failed to return results" . ($! ? ': ' . $! : undef))));
    0          
    0          
648             }
649             }
650              
651             sub _seterrstr {
652 3     3   6 my ($self, $err) = @_;
653 3         17 $self->errstr($err);
654 3         21 return;
655             }
656              
657             sub _clean {
658 0     0   0 my ($self, @lines) = @_;
659 0         0 for(my $i = 0; $i < @lines; $i++){
660 0         0 $lines[$i] =~ s/^\s+|\s+$//g;
661 0         0 $lines[$i] =~ s/[\r\n\x0A\x0D]+//g;
662             }
663 0 0       0 return (wantarray ? @lines : join("\n", @lines));
664             }
665              
666             sub _pd {
667 4     4   12 my ($self, $msg, $pkg, $file, $line) = (shift, shift, @_);
668 4         11 my ($l_pkg, $l_file, $l_line) = caller;
669              
670 4         10 $self->{_debug_cnt}++;
671 4 50       12 if($self->{debug}){
672 0         0 my $str = sprintf("[%5d] internal->{ $l_pkg on $l_line line } external->{ $file\->$pkg on $line } data->{ %s }\r\n", $self->{_debug_cnt}, scalar $msg);
673 0 0       0 if($self->{debug} eq 1){
674 0         0 print STDOUT $str;
675             } else {
676 0         0 my $handle = $self->{debug};
677 0         0 print $handle $str;
678             }
679             }
680 4         9 return 1;
681             }
682              
683             1;
684              
685             __END__