<?php
// FormMailer, copyright 2007-2011, EB Dynamics, Inc., Ed Lemmers
// For licensing, see license.txt.
//
// This module may be customized to your needs, however, the design is intended to cover all
// form mailing needs without modification by directing this module through hidden fields
// from within your form.  Having said that, we know there will always be something else that
// is required, but we think this module should do a good job of handling most situations
// without modification.	

// Modify the line below for your particular website.  This will eliminate attacks from remote servers.
//$referers = array('www.example.com', 'example.com');
$server_name = $_SERVER['SERVER_NAME'];
$server_name_www = "www." . $server_name;
$referers = array($server_name_www, $server_name);


// Module for performaing actual email operation.
include("mime_mail.inc");
// DB connection for retrieving HTML message format for message back to inquirer, etc.
include("../connect/db_connection.php");
include("../connect/config.php");

// Used in conjunciton with $referers to eliminate atacks from remote servers.
$valid_env = array('REMOTE_HOST', 'REMOTE_ADDR', 'REMOTE_USER', 'HTTP_USER_AGENT');

// List of key fields to ignore (not customer data, but rather configuration hidden fields).
$ignore_fields = array("email_confirm", "Submit", "submit", "redirect", "from", "reply_to", "recipient", "email_required", "required_fields", "html_message_page", "table_name", "no_duplicates", "password_confirm", "password_required", "use_email_as_userid", "html", "no_mime", "Submit_x", "Submit_y");

// List of longtext type fields.
$longtext_fields = array("comments", "note", "notes", "suggestions", "feedback", "question", "questions");

// From hidden fields to direct mail to site manager and forward page to desired message, etc.
// "recipient", "redirect" and "subject" are required.  If "from" is left blank then the 'from' 
// will show as "Mail Request Form <email>".  If "html" is left blank, then the message will
// default to text.
// If desired, you may repalec the @ simbol with 5 plus signs in your mail form.  This will prenvent robots from harvesting your email
// until this technique gains popularity.
$recipient = $_POST['recipient'];
$recipient = str_replace("+++++", "@", $recipient);
$redirect = $_POST['redirect'];
$subject = $_POST['subject'];
$reply_to = $_POST['reply_to'];
$from = $_POST['from'];
if ($_POST['html'])
	$html = 1;	// html
else
	$html = 0;	// text
if ($_POST['no_mime'])
	$no_mime = 1;	// Certain servers can't handle mime messages such as GoDaddy hosting.
else
	$no_mime = 0;
if ($_POST['octet_stream'])
	$octet_stream = 1;	// If adding attachments, then it might be necessary to set the content type to application/octet-stream.
else
	$octet_stream = 0;
if ($_POST['html_msg_as_text'])
	$html_msg_as_text = 1;	// Override to send HTML message to form user as text instead.
else
	$html_msg_as_text = 0;
	
// Special flag to denote that 'email' is a required field.  If 'email' is required here, 'email_confirm'
// will also be required.  If you do not need email confirm, then add "email" to the 'required_fields'
// string on your form instead.
$email_required = $_POST['email_required'];

// Special flag to denote that 'password' is a required field.  If 'password' is required here,
// 'password_confirm' will also be required.
$password_required = $_POST['password_required'];

// You may specify which fields are required to be filled in.  Use a comma "," to separate fields.
$required_fields = $_POST['required_fields'];
if ($required_fields)
{
	$required_field_array = explode(",", $required_fields);
	foreach ($required_field_array as $value)
	{
		if (!$_POST[$value])
		{
			echo <<<END
				<br>
				<div align="center">
				<h2>The '$value' field has not been filled in.  Please fill in this field.</h2>
				<h2><a href="javascript:history.go(-1)">Click here</a> to return to the previous page, or use your 'Back' button.</h2>
				</div>
				<br>
END;
			exit;
		}	
	}
}

// Information from user input.  Possible expected fields that may require special handling.
$email	= $_POST['email'];
$email_confirm = $_POST['email_confirm'];
$password	= $_POST['password'];
$password_confirm = $_POST['password_confirm'];
$use_email_as_userid = $_POST['use_email_as_userid'];

// If email required flag is sent, then verify that 'email' has been filled in and 'email_confirm'
// matches 'email'.
if (((!$email) || ($email != $email_confirm)) && $email_required)
{
	echo <<<END
	<br>
	<div align="center">
	<h2>Your email is blank or does not match the confirm.  Please fill in your email address.</h2>
	<h2><a href="javascript:history.go(-1)">Click here</a> to return to the previous page, or use your 'Back' button.</h2>
	</div>
	<br>
END;

exit;
}

