<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
// BotBanish 7.1.06
// Randem Systems: https://randemsystems.support
// BotBanish Contact Form SPAM Denial
// Date: 04/16/2025
//
// Function: Deny SPAM Messages
//
// SMF: 		array(&$subject, &$message, &$headers, &$to_array)
// WordPress:	array('to' => &to, 'Subject' => &subject, 'Message' => &message, 'headers' => &headers, 'attachments' => &attachments)
//
//	------------------
//	Message Type 1
//	------------------
//
//	$msg = '
//	to Array(
//		0 => sales@randemsystems.com
//	)
//	subject = Contact from Randem System\'s Website
//	message = <p></p>
//	<ol>
//	<li><b>Your name</b><br />Louis Key</li>
//	<li><b>Your email</b><br /><a href="mailto:ocasio.roberto95@msn.com">ocasio.roberto95@msn.com</a></li>
//	<li><b>Phone</b><br />494340380</li>
//	<li><b>Subject</b><br />You might Like this</li>
//	<li><b>Your message</b><br />Hi,
//	<p>I came across your website and thought Deel could be a great fit for your business.<br />
//	It’s a platform that makes managing payroll, contracts, taxes, and compliance easy. Whether you\’re hiring locally or globally, Deel helps automate payments, stay compliant with tax laws, and handle accounts across countries.</p>
//	<p>Check it out here: <a href="https://bit.ly/deel-for-business" rel="nofollow">https://bit.ly/deel-for-business</a><br />
//	Or, if you know anyone else who might benefit, feel free to forward this to them!</p>
//	<p>Best,<br />
//	Louis</li>
//	</ol>
//	<p></p>
//
//	headers Array(
//		0 => From: Randem Systems <noreply@randemsystems.com>
//		1 => Content-Type: text/html; charset=UTF-8
//	)
//	attachments Array(
//	)';
//
//	------------------
//	Message Type 2
//	------------------
//
//	$msg = '
//	to = support@randemsystems.com
//	subject = BotBanish Contact From Website
//	message = From: htXbGrzHfsdI
//	Email: wxhirtzxm@yahoo.com
//	Phone: 4782640790
//	Subject: fVXAiNTeH
//
//	Message Body:
//
//	headers = From: BotBanish <wordpress@botbanish.com>
//	X-WPCF7-Content-Type: text/plain
//	Reply-To: wxhirtzxm@yahoo.com
//
//	attachments Array(
//	)';
///////////////////////////////////////////////////////////////////////////////////////////////////////

function BotBanishCheckContact() {

	global $BotBanishSettings;

	$row = BotBanishGetContactPassedData();
	$BotBanishSettings['DOMAIN_NAME'] = isset($row['domain_name']) ? $row['domain_name'] : $BotBanishSettings['BOTBANISH_USER_HOST'];
	$action = BotBanishValidateFormSpamContact($row);
	$action['bot_ip'] = $row['bot_ip'];
	return $action;
}

function BotBanishValidateFormSpamContact($row) {

	$action = array('terminate' => false, 'error' => '', 'args' => $row);

	if (!isset($row['args']) || empty($row['args'])) {

		$action['error'] = 'No Arguments?';
		return $action;
	}

	$orig_args = $row['args'];
	$orig_tags = BotBanishFixExplode(',', $row['BOTBANISH_CONTACT_TAGS']);

	if (!BotBanishIsActive()) {

		$action['args'] = $orig_args;
		$action['error'] = 'BotBanish is not active';
		return $action;
	}

	$args = BotBanishArrayKey_strtolower($orig_args);

	$contact_to = isset($args['to']) ? $args['to'] : '';
	$contact_subject = isset($args['subject']) ? $args['subject'] : '';
	$contact_message = isset($args['message']) ? $args['message'] : '';
	$contact_headers = isset($args['headers']) ? $args['headers'] : '';
	$contact_attachments = isset($args['attachments']) ? $args['attachments'] : '';

	$tags = BotBanishFixExplode(',', $row['BOTBANISH_CONTACT_TAGS'] . ', Reply-To, Content-Type, X-WPCF7-Content-Type');
	if (isset($tags['Message'])) unset($tags['Message']);

	if (empty($contact_message)) {

		$action['error'] = 'Contact Message Empty: ' . var_export($orig_args, true) . PHP_EOL . PHP_EOL . var_export($args, true);
		$action['args'] = $orig_args;
		return $action;
	}

	// Let's process this message

	$str = BotBanishRemoveContactArrayMarkers($contact_message, array('headers Array(', 'attachments Array(', 'to Array('));
	$str = BotBanishReFormatContactMessage($str, $tags);
	$arr = BotBanishGatherContactMessageTags($str, $tags);

	if (!isset($arr['Subject']))
		$arr['Subject'] = $args['subject'];

	$action = BotBanishValidateFormSpamContactMessageTags($orig_args, $arr, $row);
	return $action;
}

