<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
// BotBanish 7.1.06
// Randem Systems: https://randemsystems.support
// BotBanish Pre-install Check
// Date: 03/28/2026
// Usage: Called directly
// Description: Checks to see if the needed modules and function are present before installation begins
//
//	Array structure
//		'extensions' - Any PHP module that may need to be present
//		'functions' - Array of any PHP fuctions that may need to be present
//		'level' 	- Type of checking to comply with
//		'module'	- Array of Apache module that need to be accessible
//
// Levels:
// 0 - One item must exists
// 1 - Every item must exist
// 2 - Not needed but may be used if existing
///////////////////////////////////////////////////////////////////////////////////////////////////////

	$php_version_max = '8.3.30';

	if (defined('BOTBANISH')) {

		$filename = BOTBANISH_DIR . 'Include/BotBanish_Version.php';

		if (file_exists($filename))
			include_once $filename;
	}

	$counts_array = array('good' => 0, 'bad' => 0);
	
	// Will not work on PHP-FPM!!! But we get all the information that we can

	$apache_modules = array();

	if (function_exists('apache_get_modules'))
		$apache_modules[] = apache_get_modules();

	$items = BotBanish_PHPInfo();
	$apache_modules[] = isset($items['loaded modules']) ? explode(' ', $items['loaded modules']) : array();
	$server_api = isset($items['server api']) ? $items['server api'] : 'Unknown';

	BotBanishCheckPreInstall($php_version_max, $apache_modules, $server_api);

function BotBanishCheckPreInstall($php_version_max, $apache_modules, $server_api) {

	global $counts_array;
	
	echo '
	<!DOCTYPE html>
	<html>
	<head>
	<title>BotBanish PreiInstall Checker</title>
	</head>';

	echo 'BotBanish Pre-Install Checker<br><br>';

	echo '
	<form name="theForm" id="theForm" action="" method="post" enctype="multipart/form-data">' . PHP_EOL;

	$phpversion = phpversion();
	$error = '';
	$maxphpversion = '';
	$curphpversion = '';

	$arr = explode('.', $phpversion);

	foreach($arr as $num)
		$curphpversion .= str_pad($num, 3, 0, STR_PAD_LEFT);

	$arr = explode('.', $php_version_max);

	foreach($arr as $num)
		$maxphpversion .= str_pad($num, 3, 0, STR_PAD_LEFT);

	if (intval($curphpversion) > intval($maxphpversion))
		$error = '<div style="background-color:Red; color:White";><b>WARNING: Not tested on PHP ' . $phpversion . '. Only tested up to PHP ' . $php_version_max . '</b></div>' . PHP_EOL;

	// Check for all modules and functions that we need to operate

	$error_txt = '';

	//=========================================================================================
	// These are the module, function and extensions dependency definitions
	//=========================================================================================

	$exists = array(
		'one' => array('extensions' => array('curl'),
				'functions' => array(
//									array('routine' => 'fetch_web_data', 'dependancy' => function_exists('fetch_web_data')),
									array('routine' => 'file_get_contents', 'dependancy' => function_exists('file_get_contents')),
								),
			),

		'ok' => array('extensions' => array('ftp'),
				'functions' => array(
									array('routine' => 'ftp_connect', 'dependancy' => function_exists('ftp_connect')),
								),
			),

		'all' => array('extensions' => array('mbstring', 'mysqli', 'fileinfo'),
				'functions' => array(
									array('routine' => 'fopen', 'dependancy' => true),
									array('routine' => 'mb_convert_encoding', 'dependancy' => true),
								),
//				'modules' => array('mod_env'), 'level' => 1),
			),
	);

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

	$counts = array();
		
	foreach ($exists as $level => $sections) {
		
		$error_txt .= '<table width=60%>
						<tr>
							<td width=20%><b>Status</b></td>
							<td width=20%><b>Name</b></td>
							<td width=20%><b>Type</b></td>
						</tr>';

		$array_func = array();
		$array_ext = array();
		$array_mod = array();
		$counts[$level] = array('good' => 0, 'bad' => 0);
			
		foreach ($sections as $key => $section) {
			
			$count = BotBanishCheckCounts($key, $section, $array_ext, $array_func, $array_mod);
			$counts[$level]['good'] += $count[$key]['good'];
			$counts[$level]['bad'] += $count[$key]['bad'];
		}

		$txt = '<div>';
		$txt .= !empty($array_ext) ? implode(PHP_EOL, $array_ext) : '';
		$txt .= !empty($array_func) ? implode(PHP_EOL, $array_func) : '';
		$txt .= !empty($array_func) ? implode(PHP_EOL, $array_mod) : '';
		$txt .= '</div></table>' . PHP_EOL;
		$txt = str_ireplace('<br>', '', $txt);

		$found = false;

		switch ($level) {

			case 'one':

				if ($counts[$level]['good'] === 0)

					$error_txt .= '<div style="background-color:Red; color:White";><b>One extensions or functions must be accessible - BAD (None Accessible)</b></color></div>' . PHP_EOL;
				else 
					$error_txt .= '<div style="background-color:Green; color:White";><b>At least one extension or function must be accessible - GOOD</b></color></div>' . PHP_EOL;

				break;

			case 'all':

				if ($counts[$level]['bad'] > 0)
					
					$error_txt .= '<div style="background-color:Red; color:White;"><b>Every extension, function and module must be accessible - BAD (All must be accessible) ' . $php . '</b></div>' . PHP_EOL;
				else 
					$error_txt .= '<div style="background-color:Green; color:White;"><b>Every extension, function and module is accessible - GOOD</b></div>' . PHP_EOL;

				break;

			case 'ok':

				$error_txt .= '<div style="background-color:Yellow; color:Black;"><b>Extensions, functions and modules are not needed but may be used if accessible - OK</b></div>' . PHP_EOL;

				break;
		}

		$error_txt .= $txt . '<br>';
	}

	echo $error;
	echo '<div>PHP Version: ' . $phpversion . '</div><br>';
	echo '<div>Server API: ' . $server_api . '</div><br>' . PHP_EOL;
	echo 	'<table <table width=60%>'
			. PHP_EOL . $error_txt .
		'</table>' . PHP_EOL;

	echo '
		</form>
		</body>
	</html>';
}

