c143c4

c143c4
<html>
c143c4
<head>
c143c4
	<meta content="text/html; charset=windows-1252" http-equiv="Content-Type" />
c143c4
	<meta http-equiv="MSThemeCompatible" content="yes" />
c143c4
	<title>vBulletin Test Script</title>
c143c4
	<link rel="stylesheet" href="https://images.vbulletin.com/testscript/vb_test.css" />
c143c4
</head>
c143c4
<body>
c143c4
	
c143c4
		
c143c4
			cplogo
c143c4
			vBulletin Server Test Script
vBulletin Website
 
c143c4
		
c143c4
	
c143c4
	
c143c4
	
c143c4
c143c4
c143c4
error_reporting(E_ALL);
c143c4

c143c4
function iif($condition, $truevalue, $falsevalue = '')
c143c4
{
c143c4
	if ($condition)
c143c4
	{
c143c4
		return $truevalue;
c143c4
	}
c143c4
	else
c143c4
	{
c143c4
		return $falsevalue;
c143c4
	}
c143c4
}
c143c4

c143c4
class DB
c143c4
{
c143c4
	public static function fetch_db($host, $user, $password, $dbname)
c143c4
	{
c143c4
		global $db_connection_error;
c143c4
		$obj = @new mysqli($host, $user, $password, $dbname);
c143c4

c143c4
		//note that according to the documentation we should do this between
c143c4
		//the init call and real_connect (the constructor effectively does both
c143c4
		//of these at once).  However there is a bug in PHP where this doesn't work
c143c4
		//and real_connect will reset the option to the ini value.
c143c4
		//
c143c4
		//We can't set the ini value because PHP doesn't allow this value to be
c143c4
		//set in a script.  So this is the best we can do. Note that on all supported
c143c4
		//versions of PHP this ini value is set securely by default.
c143c4
		$obj->options(MYSQLI_OPT_LOCAL_INFILE, false);
c143c4

c143c4
		if (mysqli_connect_errno())
c143c4
		{
c143c4
			$db_connection_error = mysqli_connect_error();
c143c4
			return false;
c143c4
		}
c143c4
		return $obj;
c143c4
	}
c143c4
}
c143c4

c143c4
function test_ini_set($setting, $value)
c143c4
{
c143c4
	$result = @ini_set($setting, $value);
c143c4
	if ($result === false OR $result === null)
c143c4
	{
c143c4
		return false;
c143c4
	}
c143c4
	else
c143c4
	{
c143c4
		return $result;
c143c4
	}
c143c4
}
c143c4

c143c4
//initalise variables dont want any XSS in our test script :)
c143c4
$versions = array();
c143c4

c143c4
$required_versions = array(
c143c4
	'PHP' => '7.2.0',
c143c4
	'MySQL' => '5.5.8'
c143c4
);
c143c4

