#!/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>";
}