// If password required flag is sent, then verify that 'password' has been filled in and 'password_confirm'
// matches 'password'.
if (((!$password) || ($password != $password_confirm)) && $password_required)
{
	echo <<<END
	<br>
	<div align="center">
	<h2>Your password is blank or does not match the confirm.  Please fill in your password.</h2>
	<h2><a href="javascript:history.go(-1)">Click here</a> to return to the previous page, or use your 'Back' button.</h2>
	</div>
	<br>
END;

exit;
}

// Check email address to make sure it is not bogus.
if ($email_required)
{
	if (!check_email_address($email))
	{
		echo <<<END
		<br>
		<div align="center">
		<h2>The email address $email is not valid.  Please go back and type your email address again.</h2>
		<h2><a href="javascript:history.go(-1)">Click here</a> to return to the previous page, or use your 'Back' button.</h2>
		</div>
		<br>
END;

	exit;
	}
}
	
// Check referers to make sure SPAM bot is not trying to brake in.
if (!check_referer($referers))
{
	echo <<<END
	<br>
	<div align="center">
	<h2>You do not appear to be a valid.  If this is in error, go back and try again.</h2>
	<h2><a href="javascript:history.go(-1)">Click here</a> to return to the previous page, or use your 'Back' button.</h2>
	</div>
	<br>
END;

	exit;
}

// In many instances, it is desirable to use the email address as the user ID.
if (isset($use_email_as_userid))
{
	$_POST['UserID'] = $email;
	$_POST['userid'] = $email;
}

//Mail fields to recipient.
$mail = new mime_mail;

if ($from)
	$from_email = "$from";
else
	$from_email = "Mail Request Form <$email>";
	
$to_email = $recipient;
//$cc_email = "ed@ebdynamics.com";	//for testing

	
if ($html == 1)
	$lf = "<br>";
else
	$lf = "\n";

$msg = $_POST;
foreach ( $msg as $key => $value )
{
	// If a phone number is found, then check for robot attacks.
	if ((strpos($key, "phone") > -1) && ($key != "preferred_phone"))
	{
		if (!CheckPhoneField($value))
		{
			header("Location: $redirect");
			exit;
		}
	}
	
	if ((!in_array($key, $ignore_fields)) && ($key != "subject"))
		$msg = $msg."$lf".$key.": ".$value;
}
$msg = str_replace( "Array", "", $msg );
if ($html == 1)
	$msg = "<b>$subject</b>$lf" . $msg;
else
	$msg = "$subject$lf" . $msg;

/////////// Check for robots by counting URLs. ////////////////////
$http_cnt = 0;
$pos = stripos($msg, "http");
if ($pos !== false)
{
	$http_cnt++;
	$pos2 = stripos($msg, "http", $pos + 1);
	if ($pos2 !== false)
		$http_cnt++;
}
if ($http_cnt > 1)
{
	header("Location: $redirect");
	exit;
}
/////////// Check for robots by counting URLs. ////////////////////

$mail->from = $from_email;
$mail->to = $to_email;
$mail->cc = $cc_email;
$mail->replyto = $reply_to;
$mail->subject = $subject;
$mail->body = $msg;
$mail->html = $html;
$mail->no_mime = $no_mime;
$mail->octet_stream = $octet_stream;

$mail->send();

$email_ext = substr($to_email, strlen($to_email) - 8);
if ($email_ext == "@aol.com")	// AOL emails
	mail($to_email, $subject, $msg);

