#!/usr/bin/perl
#
# sg-search - script for searching entries in squidGuard blacklists bases.
# author: Vladimir Lettiev aka crux <crux@altlinux.org> 2004
# license: LGPL
# version: 0.2
#

use strict;
use DB_File;
use Time::HiRes qw/ gettimeofday tv_interval /;

my $nowTime = [gettimeofday];

my (%db, %domains, %urls, @dest, @bases, $output, $entries);

my $config = "/etc/squid/squidGuard.conf";
my $dbdir = "/var/lib/squidGuard";

unless (@ARGV && $#ARGV == 1 ) {
    print &usage;
    exit 1;
}

parseConf();

if ($ARGV[0] ne "ALL"){
    foreach my $dest (@dest) {
        if ($dest ne $ARGV[0]) { next; }
        push(@bases,$dest);
        last;
    }
    if (! @bases){
        print "destination \"$ARGV[0]\" not found in $config\n";
        exit 2;
    }
} else {
    @bases = @dest;
}

my $string = quotemeta(lc($ARGV[1]));

foreach my $base (@bases){
    my @baselist = ();
    if (exists ($domains{$base})) {
        if (ref ($domains{$base})){
            push(@baselist,@{$domains{$base}});
        } else {
            push(@baselist,$domains{$base});
        }
    }
    if (exists ($urls{$base})) {
        if (ref ($urls{$base})){
            push(@baselist,@{$urls{$base}});
        } else {
            push(@baselist,$urls{$base});
        }
    }    
    if (! @baselist){
        print "empty url/domain lists for base $base.. skip\n";
        next;
    }
    
    foreach my $curbase (@baselist) {
        unless ( tie(%db, "DB_File", $dbdir."/".$curbase.".db", O_RDONLY, 0664, $DB_BTREE) ) {
            print "Skip $base: $!\n";
            next;
        }
        foreach my $key (keys %db){
            if ($key =~ /^\./) {
                $key =~ s/^\.//;
            }
            if ($key =~ /$string/){
                $entries++;
                $output .= "$curbase\t: $key\n";
            }
        }
        untie %db;
    }
}

if ($output) {
    print $output;
    print "\nFound $entries entries (time elapsed: ". tv_interval ($nowTime) ." sec.)\n";
} else {
    print "Sorry, no entries found for \"$ARGV[1]\"\n";
}

sub parseConf () {
    my $dest;
    open(CONF,$config) || die "can't open $config: $!\n";
    while (<CONF>) {
        unless (/^\s*dbhome\s+(\S+)/) { next; }
        $dbdir = $1;
        last;
    }
    while (<CONF>) {
        unless (/^\s*dest\s+(\S+)/) { next; }
        $dest = $1;
        push (@dest,$dest);
        while (<CONF>) {
            if (/^\s*domainlist\s+(\S+)/) {
                if (exists ($domains{$dest})){
                    $domains{$dest} = [ $domains{$dest},$1 ];
                } else {
                    $domains{$dest} = $1;
                }
            } elsif (/^\s*urllist\s+(\S+)/) {
                if (exists ($urls{$dest})){
                    $urls{$dest} = [ $urls{$dest},$1 ];
                } else {
                    $urls{$dest} = $1;
                }
            } elsif (/\}/) {
                last;
            }
        }
    }
    close(CONF);
}

sub usage() {
return <<EOF;
sg-search - script for searching entries in squidGuard blacklists bases.
            Note! you must have read access to .db files and squidGuard.conf.
            In most cases you dont need root privileges, use
            sudo -u squid sg-search <params> -- this will be enough.

usage:
    sg-search <dest|ALL> string

    dest   - name of destination base (such as "ads", "porn", etc..)
    ALL    - search in all destinations
    string - substring to find
EOF
}
