#!/usr/ug/bin/perl5
#			vim:fo=croql:cin:com=\:#
#
# killfiling gsubrc, mark I
# jtr@ugcs.caltech.edu

use strict;
use POSIX qw(strftime);

# gale info
use vars qw($CONTENT $PING $FROM $ENC $CAT $SIGN $TIME @MESSAGE $AGENT);

# misc
use vars qw($GALE $HOME);

# formatting
use vars qw($BON $BOFF $CEOL);

# killinfo
use vars qw(%killpeople @killcats %polluted %gvars);

$BON=`tput bold`;
$BOFF=`tput sgr0`;       
$CEOL= `tput el`;
$FROM= $ENV{'HEADER_FROM'};
$TIME= $ENV{'HEADER_TIME'};
$AGENT= $ENV{'HEADER_AGENT'};
$PING= $ENV{'HEADER_RECEIPT_TO'};
$CAT= $ENV{'GALE_CATEGORY'};
$CAT =~ s-zephyr/message-zephyr/MESSAGE-gi;
$ENC= $ENV{'GALE_ENCRYPTED'};
$SIGN= $ENV{'GALE_SIGNED'};
$CONTENT= $ENV{'HEADER_CONTENT_TYPE'};
$HOME= $ENV{'HOME'};
$GALE= $HOME . "/.gale/";


@MESSAGE= <>;


#
# main handler
#


&logit;
&mkKillfile;

system('/bin/env > ' . $HOME . '/.galevars');

if ($CAT =~ m-^notice/-)		{ &printNotice(@MESSAGE); }
elsif ($CAT =~ m-^receipt/-)	{ &printReceipt(@MESSAGE); }
else {
	my $res= &chkkill;
	$gvars{'nummsg'}= 0 if !defined($gvars{'nummsg'});
	$gvars{'numkilled'}= 0 if !defined($gvars{'numkilled'});
	$gvars{'nummsg'}++;
	if (!$res) {
		&printMessage(@MESSAGE);
	}
	else {
		&printKilledHeader($res);
		$gvars{'numkilled'}++;
	}
}

&svKillFile;




# 
# log information about recent messages
#

sub logit {
	if (open(LOG, "$GALE/glog")) {
		my @lines= <LOG>;
		my $FRUM= $SIGN if defined($SIGN);
		$FRUM= $FROM if !defined($SIGN);
		if ($FRUM =~ /@/) {
			$FRUM =~ s/^.*<(.*)@.*>.*$/$1/;
		} else {
			$FRUM= `ypcat passwd | grep "$FRUM" | head -1`;
			$FRUM =~ s/:.*$//;
			chop($FRUM);
		}
		$FRUM =~ s/\t/ /g;
		push @lines, "$CAT\t$FRUM\t$TIME\n";
		close(LOG);
		open(LOG, ">$GALE/glog") || die "can't write to thingy";
		my $i= $#lines - 100;
		$i= 0 if $i < 0;
		for (; $i <= $#lines; $i++) {
			print LOG $lines[$i];
		}
		close(LOG);
	}
}


#
# formatting
#

sub center {
	my($str, $bold)= @_;

	print "\r", ' ' x (40 - length($str) / 2);
	print $BON if ($bold);
	print $str;
	print $BOFF if ($bold);
	print "$CEOL\n";
}


sub printKilledHeader {
	my ($res)= @_;
	if ($gvars{'showkillshit'}) {
		my $name= $FROM;
		$name =~ s/ <.*>//;
		print "\r$res KILLED: [$BON$CAT$BOFF] from $BON$name$BOFF$CEOL\n";
		print "\r\tencrypted: $BON$ENC$BOFF$CEOL\n" if defined($ENC);
		print "\r";
	}
}


sub printNotice {
	print $BON;
	print "* " if defined($SIGN);
	my $C= $CAT;
	$C =~ s-notice/[^/]*/[^/]*/([^/]*)-$1-;
	print "$C: ";
	print "$AGENT on ";
	print strftime("%a %T", localtime($TIME)), "$BOFF$CEOL\n\r";
}

