<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
// BotBanish 9.0.05
// Randem Systems: https://randemsystems.support
// BotBanish Spider / Bot Routines
// Date: 08/06/2026
//
///////////////////////////////////////////////////////////////////////////////////////////////////////

function BotBanishCheckForGoodSpider($user_agent, $domain) {

	global $BotBanishSettings;

	$table = isset($BotBanishSettings['BOTBANISH_SERVER']) && $BotBanishSettings['BOTBANISH_SERVER'] ? 'bbs_botbanishserver_spider_good' : 'bbc_botbanishclient_spider_good';

	$sql = 'SELECT `id_spider` FROM ' . $table .
				' WHERE  LOCATE(`user_agent_part`, "' . addslashes($user_agent) . '") AND `active` = 1 LIMIT 1' ;

	$rows = BotBanishExecuteSQL($sql);
	$row = BotBanishLimitReturn($rows);

	if (!is_array($row) || empty($row))
		return false;	// Not a Good Spider

	//------------------------------------------------------------------------------------------------
	// If this is a good spider in our table we must check to see if it is really legitimate
	// by checking if it comes from a valid domain. If not, reject it for it is spoofing a good spider
	//------------------------------------------------------------------------------------------------

	$bool = BotBanishCheckForGoodDomain($domain);	// See if this spider is from an acceptable domain

	if (empty($user_agent) && $bool)	// If a blank user-agent and from an acceptable domain, accept it
		return true;

	if (!$bool) {

		$lockout = $BotBanishSettings['BOTBANISH_SPOOF_BOT_LOCKOUT'];
		return $lockout;
	}

	return true;
}

function BotBanishCheckForBadSpider($user_agent) {

	global $BotBanishSettings;

	$table = isset($BotBanishSettings['BOTBANISH_SERVER']) && $BotBanishSettings['BOTBANISH_SERVER'] ? 'bbs_botbanishserver_spider_bad' : 'bbc_botbanishclient_spider_bad';

	$sql = 'SELECT `id_spider` FROM `' . $table . '`
				WHERE  LOCATE(`user_agent_part`, "' . addslashes($user_agent) . '") AND `active` = 1 LIMIT 1' ;

	$rows = BotBanishExecuteSQL($sql);
//	$row = BotBanishLimitReturn($rows);

	if (!is_array($rows) || empty($rows)) {
		
		$lockout = BotBanishCheckForUnknownSpider($user_agent);
		return $lockout;
	}

	return false;
}

function BotBanishCheckForUnknownSpider($user_agent) {

	global $BotBanishSettings;
	
	$exception = explode(',', $BotBanishSettings['BOTBANISH_UA_EXCEPTIONS']);
	$lockout = false;

	foreach ($exception as $key => $element){

		// Log this bot / spider / user and lock it out for it is most likely a bot

		if (strpos($user_agent, $element) !== false) {

			$lockout = $BotBanishSettings['BOTBANISH_UNKNOWN_BOT_LOCKOUT'];
			break;
		}
	}

	return $lockout;
}

function BotBanishSpiderMonitorActivity($row) {

	global $BotBanishSettings;

	$table = isset($BotBanishSettings['BOTBANISH_SERVER']) && $BotBanishSettings['BOTBANISH_SERVER'] ? 'bbs_botbanishserver_spider_bad' : 'bbc_botbanishclient_spider_bad';

	// We should only get here if a bot/spider is filling out hidden fields in forms.
	// Humans cannot accomplish this task. Good or bad bot? We don't know yet
	// Someone will need to research the entries in the spider table to determine this
	// then place the information in the good or bad spider table to track or deny.

	$sql = 'SELECT `id_spider`, `hit_count`, `first_hit` FROM `' . $table . '`'.
				' WHERE  LOCATE(`user_agent`, "' . $row['user_agent'] . '") LIMIT 1' ;

	$user_agent = BotBanishExecuteSQL($sql);
	$user_agent = BotBanishLimitReturn($user_agent);
	$date = BotBanishGetCorrectDateTimeB();

	if (!is_array($user_agent) || empty($user_agent)) {

		global $BotBanishSettings;

		$row['forcelockout'] = $BotBanishSettings['BOTBANISH_UNKNOWN_BOT_LOCKOUT'];
		$row['type'] = 'bot';
	}

	return $row['forcelockout'];
}

function BotBanishCheckForSpiderOverride($ip, $user_agent = '', $domain = '') {

	global $BotBanishSettings;

	if (getenv('bad_bot'))
		return $BotBanishSettings['BOTBANISH_BAD_BOT_LOCKOUT'];

	if (empty($user_agent))
		return $BotBanishSettings['BOTBANISH_EMPTY_USERAGENT_LOCKOUT'];

	// If this is a real Google bot, let it be

//	if (BotBanishCheckForGoogleSpider($ip))	
	
	// If this is an approved search engine, let it be

	if (BotBanishSearchGeoForSearchEngine())
		return false;

	// If a user acceptible bot, let it be

	if (BotBanishCheckForGoodSpider($user_agent, $domain))
		return false;

	// If a bad bot, let the caller know

	if (BotBanishCheckForBadSpider($user_agent))
		return $BotBanishSettings['BOTBANISH_BAD_BOT_LOCKOUT'];

	return false;
}

function BotBanishCheckForSpiders() {

	global $BotBanishSettings;

	// Let's see if you are a spider...

	$user_agent = BotBanishGetUserAgent($_SERVER);
	$ip = BotBanishGetIP();

	if (empty($user_agent))
		BotBanishRedirectExit($BotBanishSettings['BOTBANISH_EMPTY_user_agent_LOCKOUT'], $ip);

	// If so, we don't need them in the analytics!!! Off you go!
	
	if (BotBanishCheckForBadSpider($user_agent))
		BotBanishRedirectExit($BotBanishSettings['BOTBANISH_BAD_BOT_LOCKOUT'], $ip);

	// If so, we don't need them in the analytics!!! Off you go!
	
	if (BotBanishCheckForGoodSpider($user_agent))
		BotBanishExit(true);
	
	return false;
}

