#!/usr/bin/perl -w
use XML::Parser;
use Text::Iconv;
  
require "/etc/squid/redirector/dbl/dbl.conf";

  ## Init some vars
   %files=();
   $converter = Text::Iconv->new("UTF-8","KOI8-R"); #or windows-1251
   %members=();
   %member_block=();
   $member_block_flag=0;
   %rule=();
   $trust=0;

  ## Set handlers for xml parser
   my $parser= XML::Parser->new(Handlers=>{
	    Start=> \&elem_start,
	    End  => \&elem_end,
	    Char => \&char_data});

  ## Parse input
    $filename=shift @ARGV or die "Use $0 file.dbl\n";
    chomp ($filename);
    open(IN, "cat $filename | gzip -d |");
    $parser->parse(*IN);
    close(IN);

  ## Close files    
    foreach $file (keys %files)
    {
     close($files{$file});
    }

  ## Sort, uniq, delete
    foreach $file (keys %files)
    {
     if ($file=~/^-/) {next;}
     @list=();
     %del=();

     delete($files{"$file"});     
     ## Read del file if exists
     if (exists($files{"-$file"}))
        {
	
	 open (DEL,"<$dir/lists/-$file") or die "Can't open $dir/lists/-$file: $!\n";
	 while (<DEL>)
	 {
	  chomp ();
	  $del{$_}=1;
	 }
	 close(DEL);
	 unlink("$dir/lists/-$file");
	 delete($files{"-$file"});
	}
	
     ## Read data file
	 open (DTA,"<$dir/lists/$file") or die "Can't open $dir/lists/$file: $!\n";
	 while (<DTA>)
	 {
	  chomp ();
	  push(@list,$_);
	 }
	 close (DTA);
    
    
     ## Sort, uniq, del & write to temp file
     $old="";
     open (DTA,">$dir/lists/${file}") or die "Can't open $dir/lists/$file: $!\n";
     foreach $line (sort @list)
     {
      if ($old eq $line) {next;}
      if (exists($del{$line})) {next;}
      $old=$line;
      print DTA "$line\n";
     }
     close (DTA);
    }

 ## Sort, uniq, delete remaining files
    foreach $file (keys %files)
    {
     $file=~s/^-//;
     @list=();
     %del=();

     ## Read del file if exists
     if (exists($files{"-$file"}))
        {
	 open (DEL,"<$dir/lists/-$file") or die "Can't open $dir/lists/-$file: $!\n";
	 while (<DEL>)
	 {
	  chomp ();
	  $del{$_}=1;
	 }
	 close(DEL);
	 unlink("$dir/lists/-$file");
	}
	
     ## Read data file
	 open (DTA,"<$dir/lists/$file") or die "Can't open $dir/lists/$file: $!\n";
	 while (<DTA>)
	 {
	  chomp ();
	  push(@list,$_);
	 }
	 close (DTA);
    
    
     ## Sort, uniq, del & write to temp file
     $old="";
     open (DTA,">$dir/lists/${file}") or die "Can't open $dir/lists/$file: $!\n";
     foreach $line (sort @list)
     {
      if ($old eq $line) {next;}
      if (exists($del{$line})) {next;}
      $old=$line;
      print DTA "$line\n";
     }
     close (DTA);
    }

   exit;
 
  ## Element start handler
    sub elem_start
     {
      my ($expat,$name,%attr)=@_;

      if ($name eq "member")
         {
	  %member_block=();
	  $member_block_flag=1;
	  return(0);
         }

      if ($name eq "record")
         {
	  %rule=();
	  $trust=0;
	  return(0);
         }
	 
      if ($name eq "add" or $name eq "check")
         {
          $calc_flag=1;
          %calc=();
          return(0);
         }
				 
      $option=$name;
     }
 
    ## Element end handler
     sub elem_end
     {
      my ($expat,$name)=@_;
  
      if ($name eq "member")
      {
       if (exists($member_block{"name"}) && exists($member_block{"trust"}))
          {
	    ## Users trust modifications
            if ($member_block{"name"} eq $my_nick) {$member_block{"trust"}+=9999999999999;}

	    foreach (@good_guys)
	     {if ($_ eq $member_block{"name"}) {$member_block{"trust"}+=999999;}}

	    foreach (@bad_guys)
	     {if ($_ eq $member_block{"name"}) {$member_block{"trust"}=0;}}

	   ## Add member to list
	   $members{$member_block{"name"}}=$member_block{"trust"};
	  }
       $member_block_flag=0;
       return(0);
      }
  
    if ($name eq "check" or $name eq "add")
       {

	$calc_flag=0;
	if (exists($calc{"answer"}) && $calc{"answer"} eq "No")
	   {$trust-=$members{$calc{"user"}};}
	else 
	   {$trust+=$members{$calc{"user"}};}
	return(0);
       }
       
       
    if ($name eq "record")
    {  
       if ( $trust>=$min_trust)
       {	
         add($rule{"group"},$converter->convert($rule{"rule"}));
       }
       else
       {
         del($rule{"group"},$converter->convert($rule{"rule"}));
       }
	 return(0);       
     }
     $option="null";
   } 
 
  ## Char data handler
    sub char_data
    {
      my ($expat,$text)=@_;
      if ($option eq "null") {return(0);}
      if ($member_block_flag==1) {$member_block{$option}.=$text;}
      if ($calc_flag) {$calc{$option}.=$text;}
      else {$rule{$option}.=$text;}
    }
  
  sub add
  {
   my $group=$_[0];
   my $rule=$_[1];

   unless (exists($files{$group}))
    {
     open ($files{$group}, ">>$dir/lists/$group") or die "Can't make file $dir/lists/$group: $!\n";
    }
	 
   print {$files{$group}} "$rule\n";
  }
  
  sub del
  {
   my $group="-".$_[0];
   my $rule=$_[1];

   unless (exists($files{$group}))
    {
     open ($files{$group}, ">>$dir/lists/$group") or die "Can't make file $dir/lists/$group: $!\n";
    }
	 
   print {$files{$group}} "$rule\n";

  }
   
