#!/usr/bin/perl
##############################################################################
# FormMail                        Version 1.92                               #
# Copyright 1995-2002 Matt Wright mattw@scriptarchive.com                    #
# Created 06/09/95                Last Modified 04/21/02                     #
# Matt's Script Archive, Inc.:    http://www.scriptarchive.com/              #
##############################################################################
# COPYRIGHT NOTICE                                                           #
# Copyright 1995-2002 Matthew M. Wright  All Rights Reserved.                #
#                                                                            #
# FormMail may be used and modified free of charge by anyone so long as this #
# copyright notice and the comments above remain intact.  By using this      #
# code you agree to indemnify Matthew M. Wright from any liability that      #
# might arise from its use.                                                  #
#                                                                            #
# Selling the code for this program without prior written consent is         #
# expressly forbidden.  In other words, please ask first before you try and  #
# make money off of my program.                                              #
#                                                                            #
# Obtain permission before redistributing this software over the Internet or #
# in any other medium. In all cases copyright and header must remain intact. #
##############################################################################
# ACCESS CONTROL FIX: Peter D. Thompson Yezek                                #
#                     http://www.securityfocus.com/archive/1/62033           #
##############################################################################
# Define Variables                                                           #
#      Detailed Information Found In README File.                            #

# $mailprog defines the location of your sendmail program on your unix       #
# system. The flags -i and -t should be passed to sendmail in order to       #
# have it ignore single dots on a line and to read message for recipients    #

$mailprog = '/usr/lib/sendmail -i -t';

# @referers allows forms to be located only on servers which are defined     #
# in this field.  This security fix from the last version which allowed      #
# anyone on any server to use your FormMail script on their web site.        #

@referers = ('scriptarchive.com','209.196.21.3');

# @recipients defines the e-mail addresses or domain names that e-mail can   #
# be sent to.  This must be filled in correctly to prevent SPAM and allow    #
# valid addresses to receive e-mail.  Read the documentation to find out how #
# this variable works!!!  It is EXTREMELY IMPORTANT.                         #
@recipients = &fill_recipients(@referers);

# ACCESS CONTROL FIX: Peter D. Thompson Yezek                                #
# @valid_ENV allows the sysadmin to define what environment variables can    #
# be reported via the env_report directive.  This was implemented to fix     #
# the problem reported at http://www.securityfocus.com/bid/1187              #

@valid_ENV = ('REMOTE_HOST','REMOTE_ADDR','REMOTE_USER','HTTP_USER_AGENT');

# Done                                                                       #
##############################################################################

# Check Referring URL
&check_url;

# Retrieve Date
&get_date;

# Parse Form Contents
&parse_form;

# Check Required Fields
&check_required;

# Send E-Mail
&send_mail;

# Return HTML Page or Redirect User
&return_html;

# NOTE rev1.91: This function is no longer intended to stop abuse, that      #
#    functionality is now embedded in the checks made on @recipients and the #
#    recipient form field.                                                   #

