mirror of https://github.com/itflow-org/itflow
758 lines
25 KiB
PHP
758 lines
25 KiB
PHP
<?php
|
|
|
|
require_once "includes/inc_all_admin.php";
|
|
require_once "includes/database_version.php";
|
|
require_once "config.php";
|
|
|
|
$checks = [];
|
|
|
|
// Execute the git command to get the latest commit hash
|
|
$commitHash = shell_exec('git log -1 --format=%H');
|
|
|
|
// Get branch info
|
|
$gitBranch = shell_exec('git rev-parse --abbrev-ref HEAD');
|
|
|
|
// Section: System Information
|
|
$systemInfo = [];
|
|
|
|
// Operating System and Version
|
|
$os = php_uname();
|
|
$systemInfo[] = [
|
|
'name' => 'Operating System',
|
|
'value' => $os,
|
|
];
|
|
|
|
// Web Server and Version
|
|
$webServer = $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown';
|
|
$systemInfo[] = [
|
|
'name' => 'Web Server',
|
|
'value' => $webServer,
|
|
];
|
|
|
|
// Kernel and Version
|
|
$kernelVersion = php_uname('r');
|
|
$systemInfo[] = [
|
|
'name' => 'Kernel Version',
|
|
'value' => $kernelVersion,
|
|
];
|
|
|
|
// 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',
|
|
];
|
|
}
|
|
|
|
// Section: PHP Configuration
|
|
$phpConfig = [];
|
|
|
|
// 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' => '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;
|
|
}
|
|
}
|
|
$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',
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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',
|
|
];
|
|
}
|
|
}
|
|
} else {
|
|
$dbComparison[] = [
|
|
'name' => 'db.sql file not found',
|
|
'status' => 'File Missing',
|
|
];
|
|
}
|
|
|
|
$mysqli->close();
|
|
?>
|
|
|
|
<div class="card card-dark">
|
|
<div class="card-header py-3">
|
|
<h3 class="card-title"><i class="fas fa-fw fa-bug mr-2"></i>Debug</h3>
|
|
</div>
|
|
<div class="card-body">
|
|
|
|
<h2>Debugging</h2>
|
|
<ul>
|
|
<li>If you are experiencing a problem with ITFlow, this page should help you identify any configuration issues.</li>
|
|
<li>Note: You might also need to gather <a href="https://docs.itflow.org/gathering_logs#error_logs">error logs</a></li>
|
|
</ul>
|
|
<hr>
|
|
|
|
<table class="table table-bordered mb-3">
|
|
<tr>
|
|
<th>ITFlow release version</th>
|
|
<th><?php echo APP_VERSION; ?></th>
|
|
</tr>
|
|
<tr>
|
|
<td>Current DB Version</td>
|
|
<td><?php echo CURRENT_DATABASE_VERSION; ?></td>
|
|
</tr>
|
|
<tr>
|
|
<td>Current Code Commit</td>
|
|
<td><?php echo $commitHash; ?></td>
|
|
</tr>
|
|
<tr>
|
|
<td>Current Branch</td>
|
|
<td><?php echo $gitBranch; ?></td>
|
|
</tr>
|
|
</table>
|
|
|
|
<!-- System Information Table -->
|
|
<h3>System Information</h3>
|
|
<table class="table table-sm table-bordered">
|
|
<tbody>
|
|
<?php foreach ($systemInfo as $info): ?>
|
|
<tr>
|
|
<td><?= htmlspecialchars($info['name']); ?></td>
|
|
<td><?= htmlspecialchars($info['value']); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
|
|
<!-- PHP Extensions and Configuration Table -->
|
|
<h3 class="mt-3">PHP Extensions and Configuration</h3>
|
|
<table class="table table-sm table-bordered">
|
|
<!-- PHP Extensions Section -->
|
|
<thead>
|
|
<tr class="table-secondary">
|
|
<th colspan="3">PHP Extensions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($phpExtensions as $check): ?>
|
|
<tr>
|
|
<td><?= htmlspecialchars($check['name']); ?></td>
|
|
<td class="text-center">
|
|
<?php if ($check['passed']): ?>
|
|
<i class="fas fa-check" style="color:green"></i>
|
|
<?php else: ?>
|
|
<i class="fas fa-times" style="color:red"></i>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?= htmlspecialchars($check['value']); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
<!-- PHP Configuration Section -->
|
|
<thead>
|
|
<tr class="table-secondary">
|
|
<th colspan="3">PHP Configuration</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($phpConfig as $check): ?>
|
|
<tr>
|
|
<td><?= htmlspecialchars($check['name']); ?></td>
|
|
<td class="text-center">
|
|
<?php if ($check['passed']): ?>
|
|
<i class="fas fa-check" style="color:green"></i>
|
|
<?php else: ?>
|
|
<i class="fas fa-times" style="color:red"></i>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?= htmlspecialchars($check['value']); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
<thead>
|
|
<tr class="table-secondary">
|
|
<th colspan="3">Shell Commands</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($shellCommands as $check): ?>
|
|
<tr>
|
|
<td><?= htmlspecialchars($check['name']); ?></td>
|
|
<td class="text-center">
|
|
<?php if ($check['passed']): ?>
|
|
<i class="fas fa-check" style="color:green"></i>
|
|
<?php else: ?>
|
|
<i class="fas fa-times" style="color:red"></i>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?= htmlspecialchars($check['value']); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
<thead>
|
|
<tr class="table-secondary">
|
|
<th colspan="3">SSL Checks</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($sslChecks as $check): ?>
|
|
<tr>
|
|
<td><?= htmlspecialchars($check['name']); ?></td>
|
|
<td class="text-center">
|
|
<?php if ($check['passed']): ?>
|
|
<i class="fas fa-check" style="color:green"></i>
|
|
<?php else: ?>
|
|
<i class="fas fa-times" style="color:red"></i>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?= htmlspecialchars($check['value']); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
<thead>
|
|
<tr class="table-secondary">
|
|
<th colspan="3">Domain Checks</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($domainChecks as $check): ?>
|
|
<tr>
|
|
<td><?= htmlspecialchars($check['name']); ?></td>
|
|
<td class="text-center">
|
|
<?php if ($check['passed']): ?>
|
|
<i class="fas fa-check" style="color:green"></i>
|
|
<?php else: ?>
|
|
<i class="fas fa-times" style="color:red"></i>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?= htmlspecialchars($check['value']); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
|
|
<!-- File Permissions Table -->
|
|
<thead>
|
|
<tr class="table-secondary">
|
|
<th colspan="3">File Permissions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($filePermissions as $check): ?>
|
|
<tr>
|
|
<td><?= htmlspecialchars($check['name']); ?></td>
|
|
<td class="text-center">
|
|
<?php if ($check['passed']): ?>
|
|
<i class="fas fa-check" style="color:green"></i>
|
|
<?php else: ?>
|
|
<i class="fas fa-times" style="color:red"></i>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?= htmlspecialchars($check['value']); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
|
|
|
|
|
|
<!-- Database Structure Comparison Table -->
|
|
<h3 class="mt-3">Database Structure Comparison</h3>
|
|
<table class="table table-sm table-bordered">
|
|
<tbody>
|
|
<?php if (!empty($dbComparison)): ?>
|
|
<?php foreach ($dbComparison as $issue): ?>
|
|
<tr>
|
|
<td><?= htmlspecialchars($issue['name']); ?></td>
|
|
<td colspan="2"><?= htmlspecialchars($issue['status']); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php else: ?>
|
|
<tr>
|
|
<td colspan="3">No discrepancies found between the database and db.sql file.</td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
|
|
<!-- Uploads Directory Stats Table -->
|
|
<h3 class="mt-3">Uploads Directory Stats</h3>
|
|
<table class="table table-sm table-bordered">
|
|
<tbody>
|
|
<?php foreach ($uploadsStats as $stat): ?>
|
|
<tr>
|
|
<td><?= htmlspecialchars($stat['name']); ?></td>
|
|
<td colspan="2"><?= htmlspecialchars($stat['value']); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
|
|
<!-- Database Stats Table -->
|
|
<h3 class="mt-3">Database Stats</h3>
|
|
<table class="table table-sm table-bordered">
|
|
<tbody>
|
|
<?php foreach ($databaseStats as $stat): ?>
|
|
<tr>
|
|
<td><?= htmlspecialchars($stat['name']); ?></td>
|
|
<td colspan="2"><?= htmlspecialchars($stat['value']); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
|
|
<!-- Table Stats Table -->
|
|
<h3 class="mt-3">Table Stats</h3>
|
|
<table class="table table-sm table-bordered">
|
|
<thead>
|
|
<tr>
|
|
<th>Table Name</th>
|
|
<th>Fields / Rows</th>
|
|
<th>Size (MB)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($tableDetails as $table): ?>
|
|
<tr>
|
|
<td><?= htmlspecialchars($table['name']); ?></td>
|
|
<td><?= htmlspecialchars("Fields: {$table['fields']}, Rows: {$table['rows']}"); ?></td>
|
|
<td><?= htmlspecialchars($table['size'] . ' MB'); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<?php
|
|
|
|
require_once "includes/footer.php";
|
|
|