fix is_ipaddr? change pc92 A/D default
[spider.git] / perl / DXCIDR.pm
index 88a26d5c552631e4b66c173eb0c3262400e17d0d..fae0f671140925cbe3aa9cfe7536cb663da510a5 100644 (file)
@@ -38,12 +38,25 @@ sub _read
        $fn .= ".$suffix" if $suffix;
        my $fh = IO::File->new($fn);
        my @out;
+       my $ecount;
+       my $line;
+       
 
        if ($fh) {
                while (<$fh>) {
                        chomp;
+                       ++$line;
                        next if /^\s*\#/;
                        next unless /[\.:]/;
+                       next unless $_;
+                       unless (is_ipaddr($_)) {
+                               ++$ecount;
+                               LogDbg('err', qq(DXCIDR: $fn line $line: '$_' not an ip address));
+                               if ($ecount > 10) {
+                                       LogDbg('err', qq(DXCIDR: More than 10 errors in $fn at/after line $line: '$_' - INVALID INPUT FILE));
+                                       return ();
+                               }
+                       }
                        push @out, $_;
                }
                $fh->close;
@@ -55,8 +68,10 @@ sub _read
 
 sub _load
 {
+       return unless $active;
        my $suffix = shift;
        my @in = _read($suffix);
+       return 0 unless @in;
        return scalar add(@in);
 }
 
@@ -82,20 +97,21 @@ sub _put
 
 sub append
 {
+       return 0 unless $active;
+       
        my $suffix = shift;
        my @in = @_;
        my @out;
        
        if ($suffix) {
                my $fn = _fn() . ".$suffix";
-               my $r = rand;
-               my $fh = IO::File->new (">>$fn.$r");
-               if ($fh) {
+               my $fh = IO::File->new;
+               if ($fh->open("$fn", "a+")) {
+                       $fh->seek(0, 2);        # belt and braces !!
                        print $fh "$_\n" for @in;
                        $fh->close;
-                       move "$fn.$r", $fn;
                } else {
-                       LogDbg('err', "DXCIDR::append error appending to $fn.$r $!");
+                       LogDbg('err', "DXCIDR::append error appending to $fn $!");
                }
        } else {
                LogDbg('err', "DXCIDR::append require badip suffix");
@@ -105,20 +121,32 @@ sub append
 
 sub add
 {
+       return 0 unless $active;
        my $count = 0;
+       my @out;
        
        for my $ip (@_) {
                # protect against stupid or malicious
+               next unless is_ipaddr($ip);
                next if $ip =~ /^127\./;
                next if $ip =~ /^::1$/;
+               next if find($ip);
                if ($ip =~ /\./) {
-                       $ipv4->add_any($ip);
-                       ++$count;
-                       ++$count4;
+                       eval {$ipv4->add_any($ip)};
+                       if ($@) {
+                               push @out, $@;
+                       } else {
+                               ++$count;
+                               ++$count4;
+                       }
                } elsif ($ip =~ /:/) {
-                       $ipv6->add_any($ip);
-                       ++$count;
-                       ++$count6;
+                       eval {$ipv6->add_any($ip)};
+                       if ($@) {
+                               push @out, $@;
+                       } else {
+                               ++$count;
+                               ++$count6;
+                       }
                } else {
                        LogDbg('err', "DXCIDR::add non-ip address '$ip' read");
                }
@@ -128,6 +156,8 @@ sub add
 
 sub clean_prep
 {
+       return unless $active;
+
        if ($ipv4 && $count4) {
                $ipv4->clean;
                $ipv4->prep_find;
@@ -143,7 +173,8 @@ sub _sort
        my @in;
        my @out;
        for (@_) {
-               push @in, [inet_pton(m|:|?AF_INET6:AF_INET, $_), split m|/|];
+               my @ip = split m|/|;
+               push @in, [inet_pton(m|:|?AF_INET6:AF_INET, $ip[0]), @ip];
        }
        @out = sort {$a->[0] <=> $b->[0]} @in;
        return map { "$_->[1]/$_->[2]"} @out;
@@ -151,6 +182,7 @@ sub _sort
 
 sub list
 {
+       return () unless $active;
        my @out;
        push @out, $ipv4->list if $count4;
        push @out, $ipv6->list if $count6;
@@ -176,7 +208,12 @@ sub init
                return;
        }
 
-       import Net::CIDR::Lite;
+       eval {import Net::CIDR::Lite };
+       if ($@) {
+               LogDbg('DXProt', "DXCIDR: import Net::CIDR::Lite error $@");
+               return;
+       }
+
        $active = 1;
 
        my $fn = _fn();
@@ -200,18 +237,35 @@ sub _touch
 
 sub reload
 {
+       return 0 unless $active;
+
        new();
 
-       my $count = _load('base');
-       $count += _load('local');
+       my $count = 0;
+       my $files = 0;
+
+       LogDbg('DXProt', "DXCIDR::reload reload database" );
 
-       LogDbg('DXProt', "DXCIDR::reload $count ip addresses found (IPV4: $count4 IPV6: $count6)" );
+       my $dir;
+       opendir($dir, $main::local_data);
+       while (my $fn = readdir $dir) {
+               next unless my ($suffix) = $fn =~ /^badip\.(\w+)$/;
+               my $c = _load($suffix);
+               LogDbg('DXProt', "DXCIDR::reload: $fn read containing $c ip addresses" );
+               $count += $c;
+               $files++;
+       }
+       closedir $dir;
+       
+       LogDbg('DXProt', "DXCIDR::reload $count ip addresses found (IPV4: $count4 IPV6: $count6) in $files badip files" );
 
        return $count;
 }
 
 sub new
 {
+       return 0 unless $active;
+
        $ipv4 = Net::CIDR::Lite->new;
        $ipv6 = Net::CIDR::Lite->new;
        $count4 = $count6 = 0;