#!/usr/bin/perl -w

use strict;
use HTML::Strip;
use CGI;

my $SCRIPT = "/cgi-bin/spasm.cgi";

my $MSIE = $ENV{HTTP_USER_AGENT} =~ /MSIE/;

my $SPASM_LOG_DIR = "/etc/mail/spasm/logs";
my $SPASM_QUARANTINE_DIR = "/etc/mail/spasm/quarantine";
my $SPASM_BIN_DIR = "/var/www/bin/spasm";
my $SENDMAIL_PATH = "/usr/sbin/sendmail";
my $DEFAULT_DOMAIN = "theasylum.org";

my @SF = (
  "USE_LOGGING",
  "USE_SUBJECT_TAGGING",
  "SF_VIRUS_SCAN",
  "SF_WHITELIST_ONLY",
  "SF_PERSONAL_BLACKLIST",
  "SF_SPAMTRAP",
  "SF_LOCALFILTER",
  "SF_RDNS",
  "SF_HELO",
  "SF_MAIL_HOST",
  "SF_SPAMASSASSIN",
  "SA_REQUIRED_HITS",
  "SF_ORDB",
  "SF_DSBL",
  "SF_SPAMCOP",
  "SF_SBL",
  "SF_SORBS",
  "SF_POSTMASTERRFC",
  "SF_DSNRFC",
  "SF_ABUSERFC",
  "SF_WHOISRFC",
  "SF_IPWHOISRFC",
  "SF_KOREABLACKHOLES",
  "SF_CHINABLACKHOLES",
  "SF_BRAZILBLACKHOLES",
  "SF_JAPANBLACKHOLES",
  "SF_TAIWANBLACKHOLES",
  "SF_VERIOBLACKHOLES",
  "SF_VALUEWEBBLACKHOLES",
  "SF_RACKSPACEBLACKHOLES",
  "SF_INFLOWBLACKHOLES",
  "SF_BROADWINGBLACKHOLES",
  "SF_XOBLACKHOLES",
  "SF_ELIBLACKHOLES",
  "SF_ARGENTINABLACKHOLES",
  "SF_NIGERIABLACKHOLES",
  "SF_RUSSIABLACKHOLES",
  "SF_SINGAPOREBLACKHOLES",
  "SF_THAILANDBLACKHOLES",
  "SF_CIBERLYNXBLACKHOLES",
  "SF_CWBLACKHOLES",
  "SF_EPOCHBLACKHOLES",
  "SF_HEBLACKHOLES",
  "SF_INTERNAPBLACKHOLES",
  "SF_LEVEL3BLACKHOLES",
  "SF_RRBLACKHOLES",
  "SF_SKYNETWEBBLACKHOLES",
  "SF_WANADOOFRBLACKHOLES",
);

my @FILTERGROUP = (
  "Off",
  "Low",
  "Medium",
  "High",
  "All",
  "Custom"
);

my %FG_LOW = (
  "USE_LOGGING", 2,
  "USE_SUBJECT_TAGGING", 0,
  "SF_VIRUS_SCAN", 2,
  "SF_WHITELIST_ONLY", 0,
  "SF_PERSONAL_BLACKLIST", 2,
  "SF_SPAMTRAP", 0,
  "SF_LOCALFILTER", 0,
  "SF_RDNS", 0,
  "SF_HELO", 0,
  "SF_MAIL_HOST", 0,
  "SF_SPAMASSASSIN", 0,
  "SA_REQUIRED_HITS", 5,
  "SF_ORDB", 2,
  "SF_DSBL", 2,
  "SF_SPAMCOP", 0,
  "SF_SBL", 2,
  "SF_SORBS", 2,
  "SF_POSTMASTERRFC", 0,
  "SF_DSNRFC", 0,
  "SF_ABUSERFC", 0,
  "SF_WHOISRFC", 0,
  "SF_IPWHOISRFC", 0,
  "SF_KOREABLACKHOLES", 0,
  "SF_CHINABLACKHOLES", 0,
  "SF_BRAZILBLACKHOLES", 0,
  "SF_JAPANBLACKHOLES", 0,
  "SF_TAIWANBLACKHOLES", 0,
  "SF_VERIOBLACKHOLES", 0,
  "SF_VALUEWEBBLACKHOLES", 0,
  "SF_RACKSPACEBLACKHOLES", 0,
  "SF_INFLOWBLACKHOLES", 0,
  "SF_BROADWINGBLACKHOLES", 0,
  "SF_XOBLACKHOLES", 0,
  "SF_ELIBLACKHOLES", 0,
  "SF_ARGENTINABLACKHOLES", 0,
  "SF_NIGERIABLACKHOLES", 0,
  "SF_RUSSIABLACKHOLES", 0,
  "SF_SINGAPOREBLACKHOLES", 0,
  "SF_THAILANDBLACKHOLES", 0,
  "SF_CIBERLYNXBLACKHOLES", 0,
  "SF_CWBLACKHOLES", 0,
  "SF_EPOCHBLACKHOLES", 0,
  "SF_HEBLACKHOLES", 0,
  "SF_INTERNAPBLACKHOLES", 0,
  "SF_LEVEL3BLACKHOLES", 0,
  "SF_RRBLACKHOLES", 0,
  "SF_SKYNETWEBBLACKHOLES", 0,
  "SF_WANADOOFRBLACKHOLES", 0
);