function BotBanishReFormatContactMessage($msg, $tags) {

	// Convert the message to something we can process

	$str = str_ireplace(array(' =' , '</b><br />'), ': ', $msg);
	$str = str_ireplace(array('<li>', '</li>', '<b>', '<br />', '<p>', '</p>', '<ol>', '</ol>'), '', $str);

	// Make sure all tags in the message have the correct format

	foreach ($tags as $tag)
		$str = str_replace(strtolower($tag) . ':', $tag . ':', $str);

	return $str;
}

function BotBanishRemoveContactArrayMarkers($msg, $findarray = array()) {

	// Find and remove the Array() area

	foreach ($findarray as $find) {

		$x = stripos($msg, $find);

		if ($x !== false) {

			$y = stripos($msg, ')', $x);

			if ($y !== false)
				$msg = str_replace(substr($msg, $x, ($y - $x) + 1), '', $msg);
		}
	}

	return $msg;
}

function BotBanishGatherContactMessageTags($msg, $tags) {

	// Find all the current tags with colons in the message and get their data

	$arr = array();

	foreach ($tags as $tag) {

		$loc = -1;
		$find_tag = $tag . ':';

		// Possible duplicate tags names can be in message. Find them all!

		while (true) {

			$loc = stripos($msg, $find_tag, $loc + 1);

			if ($loc === false)
				break;

			$arr[$loc] = $find_tag;
		}
	}

	ksort($arr);

	$start = 0;
	$end = 0;
	$tagKey = '';
	$msgTags = array();

	// If multiple matching message tags exist, we will use the last one found.
	// The first one is most likely the header information from the contact form which we should ignore.

	foreach ($arr as $key => $value) {

		if (empty($end)) {

			$start = $key;
			$msgTags[$value] = $key; // Doesn't matter what the value is here, key just needs to exist
			$tagKey = $value;
			$end = true;

		} else {

			$end = $key;
			$msgTags[$tagKey] = str_replace($tagKey, '', substr($msg,$start, $end - $start)); // Remove tag from the data
			$tagKey = $value;
			$end = true;

			$start = $key;
			$tagKey = $value;
		}
	}

	$msgTags[$tagKey] = str_replace($tagKey, '', substr($msg, $start)); // Remove tag from the data

	// Remove ':' from the tag keys

	foreach($msgTags as $key => $value) {

		$msgTags[str_replace(':', '', $key)] = $msgTags[$key];
		unset($msgTags[$key]);
	}

	// If Body tags exist make it the Message tags

//	if (isset($msgTags['Body']) && !isset($msgTags['Message'])) {
	if (isset($msgTags['Body'])) {

		unset($msgTags['Message']);
//		$msgTags['Message'] = $msgTags['Body'];
//		unset($msgTags['Body']);
	}

	return $msgTags;
}

