#!/usr/bin/perl -T require 5; ## # params: # ctl:required Fields that the user is required to enter. # ctl:required_mesg Message to display if the user doesn't fill out # a required field. # # ctl:pretty_print Nicely format the mail body. (Default: true) # Currently obsolete. # ctl:keep_empties Mail an input and it's value, even if it wasn't # defined. (Default: false) # # ctl:link... There can be links appended to the end of the # follow-up document. Each link directive is specified # with ctl:link?_, where ? is the number of the link, # starting with 1. # ctl:link?_url A link to append at the end of the document. # ctl:link?_mesg The text of the given link. # ctl:link?_img The image associated with the given link. # # ctl:link_sepstr String used to separate one link from another # ctl:link_sepimg Image used to separate one link from another # # ctl:followup_url URL to display after form submission, as a # replacement for any output from this script. # ctl:followup_head Absolute pathname of file to prepend the default # output from this script. # ctl:followup_tail Absolute pathname of file to append the default # output from this script. # # hdr:to Target address of mail. Required. # hdr:* Arbitrary mail header line. Anything can be put # in place of the '*' -- it's up to sendmail to decide # what to do with it. # # anything_else All other inputs will be sent as part of the mail # body. ## ## # This script Copyright (c) 1997 O'Shaughnessy Evans, GST-Call America # Business Communications Corp. ## sub init { # Referer Pattern: the regular expression describing hosts that will # be allowed to call this script. That is, what addresses will the # environmental variable HTTP_REFERER successfully match? $referer_pat = '^(207.114.188.170)$'; # Sendmail: where is the local version of sendmail installed? $sendmail = "/usr/lib/sendmail"; # Force Required: the list of parameters that MUST be included. # Should be a comma-separated list @force_reqd = ( 'hdr:to' ); # Input defaults $required_mesg = "Sorry, but you must fill out all of the required fields". " as indicated on the form."; $Control{'link_sepstr'} = '/'; $Control{'pretty_print'} = 1; $Control{'keep_empties'} = 0; $ENV{'PATH'} = "/usr/bin:/usr/ucb:/usr/sbin:/usr/lib"; } sub htstart { $Cgi = new CGI; if ($Cgi->param('ctl:DEBUG')) { $DEBUG = 1; $| = 1; $Cgi->delete('ctl:DEBUG'); print $Cgi->header, $Cgi->start_html(-'title' => 'Mailserf Output'); } } sub htend { dprint("
", $Cgi->dump); print $Cgi->end_html, "\n"; } sub hterr { my($title, @mesg) = @_; print $Cgi->header, "

$title

\n

@mesg
\n"; exit(2); } sub dprint { print @_ if $DEBUG; } sub name_to_addr { my $name = shift; my($addr); $addr = inet_ntoa(inet_aton($name)); if (!$addr) { dprint("Couldn't look up $name\n"); return 0; } else { return $addr; } } sub hostallow { $Cgi->referer =~ "^[a-zA-Z]+:\/\/([^:/]+)"; $addr = name_to_addr($1); $addr =~ /$referer_pat/ or hterr("CGI-BIN access denied from referer $1", "Sorry, but only local hosts are allowed to access cgi-bin programs ". "on this server."); } # Recursively dereference a "val:key" input value. # input : an input value (as opposed to an input name) # returns: value of the last-derefenced input sub deref_val { local($_) = shift; while ( /^val:(\S+)/ ) { $_ = $Cgi->param($1); } return $_; } # Find and expand the '+' and 'val:' tokens in an input value. # input : the name of the input to expand # returns: Changes the CGI object's definition of the given input's value. # Returns nothing. sub expand_input { shift; my($val); $val = $Cgi->param($_); if ($val =~ /\+/) { my(@line); foreach ( split(/\s*\+\s*/, $val) ) { push(@line, /^val:/ ? deref_val($_) : $_); } $Cgi->param($_, "@line"); dprint("Expanded $val to ", $Cgi->param($_), "
\n"); } elsif ($val =~ /^val:/) { $Cgi->param($_, deref_val($val)); dprint("Expanded $val to ", $Cgi->param($_), "
\n"); } } sub abs_path { my($path) = @_; return $ENV{'DOCUMENT_ROOT'}.'/'.$path; } sub parse_params { my(@reqd, $tmp); # check for required params push @reqd, @force_reqd; if ($Cgi->param('ctl:required')) { push @reqd, ( split(/\s*,\s*/, $Cgi->param('ctl:required')) ); } if ($Cgi->param('ctl:required_mesg')) { $required_mesg = $Cgi->param('ctl:required_mesg'); } dprint("Required: @reqd
\n"); grep { $tmp = $Cgi->param($_); dprint("looking for $_..."); $tmp =~ /\S/ or hterr("Missing Arguments", $required_mesg); dprint("found.
\n"); } @reqd; $Cgi->delete('ctl:required'); $Cgi->delete('ctl:required_mesg'); foreach ($Cgi->param) { expand_input($_); if (/^ctl:(\S+)/) { $tmp = lc $1; if ($Cgi->param($_) =~ /^(false|0)$/) { $Control{$tmp} = 0; } elsif ($Cgi->param($_) =~ /^(true|1)$/) { $Control{$tmp} = 1; } else { $Control{$tmp} = $Cgi->param($_); } dprint("Found control line: $tmp = ", $Control{$tmp}, "
\n"); } elsif (/^hdr:(\S+)/) { $Headers{$1} = $Cgi->param($_); dprint("Found header line: $1 = ", $Headers{$1}, "
\n"); } else { $Body{$_} = $Cgi->param($_); dprint("Found body line: $_ = ", $Body{$_}, "
\n"); } } $Cgi->delete_all() unless $DEBUG; } sub send_mail { my($hdr); # Build message header $hdr = "To: $Headers{'to'}\n"; delete $Headers{'to'}; foreach (keys %Headers) { $hdr .= "$_: $Headers{$_}\n"; } # Send message if ($DEBUG) { open(MTA, ">&STDOUT") || croak("I couldn't dup STDOUT"); print MTA "The following message was generated, but not sent:
\n", "


