/dev/null'); if ($result === null) return 'unknown'; return ($result !== '') ? 'ok' : 'missing'; } // --------------------------------------------------------------------------- // Constants // --------------------------------------------------------------------------- define('CHECK_BASE', __DIR__); define('PANEL_VERSION_MIN', '8.3.0'); // --------------------------------------------------------------------------- // Run all checks and collect rows // --------------------------------------------------------------------------- $rows = []; // ── PHP version ───────────────────────────────────────────────────────────── $php_ver = PHP_VERSION; $php_ok = version_compare($php_ver, PANEL_VERSION_MIN, '>='); $rows[] = [ 'section' => 'PHP Runtime', 'name' => 'PHP Version', 'status' => $php_ok ? 'ok' : 'warning', 'current' => $php_ver, 'fix' => $php_ok ? '' : 'sudo apt install php8.3 libapache2-mod-php8.3 -y', 'notes' => 'Minimum recommended: PHP ' . PANEL_VERSION_MIN, ]; // ── Required PHP extensions ────────────────────────────────────────────────── $required_exts = [ 'mysqli' => 'Database connectivity', 'curl' => 'Remote HTTP requests', 'gd' => 'Image processing', 'mbstring' => 'Multi-byte string handling', 'zip' => 'Archive extraction', 'xml' => 'XML parsing (game configs)', 'json' => 'JSON encoding/decoding', 'openssl' => 'Encrypted connections', 'fileinfo' => 'MIME type detection', 'session' => 'Session management', ]; foreach ($required_exts as $ext => $desc) { $loaded = extension_loaded($ext); $rows[] = [ 'section' => 'PHP Extensions', 'name' => 'ext/' . $ext, 'status' => $loaded ? 'ok' : 'missing', 'current' => $loaded ? 'Loaded' : 'Not loaded', 'fix' => $loaded ? '' : 'sudo apt install php8.3-' . $ext . ' -y', 'notes' => $desc, ]; } // xmlrpc is packaged separately on modern Debian/Ubuntu so check it alone. $xmlrpc_loaded = extension_loaded('xmlrpc'); $rows[] = [ 'section' => 'PHP Extensions', 'name' => 'ext/xmlrpc', 'status' => $xmlrpc_loaded ? 'ok' : 'warning', 'current' => $xmlrpc_loaded ? 'Loaded' : 'Not loaded', 'fix' => $xmlrpc_loaded ? '' : 'sudo apt install php8.3-xmlrpc -y', 'notes' => 'Required for agent communication. May need separate package on PHP 8+.', ]; // ── PEAR ───────────────────────────────────────────────────────────────────── $pear_path = stream_resolve_include_path('PEAR.php'); $rows[] = [ 'section' => 'PHP Libraries', 'name' => 'PEAR', 'status' => $pear_path !== false ? 'ok' : 'warning', 'current' => $pear_path !== false ? $pear_path : 'Not found', 'fix' => $pear_path !== false ? '' : 'sudo apt install php-pear -y', 'notes' => 'Used by some legacy OGP/GSP modules.', ]; // ── Writable / readable paths ──────────────────────────────────────────────── // Paths marked 'required_writable' will show as 'error' (not just 'warning') // when they are not writable, because the installer WILL crash without them. $paths_to_check = [ 'includes/' => ['note' => 'Config directory (must be writable at install time)', 'required_writable' => true], 'modules/' => ['note' => 'Modules directory', 'required_writable' => false], 'upload/' => ['note' => 'Upload directory (optional)', 'required_writable' => false, 'optional' => true], 'cache/' => ['note' => 'Cache directory (optional)', 'required_writable' => false, 'optional' => true], 'log/' => ['note' => 'Log directory (optional)', 'required_writable' => false, 'optional' => true], 'temp/' => ['note' => 'Temp directory (optional)', 'required_writable' => false, 'optional' => true], 'includes/config.inc.php' => ['note' => 'Panel config file (must be writable at install time)', 'required_writable' => true], ]; foreach ($paths_to_check as $rel => $meta) { $note = $meta['note']; $required_writable = $meta['required_writable']; $optional = $meta['optional'] ?? false; $abs = CHECK_BASE . '/' . $rel; if (!file_exists($abs)) { // For required-writable files that don't exist yet, the parent directory // must be writable. Flag as error only if the parent dir is also not writable. if ($required_writable && !is_dir($abs)) { $parent_writable = is_writable(dirname($abs)); $not_exist_status = $parent_writable ? 'warning' : 'error'; } else { $not_exist_status = $optional ? 'warning' : 'missing'; } $rows[] = [ 'section' => 'Filesystem', 'name' => $rel, 'status' => $not_exist_status, 'current' => 'Does not exist', 'fix' => is_dir(dirname($abs)) ? 'sudo touch ' . escapeshellarg($rel) . ' && sudo chmod 664 ' . escapeshellarg($rel) . ' && sudo chown www-data:www-data ' . escapeshellarg($rel) : 'sudo mkdir -p ' . escapeshellarg(rtrim($rel, '/')) . ' && sudo chown -R www-data:www-data ' . escapeshellarg(rtrim($rel, '/')), 'notes' => $note . ($optional ? ' (optional)' : ''), ]; continue; } $is_dir = is_dir($abs); $readable = is_readable($abs); $writable = is_writable($abs); if ($is_dir) { $status = ($readable && $writable) ? 'ok' : ($required_writable ? 'error' : 'warning'); $cur = 'Exists — readable: ' . ($readable ? 'yes' : 'no') . ', writable: ' . ($writable ? 'yes' : 'no'); $fix = (!$writable) ? 'sudo chmod -R 775 ' . escapeshellarg($rel) . ' && sudo chown -R www-data:www-data ' . escapeshellarg($rel) : ''; } else { // It's a file $status = ($readable && $writable) ? 'ok' : ($required_writable ? 'error' : 'warning'); $cur = 'Exists — readable: ' . ($readable ? 'yes' : 'no') . ', writable: ' . ($writable ? 'yes' : 'no'); $fix = (!$writable) ? 'sudo chmod 664 ' . escapeshellarg($rel) . ' && sudo chown www-data:www-data ' . escapeshellarg($rel) : ''; } $rows[] = [ 'section' => 'Filesystem', 'name' => $rel, 'status' => $status, 'current' => $cur, 'fix' => $fix, 'notes' => $note, ]; } // ── Linux commands ─────────────────────────────────────────────────────────── $commands = ['unzip', 'tar', 'screen', 'sudo', 'subversion', 'git', 'rsync', 'mysql']; $shell_available = function_exists('shell_exec'); foreach ($commands as $cmd) { $status_str = check_command($cmd); if (!$shell_available) { $status_str = 'unknown'; $cur = 'shell_exec disabled'; $fix = 'Enable shell_exec in php.ini'; } else { $cur = $status_str === 'ok' ? safe_shell('command -v ' . escapeshellarg($cmd) . ' 2>/dev/null') ?? $cmd : 'Not found in PATH'; $fix = ($status_str === 'missing') ? 'sudo apt install ' . escapeshellarg($cmd) . ' -y' : ''; } $rows[] = [ 'section' => 'Linux Commands', 'name' => $cmd, 'status' => $status_str, 'current' => $cur, 'fix' => $fix, 'notes' => 'Required for game server management', ]; } // ── Apache modules ─────────────────────────────────────────────────────────── if (function_exists('apache_get_modules')) { $apache_mods = apache_get_modules(); $rewrite_loaded = in_array('mod_rewrite', $apache_mods, true); $rows[] = [ 'section' => 'Apache', 'name' => 'mod_rewrite', 'status' => $rewrite_loaded ? 'ok' : 'warning', 'current' => $rewrite_loaded ? 'Enabled' : 'Not enabled', 'fix' => $rewrite_loaded ? '' : "sudo a2enmod rewrite\nsudo systemctl restart apache2", 'notes' => 'Required for clean panel URLs', ]; } else { $rows[] = [ 'section' => 'Apache', 'name' => 'mod_rewrite', 'status' => 'unknown', 'current' => 'apache_get_modules() unavailable (CGI/FPM mode or non-Apache?)', 'fix' => "sudo a2enmod rewrite\nsudo systemctl restart apache2", 'notes' => 'Required for clean panel URLs. Verify manually if not using mod_php.', ]; } // ── Optional DB connectivity test ──────────────────────────────────────────── $config_path = CHECK_BASE . '/includes/config.inc.php'; if (is_readable($config_path)) { // Extract credentials using regex instead of executing the config file, // to avoid running arbitrary PHP code from the config. $raw = file_get_contents($config_path); $cfg = []; foreach (['db_host', 'db_port', 'db_user', 'db_pass', 'db_name'] as $var) { if ($raw !== false && preg_match('/\$' . $var . '\s*=\s*"([^"]*)"/', $raw, $m)) { $cfg[$var] = $m[1]; } } $db_host_cfg = $cfg['db_host'] ?? null; $db_user_cfg = $cfg['db_user'] ?? null; $db_pass_cfg = $cfg['db_pass'] ?? null; $db_name_cfg = $cfg['db_name'] ?? null; $db_port_cfg = isset($cfg['db_port']) ? (int)$cfg['db_port'] : 3306; if ($db_host_cfg !== null && $db_user_cfg !== null && $db_name_cfg !== null) { $conn = @mysqli_connect($db_host_cfg, $db_user_cfg, $db_pass_cfg ?? '', $db_name_cfg, $db_port_cfg); if ($conn) { $db_status = 'ok'; $db_current = 'Connected to ' . $db_host_cfg . ':' . $db_port_cfg . ' / ' . $db_name_cfg; $db_fix = ''; mysqli_close($conn); } else { $db_status = 'warning'; $db_current = 'Connection failed — ' . (mysqli_connect_error() ?? 'unknown error'); $db_fix = 'Check credentials in includes/config.inc.php'; } $rows[] = [ 'section' => 'Database', 'name' => 'MySQL connection', 'status' => $db_status, 'current' => $db_current, 'fix' => $db_fix, 'notes' => 'Host: ' . $db_host_cfg . ' | Port: ' . $db_port_cfg . ' | DB: ' . $db_name_cfg . ' | User: ' . $db_user_cfg, ]; } else { $rows[] = [ 'section' => 'Database', 'name' => 'MySQL connection', 'status' => 'warning', 'current' => 'config.inc.php present but incomplete (missing host/user/db)', 'fix' => 'Run the installer at install.php', 'notes' => 'Cannot test connection without full credentials', ]; } } else { $rows[] = [ 'section' => 'Database', 'name' => 'MySQL connection', 'status' => 'warning', 'current' => 'config.inc.php not found or not readable — not yet installed', 'fix' => 'Run the installer at install.php', 'notes' => 'This is normal before first install', ]; } // --------------------------------------------------------------------------- // Summary counts // --------------------------------------------------------------------------- $count_ok = 0; $count_warning = 0; $count_error = 0; $count_missing = 0; $count_unknown = 0; foreach ($rows as $r) { switch ($r['status']) { case 'ok': $count_ok++; break; case 'warning': $count_warning++; break; case 'error': $count_error++; break; case 'missing': $count_missing++; break; default: $count_unknown++; break; } } // --------------------------------------------------------------------------- // Render HTML // --------------------------------------------------------------------------- ?>
This page checks the server environment for GSP panel compatibility.
Items marked Warning or Missing are non-blocking.
Items marked Error (e.g. unwritable includes/ directory) will cause
the installer to crash — fix those before running
install.php.
| Name | Status | Current Value | Recommended Fix | Notes |
|---|---|---|---|---|
| = h($row['section']) ?> | ||||
= h($row['name']) ?> |
= h($row['status']) ?> | = h($row['current']) ?> |
= h($row['fix']) ?> = h($row['fix']) ?>
—
|
= h($row['notes']) ?> |
| One-liner to install all recommended packages |
|---|
= h(
'sudo apt update
sudo apt install apache2 mysql-client unzip tar screen sudo subversion git rsync \
php8.3 php8.3-mysql php8.3-gd php8.3-curl php8.3-mbstring php8.3-zip \
php8.3-xml php8.3-xmlrpc php-pear libapache2-mod-php8.3 -y
sudo a2enmod rewrite
sudo systemctl restart apache2'
) ?> |