#!/usr/bin/perl

# Name: form_processor.cgi
#
# Version: 2.0
#
# Last Modified: 5-16-96
#
# Copyright Information: This script was written by Selena Sol
#
# Description: This form processing script allows a site
#     administrator to process multiple HTML forms with one script.  By 
#     taking advantage of various hidden tags which this script can 
#     understand, the admin can use this one script to process all of her 
#     scripts in multiple ways from dynamic email to building a database.
#
# Usage: This script should be placed in a directory from which the web
#      server is allowed to execute cgis.  It should also have its
#      permissions set appropriately.  
#
#      Accompanying this script should be two  supporting files called 
#      cgi-lib.pl and mail-lib.pl which will be used to parse the form 
#      variables and handle emailing.  They should be kept in the same 
#      directory as this script (or in the cgi library preferrably) and 
#      be readable by the web server.
#
# Before you run this script, you need to prepare your HTML forms to send 
# enough information so that this script can be most efficient.  
# Specifically, you must send some information as hidden variables along 
# with the client-defined information.
#
# This script takes 17 hidden variables
#
# mailto - The email address of the person who should receive the results 
#     of form submission.  This field is REQUIRED.
# html_response - This is the text of the HTML response that you would 
#     like the client to receive after she submits her information.  This 
#     is not required, but a good idea.
# email_subject - is the subject that you want to appear on the email 
#     sent to the  person who will receive the results of form submission.  
#     This is not requied, but a good touch.
# variable_order - is the order that you want all of the variables to 
#     appear on the email sent to the person who will receive the results of 
#     form submission.  The format of this tag is a pipe delimited list
#     and every input field in your form MUST be represented in the list 
#     (see example below) This is a REQUIRED field.
# required_variables is a list of variables that are required.  That is, 
#     if the client does not fil out information for those input fields, she 
#     should get an error message requesting that she go back and fill out 
#     all the forms.  This field is not required.
# url_of_this_form is the url of the form that is being used to submit 
#     information so that if the user does not submit all the required 
#     fields, they can link back to the form to try again.  Not required
# background, bgcolor, text_color, link_color, vlink_color and alink_color
#     all relate to the body tag for all of the HTMl responses.  None of 
#     them are required but what is the good of GUI without graphics!
# response_title is the title that you want to appear on the HTML 
#     response for successes.  Not required, but suggested
# return_link_url is the url of the page that you want people to click on 
#     from the HTML response page after they have submitted their 
#     information.   Not required, but suggested.
# return_link_name is the text of the clickable link related to 
#     return_link_url.   Not required, but suggested
# database_name is the path (relative to this script) of the data file 
#     which is being used to store information submitted by this form.
# database_delimiter is the delimiter your database uses to divide 
#     fields.  Common ones are , or : or |
#
# These hidden variables define how this script needs to perform...who it 
# should email, how to order the variables in the email message, how to 
# respond to the client, etc...
#
# Here is an example of a very short form
#
# <HTML><HEAD><TITLE>Test Form</TITLE></HEAD><BODY>
# <FORM ACTION = "http://www.foobar.com/cgi-bin/form_processor.cgi"
#    METHOD = "POST">
# <INPUT TYPE = "hidden" NAME = "mailto" VALUE = "selena@net.com">
# <INPUT TYPE = "hidden" NAME = "html_response"
#        VALUE = "Thank you for submitting your personal information.">
# <INPUT TYPE = "hidden" NAME = "email_subject"
#        VALUE = "Form Test (From Scripts Page)">
# <INPUT TYPE = "hidden" NAME = "variable_order"
#        VALUE = "name|client_email|sign|purpose">
# <INPUT TYPE = "hidden" NAME = "required_variables"
#        VALUE = "name|client_email">
# <INPUT TYPE = "hidden" NAME = "url_of_this_form"
#        VALUE = "/cgi-bin/Selena/Form_processing/test_form1.cgi">
# <INPUT TYPE = "hidden" NAME = "background" VALUE = "">
# <INPUT TYPE = "hidden" NAME = "bgcolor" VALUE = "FFFFFF">
# <INPUT TYPE = "hidden" NAME = "text_color" VALUE = "000000">
# <INPUT TYPE = "hidden" NAME = "link_color" VALUE = "">
# <INPUT TYPE = "hidden" NAME = "vlink_color" VALUE = "">
# <INPUT TYPE = "hidden" NAME = "alink_color" VALUE = "">
# <INPUT TYPE = "hidden" NAME = "response_title" VALUE = "Thank You">
# <INPUT TYPE = "hidden" NAME = "return_link_name"
#        VALUE = "Selena Sol's Script Archive">
# <INPUT TYPE = "hidden" NAME = "return_link_url"
#        VALUE = "http://www.eff.org/~erict/Scritps/">
# <INPUT TYPE = "hidden" NAME = "database_name" VALUE = "Databases/main.data">
# <INPUT TYPE = "hidden" NAME = "database_delimiter" VALUE = ",">
#
# <P><B>Name (Required):</B><BR>
# <INPUT TYPE = "text" NAME = "name" SIZE = "35" MAXLENGTH = "35">
#
# <P><B>Email (Required):</B><BR>
# <INPUT TYPE = "text" NAME = "client_email" SIZE = "35" MAXLENGTH = "35">
#
# <P><B>Astrological Sign:</B><BR>
# <INPUT TYPE = "text" NAME = "sign" SIZE = "35" MAXLENGTH = "35">
#
# <P><B>Purpose in Life: </B><BR>
# <INPUT TYPE="text" NAME="purpose" SIZE="35" MAXLENGTH="35">
#
# <P><CENTER>
# <INPUT TYPE = "submit" VALUE = "Tell me about yourself!">
# </CENTER>
# </FORM></BODY></HTML>

