#! /usr/bin/perl -w

# Display a message in a user's log directory

# Distributed Checksum Clearinghouse
#
# Copyright (c) 2005 by Rhyolite Software, LLC
#
# This agreement is not applicable to any entity which sells anti-spam
# solutions to others or provides an anti-spam solution as part of a
# security solution sold to other entities, or to a private network
# which employes the DCC or uses data provided by operation of the DCC 
# but does not provide corresponding data to other users.
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# Parties not eligible to receive a license under this agreement can 
# obtain a commercial license to use DCC and permission to use
# U.S. Patent 6,330,590 by contacting Commtouch at http://www.commtouch.com/
# or by email to nospam@commtouch.com.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC
# BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
# OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
# SOFTWARE.
#
#	Rhyolite Software DCC 1.3.0-1.12 $Revision$
#	Generated automatically from list-msg.in by configure.

# This file must protected with an equivalent to httpd.conf lines
#   in the README file.


use strict 'subs';


# get DCC parameters
local($logdir, $DCC_HOMEDIR);		# quiet -w warnings
do('/var/www/dcc-bin/common') || die("could not get DCC configuration: $!\n");

get_query();
# punt to directory listing if no message specified
punt("no message specified for listing")
    if (!($msg = $query{msg}));

my($path) = "$logdir/msg.$msg";



# display the message literally if asked
if ($query{literal}) {
    my($buf);

    if (!open(MSG, $path)) {
	html_head("Message $msg for $user");
	print "<P class=warn>Cannot open $path: $!\n</BODY>\n</HTML>";
	exit;
    }
    print "Content-type: text/plain\n";
    print "Expires: Thu, 01 Dec 1994 16:00:00 GMT\n";
    print "pragma: no-cache\n\n";
    print $buf
	while (read(MSG, $buf, 4*1024));
    exit;
}


# find the previous and next messages
local($msgs_mtime, $msg_first, $msg_last);		# quiet -w warnings
get_log_msgs($msg, 0);
if (!$msgs_mtime{$msg}) {
    punt("message $msg has disappeared")
} else {
    my($msg_num, $older_msg, $oldest_msg, $newer_msg, $newest_msg);

    $older_msg = $oldest_msg = $msgs_num[@msgs_num-1];
    $newer_msg = $newest_msg = $msgs_num[0];
    for ($msg_num = $msg_first; $msg_num <= $msg_last; ++$msg_num) {
	if ($msgs_num[$msg_num] eq $msg) {
	    $newer_msg = $msgs_num[$msg_num-1] if ($msg_num > 0);
	    $older_msg = $msgs_num[$msg_num+1] if ($msg_num < @msgs_num-1);
	    last;
	}
    }

    $oldest_link = (($oldest_msg eq $msg) ? "Oldest"
		    : "$list_msg_link?msg=$oldest_msg\">Oldest</A>");
    $older_link = (($older_msg eq $msg) ? "Older"
		   : "$list_msg_link?msg=$older_msg\">Older</A>");
    $newer_link = (($newer_msg eq $msg) ? "Newer"
		   : "$list_msg_link?msg=$newer_msg\">Newer</A>");
    $newest_link = (($newest_msg eq $msg) ? "Newest"
		    : "$list_msg_link?msg=$newest_msg\">Newest</A>");
    html_head("Message $msg for $user");
    common_buttons();
    print <<EOF;
<TR><TD>$oldest_link
    <TD>$older_link
    <TD>$newer_link
    <TD>$newest_link
</TABLE>

<H3>Message $msg for <EM>$user</EM></H3>
<P>
$list_msg_link?msg=$msg&amp;literal=yes"
    TARGET="DCC literal log file">Literal log file</A>
contents for reporting or analysis.
EOF
}

