<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
// BotBanish 8.0.00
// Randem Systems: https://randemsystems.support
// BotBanish Log file Subroutines
// Date: 05/13/2026
// Usage:
//
///////////////////////////////////////////////////////////////////////////////////////////////////////

function BotBanishSetLogFilename($filetype = '', $domain_name = '') {

	global $BotBanishSettings;
	
	$domain_name = empty($domain_name) && isset($BotBanishSettings['BOTBANISH_DOMAIN_NAME']) ? $BotBanishSettings['BOTBANISH_DOMAIN_NAME'] : $domain_name;
	$log_array = BotBanishLogGetLocation($filetype, $domain_name);

	$filename = $log_array['filename'];
	return $filename;
}

function BotBanishLogInfo($text, $info_data, $savestate = false, $logtype = '') {

	global $BotBanishSettings;

	if (!$savestate) {

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

	} else {

		BotBanishSaveLogState();
	}

	$type = !empty($logtype) ? $logtype : 'Info';
	$sep = PHP_EOL . str_repeat('=', 80) . PHP_EOL;

	if (is_object($info_data)) {
		
		$data = var_export($info_data, true);
		
	} else {
	
		$data = BotBanishSafeUnSerialize($info_data);
		$data = is_array($data) ? BotBanishFormatArray($data) : $data;

		if (!is_array($data)) {

			if (stripos($data, '|') !== false) {

				$row = array();
				parse_str($data, $row);
				$data = BotBanishFormatArray($row);
			}
		}
	}

	$str = BotBanishFormatArray($text) . PHP_EOL . PHP_EOL . BotBanishFormatArray($data) . PHP_EOL;

//	$filename = BotBanishSetLogFilename($type, $BotBanishSettings['BOTBANISH_USER_HOST']);
	$filename = BotBanishSetLogFilename($type);

	if (isset($BotBanishSettings['BOTBANISH_DEBUG_BACKTRACE']) && $BotBanishSettings['BOTBANISH_DEBUG_BACKTRACE'])
		$str .= PHP_EOL . PHP_EOL . BotBanishDebugBackTrace();

	BotBanishWriteFile($filename, BotBanishGetCorrectDateTime() . '  ' . $str . $sep, true);

	if ($savestate)
		BotBanishRestoreLogState();
}

function BotBanishLogGetLocation($log_type = '', $domain_name = '') {

	global $BotBanishSettings;

	$log_array = array(
		'location' => '',
		'file_date' => '',
		'table_name' => '',
		'type' => '',
		'version' => '',
		'curloc' => '',
		'filename' => ''
		);

	// Set filename date

	$log_array['file_date'] = date('Y-m-d', strtotime('now'));

	$system = BotBanishCheckSystem();

	// Get database error table name

	switch ($system['system']) {

		case 'SERVER':

			$log_array['table_name'] = 'bbs_botbanishserver_doc_errors';
			$log_array['type'] = 'Server';
			$side = '[Serverside]';
			break;

		default:

			$log_array['table_name'] = 'bbc_botbanishclient_doc_errors';
			$log_array['type'] = 'Client';
			$side = '[Clientside]';
			break;
	}

	$domain_name = !empty($domain_name) ? '_'  . $domain_name : $domain_name;
	
	$log_array['version'] = $BotBanishSettings['BOTBANISH_VERSION'];

	// Get log file path

	$log_array['location'] = $BotBanishSettings['BOTBANISH_STATIC_LOGS_DIR'];

	// Create the log folder if it does not exist

	if (!is_dir($log_array['location']))
		@mkdir($log_array['location'], 0755, true);

	$log_type = !empty($log_type) ? ucfirst($log_type) : 'Activity';
	$log_array['filename'] = $BotBanishSettings['BOTBANISH_STATIC_LOGS_DIR'] . $BotBanishSettings['BOTBANISH_USER_HOST'] . $domain_name . '_' . str_replace(' ', '_', $BotBanishSettings['BOTBANISH_VERSION']) . '_' . $log_type . '_' . $side . '_' . $log_array['file_date'] . '.log';

	return $log_array;
}