# In this example, the script will email selena@eff.org when someone 
# submits form data.  It will use "Form Test (From Scripts Page)" as the 
# subject of the email, and return the client a little blurb with a 
# pointer back to Selena Sol's Script Archive.
#
# In the body of the email messsage it will print out the variables and 
# their client-defined values in the specific order name, email, sign, 
# and purpose of life.

# I'll explain more about how the script determines the order later, but 
# I want to draw your attention to the way the order is predefined in the 
# HTML form.  It is pipe delimited and all variables MUST appear in the 
# order you want them to be processed.

#######################################################################
#                       Begin Processing the Form.                    #
#######################################################################

# First, print out the HTTP header.  We'll output this quickly so that we
# will be able to do some of our debugging from the web and so that in
# the case of a bogged down server, we won't get timed-out.

  print "Content-type: text/html\n\n";

#######################################################################
#                     Set server specifc variables.                   #
#######################################################################

# $email_of_sender is the email address of the account from which mail 
#     should be sent to the admin.  This is only required if you have not 
#     used a $client_email variable in your form.

  $email_of_sender = "email\@email.net";

# $your_server_name is the name of your web server.  We will use this value 
# to make sure that the form that is using this script is actually on your 
# server...we wouldn't want everyone in the universe using your server for 
# form processing :)  If you are not sure what this is...it is probably 
# the "www.foobar.com" in your URL address.  This is only required if you 
# want the greater security

  $your_server_name = "www.msucob.com";

# $restricted_use is a flag that we will use to activate the above 
# security.  If you set this to no, it means that this script will process 
# forms from any server on the net.  This is only required if you
# want the greater security

  $restricted_use = "yes";

# $location_of_cgi-lib and $location_of_mail_lib are the locations of 
# the library files that should accompany this script.

  $location_of_cgi_lib = "cgi-lib.pl";
  $location_of_mail_lib = "mail-lib.pl";

# $should_i_mail and $should_I_append_a_database are flags which you can 
# set depending on how you want the results of the form processing to be 
# gathered.  By setting $should_i_mail = "yes" the form data will be sent 
# to the admin who you have already defined in above variables.  If you set 
# $should_I_append_a_database = "yes" then the form information will be 
# saved in a database that you can import to whatever database you use.  
# The name of the database are defined with hidden variables as are the 
# database delimiter...

  $should_i_mail = "yes";
  $should_I_append_a_database = "yes";

#######################################################################
#               Require Libraries and Parse Form Data                 #
#######################################################################

# Use cgi-lib.pl to read the incoming form data.  However, send form_data 
# as a parameter to the subroutine &ReadParse in cgi-lib.pl so that the 
# associative array of form keys/values comes back with a descriptinve 
# name rather than just $in. Also require the library which we will use 
# to send out mail using sendmail

  require "$location_of_cgi_lib";
  &ReadParse(*form_data);
  require "$location_of_mail_lib";

#######################################################################
#                            Security Test                            #
#######################################################################

# Next let's figure out where the form that is requesting our attention 
# is located.  We'll do this by accessing the environment variable
# $ENV{'HTTP_REFERER'} which is equal to the url of the form in question 
# (ie: http://www.foobar.com/Feedback/feedback.html).  We are going to take 
# that value and split it up into separate variables for every occurance of 
# "/".  We do this in order to isolate www.foobar.com which we can compare 
# to  the value of $your_server_name.  Thus $referring_server is the 
# only varriable here we actually give a hoot about.  If they are 
# not the same, the script # is being accessed by a form on another server.