/////////////////////////////////////////////////////////////////////////
// Pipe data to table.  Create table if it does not exist.
$table_name = $_POST['table_name'];
if (isset($table_name) && ($table_name != ""))
{	
	$table_name = mysql_real_escape_string($table_name);
	// Check to see if table exists.
	$query = "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '[$bwb_database]' AND table_name = '[$table_name]'";
	$result = mysql_query($query, $bwb_link);
	$row = mysql_fetch_array($result);
	if ($row["COUNT"] < 1)
	{
		$query = "CREATE TABLE IF NOT EXISTS `$table_name` (`id` bigint(20) NOT NULL auto_increment, ";
		// Add column for each key.
		foreach ($_POST as $key => $value)
		{
			$key = mysql_real_escape_string($key);
			if (in_array($key, $longtext_fields))
				$query .= "`$key` longtext default NULL, ";
			elseif (!in_array($key, $ignore_fields))
				$query .= "`$key` varchar(255) default NULL, ";
		}
		// Add created field.
		$query .= "`created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, ";
		// Add primary key.
		$query .= "PRIMARY KEY  (`id`) ) TYPE=MyISAM AUTO_INCREMENT=1";
		$result = mysql_query($query, $bwb_link);
	}
	
	// Add any missing columns due to new fields in form.
	foreach ($_POST as $key => $value)
	{
		$key = mysql_real_escape_string($key);
		$field_found = false;
		$query ="SHOW COLUMNS FROM $bwb_database.$table_name";
		$result = mysql_query($query, $bwb_link);
		while ($row = mysql_fetch_array($result))
		{
			if ($row['field'] == $key)
				$field_found = true;
		}
		if (in_array($key, $longtext_fields))
		{
			$query2 = "ALTER TABLE `$table_name` ADD `$key` longtext NULL ";
			$result2 = mysql_query($query2, $bwb_link);
		}
		elseif (!$field_found && !in_array($key, $ignore_fields))
		{
			$query2 = "ALTER TABLE `$table_name` ADD `$key` VARCHAR( 255 ) NULL ";
			$result2 = mysql_query($query2, $bwb_link);
		}
	}
	
	// If no_duplicates defined, then check to see if record already exists.
	$no_duplicates = $_POST['no_duplicates'];
	if ($no_duplicates)
	{
		$no_dupes_array = explode(",", $no_duplicates);
		foreach ($no_dupes_array as $value)
		{
			$unique_field_val = $_POST[$value];
			$query = "SELECT * FROM " . $table_name . " WHERE `" . $value . "`='" . $unique_field_val . "'";
			$result = mysql_query($query, $bwb_link);
			if (mysql_num_rows($result) > 0)
			{	
				echo <<<END
					<br>
					<div align="center">
					<h2><b>$unique_field_val</b> already exists for the <b>$value</b> field.  You will need to enter a different $value.</h2>
					<h2><a href="javascript:history.go(-1)">Click here</a> to return to the previous page, or use your 'Back' button.</h2>
					</div>
					<br>
END;
				exit;
			}
		}
	}
	
	// Insert row.
	$query = "INSERT INTO `$table_name` SET ";
	$first = true;
	if (isset($_POST['userid']) && isset($_POST['UserID']))
	{	// Can't have both, need to consolitade.
		if ($_POST['userid'] == $_POST['UserID'])
			unset($_POST['userid']);
		elseif (strlen($_POST['userid']) > strlen($_POST['userid']))
			unset($_POST['UserID']);
		else
			unset($_POST['userid']);
	}
	foreach ($_POST as $key => $value)
	{
		$key = mysql_real_escape_string($key);
		if (!in_array($key, $ignore_fields))
		{
			$value = mysql_real_escape_string($value);
			//If password found, encrypt password using user ID,last name or email address as key.
			if ($key == "password")
			{
				if (isset($_POST['userid']))
					$value = doEncrypt($value, $_POST['userid']);
				elseif (isset($_POST['UserID']))
					$value = doEncrypt($value, $_POST['UserID']);
				elseif (isset($_POST['last_name']))
					$value = doEncrypt($value, $_POST['last_name']);
				elseif (isset($_POST['email']))
					$value = doEncrypt($value, $_POST['email']);
			}
	
			if (!$first) $query .= ", "; else $first = false;
			$query .= "`$key` = '$value'";
		}
	}
	$result = mysql_query($query, $bwb_link);
	
	// Get last inserted id for possible use by other modules.
	$last_id = mysql_insert_id($bwb_link);
	
	/////////////////////////////////////////////
	// If table is user table for page access, then see if need to activate right now.
	$query = "SELECT option_value FROM `" . BWB_TABLE_PREFIX . "options_selected` WHERE option_name='ActivateNewUsersAutomatically'";
	$result = mysql_query($query, $bwb_link);
	$row = mysql_fetch_array($result);
	$activate = $row['option_value'];
	
	if ($activate == 1)
	{
		$got_active = false;
		$got_session = false;
		$got_ip = false;
		$got_userid = false;
		$got_password = false;
		$query ="SHOW COLUMNS FROM $bwb_database.$table_name";
		$result = mysql_query($query, $bwb_link);
		while ($row = mysql_fetch_array($result))
		{
			if ($row['field'] == "Active")
				$got_active = true;
			if ($row['field'] == "Session")
				$got_session = true;
			if ($row['field'] == "IP")
				$got_ip = true;
			if (($row['field'] == "UserID") || ($row['field'] == "userid"))
				$got_userid = true;
			if ($row['field'] == "password")
				$got_password = true;
		}
		if ($got_active && $got_session && $got_ip && $got_userid && $got_password)
		{
			$query = "UPDATE `$table_name` SET `Active`=1 WHERE id=$last_id";
			$result = mysql_query($query, $bwb_link);
		}
	}
	/////////////////////////////////////////////
}