function BotBanishLogError($error, $data = '', $log_type = '', $domain_name = '', $short = false) {

	// Short error processing is basically for bot traffic reporting (email)

	global $BotBanishSettings, $BotBanishSQL, $BotBanishURL, $BotBanishText, $botbanish_info, $client_info;

	// Turn off our error handler while in our error handler

	BotBanishRestoreErrorHandler();

	$logall = true;

	$date = BotBanishGetCorrectDateTime();
	$error_trace = '';
	$errors = '';
	$cause = '';
	
	// Error file processing

	$str = sprintf('---------------------------%s - %s - %s -----------------------------', $BotBanishSettings['BOTBANISH_VERSION'], $date, BotBanishGetIP());
	$str .= PHP_EOL . PHP_EOL;
	$str .= $BotBanishText['location'] . ': ' . $BotBanishSettings['BOTBANISH_LOCATION'] . PHP_EOL . $errors . PHP_EOL;

	if (is_object($error)) {

		$errors = var_export($error, true);

	} else {

		$errors = strip_tags($error, '<br><br />');
		$errors = str_replace('<br>', PHP_EOL, $errors);
		$errors = str_replace('<br />', PHP_EOL, $errors);
	}

	if (!$short) {

		$data = BotBanishSafeUnserialize($data);

		if (is_array($data))
			$data = BotBanishFormatArray($data);

		if (substr_count($data, '&') > 5)
			$data = parse_url($data);

		if (!empty($data))
			$errors .= PHP_EOL . $BotBanishText['error_data'] . ': ' . str_replace(array('<br>', '</br>'),  PHP_EOL, $data) . PHP_EOL . PHP_EOL;

		$errors = $str . $errors;
		$errData = $errors;

		$cause = isset($_SERVER['REDIRECT_URI']) ? $_SERVER['REDIRECT_URI'] : '';
		$cause = empty($cause) && isset($_SERVER['REDIRECT_QUERY_STRING']) ? $_SERVER['REDIRECT_QUERY_STRING']  : '';
		$cause = empty($cause) && isset($_SERVER['SCRIPT_URL']) ? $_SERVER['SCRIPT_URL']  : '';
		$cause = !empty($cause) ? $cause . PHP_EOL . $BotBanishText['filenotfound'] : '';
		$cause .= PHP_EOL . PHP_EOL . var_export($_SERVER, true);

		// We can't do a country lookup if the database connection has failed...

		if (stripos($error, 'Connection Failed') === false) {

			$country_info = isset($GLOBALS['country_info']) ? $GLOBALS['country_info'] : array();

			if (!empty($cause) && isset($country_info['country']) && !empty($country_info))
				$cause .= PHP_EOL . $BotBanishText['offending_country'] . ': ' . $country_info['country'];
		}

		$errors .= PHP_EOL . PHP_EOL . $BotBanishText['execution_location'] . ': ' . dirname(__FILE__) . PHP_EOL;

		// SQL is for all errors

		if (isset($BotBanishSQL) && !empty($BotBanishSQL))
			$errors .= $BotBanishText['last_sql'] . ': ' . $BotBanishSQL . PHP_EOL;

		// URL is only for client side errors!!!

		if (isset($BotBanishSettings['BOTBANISH_CLIENT']) && ($BotBanishSettings['BOTBANISH_CLIENT']) && (!empty($BotBanishURL)))
			$errors .= $BotBanishText['last_url'] . ': ' . $BotBanishURL . PHP_EOL;

		if (!empty($cause))
			$errors .= !empty($cause) ? $BotBanishText['cause'] . ': ' . str_replace('&', PHP_EOL, urldecode($cause)) . PHP_EOL : '';

		if ($logall) {

			// We may need to see what the client is attempting to do...

			if (isset($BotBanishSettings['BOTBANISH_DB_SERVERNAME']))
				$errors .= $BotBanishText['database_name'] . ': ' . $BotBanishSettings['BOTBANISH_DB_NAME'] . PHP_EOL . $BotBanishText['host'] . ': ' . $BotBanishSettings['BOTBANISH_DB_SERVERNAME'] . PHP_EOL . PHP_EOL;

			$errors .= BotBanishFormatArray($botbanish_info);
			$errors .= BotBanishFormatArray($client_info);
		}

			$errors .= BotBanishDebugBackTrace();
	}

	// Write to a flat file in case of a database error
	// Turn off special debug processing

	$filename = BotBanishSetLogFilename($log_type, $domain_name);
	BotBanishWriteFile($filename, $errors, true);

	BotBanishSetErrorHandler();	// Restore our error handler
}