function BotBanishRemoveContactMessageTags($message, $tags) {

	// Remove all tags from the message area

	$remove = array('Reply-To', 'Content-Type', 'Message', 'IP');
	$remove = array_merge ($tags, $remove);
	$msg = explode("\n", $message);

	$arr = array();

	foreach ($msg as $key => $value) {

		if (empty($value))
			continue;

		foreach ($tags as $tag) {

			$tag = trim($tag);
			$tag_key = $tag . ':';

			if (stripos($value, $tag_key ) !== false) {

				unset ($msg[$key]);
				continue;
			}
		}
	}

	return $msg;
}

function BotBanishCheckForContactRequired($params) {

	global $BotBanishSettings;

	$key = $params['key'];
	$action = $params['action'];
	$item = $params['arr'][$key];
	$row = $params['row'];

	// If item has no spaces or only 1 group of characters, get rid of it!

	$found = (stripos($item, ' ') !== false) ? true : false;

	if (!$found) {

		$action['error'] = $key . ' Has no spaces or contains only 1 group of characters';
		$action['terminate'] = true;

	} else {

		$data = (isset($row['BOTBANISH_CONTACT_REQUIRED']) && !empty($row['BOTBANISH_CONTACT_REQUIRED'])) ? $row['BOTBANISH_CONTACT_REQUIRED'] : 'a,e,i,o,u';
		$chars = explode(',', $data);
		array_filter($chars);
		$found = false;

		foreach ($chars as $char) {

			if (stripos($item, $char) !== false) {

				$found = true;
				break;
			}
		}

		if (!$found) {

			$action['error'] = $key . ' Has not one of the required data elements';
			$action['terminate'] = true;
		}
	}

	return $action;
}

function BotBanishCheckForContactNumbers($params) {

	$arr = $params['arr'];
	$key = $params['key'];
	$action = $params['action'];

	$item = trim($arr[$key]);

	$numbers = explode(',', '0,1,2,3,4,5,6,7,8,9,-,(,),+,.');
	$found = true;
	$lth = strlen($item);

	for ($x=0; $x < $lth; $x++) {

		$y = substr($item, $x, 1);

		if (in_array($y, $numbers) === false) {

			$found = false;
			break;
		}
	}

	if (!$found) {

		$action['error'] = $key . ' should contain only Numbers';
		$action['terminate'] = true;
	}

	return $action;
}

function BotBanishCheckContactWordCount($params) {

	global $BotBanishSettings;

	$arr = $params['arr'];
	$key = $params['key'];
	$action = $params['action'];
	$wordCount = (!isset($BotBanishSettings['BOTBANISH_CONTACT_WORD_COUNT']) || (intval($BotBanishSettings['BOTBANISH_CONTACT_WORD_COUNT']) !== 0)) ? 7 : $BotBanishSettings['BOTBANISH_CONTACT_WORD_COUNT'];

	$item = trim($arr[$key]);

	$words = explode(' ', $item);
	$words = array_filter($words);

	if (count($words) < $wordCount) {

		$action['error'] = $key . ' does not have enough words to be a legitimate message';
		$action['terminate'] = true;
	}

	return $action;
}

function BotBanishRejectContactMessage($passed, $message_array, $action){

	BotBanishContactMessageTrace($passed, $action['error'], 'Reject', $message_array);
	BotBanishContactLockOut($passed);
}

//========================================================================================

function BotBanishValidateFormSpamContactMessageTags($args, $message_array, $row) {

//	BotBanishContactMessageTrace($row, 'BotBanishValidateFormSpamContactMessageTags()');

	$action = array('terminate' => false, 'error' => '', 'args' => $row);

	foreach ($message_array as $key => $tag) {

		$func = 'BotBanishValidateFormSpamContact' . str_replace('-', '', $key);

		if (function_exists($func)) {

			$params = array('arr' => $message_array,
							'key' => ucwords($key),
							'action' => $action,
							'row' => $row,
							'args' => $args
							);

			$action = call_user_func($func, $params);
//			BotBanishContactTrace($func . '($params, $action)', $params, $action, false, $row);
			BotBanishContactTrace($func, $tag, $action, false, $row);

			if ($action['terminate']) {

				BotBanishRejectContactMessage($row, $message_array, $action);
				break;
			}

		} else {

			BotBanishLogError('Contact Function: ' . $func . ' does not exist', $message_array, 'Error');
		}
	}

//	BotBanishContactTrace('BotBanishValidateFormSpamContactMessageTags($args, $message_array, $row)', $args, $message_array, true, $row);
	BotBanishContactMessageTrace($row, 'BotBanishValidateFormSpamContactMessageTags()');

	return $action;
}