# pass a greylist triple
if ($query{greywhite}) {
    my($sight) = `/usr/sbin/dccsight -G "$query{greywhite}" 2>&1`;
    my($log) = ". $DCC_HOMEDIR/dcc_conf;" . ' $DCC_LOGGER "';
    $log .= "$ENV{SCRIPT_NAME} $user $msg; dccsight -G $query{greywhite}: ";
    $log .= "$sight\"";
    `$log >/dev/null 2>&1`;
    print "\n<P>\ngreylist passing $query{greywhite}: $sight";
}

local($msg_date, $msg_env_from, $msg_helo,	# quiet -w warnings
      $msg_client_name, $msg_ip, $msg_mail_host,
      $msg_hdrs, $msg_body, $msg_cksums);
@error = parse_log_msg($msg, $path);
if (defined $error[0]) {
    print "<P class=warn><B>$error[0]:</B> $error[1]\n";
    print "</BODY>\n</HTML>\n";
    exit;
}


print <<EOF;
<P>
<HR><H4>Envelope</H4>
<TABLE border=0 cellspacing=0 cellpadding=0>
EOF

print_envelope_link(0, "", "", "", $msg_date);
print_envelope_link(1, "IP", "IP", $msg_client_name, $msg_ip);
print_envelope_link(scalar "helo" =~ /^($sub_hdrs)$/i,
		    "HELO", "substitute HELO", "", $msg_helo);
print_envelope_link(1, "env_From", "env_From", "", $msg_env_from);
print_envelope_link(scalar "mail_host" =~ /^($sub_hdrs)$/i,
		    "mail_host", "substitute mail_host", "", $msg_mail_host);

# make links for whitelisting the body checksusm
$msg_cksums =~ s/(Body|Fuz1|Fuz2):((\s\S{8}){4})/make_hex_link($1,$2)/eg;

# make whitelisting links for greylist checksums with active embargos
if ($msg_cksums =~ /greylist recipient/) {
    my($sum, $sight, $link, $text);

    while ($msg_cksums =~ /^\s+([a-z0-9]{8}(?: [a-z0-9]{8}){3}) Embargo[\s#0-9]*$/mi) {
	$sum = $1;
	$sight = `/usr/sbin/dccsight -QG "$sum" 2>&1`;
	if ($sight =~ /Embargo.*/) {
	    $link = make_greywhite_link($sum);
	    $text = "    <B>select checksum to whitelist</B>\n";
	} else {
	    $link = "$sum<!--inactive-->";
	    $text = "    current value: " . html_str_encode($sight);
	}
	$msg_cksums =~ s/(^\s+)$sum(.*$)\n/$1$link$2\n$1$text/m;
    }
}

print <<EOF;
</TABLE>
<P>
<HR><H4>Headers</H4>
<PRE>
$msg_hdrs
</PRE>

<HR><H4>Body</H4>
$msg_body

<HR><H4>Checksums</H4>
<PRE>$msg_cksums</PRE>

</BODY>
</HTML>
EOF

exit;

#############################################################################


sub print_envelope_link {
    my($enable, $label, $type, $text, $value) = @_;

    # skip the row if the value is absent
    return
	if (! $value);

    print "<TR><TD>";
    if ($label) {
	print html_str_encode($label);
	print ":&nbsp;";
    }
    print "<TD>";

    if (! $enable) {
	print html_str_encode($text . $value);
	print "\n";
	return;
    }

    print "$text$edit_link?type=";
    print url_encode($type);
    print "&amp;val=";
    print url_encode($value);
    print "&amp;msg=$query{msg}" if ($query{msg});
    print "&amp;auto=1\">";
    print html_str_encode($value);
    print "</A>\n";
}



sub make_hex_link {
    my($type, $sum) = @_;
    my($str);

    $str = "$edit_link?type=";
    $str .= url_encode("hex $type");
    $str .= "&amp;val=";
    $str .= url_encode($sum);
    $str .= "&amp;msg=$msg&amp;auto=1\">$type:$sum</A>";

    return $str;
}


sub make_greywhite_link {
    my($sum) = @_;
    my($str);

    $str = "$list_msg_link?msg=$msg&amp;greywhite=";
    $str .= url_encode($sum);
    $str .= "\">$sum</A>";

    return $str;
}