function BotBanishLogSQL($sql, $override = false) {

	global $BotBanishSettings;

	if (!$override) {

		if (!isset($BotBanishSettings['BOTBANISH_DEBUG_SQL']) || ($BotBanishSettings['BOTBANISH_DEBUG_SQL'] == false))
			return;
	}

	// If an array, this might be an error exception being passed, so record all elements

	$data = is_array($sql) ? BotBanishFormatArray($sql) : $sql;
	$filename = BotBanishSetLogFilename('SQLStatements');

	$str = function_exists('smf_db_initiate') ? 'smcFunc ' : '';
	$str = empty($str) && function_exists('add_filter') ? 'wpdb ' : '';
	$str = empty($str) ? 'Native ' : '';

	if (isset($BotBanishSettings['BOTBANISH_DEBUG_BACKTRACE']) && $BotBanishSettings['BOTBANISH_DEBUG_BACKTRACE'])
		$data .= PHP_EOL . PHP_EOL . BotBanishDebugBackTrace();

	BotBanishWriteFile($filename, BotBanishGetCorrectDateTime() . ' (' . $str . ')  ' . $data . PHP_EOL . PHP_EOL, true);
}

function BotBanishLogProgress($data) {

	global $BotBanishSettings;

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

	global $BotBanishSettings;

	$filename = BotBanishSetLogFilename('Progress');
	BotBanishWriteFile($filename, BotBanishGetCorrectDateTime() . '  ' . $data . PHP_EOL, true);
}

function BotBanishDebugBackTrace($logit = false) {

	global $BotBanishText;

	$error_trace = '';
	$backtrace_array = debug_backtrace();

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

		$error_trace .= isset($BotBanishText['called_from']) ? $BotBanishText['called_from'] . PHP_EOL : 'Called From: ';
		$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($error_info['line']) ? "\t" . 'Line: ' . $error_info['line'] . PHP_EOL : '';
		$error_trace .= PHP_EOL;
	}

	if ($logit) {

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

	return $error_trace;
}

function BotBanishMaintainLogs($num = '') {

	global $BotBanishSettings;

	if (!isset($BotBanishSettings['BOTBANISH_LOG_FILES']) || ($BotBanishSettings['BOTBANISH_LOG_FILES'] < 5))
		return;

	if (empty($num))
		$num = $BotBanishSettings['BOTBANISH_LOG_FILES'];

	$log_array = explode(',', $BotBanishSettings['BOTBANISH_LOG_TYPES']);

	sort($log_array);
	$files = array();

	foreach ($log_array as $log) {

		$files = glob($BotBanishSettings['BOTBANISH_STATIC_LOGS_DIR'] . '*_' . $log . '_*.log');
		$x = $num;
		$y = count($files);

		if ($x >= $y) return;

		$i = $y - $x;

		for ($j = 0; $j < $i; $j++)
			unlink($files[$j]);
	}
}

function BotBanishTraceIt($text, $data, $logit = true, $post = false, $backtrace = false, $server = false) {

	if (!$logit) return;
	
	BotBanishDebugTrace($text, $data, $post, $backtrace, $server);
}