my %FG_MED = (
  "USE_LOGGING", 2,
  "USE_SUBJECT_TAGGING", 0,
  "SF_VIRUS_SCAN", 2,
  "SF_WHITELIST_ONLY", 0,
  "SF_PERSONAL_BLACKLIST", 2,
  "SF_SPAMTRAP", 2,
  "SF_LOCALFILTER", 2,
  "SF_RDNS", 0,
  "SF_HELO", 0,
  "SF_MAIL_HOST", 0,
  "SF_SPAMASSASSIN", 2,
  "SA_REQUIRED_HITS", 5,
  "SF_ORDB", 2,
  "SF_DSBL", 2,
  "SF_SPAMCOP", 2,
  "SF_SBL", 2,
  "SF_SORBS", 2,
  "SF_POSTMASTERRFC", 0,
  "SF_DSNRFC", 0,
  "SF_ABUSERFC", 0,
  "SF_WHOISRFC", 0,
  "SF_IPWHOISRFC", 0,
  "SF_KOREABLACKHOLES", 0,
  "SF_CHINABLACKHOLES", 0,
  "SF_BRAZILBLACKHOLES", 0,
  "SF_JAPANBLACKHOLES", 0,
  "SF_TAIWANBLACKHOLES", 0,
  "SF_VERIOBLACKHOLES", 0,
  "SF_VALUEWEBBLACKHOLES", 0,
  "SF_RACKSPACEBLACKHOLES", 0,
  "SF_INFLOWBLACKHOLES", 0,
  "SF_BROADWINGBLACKHOLES", 0,
  "SF_XOBLACKHOLES", 0,
  "SF_ELIBLACKHOLES", 0,
  "SF_ARGENTINABLACKHOLES", 0,
  "SF_NIGERIABLACKHOLES", 0,
  "SF_RUSSIABLACKHOLES", 0,
  "SF_SINGAPOREBLACKHOLES", 0,
  "SF_THAILANDBLACKHOLES", 0,
  "SF_CIBERLYNXBLACKHOLES", 0,
  "SF_CWBLACKHOLES", 0,
  "SF_EPOCHBLACKHOLES", 0,
  "SF_HEBLACKHOLES", 0,
  "SF_INTERNAPBLACKHOLES", 0,
  "SF_LEVEL3BLACKHOLES", 0,
  "SF_RRBLACKHOLES", 0,
  "SF_SKYNETWEBBLACKHOLES", 0,
  "SF_WANADOOFRBLACKHOLES", 0
);

my %FG_HIGH = (
  "USE_LOGGING", 2,
  "USE_SUBJECT_TAGGING", 0,
  "SF_VIRUS_SCAN", 2,
  "SF_WHITELIST_ONLY", 0,
  "SF_PERSONAL_BLACKLIST", 2,
  "SF_SPAMTRAP", 2,
  "SF_LOCALFILTER", 2,
  "SF_RDNS", 2,
  "SF_HELO", 2,
  "SF_MAIL_HOST", 2,
  "SF_SPAMASSASSIN", 2,
  "SA_REQUIRED_HITS", 4,
  "SF_ORDB", 2,
  "SF_DSBL", 2,
  "SF_SPAMCOP", 2,
  "SF_SBL", 2,
  "SF_SORBS", 2,
  "SF_POSTMASTERRFC", 2,
  "SF_DSNRFC", 2,
  "SF_ABUSERFC", 2,
  "SF_WHOISRFC", 2,
  "SF_IPWHOISRFC", 2,
  "SF_KOREABLACKHOLES", 0,
  "SF_CHINABLACKHOLES", 0,
  "SF_BRAZILBLACKHOLES", 0,
  "SF_JAPANBLACKHOLES", 0,
  "SF_TAIWANBLACKHOLES", 0,
  "SF_VERIOBLACKHOLES", 0,
  "SF_VALUEWEBBLACKHOLES", 0,
  "SF_RACKSPACEBLACKHOLES", 0,
  "SF_INFLOWBLACKHOLES", 0,
  "SF_BROADWINGBLACKHOLES", 0,
  "SF_XOBLACKHOLES", 0,
  "SF_ELIBLACKHOLES", 0,
  "SF_ARGENTINABLACKHOLES", 0,
  "SF_NIGERIABLACKHOLES", 0,
  "SF_RUSSIABLACKHOLES", 0,
  "SF_SINGAPOREBLACKHOLES", 0,
  "SF_THAILANDBLACKHOLES", 0,
  "SF_CIBERLYNXBLACKHOLES", 0,
  "SF_CWBLACKHOLES", 0,
  "SF_EPOCHBLACKHOLES", 0,
  "SF_HEBLACKHOLES", 0,
  "SF_INTERNAPBLACKHOLES", 0,
  "SF_LEVEL3BLACKHOLES", 0,
  "SF_RRBLACKHOLES", 0,
  "SF_SKYNETWEBBLACKHOLES", 0,
  "SF_WANADOOFRBLACKHOLES", 0
);

my $cgi;
my $username;
my $password;
my $submit;
my $viewbutton;
my $source;

$cgi = new CGI;

$username = $cgi->param('username')?$cgi->param('username'):"";
$password = $cgi->param('password')?$cgi->param('password'):"";
$submit = $cgi->param('submit')?$cgi->param('submit'):"";
$viewbutton = $cgi->param('viewbutton')?$cgi->param('viewbutton'):"";
$source = $cgi->param('source')?$cgi->param('source'):"";

unless($username and $password) { printLoginScreen(); exit; }

verifyLogin();	# Verifies username/password

if($submit eq "Login") { printMainMenu(); }

# Mail Filters Menu
elsif($submit eq "Mail Filters") { viewMailFilters(); }
elsif($submit eq "Update" and $source eq "viewMailFilters") { updateMailFilters(); }

# Log Menu
elsif($submit eq "View Log") { viewLog(); }
elsif($submit eq "View Selected Entries") { viewLogEntry(); }
elsif($submit eq "View All Entries") { viewAllLogEntries(); }
elsif($submit eq "Clear Log") { clearLog(); }
elsif($submit eq "Whitelist Selected Senders") { whitelistSenders(); }
elsif($submit eq "Blacklist Selected Senders") { blacklistSenders(); }

