From c488e89a45c46067a273b2258e90f5ae139cfbaa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Apr 2026 20:36:43 +0000 Subject: [PATCH 1/2] feat: add check.php, reinstall support, DB backup, and install.php.bak logic Agent-Logs-Url: https://github.com/GameServerPanel/GSP/sessions/d2560591-832a-44dc-bd98-baf5c3e26cd5 Co-authored-by: iaretechnician <2749183+iaretechnician@users.noreply.github.com> --- INSTALL_README.md | 187 ++++++++++++++++ check.php | 475 ++++++++++++++++++++++++++++++++++++++++ includes/config.inc.php | 1 + install.php | 172 +++++++++++++++ 4 files changed, 835 insertions(+) create mode 100644 INSTALL_README.md create mode 100644 check.php diff --git a/INSTALL_README.md b/INSTALL_README.md new file mode 100644 index 00000000..ad262848 --- /dev/null +++ b/INSTALL_README.md @@ -0,0 +1,187 @@ +# GSP / WDS Panel — Installer Guide + +> **GSP is a heavily customized fork of OGP maintained by WDS.** + +--- + +## 1. Quick Install + +### 1.1 Install Ubuntu 24.04 dependencies + +```bash +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 +``` + +### 1.2 Set file permissions + +```bash +sudo chown -R www-data:www-data /var/www/html/gsp +sudo chmod -R 755 /var/www/html/gsp +sudo chmod 664 /var/www/html/gsp/includes/config.inc.php +``` + +### 1.3 Create database + +```sql +CREATE DATABASE panel CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +CREATE USER 'localuser'@'localhost' IDENTIFIED BY 'your_password'; +GRANT ALL PRIVILEGES ON panel.* TO 'localuser'@'localhost'; +FLUSH PRIVILEGES; +``` + +### 1.4 Run the installer + +1. Open `http://your-server/check.php` — review dependency status (no hard blockers). +2. Open `http://your-server/install.php` — follow the wizard. +3. Fill in database credentials (host, port, name, user, password, table prefix). +4. Default table prefix: `gsp_` +5. Click **Next** to install. + +--- + +## 2. Dependency Check (`check.php`) + +`check.php` is a standalone page that checks your server environment **before or after install**. It never blocks installation and can be loaded at any time. + +Checks include: + +| Category | What's checked | +|---|---| +| PHP Runtime | PHP version (≥ 8.3 recommended) | +| PHP Extensions | mysqli, curl, gd, mbstring, zip, xml, json, openssl, fileinfo, session, xmlrpc | +| PHP Libraries | PEAR | +| Filesystem | Writable paths (includes/, modules/, upload/, cache/, log/, temp/) | +| Linux Commands | unzip, tar, screen, sudo, subversion, git, rsync, mysql | +| Apache | mod_rewrite | +| Database | Optional live connectivity test if config.inc.php exists | + +**Statuses:** +- ✅ **OK** — Requirement satisfied +- ⚠ **Warning** — Missing but non-fatal; installation can proceed +- ❌ **Missing** — Extension or binary not found +- ❓ **Unknown** — Cannot be determined (e.g. shell_exec disabled) + +--- + +## 3. Installer Form Fields + +| Field | Default | Description | +|---|---|---| +| Database Host | `localhost` | MySQL hostname or IP | +| Database Port | `3306` | MySQL TCP port | +| Database Name | _(empty)_ | Target database name | +| Database User | _(empty)_ | MySQL username | +| Database Password | _(empty)_ | MySQL password | +| Table Prefix | `gsp_` | Prefix for all panel tables | + +**Generated `includes/config.inc.php`:** + +```php +$db_host="HOST"; +$db_port="3306"; +$db_user="USER"; +$db_pass="PASSWORD"; +$db_name="DATABASE"; +$table_prefix="gsp_"; +$db_type="mysql"; +``` + +--- + +## 4. Reinstall Flow + +If you need to reinstall the panel (e.g. after a migration or reset): + +1. Restore the full installer: + ```bash + cp install.php.bak install.php + ``` + _Or_ open `install.php` in your browser — it will show a **Restore & Re-run Installer** button. + +2. Navigate to `http://your-server/install.php` and follow the wizard again. + +3. The installer will detect an existing database, back it up, then reinstall cleanly. + +--- + +## 5. Backup Behavior + +When the installer detects **existing tables** in the target database, it: + +1. Displays a warning: _"Existing database detected. A backup will be created before reinstall."_ +2. Creates a backup database named `panel_BAK`. + - If `panel_BAK` already exists, a timestamped name is used: `panel_BAK_YYYYMMDD_HHMMSS`. +3. Copies schema + data for every table into the backup database. +4. Drops all tables from the target database. +5. Proceeds with a fresh install. + +**To restore from backup:** + +```sql +-- Example restore of a single table +INSERT INTO panel.gsp_users SELECT * FROM panel_BAK.gsp_users; + +-- Or restore the full backup DB +mysqldump panel_BAK | mysql panel +``` + +--- + +## 6. Post-Install Security + +After installation completes: + +- `install.php` is automatically replaced with a **stub page** (the full installer is saved as `install.php.bak`). +- The stub prevents accidental re-runs and offers an admin action to restore the installer. +- **Change the default admin password immediately** — default credentials are `admin` / `admin`. +- Secure `includes/config.inc.php`: + ```bash + sudo chmod 640 includes/config.inc.php + sudo chown www-data:www-data includes/config.inc.php + ``` + +--- + +## 7. Table Prefix Migration (ogp_ → gsp_) + +If you are migrating from an older OGP installation: + +- The installer automatically renames `ogp_*` tables to `gsp_*` (or your chosen prefix) when they don't already exist. +- Tables that already exist under the new prefix are skipped safely. +- You can choose a custom prefix (e.g. `mypanel_`) in the installer form. + +**Module SQL files** containing `ogp_` references are dynamically converted to the chosen prefix at import time. + +--- + +## 8. Modules + +All modules found in the `modules/` directory are automatically detected and installed. Module SQL files are imported with dynamic prefix substitution. + +- `modulemanager` is installed first (prerequisite for all other modules). +- Prerequisite failures are treated as warnings, not hard errors. + +--- + +## 9. Rollback + +| Scenario | Action | +|---|---| +| Bad install, want fresh start | Restore DB from `panel_BAK`, restore installer via `cp install.php.bak install.php`, re-run | +| Config broken | Edit `includes/config.inc.php` manually or re-run installer | +| Installer stub needs removal | `cp install.php.bak install.php` | +| Modules failed to install | Re-run installer (it detects existing DB and backs up first) | + +--- + +## 10. Security Notes + +- Passwords are **never printed** in check.php or any installer output. +- All user input is escaped with `htmlspecialchars()` before rendering. +- The `install.php.bak` stub restore action is unprotected — remove `install.php` and `install.php.bak` once you no longer need them. +- The default admin password is stored as MD5 to match the legacy panel login system. Change it immediately. diff --git a/check.php b/check.php new file mode 100644 index 00000000..61da8ec2 --- /dev/null +++ b/check.php @@ -0,0 +1,475 @@ +/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 ? h($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_to_check = [ + 'includes/' => 'Config directory (must be writable at install time)', + 'modules/' => 'Modules directory', + 'upload/' => 'Upload directory (optional)', + 'cache/' => 'Cache directory (optional)', + 'log/' => 'Log directory (optional)', + 'temp/' => 'Temp directory (optional)', + 'includes/config.inc.php' => 'Panel config file (writable at install time)', +]; + +foreach ($paths_to_check as $rel => $note) { + $abs = CHECK_BASE . '/' . $rel; + $optional = in_array($rel, ['upload/', 'cache/', 'log/', 'temp/'], true); + + if (!file_exists($abs)) { + $rows[] = [ + 'section' => 'Filesystem', + 'name' => $rel, + 'status' => $optional ? 'warning' : 'warning', + 'current' => 'Does not exist', + 'fix' => 'mkdir -p ' . escapeshellarg($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' : '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' : 'warning'; + $cur = 'Exists — readable: ' . ($readable ? 'yes' : 'no') . ', writable: ' . ($writable ? 'yes' : 'no'); + $fix = (!$writable) ? 'sudo chmod 664 ' . 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 only the variables we need without executing arbitrary code. + // We use a limited include inside an isolated function scope. + $db_host = $db_port = $db_user = $db_pass = $db_name = null; + (static function () use ($config_path, &$db_host, &$db_port, &$db_user, &$db_pass, &$db_name): void { + @include $config_path; + })(); + + if ($db_host !== null && $db_user !== null && $db_name !== null) { + $db_port_int = (int)($db_port ?? 3306); + $conn = @mysqli_connect($db_host, $db_user, $db_pass ?? '', $db_name, $db_port_int); + if ($conn) { + $db_status = 'ok'; + $db_current = 'Connected to ' . h($db_host) . ':' . $db_port_int . ' / ' . h($db_name); + $db_fix = ''; + mysqli_close($conn); + } else { + $db_status = 'warning'; + $db_current = 'Connection failed — ' . h(mysqli_connect_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: ' . h($db_host) . ' | Port: ' . $db_port_int . ' | DB: ' . h($db_name) . ' | User: ' . h($db_user ?? ''), + ]; + } 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_missing = 0; +$count_unknown = 0; + +foreach ($rows as $r) { + switch ($r['status']) { + case 'ok': $count_ok++; break; + case 'warning': $count_warning++; break; + case 'missing': $count_missing++; break; + default: $count_unknown++; break; + } +} + +// --------------------------------------------------------------------------- +// Render HTML +// --------------------------------------------------------------------------- +?> + + +
+ + +This page checks the server environment for GSP panel compatibility. + No dependency is a hard blocker — missing items appear as warnings only. + The installer at install.php can proceed regardless.
+| Name | +Status | +Current Value | +Recommended Fix | +Notes | +
|---|---|---|---|---|
| = h($row['section']) ?> | +||||
= h($row['name']) ?> |
+ + + = h($row['status']) ?> + + | += $row['current'] /* already escaped where built */ ?> | +
+
+
+ = 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' + ) ?> |
Welcome to the GSP (Game Server Panel) installer, maintained by WDS.
"; + echo ""; echo "GSP is a heavily customized fork of OGP. This installer will:
"; echo "includes/config.inc.php with your database credentials.ogp_ tables to your chosen prefix.modules/ directory.| \n"; + echo ""; echo " | -= $row['current'] /* already escaped where built */ ?> | += h($row['current']) ?> | @@ -469,7 +478,7 @@ sudo systemctl restart apache2' |