sub printReceipt {
	print $BON;
	print "* " if defined($SIGN);
	print "receipt: ";
	print "$AGENT at ";
	print strftime("%a %T", localtime($TIME)), "$BOFF$CEOL\n\r";
}

sub printMessage {
	my @MESSAGE= @_;
	&printHeader;

	open(FMT, "|fmt") || die "can't fmt, meh.";
	my $line;
	foreach $line (@MESSAGE) {
		chop $line;
		$line =~ s/[^ -~\s]+//g;
		if ($CONTENT =~ /xml/) {
			$line =~ s-<B>-$BON-g;
			$line =~ s-</B>-$BOFF-g;
		}
		print FMT "$line\n";
#print FMT "\r$line$CEOL\n";
	}
	close FMT;

	if (defined($SIGN) || defined($ENC)) {
		my $enc= '-- ';
		$enc .= "signed: $SIGN" if defined($SIGN);
		$enc .= " / " if (defined($SIGN) && defined($ENC));
		$enc .= "encrypted: $ENC" if defined($ENC);
		$enc .= ' --';

		&center($enc, 1);
	}


	print "\a" if defined($ENC);
	print "\r$CEOL\n$CEOL\r";
}


sub printHeader {
	my $name= $FROM;
	$name =~ s/ <.*>//;
	print "\r";
	print "+" if defined($PING);
	print "[$BON$CAT$BOFF] from $BON$name$BOFF";
	print strftime(" %a %T", localtime($TIME)), "$CEOL\n";
}



#
# killfile
#

sub mkKillfile {
	if (! -f "$GALE.gkill") {
		system("/bin/touch", "$GALE.gkill");
	}
	open(KILL, $GALE . "gkill") || die "can't open killfile";
	while (<KILL>) {
		if (!/^\s*$/ && !/^\s*#.*$/) {
			my @entry= split(/\s+/, $_);
			if ($entry[0] eq 'dipshit') {
				$killpeople{$entry[1]}= $entry[2];
			}
			elsif ($entry[0] eq 'category') {
				$entry[1] =~ s-\$Z-zephyr/MESSAGE/-;
				push @killcats, $entry[1];
			}
			elsif ($entry[0] eq 'polluted') {
				$polluted{$entry[1]}= $entry[2];
			}
			else {
				$gvars{$entry[0]}= $entry[1];
			}
		}
	}
	close KILL;
	&expireNukes;
}



sub chkkill {
	my $addr;
	if (defined($SIGN)) {
		$addr= $SIGN;
	} else {
		$addr= $FROM;
	}
	$addr =~ s/^.*<(.*)>.*$/\1/;
	$addr =~ s/@.*//;
	my $badcat;
	return 0 if defined($ENC);
	foreach $badcat (@killcats) {
		return 2 if eval $CAT =~ /$badcat/i;
	}
	return 3 if defined($polluted{$CAT});
	if (defined($killpeople{$addr})) {
		if ($killpeople{$addr} eq 'nuke') {
			&nukeInstance;
			return 4;
		}
		return 1;
	}
	return 0;
}


sub svKillFile {
	open(GK, ">$GALE/gkill") || die "can't write to killfile";

	my $f;
	foreach $f (keys %killpeople) {
		print GK "dipshit $f ", $killpeople{$f}, "\n";
	}
	foreach $f (@killcats) {
		print GK "category $f", "\n";
	}
	foreach $f (keys %polluted) {
		print GK "polluted $f ", $polluted{$f}, "\n";
	}
	foreach $f (keys %gvars) {
		print GK "$f ", $gvars{$f}, "\n";
	}
	close GK;
}



sub nukeInstance {
	my $len= 3600;
	my $now= time;
	my $expiretime= $now + $len;
	$polluted{$CAT}= $expiretime;
}

sub expireNukes {
	my $key;
	foreach $key (keys %polluted) {
		delete $polluted{$key} if ($polluted{$key} < time);
	}
}