\n";
    }
    else {
        open(MTA, "|$sendmail -t -oi") || croak("I couldn't open $sendmail!");
    }

    print MTA "$hdr\n";
    print MTA "The following data was submitted from ", 
     $Cgi->remote_host(), "\non ", scalar localtime(), ":\n\n";
    foreach (sort keys %Body) {
        next if (!$Control{'keep_empties'} && !$Body{$_});
        if ($Body{$_} =~ /\n/) {
            print MTA "  o $_ = \n";
            foreach (split /\n/, $Body{$_}) {
                print MTA "       $_\n";
            }
        }
        else {
            print MTA "  o $_ = $Body{$_}\n";
        }
    }

    close(MTA) || croak("Weird error: I couldn't close $sendmail!");
    dprint("

\n"); } sub follow_up { my($url, $img, $mesg); local(*FILE); if ($Control{'followup_url'}) { print "Location: ", $Control{'followup_url'}, "\n\n"; dprint("

\n"); dprint("No follow up text; Browser redirected to ". "$Control{'followup_url'}
\n"); return; } else { print $Cgi->header, $Cgi->start_html( -'title' => 'Mailserf Output', -'author' => 'shaug@callamer.com', -'meta' => { 'copyright' => "copyright (c) 1997 O'Shaughnessy ". "Evans, GST-Call America" }); } if ($Control{'followup_head'}) { dprint("

Opening up followup header file ", abs_path($Control{'followup_head'}), "
\n"); open(FILE, abs_path($Control{'followup_head'})) || carp("Couldn't read in followup header file ". $Control{'followup_head'}.": $!"); while() { print; } close(FILE) || carp("mailserf: Couldn't close followup header file ". $Control{'followup_head'}.": $!"); dprint("

End of followup header file
\n"); } # Display the submitted information print "

Thank you! Your form was submitted with the following ". "information:

\n"; print "

\n"; if ($Control{'followup_tail'}) { dprint("

Opening up followup tail file ", abs_path($Control{'followup_tail'}), "
\n"); open(FILE, abs_path($Control{'followup_tail'})) || carp("mailserf: Couldn't read in followup tail file ". $Control{'followup_tail'}.": $!"); while() { print; } close(FILE) || carp("mailserf: Couldn't close followup tail file ". $Control{'followup_tail'}.": $!"); dprint("

End of followup tail file
\n"); } # Provide options (i.e. links) for continuing print qq/


\n/; $url = $Control{'link1_url'}; if ($url) { $img = $Control{'link1_img'}; $mesg = $Control{'link1_mesg'}; print qq/\n/; print qq/\t\n/ if $img; print $mesg if $mesg; print "\n"; } $i = 1; $link_sep = $Control{'link_sepimg'} ? qq/\t\n/ : qq/\t$Control{'link_sepstr'}\n/; while ($url = $Control{'link'.++$i.'_url'}) { dprint("
{$i} Building link for $url
\n"); $mesg = $Control{'link'.$i.'_mesg'}; $img = $Control{'link'.$i.'_img'}; dprint("-> found link message $mesg
\n"); dprint("-> found link image $img
\n"); print $link_sep; print qq/\n/; print qq/\t\n/ if $img; print "\t$mesg" if $mesg; print "\n"; } } BEGIN { use Socket; use CGI; use CGI::Carp; init(); htstart(); } hostallow(); parse_params(); send_mail(); follow_up(); END { htend(); }