#!/usr/athena/bin/perl

use strict;
use warnings;

my $stderr = "/var/www/logs/comment_logs/new_comment_usage";
my $usage = "/var/www/logs/comment_logs/new_comment_usage";
my $twits = "/var/www/data/comment_twits";
my $comments = "/var/www/logs/comment_logs/comments";
my $allowed_addrs = "/var/www/data/allowed-addresses";

open(STDERR,">>${stderr}") or die "Can't open $stderr : $!";

check_immediate_reject();
print "Content-Type: text/html\n\n";
my $query = join(' ', @ARGV) if $ARGV[0];
if (badformclient()) {
  loserclient();
} elsif (twit_sender()) {
  you_are_a_twit();
} elsif (isabot()) {
  you_are_a_twit();
} else {
  if ($ENV{'REQUEST_METHOD'} eq "POST") {
    read(STDIN, $query, $ENV{'CONTENT_LENGTH'});
    &parse($query);
  } else {
    if (! $ENV{'SERVER_PROTOCOL'}) {
      &old($query);
    } else {
      &form();
    }
  }
}

### generate a form to be filled out
#
#   for more info, see
#http://www.ncsa.uiuc.edu/SDG/Software/Mosaic/Docs/fill-out-forms/overview.html

sub form {
  print <<EOF;
<html>
<head>
<meta http-equiv="Refresh" content="0; URL=http://stuff.mit.edu/sipb/comment.html">
</head>
<body>
</body>
</html>
EOF
}

sub old_form {
  my $remuser = $ENV{'REMOTE_USER'};
  my $referer = $ENV{HTTP_REFERER} || "";
  my $r1 = int(rand(10)); my $r2 = int(rand(10));
  print <<"EndOfForm";
<title>Comments on STUFF.MIT.EDU</title>
<h1>Comments on this server</h1>

Thank you for taking some time to comment on our server.  Just fill
out the form below, and click on the "Send..." button.  If you are not sure
who to send to, please send to stuffmaster\@mit.edu.<p>

If you wish to remain anonymous, leave the E-mail address field blank.
Just remember that we can't reply to you if you don't tell us who you
are :-)

Note: if you use our gateway to send email and it bounces, the bounced
email will go to the SIPB webmasters.

<hr>

<FORM method="POST">
Your E-mail address: <input name="email" value="$remuser" size=30><p>
Mail to: <select name="to">
	<option value="stuffmaster\@mit.edu" selected> stuffmaster\@mit.edu

</select><p>
Subject or URL: <input name="url" value="$referer" size=40><p>
<TEXTAREA name="body" rows=9 cols=60></TEXTAREA><p>
Anti-spam test: What is $r1 + $r2? <input name="sum" size=10><p>
<input type="hidden" name="addone" value="$r1">
<input type="hidden" name="addtwo" value="$r2">
<input type="submit" value="Send in the comment">
<input type="reset" value="Naaaaah, just kidding">
</FORM>
<hr>
<ul>
<li><a href="/">SIPB Home Page</a>
</ul>
EndOfForm
}

sub prot {
  $_[0] =~ s/[\000-\037\177-\377]+//g;
  return $_[0];
}
### parsing comments
#
#   the comments are all packed in the form
#      field1=value1&field2=value2&...
#   with the "invalid" characters encoded as %-sequences.