($http, $empty, $referring_server, @path) = split (/\//, $ENV{'HTTP_REFERER'});

# Now if the $restricted_use has been set to yes, "and" the 
# $referring_server is not the same as $your_server_name it means that we 
# have had an illegal attempted access and we will deny the use of this 
# script.

  if ($restricted_use eq "yes")
    {   
    if ($referring_server ne "$your_server_name")
    {
    &html_header("Form Error - Wrong Server");
    print "I'm sorry, you are not allowed to use this form processing 
          script from a server other than $your_server_name<P>";
    print "As far as I can tell, you are coming from: $referring_server";
    print "<P>$restricted_use = restrictered use<BR>";
    print "</BODY></HTML>";
    exit;
    }
    }

#######################################################################
#                          Get Variable Order                         #
#######################################################################

# Now break up the variable_order variable that was sent to us from the 
# form.  It should look something like name|email|sign|purpose| and will
# have been defined by whoever wrote the form which calls this script
# We'll take that variable and split it into array elements everytime we 
# see a | so that @form_variables might look like ("name", "email",
# "sign", "purpose").

  @form_variables = split (/\|/, $form_data{'variable_order'});

#######################################################################
#                       Check Required Fields                         #
#######################################################################

# Now let's do the same thing we did for variable order, but for required 
# variables.

  @required_variables = split (/\|/, $form_data{'required_variables'});

# Now that we have the list of required variables, let's check to make 
# sure that the client submitted values for each of those variables.  If 
# the user did not, then they get a note explaining the problem and a list 
# of required variables so they won't do it again...asd well as a pointer 
# back to the form.  If you edit this note, make sure to "escape" any 
# occurances of @ or " with a backslash (ie: 
# print "<A HREF = \"mailto:selena\@eff.org\">selena\@eff.org</A>";

  foreach $variable (@required_variables)
    {
    if ($form_data{$variable} eq "")
      {
      &html_header("Form Error - Missing Data");
      print "Woops, I'm sorry, the following fields are required: ";
      print "<BLOCKQUOTE>";
      foreach $variable (@required_variables)
        {
        print "$variable<BR>";
        } # End of foreach $variable (@required_variables)
      print "</BLOCKQUOTE>";
      print "Please <A HREF = \"$form_data{'url_of_this_form'}\">go back to 
             the form</A> and make sure you fill out all the required 
             information."; 
      print "</BODY></HTML>";
      exit;
      } # End of if ($form_data{$variable} eq "")
    } # End of foreach $variable (@required_variables)

#######################################################################
#                  Email the Results to the Admin                     #
#######################################################################

  if ($should_i_mail eq "yes")
    {

# If we have set the $should_i_mail to yes in the define variables area, 
# then we want to send the results of the form to some admin alos defined...
# So break out the email address that was sent to us from the form into 
# both the email we should send the processed form data to as well as the 
# server which runs their email.  Also, rename the Email Subject

  if ($form_data{'mailto'} ne "")
    {
    $email_to = "$form_data{'mailto'}";
    }

    $email_subject = "$form_data{'email_subject'}";

# Then begin building the body of the email message that we will send.  
# We'll create a variables called $email_body which will store the 
# information that we are going to mail.  First we'll note the time with a 
# little routine written by Matt Wright.  Notice also the use of .= which 
# tells the script to append the new information to the end of the 
# old...thus $email_body just keeps getting longer and longer as new info 
# is tagged to the end of the old...

    $email_body = "This data was submitted on: ";
    $email_body .= &get_date;
    $email_body .="\n\n";

# For every form variable, we should add the variable name and their 
# values in the order specified by $form_data{'variable_order'}.

    foreach $variable (@form_variables)
      {
      $email_body .= "$variable = $form_data{$variable}\n";
      }

  if ($form_data{'client_email'} ne "")
    {
    $email_of_sender = "$form_data{'client_email'}";
    }

# Now, use the send_mail routine in mail-lib.pl to send the data.  The 
# send_mail routine takes 6 parameters, all of which have already been 
# defined and explained.

    &send_mail("$email_of_sender","$email_to",
               "$email_subject", "$email_body");

    } # End of  if ($should_i_mail eq "yes")

#######################################################################
#                       Append a Database                             #
#######################################################################

# If the $should_I_append_a_database has been set to yes, we will need to 
# append to the database specified in the hidden field database_name 
# specified in the form.

  if ($should_I_append_a_database eq "yes")
    {

# Check to see if the Database actually exists! (-e)

    $database = "$form_data{'database_name'}";
    if (-e $database)
      {

# If the database actually exists, open it for appending >> and set the 
# $counter variable equal to zero...we will use the $counter variable to 
# keep track of the number of fields sent from the form so that we will 
# know when the database row actually ends.

      open (DATABASE, ">>$database");
      $counter = "0";

# For every fields sent in from the form

      foreach $variable (@form_variables)
        {

# Increment the counter by one.

        $counter++;

# Append the value of the variable to the growing $database_row variable.

        $database_row .= "$form_data{$variable}";

# If this is not the last item in the row, we should also divide each 
# field with the database delimiter.  When counter equals the number of 
# elements in @form_variables, then we will know that it is the end of the 
# row and we need not append another delimiter.

        if ($counter <= @form_variables)
          {
 	  $database_row .= "$form_data{'database_delimiter'}";
          }

        } # End of foreach $variable (@form_variables)

# Now append the database with the new row...and don't forget the newline 
# at the end of the row.

      print DATABASE "$database_row\n";
      close (DATABASE);
      } # End of if (-e $database)

# If the database file did not exist, however, we need to send an error 
# message back to the user.  Most likely, the hidden form variable was not 
# correct (the path is wrong) or the permissions of the file or its 
# directory are not set to be read.writable by the web server.

    else
      {
      &html_header("Form Error - Database Does Not Exist"); 
      print "I'm sorry, I am having trouble finding the database that 
            this informatioon should be sent to.  Please contact <A HREF 
            = \"mailto:$form_data{'mailto'}\">$form_data{'mailto'}</A> and 
            let them know that there has been a problem.  Thank you very 
            much.";
      print "</BODY></HTML>";
      exit;
      }
    } # End of if ($should_I_append_a_database eq "yes")

#######################################################################
#                       Respond to the Client                         #
#######################################################################

# Now print up a response to the client.

  &html_header($form_data{'response_title'});
  print "$form_data{'html_response'}";
  print "<P>You sent us the follwing data:<P>";
  foreach $variable (@form_variables)
    {
    print "$variable = $form_data{$variable}<BR>";
    }

  print "<P>Please return to ";
  print "<A HREF = \"$form_data{'return_link_url'}\" 
         TARGET = \"_top\">$form_data{'return_link_name'}</A>";
  print "</BLOCKQUOTE>";
  print "</BODY></HTML>";
  exit;

#######################################################################
#                            get_date                                 #
#######################################################################

  sub get_date 
    {

   @days = ('Sunday','Monday','Tuesday','Wednesday','Thursday',
	    'Friday','Saturday');
   @months = ('January','February','March','April','May','June','July',
              'August','September','October','November','December');

# Use the localtime command to get the current time, splitting it into 
# variables.

   ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);

# Format the variables and assign them to the final $date variable.

   if ($hour < 10) { $hour = "0$hour"; }
   if ($min < 10) { $min = "0$min"; }
   if ($sec < 10) { $sec = "0$sec"; }

   $date = "$days[$wday], $months[$mon] $mday, 19$year at $hour\:$min\:$sec";
   }

#######################################################################
#                         html_header                                 #
#######################################################################

 sub html_header
   {

# Assign the title variable coming in from the subroutine call to the 
# local variable $title.

    local($title) = @_;

# Print out the header.

    print "<HTML><HEAD><TITLE>$title</TITLE></HEAD>";
    print "<BODY";

# Create the body tag the way the hidden form variables have defined it 
# to be.

    if ($form_data{'background'} ne "")
      {
      print " BACKGROUND = \"$form_data{'background'}\"";
      }
    if ($form_data{'bgcolor'} ne "")
      {
      print " BGCOLOR = \"$form_data{'bgcolor'}\"";
      }
    if ($form_data{'text_color'} ne "")
      {
      print " TEXT = \"$form_data{'text_color'}\"";
      }
    if ($form_data{'link_color'} ne "")
      {
      print " LINK = \"$form_data{'link_color'}\"";
      }
    if ($form_data{'vlink_color'} ne "")
      {
      print " VLINK = \"$form_data{'vlink_color'}'}\"";
      }
    if ($form_data{'alink_color'} ne "")
      {
      print " ALINK = \"$form_data{'alink_color'}\"";
      }
    print "><H2><CENTER>$title</CENTER></H2><BLOCKQUOTE>";
    }