Agent-Logs-Url: https://github.com/GameServerPanel/GSP/sessions/73ed1a44-9f9b-44d6-995a-706993bdef21 Co-authored-by: iaretechnician <2749183+iaretechnician@users.noreply.github.com>
604 lines
25 KiB
PHP
604 lines
25 KiB
PHP
<?php
|
||
/*
|
||
*
|
||
* GSP - Game Server Panel (WDS)
|
||
* Copyright (C) 2008 - 2018 The OGP Development Team
|
||
* GSP customizations (C) WDS / GameServerPanel
|
||
*
|
||
* GSP is a heavily customized fork of OGP maintained by WDS.
|
||
* https://github.com/GameServerPanel/GSP
|
||
*
|
||
* This program is free software; you can redistribute it and/or
|
||
* modify it under the terms of the GNU General Public License
|
||
* as published by the Free Software Foundation; either version 2
|
||
* of the License, or any later version.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
*/
|
||
|
||
error_reporting(E_ALL);
|
||
$_GET['action'] = true;
|
||
define("MODULES", "modules/");
|
||
|
||
// Strip Input Function, prevents HTML in unwanted places
|
||
function stripinput($text) {
|
||
$search = array("\"", "'", "\\", '\"', "\'", "<", ">", " ");
|
||
$replace = array(""", "'", "\", """, "'", "<", ">", " ");
|
||
$text = str_replace($search, $replace, $text);
|
||
return $text;
|
||
}
|
||
|
||
session_start();
|
||
|
||
if (!isset($_SESSION['users_lang']))
|
||
$_SESSION['users_lang'] = "English";
|
||
|
||
if (isset($_GET['localeset']))
|
||
$_SESSION['users_lang'] = $_GET['localeset'];
|
||
|
||
require_once("includes/helpers.php");
|
||
require_once("includes/view.php");
|
||
require_once("includes/lang.php");
|
||
require_once("includes/html_functions.php");
|
||
require_once("includes/functions.php");
|
||
ogpLang();
|
||
|
||
$view = new OGPView();
|
||
$view->setCharset(get_lang('lang_charset'));
|
||
|
||
?>
|
||
<style>
|
||
body { background-image: url("images/bg.png"); }
|
||
#install-content {
|
||
width: 650px;
|
||
margin: 0 auto;
|
||
margin-top: 30px;
|
||
padding: 0px 15px;
|
||
background-color: #FFF;
|
||
border-radius: 9px;
|
||
-moz-border-radius: 9px;
|
||
border: 1px solid #C8C8C8;
|
||
overflow: hidden;
|
||
}
|
||
#install-title {
|
||
width: 680px;
|
||
height: 30px;
|
||
background: #f5f5f5;
|
||
border-top: 1px solid #cfcfcf;
|
||
border-bottom: 1px solid #cfcfcf;
|
||
margin-bottom: 5px;
|
||
margin-top: -1px;
|
||
margin-left: -18px;
|
||
margin-right: -15px;
|
||
padding-top: 5px;
|
||
font-size: 20px;
|
||
text-align: center;
|
||
color: #000;
|
||
font-family: "Trebuchet MS";
|
||
}
|
||
.lang { width: 100%; text-align: center; margin-left: auto; margin-right: auto; }
|
||
li { list-style-type: square; }
|
||
</style>
|
||
<!--[if IE]>
|
||
<style>
|
||
#install-content { text-align: center; width: 100%; }
|
||
#install-title { width: 100%; background: #FFF; border: none; }
|
||
</style>
|
||
<![endif]-->
|
||
<div id="install-content">
|
||
<?php
|
||
install();
|
||
|
||
function install() {
|
||
global $db;
|
||
$step = (isset($_REQUEST['step']) ? $_REQUEST['step'] : "0");
|
||
|
||
// ----------------------------------------------------------------
|
||
// Step 0 – Language selection + welcome (no prerequisite checks)
|
||
// ----------------------------------------------------------------
|
||
if ($step == "0") {
|
||
$locale_files = makefilelist("lang/", ".|..|.svn", true, "folders");
|
||
$columns = 3;
|
||
$width = round(100 / $columns);
|
||
|
||
echo "<div id=\"install-title\" style=\"margin-top:-4px;\">".get_lang('install_lang')."</div>";
|
||
echo "<table class='lang' style='margin-bottom:10px;'>\n<tr>";
|
||
$counter = 0;
|
||
for ($i = 0; $i < count($locale_files); $i++) {
|
||
if ($counter != 0 && ($counter % $columns == 0)) echo "</tr>\n<tr>\n";
|
||
echo "<td style='width:".$width."%'>";
|
||
if ($locale_files[$i] == $_SESSION['users_lang'])
|
||
echo "<li><b>".$locale_files[$i]."</b></li>";
|
||
else
|
||
echo "<li><a href='?localeset=".htmlspecialchars($locale_files[$i])."'>".htmlspecialchars($locale_files[$i])."</a></li>";
|
||
echo "</td>\n";
|
||
$counter++;
|
||
}
|
||
echo "</tr>\n</table>\n";
|
||
|
||
echo "<div id=\"install-title\">GSP / WDS Panel Installer</div>";
|
||
echo "<p>Welcome to the <strong>GSP (Game Server Panel)</strong> installer, maintained by WDS.</p>";
|
||
echo "<p style='margin:8px 0;'><a href='check.php' style='background:#1565c0;color:#fff;padding:6px 14px;border-radius:5px;text-decoration:none;font-weight:bold;'>🔍 Run Dependency Check</a></p>";
|
||
echo "<p>GSP is a heavily customized fork of OGP. This installer will:</p>";
|
||
echo "<ul>
|
||
<li>Write <code>includes/config.inc.php</code> with your database credentials.</li>
|
||
<li>Back up any existing database before reinstalling.</li>
|
||
<li>Optionally migrate any existing <code>ogp_</code> tables to your chosen prefix.</li>
|
||
<li>Install all modules found in the <code>modules/</code> directory.</li>
|
||
<li>Create a default admin account (<em>admin / admin</em>) if none exists.</li>
|
||
</ul>";
|
||
echo "<p><a href='?step=1'>".get_lang('next')."</a></p>";
|
||
echo "</div>\n";
|
||
}
|
||
|
||
// ----------------------------------------------------------------
|
||
// Step 1 – Database settings form
|
||
// ----------------------------------------------------------------
|
||
elseif ($step == "1") {
|
||
if (is_readable('includes/config.inc.php'))
|
||
require_once "includes/config.inc.php";
|
||
|
||
echo "<table class='install'><tr><td>\n";
|
||
echo "<p style='margin-bottom:10px;'><a href='check.php' style='background:#1565c0;color:#fff;padding:5px 12px;border-radius:5px;text-decoration:none;font-weight:bold;'>🔍 Run Dependency Check</a></p>";
|
||
echo "<form name='setup' method='post' action='?step=2'>";
|
||
echo "<table class='install'>\n";
|
||
echo "<tr><td colspan='2'><div id=\"install-title\" style=\"margin-left:-21px; margin-top:-7px;\">".get_lang('database_settings')."</div></td></tr>";
|
||
echo "<tr><td>".get_lang('database_type').":</td><td>MySQL</td></tr>";
|
||
|
||
// Host
|
||
$OS = strtoupper(substr(PHP_OS, 0, 3));
|
||
$default_host = ($OS === 'WIN' || $OS === 'CYG') ? "127.0.0.1" : "localhost";
|
||
echo "<tr><td>".get_lang('database_hostname').":</td>
|
||
<td><input type='text' value='".htmlspecialchars(isset($db_host) ? $db_host : $default_host)."' name='db_host' class='textbox' /></td></tr>";
|
||
|
||
// Port (GSP addition – no lang key needed; label is always in English for installer)
|
||
echo "<tr><td>Database Port:</td>
|
||
<td><input type='text' value='".htmlspecialchars(isset($db_port) ? $db_port : "3306")."' name='db_port' class='textbox' /></td></tr>";
|
||
|
||
// User
|
||
echo "<tr><td>".get_lang('database_username').":</td>
|
||
<td><input type='text' value='".htmlspecialchars(isset($db_user) ? $db_user : "")."' name='db_user' class='textbox' /></td></tr>";
|
||
|
||
// Password
|
||
echo "<tr><td>".get_lang('database_password').":</td>
|
||
<td><input type='password' value='".htmlspecialchars(isset($db_pass) ? $db_pass : "")."' name='db_pass' class='textbox' /></td></tr>";
|
||
|
||
// Name
|
||
echo "<tr><td>".get_lang('database_name').":</td>
|
||
<td><input type='text' value='".htmlspecialchars(isset($db_name) ? $db_name : "")."' name='db_name' class='textbox' /></td></tr>";
|
||
|
||
// Prefix – default gsp_
|
||
echo "<tr><td>".get_lang('database_prefix').":</td>
|
||
<td><input type='text' value='".htmlspecialchars(isset($table_prefix) ? $table_prefix : "gsp_")."' name='table_prefix' class='textbox' /></td></tr>";
|
||
|
||
echo "</table>\n";
|
||
echo "<p><input type='submit' name='next' value='".get_lang('next')."' class='button' /></p></form>";
|
||
echo "<p><a href='?step=0'>".get_lang('back')."</a></p>";
|
||
echo "</td></tr></table>\n";
|
||
}
|
||
|
||
// ----------------------------------------------------------------
|
||
// Step 2 – Write config, migrate tables, install modules, create admin
|
||
// ----------------------------------------------------------------
|
||
elseif ($step == "2") {
|
||
echo "<table class='install'><tr><td>\n";
|
||
|
||
if (!isset($_POST['db_host'])) {
|
||
print_failure("No form data received. Please go back and fill in the database settings.");
|
||
echo "<p><a href='?step=1'>".get_lang('back')."</a></p>";
|
||
echo "</td></tr></table>\n";
|
||
return;
|
||
}
|
||
|
||
$db_host = stripinput($_POST['db_host']);
|
||
$db_port = stripinput($_POST['db_port']);
|
||
$db_user = stripinput($_POST['db_user']);
|
||
$db_pass = stripinput($_POST['db_pass']);
|
||
$db_name = stripinput($_POST['db_name']);
|
||
$table_prefix = stripinput($_POST['table_prefix']);
|
||
$db_type = "mysql";
|
||
|
||
// Default prefix to gsp_ if empty
|
||
if (empty($table_prefix)) $table_prefix = "gsp_";
|
||
// Default port to 3306 if empty
|
||
if (empty($db_port)) $db_port = "3306";
|
||
|
||
// --- Write config.inc.php ---
|
||
$config = "<?php\n".
|
||
"###############################################\n".
|
||
"# Site configuration\n".
|
||
"###############################################\n".
|
||
"\$db_host=\"".addslashes($db_host)."\";\n".
|
||
"\$db_port=\"".addslashes($db_port)."\";\n".
|
||
"\$db_user=\"".addslashes($db_user)."\";\n".
|
||
"\$db_pass=\"".addslashes($db_pass)."\";\n".
|
||
"\$db_name=\"".addslashes($db_name)."\";\n".
|
||
"\$table_prefix=\"".addslashes($table_prefix)."\";\n".
|
||
"\$db_type=\"".$db_type."\";\n".
|
||
"?>";
|
||
|
||
$temp = fopen("includes/config.inc.php", "w");
|
||
if ($temp === false) {
|
||
print_failure(get_lang('unable_to_write_config') .
|
||
" — <code>includes/config.inc.php</code> could not be opened for writing. " .
|
||
"Please run: <code>sudo chmod 664 includes/config.inc.php && sudo chown www-data:www-data includes/config.inc.php</code> " .
|
||
"(or <code>sudo chmod -R 775 includes/ && sudo chown -R www-data:www-data includes/</code> if the file does not yet exist). " .
|
||
"You can also use the <a href='check.php'>Dependency Check</a> page for a full diagnostics report.");
|
||
echo "<p><a href='?step=1'>".get_lang('back')."</a></p>";
|
||
echo "</td></tr></table>\n";
|
||
return;
|
||
}
|
||
if (fwrite($temp, $config) === false) {
|
||
print_failure(get_lang('unable_to_write_config'));
|
||
echo "<p><a href='?step=1'>".get_lang('back')."</a></p>";
|
||
fclose($temp);
|
||
echo "</td></tr></table>\n";
|
||
return;
|
||
}
|
||
fclose($temp);
|
||
print_success(get_lang('config_written'));
|
||
|
||
// --- Connect to database using port ---
|
||
$db = createDatabaseConnection($db_type, $db_host, $db_user, $db_pass, $db_name, $table_prefix, (int)$db_port);
|
||
$error_text = "";
|
||
if (get_db_error_text($db, $error_text)) {
|
||
print_failure($error_text);
|
||
echo "<p><a href='?step=1'>".get_lang('back')."</a></p>";
|
||
echo "</td></tr></table>\n";
|
||
return;
|
||
}
|
||
|
||
// --- Detect existing database and back it up before reinstall ---
|
||
gsp_backup_existing_db($db, $db_host, $db_user, $db_pass, $db_name, $db_port);
|
||
|
||
// --- Optional ogp_ → gsp_ migration ---
|
||
gsp_migrate_tables($db, $table_prefix);
|
||
|
||
// --- Create base module management tables ---
|
||
$db->query("DROP TABLE IF EXISTS `".$table_prefix."modules`");
|
||
$db->query("CREATE TABLE IF NOT EXISTS `".$table_prefix."modules` (
|
||
`id` smallint(5) unsigned NOT NULL auto_increment,
|
||
`title` varchar(100) NOT NULL default '',
|
||
`folder` varchar(100) NOT NULL default '',
|
||
`version` varchar(10) NOT NULL default '0',
|
||
`db_version` int(10) NOT NULL default '0',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `folder` (`folder`)
|
||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;");
|
||
|
||
$db->query("DROP TABLE IF EXISTS `".$table_prefix."module_menus`");
|
||
$db->query("CREATE TABLE IF NOT EXISTS `".$table_prefix."module_menus` (
|
||
`module_id` int(11) NOT NULL COMMENT 'This references to modules.id',
|
||
`subpage` varchar(64) NOT NULL default '',
|
||
`group` varchar(32) NOT NULL,
|
||
`menu_name` varchar(128) NOT NULL,
|
||
`pos` INT UNSIGNED NOT NULL,
|
||
PRIMARY KEY (`module_id`, `subpage`, `group`)
|
||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;");
|
||
|
||
// --- Install all modules ---
|
||
require_once("modules/modulemanager/module_handling.php");
|
||
@add_lang_module('modulemanager');
|
||
$modules = list_available_modules();
|
||
|
||
// Install modulemanager first
|
||
if (in_array('modulemanager', $modules)) {
|
||
gsp_install_module($db, 'modulemanager');
|
||
}
|
||
|
||
foreach ($modules as $module) {
|
||
if ($module == 'modulemanager') continue;
|
||
gsp_install_module($db, $module);
|
||
}
|
||
print_success(get_lang('database_created'));
|
||
|
||
// --- Default site settings ---
|
||
$site_settings = array(
|
||
"title" => "GSP - Game Server Panel",
|
||
"slogan" => get_lang('slogan'),
|
||
"ogp_version" => "0",
|
||
"version_type" => "GSP",
|
||
"theme" => "Revolution",
|
||
"welcome_title" => "1",
|
||
"welcome_title_message"=> "<h0>".get_lang('default_welcome_title_message')."</h0>",
|
||
"page_auto_refresh" => "1",
|
||
);
|
||
$db->setSettings($site_settings);
|
||
|
||
// --- Auto-create default admin user ---
|
||
// NOTE: The default password 'admin' is intentionally weak for first-boot convenience.
|
||
// The installer prominently warns the operator to change it. Passwords are stored as
|
||
// MD5 to match the existing panel login system (legacy behaviour).
|
||
$existing_admin = $db->getUser('admin');
|
||
if (!$existing_admin) {
|
||
$db->addUser('admin', 'admin', 'admin', 'admin@localhost');
|
||
print_success("Default admin account created (username: <strong>admin</strong>).");
|
||
} else {
|
||
echo "<p class='note'>Admin user already exists – skipped creation.</p>";
|
||
}
|
||
|
||
// --- Update game configs ---
|
||
updateGameConfigsPostInstall();
|
||
|
||
echo "<p class='note' style='color:#c00; font-weight:bold;'>".get_lang('remove_install_and_secure_config')."</p>";
|
||
echo "<p class='note' style='color:#c00; font-weight:bold;'>SECURITY: The default admin password is <strong>admin</strong>. Change it immediately after your first login at Admin → User Management.</p>";
|
||
echo "<p class='note'><a href='index.php'>".get_lang('go_to_panel')."</a></p>";
|
||
echo "</td></tr></table>\n";
|
||
|
||
// --- Disable the installer by renaming install.php to install.php.bak ---
|
||
gsp_disable_installer();
|
||
echo "</div>\n";
|
||
}
|
||
|
||
else {
|
||
echo "<p>Unknown step. <a href='?step=0'>Start over</a></p>";
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Install a single module, treating prerequisite failures as warnings
|
||
* (not hard failures) per GSP policy: "Do not run prerequisite checks –
|
||
* our environment is customized."
|
||
*
|
||
* Returns the same values as install_module(), but the caller does not
|
||
* abort the overall install when -2 is returned.
|
||
*/
|
||
function gsp_install_module($db, $module) {
|
||
$result = install_module($db, $module, FALSE);
|
||
// -1 = module.php missing or malformed (genuine hard error)
|
||
// -2 = prereq missing or DB query failed; treat as warning
|
||
// 0 = already installed
|
||
// 1 = installed successfully
|
||
// 2 = optional, skipped
|
||
if ($result === -1) {
|
||
// Already printed by install_module(); just note it.
|
||
}
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* Optional ogp_ → configured-prefix migration.
|
||
*
|
||
* Rules:
|
||
* - If a table named ogp_X exists AND the corresponding prefix_X does NOT
|
||
* exist, rename ogp_X -> prefix_X.
|
||
* - If prefix_X already exists, skip that table (never fail).
|
||
* - If no ogp_ tables exist at all, do nothing.
|
||
*/
|
||
function gsp_migrate_tables($db, $table_prefix) {
|
||
if ($table_prefix === 'ogp_') {
|
||
// Already using ogp_ prefix – nothing to migrate.
|
||
return;
|
||
}
|
||
|
||
// Fetch all tables starting with ogp_
|
||
$rows = $db->resultQuery("SHOW TABLES LIKE 'ogp\\_%'");
|
||
if (!$rows || !is_array($rows)) return;
|
||
|
||
$renamed = 0;
|
||
$skipped = 0;
|
||
foreach ($rows as $row) {
|
||
$ogp_table = array_values($row)[0]; // e.g. ogp_users
|
||
$suffix = substr($ogp_table, 4); // strip leading "ogp_"
|
||
$new_table = $table_prefix . $suffix;
|
||
|
||
// Check if destination table already exists
|
||
$exists = $db->resultQuery("SHOW TABLES LIKE '".str_replace("_", "\\_", $new_table)."'");
|
||
if ($exists && is_array($exists) && count($exists) > 0) {
|
||
$skipped++;
|
||
continue;
|
||
}
|
||
|
||
// Rename
|
||
$ok = $db->query("RENAME TABLE `".mysqli_real_escape_string_compat($ogp_table)."` TO `".mysqli_real_escape_string_compat($new_table)."`");
|
||
if ($ok) {
|
||
$renamed++;
|
||
}
|
||
}
|
||
|
||
if ($renamed > 0)
|
||
print_success("Migrated {$renamed} table(s) from <code>ogp_</code> to <code>{$table_prefix}</code> prefix.");
|
||
if ($skipped > 0)
|
||
echo "<p class='note'>{$skipped} table(s) already existed under the <code>{$table_prefix}</code> prefix – skipped.</p>";
|
||
}
|
||
|
||
/**
|
||
* Sanitize a MySQL identifier (table name) for use in RENAME TABLE.
|
||
*
|
||
* Table names sourced from SHOW TABLES consist only of alphanumeric
|
||
* characters and underscores in standard installations. This function
|
||
* enforces that invariant by stripping any other characters, making the
|
||
* identifier safe to embed between backticks in a SQL statement.
|
||
* If a table name ever contained characters outside [a-zA-Z0-9_] it would
|
||
* simply be skipped rather than cause an injection.
|
||
*/
|
||
function mysqli_real_escape_string_compat($identifier) {
|
||
return preg_replace('/[^a-zA-Z0-9_]/', '', $identifier);
|
||
}
|
||
|
||
/**
|
||
* Detect whether the target database already contains tables.
|
||
* If so, create a backup database (panel_BAK or panel_BAK_YYYYMMDD_HHMMSS)
|
||
* by copying schema + data, then drop all tables in the target database so
|
||
* the fresh install proceeds cleanly.
|
||
*
|
||
* The backup is performed entirely through the panel's own DB connection so
|
||
* no external mysqldump binary is required.
|
||
*/
|
||
function gsp_backup_existing_db($db, $db_host, $db_user, $db_pass, $db_name, $db_port) {
|
||
// Count tables in the target database
|
||
$tables_result = $db->resultQuery("SHOW TABLES");
|
||
if (!$tables_result || !is_array($tables_result) || count($tables_result) === 0) {
|
||
// Fresh database – nothing to back up
|
||
return;
|
||
}
|
||
|
||
$table_count = count($tables_result);
|
||
echo "<p class='note' style='color:#b35900;font-weight:bold;'>⚠ Existing database detected (" . htmlspecialchars((string)$table_count, ENT_QUOTES, 'UTF-8') . " table(s)). Creating backup before reinstall…</p>";
|
||
|
||
// Determine backup DB name
|
||
$backup_name = $db_name . '_BAK';
|
||
$check_bak = $db->resultQuery("SHOW DATABASES LIKE '" . mysqli_real_escape_string_compat($backup_name) . "'");
|
||
if ($check_bak && is_array($check_bak) && count($check_bak) > 0) {
|
||
$backup_name = $db_name . '_BAK_' . date('Ymd_His');
|
||
}
|
||
|
||
// Create backup database
|
||
$safe_backup = '`' . mysqli_real_escape_string_compat($backup_name) . '`';
|
||
$safe_src = '`' . mysqli_real_escape_string_compat($db_name) . '`';
|
||
|
||
$created = $db->query("CREATE DATABASE IF NOT EXISTS {$safe_backup} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
|
||
if (!$created) {
|
||
echo "<p class='note' style='color:#900;'>Could not create backup database <code>" . htmlspecialchars($backup_name) . "</code>. Skipping backup (install will continue).</p>";
|
||
return;
|
||
}
|
||
|
||
// Copy each table: CREATE … SELECT
|
||
$copied = 0;
|
||
$failed = 0;
|
||
foreach ($tables_result as $row) {
|
||
$tbl = array_values($row)[0];
|
||
$safe_tbl = '`' . mysqli_real_escape_string_compat($tbl) . '`';
|
||
|
||
// Copy structure
|
||
$ok1 = $db->query("CREATE TABLE {$safe_backup}.{$safe_tbl} LIKE {$safe_src}.{$safe_tbl}");
|
||
// Copy data
|
||
$ok2 = $ok1 && $db->query("INSERT INTO {$safe_backup}.{$safe_tbl} SELECT * FROM {$safe_src}.{$safe_tbl}");
|
||
if ($ok2) {
|
||
$copied++;
|
||
} else {
|
||
$failed++;
|
||
}
|
||
}
|
||
|
||
print_success("Backup created as <code>" . htmlspecialchars($backup_name) . "</code> — {$copied} table(s) copied" . ($failed > 0 ? ", {$failed} failed (non-fatal)" : "") . ".");
|
||
|
||
// Drop all tables in the target database so the fresh install is clean
|
||
$db->query("SET FOREIGN_KEY_CHECKS = 0");
|
||
foreach ($tables_result as $row) {
|
||
$tbl = array_values($row)[0];
|
||
$safe_tbl = '`' . mysqli_real_escape_string_compat($tbl) . '`';
|
||
$db->query("DROP TABLE IF EXISTS {$safe_src}.{$safe_tbl}");
|
||
}
|
||
$db->query("SET FOREIGN_KEY_CHECKS = 1");
|
||
|
||
print_success("Target database cleared. Fresh install will proceed.");
|
||
}
|
||
|
||
/**
|
||
* After a successful install, rename install.php to install.php.bak and write
|
||
* a minimal bootstrap stub as the new install.php that prevents accidental
|
||
* re-runs while giving an admin an easy path to restore the real installer.
|
||
*/
|
||
function gsp_disable_installer() {
|
||
$self = __FILE__;
|
||
$bak_path = dirname($self) . '/install.php.bak';
|
||
|
||
// Read the current file before we rename it
|
||
$installer_content = @file_get_contents($self);
|
||
if ($installer_content === false) {
|
||
echo "<p class='note' style='color:#900;'>Could not read install.php for backup — installer not renamed (non-fatal).</p>";
|
||
return;
|
||
}
|
||
|
||
// Write the backup copy
|
||
if (@file_put_contents($bak_path, $installer_content) === false) {
|
||
echo "<p class='note' style='color:#900;'>Could not write install.php.bak — installer not renamed (non-fatal).</p>";
|
||
return;
|
||
}
|
||
|
||
// Write the stub that replaces install.php
|
||
$stub = <<<'STUB'
|
||
<?php
|
||
/*
|
||
* GSP / WDS — Installer bootstrap stub
|
||
*
|
||
* The full installer has been moved to install.php.bak after a successful
|
||
* installation to prevent accidental re-runs.
|
||
*
|
||
* To restore the installer:
|
||
* cp install.php.bak install.php
|
||
*
|
||
* Or via the button below (admin action — requires a one-time restore token).
|
||
*/
|
||
session_start();
|
||
|
||
// Generate a one-time CSRF token if not already set
|
||
if (empty($_SESSION['gsp_restore_token'])) {
|
||
$_SESSION['gsp_restore_token'] = bin2hex(random_bytes(16));
|
||
}
|
||
|
||
if (isset($_POST['restore_installer'])) {
|
||
// Validate CSRF token
|
||
$submitted = $_POST['gsp_restore_token'] ?? '';
|
||
if (!hash_equals($_SESSION['gsp_restore_token'], $submitted)) {
|
||
http_response_code(403);
|
||
die('<p style="color:red">Invalid or expired restore token. Please reload the page and try again.</p>');
|
||
}
|
||
|
||
$bak = __DIR__ . '/install.php.bak';
|
||
if (!is_readable($bak)) {
|
||
die('<p style="color:red">install.php.bak not found. Restore manually.</p>');
|
||
}
|
||
$content = file_get_contents($bak);
|
||
if ($content === false || file_put_contents(__FILE__, $content) === false) {
|
||
die('<p style="color:red">Could not overwrite install.php. Check file permissions.</p>');
|
||
}
|
||
// Invalidate the token after use
|
||
unset($_SESSION['gsp_restore_token']);
|
||
header('Location: install.php');
|
||
exit;
|
||
}
|
||
|
||
$token = htmlspecialchars($_SESSION['gsp_restore_token'], ENT_QUOTES, 'UTF-8');
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>GSP Installer — Disabled</title>
|
||
<style>
|
||
body { font-family: Arial, sans-serif; background:#1a1a2e; color:#e0e0e0; display:flex; align-items:center; justify-content:center; min-height:100vh; margin:0; }
|
||
.box { background:#12122a; border:1px solid #2a2a5a; border-radius:10px; padding:40px 50px; max-width:480px; text-align:center; }
|
||
h1 { color:#ffd84d; font-size:20px; margin-bottom:12px; }
|
||
p { color:#aaa; font-size:14px; margin:8px 0; }
|
||
code { background:#0d0d22; color:#aaf; padding:2px 8px; border-radius:4px; font-size:13px; }
|
||
.btn { display:inline-block; margin-top:18px; padding:10px 22px; background:#b35900; color:#fff; border:none; border-radius:6px; cursor:pointer; font-size:14px; font-weight:bold; }
|
||
.btn:hover { background:#e07000; }
|
||
.note { color:#888; font-size:12px; margin-top:14px; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="box">
|
||
<h1>⚠ Installer Disabled</h1>
|
||
<p>The GSP installer has been disabled after a successful installation to prevent accidental re-runs.</p>
|
||
<p>The original installer is preserved at <code>install.php.bak</code>.</p>
|
||
<form method="post">
|
||
<input type="hidden" name="gsp_restore_token" value="<?= $token ?>">
|
||
<button type="submit" name="restore_installer" class="btn" onclick="return confirm('Restore the full installer? Only do this if you intend to reinstall the panel.');">↺ Restore & Re-run Installer</button>
|
||
</form>
|
||
<p class="note">
|
||
To restore manually:<br>
|
||
<code>cp install.php.bak install.php</code>
|
||
</p>
|
||
<p class="note"><a href="index.php" style="color:#7aaaf5;">Go to Panel</a></p>
|
||
</div>
|
||
</body>
|
||
</html>
|
||
STUB;
|
||
|
||
if (@file_put_contents($self, $stub) === false) {
|
||
echo "<p class='note' style='color:#900;'>Could not overwrite install.php with stub — installer not disabled (non-fatal). Delete or rename install.php manually.</p>";
|
||
return;
|
||
}
|
||
|
||
print_success("Installer disabled: <code>install.php</code> renamed to stub. Full installer preserved as <code>install.php.bak</code>.");
|
||
echo "<p class='note'>To re-enable the installer, click <em>Restore & Re-run Installer</em> on the new <code>install.php</code> page, or run: <code>cp install.php.bak install.php</code></p>";
|
||
}
|
||
|
||
$view->printView();
|
||
?>
|