<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
// BotBanish 9.0.05
// Randem Systems: https://randemsystems.support
// BotBanish Pre-Incude Routines
// Date: 08/06/2026
//
///////////////////////////////////////////////////////////////////////////////////////////////////////

function BotBanishCheckSystem() {

	global $BotBanishSettings;

	$system = defined('SMF') ? 'SMF' : '';
	$system = empty($system) && defined('ABSPATH') ? 'WORDPRESS' : $system;
	$system = empty($system) && defined('DIR_APPLICATION') ? 'OPENCART' : $system;
	$system = empty($system) && defined('WEBSITE') && WEBSITE ? 'WEBSITE' : $system;
	$system = empty($system) && defined('CLIENT') && CLIENT ? 'CLIENT' : $system;
	$system = empty($system) && defined('SERVER') && SERVER ? 'SERVER' : $system;
	$system = empty($system) && isset($BotBanishSettings['BOTBANISH_SYSTEM']) ? $BotBanishSettings['BOTBANISH_SYSTEM'] : $system;
	$system = empty($system) && defined('BOTBANISH_SYSTEM') ? BOTBANISH_SYSTEM : $system;

	$dir = '';
	$paths = get_included_files();
	$i = count($paths) - 1;

	do {

		$path = str_replace('\\', '/', $paths[$i]);

		if (stripos($path, '/Include/') !== false) {

			$index = strrpos($path, '/');
			$dir = realpath(substr($path, 0, $index + 1) . '../');
			$dir = str_replace('\\', '/', $dir);
			break;
		}

		$i--;

	} while ($i > 0);

	$install_type = is_dir($dir . '/Server') ? 'Server' : 'Client';
	$system = $install_type == 'Server' ? 'SERVER' : $system;

	BotBanishDefineGlobals('BOTBANISH_SYSTEM', $system);

	return array('system' => strtoupper($system), 'install_type' => $install_type, 'apache_version' => '2.4.00', 'location' => $dir . '/');
}

function BotBanish_getWpTimezone() {

	$timezone_string = get_option( 'timezone_string' );

	if (!empty($timezone_string ))
		return $timezone_string;

	return 'Pacific/Honolulu';
}

function BotBanishDefineGlobals($variable, $value, $global = false) {
	global $BotBanishSettings;

	// Defines cannot be redefined (they are static) but we can update the BotBanish Settings array for dynamic changes

	$value = is_numeric($value) ? intval($value) : $value;

	if ($global) {

		if (!defined($variable))
			define($variable, $value);
	}

	$BotBanishSettings[$variable] = $value;
}

function BotBanishGetConfigLocation($config = 'config.php', $dir = '') {

	$dir = !empty($dir) ? $dir : getcwd();
	$dir = str_replace('\\', '/', $dir);
	$dir = rtrim($dir, '/');
	$found = false;

	$str = substr($dir, 0, 1) === '/' ? '/' : '';

	$paths = explode('/', $dir);
	$index = count($paths) - 1;

	while (true){

		$path = $str . implode('/', $paths) . '/';

		if (file_exists($path . $config)) {

			$found = true;
			break;
		}

		unset($paths[$index]);
		$index--;

		if (($index == -1) || ($path == $_SERVER['DOCUMENT_ROOT'] . '/') || empty($path) || ($path == '/')) {

			$path = '';
			break;
		}
	}

	return $path;
}