# Quarantine Menu
elsif($submit eq "View Quarantine") { viewQuarantine(); }
elsif($viewbutton) { viewQuarantineFile(); }
elsif($submit eq "View Full Headers" or $submit eq "View Standard Headers") { viewQuarantineFile(); }
elsif($submit eq "Delete Message" or $submit eq "Delete Selected Messages") { deleteQuarantineFile(); }
elsif($submit eq "Deliver Message") { deliverQuarantineFile(); }
elsif($submit eq "Blacklist Sender") { blacklistEntry(); }
elsif($submit eq "Blacklist Host") { blacklistEntry(); }
elsif($submit eq "Blacklist Server") { blacklistEntry(); }
elsif($submit eq "Whitelist Sender") { whitelistEntry(); }
elsif($submit eq "Whitelist Host") { whitelistEntry(); }
elsif($submit eq "Whitelist Server") { whitelistEntry(); }
elsif($submit eq "Delete All Messages") { clearQuarantine(); }

# Whitelist Menu
elsif($submit eq "Whitelist") { viewWhitelist(); }
elsif($submit eq "Update" and $source eq "viewWhitelist") { updateWhitelist(); }

# Blacklist Menu
elsif($submit eq "Blacklist") { viewBlacklist(); }
elsif($submit eq "Update" and $source eq "viewBlacklist") { updateBlacklist(); }

# Logout
elsif($submit eq "Logout") { printLoginScreen(); }
else { printError("Invalid submission"); }

sub verifyLogin {
    my $rc = system("$SPASM_BIN_DIR/authuser", $username, $password);
    if($rc != 0) {
        printError("Invalid username or password");
    }
}

sub viewLog {
    unless(-s "$SPASM_LOG_DIR/$username\@$DEFAULT_DOMAIN") {
        printHeader();
	printMenuBar();
        print <<EOF;
  <H1>Log Empty</H1>
EOF
	printFooter();
        exit;
    }
    open(IF, "<$SPASM_LOG_DIR/$username\@$DEFAULT_DOMAIN") or printError("Error opening logfile: $!");
    printHeader();
    printMenuBar();
    print <<EOF;
    <FORM action="$SCRIPT" method=POST>
    <input type=hidden name=username value="$username">
    <input type=hidden name=password value="$password">
    <input type=hidden name=source value="viewLog">
    <TABLE>
      <TR><TD align=center><input type=submit name=submit value="View Selected Entries"><TD align=center><input type=submit name=submit value="View All Entries"></TR>
      <TR><TD align=center><input type=submit name=submit value="Whitelist Selected Senders"><TD align=center><input type=submit name=submit value="Blacklist Selected Senders"></TR>
      <TR><TD align=center colspan=2><input type=submit name=submit value="Clear Log"></TR>
    </TABLE>
    <TABLE border=1>
      <TR><TH>&nbsp;<TH>Date<TH>Sender</TR>
EOF

    while(<IF>) {
	chomp $_;
	s/</&lt\;/g;
	my @fields = split(/:/, $_);
	print "<TR><TD align=center><input type=checkbox name=logentry value='$fields[0]'><TD>$fields[1]:$fields[2]:$fields[3]<TD align=center>$fields[5]</TR>\n";
    }
    close(IF);

    print <<EOF;
    </TABLE>
    </P>
    <TABLE>
      <TR><TD align=center><input type=submit name=submit value="View Selected Entries"><TD align=center><input type=submit name=submit value="View All Entries"></TR>
      <TR><TD align=center><input type=submit name=submit value="Whitelist Selected Senders"><TD align=center><input type=submit name=submit value="Blacklist Selected Senders"></TR>
      <TR><TD align=center colspan=2><input type=submit name=submit value="Clear Log"></TR>
    </TABLE>
    </FORM>
EOF
    printFooter();
}

sub clearLog {
    system "$SPASM_BIN_DIR/archivelog", "$username\@$DEFAULT_DOMAIN";
    printHeader();
    printMenuBar();
    print <<EOF;
    <H1>Log Cleared</H1>
EOF
    printFooter();
}

sub viewLogEntry {
    my @logEntries = $cgi->param('logentry')?$cgi->param('logentry'):();
    my %entries;
    for(@logEntries) { $entries{$_} = 1; }
    unless(@logEntries) { printError("No entries selected"); }
    open(IF, "<$SPASM_LOG_DIR/$username\@$DEFAULT_DOMAIN") or printError("Error opening logfile: $!");
    printHeader();
    printMenuBar();
    while(<IF>) {
	chomp;
	s/</&lt;/g;
	s/>/&gt;/g;
	my @fields = split(/:/, $_);
	if($entries{$fields[0]}) {
	    $fields[9] =~ s/\|/<br>/g;
	    print <<EOF;
    <TABLE border=1>
      <TR><TH>Date<TD align=center>$fields[1]:$fields[2]:$fields[3]</TR>
      <TR><TH>Sender<TD align=center>$fields[5]</TR>
      <TR><TH>Hostname<TD align=center>$fields[6]</TR>
      <TR><TH>Host IP<TD align=center>$fields[7]</TR>
      <TR><TH>Host HELO<TD align=center>$fields[8]</TR>
      <TR><TH>Filters<TD align=center>$fields[9]</TR>
    </TABLE>
    <P>&nbsp;<P>
EOF
	}
    }
    printFooter();
}

sub viewAllLogEntries {
    open(IF, "<$SPASM_LOG_DIR/$username\@$DEFAULT_DOMAIN") or printError("Error opening logfile: $!");
    printHeader();
    printMenuBar();
    while(<IF>) {
        chomp $_;
        s/</&lt;/g;
	s/>/&gt;/g;
        my @fields = split(/:/, $_);
        $fields[9] =~ s/\|/ - /g;
        for(1..3){chop $fields[9];}
        print <<EOF;
    <TABLE border=1>
      <TR><TH>Date<TD align=center>$fields[1]:$fields[2]:$fields[3]</TR>
      <TR><TH>Sender<TD align=center>$fields[5]</TR>
      <TR><TH>Hostname<TD align=center>$fields[6]</TR>
      <TR><TH> Host IP<TD align=center>$fields[7]</TR>
      <TR><TH>Host HELO<TD align=center>$fields[8]</TR>
      <TR><TH>Filters<TD align=center>$fields[9]</TR>
    </TABLE>
    <P>&nbsp;<P>
EOF
    }
    printFooter();
}