function BotBanishDebugTrace($text, $data, $post = false, $backtrace = false, $server = false) {
	
	$debug = array(
			'BOTBANISH_COUNTRY_DEBUG' =>'country',
			'BOTBANISH_CLIENT_DEBUG' => 'client',
			'BOTBANISH_SERVER_DEBUG' => 'server',
		);
		
	foreach ($debug as $key => $value) {
		
		if (defined($key) && ($key === true)) {
			
			$type = $value;
			break;
		}
	}

	global $BotBanishSettings;
	
	if (isset($BotBanishSettings['BOTBANISH_DEBUG_OVERRIDE']) && !empty($BotBanishSettings['BOTBANISH_DEBUG_OVERRIDE']))		
		$type = $BotBanishSettings['BOTBANISH_DEBUG_OVERRIDE'];
		
	if (!isset($type)) return;

	$method = isset($_POST) && !empty($_POST) ? $_POST : $_GET;
	
	$ip = isset($method['bot_ip']) ? $method['bot_ip'] : '';
	$ip = empty($ip) && isset($method['ip']) ? $method['ip'] : $ip;
	$ip = empty($ip) ? BotBanishGetIP() : $ip;

	if (isset($BotBanishSettings['BOTBANISH_LIMIT_LOG_IP']) && !empty($BotBanishSettings['BOTBANISH_LIMIT_LOG_IP'])) {
		
		if (!BotBanishLimitLogs($ip))
			return;
	}
		
	$filename = BotBanishSetLogFilename('Trace_' . $ip);

	$date = BotBanishGetCorrectDateTime();

	$msg = PHP_EOL . PHP_EOL .  'Data:' . PHP_EOL . var_export(BotBanishSafeUnSerialize($data), true);

	if ($post)
		$msg .= PHP_EOL . PHP_EOL . '$_POST:' . PHP_EOL . var_export($_POST, true);
	
	if ($server)
		$msg .= PHP_EOL . PHP_EOL . '$_SERVER:' . PHP_EOL . var_export($_SERVER, true);
	
	if ($backtrace)
		$msg .= PHP_EOL . PHP_EOL . 'Backtrace:' . PHP_EOL . BotBanishDebugBackTrace();
		
	$str = PHP_EOL . str_repeat('=', 80) . PHP_EOL;
	BotBanishWriteFile($filename, $str . $date . ' - ' . $BotBanishSettings['BOTBANISH_FONT_RED_START'] . BotBanishGetCorrectDateTime() . ' - Rtn: ' . $text . ' - IP: ' . $ip . $BotBanishSettings['BOTBANISH_FONT_RED_END'] . PHP_EOL . PHP_EOL . $msg . PHP_EOL . PHP_EOL, true);
}

function BotBanishLimitLogs($ip) {
	
	global $BotBanishSettings;
	
	$ip_ranges = explode(',', $BotBanishSettings['BOTBANISH_LIMIT_LOG_IP']);
	
	if (in_array($ip, $ip_ranges))
		return true;

	return false;
}

function BotBanishSMFLogError($subject, $body) {
	
	global $BotBanishSettings;
	
	$dbInfo = BotBanishGetDatabaseInfo();
	
	require_once $BotBanishSettings['BOTBANISH_SMF_ROOT'] . '/Sources/Errors.php';
	log_error($subject . PHP_EOL . PHP_EOL . $body, 'botbanish');
}

function BotBanishUpdateBlockLogs($subject) {

	$subject = trim(str_ireplace(array($_SERVER['SERVER_NAME'], 'BotBanishClient:'), '', $subject));
	$table = 'bbc_botbanishclient_website_blocks';
	$ip = BotBanishGetIP();
	$date = date("Y-m-d");

	$sql = 'SELECT `id_no`, `bot_ip`, `subject`, `blocks` FROM `' . $table . '` WHERE `bot_ip` = "' . $ip . '" AND `subject` = "' . $subject . '" AND `date` = "' . $date . '" LIMIT 1';
	$row = BotBanishExecuteSQL($sql, true, true);
	$row = BotBanishLimitReturn($row);

	if (is_array($row) && isset($row['id_no'])) {

		$row['subject'] = $subject;
		$row['bot_ip'] = $ip;
		$row['date'] = $date;
		$row['blocks'] = isset($row['blocks']) ? $row['blocks'] + 1 : 1;

		$sql = 'UPDATE ' . $table . ' SET `blocks` = ' . $row['blocks'] . ' WHERE `id_no` = ' . $row['id_no'];

	} else {

		$row = array();
		$row['subject'] = $subject;
		$row['bot_ip'] = $ip;
		$row['date'] = $date;
		$row['blocks'] = 1;

		$params = BotBanishBuildSQLStatementInsert($row, $table);
		$sql = 'INSERT INTO `' . $table . '` (' . $params['columns'] . ') VALUES (' . $params['values'] . ')
				 ON DUPLICATE KEY UPDATE `blocks` = `blocks` + 1';
	}

	BotBanishExecuteSQL($sql, true, true);
}