function BotBanishValidateFormSpamContactSubject($params) {

	$arr = $params['arr'];
	$key = $params['key'];
	$action = $params['action'];

	$item = $arr[$key];

	if (!empty($item)) {

		// if Subject: contains forbidden elements, reject it!!!

		$action = BotBanishCheckForContactForbidden($params);
		if ($action['terminate']) return $action;

		$len = strlen($item);
		$newlen = isset($arr['Message']) ? strlen($arr['Message']) : 0;

		if ($len == $newlen) {

			// If subject is the same as the message, reject it!!

			if ($arr['Message'] == $item) {

				$action['error'] = $key . ' and Message are the same';
				$action['terminate'] = true;
			}
		}
	}

	return $action;
}

function BotBanishValidateFormSpamContactFrom($params) {

	$arr = $params['arr'];
	$action = $params['action'];

	// if email tag is present along with the from tag
	// only validate the email tag

	if (isset($arr['Email']))
		return $action;
	
	$action = BotBanishValidateFormSpamContactEmail($params);

	if (!$action['terminate'] && !isset($arr['Name'])) {

		$str_array = array_values(array_filter(explode(' ', $arr['From'])));
		unset($str_array[count($str_array) - 1]);
		$arr['Name'] = implode(' ', $str_array);
		$params['key'] = 'Name';
		$params['arr'] = $arr;
		$action = BotBanishValidateFormSpamContactName($params);
	}

	return $action;
}

function BotBanishValidateFormSpamContactName($params) {

	$action = BotBanishCheckForContactForbidden($params);
	return $action;
}

function BotBanishValidateFormSpamContactFirst($params) {

	$action = BotBanishCheckForContactForbidden($params);
	return $action;
}

function BotBanishValidateFormSpamContactLast($params) {

	$action = BotBanishCheckForContactForbidden($params);
	return $action;
}

function BotBanishValidateFormSpamContactPhone($params) {

	$action = BotBanishCheckForContactNumbers($params);
	return $action;
}

function BotBanishValidateFormSpamContactTo($params) {

	$action = $params['action'];
	return $action;
}

function BotBanishValidateFormSpamContactEmail($params) {

	$arr = $params['arr'];
	$key = $params['key'];
	$action = $params['action'];
	$row = $params['row'];

	$email = trim(strip_tags($arr[$key]));
	$email_arr = explode(' ', $email);
	$email = trim($email_arr[count($email_arr) - 1]);

	if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {

		$action['error'] = $key . ' is not in a valid email format';
		$action['terminate'] = true;
		return $action;
	}

	if (isset($row['country_codes']) && is_array($row['country_codes'])) {
		
		if (BotBanishContactCheckForBlockedCountryEmailDomain($row['country_codes'], $email)) {
			
			$action['terminate'] = true;
			$action['error'] = 'Email Address From a Blocked Country';
			return $action;		
		}
	}
	
	$row['email'] = $email;
	$row['username'] = '';
	$row = BotBanishServerEmailVerify($row);

	return $action;
}

function BotBanishContactCheckForBlockedCountryEmailDomain($blocked_country_codes, $email) {

	// If the last part of the email is 2 characters it may be the code of the origin country.
	// If more than 2 check for the actual domain country

	if (function_exists('geoip_country_code_by_name')) {

		$info = explode('@', $email);
		$dn = $info[count($info) - 1];

		$cc = geoip_country_code_by_name($dn);
		
		if (strlen($cc) === 2) {
			
			if (in_array($cc, $blocked_country_codes))
				return true;
		}
	}

	if (BotBanishContactCheckForBlockedCountryEmail($blocked_country_codes, $email))
		return true;
	
	return false;
}
			