/////////////////////////////////////////////////////////////////////////
// Send HTML message to inquirer if message is setup.
$html_message_page = $_POST['html_message_page'];
if (isset($html_message_page) && ($html_message_page != ""))
{
	$first_name = $_POST['first_name'];
	$last_name = $_POST['last_name'];
	if (isset($_POST['UserID']))
		$userid = $_POST['UserID'];
	elseif (isset($_POST['userid']))
		$userid = $_POST['userid'];
	else
		$userid = "";
	
	$html_message_page = mysql_real_escape_string($html_message_page);
	$query = "SELECT * FROM " . BWB_TABLE_PREFIX . "page_data WHERE page_name = '". $html_message_page . "'";
	$result = mysql_query($query, $bwb_link);
	if ($row = mysql_fetch_array($result))
	{
		$html_msg = stripslashes($row["page_content"]);
		$html_msg = str_replace("[FIRST_NAME]", $first_name, $html_msg);
		$html_msg = str_replace("[LAST_NAME]", $last_name, $html_msg);
		$html_msg = str_replace("[USER_ID]", $userid, $html_msg);
		$html_msg = str_replace("[PASSWORD]", $password, $html_msg);
		
		$mail->from = $from;
		$mail->to = $email;
		$mail->replyto = $reply_to;
		$mail->subject = $subject;
		$mail->body = $html_msg;
		if ($html_msg_as_text == 1)
			$mail->html = 0;
		else
			$mail->html = 1;
		$mail->no_mime = $no_mime;
		$mail->octet_stream = $octet_stream;
		
		$mail->send();
		
		$email_ext = substr($email, strlen($email) - 8);
		if ($email_ext == "@aol.com")	// AOL emails
			mail($email, $subject, $html_msg);
	}
}

/////////////////////////////////////////////////////////////////////////
// If data stored in table, then pass along last id to next page.
if (isset($table_name) && ($table_name != ""))
{
	if (strpos($redirect, "?") > 0)
		$redirect .= "&last_id=" . $last_id;
	else
		$redirect .= "?last_id=" . $last_id;
}
// Go to desired next page.
header("Location: $redirect");
exit;

/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
// Check for valid emails. //////////////////////////////////////////////
function check_email_address($email) {
// First, we check that there's one @ symbol, and that the lengths are right
	if (!ereg("^[^@]{1,64}@[^@]{1,255}$", $email)) {
		// Email invalid because wrong number of characters in one section, or wrong number of @ symbols.
		return false;
	}
	// Split it into sections to make life easier
	$email_array = explode("@", $email);
	$local_array = explode(".", $email_array[0]);
	for ($i = 0; $i < sizeof($local_array); $i++) {
		if (!ereg("^(([A-Za-z0-9!#$%&'*+/=?^_`{|}~-][A-Za-z0-9!#$%&'*+/=?^_`{|}~\.-]{0,63})|(\"[^(\\|\")]{0,62}\"))$", $local_array[$i])) {
		return false;
		}
	}
	if (!ereg("^\[?[0-9\.]+\]?$", $email_array[1])) { // Check if domain is IP. If not, it should be valid domain name
		$domain_array = explode(".", $email_array[1]);
		if (sizeof($domain_array) < 2) {
			return false; // Not enough parts to domain
		 }
		for ($i = 0; $i < sizeof($domain_array); $i++) {
			 if (!ereg("^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]+))$", $domain_array[$i])) {
				return false;
			 }
		}
	 }
	 return true;
}

/****************************************************************
 * check_referer() breaks up the enviromental variable		*
 * HTTP_REFERER by "/" and then checks to see if the second	*
 * member of the array (from the explode) matches any of the	*
 * domains listed in the $referers array (declaired at top)	*
 ****************************************************************/

