From de80f896192f8df1bdead3e570e98de565b3f7cf Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 3 May 2026 23:43:41 +0000
Subject: [PATCH 1/2] fix: wrap DayZ post_install scripts in CDATA, add XML
editor auto-sanitizer
- dayz_arma2co_win32.xml: wrap post_install in CDATA to fix raw '<' breaking
XML parsing; fix dbPass generation to use portable tr form
- dayz_epoch_mod_win32.xml: same CDATA wrapping; replace < literals so
bash actually receives real '<' redirect characters
- config_servers.php: add config_games_sanitize_xml_scripts() that wraps bare
'<' in script-like nodes with CDATA before saving raw XML; add
config_games_script_node_names() helper; structured-editor save now uses
createCDATASection() for post_install/pre_start/etc. nodes so shell
characters survive DOM round-trips intact
Agent-Logs-Url: https://github.com/GameServerPanel/GSP/sessions/1afce49e-510d-49a6-9d11-0b7118d3cf85
Co-authored-by: iaretechnician <2749183+iaretechnician@users.noreply.github.com>
---
modules/config_games/config_servers.php | 58 ++++++++++++++++++-
.../server_configs/dayz_arma2co_win32.xml | 9 +--
.../server_configs/dayz_epoch_mod_win32.xml | 11 ++--
3 files changed, 62 insertions(+), 16 deletions(-)
diff --git a/modules/config_games/config_servers.php b/modules/config_games/config_servers.php
index 9d55ebb7..ee387950 100644
--- a/modules/config_games/config_servers.php
+++ b/modules/config_games/config_servers.php
@@ -169,6 +169,50 @@ function config_games_validate_xml_file(string $config_file): array
return [];
}
+/**
+ * Script-like element names whose text content is shell/batch code.
+ * These nodes should be stored as CDATA sections so that characters such as
+ * '<', '>', '&', etc. survive round-trips through the XML parser unchanged.
+ */
+function config_games_script_node_names(): array
+{
+ return ['pre_install', 'post_install', 'pre_start', 'post_start', 'precmd', 'postcmd'];
+}
+
+/**
+ * Auto-sanitize raw XML text: for every script-like element whose text content
+ * contains a bare '<' outside an existing CDATA block, wrap that content in a
+ * CDATA section so the file becomes well-formed. Non-script elements are left
+ * untouched.
+ *
+ * This is applied to raw XML submitted through the editor's "Raw XML" path
+ * before the validation step, giving a best-effort fix rather than a hard
+ * rejection for the most common authoring mistake.
+ *
+ * @param string $xml Raw XML string (may be malformed).
+ * @return string XML string with script content wrapped in CDATA where needed.
+ */
+function config_games_sanitize_xml_scripts(string $xml): string
+{
+ $tags = config_games_script_node_names();
+ foreach ($tags as $tag) {
+ $xml = preg_replace_callback(
+ '/<' . preg_quote($tag, '/') . '(\s[^>]*)?>(?!\s*/si',
+ function ($m) use ($tag) {
+ $attrs = $m[1];
+ $content = $m[2];
+ // Only wrap if the content contains raw < that are not XML entities/tags.
+ if (strpos($content, '<') === false) {
+ return $m[0];
+ }
+ return '<' . $tag . $attrs . '>' . $tag . '>';
+ },
+ $xml
+ );
+ }
+ return $xml;
+}
+
function config_games_print_editor_css()
{
static $printed = false;
@@ -388,13 +432,19 @@ function config_games_save_xml($db, $home_cfg_id, array $nodesPayload)
continue;
}
$hasChildren = !empty($nodeData['has_children']);
+ $nodeName = strtolower(substr($path, (int)strrpos($path, '/') + 1));
+ $isScriptNode = in_array($nodeName, config_games_script_node_names(), true);
if (array_key_exists('value', (array)$nodeData)) {
$normalizedValue = config_games_normalize_newlines($nodeData['value']);
while ($domNode->firstChild) {
$domNode->removeChild($domNode->firstChild);
}
if ($normalizedValue !== '') {
- $domNode->appendChild($dom->createTextNode($normalizedValue));
+ if ($isScriptNode) {
+ $domNode->appendChild($dom->createCDATASection($normalizedValue));
+ } else {
+ $domNode->appendChild($dom->createTextNode($normalizedValue));
+ }
}
} elseif (!$hasChildren) {
while ($domNode->firstChild) {
@@ -530,9 +580,11 @@ function exec_ogp_module() {
if ($cfg_info !== FALSE) {
$config_file = SERVER_CONFIG_LOCATION . $cfg_info['home_cfg_file'];
$raw_content = $_POST['raw_xml_content'];
+ // Apply best-effort auto-fix: wrap bare '<' chars in script blocks with CDATA.
+ $sanitized_content = config_games_sanitize_xml_scripts($raw_content);
// Write to a temp file for validation
$tmp = tempnam(sys_get_temp_dir(), 'gsp_xml_');
- file_put_contents($tmp, $raw_content);
+ file_put_contents($tmp, $sanitized_content);
$xmlErrors = config_games_validate_xml_file($tmp);
@unlink($tmp);
if (!empty($xmlErrors)) {
@@ -542,7 +594,7 @@ function exec_ogp_module() {
}
echo "";
} else {
- if (file_put_contents($config_file, $raw_content) !== false) {
+ if (file_put_contents($config_file, $sanitized_content) !== false) {
print_success(get_lang('configs_updated_ok'));
$config = read_server_config($config_file);
if ($config !== FALSE) {
diff --git a/modules/config_games/server_configs/dayz_arma2co_win32.xml b/modules/config_games/server_configs/dayz_arma2co_win32.xml
index c2ad3a6b..12baa823 100644
--- a/modules/config_games/server_configs/dayz_arma2co_win32.xml
+++ b/modules/config_games/server_configs/dayz_arma2co_win32.xml
@@ -65,7 +65,7 @@ Make sure if you install a MOD, you list the name here or else it wont get loade
-
+"..\_alsoRun.pid" echo %%P' \
> _alsoRun.bat
-
-
+]]>
diff --git a/modules/config_games/server_configs/dayz_epoch_mod_win32.xml b/modules/config_games/server_configs/dayz_epoch_mod_win32.xml
index b5175c72..df70c72a 100644
--- a/modules/config_games/server_configs/dayz_epoch_mod_win32.xml
+++ b/modules/config_games/server_configs/dayz_epoch_mod_win32.xml
@@ -65,7 +65,7 @@ Make sure if you install a MOD, you list the name here or else it wont get loade
-
+"..\_alsoRun.pid" echo %%P' \
> _alsoRun.bat
-
-
+]]>
From 7391d23487f32da31d39b1c5e1b46908693e325d Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 3 May 2026 23:44:57 +0000
Subject: [PATCH 2/2] fix: address code review - add sanitizer comments, fix
strrpos false-return edge case
Agent-Logs-Url: https://github.com/GameServerPanel/GSP/sessions/1afce49e-510d-49a6-9d11-0b7118d3cf85
Co-authored-by: iaretechnician <2749183+iaretechnician@users.noreply.github.com>
---
modules/config_games/config_servers.php | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/modules/config_games/config_servers.php b/modules/config_games/config_servers.php
index ee387950..0e4d15ce 100644
--- a/modules/config_games/config_servers.php
+++ b/modules/config_games/config_servers.php
@@ -185,6 +185,14 @@ function config_games_script_node_names(): array
* CDATA section so the file becomes well-formed. Non-script elements are left
* untouched.
*
+ * Assumptions / limitations:
+ * - Script elements are treated as leaf nodes (no child elements expected).
+ * Nested XML tags inside a script block are not supported and the regex
+ * will not handle them correctly.
+ * - The detection of an already-present CDATA section relies on the opening
+ * tag being immediately followed by '