fix: billing order flow, steam_workshop lang key, workshop module install queries

- order.php: replace foreach((array)$mysqli_result) with proper fetch_assoc() loop
- order.php: fix hidden service_id field to use $_REQUEST instead of $_POST
- order.php: add safe error messages and error_log() on failed service lookup
- lang/English/global.php: add OGP_LANG_steam_workshop to fix _steam_workshop_ raw key
- steam_workshop/module.php: replace unusable $module_db_create heredoc with
  proper $install_queries[0] array so tables are created during module install
- timestamp.txt: updated

Agent-Logs-Url: https://github.com/GameServerPanel/GSP/sessions/70fa0082-93ad-4a4d-a1b3-ea6afa77ee80

Co-authored-by: iaretechnician <2749183+iaretechnician@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-05-04 17:15:07 +00:00 committed by GitHub
parent d06ac4fb63
commit 9550cd32b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 95 additions and 85 deletions

View file

@ -78,6 +78,7 @@ define('OGP_LANG_xml_file_not_valid', "XML file '%s' could not be validated with
define('OGP_LANG_unable_to_load_xml', "Unable to load XML file '%s'. Permission issue?"); define('OGP_LANG_unable_to_load_xml', "Unable to load XML file '%s'. Permission issue?");
define('OGP_LANG_gamemanager', "Game Manager"); define('OGP_LANG_gamemanager', "Game Manager");
define('OGP_LANG_game_monitor', "Game Monitor"); define('OGP_LANG_game_monitor', "Game Monitor");
define('OGP_LANG_steam_workshop', "Steam Workshop");
define('OGP_LANG_dashboard', "Dashboard"); define('OGP_LANG_dashboard', "Dashboard");
define('OGP_LANG_user_addons', "Addons"); define('OGP_LANG_user_addons', "Addons");
define('OGP_LANG_ftp', "FTP"); define('OGP_LANG_ftp', "FTP");

View file

@ -66,39 +66,46 @@ THIS IS WHAT WE DISPLAY ON THE SHOP PAGE AT THE TOP
<?php <?php
// Shop Form // Shop Form
if(intval($_REQUEST['service_id']) !==0) $where_service_id = " WHERE enabled = 1 and service_id=".intval($_REQUEST['service_id']); else $where_service_id = " where enabled = 1"; $req_service_id = intval($_REQUEST['service_id'] ?? 0);
$qry_services = "SELECT * FROM {$table_prefix}billing_services ".$where_service_id ." ORDER BY service_name"; if ($req_service_id !== 0) {
$services = $db->query($qry_services); $where_service_id = " WHERE enabled = 1 AND service_id=" . $req_service_id;
} else {
if (isset($_REQUEST['service_id']) && $services === false) { $where_service_id = " WHERE enabled = 1";
echo "<meta http-equiv='refresh' content='1'>";
return;
} }
$qry_services = "SELECT * FROM {$table_prefix}billing_services " . $where_service_id . " ORDER BY service_name";
foreach ((array)$services as $key => $row) { $services_result = $db->query($qry_services);
$service_ids[$key] = $row['service_id'];
$home_cfg_id[$key] = $row['home_cfg_id']; if ($services_result === false) {
$mod_cfg_id[$key] = $row['mod_cfg_id']; echo "<p class='error'>Unable to load service information. Please try again or contact support.</p>";
$service_name[$key] = $row['service_name']; error_log("billing order.php: query failed - " . $db->error . " | SQL: " . $qry_services);
$remote_server_id[$key] = $row['remote_server_id']; billing_maybe_close_db($db);
$slot_max_qty[$key] = $row['slot_max_qty']; include(__DIR__ . '/includes/footer.php');
$slot_min_qty[$key] = $row['slot_min_qty']; echo '</body></html>';
$price_daily[$key] = $row['price_daily']; exit;
$price_monthly[$key] = $row['price_monthly'];
$price_year[$key] = $row['price_year'];
$description[$key] = $row['description'];
$img_url[$key] = $row['img_url'];
$ftp[$key] = $row['ftp'];
$install_method[$key] = $row['install_method'];
$manual_url[$key] = $row['manual_url'];
$access_rights_list[$key] = $row['access_rights'];
} }
// Fetch all rows into an array so foreach works correctly
$serviceRows = [];
while ($row = $services_result->fetch_assoc()) {
$serviceRows[] = $row;
}
$services_result->free();
if ($req_service_id !== 0 && empty($serviceRows)) {
error_log("billing order.php: service_id={$req_service_id} not found or not enabled");
echo "<p class='error'>The requested service could not be found or is no longer available.</p>";
echo "<p><a href='serverlist.php'>Back to server list</a></p>";
billing_maybe_close_db($db);
include(__DIR__ . '/includes/footer.php');
echo '</body></html>';
exit;
}
?> ?>
<div class="clearfix"> <div class="clearfix">
<?php <?php
foreach ((array)$services as $row) foreach ($serviceRows as $row)
{ {
if(!isset($_REQUEST['service_id'])) if(!isset($_REQUEST['service_id']))
{ {
?> ?>
@ -177,7 +184,7 @@ if ($row['price_monthly'] == 0.0) {
</div> </div>
<table class="float-left"> <table class="float-left">
<form method="post" action="add_to_cart.php"> <form method="post" action="add_to_cart.php">
<input type="hidden" name="service_id" size="15" value="<?php if(isset($_POST['service_id'])) echo $_POST['service_id'];?>"> <input type="hidden" name="service_id" size="15" value="<?php echo intval($_REQUEST['service_id'] ?? $row['service_id'] ?? 0); ?>">
<input type="hidden" name="remote_control_password" size="15" value="ChangeMe"> <input type="hidden" name="remote_control_password" size="15" value="ChangeMe">
<input type="hidden" name="ftp_password" size="15" value="ChangeMe"> <input type="hidden" name="ftp_password" size="15" value="ChangeMe">
<tr> <tr>

View file

@ -1 +1 @@
Last Updated at 3:21pm on 2026-02-05 Last Updated at 5:10pm on 2026-05-04

View file

@ -28,60 +28,62 @@ $db_version = 1;
$module_required = TRUE; $module_required = TRUE;
$module_menus = array(); $module_menus = array();
// Database schema migration: create the three Workshop tables when not present. // Database schema: create the three Workshop tables when the module is installed.
// Called by the panel module installer when db_version increments. // $install_queries[0] is run during initial install (from db_version 0 to 1).
$module_db_create = <<<'SQL' // Each table uses IF NOT EXISTS so re-running is safe.
CREATE TABLE IF NOT EXISTS `OGP_DB_PREFIXworkshop_game_profiles` ( $install_queries = array();
`id` INT NOT NULL AUTO_INCREMENT, $install_queries[0] = array(
`game_key` VARCHAR(100) NOT NULL, "CREATE TABLE IF NOT EXISTS `".OGP_DB_PREFIX."workshop_game_profiles` (
`game_name` VARCHAR(255) NOT NULL, `id` INT NOT NULL AUTO_INCREMENT,
`workshop_app_id` VARCHAR(32) NOT NULL, `game_key` VARCHAR(100) NOT NULL,
`supported_os` SET('linux','windows') NOT NULL DEFAULT 'linux', `game_name` VARCHAR(255) NOT NULL,
`cache_path_template` TEXT NOT NULL, `workshop_app_id` VARCHAR(32) NOT NULL,
`install_path_template` TEXT NOT NULL, `supported_os` SET('linux','windows') NOT NULL DEFAULT 'linux',
`folder_name_template` VARCHAR(255) NOT NULL DEFAULT '@{mod_id}', `cache_path_template` TEXT NOT NULL,
`copy_method` ENUM('rsync','robocopy','custom_script') NOT NULL DEFAULT 'rsync', `install_path_template` TEXT NOT NULL,
`install_script` TEXT NULL, `folder_name_template` VARCHAR(255) NOT NULL DEFAULT '@{mod_id}',
`config_file_template` TEXT NULL, `copy_method` ENUM('rsync','robocopy','custom_script') NOT NULL DEFAULT 'rsync',
`launch_param_template` TEXT NULL, `install_script` TEXT NULL,
`requires_restart` TINYINT(1) NOT NULL DEFAULT 1, `config_file_template` TEXT NULL,
`enabled` TINYINT(1) NOT NULL DEFAULT 1, `launch_param_template` TEXT NULL,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `requires_restart` TINYINT(1) NOT NULL DEFAULT 1,
`updated_at` DATETIME NULL, `enabled` TINYINT(1) NOT NULL DEFAULT 1,
PRIMARY KEY (`id`), `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY `uniq_game_key` (`game_key`) `updated_at` DATETIME NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; PRIMARY KEY (`id`),
UNIQUE KEY `uniq_game_key` (`game_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
CREATE TABLE IF NOT EXISTS `OGP_DB_PREFIXworkshop_cache` ( "CREATE TABLE IF NOT EXISTS `".OGP_DB_PREFIX."workshop_cache` (
`id` INT NOT NULL AUTO_INCREMENT, `id` INT NOT NULL AUTO_INCREMENT,
`agent_id` INT NOT NULL, `agent_id` INT NOT NULL,
`os_type` ENUM('linux','windows') NOT NULL DEFAULT 'linux', `os_type` ENUM('linux','windows') NOT NULL DEFAULT 'linux',
`workshop_app_id` VARCHAR(32) NOT NULL, `workshop_app_id` VARCHAR(32) NOT NULL,
`workshop_id` VARCHAR(64) NOT NULL, `workshop_id` VARCHAR(64) NOT NULL,
`title` VARCHAR(255) NULL, `title` VARCHAR(255) NULL,
`cache_path` TEXT NOT NULL, `cache_path` TEXT NOT NULL,
`status` ENUM('missing','cached','failed') NOT NULL DEFAULT 'missing', `status` ENUM('missing','cached','failed') NOT NULL DEFAULT 'missing',
`last_checked` DATETIME NULL, `last_checked` DATETIME NULL,
`last_updated` DATETIME NULL, `last_updated` DATETIME NULL,
`last_error` TEXT NULL, `last_error` TEXT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `uniq_agent_workshop` (`agent_id`, `workshop_app_id`, `workshop_id`) UNIQUE KEY `uniq_agent_workshop` (`agent_id`, `workshop_app_id`, `workshop_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
CREATE TABLE IF NOT EXISTS `OGP_DB_PREFIXserver_workshop_mods` ( "CREATE TABLE IF NOT EXISTS `".OGP_DB_PREFIX."server_workshop_mods` (
`id` INT NOT NULL AUTO_INCREMENT, `id` INT NOT NULL AUTO_INCREMENT,
`home_id` INT NOT NULL, `home_id` INT NOT NULL,
`agent_id` INT NOT NULL, `agent_id` INT NOT NULL,
`profile_id` INT NOT NULL, `profile_id` INT NOT NULL,
`workshop_app_id` VARCHAR(32) NOT NULL, `workshop_app_id` VARCHAR(32) NOT NULL,
`workshop_id` VARCHAR(64) NOT NULL, `workshop_id` VARCHAR(64) NOT NULL,
`title` VARCHAR(255) NULL, `title` VARCHAR(255) NULL,
`enabled` TINYINT(1) NOT NULL DEFAULT 1, `enabled` TINYINT(1) NOT NULL DEFAULT 1,
`install_path` TEXT NOT NULL, `install_path` TEXT NOT NULL,
`load_order` INT NOT NULL DEFAULT 0, `load_order` INT NOT NULL DEFAULT 0,
`installed_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `installed_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL, `updated_at` DATETIME NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `uniq_home_workshop` (`home_id`, `workshop_id`) UNIQUE KEY `uniq_home_workshop` (`home_id`, `workshop_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
SQL; );