c143c4
if (!empty($_GET['help']))
c143c4
{
c143c4
	$tested = false;
c143c4

c143c4
	$type = strtolower($_GET['help']);
c143c4
	$help = array();
c143c4
	$help['php'] = 'Your PHP Version is too low to support vBulletin 5, you must at least upgrade to ' . $required_versions['PHP'];
c143c4
	$help['mysql'] = 'Your MySQL version is too low to support vBulletin 5, you must at least upgrade to ' . $required_versions['MySQL'];
c143c4
	$help['pcre'] = 'vBulletin requires PCRE to be enabled in PHP, ask your host to enable this in php.ini';
c143c4
	$help['open_basedir'] = 'You may experience problems with uploading files to vBulletin';
c143c4
	$help['curl'] = 'The cUrl extension is needed for many features that gather data from the internet';
c143c4
	$help['json'] = 'The JSON extension is required to support vBulletin 5';
c143c4
	$help['gzip'] = 'vBulletin uses GZIP to compress pages, though this is not essential for operation';
c143c4
	$help['mysql_perms'] = 'vBulletin requires that the mysql username has create, select, update, insert, ' .
c143c4
		'delete, alter and drop privledges, contact your host and ask them to adjust these privledges.';
c143c4
	$help['xml'] = 'XML is required as a major component of vBulletin for data storage of languages, settings and templates.';
c143c4
	$help['gd'] = 'GD functions are used to produce images, this includes features such as thumbnails and image verification on registration';
c143c4
	$help['iconv'] = 'Iconv is used to handle different character encodings.  Either the Multibyte String ' .
c143c4
		'or iconv modules are required to properly handle character encodings. Multibyte String is preferred.';
c143c4
	$help['mbstring'] = 'Multibyte String is used to handle different character encodings.  Either the Multibyte String ' .
c143c4
		'or iconv modules are required to properly handle character encodings. Multibyte String is preferred.';
c143c4
	$help['pcre.backtrack_limit'] = 'PHP 5.2.0 and above imposes a limit on PCRE code that we are unable to work-around on this server. ' .
c143c4
		'Ask your host to add the following to php.ini:
pcre.backtrack_limit = -1';
c143c4
	$help['pcre.utf8'] = 'PCRE with utf8 support is recommended';
c143c4
	$help['mysql.utf8mb4'] = 'The utf8mb4 character set allows extended (up to four byte) utf8 characters. Requires MySql 5.5.3 or greater.';
c143c4

c143c4
	echo '' . htmlspecialchars($type) . ' Help';
c143c4
	echo '' . $help["$type"] . '';
c143c4
}
c143c4
elseif (empty($_POST['server']) or empty($_POST['user']) or empty($_POST['db']))
c143c4
{
c143c4
	$tested = false;
c143c4

c143c4
	echo 'MySQL Information';
c143c4
	echo '<form method="post">';
c143c4
	echo '';
c143c4
	echo '	MySQL Server';
c143c4
	echo '	<input type="text" name="server" value="localhost" />';
c143c4
	echo '';
c143c4
	echo '';
c143c4
	echo '	MySQL Database';
c143c4
	echo '	<input type="text" name="db" />';
c143c4
	echo '';
c143c4
	echo '';
c143c4
	echo '	MySQL Username';
c143c4
	echo '	<input type="text" name="user" />';
c143c4
	echo '';
c143c4
	echo '';
c143c4
	echo '	MySQL Password';
c143c4
	echo '	<input type="password" name="pass" autocomplete="off" />';
c143c4
	echo '';
c143c4
	echo '';
c143c4
	echo '<input type="submit" value="Run Test" accesskey="s" />';
c143c4
	echo '';
c143c4
	echo '</form>';
c143c4
}
c143c4
else
c143c4
{
c143c4
	$tested = true;
c143c4

c143c4
	/**
c143c4
	 *	Define the tests
c143c4
	 */
c143c4

c143c4
	// modules
c143c4
	// modulename => 'represtative function' or array('function1', 'function2').  There should also be a "help"
c143c4
	// entry for every module
c143c4
	$required_modules = array(
c143c4
		'PCRE' => 'preg_replace',
c143c4
		'XML' => 'xml_set_element_handler',
c143c4
		'curl' => 'curl_init',
c143c4
		'json' => 'json_encode'
c143c4
	);
c143c4

c143c4
	$recommended_modules = array(
c143c4
		'GZIP' => array('crc32', 'gzcompress'),
c143c4
		'GD' => 'imagecreatetruecolor',
c143c4
		'iconv' => 'iconv',
c143c4
		'mbstring' => 'mb_convert_encoding'
c143c4
	);
c143c4

c143c4
	//'feature' => test query. Will check if query produces an error, but not
c143c4
	//what it returns
c143c4
	$mysql_perms = array(
c143c4
		'create' => 'CREATE TABLE vb3_test (test int(10) unsigned NOT NULL)',
c143c4
		'alter' => 'ALTER TABLE vb3_test CHANGE test test VARCHAR(254) NOT NULL',
c143c4
		'insert' => 'INSERT INTO vb3_test (test) VALUES (\'abcd\')',
c143c4
		'update' => 'UPDATE vb3_test SET test=123 WHERE test=\'abcd\'',
c143c4
		'select' => 'SELECT * FROM vb3_test WHERE test=123',
c143c4
		'delete' => 'DELETE FROM vb3_test WHERE test=123',
c143c4
		'drop' => 'DROP TABLE vb3_test'
c143c4
	);
c143c4

c143c4
	//either a query string (check for error) or an anonymous function that
c143c4
	//takes the mysqli object as a parameter.  Always fails when the db connection
c143c4
	//does not exist (function will not be called).
c143c4
	$mysql_recommended = array(
c143c4
		'mysql.utf8mb4' => function($db)
c143c4
		{
c143c4
				$result = $db->query("SHOW CHARACTER SET LIKE 'utf8mb4'");
c143c4
				return ($result->num_rows > 0);
c143c4
		},
c143c4
	);
c143c4

c143c4
	$required_tests = array();
c143c4

c143c4
	$recommended_tests = array(
c143c4
		'open_basedir' => function()
c143c4
		{
c143c4
			return (get_cfg_var('open_basedir') == '');
c143c4
		},
c143c4
		'pcre.backtrack_limit' => function()
c143c4
		{
c143c4
			return (!test_ini_set('pcre.backtrack_limit', -1) === false);
c143c4
		},
c143c4
		'pcre.utf8support' => function()
c143c4
		{
c143c4
			return (@preg_match('/\p{L}/u', 'a') == 1);
c143c4
		},
c143c4
	);
c143c4

c143c4

c143c4
	/**
c143c4
	 *	Run the tests
c143c4
	 */
c143c4

c143c4
	class vB_TestObserver
c143c4
	{
c143c4
		private $results = array();
c143c4
		private $failures = 0;
c143c4

c143c4
		public function getFailureCount()
c143c4
		{
c143c4
			return $this->failures;
c143c4
		}
c143c4

c143c4
		public function getResults()
c143c4
		{
c143c4
			return $this->results;
c143c4
		}
c143c4

c143c4
		public function logTest($name, $result)
c143c4
		{
c143c4
			$this->results[$name] = (bool) $result;
c143c4
			if(!$result)
c143c4
			{
c143c4
				$this->failures++;
c143c4
			}
c143c4
		}
c143c4
	}
c143c4

c143c4
	$requiredResults = new vB_TestObserver();
c143c4
	$recommendedResults = new vB_TestObserver();
c143c4
	$mysqlResults = new vB_TestObserver();
c143c4

c143c4
	//PHP
c143c4
	$versions['PHP'] = phpversion();
c143c4

c143c4
	$db = DB::fetch_db($_POST['server'], $_POST['user'], $_POST['pass'], $_POST['db']);
c143c4
	//MySQL
c143c4
	if(!$db)
c143c4
	{
c143c4
		//if we don't this this, then then it will be set by the version test.
c143c4
		$requiredResults->logTest('MySQL', false);
c143c4
	}
c143c4
	else
c143c4
	{
c143c4
		$vquery = $db->query('SELECT VERSION() AS version');
c143c4
		$mysql = $vquery->fetch_array();
c143c4
		$versions['MySQL'] = $mysql['version'];
c143c4
	}
c143c4

c143c4
	//check mysql permissions
c143c4
	foreach($mysql_perms AS $feature => $query)
c143c4
	{
c143c4
		$mysqlResults->logTest($feature, ($db AND $db->query($query)));
c143c4
	}
c143c4

c143c4
	foreach($mysql_recommended AS $feature => $query)
c143c4
	{
c143c4
		if(!$db)
c143c4
		{
c143c4
			$result = false;
c143c4
		}
c143c4
		else if (is_callable($query))
c143c4
		{
c143c4
			$result = $query($db);
c143c4
		}
c143c4
		else
c143c4
		{
c143c4
			$result = (bool) $db->query($query);
c143c4
		}
c143c4

c143c4
		$recommendedResults->logTest($feature, $result);
c143c4
	}
c143c4

c143c4

c143c4
	if ($db)
c143c4
	{
c143c4
		$db->close();
c143c4
	}
c143c4

c143c4
	//check versions -- if we don't set the version of something, we skip the check
c143c4
	//(presumably this means we couldn't look it up and there is another error that covers
c143c4
	//that such as the database.
c143c4
	foreach($versions as $feature => $version)
c143c4
	{
c143c4
		$requiredResults->logTest($feature, !version_compare($version, $required_versions[$feature], '<'));
c143c4
	}
c143c4

c143c4
	function check_modules($modules, $observer)
c143c4
	{
c143c4
		//check modules.
c143c4
		foreach ($modules AS $module => $function)
c143c4
		{
c143c4
			$test_function = $function;
c143c4
			if (!is_array($function))
c143c4
			{
c143c4
				$test_function = array($test_function);
c143c4
			}
c143c4

c143c4
			$pass = true;
c143c4
			foreach($test_function AS $check)
c143c4
			{
c143c4
				if (!function_exists($check))
c143c4
				{
c143c4
					$pass = false;
c143c4
				}
c143c4
			}
c143c4

c143c4
			$observer->logTest($module, $pass);
c143c4
		}
c143c4
	}
c143c4

c143c4
	check_modules($required_modules, $requiredResults);
c143c4
	check_modules($recommended_modules, $recommendedResults);
c143c4

c143c4
	foreach($required_tests AS $name => $function)
c143c4
	{
c143c4
		$requiredResults->logTest($name, $function());
c143c4
	}
c143c4

c143c4
	foreach($recommended_tests AS $name => $function)
c143c4
	{
c143c4
		$recommendedResults->logTest($name, $function());
c143c4
	}
c143c4

c143c4
	//translate to the previos vars for display -- should eventually rewrite that
c143c4
	//part as well.
c143c4
	$e_test = $requiredResults->getResults();
c143c4
	$mysql = $mysqlResults->getResults();
c143c4
	$test = $recommendedResults->getResults();
c143c4

c143c4
	//a bit of a hack to handle previous behavior.  This doesn't
c143c4
	//fit into our nice little formal setup.
c143c4
	//not sure why we set the version only if GD passes.
c143c4
	if ($test['GD'])
c143c4
	{
c143c4
		$versions['GD'] = '2.x';
c143c4
	}
c143c4

c143c4
	$e_error = $requiredResults->getFailureCount() + $mysqlResults->getFailureCount();
c143c4
	$error = $recommendedResults->getFailureCount();
c143c4

c143c4
	echo 'Essential vBulletin Requirements';
c143c4
	foreach ($e_test AS $type => $result) {
c143c4
		echo '';
c143c4
		echo '	' . $type . '';
c143c4
		echo '	' . (!isset($versions["$type"]) ? '' : $versions["$type"]) . '';
c143c4
		echo '	' . iif($result, 'Pass', 'Fail') . '';
c143c4
		echo '';
c143c4
	}
c143c4
	if ($db_connection_error)
c143c4
	{
c143c4
		echo '';
c143c4
		echo '	Database Connection Error:  ' . htmlspecialchars($db_connection_error) . '';
c143c4
		echo '';
c143c4
	}
c143c4
	echo 'MySQL Permission Requirements';
c143c4
	foreach ($mysql AS $type => $result) {
c143c4
		echo '';
c143c4
		echo '	' . $type . '';
c143c4
		echo '	' . iif($result, 'Pass', 'Fail') . '';
c143c4
		echo '';
c143c4
	}
c143c4

c143c4
	echo 'Recommended Settings (Optional)';
c143c4
	foreach ($test AS $type => $result) {
c143c4
		echo '';
c143c4
		echo '	' . $type . '';
c143c4
		echo '	' . (!isset($versions["$type"]) ? '' : $versions["$type"]) . '';
c143c4
		echo '	' . iif($result, 'Pass', 'Fail') . '';
c143c4
		echo '';
c143c4
	}
c143c4

c143c4
	echo 'Overall Result:' . iif($e_error, 'Fail', 'Pass') . '';
c143c4

c143c4
}
c143c4

c143c4
?>
c143c4

c143c4

c143c4
c143c4
	if ($tested AND is_array($test) AND is_array($e_test))
c143c4
	{
c143c4
		if ($e_error == 0 AND $error == 0)
c143c4
		{
c143c4
			echo '

vBulletin 5 should run on your system without any errors

';
c143c4
		}
c143c4
		elseif ($e_error == 0)
c143c4
		{
c143c4
			echo '

vBulletin 5 should run on your system though there may be reduced functionality, click the link(s) above for more information

';
c143c4
		}
c143c4
		else
c143c4
		{
c143c4
			echo '

vBulletin5 will not run on your system, please click the link(s) above for more information.

';
c143c4
		}
c143c4
	}
c143c4
/*======================================================================*\
c143c4
|| ####################################################################
c143c4
|| # CVS: $RCSfile$ - $Revision: 105451 $
c143c4
|| ####################################################################
c143c4
\*======================================================================*/
c143c4
?>
c143c4
</body>
c143c4
</html>