function BotBanishSetFolders() {

	global $BotBanishSettings, $BotBanishText;

	if (!isset($BotBanishSettings))
		$BotBanishSettings = array();

	if (!isset($BotBanishText))
		$BotBanishText = array();

	$system = BotBanishCheckSystem();

	BotBanishDefineGlobals('BOTBANISH_SERVER_TYPE', BotBanish_GetServerType());
	BotBanishDefineGlobals('BOTBANISH_INSTALL_TYPE', $system['install_type']);

	$protocol = isset($_SERVER['REQUEST_SCHEME']) ? $_SERVER['REQUEST_SCHEME'] : 'http';
	$protocol = (isset($_SERVER['HTTP_X_FORWARDED_TYPE']) && ($_SERVER['HTTP_X_FORWARDED_TYPE'] == 'ssl')) ? 'https' : $protocol;
	$protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : $protocol;

	BotBanishDefineGlobals('BOTBANISH_PROTOCOL', $protocol);

	$user_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
	$user_host = (empty($user_host) && isset($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : $user_host;
	$user_host = trim(str_ireplace('\\', '/', $user_host), '/');

	BotBanishDefineGlobals('BOTBANISH_USER_HOST', $user_host);

	switch (strtoupper($system['install_type'])) {

		case 'SERVER':

			$installFolder = 'bot_v' . $BotBanishSettings['BOTBANISH_VERSION_SERVER'] . '/';
			break;

		default:

			$installFolder = 'bot';
			break;
	}

	switch (strtoupper($system['system'])) {

		case 'WORDPRESS':

			BotBanishDefineGlobals('BOTBANISH_STATIC_DIR', ABSPATH . 'wp-content' . '/BotBanish_Data/');
			BotBanishDefineGlobals('BOTBANISH_INSTALL_URL', BOTBANISH_PLUGIN_URL . 'bot/');
			if (!defined('BOTBANISH_DIR'))
				define('BOTBANISH_DIR', plugin_dir_path( __FILE__ ) . 'bot/');
			break;

		case 'SMF':

			global $boarddir, $boardurl, $baseURL;
			BotBanishDefineGlobals('BOTBANISH_STATIC_DIR', $boarddir . '/BotBanish_Data/');
			BotBanishDefineGlobals('BOTBANISH_INSTALL_URL', $boardurl . '/BotBanish/bot/');
			if (!defined('BOTBANISH_DIR'))
				define('BOTBANISH_DIR', $boardurl . '/BotBanish/bot/');
			break;

		default:

			BotBanishDefineGlobals('BOTBANISH_STATIC_DIR', $_SERVER['DOCUMENT_ROOT'] . '/BotBanish_Data/' .  $installFolder . '/');

			$dirs = explode('/', $_SERVER['REQUEST_URI']);

			for ($i = 0; $i < 3; $i++)
				unset($dirs[count($dirs) - 1]);

			$url =  $BotBanishSettings['BOTBANISH_PROTOCOL'] . '://' . $BotBanishSettings['BOTBANISH_USER_HOST'] . implode('/', $dirs) . '/';
			BotBanishDefineGlobals('BOTBANISH_INSTALL_URL',	$url);
			if (!defined('BOTBANISH_DIR'))
				define('BOTBANISH_DIR', $_SERVER['DOCUMENT_ROOT'] . '/BotBanish/bot/');
	}

	BotBanishDefineGlobals('BOTBANISH_SYSTEM', $system['system']);
	BotBanishDefineGlobals('BOTBANISH_DIR', BOTBANISH_DIR);

	BotBanishDefineGlobals('BOTBANISH_SUBS_DIR', BOTBANISH_DIR . 'Subs/');
	BotBanishDefineGlobals('BOTBANISH_INCLUDE_DIR', BOTBANISH_DIR . 'Include/');
	BotBanishDefineGlobals('BOTBANISH_DATA_DIR', BOTBANISH_DIR . 'Data/');
	BotBanishDefineGlobals('BOTBANISH_IMAGES_DIR', BOTBANISH_DIR . 'Images/' . $system['install_type'] . '/');
	BotBanishDefineGlobals('BOTBANISH_LANGUAGE_DIR', BOTBANISH_DIR . 'Language/');
	BotBanishDefineGlobals('BOTBANISH_DOCS_DIR', BOTBANISH_DIR . 'Docs/');
	BotBanishDefineGlobals('BOTBANISH_CLASS_DIR', BOTBANISH_DIR . 'Class/');
	BotBanishDefineGlobals('BOTBANISH_TEMPLATES_DIR', BOTBANISH_DIR . 'Templates/');
	BotBanishDefineGlobals('BOTBANISH_ANALYTICS_DIR', BOTBANISH_DIR . 'Analytics/');
	BotBanishDefineGlobals('BOTBANISH_CSS_DIR', BOTBANISH_DIR . 'css/');
	BotBanishDefineGlobals('BOTBANISH_AUTOLOAD_DIR', BOTBANISH_DIR . 'vendor/');

	BotBanishDefineGlobals('BOTBANISH_CLIENT_DIR', BOTBANISH_DIR . 'Client/');
	BotBanishDefineGlobals('BOTBANISH_SERVER_DIR', BOTBANISH_DIR . 'Server/');

	BotBanishDefineGlobals('BOTBANISH_IMAGES_URL',  $BotBanishSettings['BOTBANISH_INSTALL_URL'] . '/Images/');

	switch($BotBanishSettings['BOTBANISH_INSTALL_TYPE']) {

		case 'Server':

			BotBanishDefineGlobals('BOTBANISH_INSTALL_DIR', $BotBanishSettings['BOTBANISH_SERVER_DIR']);
			break;

		default:

			BotBanishDefineGlobals('BOTBANISH_INSTALL_DIR', BOTBANISH_DIR);
			break;
	}

	BotBanishDefineGlobals('BOTBANISH_STATIC_LOGS_DIR', $BotBanishSettings['BOTBANISH_STATIC_DIR'] . 'BotBanish_Logs/');
	BotBanishDefineGlobals('BOTBANISH_STATIC_BACKUPS_DIR', $BotBanishSettings['BOTBANISH_STATIC_DIR'] . 'Backups/');
	BotBanishDefineGlobals('BOTBANISH_STATIC_BACKUPS_SQL_DIR', $BotBanishSettings['BOTBANISH_STATIC_DIR'] . 'Backups/SQL/');
	BotBanishDefineGlobals('BOTBANISH_STATIC_HTML_DIR', $BotBanishSettings['BOTBANISH_STATIC_DIR'] . 'html/');
	BotBanishDefineGlobals('BOTBANISH_STATIC_SQL_DIR', $BotBanishSettings['BOTBANISH_STATIC_DIR'] . 'SQL/');
	BotBanishDefineGlobals('BOTBANISH_STATIC_CACHE_DIR', $BotBanishSettings['BOTBANISH_STATIC_DIR'] . 'Cache/');
	BotBanishDefineGlobals('BOTBANISH_STATIC_UPLOAD_DIR', $BotBanishSettings['BOTBANISH_STATIC_DIR'] . 'Uploads/');
	BotBanishDefineGlobals('BOTBANISH_STATIC_TEMP_DIR', $BotBanishSettings['BOTBANISH_STATIC_DIR'] . 'Temp/');

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

		if (strlen($key) > 10) {

			$part = substr($key, strlen($key) - 4);

			switch ($part) {

				case '_DIR':

					$BotBanishSettings[$key] = str_ireplace(array('\\', '//'), '/', $value);
					break;
			}
		}
	}

	return $BotBanishSettings;
}

function BotBanishGetHeaders($url, $override = false) {

	$botbanish_system = ($override == true) ? array('system' => '') : BotBanishCheckSystem();

	switch ($botbanish_system['system']) {

		case 'WORDPRESS':

			// try this way and if failure allow to try the PHP CURL method.

			$headers = wp_get_http_headers($url);

			if (!is_array($headers) || empty($headers) ||
				(isset($headers['Status']) && stripos($headers['Status'], '404') !== false))
				break;

		default:

			$ch = curl_init();
			curl_setopt($ch, CURLOPT_URL, $url);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			curl_setopt($ch, CURLOPT_HEADER, 1);
			curl_setopt($ch, CURLOPT_NOBODY, 1);
			$output = curl_exec($ch);
			curl_close($ch);

			$headers = array();

			if (!empty($output)) {

				$output = rtrim($output);
				$data = explode("\n",$output);

				$headers['Status'] = $data[0];
				array_shift($data);

				foreach($data as $part){

					//some headers will contain ":" character (Location for example), and the part after ":" will be lost, Thanks to @Emanuele
					$middle = explode(":",$part,2);

					//Supress warning message if $middle[1] does not exist, Thanks to @crayons
					if ( !isset($middle[1]) ) { $middle[1] = null; }

					$headers[trim($middle[0])] = trim($middle[1]);
				}
			}
			break;
	}

	return $headers;
}

function BotBanishRemoteImageFileExists( $url ) {

//	$response = wp_remote_head( $url );
	$response = wp_remote_get( $url );

	if (wp_remote_retrieve_response_code( $response ) === 200)
		return true;

	return false;
}

function BotBanishLanguageSupported($lang = '') {

	global $BotBanishSettings;

	$language = isset($lang) ? $lang : 'english';

	if (isset($BotBanishSettings['BOTBANISH_LANGUAGES']) && !empty($BotBanishSettings['BOTBANISH_LANGUAGES'])) {

		$flag = array_search($language, $BotBanishSettings['BOTBANISH_LANGUAGES']);

		// If we find a supported language, make it the default one

		if ($flag !== false) {

			$language = $BotBanishSettings['BOTBANISH_LANGUAGES'][$flag];
			$BotBanishSettings['BOTBANISH_LANGUAGE_SELECT'] = $language;
		}

	} else {

		BotBanishDefineGlobals('BOTBANISH_LANGUAGES', array('english' => 'english', 'french' => 'french', 'german' => 'german', 'italian' => 'italian', 'portuguese' => 'portuguese', 'spanish' => 'spanish', 'swedish' => 'swedish'));
	}

	return $language;
}

function BotBanish_StartSession() {

	$botbanish_system = BotBanishCheckSystem();

	switch ($botbanish_system['system']) {

		case 'WEBSITE':
		case 'DIR_APPLICTION':
		case 'OPENCART':

			// See if a session is active, if not then start one

			if (session_status() !== PHP_SESSION_ACTIVE)  {

				if (!headers_sent()) {

					session_start();
				}
			}
			break;

		default:

			break;
	}
}

function BotBanishGetIncludeLocation ($filename) {

	$dir = '';
	$paths = get_included_files();

	foreach ($paths as $path) {

		if (stripos($path, $filename) > 0)	{
			$dir = str_ireplace($filename, '', $path);
			break;
		}
	}

	return $dir;
}

function BotBanish_GetServerType() {

	// Try to determine if we are running NGINX as a proxy cache for Apache

	ob_start();
	phpinfo();
	$info = ob_get_clean();

	$servers = array('Apache', 'NGINX', 'Lighttpd', 'LiteSpeed');

	foreach ($servers as $server) {

		if (stripos($info, $server) !== false) {

			$servertype = $server;
			break;
		}
	}

	// If we are running on Apache, nothing else matters...

	if (!isset($servertype)) {

		$url = $_SERVER['REQUEST_SCHEME']. '://' . $_SERVER['SERVER_NAME'];
		$headers = BotBanishGetHeaders($url);

		if ($headers === false)
			return 'Unknown';

		$found = false;
		$servertype = 'Unknown';

		foreach ($servers as $server) {

			foreach ($headers as $header) {

				if (stripos($header, $server) !== false) {
					$servertype = $server;
					$found = true;
					break;
				}
			}

			if ($found)
				break;
		}
	}

	switch ($servertype) {

		case 'NGINX':

			BotBanishDefineGlobals('BOTBANISH_SERVER_NGINX', 1);
			break;

		case 'Lighttpd':

			BotBanishDefineGlobals('BOTBANISH_SERVER_LIGHTTPD', 1);
			break;

		case 'LiteSpeed':

			BotBanishDefineGlobals('BOTBANISH_SERVER_LITESPEED', 1);
			break;

		default:

			BotBanishDefineGlobals('BOTBANISH_SERVER_APACHE', 1);
			break;
	}

	return $servertype;
}

function BotBanishAlert($data = 'Here') {

	echo '<script type="text/javascript">alert("' . $data . '")</script>';
}

function BotBanishSaveOverrideState() {

	array_push($GLOBALS['override_state'], $GLOBALS['override']);
	$GLOBALS['override'] = true;
}

function BotBanishRestoreOverrideState() {

	$GLOBALS['override'] = array_pop($GLOBALS['override_state']);
}

function BotBanishSaveLogState() {

	global $BotBanishSettings;

	array_push($GLOBALS['log_state'], $BotBanishSettings['BOTBANISH_DEBUG_LOG_INFO']);
	$BotBanishSettings['BOTBANISH_DEBUG_LOG_INFO'] = true;
}

function BotBanishRestoreLogState() {

	global $BotBanishSettings;

	$BotBanishSettings['BOTBANISH_DEBUG_LOG_INFO'] = array_pop($GLOBALS['log_state']);
}

function BotBanishIsAdmin($user_info = false) {

	$system = BotBanishCheckSystem();

	switch ($system['system']) {

		case 'WORDPRESS':

			if (!is_object($user_info))

				$user_obj = wp_get_current_user();
			else
				$user_obj = $user_info;

			return (in_array('administrator',  $user_obj->roles));
			break;

		case 'SMF':

			global $context;

			return $context['user']['is_admin'];
			break;

		case 'WEBSITE':

			break;

		case 'OPENCART':

			break;
	}

	return false;
}

function BotBanishClientAddActions(&$actionArray) {

	$actionArray = array_merge(
		array(
			'botbanish' => array('BotBanish_BlackWhiteLists_Manage.php', 'BotBanish'),
		),
		$actionArray
	);
}

function BotBanishRoutineTrace() {

	$backtrace_array = debug_backtrace();
	$date = BotBanishGetCorrectDateTime();

	$filename = BotBanishSetLogFilename('InstallTrace');
	BotBanishWriteFile($filename, $date . PHP_EOL, true);
	$error_trace = '';

	foreach ($backtrace_array as $key => $error_info){

		$error_trace .= 'Called From: ' . PHP_EOL;
		$error_trace .= isset($error_info['file']) ? "\t" . 'File: ' . $error_info['file'] . PHP_EOL : '';
		$error_trace .= isset($error_info['function']) ? "\t" . 'Function: ' . $error_info['function'] . PHP_EOL : '';
		$error_trace .= isset($BotBanishText['called_from']) ? $BotBanishText['called_from'] . PHP_EOL : 'Called From: ';
		$error_trace .= isset($error_info['line']) ? "\t" . 'Line: ' . $error_info['line'] . PHP_EOL : '';
	}

	$line = str_repeat('=', 40);
	BotBanishWriteFile($filename, $error_trace . PHP_EOL . $line . PHP_EOL, true);
}

function BotBanishFindServer() {

	if (!defined('BOTBANISH_TEST') || (!BOTBANISH_TEST)) {

		$servers = array();
		$test_servers = array();
		$local_servers = array();
		$hosted_servers = array();

		// Available BotBanish Servers. Check servers to find first available one
		// HTTP clients can only communicate with HTTP Servers
		// HTTPS clients can communicate with both

		if (defined('BOTBANISH_USE_TEST_SERVER') && (BOTBANISH_USE_TEST_SERVER)) {

			$test_servers = array(
				'https://botbanish-test.com',
				);

		} else {

			$debug_server = array('::1', '127.0.0.1');

			if (isset($_SERVER['SERVER_ADDR']) && (in_array($_SERVER['SERVER_ADDR'], $debug_server)))
				$local_servers = array('http://localhost');

			$hosted_servers = array(
					'https://botbanishserver.com',
					);
		}

		$servers = array_merge($test_servers, $local_servers, $hosted_servers);
		$found = false;

		global $BotBanishSettings;

		foreach ($servers as $server) {

			$url = $server . '/BotBanish/bot_v' . $BotBanishSettings['BOTBANISH_VERSION_SERVER']  . '/Server/' . $BotBanishSettings['BOTBANISH_WEB_SERVER'];

			$response = BotBanishSendPostData($url, '',false, false, false);

			if (stripos($response, 'BotBanish Server Running') !== false) {

				$found = true;
				break;
			}
		}
	}

	if ($found)

		return $url;
	else
		return false;
}

function BotBanishStartUp() {

	global $BotBanishSettings;

	// If Sucurri Website Security is active we need to force the real IP

	if (isset($_SERVER['HTTP_X_SUCURI_CLIENTIP']))
		$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_SUCURI_CLIENTIP'];

	// Items to exclude from database

	$BotBanishSettings['BOTBANISH_EXCLUDE_VARS'] = array(
				'BOTBANISH_TIMEZONES',
				'BOTBANISH_TIMEZONE_AREAS',
				'REMOVE_HTACCESS_COMMENTS',
				'BOTBANISH_HTACCESS_TAGS',
//				'BOTBANISH_COUNTRY_INFO',
				'BOTBANISH_POST_CODE',
				'BOTBANISH_INSTALL',
				'BOTBANISH_WEBROOT_URL',
				'BOTBANISH_HTML_DIR',
				'BOTBANISH_WEBROOTPATH_DIR',
				'BOTBANISH_DATA_DIR',
				'BOTBANISH_BACKUPS_SQL_DIR',
				'BOTBANISH_BACKUPS_DIR',
				'BOTBANISH_APPPATH_DIR',
				'BOTBANISH_LOGS_DIR',
				'BOTBANISH_EXCLUDE_VARS',
				'BOTBANISH_LOCALAPP_URL',
				'BOTBANISH_INSTALL_FOLDER',
				'BOTBANISH_LANGUAGEPATH',
				'BOTBANISH_LOCATION_ROOT',
				'BOTBANISH_CURRENT_FOLDER',
				'BOTBANISH_DOMAIN_NAME',
			);
}

function BotBanishCleanUpPreviousVersions() {

	BotBanishSaveOverrideState();

	// Just in case we are installing after 6.0.11.
	// We have moved this information to our own tables.

	if (defined('ABSPATH')) {

		global $table_prefix;

		$table = $table_prefix . 'options';
		$sql = 'DELETE FROM `' . $table . '` WHERE `option_name` LIKE "%botbanish%"';
		BotBanishExecuteSQL($sql, true, true);
	}

	$files = array(
					BOTBANISH_DIR . 'Settings_Client.php',
					BOTBANISH_DIR . 'Settings_Server.php',
				);

	foreach ($files as $file) {

		if (file_exists($file))
			unlink($file);
	}

	BotBanishRestoreOverrideState();
}

function BotBanishSetTableCollation() {

	global $BotBanishSettings;

	if (isset($BotBanishSettings['BOTBANISH_DATABASE_TABLE_COLLATION_SET']) && !empty($BotBanishSettings['BOTBANISH_DATABASE_TABLE_COLLATION_SET']))
		return true;

	// Default to the minimum coolation and charset to guarantee connection to get database table collation and charset

	$BotBanishSettings['BOTBANISH_DATABASE_TABLE_COLLATION_DEFAULT'] = 'utf8_general_ci';
	$BotBanishSettings['BOTBANISH_DATABASE_TABLE_CHARSET_DEFAULT'] = 'utf8';

	$collate = false;

	$sql = 'SHOW COLLATION;';
	$rows = BotBanishExecuteSQL($sql, true, true);
	$table_collations = $BotBanishSettings['BOTBANISH_DATABASE_TABLE_COLLATIONS'];

	foreach ($table_collations as $table_collate) {

		foreach ($rows as $database_collation) {

			if ($database_collation['Collation'] == $table_collate) {

				$collate = true;
				$BotBanishSettings['BOTBANISH_DATABASE_TABLE_COLLATION_DEFAULT'] = $database_collation['Collation'];
				$BotBanishSettings['BOTBANISH_DATABASE_TABLE_CHARSET_DEFAULT'] = $database_collation['Charset'];
				break;
			}
		}

		if ($collate !== false)
			break;
	}

	$BotBanishSettings['BOTBANISH_DATABASE_TABLE_COLLATION_SET'] = 1;

	return $collate;
}

function BotBanishChangeTableCollation($data) {

	global $BotBanishSettings;

	$collation = $BotBanishSettings['BOTBANISH_DATABASE_TABLE_COLLATION_DEFAULT'];
	$charset = $BotBanishSettings['BOTBANISH_DATABASE_TABLE_CHARSET_DEFAULT'];

	// Disassemble and reassemble SQL statements to have the highest collation and charset supported by the database

	$lines = explode("\n", $data);

	foreach ($lines as $key => $line) {

		if ((substr($line, 0, 2) == '--') || (substr($line, 0, 2) == '/*'))
			unset($lines[$key]);
	}

	array_filter($lines);
	$data = implode("\n", $lines);

	$stmts = explode(';', $data);

	$changes = array('ENGINE=' => 'InnoDB', 'CHARACTER SET ' => $charset, 'COLLATE ' => $collation, 'DEFAULT CHARSET=' => $charset, 'COLLATE=' => $collation);
	$terminators = array(' ', "\n", ';', ',');

	foreach ($stmts as $key => $stmt) {

		foreach ($changes as $key1 => $value) {

			$lines = explode($key1, $stmt);
			$c = count($lines);

			if ($c == 1)
				continue;

			for ($t = 1; $t < $c; $t++) {

				$txt1 = $lines[$t];
				$l = strlen($txt1);

				for ($z = 0; $z <= $l; $z++) {

					$char = substr($txt1, $z, 1);

					if (empty($char) || in_array($char, $terminators)) {

						$lines[$t] = $value;

						if (!empty($char)) {

							$lines[$t] .= substr($txt1, $z);
							break;
						}
					}
				}
			}

			$stmt = implode($key1, $lines);
		}

		$stmts[$key] = $stmt . ';';
	}

	$data = implode("\n", $stmts);

	return $data;
}

function BotBanishSetMultiTableName($table, $multi = false) {

	if (!$multi)
		return $table;

	// Used to be in Multi-Site databases

	$system = BotBanishCheckSystem();

	switch ($system['system']) {

		case 'SMF':

			global $db_prefix;

			$table = $db_prefix . $table;
			break;

		case 'WORDPRESS':

			global $table_prefix;

			$table = $table_prefix . $table;
			break;

		case 'OPENCART':

			break;

		default:

			break;
	}

	return ($table);
}

function BotBanishHitCheck($row) {

	global $BotBanishSettings;

	// When we get here we have already checked for good and bad bot/spider; so any repetitive or sucessive hits
	// have to be a bad user or a bad unknown bot/spider. Here we monitor ALL guest page hits on the system

	// After enough hits, we will check the time it took to do it. If too many hits in a defined time period
	// this is probably not a very good use of our resources

	$BotBanishSession = BotBanishGetSession();

	$hit_count = intval($BotBanishSession->getSessionKey('hitcount'));
	$hit_count++;
	$BotBanishSession->setSessionKey('hitcount', $hit_count);

	if ($hit_count == $BotBanishSettings['BOTBANISH_MAX_HIT_COUNT']) {

		$date = BotBanishGetCorrectDateTimeB();

		// If we have this many hits in 30 seconds, we need to get rid of this guy it is draining resources

		if (($date - $row['first_hit']) < $BotBanishSettings['BOTBANISH_MAX_HIT_SECONDS']) {

			$row['forcelockout'] = $BotBanishSettings['BOTBANISH_HITCOUNT_LOCKOUT'];
//			$row['lock_add'] = true;

			if ($BotBanishSettings['BOTBANISH_SERVER'])
				BotBanishServerIPLockOut($row);
		}
	}

	return $row['forcelockout'];
}

function BotBanishSetMemoryLimit($mem = '512M') {

	ini_set('memory_limit', $mem );	// Insure we have enough memory for large data
}

function BotBanishSetExecutionLimit($tm = 0) {

//	ini_set('max_execution_time', $tm);
	set_time_limit(0);
}

function BotBanishGetAvailableMemory($readable = false) {

	$mem = ini_get('memory_limit');

	if (!$readable)
		$mem = BotBanishConvertToReadable($mem);

	return $mem;
}

function BotBanishGetPeakMemoryUsage($readable = false, $real = false) {

	$mem = memory_get_peak_usage($real);

	if ($readable)
		$mem = BotBanishConvertToReadable($mem);

	return $mem;
}

function BotBanishGetMemoryUsage($readable = false, $real = false) {

	$mem = memory_get_usage($real);

	if ($readable)
		$mem = BotBanishConvertToReadable($mem);

	return $mem;
}

function BotBanishConvertToReadable($bytes) {

    $unit = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');

    // Using 1024 for binary prefixes (KiB, MiB, etc.) is more accurate for memory

    $i = floor(log($bytes, 1024));
    return round($bytes / pow(1024, $i), 2) . ' ' . $unit[$i];
}

function BotBanishCheckMemoryUsage($rtn) {

	global $BotBanishSettings;

	$filename = $BotBanishSettings['BOTBANISH_STATIC_LOGS_DIR'] . 'BotBanishMemory.txt';
	$txt = 'Area: ' . $rtn . "\t\t" . 'Total Memory: ' . BotBanishGetAvailableMemory(true) . "\t\t" . 'System Peak Memory: ' . BotBanishGetPeakMemoryUsage(true, true). "\t\t" . 'Peak Memory Usage: ' . BotBanishGetPeakMemoryUsage(true, false) . "\t\t" . 'Memory Usage: ' . BotBanishGetMemoryUsage(true, false) . "\t\t" . 'Time: ' . BotBanishGetCorrectDateTime() . PHP_EOL;
	BotBanishWriteMemoryFile($filename, $txt);
}

function BotBanishWriteMemoryFile($filename, $data, $append = true) {

	$data = BotBanish_EncodeToUtf8($data);

	$folder = dirname($filename) . '/';
	if (!is_dir($folder)) @mkdir ($folder, 0755, true);

	if (!file_exists($filename)) $append = false;

	// If log file gets too big, clear it.

	if (file_exists($filename)) {

		clearstatcache();	// Needs this to get proper filesize after a recent write operation
		if (filesize($filename) > 1024 * 50) $append = false;
	}

	if ($append)

		$bytes = file_put_contents($filename, $data, FILE_APPEND);
	else
		$bytes = file_put_contents($filename, $data);
}

function BotBanishIsUserLockedOut($ip = '') {

	// No need to contact server if ip is on the no block list

	if (isset($BotBanishSettings['BOTBANISH_REDIRECT_ONLY_ACTIVE']) && $BotBanishSettings['BOTBANISH_REDIRECT_ONLY_ACTIVE'])
		return;

	$ip = empty($ip) ? BotBanishGetIP() : $ip;

	if (BotBanishCheckForGoodIP($ip))
		return;

	$BotBanishSession = BotBanishGetSession();

	if (!BotBanishCheckForBadIP($ip)) {

		$lockedout = !empty($BotBanishSession->getSessionKey('locked')) ? true : false;

		BotBanishTraceIt('BotBanishIsUserLockedOut - Start: - $lockedout', intval($lockedout), true);

		if ($lockedout)
			BotBanishRedirectExit('Locked', $ip);

		$table = 'bbc_botbanishclient_ip_bad';
		$sql = 'SELECT `ip_id`, `forcelockout` FROM `' . $table . '` WHERE `bot_ip` = "' . $ip . '" AND `forcelockout` > 0 LIMIT 1';
		$rows = BotBanishExecuteSQL($sql);
		$row = BotBanishLimitReturn($rows);

		$lockedout = (!is_array($row) || empty($row)) ? false : true;

		if ($lockedout)
			BotBanishRedirectExit($row['forcelockout'], $ip);

		if (empty($BotBanishSession->getSessionKey('geodata'))) {

			// If we are blocking this country, get rid of it

			$country_info = BotBanishGetCountryInfo($ip);

			if (BotBanishCountryCodeBlockGet($country_info['country_code'])) {

				$row = array('bot_ip' => $ip);
				BotBanishInsertLocal($row);
				BotBanishRedirectExit($country_info['country_code'], $ip);
			}
		}

		BotBanishTraceIt('BotBanishIsUserLockedOut - End: - $lockedout', intval($lockedout), true);

		// if included from BotBanishClient prevent from calling itself

		if (!isset($_SESSION['BotBanishClient']))
			BotBanishClient();
	}
}

function BotBanish_EncodeToUtf8($string) {
     return mb_convert_encoding($string, "UTF-8", mb_detect_encoding($string, "UTF-8, ISO-8859-1, ISO-8859-15", true));
}

function BotBanish_EncodeToIso($string) {
     return mb_convert_encoding($string, "ISO-8859-1", mb_detect_encoding($string, "UTF-8, ISO-8859-1, ISO-8859-15", true));
}

function BotBanishLimitReturn($rows) {

	// Protect from multiple rows being returned
	// If we have more than one row, only use the first row returned

	if (is_array($rows) && isset($rows[0]))

		return $rows[0];
	else
		return $rows;
}

function BotBanishDisplayErrors() {

	ini_set("display_errors", 1);
	error_reporting(E_ALL);
}

function BotBanishGetURL() {

	$url = isset($_SERVER['SCRIPT_URL']) ? $_SERVER['SCRIPT_URL'] : '';
	$url = empty($url) && isset($_SERVER['SCRIPT_URI']) ? $_SERVER['SCRIPT_URI'] : $url;
	$url = empty($url) && isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $url;
	$url = empty($url) && isset($_SERVER['REDIRECT_URL']) ? $_SERVER['REDIRECT_URL'] : $url;
	return $url;
}

function BotBanishLockOut($status, $ip) {

	global $BotBanishSettings;

	BotBanishSaveOverrideState();

	$hit = BotBanishGetCorrectDateTimeB();

	$row = array();
	$row['bot_ip'] = $ip;
	$row['forcelockout'] = $status;
	$row['user_agent'] = BotBanishGetUserAgent($_SERVER);
	$row['htaccess'] = BotBanishSafeSerialize($BotBanishSettings['BOTBANISH_HTACCESS_ARRAY']);

	BotBanishInsertLocal($row);

	BotBanishRestoreOverrideState();
	BotBanishRedirectExit($status, $ip);
}

function BotBanishGet404Extensions($bylines = false) {

	global $BotBanishSettings;

	$filename = $BotBanishSettings['BOTBANISH_INCLUDE_DIR'] . 'BotBanish_404_Extensions.php';
	$default = '.png, .jpg, .gif, .svg, .ogg, .webm, .css, .html, .htm, .pdf, .txt, .mp3, .mp4';

	if (!file_exists($filename)) {

		$extensions = $default;

	} else {

		if ($bylines)

			$extensions = BotBanishReadFile($filename, true);
		else
			include_once $filename;

		if (!isset($extensions) || empty($extensions))
			$extensions = $default;
	}

	return $extensions;
}

function BotBanishDebugOn($type = 'client') {

	global $BotBanishSettings;

	if (!isset($BotBanishSettings['BOTBANISH_DEBUG_ON']) || !$BotBanishSettings['BOTBANISH_DEBUG_ON']) {

		if (isset($BotBanishSettings['BOTBANISH_DEBUG_OVERRIDE']))
			unset($BotBanishSettings['BOTBANISH_DEBUG_OVERRIDE']);

		return;
	}

	$BotBanishSettings['BOTBANISH_DEBUG_OVERRIDE'] = strtolower($type);
	return;
}

function BotBanishDebugOff() {

	global $BotBanishSettings;

	if (!isset($BotBanishSettings['BOTBANISH_DEBUG_ON']) || !$BotBanishSettings['BOTBANISH_DEBUG_ON'])
		return;

	if (isset($BotBanishSettings['BOTBANISH_DEBUG_OVERRIDE']))
		unset($BotBanishSettings['BOTBANISH_DEBUG_OVERRIDE']);

	return;
}

function BotBanishSetupRow(&$row) {

	global $BotBanishSettings;

	$BotBanishSession = BotBanishGetSession();

	$ip = $BotBanishSession->getSessionKey('botip');

	$useragent = BotBanishGetUserAgent($_SERVER);
	$useragent = BotBanishFixUserAgent($useragent); // Try to convert and remove extraneous information

	$country_info = $BotBanishSession->getSessionKey('countryinfo');
	$geo_data = $BotBanishSession->getSessionKey('geodata');

	$row['apikey'] = isset($BotBanishSettings['BOTBANISH_APIKEY']) ? $BotBanishSettings['BOTBANISH_APIKEY'] : 'Free';
	$row['geo_apikey'] = isset($BotBanishSettings['BOTBANISH_GEO_APIKEY']) ? $BotBanishSettings['BOTBANISH_GEO_APIKEY'] : 'Free';
	$row['bot_ip'] = (!isset($row['bot_ip']) || empty($row['bot_ip'])) ? $ip : $row['bot_ip'];
	$row['contact'] = isset($BotBanishSettings['BOTBANISH_WEBMASTER_EMAIL']) ? $BotBanishSettings['BOTBANISH_WEBMASTER_EMAIL'] : '';
	$row['domain_name'] = (!isset($row['domain_name']) || empty($row['domain_name'])) ? BotBanishGetDomainName($_SERVER) : $row['domain_name'];
	$row['domain'] = (!isset($row['domain']) || empty($row['domain'])) ? BotBanishGetDomainOrigin($row['bot_ip']) : $row['domain'];
	$row['first_hit'] = (!isset($row['first_hit']) || empty($row['first_hit'])) ? BotBanishGetCorrectDateTimeB() : $row['first_hit'];
	$row['forcelockout'] = !isset($row['forcelockout']) ? 0 : $row['forcelockout'];
	$row['version'] = $BotBanishSettings['BOTBANISH_VERSION'];
	$row['version_no'] = $BotBanishSettings['BOTBANISH_VERSION_NO'];
	$row['user_agent'] = (!isset($row['user_agent']) || empty($row['user_agent'])) ? $useragent : $row['user_agent'];

	$row['country'] = $country_info['country'];
	$row['country_code'] = $country_info['country_code'];
	$row['geo_info'] = BotBanishSafeSerialize($geo_data);

	$row['uri'] = isset($_SERVER['REDIRECT_SCRIPT_URI']) ? $_SERVER['REDIRECT_SCRIPT_URI'] : '';
	$row['uri'] = empty($row['uri']) && isset($_SERVER['SCRIPT_URI']) ? $_SERVER['SCRIPT_URI'] : '';
	$row['protocol'] = stripos($row['uri'], 'https://') !== false ? 'https' : 'http';
	$row['site'] = isset($_SERVER['REQUEST_SCHEME']) ? $_SERVER['REQUEST_SCHEME'] : 'http';
	$row['root'] = isset($_SERVER['DOCUMENT_ROOT']) ? $_SERVER['DOCUMENT_ROOT'] : '';
	$row['htaccess'] = BotBanishSafeSerialize($BotBanishSettings['BOTBANISH_HTACCESS_ARRAY']);
	$row['ip_addr'] = isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : $_SERVER['REMOTE_ADDR'];
	$row['redirect_only'] = $BotBanishSettings['BOTBANISH_REDIRECT_ONLY_ACTIVE'];
	$row['system'] = isset($row['system']) ?  $row['system'] : BotBanishSafeSerialize(BotBanishCheckSystem());
}

function BotBanishBrowserNoCache() {

	// Set headers to prevent caching

	header("Expires: Tue, 01 Jan 2000 00:00:00 GMT");
	header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
	header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
	header("Cache-Control: post-check=0, pre-check=0", false);
	header("Pragma: no-cache");
}

function BotBanishGetSession() {

	$system = BotBanishCheckSystem();
	
	if (strtoupper($system['install_type']) == 'SERVER')
		return;

	if (!isset($GLOBALS['BotBanishSession']) || !is_object($GLOBALS['BotBanishSession'])) {

		$BotBanishSession = new BotBanishSession;
		$GLOBALS['BotBanishSession'] = $BotBanishSession;

	} else {

		$BotBanishSession = $GLOBALS['BotBanishSession'];
	}

	return $BotBanishSession;
}

function BotBanishGetCache() {

	if (!isset($GLOBALS['BotBanishCache']) || !is_object($GLOBALS['BotBanishCache'])) {

		$BotBanishCache = new BotBanishCache;
		$GLOBALS['BotBanishCache'] = $BotBanishCache;

	} else {

		$BotBanishCache = $GLOBALS['BotBanishCache'];
	}

	return $BotBanishCache;
}

function BotBanishScheduledTasks($minutes = 5) {

	global $BotBanishSettings;

	$system = BotBanishCheckSystem();
	$installType = strtoupper($system['install_type']);

	$systemScheduleType = 'BOTBANISH_' . $installType . '_SCHEDULED_TASK_TIME';

	if (!isset($BotBanishSettings[$systemScheduleType]))
		return;

	$date = BotBanishGetCorrectDateTimeB();
		
	if ($date > $BotBanishSettings[$systemScheduleType]) {

		include_once $BotBanishSettings['BOTBANISH_SUBS_DIR'] . 'BotBanish_ScheduledTasks.php';
		
		BotBanish_ScheduledTasks($installType);

		$seconds = 60;		// Seconds in a minutes
		$elapsedTime = BotBanishGetCorrectDateTimeB() + ($seconds * $minutes);

		$BotBanishSettings[$systemScheduleType] = $elapsedTime;
		
		$rows = array();
		$rows[$systemScheduleType] = $elapsedTime;
		BotBanishSettingsTablePutValues($rows);
	}
}

function BotBanishSeeIfLockedOut($BotBanishSession) {

	$ip = BotBanishGetIP();	
	BotBanishCountCacheHits($ip);
	
	if (BotBanishSearchGeoForSearchEngine($BotBanishSession) !== false)
		BotBanishExit(true);
					
	if ($BotBanishSession->getSessionKey('locked') !== false)
		BotBanishRedirectExit();
	
	return false;	
}

//=====================================================================================================
// Used when initially loading the module to setup folders, URL's and other settings
//=====================================================================================================

	global $BotBanishSettings;

	define('BOTBANISH_SESSION', 'BotBanish');

	$system = BotBanishCheckSystem();

	if (!defined('BOTBANISH_DIR'))
		define ('BOTBANISH_DIR', $system['location']);

	require_once BOTBANISH_DIR . 'Include/BotBanish_Version.php';
	BotBanishSetVersion();
	
	$BotBanishSettings = BotBanishSetFolders();

	$BotBanishSettings['BOTBANISH_DIR'] = BOTBANISH_DIR;

	switch (strtoupper($system['install_type'])) {

		case 'SERVER':

			$filename = BOTBANISH_DIR . 'Settings_Server.php';
			$GLOBALS['parameter'] = '?';
			$BotBanishSettings['BOTBANISH_SERVER'] = 1;
			require_once BOTBANISH_DIR . 'Server/BotBanishServer_Subs_Country.php';
//			require_once BOTBANISH_DIR . 'Server/BotBanishServer_ContactFormSpamDenial.php';
			break;

		default:

			$filename = BOTBANISH_DIR . 'Settings_Client.php';
			$GLOBALS['parameter'] = '?';
			$BotBanishSettings['BOTBANISH_CLIENT'] = 1;
			require_once BOTBANISH_DIR . 'Client/BotBanishClient.php';
			require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_ContactDenial.php';
			require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_ContactFormSpamDenial.php';
			require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_UserDenial.php';
			require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_UserSpamDenial.php';
			require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_ClientCountry.php';
			break;
	}

	require_once BOTBANISH_DIR . 'Subs/BotBanish_Autoload.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Cache.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_FileUpload.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_ScheduledTasks.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Session.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_AdjustDatabase.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_Country.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_DateTime.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_DB_Website.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_Domain.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_DumpDatabase.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_Email.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_ErrorHandler.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_File.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_HTACCESS.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_IP.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_Language.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_Log.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_Redirect.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_SendMail.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_Session.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_Spider.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_URL.php';
	require_once BOTBANISH_DIR . 'Subs/BotBanish_SplitSQLAsync.php';

	BotBanishSetErrorHandler();

	require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_Options.php';

	BotBanishSetVersion();

	$GLOBALS['override_state'] = array();

	// Only use BotBanish native calls to mySQL if processing an ErrorDocument or register account issue

	$GLOBALS['override'] = (stripos($_SERVER['PHP_SELF'], 'BotBanish_AccessError') !== false) &&  (stripos($_SERVER['PHP_SELF'], 'BotBanish_RegisterAccount') !== false) ? false : true;

	$GLOBALS['log_state'] = array();
	$GLOBALS['log_override'] = false;

	BotBanishSetLanguage();

	switch ($system['system']) {

		case 'WORDPRESS':

			require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_DB_WordPress.php';
			$GLOBALS['parameter'] = '&';
			break;

		case 'SMF':

			require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_Routines_SMF.php';
			require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_DB_SMF.php';
			require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_SMF.php';
			break;

		case 'OPENCART':

			require_once BOTBANISH_DIR . 'Subs/BotBanish_Subs_DB_Opencart.php';
			break;
	}

	BotBanishStartUp();
	BotBanishDefineGlobals('BOTBANISH_WEB_SERVER', 'BotBanishServer.php');

	$htaccess_array = BotBanishGetHTACCESSLocations();
	BotBanishDefineGlobals('BOTBANISH_HTACCESS_ARRAY', $htaccess_array);

	//================================================================
	// Load all classes in the vendor folder
	//================================================================

	BotBanish_Autoload($BotBanishSettings['BOTBANISH_AUTOLOAD_DIR']);

	// Can't run without this one

	if (class_exists('PHPSQLParser'))
		$SQL_Parser = new PHPSQLParser();

	// If we are installing NEVER use the Settings_Client.php or Settings_Server.php file!!!!

	if (!isset($BotBanishSettings['BOTBANISH_INSTALL']) || (!$BotBanishSettings['BOTBANISH_INSTALL'])) {

		if (file_exists($filename)) {

			include_once $filename;

			switch (strtoupper($system['install_type'])) {

				case 'CLIENT':

					// Load BotBanish Session handling

					$BotBanishCache = new BotBanishCache();
					$GLOBALS['BotBanishCache'] = $BotBanishCache;

					$BotBanishCache->setCacheDir = (isset($BotBanishSettings['BOTBANISH_STATIC_CACHE_DIR']) && !empty($BotBanishSettings['BOTBANISH_STATIC_CACHE_DIR'])) ? $BotBanishSettings['BOTBANISH_STATIC_CACHE_DIR'] : getcwd() . '/Cache/';
					$BotBanishSession = $BotBanishCache->getCacheObject(BotBanishGetIP());
					
					BotBanishSeeIfLockedOut($BotBanishSession);					
					break;
			}
		}
	}

	$BotBanishSettings['BOTBANISH_404_EXTENSIONS'] = BotBanishGet404Extensions();
	BotBanishScheduledTasks();
?>