function BotBanishContactCheckForBlockedCountryEmail($blocked_country_codes, $email) {

	// If the last part of the email is just 2 characters it may be the country code
	// Look for a blocked country from the domain designation

	$info = explode('.', $email);
	$cc = strtolower($info[count($info) - 1]);
	$len = strlen(trim($cc));

	if ($len === 2) {

		if (in_array($cc, $blocked_country_codes))
			return true;
	}

	return false;
}
	
function BotBanishValidateFormSpamContactMessage($params) {

	$arr = $params['arr'];
	$key = $params['key'];
	$action = $params['action'];
	$row = $params['row'];
	$item = $arr[$key];

	if (!empty($item)) {

		$eliminate = BotBanishFixExplode(',', $row['BOTBANISH_CONTACT_ELIMINATE']);
		$additional = array(PHP_EOL, "\n", "\r", "  ");
		$eliminate = array_merge($eliminate, $additional);

		// Remove items we should not check for from message

		$arr[$key] = trim(str_ireplace($eliminate, '', $item));
		$params['arr'] = $arr;

		// Check message with items removed for forbidden items

		$action = BotBanishCheckForContactForbidden($params, array('@'));
		if ($action['terminate']) return $action;

		$action = BotBanishCheckContactWordCount($params);
	}

	return $action;
}

function BotBanishValidateFormSpamContactBody($params) {

	$action = BotBanishValidateFormSpamContactMessage($params);
	return $action;
}

function BotBanishValidateFormSpamContactIP($params) {

	$action = $params['action'];
	return $action;
}

function BotBanishValidateFormSpamContactReplyTo($params) {

	$action = $params['action'];
	return $action;
}

function BotBanishValidateFormSpamContactContentType($params) {

	$action = $params['action'];
	return $action;
}

function BotBanishValidateFormSpamContactXWPCF7ContentType($params) {

	$action = $params['action'];
	return $action;
}

//========================================================================================

function BotBanishCheckForContactForbidden($params, $add = array()) {

	$arr = $params['arr'];
	$key = $params['key'];
	$action = $params['action'];
	$row = $params['row'];

	$item = $arr[$key];
	$len = strlen($item);

	// if item contains forbidden elements, reject it!!!

	if (!empty($item)) {

		$forbidden = BotBanishFixExplode(',', $row['BOTBANISH_CONTACT_FORBIDDEN']);
		$forbidden = array_merge($forbidden, $add);

		$new_len = strlen(str_ireplace($forbidden, '', $item));

			if ($new_len !== $len) {

				$action['error'] = $key . ' has forbidden items';
				$action['terminate'] = true;

			} else {

				// If none of the required elements exist, reject it

				$action = BotBanishCheckForContactRequired($params);
			}
	}

	return $action;
}

function BotBanishEmptyArgs() {

	$args = array();
	$args['to'] = '';
	$args['subject'] = '';
	$args['message'] = '';
	$args['headers'] = '';
	$args['attachments'] = '';
	return $args;
}

function BotBanishGetContactPassedData() {

	$row = array();
	$data = ($_SERVER['REQUEST_METHOD'] === 'POST') ? $_POST : $_GET;

	foreach($data as $key => $value)
		$row[$key] = urldecode($value);

	$row = BotBanishContactFixRow($row);

	return $row;
}

function BotBanishContactFixRow($row) {

	global $BotBanishSettings;

	$BotBanishSettings['DOMAIN_NAME'] = isset($row['domain']) ? $row['domain'] : BotBanishGetDomainName($_SERVER);

	if (!isset($row['args'])) {

		// Where did you come from?

		$row['bt'] = BotBanishDebugBackTrace();
		BotBanishContactLogMessages($row, 'BotBanishContactFixRow()', 'Error');

	} else {

		$row['args'] = BotBanishSafeUnSerialize($row['args']);
	}

	return $row;
}
?>