#!/usr/local/bin/webwork-perl

# $Id$

# feedback.pl: Mail feedback to a specified user, with the URL of the
#              referring page automagically included.  Reject bogus
#              destination addresses.
#
# Usage: invoke as http://site/cgi-bin/feedback.pl?address1,address2,...

use lib '.'; use webworkInit; # WeBWorKInitLine
use Global;
use CGI qw(:standard);
use CGI::Carp qw(fatalsToBrowser);
use HTML::Entities ();  
use Net::SMTP;

$ENV{'PATH'} = '';  # try to avoid PATH attacks

# log access
	&Global::log_info('', query_string);

my $Course = param('course');
# establish environment for this script
&Global::getCourseEnvironment($Course) if defined $Course;

# local configuration stuff

$BGCOLOR       = '#ffffff';
$LOGFILE       = &Global::getWebworkLogsDirectory() . "webwork-feedback.log";

# if path = '/send' we're processing a filled-out form
my $ADDR;  # define 'globally' so that it can be used by subroutines
if (path_info() eq '/send') {

    # Bad destinations shouldn't make it this far, since we already checked
    # for bad "To:" when generating the feedback form.  However, it's still
    # possible that some evildoer has submitted a bogus form, so we check
    # again...
	foreach  $ADDR (split(/\s*,\s*/, param('To'))) {
	    &check_destination($ADDR);

	    &user_error('You didn\'t enter any comments.')
		if (param('comments') eq '');
	    &user_error('You didn\'t enter an e-mail address.')
		unless (param('email') =~/\@/);

	    my $smtp = Net::SMTP->new($Global::smtpServer, Timeout=>10) ||
		&internal_error("Couldn't contact SMTP server.");
	    $smtp->mail($Global::smtpSender);

		if ( $smtp->recipient($ADDR)) {  # this one's okay, keep going
	        $smtp->data(&output(0,$ADDR) . access_link($ADDR) ) ||
				&internal_error("Unknown problem sending message data to SMTP server.");
	    } else {			# we have a problem  with this address
		    $smtp->reset;                     
	        &internal_error("SMTP server doesn't like this address: <$ADDR>.");
		}
	    $smtp->quit;
	    &log("Mail sent to: " . $ADDR . "     from: " .param('email') ); 
	}
#    &log("Mail sent to: " . param('To') . "     from: " .param('email') );
    &thank_you;
    
} else {

# No path info: we're generating a form to be filled-out

    $To = $ENV{'QUERY_STRING'};
    $To = $Global::webmaster if ($To eq '');
    &check_destination($To);
    &generate_form;
}

exit(0);

############################## Subroutines #################################

sub internal_error {
    my $msg = join " ", @_;
    &log("ERROR: $msg");
    print header,
    	start_html('-title' => "Internal Error", -bgcolor=>"$BGCOLOR"),
	h1('Internal Error'),
	b(HTML::Entities::encode($msg)),
	p,
	"Your message could not be sent.  Please notify ",
	"&lt;", a({href=>"mailto:$Global::webmaster"}, $Global::webmaster), "&gt;. ",
	br,
	"We apologize for the inconvenience.",
	end_html;
    exit(1);
}

sub user_error {
    my $msg = join " ", @_;
    print header,
	start_html('-title' => 'User error', -BGCOLOR=>"$BGCOLOR"),  
	h1('User error'),
	p,
	b(HTML::Entities::encode($msg)),
	p,
        "Please hit the &quot;<B>Back</B>&quot; button on your browser to ",
	"try again, or notify ", br,
	"&lt;", a({href=>"mailto:$Global::webmaster"}, $Global::webmaster), "&gt; ",
	"if you believe this message is in error.",
	end_html;
    exit(1);
}

sub check_destination {
    my($address_list) = @_;

    my (@address) = split(/\+*,\+*/, $address_list);
    for (@address) {
       &internal_error("Sorry, I'm not allowed to send mail to <$_>.")
           if !/$Global::legalAddress/;
    }
}

