"; echo "
" . nl2br(htmlspecialchars($details, ENT_QUOTES, 'UTF-8')) . "
"; } echo "Please install the missing PHP requirements or restore the referenced configuration file, then reload this page.
"; echo ""; exit; } } /** * Collect a non-fatal XML parse/validation error for a game config file. * Errors are stored in a static array and can be retrieved via * gsp_get_xml_errors(). Does NOT stop page execution. */ if (!function_exists('gsp_collect_xml_error')) { function gsp_collect_xml_error(string $file, string $title, string $details = ''): void { $log_message = "[GSP] $title" . (empty($details) ? '' : ' Details: ' . $details); error_log($log_message); $GLOBALS['_gsp_xml_errors'][] = array( 'file' => $file, 'title' => $title, 'details' => $details, ); } } if (!function_exists('gsp_get_xml_errors')) { function gsp_get_xml_errors(): array { return isset($GLOBALS['_gsp_xml_errors']) ? $GLOBALS['_gsp_xml_errors'] : array(); } } if (!function_exists('ogp_render_missing_xml_extensions')) { function ogp_render_missing_xml_extensions($missing_extensions) { $pretty = implode(', ', $missing_extensions); $details = "Missing PHP extension(s): {$pretty}\n" . "Install the php-xml package and restart Apache/PHP-FPM.\n" . "Debian/Ubuntu: sudo apt install php-xml\n" . "RHEL/CentOS: sudo dnf install php-xml"; ogp_render_config_error("Required PHP XML extensions are not available.", $details); } } if (!function_exists('ogp_format_libxml_errors')) { function ogp_format_libxml_errors() { $errors = libxml_get_errors(); if (empty($errors)) { return "No additional libxml details are available."; } $messages = array(); foreach ((array)$errors as $error) { $messages[] = trim($error->message) . " (Line {$error->line}, Column {$error->column})"; } libxml_clear_errors(); return implode("\n", $messages); } } if (!function_exists('ogp_ensure_xml_support')) { function ogp_ensure_xml_support() { static $checked = false; if ($checked) { return; } $missing = array(); if (!extension_loaded('libxml')) { $missing[] = 'libxml'; } if (!class_exists('DOMDocument')) { $missing[] = 'dom'; } if (!function_exists('simplexml_load_file')) { $missing[] = 'simplexml'; } if (!empty($missing)) { ogp_render_missing_xml_extensions($missing); } $checked = true; } } /// \return FALSE in case of failure in parsing. /// \return array containing the elements on success. function read_server_config( $filename ) { ogp_ensure_xml_support(); if (!is_readable($filename)) { gsp_collect_xml_error( $filename, "Game configuration file is missing or unreadable.", "Expected at: {$filename}" ); return FALSE; } $previous_error_state = libxml_use_internal_errors(true); $dom = new DOMDocument(); if ($dom->load($filename) === FALSE) { gsp_collect_xml_error( $filename, "Unable to load XML configuration.", "File: {$filename}\n".ogp_format_libxml_errors() ); libxml_use_internal_errors($previous_error_state); return FALSE; } if ( $dom->schemaValidate(XML_SCHEMA) !== TRUE ) { gsp_collect_xml_error( $filename, "XML configuration failed schema validation.", "File: {$filename}\nSchema: ".XML_SCHEMA."\n".ogp_format_libxml_errors() ); libxml_use_internal_errors($previous_error_state); return FALSE; } $xml = simplexml_import_dom($dom); if($xml === false){ gsp_collect_xml_error( $filename, "Failed to parse XML configuration.", "File: {$filename}\n".ogp_format_libxml_errors() ); libxml_use_internal_errors($previous_error_state); return FALSE; } $xml->addChild('home_cfg_file',basename($filename)); libxml_use_internal_errors($previous_error_state); return $xml; } function xml_get_mod( $server_xml, $mod_key ) { foreach ( $server_xml->mods->mod as $xml_mod_tmp ) { if ($xml_mod_tmp['key'] == $mod_key) { return $xml_mod_tmp; } } return FALSE; } ?>