function BotBanishLogDownload($file_name, $system = '') {

	global $BotBanishSettings;

	if (empty($file_name))
		return;

	// If the user does not want analytics, then don't do it!

	if (!isset($BotBanishSettings['BOTBANISH_ANALYTICS_DOWNLOADS']) || $BotBanishSettings['BOTBANISH_ANALYTICS_DOWNLOADS'] == false)
		return;

	BotBanishSetTimeZone($BotBanishSettings['BOTBANISH_TIMEZONE']);

	// If this user is in our DNB table; there is no reason to log them

	$ip = BotBanishGetIP();

	if ($ip === '')
		return false;	// Nothing we can do here!!!

	// We don't count our own downloads
	// If we should not block IP, Don't record it either

	if (BotBanishCheckForGoodIP($ip))
		return;

	// Ok, ready to log

	$table = 'bbc_botbanishclient_website_downloads';

	$row = array();
	$row['ip_addr'] = $ip;
	$row['http_user_agent'] = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : $BotBanishSettings['BOTBANISH_HTTP_USER_AGENT'];
	$row['http_referer'] = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
	$row['rpt_date'] = date('Y-m-d');
	$row['date'] = date('Y-m-d');
	$row['hostname'] = gethostbyaddr($row['ip_addr']);
	$row['filename'] = $file_name;
	$row['system'] = $system;

	$row['http_referer'] = BotBanishEliminateData($row['http_referer']);

	$country_info = $BotBanishSession->getSessionKey('countryinfo');
	$geo_data = $BotBanishSession->getSessionKey('geodata');
	$row['country'] = $country_info['country'] !== 'null' ? $country_info['country'] : '';
	$row['country_code'] = $country_info['country_code'] !== 'null' ? $country_info['country_code'] : '';
	$row['geo_info'] = BotBanishSafeSerialize($geo_data);

	$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, true);
}

function BotBanishCleanupLogs($seconds) {

	global $BotBanishSettings;

	// This will clean up log files that are out of date

	$files = glob(str_replace(array('\\', '//'), '/', $BotBanishSettings['BOTBANISH_STATIC_LOGS_DIR']) . '*.log');
	$date = BotBanishGetCorrectDateTimeB();
	$cleanup_days = isset($BotBanishSettings['BOTBANISH_CLIENT_CLEANUP_DAYS_LOGS']) ? $BotBanishSettings['BOTBANISH_CLIENT_CLEANUP_DAYS_LOGS'] : 30;

	foreach ($files as $file) {

		if (is_dir($file))
			continue;

		$filename_parts = explode('_', $file);
		$part = $filename_parts[count($filename_parts) - 1];
		$file_date = trim(str_ireplace('.log', '', $part));

		$datediff = $date - strtotime($file_date);
		$days = round($datediff / $seconds);

		if ($days > $cleanup_days)
			unlink($file);
		else
			break;
	}
}

function BotBanishContactMessageTrace($row, $name = '', $fileType = '', $message = array()) {

	global $BotBanishSettings;

	$fileType = empty($fileType) ? 'Trace' : $fileType;
	$filename = BotBanishSetLogFilename($fileType, $BotBanishSettings['DOMAIN_NAME']);

	$date = BotBanishGetCorrectDateTime();

	if (!empty($message))

		$msg = var_export($message, true);
	else
		$msg = var_export($row, true);

	$str = PHP_EOL . PHP_EOL . str_repeat('=', 80) . PHP_EOL . PHP_EOL;
	BotBanishWriteFile($filename, $date . ' - ' . $str . $BotBanishSettings['BOTBANISH_FONT_RED_START'] . BotBanishGetCorrectDateTime() . ' Name: ' . $name . ' - IP: ' . $row['bot_ip'] . $BotBanishSettings['BOTBANISH_FONT_RED_END'] . PHP_EOL . PHP_EOL . $msg, true);
}

?>