", " "); $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')); ?>
".get_lang('install_lang')."
"; echo "\n"; $counter = 0; for ($i = 0; $i < count($locale_files); $i++) { if ($counter != 0 && ($counter % $columns == 0)) echo "\n\n"; echo "\n"; $counter++; } echo "\n
"; if ($locale_files[$i] == $_SESSION['users_lang']) echo "
  • ".$locale_files[$i]."
  • "; else echo "
  • ".htmlspecialchars($locale_files[$i])."
  • "; echo "
    \n"; echo "
    GSP / WDS Panel Installer
    "; echo "

    Welcome to the GSP (Game Server Panel) installer, maintained by WDS.

    "; echo "

    🔍 Run Dependency Check

    "; echo "

    GSP is a heavily customized fork of OGP. This installer will:

    "; echo ""; echo "

    ".get_lang('next')."

    "; echo "\n"; } // ---------------------------------------------------------------- // Step 1 – Database settings form // ---------------------------------------------------------------- elseif ($step == "1") { if (is_readable('includes/config.inc.php')) require_once "includes/config.inc.php"; echo "
    \n"; echo "

    🔍 Run Dependency Check

    "; echo "
    "; echo "\n"; echo ""; echo ""; // Host $OS = strtoupper(substr(PHP_OS, 0, 3)); $default_host = ($OS === 'WIN' || $OS === 'CYG') ? "127.0.0.1" : "localhost"; echo ""; // Port (GSP addition – no lang key needed; label is always in English for installer) echo ""; // User echo ""; // Password echo ""; // Name echo ""; // Prefix – default gsp_ echo ""; echo "
    ".get_lang('database_settings')."
    ".get_lang('database_type').":MySQL
    ".get_lang('database_hostname').":
    Database Port:
    ".get_lang('database_username').":
    ".get_lang('database_password').":
    ".get_lang('database_name').":
    ".get_lang('database_prefix').":
    \n"; echo "

    "; echo "

    ".get_lang('back')."

    "; echo "
    \n"; } // ---------------------------------------------------------------- // Step 2 – Write config, migrate tables, install modules, create admin // ---------------------------------------------------------------- elseif ($step == "2") { echo "
    \n"; if (!isset($_POST['db_host'])) { print_failure("No form data received. Please go back and fill in the database settings."); echo "

    ".get_lang('back')."

    "; echo "
    \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 = ""; $temp = fopen("includes/config.inc.php", "w"); if ($temp === false) { print_failure(get_lang('unable_to_write_config') . " — includes/config.inc.php could not be opened for writing. " . "Please run: sudo chmod 664 includes/config.inc.php && sudo chown www-data:www-data includes/config.inc.php " . "(or sudo chmod -R 775 includes/ && sudo chown -R www-data:www-data includes/ if the file does not yet exist). " . "You can also use the Dependency Check page for a full diagnostics report."); echo "

    ".get_lang('back')."

    "; echo "\n"; return; } if (fwrite($temp, $config) === false) { print_failure(get_lang('unable_to_write_config')); echo "

    ".get_lang('back')."

    "; fclose($temp); echo "\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 "

    ".get_lang('back')."

    "; echo "\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"=> "".get_lang('default_welcome_title_message')."", "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: admin)."); } else { echo "

    Admin user already exists – skipped creation.

    "; } // --- Update game configs --- updateGameConfigsPostInstall(); echo "

    ".get_lang('remove_install_and_secure_config')."

    "; echo "

    SECURITY: The default admin password is admin. Change it immediately after your first login at Admin → User Management.

    "; echo "

    ".get_lang('go_to_panel')."

    "; echo "\n"; // --- Disable the installer by renaming install.php to install.php.bak --- gsp_disable_installer(); echo "\n"; } else { echo "

    Unknown step. Start over

    "; } } /** * 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 ogp_ to {$table_prefix} prefix."); if ($skipped > 0) echo "

    {$skipped} table(s) already existed under the {$table_prefix} prefix – skipped.

    "; } /** * 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 "

    ⚠ Existing database detected (" . htmlspecialchars((string)$table_count, ENT_QUOTES, 'UTF-8') . " table(s)). Creating backup before reinstall…

    "; // 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 "

    Could not create backup database " . htmlspecialchars($backup_name) . ". Skipping backup (install will continue).

    "; 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 " . htmlspecialchars($backup_name) . " — {$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 "

    Could not read install.php for backup — installer not renamed (non-fatal).

    "; return; } // Write the backup copy if (@file_put_contents($bak_path, $installer_content) === false) { echo "

    Could not write install.php.bak — installer not renamed (non-fatal).

    "; return; } // Write the stub that replaces install.php $stub = <<<'STUB' Invalid or expired restore token. Please reload the page and try again.

    '); } $bak = __DIR__ . '/install.php.bak'; if (!is_readable($bak)) { die('

    install.php.bak not found. Restore manually.

    '); } $content = file_get_contents($bak); if ($content === false || file_put_contents(__FILE__, $content) === false) { die('

    Could not overwrite install.php. Check file permissions.

    '); } // 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'); ?> GSP Installer — Disabled

    ⚠ Installer Disabled

    The GSP installer has been disabled after a successful installation to prevent accidental re-runs.

    The original installer is preserved at install.php.bak.

    To restore manually:
    cp install.php.bak install.php

    Go to Panel

    STUB; if (@file_put_contents($self, $stub) === false) { echo "

    Could not overwrite install.php with stub — installer not disabled (non-fatal). Delete or rename install.php manually.

    "; return; } print_success("Installer disabled: install.php renamed to stub. Full installer preserved as install.php.bak."); echo "

    To re-enable the installer, click Restore & Re-run Installer on the new install.php page, or run: cp install.php.bak install.php

    "; } $view->printView(); ?>