<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
// BotBanish 9.0.03
// Randem Systems: https://randemsystems.support
// BotBanish Server Country Subroutines
// Date: 07/22/2026
// Usage:
//
/*
Possible returns from geoplugin.net

	geoplugin_request:66.249.79.148,
	geoplugin_status:206,
	geoplugin_delay:1ms,
	geoplugin_credit:Some of the returned data includes GeoLite data created by MaxMind, available from <a href='http:\/\/www.maxmind.com'>http:\/\/www.maxmind.com<\/a>.,
	geoplugin_city:,
	geoplugin_region:,
	geoplugin_regionCode:,
	geoplugin_regionName:,
	geoplugin_areaCode:,
	geoplugin_dmaCode:,
	geoplugin_countryCode:US,
	geoplugin_countryName:United States,
	geoplugin_inEU:0,
	geoplugin_euVATrate:false,
	geoplugin_continentCode:NA,
	geoplugin_continentName:North America,
	geoplugin_latitude:37.751,
	geoplugin_longitude:-97.822,
	geoplugin_locationAccuracyRadius:1000,
	geoplugin_timezone:America\/Chicago,
	geoplugin_currencyCode:USD,
	geoplugin_currencySymbol:$,
	geoplugin_currencySymbol_UTF8:$,
	geoplugin_currencyConverter:0

Possible returns from ipgeolocation calls

	ip:66.249.79.148
	continent_code:NA
	continent_name:North America
	country_code2:US
	country_code3:USA
	country_name:United States
	country_capital:Washington D.C.
	state_prov:California
	district:
	city:Mountain View
	zipcode:94043-1351
	latitude:37.42240
	longitude:-122.08421
	is_eu:false
	calling_code:+1
	country_tld:.us
	languages:en-US,es-US,haw,fr
	country_flag:https://ipgeolocation.io/static/flags/us_64.png
	geoname_id:6301403
	isp:Google LLC
	connection_type:
	organization:Google LLC
	asn:AS15169
	currency:{code:USD,name:US Dollar,symbol:$}
	time_zone:{name:America/Los_Angeles,offset:-8,current_time:2023-04-05 10:37:01.971-0700,current_time_unix:1680716221.971,is_dst:true,dst_savings:1}
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////

function BotBanishClientGetCountryInfo($ip) {

	global $BotBanishText;

	// Check to see if we already have this information, if not then attempt to get it

	$ip = (!empty($ip) && BotBanishCheckIfValidIP($ip)) ? $ip : BotBanishGetIp();
	$system = BotBanishCheckSystem();

	$returned_data = BotBanishClientGetGeoInfo($ip);
	$geo_data = isset($returned_data['geo_data']) ? $returned_data['geo_data'] : array();
	$country_info = isset($geo_data['country_info']) ? $geo_data['country_info'] : array();

	$country_info['country'] = isset($country_info['country']) && !empty($country_info['country']) ? $country_info['country'] : $BotBanishText['Unknown'];
	$country_info['country_code'] = isset($country_info['country_code']) && !empty($country_info['country_code']) ? $country_info['country_code'] : '';
	$country_info['country_flag'] = isset($country_info['country_flag']) && !empty($country_info['country_flag']) ? $country_info['country_flag'] : 'us.svg';

	$GLOBALS['country_info'] = $country_info;

	return $country_info;
}

function BotBanishClientGetGeoInfo($ip) {

	// Try our geo table first to see if we already have this information.
	// If we do not have the information get it and save it for later use

	$table = 'bbc_botbanishclient_geo';

	$sql = 'SELECT `country`, `country_code`, `geo_info` FROM `' . $table .'` WHERE `bot_ip` = "' . $ip . '"';
	$rows = BotBanishExecuteSQL($sql, true, true);
	$row = BotBanishLimitReturn($rows);

	// If data exists in table make sure all of it is populated

	if (isset($row['country']) && !empty($row['country'])) {

		$geo_data = BotBanishSafeUnserialize($row['geo_info']);
		$country_info = array();
		$country_info['country'] = $row['country'];
		$country_info['country_code'] = $row['country_code'];
		$geoInfo = array('geo_data' => $geo_data, 'country_info' => $country_info);

	} else {

		// Use ipgeolocation.io to get country information

		$geoInfo = BotBanishGetGeoAPI($ip);

		if (!empty($geoInfo['geo_data'])) {

			$country_info = $geoInfo['country_info'];

			$row = array();
			$row['bot_ip'] = $ip;
			$row['country'] = ucwords($country_info['country']);
			$row['country_code'] = strtoupper($country_info['country_code']);
			$row['geo_info'] =  $geoInfo['geo_data'];

			$params = BotBanishBuildSQLStatementInsert($row, $table);
			$sql = 'INSERT INTO `' . $table . '` (' . $params['columns'] . ') VALUES (' . $params['values'] . ')';
			BotBanishExecuteSQL($sql, true, true);
		}
	}

	return $geoInfo;
}

function BotBanishClientCheckGeoAPIKEY($ip, $geo_apikey = 'Free') {

	$geo_data = false;
	
	if  (strlen($geo_apikey) > 31)
		$geo_data = BotBanishClientGetGeoData_ipgeolocation($ip, $geo_apikey);
//		$geo_data = BotBanishClientGetGeoData_ipgeolocation2($ip, $geo_apikey);

	if (!$geo_data) $geo_data = array();
	
	return $geo_data;
}

function BotBanishClientGetGeoData_geoplugin($ip) {

	try {

		$query = 'http://www.geoplugin.net/json.gp?ip='.$ip;

		$ch = curl_init($query);
		curl_setopt($ch, CURLOPT_HEADER, false);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		$returned_data = curl_exec($ch);
		curl_close($ch);

		// Decode JSON response

		$geo_data = json_decode($returned_data, true);

		if (isset($geo_data['geoplugin_credit']))
			unset ($geo_data['geoplugin_credit']);

	} catch (Exception $e) {

		trigger_error(sprintf(
			'Curl failed with error #%d: %s',
			$e->getCode(), $e->getMessage()),
			E_USER_ERROR);

	} finally {

		// Close curl handle unless it failed to initialize
		if (is_resource($ch)) {
			curl_close($ch);
		}
	}

	return $geo_data;
}
/*
function BotBanishClientGetGeoData_ipgeolocation($ip, $apiKey, $lang = "en", $fields = "*", $excludes = "") {

	global $BotBanishSettings;

	try {
	
//		$url = 'https://api.ipgeolocation.io/ipgeo?';
		$url = "https://api.ipgeolocation.io/v3/ipgeo?";
		
		$params = array(
			'apiKey' => $apiKey,
			'ip' => $ip,
			'lang' => $lang,
			);
	
		$url = $url . http_build_query($params);

// BotBanishWriteFile($BotBanishSettings['BOTBANISH_STATIC_LOGS_DIR'] . 'curlURL.log' . PHP_EOL, $url, true);

		$cURL = curl_init();

		curl_setopt($cURL, CURLOPT_URL, $url);
		curl_setopt($cURL, CURLOPT_HTTPGET, true);
		curl_setopt($cURL, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($cURL, CURLOPT_HTTPHEADER, array(
			'Accept: application/json',
			'User-Agent: ' . $BotBanishSettings['BOTBANISH_HTTP_USER_AGENT'],
		));

		$returned_data = curl_exec($cURL);

//		BotBanishLogInfo('$returned_data: ', $returned_data, true, 'APIKEY');
	
		// Decode JSON response

		$geo_data = json_decode($returned_data, true);

//		BotBanishLogInfo('$geo_data: ', $geo_data, true, 'APIKEY');

	} catch (Exception $e) {

		$msg = sprintf(
			'Curl failed with error #%d: %s',
			$e->getCode(), $e->getMessage());
			
		BotBanishLogInfo('$msg: ', $msg, true, 'APIKEY');
		trigger_error($msg,	E_USER_ERROR);

	} finally {

		// Close curl handle unless it failed to initialize
		if (is_resource($cURL)) {
			curl_close($cURL);
		}
	}

	return $geo_data;
}
*/
function BotBanishClientGetGeoData_ipgeolocation($ip, $apiKey, $lang = "en", $fields = "*", $excludes = "") {

	global $BotBanishSettings;
	
	try {
		
		$url = "https://api.ipgeolocation.io/ipgeo?apiKey=".$apiKey."&ip=".$ip."&lang=".$lang."&fields=".$fields."&excludes=".$excludes;
		$cURL = curl_init();

		curl_setopt($cURL, CURLOPT_URL, $url);
		curl_setopt($cURL, CURLOPT_HTTPGET, true);
		curl_setopt($cURL, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($cURL, CURLOPT_HTTPHEADER, array(
			'Content-Type: application/json',
			'Accept: application/json',
			'User-Agent: ' . $BotBanishSettings['BOTBANISH_HTTP_USER_AGENT'],
		));

		$returned_data = curl_exec($cURL);

		// Decode JSON response

		$geo_data = json_decode($returned_data, true);
		
	} catch (Exception $e) {

		trigger_error(sprintf(
			'Curl failed with error #%d: %s',
			$e->getCode(), $e->getMessage()),
			E_USER_ERROR);

	} finally {
		
		// Close curl handle unless it failed to initialize
		if (is_resource($cURL)) {
			curl_close($cURL);
		}
	}
	
	return $geo_data;
}

function BotBanishClientGetGeoData_ipgeolocation2($ip, $geo_apikey) {

	$apiKey = $geo_apikey;

	// Note: the key travels in the query string, so don't log the full URL.
	$url = 'https://api.ipgeolocation.io/v3/ipgeo?' . http_build_query([
		'ip'     => $ip,
		'apiKey' => $apiKey,
		'fields' => 'location.country_name,location.city,time_zone.name',
	]);


// BotBanishWriteFile($BotBanishSettings['BOTBANISH_STATIC_LOGS_DIR'] . 'curlURL.log' . PHP_EOL, $url, true);

	$ch = curl_init($url);
	curl_setopt_array($ch, [
		CURLOPT_RETURNTRANSFER => true,
		CURLOPT_CONNECTTIMEOUT => 5,
		CURLOPT_TIMEOUT        => 10,
	]);

	$body = curl_exec($ch);

	if ($body === false) {
		$error = curl_error($ch);
		throw new RuntimeException("IP geolocation request failed: {$error}");
	}

	$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
	// PHP 8 frees the handle when $ch goes out of scope, so curl_close() is not needed.

	if ($status !== 200) {
		throw new RuntimeException("IP geolocation API returned HTTP {$status}");
	}

	$geo_data = json_decode($body, true);

//	BotBanishLogInfo('$geo_data: ', $geo_data, true, 'APIKEY');

	if (!is_array($geo_data)) {
		throw new RuntimeException('Could not parse the IP geolocation response.');
	}
/*
echo ($data['location']['country_name'] ?? 'Unknown') . PHP_EOL;
echo ($data['location']['city'] ?? 'Unknown') . PHP_EOL;
echo ($data['time_zone']['name'] ?? 'Unknown') . PHP_EOL;
*/	
	return $geo_data;
}

function BotBanishClientGetCountryData($geo_data) {

	$country = '';
	$country_code = '';
	$process = '';
	$flag = '';

	if (isset($geo_data['geoplugin_countryName'])) {

		$country_code = isset($geo_data['geoplugin_countryCode']) ? $geo_data['geoplugin_countryCode'] : '';
		$country = isset($geo_data['geoplugin_countryName']) ? $geo_data['geoplugin_countryName'] : '';
		$flag = isset($geo_data['country_flag']) ? substr($geo_data['country_flag'], strripos($geo_data['country_flag'], '/') + 1) : 'null';
		$process = 'geoplugin';

	} else {

		if (isset($geo_data['country_name'])) {

			$country_code = isset($geo_data['country_code2']) ? $geo_data['country_code2'] : '';
			$country = isset($geo_data['country_name']) ? $geo_data['country_name'] : '';
			$flag = 'null';
			$process = 'ipgeolocation';
		}
	}

	return array('country' => ucwords($country), 'country_code' => strtoupper($country_code), 'flag' => $flag, 'process' => $process);
}
?>