sub parse {
  my (%post, $tmp, $name);
  my $nil = 'Anonymous User <nobody>';
  my $sm = '/usr/lib/sendmail -t -fwww-bounce@mit.edu';

  for (split(/&/,$_[0])) {
    if (/=/) {
      $name = $`;
      $tmp = $';
      $tmp =~ s/\+/ /g;
      $tmp =~ s/%([\da-f]{1,2})/pack('C',hex($1))/eig;
      $post{$name} = $tmp;
    }
  }

  #   leading whitespace
  $post{'email'} =~ s/^\s+//;
  #   trailing whitespace
  $post{'email'} =~ s/\s+$//;
  if ($post{'email'} =~ /^[a-zA-Z0-9][-_a-zA-Z0-9]+$/) {
    $post{'email'} .= "\@mit.edu";
  }

  if (exists $post{addone} and
      exists $post{addtwo} and
     $post{addone} + $post{addtwo} != $post{sum}) {
    print <<"EndOfMsg";
<html><head><title>Request failed</title></head>
<body>
<h1>Request failed</h1>
Sorry, you can't add.<p>

</body></html>
EndOfMsg
    exit;
  }
    
  if (&prot($post{'to'}) =~ /listproc@/i
      || &prot($post{'to'}) =~ /listserv@/i
      || &prot($post{'to'}) =~ /majordomo@/i) {
    print <<"EndOfMsg";
<html><head><title>Request failed</title></head>
<body>
<h1>Request failed</h1>
Sorry, our gateway does not handle majordomo, listproc, or listserv mail.<p>

And even if it did, you couldn't subscribe yourself to a
listproc using it. You would end up subscribing
"stuffmaster\@mit.edu" to the listproc, which isn't likely to
be something you want. :-)
</body></html>
EndOfMsg
    exit;
  }

  if (prot($post{'to'}) !~ /@/) {
    my $toaddr = prot($post{'to'});
    print <<"EndOfMsg";
<html><head><title>Request failed</title></head>
<body>
<h1>Request failed</h1>
Sorry, the To: address for all comments through our gateway
must include a hostname.  The form you used had an address of<p>

<pre>$toaddr</pre>

Note: this may be caused by your client (Lynx/2.3 BETA is known
to do this) not respecting the value field in select lists, if the
text of the selected item is not a valid address.<p>

If the address shown above is really valid, please send mail to
<a href="/comment">stuffmaster\@mit.edu</a>
with the email address and the URL for the form being used.
</body></html>
EndOfMsg
    exit;
  }

  if (! (&access_check(&prot($post{'to'})))) {
    &loggit("-",
	    &prot($post{'to'}), 
	    ($post{'email'} =~ /\S/) ? &prot($post{'email'}) : $nil,
	    $ENV{'REMOTE_ADDR'},
	    $ENV{'HTTP_REFERER'});
    &nopenopenope(&prot($post{'to'}));
    exit;
  } else {
    &loggit("+",
	    &prot($post{'to'}), 
	    ($post{'email'} =~ /\S/) ? &prot($post{'email'}) : $nil,
	    $ENV{'REMOTE_ADDR'},
	    $ENV{'HTTP_REFERER'});
  }



  open(SM, "|$sm");
  printf SM "From: %s\nSubject: comment -- %s\nTo: %s\n",
    ($post{'email'} =~ /\S/) ? &prot($post{'email'}) : $nil,
      &prot($post{'url'}),  $post{'to'};
  print SM "X-WebClient: $ENV{'HTTP_USER_AGENT'}\n";
  print SM "X-Referer: $ENV{'HTTP_REFERER'}\n"
    if defined $ENV{'HTTP_REFERER'};

  #Reverse resolve the machine name from the IP address:

  my @ipaddr = split(/\./, $ENV{'REMOTE_ADDR'});
  my $packipaddr = pack('C4', @ipaddr);
  my $realname = (gethostbyaddr($packipaddr,2))[0];
  unless ($realname) {
    $realname = "could not reverse-resolve name"
  }

  printf SM "\n\nSubmitted by '%s' on %s (%s)\nEmail sent via the WWW comment gateway at %s:%s.\n\nWarning: the sender's name and address may be forged.\n-----\n", $post{'email'}, $ENV{'REMOTE_ADDR'}, $realname, $ENV{'SERVER_NAME'}, $ENV{'SERVER_PORT'}
    if ($post{'email'} =~ /\S/);

  print SM "\n",$post{'body'},"\n";


  close(SM);

  unless ($?) {
    print "<title>Submission Receipt</title>\n";
    if ($post{'to'} eq "stuffmaster\@mit.edu") {
      print "<h1>Thank you for your comments!</h1>\n";
      print "Please continue to let us know what you think is\n";
      print "particularly good or bad about our server.<p>\n";
    } else {
      print "<h1>Your message has been sent!</h1>\n";
    }
    print "Comment as submitted:<p>\n<pre>\n";
    printf "Comment submitted to: %s\n", $post{'to'};
    printf "Your E-mail address: %s\n",
      ($post{'email'} =~ /\S/) ? &prot($post{'email'}) : "(anonymous)";
    printf "Subject:             %s\n\n", &prot($post{'url'});
    printf "Comment body:\n<hr>\n%s\n<hr></pre>\n", $post{'body'};
  } else {
    &main'report_error('internal_error', "sendmail failed with error $?");
  }
}

### compatibility with HTTP/0.9 and earlier
#   (just uses <isindex>)

sub old {
  my ($args) = @_;

  print <<"EndOfStuff";
<title>Comments on STUFF.MIT.EDU</title>
<h1>Your client is old...</h1>

Your client does not support HTTP/1.0, and therefore can't use the
form support interface.<p>

Please enter your comments in the Search keyword field.<p>

<isindex>
EndOfStuff

  if ($args) {
    my $date = timestring();
    print "Thanks for your comments!!!\n";
    open(COMM, ">>${comments}") or
      die "Can't open $comments : $!";
    print COMM $ENV{'REMOTE_ADDR'}." $date $args\n";
    close(COMM);
  }
}

# check the HTTP_USER_AGENT string to make sure
# this browser can handle forms.  Probably hasn't been 
# relevant for many years.
sub badformclient {
  $_=$ENV{'HTTP_USER_AGENT'};
  if (/NCSA Mosaic [^\/]*\/2\.([0-9]+)/) {
    if ($1 < 2) { 
      return 1;
    }
  }
  if (/MacMosaic/) {
    return 1;
  }

  # Macweb foo example return string is "MacWeb/1.00ALPHA2.1
  # 1.00ALPHA2.1 is okay.
  if (/MacWeb(\d*\.?\d*)[^\d]/) {
    my $ver = $1;
    my $rest = $';
    if ($ver < 2) {
      $rest =~ /ALPHA(\d*\.\d*)[^\d]/;
      my $alpha_ver = $1;
      if ($alpha_ver >= 2.1) {
	return 0;
      } else {
	return 1;
      }
    } else {
      return 0;
    }
  }
  return 0;
}

# tll the user that their client can't handle forms.
sub loserclient {
  print <<"EndOfStuff";
<TITLE>Incompatible Client Warning</TITLE>

<h1>Incompatible Client Warning</h1>

I'm sorry, but your web browsing client is incompatible with this
comment script. It might be a good idea to contact your site
administrator to see if there is a more recent version of your client
program.<P>

To be more specific, your web browser must support the <b>value</b>
tag in Forms to be compatible with this script.  Otherwise, your mail
will bounce. Known incompatible client software is:

<UL>
<LI>Mosaic for X, version 2.1 and earlier
<LI>Mac Mosaic, version 2alpha6 and earlier
<LI>MacWeb, version 1.00ALPHA2 and earlier
</UL>

If your client does support the <B>value</b> tag, and we have
erroneously filtered you out, send mail to stuffmaster\@mit.edu, telling
us your client and version number so we can check it out. Thank
you.<P>

EndOfStuff

}

sub access_check {
  my ($to) = @_;
  return is_to_allowed($to);
}

sub is_to_allowed {
  my ($to) = @_;

  $to =~ tr/A-Z/a-z/;

  open(LIST, $allowed_addrs) or die "Can't open $allowed_addrs : $!";
  while (<LIST>) {
    chop;
    tr/A-Z/a-z/;
    if ($to eq $_) {
      return(1);
    }
  }
  return(0);
}

sub nopenopenope {
  my ($to) = @_;

  print <<"EOM";
<html><head><title>Request failed</title></head>
<body>
<h1>Request failed</h1>

<p>We're sorry, but your submission to <strong>$to</strong> is not
permitted.</p>

<p>Please read on for an explanation of why this submission was not
allowed, and what you can do about it.</p>

<hr>

<h2>Why your request failed</h2>

<p>You just submitted a request to send email to
<strong>"$to"</strong>, to be sent using the WWW-to-email gateway
located on <a href="http://stuff.mit.edu/">stuff.mit.edu</a>. This service
has seen increasing amounts of abuse lately, driving us to take
measures to restrict the degree to which this service can be
abused.</p>

<p>To be specific, we are only allowing this gateway to be used to
send email to a specific list of addresses. If someone tries to use
this gateway to send email to an address which has not been registered
with our service, the mail will not be sent and they will be shown
this message.</p>

<h2>What you can do about it...</h2>

<h3>...if you got here from a web page you didn't write</h3>

<p>If you were trying to send email using this service, and feel your
intended use was not an <em>abuse</em> of our service, you should send
email to the author of the web page you came from (perhaps their email
address is "$to") informing them of the changes we've made in our
www-to-email service. If you do, in fact, want to send mail to $to
about this, you can use <a href="mailto:${to}">this convenient
<strong>mailto:</strong> link</a>.</p>

<h3>...if you got here from your own web page</h3>

<p>Anyone, regardless of whether they're affiliated with MIT, is
welcome to use our gateway to send themselves email. Read on for
instructions on how to register to use our gateway.</p>

<h4>Prerequisites</h4>

<p>You'll need to have your own web pages stored on your own web
server, and you'll need to have an HTML form set up to use our comment
gateway. If you don't understand HTML forms, please don't ask us to
explain them to you. There's documentation out there on the web. Go
find it.</p>

<h4>Once you have your web pages in place</h4>

<p>If you are the maintainer of a web page which uses this gateway,
and wish to register your email address as a valid email-destination
for our gateway to send mail to, you should send mail to <a
href="mailto:stuffmaster\@mit.edu">stuffmaster\@mit.edu</a>, mentioning
<ul>
<li>your email address and
<li>the URL(s) of the web page(s) from which the email will be submitted.
</ul>

<hr>
<address>
--- <a href="/comment">stuffmaster\@mit.edu</a>
</address>
</body></html>
EOM
}

sub loggit {
  my($allowed, $to, $from, $ip, $ref) = @_;
  my $time = timestring();
  open(LOG, ">>${usage}") or die "Can't open $usage : $!";
  print(LOG "$allowed to $to from $from ($ip) $ref  $time\n");
  close(LOG);
}

sub isabot {
  
}

# Check if this sender's machine is in our twit list.
sub twit_sender {
  my $twit=$ENV{'REMOTE_ADDR'};
 
  open(LIST, $twits) or die "Can't open $twits : $!";
  while (<LIST>) {
    chomp;
    if ($_ eq $twit) {
      # Twit IP address
      return(1);
    }
  }
  close LIST;
  return(0);
}

sub you_are_a_twit {
  print <<"EndOfStuff";
<HTML><HEAD><TITLE>Unable to Use Form</TITLE></HEAD><BODY>

<h1>Unable to Use Form</h1>

We are sorry, but you are unable to use this comment gateway.  Please
check with your local system administrator or postmaster to determine
the cause.
</BODY></HTML>
EndOfStuff
}

sub check_immediate_reject {
    if ($ENV{'HTTP_REFERER'} eq "http://osiris.cs.csufresno.edu/~alan/feedback.htm") {
	print "Content-Type: text/plain\n\n.\n";
	exit 0;
    }
}
sub timestring {
  my @t = localtime();
  $t[3] += 1;
  $t[4] += 1;
  $t[5] += 1900;
  return "$t[4]-$t[3]-$t[5] $t[2]:$t[2]:$t[0]";
}



1;
