File Coverage

blib/lib/NET/IPFilter.pm
Criterion Covered Total %
statement 27 184 14.6
branch 0 54 0.0
condition 0 53 0.0
subroutine 9 19 47.3
pod 0 7 0.0
total 36 317 11.3


line stmt bran cond sub pod time code
1             package NET::IPFilter;
2              
3 1     1   24626 use Carp;
  1         4  
  1         96  
4 1     1   6 use strict;
  1         3  
  1         34  
5             # use 5.008008;
6 1     1   970 use HTTP::Request;
  1         28084  
  1         31  
7 1     1   1211 use LWP::UserAgent;
  1         27082  
  1         48  
8 1     1   1256 use Compress::Zlib;
  1         84644  
  1         307  
9 1     1   11 use Fcntl ':flock';
  1         3  
  1         1004  
10             # use Math::BigInt;
11             # use warnings;
12             # use Data::Dumper;
13              
14             require Exporter;
15              
16             our @ISA = qw(Exporter);
17              
18             # Items to export into callers namespace by default. Note: do not export
19             # names by default without a very good reason. Use EXPORT_OK instead.
20             # Do not simply export all your public functions/methods/constants.
21              
22             # This allows declaration use NET::IPFilter ':all';
23             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
24             # will save memory.
25             our %EXPORT_TAGS = ( 'all' => [ qw(
26             beautifyRawIPfromIPFilter
27             readIPFilterFile
28             httpGetStore
29             _ip2long
30             _long2ip
31             isValid
32             gunzip
33             _init
34             ) ] );
35              
36             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
37              
38             our @EXPORT = qw(
39             beautifyRawIPfromIPFilter
40             readIPFilterFile
41             httpGetStore
42             _ip2long
43             _long2ip
44             isValid
45             gunzip
46             _init
47             );
48              
49             our $VERSION = '1.2';
50              
51              
52             ######
53             my $MaxFileSizeOfWebDocument = (50 * 1024 * 1024); # 5mb
54             my $MaxRedirectRequests = 15;
55             my $AuthorEmail = 'yourname@cpan.org';
56             my $Timeout = 25;
57             my $CrawlDelay = int(rand(3));
58             my $Referer = "http://www.google.com/";
59             my $DEBUG = 1;
60             # IPFilter.dat: http://www.bluetack.co.uk/forums/index.php
61             ######
62              
63              
64             sub new(){
65              
66 0     0 0   my $class = shift;
67 0 0         my %args = ref($_[0])?%{$_[0]}:@_;
  0            
68 0           my $self = \%args;
69 0           bless $self, $class;
70 0           $self->_init();
71 0           return $self;
72            
73             }; # sub new(){
74              
75              
76             sub isValid(){
77              
78 0     0 0   my $self = shift;
79 0           my $IPtoCheck = $self->_ip2long(shift);
80 0           my $RangesArrayRef = $self->{'_IPRANGES_ARRAY_REF'};
81 0           my $howmany = scalar( @{$RangesArrayRef} );
  0            
82            
83             # $IPtoCheck = Math::BigInt->new($IPtoCheck);
84              
85 0           for ( my $count=0; $count<=$howmany; $count++) {
86            
87 0           my ($RangFrom, $RangTo) = split("-", $RangesArrayRef->[$count]);
88            
89 0 0 0       if ( $IPtoCheck >= $RangFrom && $IPtoCheck <= $RangTo ) {
90 0           return 0;
91             };
92              
93             }; # for ( my $count=0; $count<=$howmany; $count++) {
94              
95 0           return 1; # if ip not found in ipfilter.dat its valid
96              
97             }; # sub isValid(){
98              
99              
100              
101              
102             sub readIPFilterFile(){
103              
104 0     0 0   my $self = shift;
105 0           my $IPFilterDatFile = shift;
106              
107 0           my @IP_Ranges = ();
108              
109 0 0         open(RH,"<$IPFilterDatFile") or croak("$self -> _readIPFilterFile( $IPFilterDatFile ) Reading Failed");
110 0           while (defined( my $entry = )) {
111 0           chomp($entry);
112            
113 0 0 0       next if ( $entry =~ /^#/g || $entry =~ /#/g );
114 0           my ($IPRange, undef, $DESC) = split(",", $entry);
115 0 0         next if ( $DESC =~ /\[BG\]FreeSP/ig ); # ignore not used ips
116 0           my ($IP_Start,$IP_End) = split("-", $IPRange );
117            
118 0           $IP_Start =~ s/^\s+//;
119 0           $IP_Start =~ s/\s+$//;
120 0           $IP_End =~ s/^\s+//;
121 0           $IP_End =~ s/\s+$//;
122            
123             # beautifyRawIPfromIPFilter is not needed
124             # my $IPStart = $self->beautifyRawIPfromIPFilter( $IP_Start );
125             # my $IPEnd = $self->beautifyRawIPfromIPFilter( $IP_End );
126            
127 0           my $IPStart = $self->_ip2long( $IP_Start );
128 0           my $IPEnd = $self->_ip2long( $IP_End );
129              
130             # $IPStart = Math::BigInt->new($IPStart);
131             # $IPEnd = Math::BigInt->new($IPEnd);
132              
133             # print "$IP_Start und $IP_End\n";
134 0           push(@IP_Ranges, "$IPStart-$IPEnd");
135              
136              
137             }; # while (defined( my $entry = )) {
138 0           close RH;
139              
140 0           $self->{'_IPRANGES_ARRAY_REF'} = \@IP_Ranges;
141              
142 0           return $self;
143              
144             }; # sub _readIPFilterFile(){
145              
146              
147             sub beautifyRawIPfromIPFilter(){
148              
149 0     0 0   my $self = shift;
150 0           my $RawIP = shift;
151 0           my ($a,$b,$c,$d) = split(/\./, $RawIP );
152 0           my @tmp = ($a, $b, $c, $d);
153 0           my %IP = ();
154 0           my $tmp;
155            
156 0           for (my $i=0; $i<=$#tmp; $i++ ){
157            
158 0           my ($one, $two, $thr) = split("", $tmp[$i]);
159            
160 0 0 0       if ( $one == 0 && $two == 0 && $thr == 0 ){
    0 0        
    0 0        
    0 0        
      0        
      0        
      0        
      0        
161             # 000->0
162 0           $IP{$i} = 0;
163             } elsif ( $one == 0 && $two == 0 && $thr != 0 ){
164             # 001->1
165 0           $IP{$i} = $thr;
166             } elsif ( $one == 0 && $two != 0 && $thr != 0){
167             # 0XY->XY
168 0           $IP{$i} = $two.$thr;
169             } elsif ( $one != 0 && $two != 0 && $thr != 0 ){
170             # XYZ->XYZ
171 0           $IP{$i} = $tmp[$i];
172             } else {
173             # rest
174 0           $IP{$i} = $tmp[$i];
175             }; # if ( $one == 0 && $two == 0 && $thr == 0 ){
176              
177             }; # for (my $i=1; $i<=$#tmp; $i++ ){
178              
179 0           return $IP{0} . "." . $IP{1} . "." . $IP{2} . "." . $IP{3};
180              
181             }; # sub _BeautifyRawIPfromIPFilter(){
182              
183              
184             sub _ip2long(){
185              
186 0     0     my $self = shift;
187 0           my $ip = shift;
188 0           my @numbers = split(/\./,$ip);
189 0           return ($numbers[0] * 16777216) + ($numbers[1] * 65536) + ($numbers[2] * 256) + ($numbers[3]);
190              
191             }; # sub ip2long() {
192              
193              
194             sub _long2ip(){
195              
196 1     1   1111 use Socket qw ( inet_ntoa );
  1         4145  
  1         497  
197              
198 0     0     my $self = shift;
199 0           my $long = shift;
200 0           return inet_ntoa(pack("N*", $long));
201              
202             }; # sub long2ip(){
203              
204              
205             sub httpGetStore(){
206            
207 0     0 0   my $self = shift;
208 0           my $url = shift;
209 0           my $storePath = shift;
210              
211 0           my $UA = LWP::UserAgent->new( keep_alive => 1 );
212            
213 0           $UA->agent("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; YPC 3.0.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)");
214             # $UA->agent("wget");
215 0           $UA->timeout( $Timeout );
216 0           $UA->max_size( $MaxFileSizeOfWebDocument );
217 0           $UA->from( $AuthorEmail );
218 0           $UA->max_redirect( $MaxRedirectRequests );
219 0           $UA->parse_head( 1 );
220 0           $UA->protocols_allowed( [ 'http', 'https', 'ftp', 'ed2k'] );
221 0           $UA->protocols_forbidden( [ 'file', 'mailto'] );
222 0           $UA->requests_redirectable( [ 'HEAD', 'GET', 'POST'] );
223              
224             # $ua->credentials( $netloc, $realm, $uname, $pass )
225             # $ua->proxy(['http', 'ftp'], 'http://proxy.sn.no:8001/'); # f�r protokollschema http und ftp benutze proxy ...
226             # $ua->env_proxy -> wais_proxy=http://proxy.my.place/ -> export gopher_proxy wais_proxy no_proxy
227            
228 0           sleep $CrawlDelay;
229              
230 0           my $req = HTTP::Request->new( GET => $url );
231 0           $req->referer($Referer);
232              
233 0           my $res = $UA->request($req);
234              
235 0 0         if ( $res->is_success ) {
236              
237             # open(WH,">$storePath") or die "$self -> _httpGetStore() - I/O Error!\n";
238             # flock(WH,LOCK_EX);
239             # print WH $res->content;
240             # flock(WH,LOCK_UN);
241             # close WH;
242            
243 0           $self->saveFile( $storePath, $res->content , ">"); # '>' - perl file handle openening type
244            
245             } else {
246              
247 0           croak("$self -> _httpGetStore() -http-Get Request Failed: $res->status_line\n");
248              
249             }; # if ($res->is_success) {
250              
251 0           return 1;
252              
253             }; # sub _httpGetStore(){
254              
255              
256             sub gunzip(){
257              
258 0     0 0   my $self = shift;
259 0           my $ZippedFile = shift;
260 0           my $UnzippedFile = shift;
261            
262 1     1   8 no strict 'subs';
  1         2  
  1         227  
263              
264 0           my $gzerrno;
265             my $buffer;
266 0           my $gz = undef;
267 0           my $success = 1;
268              
269 0 0         if (! open FH, ">$UnzippedFile") {
270 0           $success = 0;
271             # print "Unable to write to '$outfile'\n";
272             } else {
273            
274 0           binmode FH;
275 0           flock(FH,LOCK_EX);
276              
277 0 0         if ($gz = gzopen($ZippedFile, "rb")) {
278              
279 0           while ($gz->gzread($buffer) > 0) {
280 0           print FH $buffer;
281             }; # while ($gz->gzread($buffer) > 0) {
282              
283 0 0         if ($gzerrno != Z_STREAM_END) {
284 0           $success = 0;
285             # print "ZLib Error: reading $outfile - $gzerrno: $!\n";
286             } else {
287 0           $success = 1;
288             }; # if ($gzerrno != Z_STREAM_END) {
289              
290 0           $gz->gzclose;
291              
292             } else {
293              
294 0           $success = 0;
295             # print "ZLib Error: opening $infile - $gzerrno: $!\n";
296              
297             }; # if ($gz = gzopen($infile, "rb")) {
298              
299 0           close FH;
300 0           flock(FH,LOCK_UN);
301            
302             }; # if (! open FH, ">$UnzippedFile") {
303              
304 0 0         if ( $success == 0 ) {
305            
306 0           system("/bin/mv $ZippedFile $UnzippedFile");
307 0 0         system("/bin/gunzip $UnzippedFile") && system("/usr/bin/gunzip $UnzippedFile");
308              
309             }; # if ( $success == 0 ) {
310              
311 1     1   4 use strict;
  1         2  
  1         754  
312 0           return 1;
313              
314             }; # sub _gunzip(){
315              
316              
317             sub saveFile(){
318              
319 0     0 0   my $self = shift;
320 0           my $File = shift;
321 0           my $refContent = shift;
322 0   0       my $oberator = shift || ">";
323              
324 0 0         open(FILE, $oberator . $File) or croak "$self->_saveFile(): Open Error: $!\n";
325 0           binmode(FILE);
326 0           flock(FILE,LOCK_EX);
327            
328 0 0         if ( ref($refContent) eq 'ARRAY' ) {
    0          
    0          
    0          
329              
330 0           for ( my $i=0; $i<=$#{$refContent}; $i++ ) {
  0            
331 0           print FILE $refContent->[$i];
332             }; # for ( my $i=0; ...
333              
334             } elsif ( ref($refContent) eq 'HASH' ) {
335              
336 0           my $keys = keys( %{$refContent} );
  0            
337 0           for ( my $i=0; $i<=$keys; $i++ ) {
338 0           print FILE $refContent->{$i};
339             }; # for ( my $i=0; ...
340              
341             } elsif ( ref($refContent) eq 'SCALAR' ) {
342 0           print FILE ${$refContent};
  0            
343              
344             } elsif ( ref($refContent) eq '' ) { # normaler scalar senden
345 0           print FILE $refContent;
346              
347             } else {
348              
349             # code oder glob ref
350 0           croak "CODE or GLOB Ref - not supported\n";
351 0           flock(FILE,LOCK_UN);
352 0           close FILE;
353 0           return -1;
354              
355             }; # if ( ref($refContent) eq 'ARRAY' ) {
356            
357 0           flock(FILE,LOCK_UN);
358 0           close FILE;
359              
360 0           return $File;
361              
362             }; # sub _saveFile(){
363              
364              
365             sub _init(){
366              
367 0     0     my $self = shift;
368            
369 0           my $ipfilter_file = $self->{'ipfilter'};
370 0           my $tmp_dir = $self->{'tmpdir'};
371 0           my $force_init = $self->{'force_init'};
372 0   0       mkdir $tmp_dir || system("/bin/mkdir $tmp_dir");
373            
374 0           my $IPFilerFile = "$tmp_dir/ipfilter.dat";
375 0           my $IPFilerFileGZ = "$tmp_dir/ipfilter.dat.gz";
376              
377             # Delete Files if force init == 1 resulting in recreation of ipfilter files
378 0 0         if ( $force_init == 1 ) {
379              
380 0   0       unlink $IPFilerFile || system("/bin/rm -f $IPFilerFile");
381 0   0       unlink $IPFilerFileGZ || system("/bin/rm -f $IPFilerFileGZ");
382            
383             }; # if ( $force_init == 1 ) {
384              
385             # File doesnt exsits so we need to download it
386 0 0 0       if ( ( !-e $ipfilter_file && !-f $ipfilter_file ) || ( !-e $IPFilerFile && !-f $IPFilerFile ) ){
      0        
      0        
387              
388 0 0         if ( $ipfilter_file =~ /^http:\/\//i ) {
389            
390 0           my @tmp = split('/', $ipfilter_file);
391 0           my $FileName = $tmp[$#tmp];
392 0           my ( $OnlyFileName , $OnlyFileTyp ) = split(/(\.([^.]+?)$)/i, $FileName ); # working correctly for "TEST.JPEG.bmp
393            
394             # todo: later bzip2|rar support
395 0 0 0       if ( $OnlyFileTyp eq 'gz' || $OnlyFileTyp =~ /gz/i ) {
396            
397 0 0         print "Downloading gzip file $ipfilter_file \n " if $DEBUG == 1;
398              
399             # Download and Save file
400 0           $self->httpGetStore($ipfilter_file, $IPFilerFileGZ);
401            
402 0 0         print "Unzipping gzip file $ipfilter_file \n " if $DEBUG == 1;
403              
404             # gunzip file
405 0           $self->gunzip($IPFilerFileGZ, $IPFilerFile);
406              
407             # read file
408 0           $self->readIPFilterFile( $IPFilerFile );
409 0           return $self;
410              
411             } else { # asume txt file
412            
413 0 0         print "Downloading txt file $ipfilter_file \n " if $DEBUG == 1;
414             # Download and Save file
415 0           $self->httpGetStore($ipfilter_file, $IPFilerFile);
416              
417 0           $self->readIPFilterFile( $IPFilerFile );
418 0           return $self;
419              
420             }; # if ( $OnlyFileTyp eq 'gz' || $OnlyFileTyp =~ /gz/i ) {
421            
422             }; # if ( $ipfilter_file =~ /^http:\/\//i ) {
423              
424             }; # if ( ! -e $IPFilerFile && ! -f $IPFilerFile ){
425              
426 0           $self->readIPFilterFile( $ipfilter_file );
427 0           return $self;
428              
429             }; # sub _init(){
430              
431              
432              
433             # Preloaded methods go here.
434              
435             return 1;
436             __END__