<?php 
###############################################################################
# tests.php
# Watch My Domains SED v3
# (c) Softnik Technologies. All rights reserved.
###############################################################################

function do_db_checks(&$results)
{
	$status = array();
	global $db_config_dbtype;
	
	# PHP PDO
	$status['name'] = "PHP:PDO";
	$status['info']   = "<p>The application requires PHP:PDO with a suitable driver.</p>";
	if (!defined('PDO::ATTR_DRIVER_NAME')) 
	{
		$status['status'] = "notok";
		$status['value'] .= "<p>PHP:PDO is not available. Please install / enable it.</p>";
	}
	else if (defined('PDO::ATTR_DRIVER_NAME')) 
	{
		$status['value'] = "<p>PHP:PDO is available.</p>";
		$drivers = PDO::getAvailableDrivers();
		if(in_array($db_config_dbtype, $drivers))
			$status['status'] = "ok";
		else
		{
			$status['status'] = "notok";
			$status['value'] = "<p>PHP:PDO is available, but the driver for the configured dbtype ($db_config_dbtype) is missing.</p>";
		}
		$status['value'] .= "<p>Installed drivers: ";
		foreach($drivers as $drv)
		{
			if($drv == $db_config_dbtype)
				$status['value'] .= "<b>$drv</b>, ";
			else
				$status['value'] .= $drv . ", ";
		}
		$status['value'] = trim($status['value'], " ,");
		$status['value'] .= ".</p>";
	}
	$results[] = $status;
	
	
	unset($status);
	$status['name'] = "Database Check";
	$status['info'] = "<p>Connect and select database.</p>";
	
	$db_connected = false;
	$pdo = init_db();
	if($pdo === false)
	{
		$status['value'] = "<p>" . wmDomainDatabase::$last_init_error . "</p>";
		$status['status'] = "notok";
	}
	else
	{
		global $db_config_username, $db_config_host;
		$status['value'] = "<p>MySQL server version is " . $pdo->db_connect_handle->getAttribute(PDO::ATTR_SERVER_VERSION) . "</p>";
		$status['value'] .= "<p>User '$db_config_username'@'$db_config_host' connected to MySQL.</p>";
		$status['status'] = "ok";
		$status['name'] .= " (MySQL v" . $pdo->db_connect_handle->getAttribute(PDO::ATTR_SERVER_VERSION) . ")";
		$db_connected = true;
	}
	$results[] = $status;
	
	unset($status);
	if($db_connected)
	{
		$status['name'] = "Time Zone Check";
		$status['info'] = "<p>The timezone settings on the server should be consistent</p>";
		$ct = $pdo->getCurrentTime();
		if($ct !== false)
		{
			$gmdiff = strtotime($ct) - strtotime(gmdate("Y-m-d H:i:s"));
			$mysqltimezone = timezone_name_from_abbr("", $gmdiff, false);
			$phptimezone = date_default_timezone_get();
			$status['value'] = "<p>Current PHP Time: " . date("Y-m-d H:i:s") .  ", Timezone: <b>$phptimezone</b>" . "</p>";
			$status['value'] .= "<p>Current MySQL Time: $ct, Timezone: <b>$mysqltimezone</b></p>";
			$tdiff = strtotime(date("Y-m-d H:i:s")) - strtotime($ct);
			if(abs($tdiff) > 1)
			{
				$status['status'] = "alert";
				$status['value'] .= "<p>There is a timezone difference between the MySQL server and PHP. This can cause problems with the connection interval calculations.</p>";
			}
			else
				$status['status'] = "info";
			$status['value'] .= "<p>Please verify that the PHP time is same when run from command line. Windows/Debian/Ubuntu servers may use a different php.ini file for CLI and so may have a different timezone setting in CLI. This is unlikely to actually happen, but is mentioned here because this problem is very difficult to debug if it happens. You can run verify.php from the console (php /path/to/verify.php) and check that the time shown there matches with this.</p>";
		}
		else
		{
			$status['status'] = "notok";
			$status['value'] = "<p>" . $pdo->getLastError() . "</p>";
		}
		$results[] = $status;
	}
	
	unset($status);
}

