= 4096 || stripos($outputBuffering, 'On') !== false) ? 'On' : 'Off'; $directiveValues['max_execution_time'] = ini_get('max_execution_time'); $directiveValues['memory_limit'] = memoryLimitInBytes() < 536870912 ? ini_get('memory_limit') : ini_get('memory_limit'); $shortOpenTag = ini_get('short_open_tag'); $directiveValues['short_open_tag'] = $shortOpenTag == '1' || stripos($shortOpenTag, 'On') !== false ? 'On' : 'Off'; $directiveValues['max_input_vars'] = ini_get('max_input_vars'); return $directiveValues; } /** * Converts the PHP memory limit setting to bytes. * * This function retrieves the memory limit from the PHP configuration and converts * it to an integer value in bytes. It handles suffixes like 'M' (megabytes), * 'K' (kilobytes), and 'G' (gigabytes). * * @return int The memory limit in bytes as an integer. Returns the original value if no suffix is present. */ function memoryLimitInBytes() { $s = ini_get('memory_limit'); switch (substr ($s, -1)) { case 'M': case 'm': return (int)$s * 1048576; case 'K': case 'k': return (int)$s * 1024; case 'G': case 'g': return (int)$s * 1073741824; default: return $s; } } /** * Converts the PHP memory limit setting to bytes. * * @return int The memory limit in bytes. */ function getRecommendedDirectives() { $recommendedDirectives = array ( 'file_uploads' => 'On', 'output_buffering' => 'On', 'max_execution_time' => '3600', 'memory_limit' => '512M', 'short_open_tag' => 'Off', 'max_input_vars' => 8192 ); if(version_compare(PHP_VERSION, '5.5.0') >= 0){ $recommendedDirectives['error_reporting'] = 'E_WARNING & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT'; } else if(version_compare(PHP_VERSION, '5.3.0') >= 0) { $recommendedDirectives['error_reporting'] = 'E_WARNING & ~E_NOTICE & ~E_DEPRECATED'; } return $recommendedDirectives; } // ****** Required PHP Extensions *************************************************************************************************** /** * Checks the system requirements for vtigerCRM installation. * * This function collects and verifies the system's configuration parameters, * ensuring compatibility with vtigerCRM's installation prerequisites. * It checks PHP version, web server type and version, operating system, * SSL configuration, and several PHP extensions. * * @return array An associative array where each key is a requirement, and its value is an array * containing the system's current value, the recommended value, and whether the * requirement is met (true/false). */ function getSystemPreInstallParameters() { $gdInfoAlternate = 'function gd_info() { $array = Array( "GD Version" => "", "FreeType Support" => 0, "FreeType Support" => 0, "FreeType Linkage" => "", "T1Lib Support" => 0, "GIF Read Support" => 0, "GIF Create Support" => 0, "JPG Support" => 0, "PNG Support" => 0, "WBMP Support" => 0, "XBM Support" => 0 ); $gif_support = 0; ob_start(); eval("phpinfo();"); $info = ob_get_contents(); ob_end_clean(); foreach(explode("\n", $info) as $line) { if(strpos($line, "GD Version")!==false) $array["GD Version"] = trim(str_replace("GD Version", "", strip_tags($line))); if(strpos($line, "FreeType Support")!==false) $array["FreeType Support"] = trim(str_replace("FreeType Support", "", strip_tags($line))); if(strpos($line, "FreeType Linkage")!==false) $array["FreeType Linkage"] = trim(str_replace("FreeType Linkage", "", strip_tags($line))); if(strpos($line, "T1Lib Support")!==false) $array["T1Lib Support"] = trim(str_replace("T1Lib Support", "", strip_tags($line))); if(strpos($line, "GIF Read Support")!==false) $array["GIF Read Support"] = trim(str_replace("GIF Read Support", "", strip_tags($line))); if(strpos($line, "GIF Create Support")!==false) $array["GIF Create Support"] = trim(str_replace("GIF Create Support", "", strip_tags($line))); if(strpos($line, "GIF Support")!==false) $gif_support = trim(str_replace("GIF Support", "", strip_tags($line))); if(strpos($line, "JPG Support")!==false) $array["JPG Support"] = trim(str_replace("JPG Support", "", strip_tags($line))); if(strpos($line, "PNG Support")!==false) $array["PNG Support"] = trim(str_replace("PNG Support", "", strip_tags($line))); if(strpos($line, "WBMP Support")!==false) $array["WBMP Support"] = trim(str_replace("WBMP Support", "", strip_tags($line))); if(strpos($line, "XBM Support")!==false) $array["XBM Support"] = trim(str_replace("XBM Support", "", strip_tags($line))); } if($gif_support==="enabled") { $array["GIF Read Support"] = 1; $array["GIF Create Support"] = 1; } if($array["FreeType Support"]==="enabled"){ $array["FreeType Support"] = 1; } if($array["T1Lib Support"]==="enabled") $array["T1Lib Support"] = 1; if($array["GIF Read Support"]==="enabled"){ $array["GIF Read Support"] = 1; } if($array["GIF Create Support"]==="enabled") $array["GIF Create Support"] = 1; if($array["JPG Support"]==="enabled") $array["JPG Support"] = 1; if($array["PNG Support"]==="enabled") $array["PNG Support"] = 1; if($array["WBMP Support"]==="enabled") $array["WBMP Support"] = 1; if($array["XBM Support"]==="enabled") $array["XBM Support"] = 1; return $array; }'; $phpVersion = '7.4.0'; $preInstallConfig = array(); // Name => array( System Value, Recommended value, supported or not(true/false) ); $preInstallConfig['PHP Version'] = array(phpversion(), $phpVersion, (version_compare(phpversion(), $phpVersion, '>='))); if(!empty(shell_exec('apache2 -v'))) { $preInstallConfig['Apache-Version'] = array(getCleanedVersion(shell_exec('apache2 -v')), '2.0.40',(version_compare(getCleanedVersion(shell_exec('apache2 -v')), '2.0.40', '>='))); } elseif(!empty(shell_exec('httpd -v'))) { $preInstallConfig['Apache-Version'] = array(getCleanedVersion(shell_exec('httpd -v')), '2.0.40',(version_compare(getCleanedVersion(shell_exec('httpd -v')), '2.0.40', '>='))); } elseif(!empty(shell_exec('nginx -v 2>&1'))) { $preInstallConfig['Nginx-Version'] = array(getCleanedVersion(shell_exec('nginx -v 2>&1')), '1.13',(version_compare(getCleanedVersion(shell_exec('nginx -v 2>&1')), '1.13', '>='))); } $preInstallConfig['OS'] = array(php_uname(), array("Debian", "Centos", "Ubuntu","Fedora Core"),isSupportedOS(php_uname())); $preInstallConfig['SSL'] = array($_SERVER['HTTPS'], "On",isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? true : false); if($preInstallConfig['SSL'][2] === false) { if (isset($_SERVER['HTTP_X_FORWARDED_HOST']) && ($_SERVER['HTTP_X_FORWARDED_HOST'] !='')) { $preInstallConfig['SSL'][3] = '(might be ok, since site is behind proxy for host: '.$_SERVER['HTTP_X_FORWARDED_HOST'].")"; } } $preInstallConfig['Imap Support'] = array(function_exists('imap_open'), true, (function_exists('imap_open') == true)); $preInstallConfig['Zlib Support'] = array(function_exists('gzinflate'), true, (function_exists('gzinflate') == true)); if ($preInstallConfig['PHP Version'] >= $phpVersion) { $preInstallConfig['mysqli support'] = array(extension_loaded('mysqli'), true, extension_loaded('mysqli')); } $preInstallConfig['openssl support'] = array(extension_loaded('openssl'), true, extension_loaded('openssl')); $preInstallConfig['cURL support'] = array(extension_loaded('curl'), true, extension_loaded('curl')); $preInstallConfig['xml'] = array(extension_loaded('xml'), true, extension_loaded('xml')); $preInstallConfig['mbstring'] = array(extension_loaded('mbstring'), true, extension_loaded('mbstring')); $preInstallConfig['opcache'] = array((is_array(opcache_get_status()) ? true : false), true, (is_array(opcache_get_status()) ? true : false)); $preInstallConfig['ctype'] = array(extension_loaded('ctype'), true, extension_loaded('ctype')); $preInstallConfig['simplexml'] = array(extension_loaded('simplexml'), true, extension_loaded('simplexml')); $preInstallConfig['zip'] = array(extension_loaded('zip'), true, extension_loaded('zip')); $preInstallConfig['session'] = array(extension_loaded('session'), true, extension_loaded('session')); $preInstallConfig['bcmath'] = array(extension_loaded('bcmath'), true, extension_loaded('bcmath')); $gnInstalled = false; if(!function_exists('gd_info')) { eval($gdInfoAlternate); } $gd_info = gd_info(); if (isset($gd_info['GD Version'])) { $gnInstalled = true; } $preInstallConfig['GD Library Support'] = array((extension_loaded('gd') || $gnInstalled), true, (extension_loaded('gd') || $gnInstalled)); return $preInstallConfig; } /** * Extracts and cleans the version number from command output. * * @param string $output The raw output from a version command. * @return string The cleaned version number or an error message if not found. */ function getCleanedVersion($output) { $parts = explode(" ", $output); foreach ($parts as $part) { $cleaned = filter_var($part, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); if ($cleaned && strpos($cleaned, '.') !== false) { return $cleaned; } } return 'Version nicht gefunden'; } /** * Checks if the provided OS details match any supported operating systems. * * @param string $osDetails The operating system details to check. * @return string|bool The name of the supported OS if found, otherwise false. */ function isSupportedOS($osDetails) { $supportedOS = ['Debian', 'CentOS', 'Ubuntu', 'Fedora']; foreach ($supportedOS as $os) { if (stripos($osDetails, $os) !== false) { return $os; } } return false; } // ****** MYSQL Requirements *************************************************************************************************** /** * Function checks the database connection * @param $db_type * @param $db_hostname * @param $db_username * @param $db_password * @param $db_name * @return */ function checkDbConnection($db_type, $db_hostname, $db_username, $db_password, $db_name) { require('libraries/adodb/adodb.inc.php'); $dbCheckResult = array(); $db_type_status = false; // is there a db type? $db_server_status = false; // does the db server connection exist? $db_creation_failed = false; // did we try to create a database and fail? $db_exist_status = false; // does the database exist? $db_utf8_support = false; // does the database support utf8? //Checking for database connection parameters if($db_type) { $conn = NewADOConnection($db_type); $db_type_status = true; if(@$conn->Connect($db_hostname,$db_username,$db_password)) { $db_server_status = true; $serverInfo = $conn->ServerInfo(); if(isMySQL($db_type)) { $mysql_server_version = getMySQLVersion($serverInfo); } if(@$conn->Connect($db_hostname, $db_username, $db_password, $db_name)) { $db_exist_status = true; if(!$db_utf8_support) { $db_utf8_support = checkDbUTF8Support($conn); } } $conn->Close(); } } $dbCheckResult['db_utf8_support'] = $db_utf8_support; $error_msg = ''; $error_msg_info = ''; if(!$db_type_status || !$db_server_status) { $error_msg = 'Unable to connect to database Server. Invalid mySQL Connection Parameters specified'; $error_msg_info = 'This may be due to the following reasons:
'.' - specified database user, password, hostname, database type, or port is invalid
- specified database user does not have access to connect to the database server from the host'; } elseif(isMySQL($db_type) && !strpos($serverInfo['description'], "MariaDB") && !strpos($serverInfo['description'], "MariaDB")) { $error_msg = $mysql_server_version.' -> You are not using MySQL as recommended, kindly switch to MySQL'; } elseif(isMySQL($db_type) && strpos($serverInfo['description'], "MariaDB") !== false && (intval($mysql_server_version) < 10)) { $error_msg = $mysql_server_version.' -> MariaDB version is not supported, kindly connect to MySQL 10.x.x or above'; } elseif(isMySQL($db_type) && strpos($serverInfo['description'], "mysql") && intval($mysql_server_version) < 5.5) { $error_msg = $mysql_server_version.' -> MySQL version is not supported, kindly connect to MySQL 5.1.x or above'; } elseif($db_creation_failed) { $error_msg = 'Unable to Create database'; $error_msg_info = 'Message: Specified database Root User doesn\'t have permission to Create database or the Database name has special characters. Try changing the Database settings'; } elseif(!$db_exist_status) { $error_msg = $db_name.' -> This Database is not found.Try changing the Database settings'; } else { $dbCheckResult['flag'] = true; return $dbCheckResult; } $dbCheckResult['flag'] = false; $dbCheckResult['error_msg'] = $error_msg; $dbCheckResult['error_msg_info'] = $error_msg_info; return $dbCheckResult; } /** * Function checks if its mysql type * @param type $dbType * @return type */ function isMySQL($dbType) { return (stripos(strval($dbType) ,'mysql') === 0); } /** * Retrieves the MySQL version from server information. * * @param mixed $serverInfo The server information, can be an array or a string. * @return string The MySQL server version. */ function getMySQLVersion($serverInfo) { if(!is_array($serverInfo)) { $version = explode('-',strval($serverInfo)); $mysql_server_version=$version[0]; } else { $mysql_server_version = $serverInfo['version']; } return $mysql_server_version; } /** * Checks if the connected database supports UTF-8 character set. * * @param object $conn Database connection object. * @return bool True if UTF-8 is supported, false otherwise. */ function checkDbUTF8Support($conn) { global $db_type; if($db_type == 'pgsql') return true; $dbvarRS = $conn->Execute("show variables like '%_database' "); $db_character_set = null; $db_collation_type = null; while(!$dbvarRS->EOF) { $arr = $dbvarRS->FetchRow(); $arr = array_change_key_case($arr); switch($arr['variable_name']) { case 'character_set_database' : $db_character_set = $arr['value']; break; case 'collation_database' : $db_collation_type = $arr['value']; break; } // If we have all the required information break the loop. if($db_character_set != null && $db_collation_type != null) break; } return (stristr($db_character_set, 'utf8') && stristr($db_collation_type, 'utf8')); } /** * Checks MySQL configuration settings for compatibility and best practices. * * @param string $db_type Database type (e.g., 'mysqli', 'pdo_mysql'). * @param string $db_host Database host (e.g., 'localhost'). * @param string $db_user Database username. * @param string $db_password Database password. * @return mixed Returns true if all checks pass; otherwise returns an array of error messages or false on connection failure. */ function checkMySqlConfig($db_type, $db_host, $db_user, $db_password) { require('libraries/adodb/adodb.inc.php'); $conn = NewADOConnection($db_type); if(@$conn->Connect($db_host, $db_user, $db_password)) { //Check SqlMode $res = $conn->query("SELECT @@GLOBAL.sql_mode"); $sqlMode = $res->fields[0]; $err_report = array(); $errSqlMode = true; if(strpos($sqlMode, 'STRICT_TRANS_TABLE') !== false) { $err_report['STRICT_TRANS_TABLE'] = array("Setting 'STRICT_TRANS_TABLE' should be deactivated", "active"); $errSqlMode = false; } if(strpos($sqlMode, 'IGNORE_SPACE') === false) { $err_report['IGNORE_SPACE'] = array("Setting 'IGNORE_SPACE' is missing"); $errSqlMode = false; } if(strpos($sqlMode, 'NO_AUTO_CREATE_USER') === false) { $err_report['NO_AUTO_CREATE_USER'] = array("Setting 'NO_AUTO_CREATE_USER' is missing"); $errSqlMode = false; } if(strpos($sqlMode, 'NO_ENGINE_SUBSTITUTION') === false) { $err_report['NO_ENGINE_SUBSTITUTION'] = array("Setting 'NO_ENGINE_SUBSTITUTION' is missing"); $errSqlMode = false; } //Check InnoDB active $res = $conn->query("SHOW ENGINES"); $errInnodbActive = false; while (!$res->EOF) { if ($res->fields['Engine'] === 'InnoDB' && (strtolower($res->fields['Support']) === 'yes' || strtolower($res->fields['Support']) === "default")) { $errInnodbActive = true; break; } $res->MoveNext(); } if($errInnodbActive === false) { $err_report['ENGINE=InnoDB'] = array("Engine 'InnoDB' is not active", "inactive"); } //Check innodb_strict_mode $res = $conn->query("SELECT @@GLOBAL.innodb_strict_mode"); $innodb_strict_mode = $res->fields[0]; if ($innodb_strict_mode == 0) { $errInnodbMode = true; } else { $errInnodbMode = false; $err_report['innodb_strict_mode'] = array("innodb_strict_mode is activ and should be disabled", "activ"); } //Check character_set_database $res = $conn->query("SELECT @@character_set_database"); $characterSet = $res->fields[0]; if ($characterSet === "utf8" || $characterSet === "utf8mb3" || $characterSet === "utf8mb4") { $errCharacterSet = true; if($characterSet !== "utf8mb4") { $errCharacterSet = false; $err_report['character_set_database'] = array("Should be utf8mb4 (utf8mb3 or utf8 might work as well)", $characterSet); } } else { $errCharacterSet = false; $err_report['character_set_database'] = array("The character set is incorrect and should be set to UTF-8", $characterSet); } //Check collation_database $res = $conn->query("SELECT @@collation_database"); $collation = $res->fields[0]; if ($collation === 'utf8_unicode_ci') { $errCollationDatabase = true; } else { $errCollationDatabase = false; $err_report['collation_database'] = array("collation is not correct and should be set to utf8_unicode_ci", $collation); } if($errSqlMode && $errInnodbActive && $errInnodbMode && $errCharacterSet && $errCollationDatabase) { return true; } else{ return $err_report; } } return false; } /** * Retrieves the version of the connected database. * * @param string $db_type The type of the database (e.g., 'mysqli', 'pdo_mysql'). * @param string $db_host The hostname of the database server (e.g., 'localhost'). * @param string $db_user The username for the database connection. * @param string $db_password The password for the database connection. * @return mixed Returns the MySQL version string if connected successfully; otherwise, returns false. */ function dbVersion($db_type, $db_host, $db_user, $db_password) { require('libraries/adodb/adodb.inc.php'); $conn = NewADOConnection($db_type); if(@$conn->Connect($db_host, $db_user, $db_password)) { $serverInfo = $conn->ServerInfo(); if(isMySQL($db_type)) { $mysql_server_version = getMySQLVersion($serverInfo); return $mysql_server_version; } } return false; } // ****** Required File System Privileges ********************************************************************************** /** * Checks the filesystem privileges for specified paths. * * This function verifies whether certain files and directories exist, * and whether they are readable and writable. It records the results in * an associative array and also logs the details to a text file for * review. * * @return array An associative array with paths as keys and an array of * booleans indicating existence and write access as values. */ function fileSystemPrivileges() { $pathRequiredPrivileges = array( 'tabdata.php', 'parent_tabdata.php', 'cache', 'storage/', 'user_privileges/', 'modules/', 'cron/', 'backup/', 'test/', 'logs/') ; $pathPrivileges = array(); foreach ($pathRequiredPrivileges as $path) { if(file_exists($path)) { $readable = is_readable($path); $writable = is_writable($path); if($readable && $writable) { $pathPrivileges[$path] = array(true, true); } else{ $pathPrivileges[$path] = array(true, false); } } else { $pathPrivileges[$path] = array(false, false); } } return $pathPrivileges; } // ****** Display Output *************************************************************************************************** function showDataOnDisplay($systemRequirementData, $dbConnectionStatus = '', $pathPrivileges, $dbSettingsStatus = true, $dbVersion = NULL) { $displayHTML = ' System Requirements Check

Installation Requirements

PHP Configuration

'; foreach ($systemRequirementData['preInstallConfig'] as $configName => $info) { $requiredValue = $info[1] == 1 ? 'Yes' : $info[1]; $presentValue = ''; $style = ''; if ($configName === 'PHP Version' || $configName === 'Apache-Version' || $configName === 'Nginx-Version') { $presentValue = $info[0]; $style = (version_compare($presentValue, $requiredValue, '<')) ? ' color: red' : ''; } elseif ($configName === 'OS') { $presentValue = is_string($info[2]) ? $info[2] : "No"; $requiredValue = is_array($info[1]) ? implode("
", $info[1]) : $info[1]; $style = (is_array($info[1]) && !in_array($presentValue, $info[1])) ? ' color: red' : ''; } elseif ($configName === 'SSL') { if($info[2] == 1) { $presentValue = "On"; } else { $presentValue = "Off"; if(!empty($info[3])) { $presentValue .= "

".$info[3]; } } $style = ($requiredValue !== $presentValue) ? ' color: red;' : ''; } else { $presentValue = $info[2] == 1 ? 'Yes' : 'No'; $style = ($requiredValue !== $presentValue) ? ' color: red;' : ''; } $displayHTML .= ""; } $displayHTML .= '
Configuration Required Value Current Value
$configName $requiredValue $presentValue

PHP Settings

'; foreach ($systemRequirementData['directiveValues'] as $directive => $currentValue) { $recommendedValue = isset($systemRequirementData['recommendedDirectives'][$directive]) ? $systemRequirementData['recommendedDirectives'][$directive] : 'N/A'; $style = (strtolower($currentValue) !== strtolower($recommendedValue) && $currentValue <= $recommendedValue) ? 'color: red;' : ''; $displayHTML .= ""; } $displayHTML .= '
Directive Recommended Value Current Value
" . htmlspecialchars($directive) . " " . htmlspecialchars($recommendedValue) . " " . htmlspecialchars($currentValue) . "

Filesystem Permissions

'; foreach ($pathPrivileges as $path => $status) { $accessStatus = !$status[0] ? 'Does not exist' : ($status[1] ? 'Readable & Writable' : 'No access'); $style = (!$status[0] || !$status[1]) ? ' color: red' : ''; $displayHTML .= " "; } $displayHTML .= '
Path Status
" . htmlspecialchars($path) . " " . htmlspecialchars($accessStatus) . "

Database Connection Status

Status Version Additional Messages
' . ($dbConnectionStatus['flag'] ? 'Database connection successful!' : 'Connection failed') . ' ' . ($dbVersion === null ? 'DB is not connected' : ($dbVersion === false ? 'Unknown' : htmlspecialchars($dbVersion))) . ' '; if ($dbConnectionStatus['flag']) { if ($dbSettingsStatus === true) { $displayHTML .= '

Database settings are correct.

'; } elseif (is_array($dbSettingsStatus) && !empty($dbSettingsStatus)) { $displayHTML .= '
    '; foreach ($dbSettingsStatus as $setting => $info) { $error_message = htmlspecialchars($info[0]); $current_value = isset($info[1]) ? ($info[1] !== false ? htmlspecialchars($info[1]) : 'N/A') : ''; if($current_value !== '') { $displayHTML .= "
  • " . htmlspecialchars($setting) . ": $error_message (Current: $current_value)
  • "; } else { $displayHTML .= "
  • " . htmlspecialchars($setting) . ": $error_message
  • "; } } $displayHTML .= '
'; } else { $displayHTML .= "

No specific errors found.

"; } } else { $displayHTML .= '

'. $dbConnectionStatus['error_msg'].'

'; if (!empty($dbConnectionStatus['error_msg_info'])) { $displayHTML .= '

' . $dbConnectionStatus['error_msg_info'] . '

'; } } $displayHTML .= '
'; echo $displayHTML; }