function check_referer($referers)
{
	global $errors;
	if (count($referers)) {
		if (getenv('HTTP_REFERER')) {
			$temp = explode('/', getenv('HTTP_REFERER'));
			$found = false;
			while (list(,$stored_referer) = each($referers)) {
				if (eregi('^' . $stored_referer . '$', $temp[2]))
					$found = true;
			}
			if (!$found) {
				$errors[] = '1|You are coming from an unauthorized domain.  Please read the manual section titled &quot;<a href="' . MANUAL . '#setting_up" target="_blank">Setting Up the PHPFormMail Script</a>&quot;.';
				error_log('[PHPFormMail] Illegal Referer. (' . getenv('HTTP_REFERER') . ')', 0);
			}
			return $found;
		} else {
			$errors[] = '0|Sorry, but I cannot figure out who sent you here.  Your browser is not sending an HTTP_REFERER.  This could be caused by a firewall or browser that removes the HTTP_REFERER from each HTTP request you submit.';
			error_log('[PHPFormMail] HTTP_REFERER not defined. Browser: ' . getenv('HTTP_USER_AGENT') . '; Client IP: ' . getenv('REMOTE_ADDR') . '; Request Method: ' . getenv('REQUEST_METHOD') . ';', 0);
			return false;
		}
	} else {
		$errors[] = '1|There are no referers defined.  All submissions will be denied.  Please read the manual section titled &quot;<a href="' . MANUAL . '#setting_up" target="_blank">Setting Up the PHPFormMail Script</a>&quot;.';
		error_log('[PHPFormMail] You have no referers defined.  All submissions will be denied.', 0);
		return false;
	}
}

///////////////////////////////////////////////////////////////
// Check all phone numbers for valid charecters.
function CheckPhoneField($number)
{
	$formats = array('###-###-####', '####-###-###',
                 '(###) ###-###', '(###)###-###', '####-####-####',
                 '##-###-####-####', '####-####', '###-###-###',
                 '#####-###-###', '##########',
				 '#-###-###-####', '#-####-###-###',
                 '# (###) ###-###', '#(###)###-###', '#-####-####-####',
                 '#-##-###-####-####', '#-####-####', '#-###-###-###',
                 '#-#####-###-###', '###########',
				 '##-###-###-####', '##-####-###-###',
                 '##-####-####-####',
                 '##-##-###-####-####', '##-####-####', '##-###-###-###',
                 '##-#####-###-###', '############');
	
	if (strlen($number) == 0)
		return true;	// Don't worry about blank phone numbers here.
		
	if ( preg_match("/^[A-Za-z]$/", $number) )
		return false;	// If any letters are found, then most likely bogus junk found.
		
	// + and _ are OK, -so remove for testing.
	$ignore_chars = array("+", "_");
	$number = str_replace($ignore_chars, "", $number);
	// . is used inplace of - many times, so just replace.
	$number = str_replace(".", "-", $number);
		
	$format = trim(preg_replace("/[0-9]/", "#", $number));
	return (in_array($format, $formats)) ? true : false;
}

/////////////////////////////////
function doEncrypt($Data, $Key)
{
// encrypting  a[] with key k[] into e[]
// a[] = array to be encrypted
// k[] = key of truly random gibberish
// e[] = encrypted data

	for( $i = 0; $i < strlen($Data); $i++)
	{
		$c = substr($Data, $i, 1);
		$a[$i] = ord($c);
	}
	
	for( $i = 0; $i < strlen($Data); $i++)
	{
		if ($i < strlen($Key))
		{
			$c = substr($Key, $i, 1);
			$k[$i] = ord($c);
		}
		else
			$k[$i] = 65 + $i;
	}
	
	for ( $i=0; $i < strlen($Data); $i++ )
   	{
   		$e[$i] = $k[$i] ^ $a[$i];
   	}
	
	$encrypted = "";
	for ( $i = 0; $i < strlen($Data); $i++ )
	{
		$encrypted = $encrypted. decToHex($e[$i]);
	}
	return($encrypted);
	
}

function decToHex($dec)
{
	$hexStr = "0123456789ABCDEF";
	$low = $dec % 16;
	$high = ($dec - $low)/16;
	$hex = "";
	$hex = substr($hexStr, $high, 1) . substr($hexStr, $low, 1);
	return $hex;
}

?>