#http://webwork.math.rochester.edu/cgi-bin/development/processProblem7.pl?probSetKey=51823&probNum=7&Mode=HTML_tth&course=mth161dev&user=gage&key=NQ18Kry70j*.8Lsok3ulG^QHAp3zRG0hjHE5emT4
sub access_link {
   my $ADDR = shift;
   my $url = param('referring_url');
   $USER = $ADDR; #param('To');
   $USER =~s/@.*$//;    # determine the user (the recipient of this message) from the mail message.  This method may change.
   $url =~ s/\?.*$//;
   my $warning_limit = $^W; $^W=0;
   $url .= '?probSetKey='.param('probSetKey').'&probNum='.param('probNum').'&Mode='.param('Mode').'&show_old_answers=1'.'&course='.param('course')."&user=$USER&key=".param('key');
   $^W= $warning_limit;
   return ("-------\nTo go directly to the student's page, click on the Access Link and enter your password under Fast relogin.\nAccess Link " . $url . "\n");
}

sub log {
    my $msg = $_[0];
#    open(LOGFILE, ">> $LOGFILE") || &internal_error("Can't write to $LOGFILE"); # warn("Can't write to $LOGFILE\n");
	open(LOGFILE, ">> $LOGFILE") || warn("Can't write to $LOGFILE\n"); ## above line leads to an infinite loop
    print LOGFILE 'Date: ', scalar(localtime), "\n";
    print LOGFILE $msg;
    print LOGFILE "\n------\n";
    close(LOGFILE);
}

sub thank_you {
    print header,
    start_html( '-title'=>'Thank You', -BGCOLOR=>"$BGCOLOR"),
    h1('Your message has been mailed.'),
    "To: ", param('To'),
    '<pre><br><br>',&output(0,param('To') ),'</pre>',
    end_html;
}

sub generate_form {

    my $list = "," . $To;
    $list =~ s/,/<li>/g;
	my $from = param('email');
	$from = '    ' unless defined $from;

    print header,
    start_html('-title'=>'WeBWorK - Feedback', -bgcolor=>"$BGCOLOR"),
    img({align=>'LEFT', alt=>"", src=>$Global::headerImgUrl}),
    p({align=>'right'}),
    br({clear=>'ALL'}),
    hr,
    h1('WeBWorK Feedback Gateway'),
    start_form('POST', url() . '/send'),
        hidden('To', $To),
        hidden('name'),
            hidden('id'),
        hidden('referring_url', referer()),
        hidden('probSetKey'),
        hidden('setnum'),
        hidden('probNum'),
        hidden('course'),
        hidden('section'),
        hidden('recitation'),
        hidden('Mode'),
        hidden('user'),
        hidden('key'),
        strong("To: "), kbd($To), br,
            strong("From: "), param('name'), br,
        p,
        textfield(-name=>'email',-default => $from, -size=>'32',-override=>1), ' ', b('E-mail'), i(' (must be filled in!)'),br,
        p,
        b('Your comments:'), ' ', i('(must be filled in!)'), br,
        textarea('comments', '', 15, 70),
        p,
        b(submit('submit', 'Submit Your Comments')),
    end_form,
    end_html;
}

sub output {
    my $suppress_output = $_[0];
    my $addr = $_[1];
    my $msg;
	my $replyTo = param('email');
	$replyTo .= ', ' . $Global::defaultReply if ($Global::defaultReply =~ /\w/);
	
    $msg =
       # message header
       "From: "           . param('email')   . " (" . param('name') . ")\n" .
       "To: "             . $addr      . "\n" .
       "Reply-To: "       . $replyTo   . "\n" .
       "X-Remote-Host: "  . remote_host      . " (" . remote_addr . ")\n" .
       "Subject: WeBWorK Feedback from " . param('course'). "/" . param('user'). "\n" .
       "\n" .

       # message body: student data
       "User:           " . param('user')    . "\n" .
       "Name:           " . param('name')    . "\n" .
       "Student ID:     " . param('id')      . "\n" .
       "Course:         " . param('course')  . "\n" .
       "Section:        " . param('section') . "\n" .
       "Recitation:     " . param('recitation') . "\n" .
       "PSVN:           " . param('probSetKey')    . "\n" .
       "Set number:     " . param('setnum')  . "\n" .
       "Problem number: " . param('probNum') . "\n" .
       "Mode:           " . param('Mode')    . "\n" .
       "Key:            " . param('key')     . "\n" .
       #   "DataMunger URL: $munger"         . "\n" .
       "\n";

    # for logs: don't log actual message, just student info
    return $msg if $suppress_output;

    # message body: message
    $msg .= "Allegedly from: " . param('email') . "\n" .
      "Comments:\n-------\n" . param('comments') . "\n";

    return $msg;
}