function BotBanishGetUserAgent($arr = array()) {

	$user_agent = '';

	$arr = empty($arr) ? $_SERVER : $arr;

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

		$user_agent = (stripos($key, 'HTTP_USER_AGENT') !== false) ? $value : '';

		if (!empty($user_agent))
			break;
	}

	return $user_agent;
}

function BotBanishCheckForGoogleSpider($ip) {

	// Begin anti-spoofing measures to check for a real Google bot
	// May expand to other search engines

	$domain = BotBanishGetDomainOrigin($ip);

	// Did Google send this bot? Domain name should be 'google'

	$domains = array('.google.com', '.googlebot.com');

	$len1 = strlen($domain);
	$len2 = strlen(str_ireplace($domains, '', $domain));

	if ($len1 != $len2)
		return true;

	// Still not sure? Check Country Info

	$BotBanishSession = BotBanishGetSession();


	return false;	// Not Google
}

function BotBanishSpiderGetList($table) {

	$sql = 'SELECT `user_agent_part` FROM `' . $table . '` WHERE `active` = 1';
	$rows = BotBanishExecuteSQL($sql);
	$bot_list = array();

	if (!empty($rows) && is_array($rows)) {

		foreach ($rows as $row) {

//			if (BotBanishCheckIfValidItem($row['user_agent_part']))
				$bot_list[] = $row['user_agent_part'];
		}
	}

	return $bot_list;
}

function BotBanishBadSpiderInsert($bot_list, $table) {

	if (!is_array($bot_list))
		$bot_list = array($bot_list);

	// Add blocked BOT to our local database (Ignore duplicates)

	foreach ($bot_list as $bot) {

		$row = array();

		$row['spider_name'] = $bot;
		$row['user_agent_part'] = $bot;
		$row['active'] = 1;

		$params = BotBanishBuildSQLStatementInsert($row, $table);

		$sql = 'INSERT INTO `' . $table.'` (' . $params['columns'] . ') VALUES (' . $params['values'] . ')';

		if (isset($params['updates']) && !empty($params['updates']))
			$sql .= ' ON DUPLICATE KEY UPDATE ' . $params['updates'];

		BotBanishExecuteSQL($sql);
	}
}

function BotBanishFixUserAgent($user_agent) {

	$user_agent = urldecode($user_agent);
	$user_agent = html_entity_decode($user_agent);		// Make sure no HTML encoded strings are in User-Agent

	// Some bots try to be sneaky and put carriage returns, line feeds and other strings in to thwart detection

	$user_agent = str_replace(array('"', "'", PHP_EOL, "\n", "\r", "\0", 'string:quot;', 'quot;', '{', '}', '&quot', 'quot;'), '', $user_agent);
	$user_agent = addslashes ($user_agent);				// Escape any slashes, quotes etc...

	return $user_agent;
}

function CheckIfSpider($user_agent) {

	global $BotBanishSettings;
	
	$table = (isset($BotBanishSettings['BOTBANISH_SERVER']) && $BotBanishSettings['BOTBANISH_SERVER']) ? 'bbs_botbanishserver_spider_bad' : 'bbc_botbanishclient_ip_bad';

	$spider = BotBanishSpiderCheck($user_agent);
	return $spider;
}

function BotBanishSpiderCheck($user_agent) {

	$user_agent = BotBanishFixUserAgent($user_agent);
	
	// Good spider check

	$table = (isset($BotBanishSettings['BOTBANISH_SERVER']) && $BotBanishSettings['BOTBANISH_SERVER']) ? 'bbs_botbanishserver_spider_good' : 'bbc_botbanishclient_ip_good';

	$sql = 'SELECT `id_spider`, `spider_name` FROM ' . $table . '
		WHERE  LOCATE(`user_agent_part`, "'. addslashes($user_agent) . '")';

	$rows = BotBanishExecuteSQL($sql);
	$row = BotBanishLimitReturn($rows);

	if (is_array($row) && !empty($row))
		return $row['spider_name'];

	// Bad spider check

	$table = (isset($BotBanishSettings['BOTBANISH_SERVER']) && $BotBanishSettings['BOTBANISH_SERVER']) ? 'bbs_botbanishserver_spider_bad' : 'bbc_botbanishclient_ip_bad';

	$sql = 'SELECT `id_spider`, `spider_name` FROM ' . $table . '
		WHERE  LOCATE(`user_agent_part`, "'. addslashes($user_agent) . '")';

	$rows = BotBanishExecuteSQL($sql);
	$row = BotBanishLimitReturn($rows);

	if (is_array($row) && !empty($row))
		return $row['spider_name'];

	if (BotBanishCheckForUnknownSpider($user_agent))
		return 'Unknown';

	return '';
}

function BotBanishSearchGeoForSearchEngine($BotBanishSession = '') {
	
	if (empty($BotBanishSession))
		$BotBanishSession = BotBanishGetSession();
	
	$geo_data = $BotBanishSession->getSessionKey('geodata');
	
	if (!isset($geo_data['organization']))
		return false;
	
	$org = $geo_data['organization'];
	
	// Place into a table for future reference
	
	$engines = array('Google');
	$flag = false;
	
	foreach ($engines as $engine) {
		
		$flag = stripos($org, $engine);
		
		if ($flag !== false)
			break;
	}
	
	return $flag;
}
?>