function BotBanishCheckCounts($key, $section, &$array_ext, &$array_func, &$array_mod) {
	
	switch ($key) {
		
		case 'extensions':
		
			$count[$key] = BotBanishExtensions($section, $array_ext);
			break;
		
		case 'functions':
		
			$count[$key] = BotBanishFunctions($section, $array_func);
			break;
		
		case 'modules':
		
			$count[$key] = BotBanishModules($section, $array_mod);
			break;				
	}
	
	return $count;
}

function BotBanishGetCounts($array_ext, $array_func, $array_mod) {
	
	$counts = $array_ext;
	$counts['good'] =+ ($array_func['good'] + $array_mod['good']);
	return $counts;
}

function BotBanishExtensions($section, &$array_ext) {
				
	// Find all extensions and function that are in our lists that may need to be accessible

	$good = 0;
	$bad = 0;

	foreach ($section as $extension) {

		if (BotBanishIsExtensionLoaded($extension)) {

			$array_ext[] = '
							<tr>' .
								BotBanishGreenText('Accessible:') . BotBanishGreenText($extension) . BotBanishGreenText('PHP Extension') .
							'</tr>' . PHP_EOL;
			$good++;

		} else {

			$array_ext[] = '
							<tr>' .
								BotBanishRedText( 'Not Accessible:') . BotBanishRedText($extension) . BotBanishRedText('PHP Extension') .
							'</tr>' . PHP_EOL;
			$bad++;
		}
	}
	
	return array('good' => $good, 'bad' => $bad);
}

function BotBanishFunctions($section, &$array_func) {
	
	$good = 0;
	$bad = 0;

	foreach ($section as $function_item) {

		$flag1 = 0;
		$flag2 = 0;
		$function = '';

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

			switch ($key) {

				case 'routine':

					$function = $value;
					$flag1 = BotBanishIsFunctionLoaded($value);
					break;

				case 'dependancy':

					$flag2 = $value;
					break;
			}

		}
		
		if ($flag1 && $flag2) {

			$array_func[] = '
			<tr>' .
				 BotBanishGreenText('Accessible:') . BotBanishGreenText($function) . BotBanishGreenText('PHP Function') .
			'</tr>' . PHP_EOL;
			
			$good++;

		} else {

			$array_func[] = '
			<tr>' .
				 BotBanishRedText('Not Accessible:') . BotBanishRedText($function) . BotBanishRedText('PHP Function') .
			'</tr>' . PHP_EOL;

			$bad++;
		}
	}
	
	return array('good' => $good, 'bad' => $bad);
}

function BotBanishModules($section, &$array_mod) {

	$good = 0;
	$bad = 0;

	global $apache_modules;
	$i = 0;

	foreach ($apache_modules as $apache_module)
		$i .+ count($apache_module) . '</br>';

	$php = $i == 0 ? '</br><b>* * * Apache modules cannot be detected if PHP is running as a module of Apache (PHP-FPM). * * *</b>' : '';

	foreach ($section as $module) {

		if (BotBanishIsModuleEnabled($module, $apache_modules)) {

			$array_mod[] = '
							<tr>' .
								BotBanishGreenText('Enabled:') . BotBanishGreenText($module) . BotBanishGreenText('Apache Module') .
							'</tr>' . PHP_EOL;
			$good++;

		} else {

			$array_mod[] = '
							<tr>' .
								BotBanishRedText('Not Enabled:') . BotBanishRedText($module) . BotBanishRedText('Apache Module') .
							'</tr>' . PHP_EOL;
			$bad++;
		}
	}

	return array('good' => $good, 'bad' => $bad);
}
	
function BotBanishRedText($text) {

	return '<td style="color:Tomato; font-weight:bold">' . $text . '</td>';
}

function BotBanishGreenText($text) {

	return '<td style="color:MediumSeaGreen; font-weight:bold">' . $text . '</td>';
}

function BotBanishIsFunctionLoaded($function_name) {

	if (empty($function_name))
		return false;

	return function_exists($function_name);
}

function BotBanishIsExtensionLoaded($extension_name) {

	if (empty($extension_name))
		return false;

	return extension_loaded($extension_name);
}

function BotBanishIsModuleEnabled($module, $apache_modules) {

	if (empty($apache_modules))
		return false;

	$flag = false;

	foreach($apache_modules as $apache_module) {

		$flag = array_search($module, $apache_module);
		if ($flag !== false) break;
	}

	return $flag;
}

function Botbanish_PHPInfo() {

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

	$lines = explode("\n", $page);
	$items = array();

	foreach ($lines as $line) {

		if (stripos($line, '<tr><td class="e">') !== false) {

			$line = str_ireplace('</td><td class="v">', '</td><td class="v">=>', $line);
			$line = strip_tags($line);
			$tmp_array = explode('=>', $line);
			$name = isset($tmp_array[0]) ? strtolower(trim($tmp_array[0])) : '';
			$text = isset($tmp_array[1]) ? trim($tmp_array[1]) : '';

			if (!empty($name) && !empty($text))
				$items[$name] = $text;
		}
	}

	return $items;
}
?>