###########################################################################
### $Id: //depot/personal/ryan/main/src/wham/lib/wham.pm#5 $
###########################################################################
###
###########################################################################
my( $BINDIR, $LIBDIR, $CGIDIR, $CONFDIR);

use FindBin '$RealBin';                             # locate libraries
BEGIN {
$BINDIR="$RealBin/../bin";
$LIBDIR="$RealBin/../lib";
$CGIDIR="$RealBin/../cgi-bin";
$CONFDIR="$RealBin/../etc";
}

use lib "$LIBDIR";

package wham;

use strict;

my( %config, @black, @white);

### Export everything we need
use vars qw(@ISA @EXPORT @EXPORT_OK);
require      Exporter;
@ISA       = qw(Exporter);
@EXPORT    = qw(ReadList LoadConfig AddToList LogDate IsWhite IsBlack
		GrokMessage ProcessMail);
@EXPORT_OK = @EXPORT;

###########################################################################
### %config = &LoadConfig( $config_file);
###########################################################################
### load in configuration data from the specified config file
###########################################################################
sub LoadConfig
{
	my( $config) = @_;
	my( $home, @pw);

	@pw = getpwuid($<);
	$home = $pw[7];

	if( !defined( $config))
	{
		$config = $home . "/.whamrc";
		if( ! (-f $config)) {
		  $config = $CONFDIR . "/wham.conf";
		}
	}

	$config{black}  = $home . "/.blacklist";
	$config{white}  = $home . "/.whitelist";
	$config{spam}   = $home . "/mail/spam";
	$config{release}   = $home . "/mail/release";

	### Set up config options
	die "ERROR: could not find config file '$config'.\n" unless( -f $config);
	eval {
		use vars qw( $black $white $spam $release $template);
		require $config;
		$config{black}    = $black    if( defined( $black));
		$config{white}    = $white    if( defined( $white));
		$config{spam}     = $spam     if( defined( $spam));
		$config{release}  = $release  if( defined( $release));
		$config{template} = $template if( defined( $template));
	};

#	print $config{spam}, "\n";

	return( %config);
}

###########################################################################
### @LIST = &ReadList( $file);
###########################################################################
###
###########################################################################
sub ReadList
{
	my( $file) = @_;
	my( $line, @ret);

	@ret = ();
	open( FILE, "<$file") || die "ERROR: could not open '$file'\n";
	while( defined( $line = <FILE>))
	{
		chomp( $line);
		$line =~ s/#.*//;
		$line =~ s/^\s+//;
		$line =~ s/\s+$//;
		next if( $line =~ /^\s*$/);
		#print "checking $line\n";
		if( !IsValidRegExp($line)) {
		  print "WARNING: skipping invalid regexp '$line'\n";
		  next;
		}
		push( @ret, $line);
	}
	close( FILE);

	return @ret;
}

###########################################################################
###
###########################################################################
###
###########################################################################
sub IsWhite
{
	my( $addr) = @_;
	my( $filter);

#print ")))))))))))$addr(\n";

	@white = &ReadList( $config{"white"});# unless( defined( @white));
	foreach $filter( @white)
	{
#		print "$filter\n";
		return $filter if( $addr =~ /$filter/i);
	}
	return undef;
}

###########################################################################
###
###########################################################################
###
###########################################################################
sub IsBlack
{
	my( $addr) = @_;
	my( $filter);

#print ")))))))))))$addr(\n";

	@black = &ReadList( $config{"black"});# unless( defined( @black));
	foreach $filter( @black)
	{
#		print "$filter\n";
		return $filter if( $addr =~ /$filter/i);
	}
	return undef;
}

###########################################################################
### &AddToList( $file, $comment, @addrs);
###########################################################################
###
###########################################################################
sub AddToList
{
	my( $list, $comment, @addrs) = @_;
	my( $file, $line);

	if( $list eq "black")
	{
		$file = $config{"black"};
	} elsif( $list eq "white") {
		$file = $config{"white"};
	} else {
		return "ERROR: unknown list '$list'\n";
	}

	open( FILE, ">>$file") || return "ERROR: could not append to '$file'\n";
	foreach $line (@addrs)
	{
		chomp( $line);

		if( !IsValidRegExp( $line)) {
		  print "WARNING: skipping invalid regexp '$line'\n";
		  next;
		}
		#print $line, "\n";
		if( defined( $comment))
		{
			printf( FILE "%-30s # %-20s %s", $line, $comment, &LogDate());
		} else {
			print FILE $line;
		}
		print FILE"\n";
	}
	close( FILE);
	return "";
}

###########################################################################
### $string = &LogDate();
###########################################################################
### pretty print the date
###########################################################################
sub LogDate
{
	my($t) = @_;
	my ($sec,$min,$hour,$mday,$mon,$year);


	$t = time if( !defined($t));
	($sec,$min,$hour,$mday,$mon,$year) = localtime ($t);

	return sprintf ("%02d/%02d/%02d %02d:%02d",
		$mon + 1, $mday, $year + 1900, $hour, $min);
}

###########################################################################
### @addrs = &GrokMessage();
###########################################################################
### Grab the from addr from a message
###########################################################################
sub GrokMessage() {

  my( $fh) = @_;
  my( $line, $type, $From);

  $type="";
  while( defined( $line = <$fh>)) {
    ### end of headers
    last if( $line =~ /^\s*$/);

    if( $line =~ /^([^:     ]+):/) {
      $type = $1;
      #print STDERR "tyep: $type\n";
    }

    if( $type =~ /From/i) {
      if( $line =~ /^(From:)?\s*(.*)/i) {
	$From = Mail::Field->new('From', $2);
	my @addrs = $From->addresses;
	for( my $i=0; $i<=$#addrs; $i++) {
	  $addrs[$i] = quotemeta( $addrs[$i]);
	}
	return(@addrs)
      }
    } 
  }
}

###########################################################################
### &ProcessMail( $procrc);
###########################################################################
### Processes all spam throught the procrc file specified
###########################################################################
sub ProcessMail($) {
  my( $procrc) = @_;
  my( $cmd, $line);

  rename( $config{spam}, $config{spam} . ".tmp");

  $cmd = "/usr/bin/formail -s /usr/bin/procmail /tmp/procmailrc.wham.$$ < $config{spam}.tmp";
  print scalar localtime, "<BR>\n";
  print $cmd;
  open( CMD, "$cmd|") || die "ERROR: could not execute '$cmd' : $!\n";
  while( defined( $line = <CMD>)) {
    print "$line";
  }
  close( CMD);
  print "<BR>\n";
  print scalar localtime, "<BR>\n";
  die "ERROR: '$cmd' exited with : $?\n" if( $? != 0);

  unlink( $config{spam} . ".tmp");
  unlink( "/tmp/procmailrc.wham.$$");
}

###########################################################################
### if( !IsValidRegExp( $re)) { die;}
###########################################################################
###
###########################################################################
sub IsValidRegExp {
  my( $re) = (@_);

  my $tmp = "";
  eval {$tmp =~ /$re/};
  if( $@ ne "") {
    print "WARNING: invalid regexp '$re'\n";
    return 0;
  } else {
    return 1;
  }
}
1;