sub whitelistSenders {
    my @logEntries = $cgi->param('logentry')?$cgi->param('logentry'):();
    my %entries;
    for(@logEntries) { $entries{$_} = 1; }
    unless(@logEntries) { printError("No entries selected"); }
    open(IF, "<$SPASM_LOG_DIR/$username\@$DEFAULT_DOMAIN") or printError("Error opening logfile: $!");
    while(<IF>) {
        my @fields = split(/:/, $_);
	if($entries{$fields[0]}) {
	    `$SPASM_BIN_DIR/add_whitelist $username\@$DEFAULT_DOMAIN "$fields[5]"`;
	}
    }
    close(IF);
    printHeader();
    printMenuBar();
    print <<EOF;
    <H1>Senders Whitelisted</H1>
EOF
    printFooter();
}

sub blacklistSenders {
    my @logEntries = $cgi->param('logentry')?$cgi->param('logentry'):();
    my %entries;
    for(@logEntries) { $entries{$_} = 1; }
    unless(@logEntries) { printError("No entries selected"); }
    open(IF, "<$SPASM_LOG_DIR/$username\@$DEFAULT_DOMAIN") or printError("Error opening logfile: $!");
    while(<IF>) {
        my @fields = split(/:/, $_);
        if($entries{$fields[0]}) {
            `$SPASM_BIN_DIR/add_blacklist $username\@$DEFAULT_DOMAIN "$fields[5]"`;
        }
    }
    close(IF);
    printHeader();
    printMenuBar();
    print <<EOF;
    <H1>Senders Blacklisted</H1>
EOF
    printFooter();
}

sub viewQuarantine {
    unless(-d "$SPASM_QUARANTINE_DIR/$username\@$DEFAULT_DOMAIN") {
        printHeader();
        printMenuBar();
        print <<EOF;
  <H1>Quarantine is Empty</H1>
EOF
        printFooter();
        exit;
    }
    opendir(DIR, "$SPASM_QUARANTINE_DIR/$username\@$DEFAULT_DOMAIN") or
        printError("Unable to open quarantine directory: $!");

    printHeader();
    printMenuBar();
    print <<EOF;
    <FORM action=$SCRIPT method=POST>
    <input type=hidden name=username value='$username'>
    <input type=hidden name=password value='$password'>
    <input type=hidden name=source value='viewQuarantine'>
    <TABLE border=1>
      <TR><TH>Delete<TH>View<TH>Sender<TH>Subject</TR>
EOF

    while(my $file = readdir(DIR)) {
	my $sender = "";
	my $subject = "";
        if($file eq "." or $file eq "..") { next; }
	my @fstat = stat("$SPASM_QUARANTINE_DIR/$username\@$DEFAULT_DOMAIN/$file");
	if($fstat[7] == 0) {
	    next;
	}
        open(IF, "$SPASM_QUARANTINE_DIR/$username\@$DEFAULT_DOMAIN/$file") or
	    printError("Unable to open quarantine file: $!");;
        while(my $line = <IF>) {
            if($line =~ /^X-spasm-sender: (.+)$/) {
                $sender = $1;
		$sender =~ s/</&lt;/g;
            } elsif($line =~ /^Subject: (.+)$/i) {
                $subject = $1;
		$subject =~ s/</&lt;/g;
            }
	    if($sender and $subject) { last; }
        }
        close(IF);
	print "<TR><TD align=center><input type=checkbox name=qfile value='$file'>\n";
	if($MSIE) {
            # The losers at M$ can't write a proper <BUTTON> tag handler
            print "<TD align=center><input type=submit name=viewbutton value='$file'>\n";
        } else {
            print "<TD align=center><button type=submit name=viewbutton value='$file'>View</button>\n";
        }
	print "<TD>$sender<TD>$subject</TR>\n";
    }
    closedir(DIR);

    print <<EOF;
    </TABLE>
    <P>
    <center>
    <input type=submit name=submit value="Delete Selected Messages">
    <input type=submit name=submit value="Delete All Messages">
    </center>
    </FORM>
    <P>
    <center>
    </center>
EOF
    printFooter();
}