###############################################################################

function do_wmdsed_tests(&$results)
{
	$status = array();
	
	# PHP Version
	$status['name'] = "PHP Version";
	$status['info']  = "<p>Watch My Domains SED Standard / Demo / Professional Editions require PHP 5.3.x to 5.6.x or PHP 7.0-7.1</p>";
	$phpver = phpversion();
	if(substr($phpver, 0, 3) == "5.3" || substr($phpver, 0, 3) == "5.4" || substr($phpver, 0, 3) == "5.5" || substr($phpver, 0, 3) == "5.6" || substr($phpver, 0, 3) == "5.7" || substr($phpver, 0, 2) == "7.")
		$status['status'] = 'ok';
	else 
		$status['status'] = "alert";
	$status['value'] = "<p>PHP Version is $phpver</p>";
	$status['name'] .= " (v" . "$phpver)";
	$results[] = $status;
	unset($status);
	
	# PHP Error Reporting
	$errorreporting = error_reporting();
	$rooturl = (!empty($_SERVER['HTTPS']) ? 'https' : 'http') . '://';
	if(isset($_SERVER['HTTP_HOST']))
		$rooturl .= $_SERVER['HTTP_HOST'];
	$rooturl .= get_install_url_path() . "verify.php?debug";
	$status['name'] = "PHP Error Reporting";
	if($errorreporting & E_NOTICE)
	{
		$status['info'] = "<p>Running in debug mode. PHP will report all errors and warnings.</p>";
		$status['status'] = 'info';
	}
	else if(isset($_REQUEST['debug']))
	{
		$status['info']   = "<p>Running in <code>debug mode</code>, but this server's php configuration doesn't allow full error reporting.</p>";
		$status['status'] = 'ok';
	}
	else
	{
		$status['info']   = "<p>The following errors and warnings will be reported. You can add <code>?debug</code> to the URL to make the application report all PHP errors and warnings. For example, <code>$rooturl</code></p>";
		$status['status'] = 'ok';
	}
	$status['value'] = error_level_tostring($errorreporting, ", ");
	$results[] = $status;
	unset($status);
	
	# PHP Curl
	$status['name'] = "PHP Curl";
	$status['info']   = "<p>PHP Curl is required if you want to use third-party add-ons (MOZ, EstiBot) and domain homepage checks.</p>";
	if(!function_exists('curl_version'))
	{
		$status['status'] = 'alert';
		$status['value'] = "<p>PHP-Curl is not available.</p>";
	}
	else 
	{
		$status['status'] = 'ok';
		$status['value'] = "<p>PHP-Curl is available.</p>";
	}
	$results[] = $status;
	unset($status);
	
	// PHP Ini
	$status['status'] = "info";
	$status['name'] = "PHP Ini Path";
	$status['info'] = "<p>PHP was loaded from the following Ini File.</p>";
	$status['value'] = php_ini_loaded_file();
	$results[] = $status;
	unset($status);
	
	if(isset($_REQUEST['debug']))
	{
		// PHP Info
		$status['status'] = "info";
		$status['name'] = "PHP Info";
		$status['info'] = "<p>Output from phpinfo()</p>";
		$status['value'] = pinfo();
		$results[] = $status;
		unset($status);
	}
	
	# PHP Sessions
	if(function_exists('session_status'))
	{
		$status['name'] = "PHP Sessions";
		$status['info'] = "<p>PHP session support is required for user authentication.</p>";

		if(session_status() == PHP_SESSION_ACTIVE)
		{
			$status['value'] = "<p>PHP Sessions are active.</p>";
			$status['status'] = 'ok';
		}
		else if(session_status() == PHP_SESSION_DISABLED)
		{
			$status['value'] = "<p>PHP Sessions are disabled.</p>";
			$status['status'] = 'notok';
		}
		else if(session_status() == PHP_SESSION_NONE)
		{
			$status['value'] =  "<p>PHP Sessions are enabled but none exists.</p>";
			$status['status'] = 'alert';
		}
		$results[] = $status;
		unset($status);
	}
	
	# ionCube
	$isWindows = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? true : false;
	$status['name'] = "ionCube Loader";
	$status['info'] = "<p>ionCube Loader v4.6 or greater (v10 or greater if using PHP 7.1 and above) is required for demo, basic and standard version installations.</p>";
	if ( extension_loaded('ionCube Loader') ) 
	{
		$ion_status = ioncube_loader_version_array();
		$ion_version = $ion_status['version'];
		if(($ion_status['major'] == 4 && $ion_status['minor'] >= 6) || ($ion_status['major'] >= 5))
		{
			$status['value']  = "<p>ionCube Loader v$ion_version installed.</p>"; 
			$status['status'] = 'ok';
		}
		else
		{
			$status['value']  = "<p>ionCube Loader v$ion_version installed.</p>";
			$status['status'] = 'alert';
		}
		$status['name'] .= " (" . "v$ion_version" . ")";
		global $ioncubeVersionSourceInUse;
		if(isset($_REQUEST['debug']))
		{
			if($ioncubeVersionSourceInUse != "")
				$status['value'] .= "<p>$ioncubeVersionSourceInUse</p>";
		}
	}
	else
	{
		$status['status'] = 'notok';
		$status['value']  = "<p>ionCube Loader is not installed.</p>";
	}
	if(isProConfigFile())
	{
		$status['status'] = "info";
		$status['info']  .= "<p>You are using the Professional Edition, so ionCube Loader is not required.</p>";
	}
	else
	{
		if($status['status'] == 'ok')
			$status['status'] = 'info';
		$status['value'] .= "<p><b>Important:</b> Windows/Debian/Ubuntu servers may use a different php.ini file for CLI and so ionCube Loader may need to be configured in two places; first for Apache/Web Server and then for PHP command line. For example, WAMP server has the php.ini for CLI at wamp/bin/php/phpx.x.x/ folder and Debian has it at /etc/php5/cli/php.ini</p>";
	}
	$results[] = $status;
	unset($status);
	
	
	# Whois
	$status['name'] = "Whois Lookup";
	$status['info'] = "<p>Port 43 Whois</p>";
	$whois_stat = test_whois($whoisdata);
	if($whois_stat !== false)
	{
		$status['value'] = "<p>Able to make port 43 whois connections</p>";
		$status['status'] = "ok";
		if(!is_cli())
			$status['value'] .= str_replace("\n", "<br>", $whoisdata);
	}
	else
	{
		$status['status'] = "notok";
		$status['value'] = "<p>Unable to make a port 43 whois connection to whois.crsnic.net!</p>";
		$status['value'] .= "<br><br>" . $whoisdata;
	}
	$results[] = $status;
	unset($status);
}