sub check_url {

        # Localize the check_referer flag which determines if user is
	# valied'});
	    @Env_Report = split(/,/,$Config{'env_report'});
	        @Print_Config = split(/,/,$Config{'print_config'});

		    # ACCESS CONTROL FIX: Only allow ENV variables in
		    # @valid_ENV in          #
		        # @Env_Report for security reasons.
			# #
			    foreach $env_item (@Env_Report) {
				        foreach $valid_item (@valid_ENV) {
					                if ( $env_item eq
							$valid_item ) {
							    push(@temp_array,
							    $env_item) }
							            }
								        } 
									    @Env_Report
									    =
									    @temp_array;
									}

									sub
									check_required
									{

									        # Localize
										# the
										# variables
										# used
										# in
										# this
										# subroutine.
										# #
										    local($require,
										    @error);

										        # The
											# following
											# insures
											# that
											# there
											# were
											# no
											# newlines
											# in
											# any
											# fields
											# which
											# #
											    # will
											    # be
											    # used
											    # in
											    # the
											    # header.
											    # #
											        if
												($Config{'subject'}
												=~
												/(\n|\r)/m
												||
												$Config{'email'}
												=~
												/(\n|\r)/m
												||
												        $Config{'realname'}
													=~
													/(\n|\r)/m
													||
													$Config{'recipient'}
													=~
													/(\n|\r)/m)
													{
													            &error('invalid_headers');
														        }

															    if
															    (!$Config{'recipient'})
															    {
																        if
																	(!defined(%Form))
																	{
																	    &error('bad_referer')
																	    }
																	            else
																		    {
																			&error('no_recipient')
																			}
																			    }
																			        else
																				{
																				            # This
																					    # block
																					    # of
																					    # code
																					    # requires
																					    # that
																					    # the
																					    # recipient
																					    # address
																					    # end
																					    # with
																					    # #
																					            # a
																						    # valid
																						    # domain
																						    # or
																						    # e-mail
																						    # address
																						    # as
																						    # defined
																						    # in
																						    # @recipients.
																						    # #
																						            $valid_recipient
																							    =
																							    0;
																							            foreach
																								    $send_to
																								    (split(/,/,$Config{'recipient'}))
																								    {
																									            foreach
																										    $recipient
																										    (@recipients)
																										    {
																											                if
																													($send_to
																													=~
																													/$recipient$/i)
																													{
																													                        push(@send_to,$send_to);
																																last;
																																                }
																																		            }
																																			            }
																																				            if
																																					    ($#send_to
																																					    <
																																					    0)
																																					    {
																																						&error('no_recipient')
																																						}
																																						        $Config{'recipient'}
																																							=
																																							join(',',@send_to);
																																							    }

																																							        # For
																																								# each
																																								# require
																																								# field
																																								# defined
																																								# in
																																								# the
																																								# form:
																																								# #
																																								    foreach
																																								    $require
																																								    (@Required)
																																								    {

																																									        # If
																																										# the
																																										# required
																																										# field
																																										# is
																																										# the
																																										# email
																																										# field,
																																										# the
																																										# syntax
																																										# of
																																										# the
																																										# email
																																										# #
																																										        # address
																																											# if
																																											# checked
																																											# to
																																											# make
																																											# sure
																																											# it
																																											# passes
																																											# a
																																											# valid
																																											# syntax.
																																											# #
																																											        if
																																												($require
																																												eq
																																												'email'
																																												&&
																																												!&check_email($Config{$require}))
																																												{
																																												                push(@error,$require);
																																														        }

																																															        # Otherwise,
																																																# if
																																																# the
																																																# required
																																																# field
																																																# is
																																																# a
																																																# configuration
																																																# field
																																																# and
																																																# it
																																																# #
																																																        # has
																																																	# no
																																																	# value
																																																	# or
																																																	# has
																																																	# been
																																																	# filled
																																																	# in
																																																	# with
																																																	# a
																																																	# space,
																																																	# send
																																																	# an
																																																	# error.
																																																	# #
																																																	        elsif
																																																		(defined($Config{$require}))
																																																		{
																																																		                if
																																																				($Config{$require}
																																																				eq
																																																				'')
																																																				{
																																																				    push(@error,$require);
																																																				    }
																																																				            }

																																																					            # If
																																																						    # it
																																																						    # is
																																																						    # a
																																																						    # regular
																																																						    # form
																																																						    # field
																																																						    # which
																																																						    # has
																																																						    # not
																																																						    # been
																																																						    # filled
																																																						    # in
																																																						    # or
																																																						    # #
																																																						            # filled
																																																							    # in
																																																							    # with
																																																							    # a
																																																							    # space,
																																																							    # flag
																																																							    # it
																																																							    # as
																																																							    # an
																																																							    # error
																																																							    # field.
																																																							    # #
																																																							            elsif
																																																								    (!defined($Form{$require})
																																																								    ||
																																																								    $Form{$require}
																																																								    eq
																																																								    '')
																																																								    {
																																																									            push(@error,$require);
																																																										            }
																																																											        }

																																																												    # If
																																																												    # any
																																																												    # error
																																																												    # fields
																																																												    # have
																																																												    # been
																																																												    # found,
																																																												    # send
																																																												    # error
																																																												    # message
																																																												    # to
																																																												    # the
																																																												    # user.
																																																												    # #
																																																												        if
																																																													(@error)
																																																													{
																																																													    &error('missing_fields',
																																																													    @error)
																																																													    }
																																																													}

																																																													sub
																																																													return_html
																																																													{
																																																													        # Local
																																																														# variables
																																																														# used
																																																														# in
																																																														# this
																																																														# subroutine
																																																														# initialized.
																																																														# #
																																																														    local($key,$sort_order,$sorted_field);

																																																														        # Now
																																																															# that
																																																															# we
																																																															# have
																																																															# finished
																																																															# using
																																																															# form
																																																															# values
																																																															# for
																																																															# any
																																																															# e-mail
																																																															# related
																																																															# #
																																																															    # reasons,
																																																															    # we
																																																															    # will
																																																															    # convert
																																																															    # all
																																																															    # of
																																																															    # the
																																																															    # form
																																																															    # fields
																																																															    # and
																																																															    # config
																																																															    # values
																																																															    # #
																																																															        # to
																																																																# remove
																																																																# any
																																																																# cross-site
																																																																# scripting
																																																																# security
																																																																# holes.
																																																																# #
																																																																    local($field);
																																																																        foreach
																																																																	$field
																																																																	(keys
																																																																	%Config)
																																																																	%{
																																																																	            $safeConfig{$field}
																																																																		    =
																																																																		    &clean_html($Config{$field});
																																																																		        }

																																																																			    foreach
																																																																			    $field
																																																																			    (keys
																																																																			    %Form)
																																																																			    %{
																																																																				        $Form{$field}
																																																																					=
																																																																					&clean_html($Form{$field});
																																																																					    }


																																																																					        # If
																																																																						# redirect
																																																																						# option
																																																																						# is
																																																																						# used,
																																																																						# print
																																																																						# the
																																																																						# redirectional
																																																																						# location
																																																																						# header.
																																																																						# #
																																																																						    if
																																																																						    ($Config{'redirect'})
																																																																						    {
																																																																							        print
																																																																								"Location:
																																																																								$safeConfig{'redirect'}\n\n";
																																																																								    }

																																																																								        # Otherwise,
																																																																									# begin
																																																																									# printing
																																																																									# the
																																																																									# response
																																																																									# page.
																																																																									# #
																																																																									    else
																																																																									    {

																																																																										        # Print
																																																																											# HTTP
																																																																											# header
																																																																											# and
																																																																											# opening
																																																																											# HTML
																																																																											# tags.
																																																																											# #
																																																																											        print
																																																																												"Content-type:
																																																																												text/html\n\n";
																																																																												        print
																																																																													"<html>\n
																																																																													<head>\n";

																																																																													        # Print
																																																																														# out
																																																																														# title
																																																																														# of
																																																																														# page
																																																																														# #
																																																																														        if
																																																																															($Config{'title'})
																																																																															{
																																																																															    print
																																																																															    "<title>$safeConfig{'title'}</title>\n"
																																																																															    }
																																																																															            else
																																																																																    {
																																																																																	print
																																																																																	"<title>Thank
																																																																																	You</title>\n"
																																																																																	}

																																																																																	        print
																																																																																		"
																																																																																		</head>\n
																																																																																		<body";

																																																																																		        # Get
																																																																																			# Body
																																																																																			# Tag
																																																																																			# Attributes 
