#!/usr/bin/perl -w

# mailhtml - convert an RFC822 mail message to an HTML document
#
# Copyright (C) 1996 by John J. Chew, III <jjchew@math.utoronto.ca>
# All Rights Reserved.
#
# <title>mailhtml - convert an RFC822 mail message to HTML</title>

unshift (@INC, "$ENV{'HOME'}/lib/perl");

require 'getopts.pl';
do "$ENV{'HOME'}/etc/cgarc.config"; # can fail

$gVersion = '1.06';

sub clean {
  local($_) = @_;
  s/\&/&amp;/g;
  s/\</&lt;/g;
  s/\>/&gt;/g;
  s/\"/&quot;/g;
  s!http://[^\s&]+!<a href="$&">$&</a>!g;
  s!(^|\s)\*(\S+)\*($|[\s.,;:])!$1<em>$2</em>$3!g;
  s!^(--+|==+|__+)\s*$!<hr>!;
  $_;
  }

sub mark_address {
  local($_) = @_;
  /@/ || s/\bjjchew\b/jjchew\@math.utoronto.ca/;
  s/[^,<>&;\s]+@[^,<>&;\s]+/<a href="mailto:$&">$&<\/a>/g;
  $_;
  }

sub Usage {
  die "Usage: $0 [-d h1:h2:...:hn][-D][-m author][-v] file\n".
      "  -a               include unknown RFC822 headers\n".
      "  -d h1:h2:...:hn  suppress RFC822 headers\n".
      "  -m author        author for link rev=made purposes\n".
      "  -t topic         topic\n".
      "  -v               display version number\n".
      "";
  }

$opt_a = 0;
$opt_d = '';
# replace the following line with: $opt_m = 'your-email-address';
$opt_m = 'jjchew@math.utoronto.ca' if $ENV{'USER'} eq 'jjchew';
$opt_v = 0;
$opt_t = '?';
&Getopts('ad:Dm:vt:') || &Usage;

if ($opt_v) { print "$0 version $gVersion\n"; exit 0; }
if (!defined $opt_m) { 
  print "Please use '-m' to specify your e-mail address, or edit this\n";
  print "script to avoid having to do so in future.\n\n";
  &Usage;
  }
$opt_t = $gIDToTitle{$opt_t} if defined $gIDToTitle{$opt_t};

%address_headers = ('from', 1, 'to', 1, 'cc', 1, 'bcc', 1);
$state = 'init';

while (<>) {
  if ($state eq 'init') {
    die "Expected From line, got:\n$_Aborting" unless /^From /;
    $state = 'head';
    $last_header = undef;
    %headers = ();
    }
  elsif ($state eq 'head') {
    chop;
    if (s/^\s+/ /) {
      if (defined $last_header) { $headers{$last_header} .= $_; }
      else { die "Expected RFC822 header line, got:\n$_\nAborting"; }
      }
    elsif (($name, $value) = /(\S+)\s*:\s*(.*)/) {
      $headers{$last_header = "\L$name"} = $value;
      }
    elsif (length) {
      die "Malformed RFC822 header line:\n$_\nAborting";
      }
    else {
      $state = 'body';

      print "<html>\n";
      print "<head>\n";
      print "<link rev=made href=\"mailto:$opt_m\">\n";
      $title = $headers{'subject'} || "(no subject)";
      print "<title>", &clean($title), "</title>\n";
      print "</head>\n";
      print "<body>\n";
      print "<i><a href=\"index.html\">Back to $opt_t</a></i><p>\n";

      for $header ('received', split(/:/, "\L$opt_d")) 
        { delete $headers{$header}; }

      @headers = ();

      for $header ('from', 'to', 'date', 'subject', 'message-id', 
	'references', 'cc', 'bcc') {
	$_ = $headers{$header};
	if (defined $_) {
	  delete $headers{$header};
	  push(@headers, "<b>\u$header:</b> " .
	    ($address_headers{$header}
	      ? &mark_address(&clean($_))
	      : &clean($_)));
	  }
	}
      if ($opt_a) {
	for $header (sort keys %headers) {
	  $_ = $headers{$header};
	  if (defined $_) {
	    delete $headers{$header};
	    push(@headers, "<b>\u$header:</b> " .
	      ($address_headers{$header}
		? &mark_address(&clean($_))
		: &clean($_)));
	    }
	  }
	}
      }
    }
  elsif ($state eq 'body') {
    chop;

    push(@body, $_);
    }
  }

for $i (0..$#headers) {
  print $headers[$i], $i == $#headers ? "<p>\n" : "<br>\n";
  }

while ($body[0] eq '') { shift @body; }
while ($body[-1] eq '') { pop @body; }

# then print
$state = 'base';
for $i (0..$#body) { $_ = $body[$i];
  if (s/^>\s*//) {
    if (/^>/) {
      if ($state eq 'qquote')
	{ }
      elsif ($state eq 'quote')
	{ print "<br>\n"; }
      else 
	{ print "<blockquote>\n"; }
      print &clean($_), "<br>\n";
      $state = 'qquote';
      }
    else {
      if ($state eq 'quote') 
	{ }
      elsif ($state eq 'qquote') 
	{ }
      else
	{ print "<blockquote>\n"; }
      print &clean($_), "\n";
      $state = 'quote';
      }
    next;
    }

  if ($state =~ /^q?quote$/) 
    { print "</blockquote>\n"; $state = 'base'; }

  if (/[^\s.!?] {2,}\S.*[^s.!?] {2,}\S|[^\s.!?] {3,}\S/) {
    if ($state ne 'table') { print "<pre>\n"; $state = 'table'; }
    print &clean($_), "\n";
    next;
    }
  elsif ($state eq 'table') { 
    if (/\S/) { print "</pre>\n"; $state = 'base'; }
    else { print "\n"; next; }
    }

  if (length) { print &clean($_), "\n"; }
  else { print "<p>\n"; }
  }

if ($state =~ /^q?quote$/) { print "</blockquote>\n"; }
elsif ($state eq 'table') { print "</pre>\n"; }
print "</body>\n";
print "</html>\n";