sub viewQuarantineFile {
    my $qfile = "";
    if($submit eq "View Full Headers" or $submit eq "View Standard Headers") {
	$qfile = $cgi->param('qfile')?$cgi->param('qfile'):"";
    } else {
        $qfile = $viewbutton;
    }
    unless($qfile) { printError("No message specified"); }
    my $sender = "";
    my $server = "";
    my $host = "";

    open(IF, "$SPASM_QUARANTINE_DIR/$username\@$DEFAULT_DOMAIN/$qfile") or
	printError("Error opening message file: $!");
    $/ = "\r\n\r\n";
    my $headers = <IF>;
    $headers =~ s/\r//g;
    $headers =~ s/</&lt;/g;
    $headers =~ s/>/&gt;/g;
    $headers =~ s/\n/<br>/g;
    undef $/;
    my $body = <IF>;
    close(IF);

    my $hs = HTML::Strip->new();
    my $bodyclean = $hs->parse($body);
    $hs->eof;

    $bodyclean =~ s/\r//g;
    $bodyclean =~ s/</&lt;/g;
    $bodyclean =~ s/>/&gt;/g;
    $bodyclean =~ s/\n/<br>/g;

    my $hdrButton;
    if($submit eq "View Full Headers") {
	$hdrButton = "View Standard Headers";
    } else {
	$hdrButton = "View Full Headers";
    }

    printHeader();
    printMenuBar();
    print <<EOF;
  <P style="font-size: 10pt;">
    <FORM action="$SCRIPT" method=POST>
      <input type=hidden name=username value="$username">
      <input type=hidden name=password value="$password">
      <input type=hidden name=qfile value="$qfile">
      <TABLE>
        <TR>
          <TD align=center>
            <input type=submit name=submit value="Delete Message">
            <input type=submit name=submit value="Deliver Message">
            <input type=submit name=submit value="$hdrButton">
        </TR>
        <TR>
          <TD align=center>
            <input type=submit name=submit value="Blacklist Sender">
	    <input type=submit name=submit value="Blacklist Server">
	    <input type=submit name=submit value="Blacklist Host">
	</TR>
	<TR>
	  <TD align=center>
            <input type=submit name=submit value="Whitelist Sender">
	    <input type=submit name=submit value="Whitelist Server">
	    <input type=submit name=submit value="Whitelist Host">
        </TR>
      </TABLE>
      <P>
EOF

    if($submit eq "View Full Headers") {
        print $headers;
	if($headers =~ /X-spasm-sender: (.+)</) { $sender = $1; }
	if($headers =~ /X-spasm-sender-IP: (.+)/) { $server = $1; }
	if($headers =~ /X-spasm-sender-host: [^\[].*?([^\.]+\.[^\.]+)/) { $host = $1; }
    } else {
        for my $header (split(/<br>/, $headers)) {
            if($header =~ /^From:/i or $header =~ /^To:/i or $header =~ /^Subject:/i or $header =~ /^Date:/i) {
                print "$header<br>";
            }
	    if($header =~ /^X-spasm-sender:/) {
		$header =~ s/^X-spasm-sender/Sender/;
		print "<br>";
		print "$header<br>";
		$header =~ /^Sender: (.*)$/;
		$sender = $1;
	    }
            if($header =~ /^X-spasm-sender-IP:/) {
                $header =~ s/^X-spasm-sender-IP/Server/;
                print "$header<br>";
		$header =~ /^Server: (.*)$/;
		$server = $1;
            }
	    if($header =~ /^X-spasm-sender-host: [^\[]/) {
		$header =~ s/^X-spasm-sender-host: .*?([^\.]+\.[^\.]+)$/Host: $1/;
		print "$header<br>";
		$host = $1;
	    }
        }
    }
    print "<BR><BR>";
    print $bodyclean;

    print <<EOF;
      <input type=hidden name=sender value="$sender">
      <input type=hidden name=server value="$server">
      <input type=hidden name=host value="$host">
    </FORM>
  </P>
EOF
    printFooter();
}

sub clearQuarantine {
    opendir(DIR, "$SPASM_QUARANTINE_DIR/$username\@$DEFAULT_DOMAIN");
    my @readdir = readdir(DIR);
    closedir(DIR);
    for my $qfile (@readdir) {
	if($qfile =~ /^\./) { next; }
	`$SPASM_BIN_DIR/delete_qfile $username\@$DEFAULT_DOMAIN $qfile`;
    }
    printHeader();
    printMenuBar();
    print <<EOF;
    <H1>Quarantine Cleared</H1>
EOF
    printFooter();
}

sub deleteQuarantineFile {
    my @qfile = $cgi->param('qfile')?$cgi->param('qfile'):();
    unless(@qfile) { printError("No message specified"); }
    for my $qfile (@qfile) {
        `$SPASM_BIN_DIR/delete_qfile $username\@$DEFAULT_DOMAIN $qfile`;
    }
    printHeader();
    printMenuBar();
    if(scalar(@qfile) > 1) {
	print "<H1>Messages Deleted</H1>";
    } else {
	print "<H1>Message Deleted</H1>";
    }
    printFooter();
}

sub deliverQuarantineFile {
    my $qfile = $cgi->param('qfile')?$cgi->param('qfile'):"";
    unless($qfile) { printError("No message specified"); }
    chdir("$SPASM_QUARANTINE_DIR/$username\@$DEFAULT_DOMAIN");
    open(IF, "$qfile") or printError("Error opening message file ($username\@$DEFAULT_DOMAIN/$qfile): $!");
    my $mailfrom = "";
    while(<IF>) {
	if(/X-spasm-sender: (\S+)/) {
	    $mailfrom = $1;
	}
	if(/X-spasm-sender:/ and !$mailfrom) {
	    $mailfrom = "<>";
	}
	if($mailfrom) { last; }
    }
    close(IF);
    unless($mailfrom) { printError("Error reading message sender"); }
    `$SENDMAIL_PATH -f"$mailfrom" -- "$username\@$DEFAULT_DOMAIN" < $SPASM_QUARANTINE_DIR/$username\@$DEFAULT_DOMAIN/$qfile`;
    `$SPASM_BIN_DIR/delete_qfile $username\@$DEFAULT_DOMAIN $qfile`;
    printHeader();
    printMenuBar();
    print <<EOF;
    <H1>Message Delivered</H1>
EOF
    printFooter();
}

sub blacklistEntry {
    my $entry = "";
    my $type = "";
    if($submit eq "Blacklist Sender") {
	my $sender = $cgi->param('sender')?$cgi->param('sender'):"";
	unless($sender) { printError("Error: Sender not found"); }
	$entry = $sender;
	$type = "Sender";
    }
    if($submit eq "Blacklist Host") {
	my $host = $cgi->param('host')?$cgi->param('host'):"";
	unless($host) { printError("Error: Host not found"); }
	$entry = $host;
	$type = "Host";
    }
    if($submit eq "Blacklist Server") {
	my $server = $cgi->param('server')?$cgi->param('server'):"";
	unless($server) { printError("Error: Server not found"); }
	$entry = $server;
	$type = "Server";
    }
    `$SPASM_BIN_DIR/add_blacklist $username\@$DEFAULT_DOMAIN "$entry"`;
    printHeader();
    printMenuBar();
    print <<EOF;
    <H1>$type $entry Blacklisted</H1>
EOF
    printFooter();
}

sub whitelistEntry {
    my $entry = "";
    my $type = "";
    if($submit eq "Whitelist Sender") {
        my $sender = $cgi->param('sender')?$cgi->param('sender'):"";
        unless($sender) { printError("Error: Sender not found"); }
        $entry = $sender;
        $type = "Sender";
    }
    if($submit eq "Whitelist Host") {
        my $host = $cgi->param('host')?$cgi->param('host'):"";
        unless($host) { printError("Error: Host not found"); }
        $entry = $host;
        $type = "Host";
    }
    if($submit eq "Whitelist Server") {
        my $server = $cgi->param('server')?$cgi->param('server'):"";
        unless($server) { printError("Error: Server not found"); }
        $entry = $server;
        $type = "Server";
    }
    `$SPASM_BIN_DIR/add_whitelist $username\@$DEFAULT_DOMAIN "$entry"`;
    printHeader();
    printMenuBar();
    print <<EOF;
    <H1>$type $entry Whitelisted</H1>
EOF
    printFooter();
}

sub viewMailFilters {
    printFilterHeader();
    printMenuBar();
    my %FSTATUS = ();
    my $FGROUP = 5;
    my $flag;
    for my $filter (@SF) {
	$FSTATUS{$filter} = `$SPASM_BIN_DIR/lookup_filter $username\@$DEFAULT_DOMAIN $filter`;
	chomp $FSTATUS{$filter};
    }
    print <<EOF;
    <FORM name=fForm action="$SCRIPT" method=POST>
      <input type=hidden name=username value="$username">
      <input type=hidden name=password value="$password">
      <input type=hidden name=source value="viewMailFilters">
      <H1>Basic Settings</H1>
      <P>
      <TABLE>
	<TR><TD>
EOF

    # Check for "Off" Setting
    $flag = 1;
    for(@SF) {
	if($_ eq "SA_REQUIRED_HITS") { next; }
	if($FSTATUS{$_} != 0) { $flag = 0; }
    }
    if($flag) { $FGROUP = 0; }

    # Check for "All" Setting
    $flag = 1;
    for(@SF) {
	if($_ eq "SA_REQUIRED_HITS") {
	    if($FSTATUS{$_} != 4) { $flag = 0; }
	    next;
	}
	if($_ eq "USE_SUBJECT_TAGGING") {
	    if($FSTATUS{$_} != 0) { $flag = 0; }
	    next;
	}
	if($_ eq "SF_WHITELIST_ONLY") {
	    if($FSTATUS{$_} != 0) { $flag = 0; }
	    next;
	}
	if($FSTATUS{$_} != 2) { $flag = 0; }
    }
    if($flag) { $FGROUP = 4; }

    # Check for "Low" Setting
    $flag = 1;
    for(@SF) {
	if($_ eq "SA_REQUIRED_HITS") { next; }
	if($FSTATUS{$_} != $FG_LOW{$_}) { $flag = 0; }
    }
    if($flag) { $FGROUP = 1; }

    # Check for "Medium" Setting
    $flag = 1;
    for(@SF) {
        if($FSTATUS{$_} != $FG_MED{$_}) { $flag = 0; }
    }
    if($flag) { $FGROUP = 2; }

    # Check for "High" Setting
    $flag = 1;
    for(@SF) {
        if($FSTATUS{$_} != $FG_HIGH{$_}) { $flag = 0; }
    }
    if($flag) { $FGROUP = 3; }

    for(0..5) {
	if($_ == $FGROUP) {
	    print "<input type=radio name=newfg value='$_' onClick='checkRadioButton(this.value)' checked>$FILTERGROUP[$_]\n";
	} else {
	    print "<input type=radio name=newfg value='$_' onClick='checkRadioButton(this.value)'>$FILTERGROUP[$_]\n";
	}
    }

    my $visibleCustom;
    if($FGROUP == 5) { $visibleCustom = "visible"; }
    else { $visibleCustom = "hidden"; }

    print <<EOF;
        </TR>
      </TABLE>
      <P>
      <TABLE>
        <TR><TD align=center><input type=submit name=submit value="Update"></TR>
      </TABLE>
      <SPAN Id="customTable" class="customTable" style="visibility: $visibleCustom;">
      <P>
      <H1>Custom Settings</H1>
      <P>
      <TABLE>
	<TR><TH>Filter<TH>Off<TH>Tag<TH>Quarantine<TH>Reject</TR>
EOF

    for my $filter (@SF) {
	my $fstatus = $FSTATUS{$filter};
        print "<TR>";
	print "<TD>$filter";
	if($filter eq "SA_REQUIRED_HITS") {
	    print "<TD><input type=text size=3 maxlength=3 name='SA_REQUIRED_HITS' value='$fstatus'>";
	} elsif($filter eq "USE_SUBJECT_TAGGING") {
	    if($fstatus == 0) {
		print "<TD align=center><input type=radio name=$filter value=\"0\" checked>";
		print "<TD align=center><input type=radio name=$filter value=\"1\">";
	    } else {
		print "<TD align=center><input type=radio name=$filter value=\"0\">";
		print "<TD align=center><input type=radio name=$filter value=\"1\" checked>";
	    }
	} elsif($fstatus == 0) {
	    print "<TD align=center><input type=radio name=$filter value=\"0\" checked>";
            print "<TD align=center><input type=radio name=$filter value=\"1\">";
            print "<TD align=center><input type=radio name=$filter value=\"2\">";
            print "<TD align=center><input type=radio name=$filter value=\"3\">";
        } elsif($fstatus == 1) {
	    print "<TD align=center><input type=radio name=$filter value=\"0\">";
	    print "<TD align=center><input type=radio name=$filter value=\"1\" checked>";
	    print "<TD align=center><input type=radio name=$filter value=\"2\">";
	    print "<TD align=center><input type=radio name=$filter value=\"3\">";
	} elsif($fstatus == 2) {
	    print "<TD align=center><input type=radio name=$filter value=\"0\">";
            print "<TD align=center><input type=radio name=$filter value=\"1\">";
            print "<TD align=center><input type=radio name=$filter value=\"2\" checked>";
            print "<TD align=center><input type=radio name=$filter value=\"3\">";
        } elsif($fstatus == 3) {
	    print "<TD align=center><input type=radio name=$filter value=\"0\">";
            print "<TD align=center><input type=radio name=$filter value=\"1\">";
            print "<TD align=center><input type=radio name=$filter value=\"2\">";
            print "<TD align=center><input type=radio name=$filter value=\"3\" checked>";
        } else { warn "Unexpected fstatus: $fstatus\n"; }
	print "</TR>\n";
    }

    print <<EOF;
      </TABLE>
      <P>
      <TABLE>
        <TR><TD align=center><input type=submit name=submit value="Update"></TR>
      </TABLE>
      </SPAN>
    </FORM>
EOF
    printFooter();
}

sub updateMailFilters {
    for my $filter(@SF) {
	my $fstatus = $cgi->param($filter)?$cgi->param($filter):0;
	`$SPASM_BIN_DIR/set_filter $username\@$DEFAULT_DOMAIN $filter $fstatus`;
    }
    printHeader();
    printMenuBar();
    print <<EOF;
    <H1>Mail Filters Updated</H1>
EOF
    printFooter();
}

sub sortRoutine {
    my $c = $a;
    my $d = $b;
    chomp $c;
    chomp $d;
    $c =~ s/\s*\/\/.*$//;
    $d =~ s/\s*\/\/.*$//;
    if($c =~ /^[\d\.\/]+$/ and $d =~ /^[\d\.\/]+$/) {
	$c =~ s/\/.*//;
	$d =~ s/\/.*//;
	my $e = unpack("N", pack("C4", split(/\./,$c)));
	my $f = unpack("N", pack("C4", split(/\./,$d)));
	$e <=> $f;
    }
    elsif($c =~ /@/ or $d =~ /@/) {
	$c =~ s/^.+?@//;
	$d =~ s/^.+?@//;
	$c cmp $d;
    }
    else {
	$c cmp $d;
    }
}

sub viewWhitelist {
    my @whitelist = `$SPASM_BIN_DIR/get_whitelist $username\@$DEFAULT_DOMAIN`;
    my $whitelist = join('', sort sortRoutine @whitelist);
    printHeader();
    printMenuBar();
    print <<EOF;
    <FORM action="$SCRIPT" method=POST>
      <input type=hidden name=username value="$username">
      <input type=hidden name=password value="$password">
      <input type=hidden name=source value="viewWhitelist">
      <center>
        Whitelists are one entry per line, and may be an email address, domain name, classful<br>
	netblock (e.g, 10, 10.1, 10.1.2, 10.1.2.3), or CIDR address (e.g, 10.1.2.0/25).<br>
        <textarea name=whitelist cols=40 rows=20 wrap=off>$whitelist</textarea><br>
        <input type=submit name=submit value="Update">
      </center>
    </FORM>
EOF
    printFooter();
}

sub updateWhitelist {
    my $whitelist = $cgi->param('whitelist')?$cgi->param('whitelist'):"";
    open(PIPE, "|$SPASM_BIN_DIR/set_whitelist $username\@$DEFAULT_DOMAIN");
    for my $wl (split(/[\n|\r]/, $whitelist)) {
	$wl =~ s/[\n|\r]//g;
	next unless $wl;
	$wl =~ tr/A-Z/a-z/;
	print PIPE "$wl\n";
    }
    close(PIPE);

    printHeader();
    printMenuBar();
    print <<EOF;
    <H1>Whitelist Updated</H1>
EOF
    printFooter();
}

sub viewBlacklist {
    my @blacklist = `$SPASM_BIN_DIR/get_blacklist $username\@$DEFAULT_DOMAIN`;
    my $blacklist = join('', sort sortRoutine @blacklist);
    printHeader();
    printMenuBar();
    print <<EOF;
    <FORM action="$SCRIPT" method=POST>
      <input type=hidden name=username value="$username">
      <input type=hidden name=password value="$password">
      <input type=hidden name=source value="viewBlacklist">
      <center>
        Blacklists are one entry per line, and may be an email address, domain name, classful<br>
        netblock (e.g, 10, 10.1, 10.1.2, 10.1.2.3), or CIDR address (e.g, 10.1.2.0/25).<br>
        <textarea name=blacklist cols=40 rows=20 wrap=off>$blacklist</textarea><br>
        <input type=submit name=submit value="Update">
      </center>
    </FORM>
EOF
    printFooter();
}

sub updateBlacklist {
    my $blacklist = $cgi->param('blacklist')?$cgi->param('blacklist'):"";
    open(PIPE, "|$SPASM_BIN_DIR/set_blacklist $username\@$DEFAULT_DOMAIN");
    for my $bl (split(/[\n|\r]/, $blacklist)) {
        $bl =~ s/[\n|\r]//g;
        next unless $bl;
        $bl =~ tr/A-Z/a-z/;
        print PIPE "$bl\n";
    }
    close(PIPE);

    printHeader();
    printMenuBar();
    print <<EOF;
    <H1>Blacklist Updated</H1>
EOF
    printFooter();
}

sub printMainMenu {
    printHeader();
    printMenuBar();
    printFooter();
}

sub printMenuBar {
    print <<EOF;
  <BODY>
    <FORM action=$SCRIPT method=POST>
      <input type=hidden name=username value="$username">
      <input type=hidden name=password value="$password">
      <TABLE width=100%>
	<TR>
	  <TD align=right><a href=/spasmdoc>Help!</a></TD>
	</TR>
      </TABLE>
      <TABLE width=100%>
        <TR>
	  <TD align=left>$username\@$DEFAULT_DOMAIN
          <TD align=right><input type=submit name=submit value="Logout">
        </TR>
      </TABLE>
      <TABLE>
        <TR>
          <TD><input type=submit name=submit value="Mail Filters">
          <TD><input type=submit name=submit value="Whitelist">
          <TD><input type=submit name=submit value="Blacklist">
          <TD><input type=submit name=submit value="View Log">
          <TD><input type=submit name=submit value="View Quarantine">
        </TR>
      </TABLE>
    </FORM>
    <HR>
EOF
}

sub printLoginScreen {
    printHeader();
    print <<EOF;
  <BODY>
    <FORM action=$SCRIPT method=POST>
      <TABLE style="margin-left: auto; margin-right: auto; background: #ddddff;" border=1>
        <TR><TD>Username:<TD><input type=text size=16 name=username value="$username"></TR>
        <TR><TD>Password:<TD><input type=password size=16 name=password value=""></TR>
      </TABLE>
      <P style="text-align: center">
        <input type=submit name=submit value="Login">
      </P>
    </FORM>
EOF
    printFooter();
}

sub printError {
    print <<EOF;
Content-type: text/html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<HTML>
  <HEAD>
    <TITLE>spasm account administrator</TITLE>
    <META http-equiv="Content-Type" content="text/html; charset=utf-8">
    <STYLE type="text/css">
      BODY { background: white; color: black; font-family: "times new roman", serif; font-size: 12pt; }
      H1 { text-align: center; }
      H2 { text-align: center; }
      IMG { border: none; }
      TABLE { margin-left: auto; margin-right: auto; }
    </STYLE>
  </HEAD>
  <BODY>
    <H1>
EOF
    print @_;
    print <<EOF;
    </H1>
  </BODY>
</HTML>
EOF
    exit;
}

sub printHeader {
    print <<EOF;
Content-type: text/html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<HTML>
  <HEAD>
    <TITLE>spasm account administrator - $username\@$DEFAULT_DOMAIN</TITLE>
    <META http-equiv="Content-Type" content="text/html; charset=utf-8">
    <STYLE type="text/css">
      BODY { background: white; color: black; font-family: "times new roman", serif; font-size: 12pt; }
      H1 { text-align: center; }
      H2 { text-align: center; }
      H3 { text-align: center; }
      IMG { border: none; }
      TABLE { margin-left: auto; margin-right: auto; }
      SPAN.center { margin-left: auto; margin-right: auto; text-align: center; }
      FORM { margin-bottom: 0; }
    </STYLE>
  </HEAD>
EOF
}

sub printFilterHeader {
    my $numFilters = scalar(@SF);
    my $farray = "";
    for (@SF) { $farray .= "'$_',"; }
    chop $farray;
    print <<EOF;
Content-type: text/html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<HTML>
  <HEAD>
    <TITLE>spasm account administrator - $username\@$DEFAULT_DOMAIN</TITLE>
    <META http-equiv="Content-Type" content="text/html; charset=utf-8">
    <STYLE type="text/css">
      BODY { background: white; color: black; font-family: "times new roman", serif; font-size: 12pt; }
      H1 { text-align: center; }
      H2 { text-align: center; }
      H3 { text-align: center; }
      IMG { border: none; }
      TABLE { margin-left: auto; margin-right: auto; }
      SPAN.center { margin-left: auto; margin-right: auto; text-align: center; }
      FORM { margin-bottom: 0; }
    </STYLE>
    <SCRIPT language="JavaScript">
      function checkRadioButton(myradio) {
	fArray = [$farray];

	if(myradio == 5) { document.getElementById("customTable").style.visibility = "visible"; }
	else { document.getElementById("customTable").style.visibility = "hidden"; }

	if(myradio == 5) {
	}
	else if(myradio == 4) {
	  for(var i=0; i<$numFilters; i++) {
	    obj = document.getElementsByName(fArray[i]);
	    if(fArray[i] == "USE_SUBJECT_TAGGING") { obj[0].checked = 1; }
	    else if(fArray[i] == "SA_REQUIRED_HITS") { obj[0].value = "4"; }
	    else if(fArray[i] == "SF_WHITELIST_ONLY") { obj[0].checked = 1; }
	    else { obj[2].checked = 1; }
	  }
	} else {
	  if(myradio >= 0) {
	    for(var i=0; i<$numFilters; i++) {
	      obj = document.getElementsByName(fArray[i]);
	      obj[0].checked = 1;
	    }
	  }
	  if(myradio >= 1) {
	    document.fForm.USE_LOGGING[2].checked = 1;
	    document.fForm.SF_VIRUS_SCAN[2].checked = 1;
	    document.fForm.SF_PERSONAL_BLACKLIST[2].checked = 1;
	    document.fForm.SF_ORDB[2].checked = 1;
	    document.fForm.SF_DSBL[2].checked = 1;
	    document.fForm.SF_SBL[2].checked = 1;
	    document.fForm.SF_SORBS[2].checked = 1;
	  }
	  if(myradio >= 2) {
	    document.fForm.SF_SPAMTRAP[2].checked = 1;
	    document.fForm.SF_LOCALFILTER[2].checked = 1;
	    document.fForm.SF_SPAMASSASSIN[2].checked = 1;
	    document.fForm.SA_REQUIRED_HITS.value = "5";
	    document.fForm.SF_SPAMCOP[2].checked = 1;
	  }
	  if(myradio >= 3) {
	    document.fForm.SF_RDNS[2].checked = 1;
	    document.fForm.SF_HELO[2].checked = 1;
	    document.fForm.SF_MAIL_HOST[2].checked = 1;
	    document.fForm.SA_REQUIRED_HITS.value = "4";
	    document.fForm.SF_POSTMASTERRFC[2].checked = 1;
	    document.fForm.SF_DSNRFC[2].checked = 1;
	    document.fForm.SF_ABUSERFC[2].checked = 1;
	    document.fForm.SF_WHOISRFC[2].checked = 1;
	    document.fForm.SF_IPWHOISRFC[2].checked = 1;
	  }
	}
      }
    </SCRIPT>
  </HEAD>
EOF
}

sub printFooter {
    print <<EOF;
  </BODY>
</HTML>
EOF
}