###############################################################################

function get_folder_status(&$results)
{
	# Folders and Paths
	
	$cronname = "Cron";
	$isWindows = false;
	if(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
	{
		$isWindows = true;
		$cronname = "Task Scheduler";
	}

	$status = array();
	$status['name'] = "Folder and Path (" . PHP_OS . ")";
	$status['info'] = "";
	$status['value'] = "<p>The application is installed at</p><pre>" . get_install_folder_path() . "</pre>";
	$rooturl = get_root_url();
	$status['value'] .= "<p>The web URL is</p><pre>" . $rooturl . "</pre>";
	if(!$isWindows)
		$cronentry = "* * * * * php " . get_install_folder_path() . "runq.php auto=90 >/dev/null 2>&1";
	else
		$cronentry = "path/to/php.exe " . get_install_folder_path() . "runq.php auto=90";
	$status['value'] .= "<p>You can use the following $cronname action for queue processing</p><pre>" . $cronentry . "</pre>";
	if($isWindows)
		$status['value'] .= "<p>Remember to set the correct path to the command line PHP binary. Please see the documentation or README.txt for details on using the Task Scheduler to process the lookup queue.</p>";
	$status['status'] = 'ok';
	$results[] = $status;
}

###############################################################################

function test_whois(&$data)
{
	$data = "";
	$whoisserver = "whois.crsnic.net";
	$fp = @fsockopen($whoisserver, 43, $errno, $errstr, 10);
	if( $fp )
	{
		@fputs($fp, "domain example.com\r\n");
		@socket_set_timeout($fp, $m_sockettimeout);
		while( !@feof($fp) )
			$data .= @fread($fp, 4096);
		@fclose($fp);
		return true;
	}
	else
	{
		$data = "Error - unable to connect to $whoisserver.<br>$errstr ($errno). ";
		$data .= "Please see the <a class=\"btn btn-xs btn-primary\" href=\"https://domainpunch.com/sed/guide/troubleshooting.php\">trouble shooting guide</a>.";
	}
	return false;
}

###############################################################################

function formatTestResults($results)
{
	if(is_cli())
	{
		$msg = "Verifying Installation\n\n";
		if(is_array($results))
		{
			foreach($results as $status)
			{
				if($status['status'] == "notok")
					$status['status'] = "Not OK";
				else
					$status['status'] = ucwords($status['status']);
				$status['info'] = str_replace("</pre>", "\n", $status['info']);
				$status['value'] = str_replace("</pre>", "\n", $status['value']);
				$status['info'] = trim(str_replace("</p>", "\n", $status['info']));
				$status['value'] = trim(str_replace("</p>", "\n", $status['value']));
				$msg .= $status['name'] . " - ";
				$msg .= $status['status'] . "\n";
				$msg .=  $status['info'] . "\n";
				$msg .=  $status['value'] . "\n";
				$msg .=  "\n----\n\n";
			}
		}
	}
	else
	{
		$msg = "<h3 class=\"heading\">Verifying Installation</h3>\n<hr>\n";
		$msg .= "<p>You can click on any of the panels below to see additional infomation.</p>";
		if(is_array($results))
		{
			$msg .= "<div id=\"testresults\">\n";
			foreach($results as $status)
			{
				$icon = "lib/css/images/32/" . $status['status'] . ".png";
				if($status['status'] == "notok")
					$style = " class=\"ui-state-highlight\"";
				else
					$style = "";
				$msg .=  "<h3$style><img src=\"$icon\" width=\"24\" height=\"24\" alt=\"". $status['status'] . "\">&nbsp;&nbsp;" . $status['name'] . "</h3>\n";
				$msg .=  "<div><div class=\"tresultbox\">\n";
				$msg .=  $status['info'];
				$msg .=  $status['value'];
				$msg .=  "</div></div>\n";
			}
			$msg .=  "</div>\n";
		}
	}
	return $msg;
}

###############################################################################

function error_level_tostring($intval, $separator)
{
    $errorlevels = array(
        E_ALL => 'E_ALL',
        E_USER_DEPRECATED => 'E_USER_DEPRECATED',
        E_DEPRECATED => 'E_DEPRECATED',
        E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',
        E_STRICT => 'E_STRICT',
        E_USER_NOTICE => 'E_USER_NOTICE',
        E_USER_WARNING => 'E_USER_WARNING',
        E_USER_ERROR => 'E_USER_ERROR',
        E_COMPILE_WARNING => 'E_COMPILE_WARNING',
        E_COMPILE_ERROR => 'E_COMPILE_ERROR',
        E_CORE_WARNING => 'E_CORE_WARNING',
        E_CORE_ERROR => 'E_CORE_ERROR',
        E_NOTICE => 'E_NOTICE',
        E_PARSE => 'E_PARSE',
        E_WARNING => 'E_WARNING',
        E_ERROR => 'E_ERROR');
    $result = '';
    foreach($errorlevels as $number => $name)
    {
        if (($intval & $number) == $number) {
            $result .= ($result != '' ? $separator : '').$name; }
    }
    return $result;
}

###############################################################################

function pinfo() 
{
    ob_start();
    phpinfo();
    $data = ob_get_contents();
    ob_clean();
    return $data;
}

###############################################################################
?>
