From 351bb484a7bb203a482be2c13889fcd35977ec7d Mon Sep 17 00:00:00 2001
From: johnnyq
Date: Tue, 5 Nov 2024 17:36:50 -0500
Subject: [PATCH] Reworked the entire debugger, only grather nessesary info and
database comparison to existing and db.sql works now
---
admin_debug.php | 976 +++++++++++++++++++++++++++++------------
admin_legacy_debug.php | 335 ++++++++++++++
2 files changed, 1025 insertions(+), 286 deletions(-)
create mode 100644 admin_legacy_debug.php
diff --git a/admin_debug.php b/admin_debug.php
index 61591900..fc6d659a 100644
--- a/admin_debug.php
+++ b/admin_debug.php
@@ -5,330 +5,734 @@ require_once "database_version.php";
require_once "config.php";
-$folderPath = 'uploads';
+$checks = [];
-function countFilesInDirectory($dir) {
- $count = 0;
- $size = 0;
- $files = scandir($dir);
+// Section: System Information
+$systemInfo = [];
- foreach ($files as $file) {
- if ($file === '.' || $file === '..') {
- continue;
- }
+// Operating System and Version
+$os = php_uname();
+$systemInfo[] = [
+ 'name' => 'Operating System',
+ 'value' => $os,
+];
- $filePath = $dir . '/' . $file;
+// Web Server and Version
+$webServer = $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown';
+$systemInfo[] = [
+ 'name' => 'Web Server',
+ 'value' => $webServer,
+];
- if (is_file($filePath)) {
- $count++;
- $size += filesize($filePath);
- } elseif (is_dir($filePath)) {
- $result = countFilesInDirectory($filePath);
- $count += $result['count'];
- $size += $result['size'];
- }
- }
+// Kernel and Version
+$kernelVersion = php_uname('r');
+$systemInfo[] = [
+ 'name' => 'Kernel Version',
+ 'value' => $kernelVersion,
+];
- return [
- 'count' => $count,
- 'size' => $size
+// Database and Version
+$dbVersion = $mysqli->server_info;
+$systemInfo[] = [
+ 'name' => 'Database Version',
+ 'value' => $dbVersion,
+];
+
+// Section: PHP Extensions
+$phpExtensions = [];
+$extensions = [
+ 'php-mailparse' => 'mailparse',
+ 'php-imap' => 'imap',
+ 'php-mysqli' => 'mysqli',
+ 'php-intl' => 'intl',
+ 'php-curl' => 'curl',
+ 'php-mbstring' => 'mbstring',
+ 'php-gd' => 'gd',
+];
+
+foreach ($extensions as $name => $ext) {
+ $loaded = extension_loaded($ext);
+ $phpExtensions[] = [
+ 'name' => "$name installed",
+ 'passed' => $loaded,
+ 'value' => $loaded ? 'Installed' : 'Not Installed',
];
}
-// Function to compare two arrays recursively and return the differences
-function arrayDiffRecursive($array1, $array2) {
- $diff = array();
+// Section: PHP Configuration
+$phpConfig = [];
- foreach ($array1 as $key => $value) {
- if (is_array($value)) {
- if (!isset($array2[$key]) || !is_array($array2[$key])) {
- $diff[$key] = $value;
- } else {
- $recursiveDiff = arrayDiffRecursive($value, $array2[$key]);
- if (!empty($recursiveDiff)) {
- $diff[$key] = $recursiveDiff;
+// Check if shell_exec is enabled
+$disabled_functions = explode(',', ini_get('disable_functions'));
+$disabled_functions = array_map('trim', $disabled_functions);
+$shell_exec_enabled = !in_array('shell_exec', $disabled_functions);
+
+$phpConfig[] = [
+ 'name' => 'shell_exec is enabled',
+ 'passed' => $shell_exec_enabled,
+ 'value' => $shell_exec_enabled ? 'Enabled' : 'Disabled',
+];
+
+// Check upload_max_filesize and post_max_size >= 500M
+function return_bytes($val) {
+ $val = trim($val);
+ $unit = strtolower(substr($val, -1));
+ $num = (float)$val;
+ switch ($unit) {
+ case 'g':
+ $num *= 1024;
+ case 'm':
+ $num *= 1024;
+ case 'k':
+ $num *= 1024;
+ }
+ return $num;
+}
+
+$required_bytes = 500 * 1024 * 1024; // 500M in bytes
+
+$upload_max_filesize = ini_get('upload_max_filesize');
+$post_max_size = ini_get('post_max_size');
+
+$upload_passed = return_bytes($upload_max_filesize) >= $required_bytes;
+$post_passed = return_bytes($post_max_size) >= $required_bytes;
+
+$phpConfig[] = [
+ 'name' => 'upload_max_filesize >= 500M',
+ 'passed' => $upload_passed,
+ 'value' => $upload_max_filesize,
+];
+
+$phpConfig[] = [
+ 'name' => 'post_max_size >= 500M',
+ 'passed' => $post_passed,
+ 'value' => $post_max_size,
+];
+
+// PHP Memory Limit >= 128M
+$memoryLimit = ini_get('memory_limit');
+$memoryLimitBytes = return_bytes($memoryLimit);
+$memoryLimitPassed = $memoryLimitBytes >= (128 * 1024 * 1024);
+$phpConfig[] = [
+ 'name' => 'PHP Memory Limit >= 128M',
+ 'passed' => $memoryLimitPassed,
+ 'value' => $memoryLimit,
+];
+
+// Max Execution Time >= 300 seconds
+$maxExecutionTime = ini_get('max_execution_time');
+$maxExecutionTimePassed = $maxExecutionTime >= 300;
+$phpConfig[] = [
+ 'name' => 'Max Execution Time >= 300 seconds',
+ 'passed' => $maxExecutionTimePassed,
+ 'value' => $maxExecutionTime . ' seconds',
+];
+
+// Check PHP version >= 8.2.0
+$php_version = PHP_VERSION;
+$php_passed = version_compare($php_version, '8.2.0', '>=');
+
+$phpConfig[] = [
+ 'name' => 'PHP version >= 8.2.0',
+ 'passed' => $php_passed,
+ 'value' => $php_version,
+];
+
+// Section: Shell Commands
+$shellCommands = [];
+
+if ($shell_exec_enabled) {
+ $commands = ['whois', 'dig', 'git'];
+
+ foreach ($commands as $command) {
+ $which = trim(shell_exec("which $command 2>/dev/null"));
+ $exists = !empty($which);
+ $shellCommands[] = [
+ 'name' => "Command '$command' available",
+ 'passed' => $exists,
+ 'value' => $exists ? $which : 'Not Found',
+ ];
+ }
+} else {
+ // If shell_exec is disabled, mark commands as unavailable
+ foreach (['whois', 'dig', 'git'] as $command) {
+ $shellCommands[] = [
+ 'name' => "Command '$command' available",
+ 'passed' => false,
+ 'value' => 'shell_exec Disabled',
+ ];
+ }
+}
+
+// Section: SSL Checks
+$sslChecks = [];
+
+// Check if accessing via HTTPS
+$https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443;
+$sslChecks[] = [
+ 'name' => 'Accessing via HTTPS',
+ 'passed' => $https,
+ 'value' => $https ? 'Yes' : 'No',
+];
+
+// SSL Certificate Validity Check
+if ($https) {
+ $streamContext = stream_context_create(["ssl" => ["capture_peer_cert" => true]]);
+ $socket = @stream_socket_client("ssl://{$_SERVER['HTTP_HOST']}:443", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $streamContext);
+
+ if ($socket) {
+ $params = stream_context_get_params($socket);
+ $cert = $params['options']['ssl']['peer_certificate'];
+ $certInfo = openssl_x509_parse($cert);
+
+ $validFrom = $certInfo['validFrom_time_t'];
+ $validTo = $certInfo['validTo_time_t'];
+ $currentTime = time();
+
+ $certValid = ($currentTime >= $validFrom && $currentTime <= $validTo);
+
+ $sslChecks[] = [
+ 'name' => 'SSL Certificate is valid',
+ 'passed' => $certValid,
+ 'value' => $certValid ? 'Valid' : 'Invalid or Expired',
+ ];
+ } else {
+ $sslChecks[] = [
+ 'name' => 'SSL Certificate is valid',
+ 'passed' => false,
+ 'value' => 'Unable to retrieve certificate',
+ ];
+ }
+} else {
+ $sslChecks[] = [
+ 'name' => 'SSL Certificate is valid',
+ 'passed' => false,
+ 'value' => 'Not using HTTPS',
+ ];
+}
+
+// Section: Domain Checks
+$domainChecks = [];
+
+// Check if the site has a valid FQDN
+$fqdn = $_SERVER['HTTP_HOST'];
+$isValidFqdn = (bool) filter_var('http://' . $fqdn, FILTER_VALIDATE_URL) && preg_match('/^[a-z0-9.-]+\.[a-z]{2,}$/i', $fqdn);
+
+$domainChecks[] = [
+ 'name' => 'Site has a valid FQDN',
+ 'passed' => $isValidFqdn,
+ 'value' => $fqdn,
+];
+
+// Section: File Permissions
+$filePermissions = [];
+
+// Check if web user has write access to webroot directory
+$webroot = $_SERVER['DOCUMENT_ROOT'];
+$writable = is_writable($webroot);
+$filePermissions[] = [
+ 'name' => 'Web user has write access to webroot directory',
+ 'passed' => $writable,
+ 'value' => $webroot,
+];
+
+// Section: Uploads Directory Stats
+$uploadsStats = [];
+
+// Define the uploads directory path
+$uploadsDir = __DIR__ . '/uploads'; // Adjust the path if needed
+
+if (is_dir($uploadsDir)) {
+ // Function to recursively count files and calculate total size
+ function getDirStats($dir) {
+ $files = 0;
+ $size = 0;
+
+ $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
+ foreach ($iterator as $file) {
+ if ($file->isFile()) {
+ $files++;
+ $size += $file->getSize();
+ }
+ }
+ return ['files' => $files, 'size' => $size];
+ }
+
+ $stats = getDirStats($uploadsDir);
+ $sizeInMB = round($stats['size'] / (1024 * 1024), 2);
+
+ $uploadsStats[] = [
+ 'name' => 'Number of files in uploads directory',
+ 'value' => $stats['files'],
+ ];
+
+ $uploadsStats[] = [
+ 'name' => 'Total size of uploads directory (MB)',
+ 'value' => $sizeInMB . ' MB',
+ ];
+} else {
+ $uploadsStats[] = [
+ 'name' => 'Uploads directory exists',
+ 'value' => 'Directory not found',
+ ];
+}
+
+// Section: Database Stats
+$databaseStats = [];
+
+// Get list of tables
+$tablesResult = $mysqli->query("SHOW TABLE STATUS");
+if ($tablesResult) {
+ $totalTables = 0;
+ $totalFields = 0;
+ $totalRows = 0;
+ $totalSize = 0;
+ $tableDetails = [];
+
+ while ($table = $tablesResult->fetch_assoc()) {
+ $tableName = $table['Name'];
+ $tableRows = $table['Rows'];
+ $dataLength = $table['Data_length'];
+ $indexLength = $table['Index_length'];
+ $tableSize = ($dataLength + $indexLength) / (1024 * 1024); // Size in MB
+
+ // Get number of fields
+ $fieldsResult = $mysqli->query("SHOW COLUMNS FROM `$tableName`");
+ $numFields = $fieldsResult->num_rows;
+ $fieldsResult->free();
+
+ $totalTables++;
+ $totalFields += $numFields;
+ $totalRows += $tableRows;
+ $totalSize += $tableSize;
+
+ $tableDetails[] = [
+ 'name' => $tableName,
+ 'fields' => $numFields,
+ 'rows' => $tableRows,
+ 'size' => round($tableSize, 2),
+ ];
+ }
+ $tablesResult->free();
+
+ $databaseStats[] = [
+ 'name' => 'Current Database Version',
+ 'value' => CURRENT_DATABASE_VERSION,
+ ];
+ $databaseStats[] = [
+ 'name' => 'Total number of tables',
+ 'value' => $totalTables,
+ ];
+ $databaseStats[] = [
+ 'name' => 'Total number of fields',
+ 'value' => $totalFields,
+ ];
+ $databaseStats[] = [
+ 'name' => 'Total number of rows',
+ 'value' => $totalRows,
+ ];
+ $databaseStats[] = [
+ 'name' => 'Total database size (MB)',
+ 'value' => round($totalSize, 2) . ' MB',
+ ];
+} else {
+ $databaseStats[] = [
+ 'name' => 'Database connection error',
+ 'value' => $mysqli->error,
+ ];
+}
+
+// Section: Database Structure Comparison
+$dbComparison = [];
+
+// Path to the db.sql file
+$dbSqlFile = __DIR__ . '/db.sql';
+
+if (file_exists($dbSqlFile)) {
+ // Read the db.sql file
+ $sqlContent = file_get_contents($dbSqlFile);
+
+ // Remove comments and empty lines
+ $lines = explode("\n", $sqlContent);
+ $sqlStatements = [];
+ $statement = '';
+
+ foreach ($lines as $line) {
+ // Remove single-line comments
+ $line = preg_replace('/--.*$/', '', $line);
+ $line = preg_replace('/\/\*.*?\*\//', '', $line);
+
+ // Skip empty lines
+ if (trim($line) == '') {
+ continue;
+ }
+
+ // Append line to the current statement
+ $statement .= $line . "\n";
+
+ // Check if the statement ends with a semicolon
+ if (preg_match('/;\s*$/', $line)) {
+ $sqlStatements[] = $statement;
+ $statement = '';
+ }
+ }
+
+ // Parse the CREATE TABLE statements
+ $sqlTables = [];
+
+ foreach ($sqlStatements as $sql) {
+ if (preg_match('/CREATE TABLE\s+`?([^` ]+)`?\s*\((.*)\)(.*?);/msi', $sql, $match)) {
+ $tableName = $match[1];
+ $columnsDefinition = $match[2];
+
+ // Extract column names and data types
+ $columns = [];
+ $columnLines = explode("\n", $columnsDefinition);
+ foreach ($columnLines as $line) {
+ $line = trim($line);
+ // Skip empty lines and lines that do not define columns
+ if ($line == '' || strpos($line, 'PRIMARY KEY') !== false || strpos($line, 'UNIQUE KEY') !== false || strpos($line, 'KEY') === 0 || strpos($line, 'CONSTRAINT') === 0 || strpos($line, ')') === 0) {
+ continue;
+ }
+
+ // Remove trailing comma if present
+ $line = rtrim($line, ',');
+
+ // Match column definition
+ if (preg_match('/^`([^`]+)`\s+(.+)/', $line, $colMatch)) {
+ $colName = $colMatch[1];
+ $colDefinition = $colMatch[2];
+
+ // Extract the data type from the column definition
+ $tokens = preg_split('/\s+/', $colDefinition);
+ $colType = $tokens[0];
+
+ // Handle data types with parentheses (e.g., varchar(255), decimal(15,2))
+ if (preg_match('/^([a-zA-Z]+)\(([^)]+)\)/', $colType, $typeMatch)) {
+ $colType = $typeMatch[1] . '(' . $typeMatch[2] . ')';
+ }
+
+ $columns[$colName] = $colType;
}
}
- } else {
- if (!isset($array2[$key]) || $array2[$key] !== $value) {
- $diff[$key] = $value;
+ $sqlTables[$tableName] = $columns;
+ }
+ }
+
+ // Get current database table structures
+ $dbTables = [];
+ $tablesResult = $mysqli->query("SHOW TABLES");
+ while ($row = $tablesResult->fetch_row()) {
+ $tableName = $row[0];
+ $columnsResult = $mysqli->query("SHOW COLUMNS FROM `$tableName`");
+ $columns = [];
+ while ($col = $columnsResult->fetch_assoc()) {
+ $columns[$col['Field']] = $col['Type'];
+ }
+ $columnsResult->free();
+ $dbTables[$tableName] = $columns;
+ }
+ $tablesResult->free();
+
+ // Compare the structures
+ foreach ($sqlTables as $tableName => $sqlColumns) {
+ if (!isset($dbTables[$tableName])) {
+ $dbComparison[] = [
+ 'name' => "Table `$tableName` missing in database",
+ 'status' => 'Missing Table',
+ ];
+ continue;
+ }
+
+ // Compare columns
+ $dbColumns = $dbTables[$tableName];
+ foreach ($sqlColumns as $colName => $colType) {
+ if (!isset($dbColumns[$colName])) {
+ $dbComparison[] = [
+ 'name' => "Column `$colName` missing in table `$tableName`",
+ 'status' => 'Missing Column',
+ ];
+ } else {
+ // Normalize data types for comparison
+ $sqlColType = strtolower($colType);
+ $dbColType = strtolower($dbColumns[$colName]);
+
+ // Remove attributes and constraints
+ $sqlColType = preg_replace('/\s+.*$/', '', $sqlColType);
+ $dbColType = preg_replace('/\s+.*$/', '', $dbColType);
+
+ // Remove additional attributes like unsigned, zerofill, etc.
+ $sqlColType = preg_replace('/\s+unsigned|\s+zerofill|\s+binary/', '', $sqlColType);
+ $dbColType = preg_replace('/\s+unsigned|\s+zerofill|\s+binary/', '', $dbColType);
+
+ if ($sqlColType != $dbColType) {
+ $dbComparison[] = [
+ 'name' => "Data type mismatch for `$colName` in table `$tableName`",
+ 'status' => "Expected: $colType, Found: {$dbColumns[$colName]}",
+ ];
+ }
+ }
+ }
+
+ // Check for extra columns in the database that are not in the SQL file
+ foreach ($dbColumns as $colName => $colType) {
+ if (!isset($sqlColumns[$colName])) {
+ $dbComparison[] = [
+ 'name' => "Extra column `$colName` in table `$tableName` not present in db.sql",
+ 'status' => 'Extra Column',
+ ];
}
}
}
- return $diff;
-}
-
-// Function to load the table structures from an SQL dump file URL
-function loadTableStructuresFromSQLDumpURL($fileURL) {
- $context = stream_context_create(array('http' => array('header' => 'Accept: application/octet-stream')));
- $fileContent = file_get_contents($fileURL, false, $context);
-
- if ($fileContent === false) {
- return null;
- }
-
- $structure = array();
- $queries = explode(";", $fileContent);
-
- foreach ($queries as $query) {
- $query = trim($query);
-
- if (!empty($query)) {
- if (preg_match("/^CREATE TABLE `(.*)` \((.*)\)$/s", $query, $matches)) {
- $tableName = $matches[1];
- $tableStructure = $matches[2];
- $structure[$tableName] = array('structure' => $tableStructure);
- }
+ // Check for tables in the database not present in the db.sql file
+ foreach ($dbTables as $tableName => $dbColumns) {
+ if (!isset($sqlTables[$tableName])) {
+ $dbComparison[] = [
+ 'name' => "Extra table `$tableName` in database not present in db.sql",
+ 'status' => 'Extra Table',
+ ];
}
}
-
- return $structure;
+} else {
+ $dbComparison[] = [
+ 'name' => 'db.sql file not found',
+ 'status' => 'File Missing',
+ ];
}
-// Function to fetch the database structure from the MySQL server
-function fetchDatabaseStructureFromServer() {
-
- global $mysqli;
-
- $tables = array();
-
- // Fetch table names
- $result = $mysqli->query("SHOW TABLES");
-
- if ($result->num_rows > 0) {
- while ($row = $result->fetch_row()) {
- $tableName = $row[0];
- $tables[$tableName] = array();
- }
- }
-
- // Fetch table structures
- foreach ($tables as $tableName => &$table) {
- $result = $mysqli->query("SHOW CREATE TABLE `$tableName`");
-
- if ($result->num_rows > 0) {
- $row = $result->fetch_row();
- $table['structure'] = $row[1];
- }
- }
-
- return $tables;
-}
-
-//function to get current crontab and return it as an array
-function get_crontab() {
- $crontab = shell_exec('crontab -l');
- $crontab = explode(PHP_EOL, $crontab);
- return $crontab;
-}
-
-// URL to the SQL dump file
-$fileURL = "https://raw.githubusercontent.com/itflow-org/itflow/master/db.sql";
-
-// Load the desired table structures from the SQL dump file URL
-$desiredStructure = loadTableStructuresFromSQLDumpURL($fileURL);
-
-if ($desiredStructure === null) {
- die("Failed to load the desired table structures from the SQL dump file URL.");
-}
-
-// Fetch the current database structure from the MySQL server
-$currentStructure = fetchDatabaseStructureFromServer();
-
-if ($currentStructure === null) {
- die("Failed to fetch the current database structure from the server.");
-}
-
-// Compare the structures and display the differences
-$differences = arrayDiffRecursive($desiredStructure, $currentStructure);
-
-//DB Stats
-// Query to fetch the number of tables
-$tablesQuery = "SHOW TABLES";
-$tablesResult = $mysqli->query($tablesQuery);
-
-$numTables = $tablesResult->num_rows;
-$numFields = 0;
-$numRows = 0;
-
-// Loop through each table
-while ($row = $tablesResult->fetch_row()) {
- $tableName = $row[0];
-
- // Query to fetch the number of fields
- $fieldsQuery = "DESCRIBE `$tableName`";
- $fieldsResult = $mysqli->query($fieldsQuery);
-
- // Check if the query was successful
- if ($fieldsResult) {
- $numFields += $fieldsResult->num_rows;
-
- // Query to fetch the number of rows
- $rowsQuery = "SELECT COUNT(*) FROM `$tableName`";
- $rowsResult = $mysqli->query($rowsQuery);
-
- // Check if the query was successful
- if ($rowsResult) {
- $numRows += $rowsResult->fetch_row()[0];
- } else {
- echo "Error executing query: " . $mysqli->error;
- }
- } else {
- echo "Error executing query: " . $mysqli->error;
- }
-}
-
-//Get loaded PHP modules
-$loadedModules = get_loaded_extensions();
-
-//Get Server Info / Service versions
-$phpVersion = phpversion();
-$databaseInfo = mysqli_get_server_info($mysqli) . " / " . $mysqli->server_version;
-$operatingSystem = php_uname();
-$webServer = $_SERVER['SERVER_SOFTWARE'];
-$errorLog = ini_get('error_log') ?: "Debian/Ubuntu default is usually /var/log/apache2/error.log";
-$updates = fetchUpdates();
-
+$mysqli->close();
?>
-
-
-
+
+
+
-
Debugging
-
- - If you are experiencing a problem with ITFlow you may be directed to this page to gather server/app info.
- - When creating forum posts / support requests ensure you share the information under Server Info, ITFlow app and Database stats.
- - Caution: Be careful when sharing the full debug output - it contains your PHP session variables/cookies ("PHPSESSID") which could allow anyone to login to your ITFlow instance
- - Note: Sometimes you might need to gather PHP error logs as well
-
-
+
Debugging
+
+ - If you are experiencing a problem with ITFlow you may be directed to this page to gather server/app info.
+ - When creating forum posts / support requests ensure you share the information under Server Info, ITFlow app and Database stats.
+ - Caution: Be careful when sharing the full debug output - it contains your PHP session variables/cookies ("PHPSESSID") which could allow anyone to login to your ITFlow instance
+ - Note: Sometimes you might need to gather PHP error logs as well
+
+
-
Server Info
+
+
System Information
+
+
+
+
+ | = htmlspecialchars($info['name']); ?> |
+ = htmlspecialchars($info['value']); ?> |
+
+
+
+
- ";
- echo "Database Version: " . $databaseInfo . "
";
- echo "Operating System: " . $operatingSystem . "
";
- echo "Web Server: " . $webServer . "
";
- echo "Apache/PHP Error Log: " . $errorLog
- ?>
+
+
PHP Extensions and Configuration
+
+
+
+
+ | PHP Extensions |
+
+
+
+
+
+ | = htmlspecialchars($check['name']); ?> |
+
+
+
+
+
+
+ |
+ = htmlspecialchars($check['value']); ?> |
+
+
+
+
+
+
+ | PHP Configuration |
+
+
+
+
+
+ | = htmlspecialchars($check['name']); ?> |
+
+
+
+
+
+
+ |
+ = htmlspecialchars($check['value']); ?> |
+
+
+
+
+
+ | Shell Commands |
+
+
+
+
+
+ | = htmlspecialchars($check['name']); ?> |
+
+
+
+
+
+
+ |
+ = htmlspecialchars($check['value']); ?> |
+
+
+
+
+
+ | SSL Checks |
+
+
+
+
+
+ | = htmlspecialchars($check['name']); ?> |
+
+
+
+
+
+
+ |
+ = htmlspecialchars($check['value']); ?> |
+
+
+
+
+
+ | Domain Checks |
+
+
+
+
+
+ | = htmlspecialchars($check['name']); ?> |
+
+
+
+
+
+
+ |
+ = htmlspecialchars($check['value']); ?> |
+
+
+
-
+
+
+
+ | File Permissions |
+
+
+
+
+
+ | = htmlspecialchars($check['name']); ?> |
+
+
+
+
+
+
+ |
+ = htmlspecialchars($check['value']); ?> |
+
+
+
+
-
File System
-
+
Database Structure Comparison
+
+
+
+
+
+ | = htmlspecialchars($issue['name']); ?> |
+ = htmlspecialchars($issue['status']); ?> |
+
+
+
+
+ | No discrepancies found between the database and db.sql file. |
+
+
+
+
- echo "Total number of files in $folderPath and its subdirectories: " . $totalFiles . "
";
- echo "Total size of files in $folderPath and its subdirectories: " . $totalSizeMB . " MB";
- ?>
+
+
Uploads Directory Stats
+
+
+
+
+ | = htmlspecialchars($stat['name']); ?> |
+ = htmlspecialchars($stat['value']); ?> |
+
+
+
+
-
-
ITFlow app
- current_version . "
";
- echo "Cron enabled: " . $config_enable_cron . "
";
- echo "App Timezone: " . $config_timezone;
- ?>
+
+
Database Stats
+
+
+
+
+ | = htmlspecialchars($stat['name']); ?> |
+ = htmlspecialchars($stat['value']); ?> |
+
+
+
+
-
-
-
Database Structure Check
-
-
Database stats
-
- ";
- echo "Total number of fields: " . $numFields . "
";
- echo "Total number of rows: " . $numRows . "
";
- echo "Current Database Version: " . CURRENT_DATABASE_VERSION . "
";
- ?>
-
-
-
-
Table Stats
-
-
+
+ Table Stats
+
+
| Table Name |
- Number of Fields |
- Number of Rows |
+ Fields / Rows |
+ Size (MB) |
-
-
-
+
+
+
- |
- |
- |
+ = htmlspecialchars($table['name']); ?> |
+ = htmlspecialchars("Fields: {$table['fields']}, Rows: {$table['rows']}"); ?> |
+ = htmlspecialchars($table['size'] . ' MB'); ?> |
-
-
+
+
+
-
-
-
PHP Modules Installed
-
- ";
- }
- ?>
-
-
-
-
PHP Info
- (.*)
(.*)$%ms', '$1', $phpinfo);
-
- //Output the result
- echo $phpinfo;
- ?>
-
-
-
+
+
$count,
+ 'size' => $size
+ ];
+}
+
+// Function to compare two arrays recursively and return the differences
+function arrayDiffRecursive($array1, $array2) {
+ $diff = array();
+
+ foreach ($array1 as $key => $value) {
+ if (is_array($value)) {
+ if (!isset($array2[$key]) || !is_array($array2[$key])) {
+ $diff[$key] = $value;
+ } else {
+ $recursiveDiff = arrayDiffRecursive($value, $array2[$key]);
+ if (!empty($recursiveDiff)) {
+ $diff[$key] = $recursiveDiff;
+ }
+ }
+ } else {
+ if (!isset($array2[$key]) || $array2[$key] !== $value) {
+ $diff[$key] = $value;
+ }
+ }
+ }
+
+ return $diff;
+}
+
+// Function to load the table structures from an SQL dump file URL
+function loadTableStructuresFromSQLDumpURL($fileURL) {
+ $context = stream_context_create(array('http' => array('header' => 'Accept: application/octet-stream')));
+ $fileContent = file_get_contents($fileURL, false, $context);
+
+ if ($fileContent === false) {
+ return null;
+ }
+
+ $structure = array();
+ $queries = explode(";", $fileContent);
+
+ foreach ($queries as $query) {
+ $query = trim($query);
+
+ if (!empty($query)) {
+ if (preg_match("/^CREATE TABLE `(.*)` \((.*)\)$/s", $query, $matches)) {
+ $tableName = $matches[1];
+ $tableStructure = $matches[2];
+ $structure[$tableName] = array('structure' => $tableStructure);
+ }
+ }
+ }
+
+ return $structure;
+}
+
+// Function to fetch the database structure from the MySQL server
+function fetchDatabaseStructureFromServer() {
+
+ global $mysqli;
+
+ $tables = array();
+
+ // Fetch table names
+ $result = $mysqli->query("SHOW TABLES");
+
+ if ($result->num_rows > 0) {
+ while ($row = $result->fetch_row()) {
+ $tableName = $row[0];
+ $tables[$tableName] = array();
+ }
+ }
+
+ // Fetch table structures
+ foreach ($tables as $tableName => &$table) {
+ $result = $mysqli->query("SHOW CREATE TABLE `$tableName`");
+
+ if ($result->num_rows > 0) {
+ $row = $result->fetch_row();
+ $table['structure'] = $row[1];
+ }
+ }
+
+ return $tables;
+}
+
+//function to get current crontab and return it as an array
+function get_crontab() {
+ $crontab = shell_exec('crontab -l');
+ $crontab = explode(PHP_EOL, $crontab);
+ return $crontab;
+}
+
+// URL to the SQL dump file
+$fileURL = "https://raw.githubusercontent.com/itflow-org/itflow/master/db.sql";
+
+// Load the desired table structures from the SQL dump file URL
+$desiredStructure = loadTableStructuresFromSQLDumpURL($fileURL);
+
+if ($desiredStructure === null) {
+ die("Failed to load the desired table structures from the SQL dump file URL.");
+}
+
+// Fetch the current database structure from the MySQL server
+$currentStructure = fetchDatabaseStructureFromServer();
+
+if ($currentStructure === null) {
+ die("Failed to fetch the current database structure from the server.");
+}
+
+// Compare the structures and display the differences
+$differences = arrayDiffRecursive($desiredStructure, $currentStructure);
+
+//DB Stats
+// Query to fetch the number of tables
+$tablesQuery = "SHOW TABLES";
+$tablesResult = $mysqli->query($tablesQuery);
+
+$numTables = $tablesResult->num_rows;
+$numFields = 0;
+$numRows = 0;
+
+// Loop through each table
+while ($row = $tablesResult->fetch_row()) {
+ $tableName = $row[0];
+
+ // Query to fetch the number of fields
+ $fieldsQuery = "DESCRIBE `$tableName`";
+ $fieldsResult = $mysqli->query($fieldsQuery);
+
+ // Check if the query was successful
+ if ($fieldsResult) {
+ $numFields += $fieldsResult->num_rows;
+
+ // Query to fetch the number of rows
+ $rowsQuery = "SELECT COUNT(*) FROM `$tableName`";
+ $rowsResult = $mysqli->query($rowsQuery);
+
+ // Check if the query was successful
+ if ($rowsResult) {
+ $numRows += $rowsResult->fetch_row()[0];
+ } else {
+ echo "Error executing query: " . $mysqli->error;
+ }
+ } else {
+ echo "Error executing query: " . $mysqli->error;
+ }
+}
+
+//Get loaded PHP modules
+$loadedModules = get_loaded_extensions();
+
+//Get Server Info / Service versions
+$phpVersion = phpversion();
+$databaseInfo = mysqli_get_server_info($mysqli) . " / " . $mysqli->server_version;
+$operatingSystem = php_uname();
+$webServer = $_SERVER['SERVER_SOFTWARE'];
+$errorLog = ini_get('error_log') ?: "Debian/Ubuntu default is usually /var/log/apache2/error.log";
+$updates = fetchUpdates();
+
+?>
+
+
+
+
+
+
Debugging
+
+ - If you are experiencing a problem with ITFlow you may be directed to this page to gather server/app info.
+ - When creating forum posts / support requests ensure you share the information under Server Info, ITFlow app and Database stats.
+ - Caution: Be careful when sharing the full debug output - it contains your PHP session variables/cookies ("PHPSESSID") which could allow anyone to login to your ITFlow instance
+ - Note: Sometimes you might need to gather PHP error logs as well
+
+
+
+
Server Info
+
+ ";
+ echo "Database Version: " . $databaseInfo . "
";
+ echo "Operating System: " . $operatingSystem . "
";
+ echo "Web Server: " . $webServer . "
";
+ echo "Apache/PHP Error Log: " . $errorLog
+ ?>
+
+
+
+
File System
+ ";
+ echo "Total size of files in $folderPath and its subdirectories: " . $totalSizeMB . " MB";
+ ?>
+
+
+
ITFlow app
+ current_version . "
";
+ echo "Cron enabled: " . $config_enable_cron . "
";
+ echo "App Timezone: " . $config_timezone;
+ ?>
+
+
+
+
Database Structure Check
+
+
Database stats
+
+ ";
+ echo "Total number of fields: " . $numFields . "
";
+ echo "Total number of rows: " . $numRows . "
";
+ echo "Current Database Version: " . CURRENT_DATABASE_VERSION . "
";
+ ?>
+
+
+
+
Table Stats
+
+
+
+ | Table Name |
+ Number of Fields |
+ Number of Rows |
+
+
+
+
+
+ |
+ |
+ |
+
+
+
+
+
+
+
PHP Modules Installed
+
+ ";
+ }
+ ?>
+
+
+
+
PHP Info
+ (.*)
(.*)$%ms', '$1', $phpinfo);
+
+ //Output the result
+ echo $phpinfo;
+ ?>
+
+
+
+
+
+