Merge pull request #160 from GameServerPanel/copilot/fix-lang-version-warning
This commit is contained in:
commit
59e03f2c28
9 changed files with 676 additions and 71 deletions
|
|
@ -1,5 +1,42 @@
|
|||
$(function() {
|
||||
// Tooltips are annoying
|
||||
// Use title attribute instead
|
||||
// $( 'input,textarea' ).tooltip();
|
||||
var methodToRows = {
|
||||
download_zip: ['#scm-row-url', '#scm-row-path', '#scm-row-post-script'],
|
||||
download_file: ['#scm-row-url', '#scm-row-path', '#scm-row-post-script'],
|
||||
steam_workshop: ['#scm-row-workshop-id', '#scm-row-workshop-app-id', '#scm-row-target-path-template', '#scm-row-optional-folder-name', '#scm-row-launch-param-additions', '#scm-row-config-edit-rule', '#scm-row-post-script'],
|
||||
post_script: ['#scm-row-post-script'],
|
||||
config_edit: ['#scm-row-path', '#scm-row-config-edit-rule', '#scm-row-post-script'],
|
||||
create_folder: ['#scm-row-path']
|
||||
};
|
||||
var allRows = [
|
||||
'#scm-row-url',
|
||||
'#scm-row-path',
|
||||
'#scm-row-workshop-id',
|
||||
'#scm-row-workshop-app-id',
|
||||
'#scm-row-target-path-template',
|
||||
'#scm-row-optional-folder-name',
|
||||
'#scm-row-post-script',
|
||||
'#scm-row-config-edit-rule',
|
||||
'#scm-row-launch-param-additions'
|
||||
];
|
||||
var $method = $('#scm-install-method');
|
||||
var $help = $('#scm-install-method-help');
|
||||
|
||||
function applyContentTypeUi() {
|
||||
if ($method.length === 0) return;
|
||||
var value = $method.val();
|
||||
var shown = methodToRows[value] || [];
|
||||
for (var i = 0; i < allRows.length; i++) {
|
||||
$(allRows[i]).hide();
|
||||
}
|
||||
for (var j = 0; j < shown.length; j++) {
|
||||
$(shown[j]).show();
|
||||
}
|
||||
var selectedOption = $method.find('option:selected');
|
||||
var helpText = selectedOption.data('help') || '';
|
||||
$help.text(helpText);
|
||||
$('#scm-path-label').text(value === 'config_edit' ? 'Config Target Path' : 'Target Path');
|
||||
}
|
||||
|
||||
$method.on('change', applyContentTypeUi);
|
||||
applyContentTypeUi();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ define('LANG_plugin', "Plugins / Mods");
|
|||
define('LANG_mappack', "Map Packs");
|
||||
define('LANG_config', "Config Packs");
|
||||
// Additional category labels (for future content types already defined in server_content_categories.php)
|
||||
if (!defined('LANG_version')) define('LANG_version', "Version");
|
||||
define('LANG_server_content_version', "Server Versions");
|
||||
define('LANG_modpack', "Modpacks");
|
||||
define('LANG_workshop', "Workshop Content");
|
||||
|
|
@ -63,9 +64,15 @@ define('LANG_addons_db', "Server Content Database");
|
|||
define('LANG_addon_has_been_created', "The server content item \"%s\" has been created.");
|
||||
define('LANG_remove_addon', "Remove");
|
||||
define('LANG_fill_the_url_address_to_a_compressed_file', "Please enter a URL for the compressed file to download.");
|
||||
define('LANG_fill_the_download_url', "Please enter a download URL.");
|
||||
define('LANG_fill_the_workshop_id', "Please enter a Workshop ID.");
|
||||
define('LANG_fill_the_target_install_path', "Please select a target install path.");
|
||||
define('LANG_fill_the_script_action_body', "Please enter a script/action body.");
|
||||
define('LANG_fill_the_config_edit_rule', "Please enter a config edit rule.");
|
||||
define('LANG_fill_the_addon_name', "Please enter a name for the server content item.");
|
||||
define('LANG_select_an_addon_type', "Please select a content type.");
|
||||
define('LANG_select_a_game_type', "Please select a game type.");
|
||||
define('LANG_select_a_content_type', "Please select a content type.");
|
||||
define('LANG_edit_addon', "Edit");
|
||||
define('LANG_invalid_addon', "Invalid server content item or access denied.");
|
||||
define('LANG_invalid_addon_type', "Invalid content type selected.");
|
||||
|
|
@ -79,4 +86,16 @@ define('LANG_show_to_group', "Show to group");
|
|||
define('LANG_all_groups', "All groups");
|
||||
define('LANG_show_addons_for_selected_group', "Show content for selected group");
|
||||
define('LANG_group', "Group");
|
||||
define('LANG_content_type', "Content Type");
|
||||
define('LANG_workshop_id', "Workshop ID");
|
||||
define('LANG_target_path_template', "Target Path");
|
||||
define('LANG_optional_folder_name', "Optional Folder Name");
|
||||
define('LANG_config_edit_rule', "Config Edit Rule");
|
||||
define('LANG_launch_param_additions', "Launch Parameter Additions");
|
||||
define('LANG_content_type_help_download_zip', "Downloads and extracts an archive into the target path.");
|
||||
define('LANG_content_type_help_download_file', "Downloads a single file without extraction.");
|
||||
define('LANG_content_type_help_steam_workshop', "Downloads/updates a Workshop item and applies it to the server.");
|
||||
define('LANG_content_type_help_post_script', "Runs a script/action only, with no URL required.");
|
||||
define('LANG_content_type_help_config_edit', "Applies config edit rules to a target path, with no URL required.");
|
||||
define('LANG_content_type_help_create_folder', "Creates target folders/paths only, with no URL required.");
|
||||
?>
|
||||
|
|
|
|||
|
|
@ -112,6 +112,10 @@ require_once("protocol/lgsl/lgsl_protocol.php");
|
|||
// Central category map — all valid addon_type values and their labels.
|
||||
require_once(dirname(__FILE__) . '/server_content_categories.php');
|
||||
require_once(dirname(__FILE__) . '/server_content_helpers.php');
|
||||
require_once(dirname(__FILE__) . '/workshop_action.php');
|
||||
if (file_exists(dirname(__FILE__) . '/../steam_workshop/includes/functions.php')) {
|
||||
require_once(dirname(__FILE__) . '/../steam_workshop/includes/functions.php');
|
||||
}
|
||||
|
||||
function exec_ogp_module() {
|
||||
|
||||
|
|
@ -161,7 +165,7 @@ function exec_ogp_module() {
|
|||
{
|
||||
$addon_id = (int)$_REQUEST['addon_id'];
|
||||
|
||||
$addons_rows = $db->resultQuery("SELECT url, path, post_script, addon_type, install_method, content_version, requires_stop, restart_after_install FROM OGP_DB_PREFIXaddons WHERE addon_id=".$addon_id.$query_groups);
|
||||
$addons_rows = $db->resultQuery("SELECT url, path, post_script, addon_type, install_method, content_version, requires_stop, restart_after_install, workshop_item_id, workshop_app_id, target_path_template, optional_folder_name, config_edit_rule, launch_param_additions, name FROM OGP_DB_PREFIXaddons WHERE addon_id=".$addon_id.$query_groups);
|
||||
if (!is_array($addons_rows)) {
|
||||
$addons_rows = [];
|
||||
}
|
||||
|
|
@ -174,10 +178,24 @@ function exec_ogp_module() {
|
|||
|
||||
$remote = new OGPRemoteLibrary($home_info['agent_ip'],$home_info['agent_port'],$home_info['encryption_key'],$home_info['timeout']);
|
||||
|
||||
$addon_info = $addons_rows[0];
|
||||
$install_method = isset($addon_info['install_method']) ? $addon_info['install_method'] : 'download_zip';
|
||||
$addon_info = $addons_rows[0];
|
||||
$install_method = scm_get_install_method_default(isset($addon_info['install_method']) ? $addon_info['install_method'] : 'download_zip');
|
||||
$content_version = isset($addon_info['content_version']) ? $addon_info['content_version'] : '';
|
||||
$requires_stop = !empty($addon_info['requires_stop']) ? 1 : 0;
|
||||
$post_script = '';
|
||||
$validation_payload = array(
|
||||
'url' => isset($addon_info['url']) ? $addon_info['url'] : '',
|
||||
'path' => isset($addon_info['path']) ? $addon_info['path'] : '',
|
||||
'workshop_item_id' => isset($addon_info['workshop_item_id']) ? $addon_info['workshop_item_id'] : '',
|
||||
'target_path_template' => isset($addon_info['target_path_template']) ? $addon_info['target_path_template'] : '',
|
||||
'post_script' => isset($addon_info['post_script']) ? $addon_info['post_script'] : '',
|
||||
'config_edit_rule' => isset($addon_info['config_edit_rule']) ? $addon_info['config_edit_rule'] : '',
|
||||
);
|
||||
$validation_message = '';
|
||||
if ($state == "start" && !scm_validate_install_method_payload($install_method, $validation_payload, $validation_message)) {
|
||||
print_failure($validation_message);
|
||||
return;
|
||||
}
|
||||
|
||||
// ── requires_stop guard ───────────────────────────────────────────────
|
||||
// If the content item requires the server to be stopped first, check
|
||||
|
|
@ -261,7 +279,155 @@ function exec_ogp_module() {
|
|||
$cache_mode
|
||||
);
|
||||
$_SESSION['scm_history_id_' . $home_id . '_' . $addon_id] = $history_id;
|
||||
$pid = $remote->start_file_download( $addon_info['url'], $home_info['home_path']."/".$addon_info['path'], $filename, "uncompress", $post_script);
|
||||
scm_log_content_install_action(array(
|
||||
'addon_id' => (int)$addon_id,
|
||||
'addon_name' => isset($addon_info['name']) ? $addon_info['name'] : '',
|
||||
'content_type' => $install_method,
|
||||
'home_id' => (int)$home_id,
|
||||
'home_cfg_id' => (int)$home_info['home_cfg_id'],
|
||||
'workshop_id' => isset($addon_info['workshop_item_id']) ? (string)$addon_info['workshop_item_id'] : '',
|
||||
'target_path' => isset($addon_info['target_path_template']) ? (string)$addon_info['target_path_template'] : (string)$addon_info['path'],
|
||||
'action' => 'started',
|
||||
));
|
||||
if ($install_method === 'steam_workshop') {
|
||||
scm_ensure_workshop_schema($db);
|
||||
$workshop_item_id = trim((string)$addon_info['workshop_item_id']);
|
||||
$target_path_template = trim((string)$addon_info['target_path_template']);
|
||||
$resolved = function_exists('steam_workshop_install_item_to_home')
|
||||
? steam_workshop_install_item_to_home($db, $home_info, $workshop_item_id, $target_path_template, array(
|
||||
'optional_folder_name' => trim((string)$addon_info['optional_folder_name']),
|
||||
'workshop_app_id' => trim((string)$addon_info['workshop_app_id']),
|
||||
))
|
||||
: array('ok' => false);
|
||||
if (empty($resolved['ok'])) {
|
||||
$fallback_profile = function_exists('sw_get_profile_for_home') ? sw_get_profile_for_home($db, (int)$home_id) : false;
|
||||
$fallback_workshop_app_id = trim((string)$addon_info['workshop_app_id']);
|
||||
if ($fallback_workshop_app_id === '' && is_array($fallback_profile) && !empty($fallback_profile['workshop_app_id'])) {
|
||||
$fallback_workshop_app_id = (string)$fallback_profile['workshop_app_id'];
|
||||
}
|
||||
if ($fallback_workshop_app_id === '') {
|
||||
$fallback_workshop_app_id = scm_extract_workshop_app_id($server_xml);
|
||||
}
|
||||
$placeholder_map = scm_build_placeholder_map($home_info, array('exe_location' => (string)$server_xml->exe_location), array(
|
||||
'WORKSHOP_ID' => $workshop_item_id,
|
||||
'WORKSHOP_APP_ID' => $fallback_workshop_app_id,
|
||||
'STEAM_APP_ID' => (is_array($fallback_profile) && !empty($fallback_profile['steam_app_id'])) ? (string)$fallback_profile['steam_app_id'] : '',
|
||||
));
|
||||
$resolved = array(
|
||||
'workshop_app_id' => $fallback_workshop_app_id,
|
||||
'steam_app_id' => (is_array($fallback_profile) && !empty($fallback_profile['steam_app_id'])) ? (string)$fallback_profile['steam_app_id'] : '',
|
||||
'target_path_resolved' => scm_apply_placeholders($target_path_template, $placeholder_map),
|
||||
);
|
||||
}
|
||||
$workshop_app_id = isset($resolved['workshop_app_id']) ? (string)$resolved['workshop_app_id'] : '';
|
||||
$steam_app_id = isset($resolved['steam_app_id']) ? (string)$resolved['steam_app_id'] : '';
|
||||
$target_path_resolved = isset($resolved['target_path_resolved']) ? (string)$resolved['target_path_resolved'] : '';
|
||||
$extra_manifest = array(
|
||||
'addon_id' => (int)$addon_id,
|
||||
'target_path_template' => $target_path_template,
|
||||
'target_path_resolved' => $target_path_resolved,
|
||||
'optional_folder_name' => trim((string)$addon_info['optional_folder_name']),
|
||||
'config_edit_rule' => trim((string)$addon_info['config_edit_rule']),
|
||||
'launch_param_additions' => trim((string)$addon_info['launch_param_additions']),
|
||||
'workshop_app_id' => $workshop_app_id,
|
||||
'steam_app_id' => $steam_app_id,
|
||||
);
|
||||
$workshop_error = '';
|
||||
$workshop_ok = scm_workshop_write_manifest_and_run($db, $home_info, $server_xml, 'install', array($workshop_item_id), $workshop_error, $extra_manifest);
|
||||
if ($workshop_ok) {
|
||||
scm_record_install_done($db, (int)$history_id, 'installed', 0, 'workshop_install_ok');
|
||||
scm_upsert_manifest($db, $home_id, $addon_id, array(
|
||||
'install_method' => $install_method,
|
||||
'content_version' => $content_version,
|
||||
'install_state' => 'installed',
|
||||
'source_url' => 'steam://workshop/' . $workshop_item_id,
|
||||
'installed_by' => $user_id,
|
||||
));
|
||||
scm_log_content_install_action(array(
|
||||
'addon_id' => (int)$addon_id,
|
||||
'addon_name' => isset($addon_info['name']) ? $addon_info['name'] : '',
|
||||
'content_type' => $install_method,
|
||||
'home_id' => (int)$home_id,
|
||||
'home_cfg_id' => (int)$home_info['home_cfg_id'],
|
||||
'workshop_id' => $workshop_item_id,
|
||||
'target_path' => $target_path_resolved,
|
||||
'action' => 'succeeded',
|
||||
));
|
||||
print_success(get_lang('addon_installed_successfully'));
|
||||
} else {
|
||||
scm_record_install_done($db, (int)$history_id, 'failed', 1, $workshop_error);
|
||||
scm_log_content_install_action(array(
|
||||
'addon_id' => (int)$addon_id,
|
||||
'addon_name' => isset($addon_info['name']) ? $addon_info['name'] : '',
|
||||
'content_type' => $install_method,
|
||||
'home_id' => (int)$home_id,
|
||||
'home_cfg_id' => (int)$home_info['home_cfg_id'],
|
||||
'workshop_id' => $workshop_item_id,
|
||||
'target_path' => $target_path_resolved,
|
||||
'action' => 'failed',
|
||||
'error' => $workshop_error,
|
||||
));
|
||||
print_failure($workshop_error);
|
||||
}
|
||||
echo "<p><a href=\"?m=addonsmanager&p=user_addons&home_id=$home_id&mod_id=$mod_id&ip=$ip&port=$port\">".get_lang('back')."</a></p>";
|
||||
return;
|
||||
}
|
||||
if ($install_method === 'post_script') {
|
||||
$script_command = "cd " . escapeshellarg($home_info['home_path']) . " && /bin/bash -lc " . escapeshellarg((string)$post_script) . " ; echo __GSP_SCRIPT_EXIT:$?";
|
||||
$script_output = $remote->exec($script_command);
|
||||
$script_ok = is_string($script_output) && preg_match('/__GSP_SCRIPT_EXIT:(\d+)/', $script_output, $sm) && (int)$sm[1] === 0;
|
||||
if ($script_ok) {
|
||||
scm_record_install_done($db, (int)$history_id, 'installed', 0, trim((string)$script_output));
|
||||
scm_upsert_manifest($db, $home_id, $addon_id, array(
|
||||
'install_method' => $install_method,
|
||||
'content_version' => $content_version,
|
||||
'install_state' => 'installed',
|
||||
'source_url' => '',
|
||||
'installed_by' => $user_id,
|
||||
));
|
||||
scm_log_content_install_action(array('addon_id' => (int)$addon_id, 'addon_name' => isset($addon_info['name']) ? $addon_info['name'] : '', 'content_type' => $install_method, 'home_id' => (int)$home_id, 'home_cfg_id' => (int)$home_info['home_cfg_id'], 'action' => 'succeeded'));
|
||||
print_success(get_lang('addon_installed_successfully'));
|
||||
} else {
|
||||
$error_msg = 'Script/action failed.';
|
||||
scm_record_install_done($db, (int)$history_id, 'failed', 1, trim((string)$script_output));
|
||||
scm_log_content_install_action(array('addon_id' => (int)$addon_id, 'addon_name' => isset($addon_info['name']) ? $addon_info['name'] : '', 'content_type' => $install_method, 'home_id' => (int)$home_id, 'home_cfg_id' => (int)$home_info['home_cfg_id'], 'action' => 'failed', 'error' => trim((string)$script_output)));
|
||||
print_failure($error_msg);
|
||||
}
|
||||
echo "<p><a href=\"?m=addonsmanager&p=user_addons&home_id=$home_id&mod_id=$mod_id&ip=$ip&port=$port\">".get_lang('back')."</a></p>";
|
||||
return;
|
||||
}
|
||||
if ($install_method === 'config_edit' || $install_method === 'create_folder') {
|
||||
$placeholder_map = scm_build_placeholder_map($home_info, array('exe_location' => (string)$server_xml->exe_location));
|
||||
$target_template = trim((string)$addon_info['path']);
|
||||
$resolved_path = scm_apply_placeholders($target_template, $placeholder_map);
|
||||
if ($resolved_path === '' || strpos($resolved_path, '/') !== 0) {
|
||||
$resolved_path = clean_path(rtrim($home_info['home_path'], '/') . '/' . ltrim($resolved_path, '/'));
|
||||
}
|
||||
$ok = false;
|
||||
if ($install_method === 'create_folder') {
|
||||
$ok = is_string($remote->exec("mkdir -p " . escapeshellarg($resolved_path) . " && echo __GSP_FOLDER_OK"));
|
||||
} else {
|
||||
$config_rule = trim((string)$addon_info['config_edit_rule']);
|
||||
$dir = dirname($resolved_path);
|
||||
$cmd = "mkdir -p " . escapeshellarg($dir) . " && touch " . escapeshellarg($resolved_path) . " && printf %s " . escapeshellarg($config_rule . PHP_EOL) . " >> " . escapeshellarg($resolved_path) . " && echo __GSP_CONFIG_OK";
|
||||
$out = $remote->exec($cmd);
|
||||
$ok = is_string($out) && strpos($out, '__GSP_CONFIG_OK') !== false;
|
||||
}
|
||||
if ($ok) {
|
||||
scm_record_install_done($db, (int)$history_id, 'installed', 0, $install_method . '_ok');
|
||||
scm_upsert_manifest($db, $home_id, $addon_id, array('install_method' => $install_method, 'content_version' => $content_version, 'install_state' => 'installed', 'source_url' => '', 'installed_by' => $user_id));
|
||||
scm_log_content_install_action(array('addon_id' => (int)$addon_id, 'addon_name' => isset($addon_info['name']) ? $addon_info['name'] : '', 'content_type' => $install_method, 'home_id' => (int)$home_id, 'home_cfg_id' => (int)$home_info['home_cfg_id'], 'target_path' => $resolved_path, 'action' => 'succeeded'));
|
||||
print_success(get_lang('addon_installed_successfully'));
|
||||
} else {
|
||||
scm_record_install_done($db, (int)$history_id, 'failed', 1, $install_method . '_failed');
|
||||
scm_log_content_install_action(array('addon_id' => (int)$addon_id, 'addon_name' => isset($addon_info['name']) ? $addon_info['name'] : '', 'content_type' => $install_method, 'home_id' => (int)$home_id, 'home_cfg_id' => (int)$home_info['home_cfg_id'], 'target_path' => $resolved_path, 'action' => 'failed', 'error' => $install_method . '_failed'));
|
||||
print_failure('Content action failed.');
|
||||
}
|
||||
echo "<p><a href=\"?m=addonsmanager&p=user_addons&home_id=$home_id&mod_id=$mod_id&ip=$ip&port=$port\">".get_lang('back')."</a></p>";
|
||||
return;
|
||||
}
|
||||
$download_action = ($install_method === 'download_file') ? "" : "uncompress";
|
||||
$pid = $remote->start_file_download( $addon_info['url'], $home_info['home_path']."/".$addon_info['path'], $filename, $download_action, $post_script);
|
||||
}
|
||||
|
||||
$headers = get_headers($url, 1);
|
||||
|
|
@ -319,10 +485,22 @@ function exec_ogp_module() {
|
|||
if(!$download_available)
|
||||
{
|
||||
print_failure(get_lang('failed_to_start_file_download'));
|
||||
scm_log_content_install_action(array(
|
||||
'addon_id' => (int)$addon_id,
|
||||
'addon_name' => isset($addon_info['name']) ? $addon_info['name'] : '',
|
||||
'content_type' => $install_method,
|
||||
'home_id' => (int)$home_id,
|
||||
'home_cfg_id' => (int)$home_info['home_cfg_id'],
|
||||
'action' => 'failed',
|
||||
'error' => 'failed_to_start_file_download',
|
||||
));
|
||||
}
|
||||
elseif( $remote->is_file_download_in_progress($pid) === 1 )
|
||||
{
|
||||
print_success(get_lang_f('wait_while_decompressing', $filename));
|
||||
if ($install_method === 'download_zip')
|
||||
print_success(get_lang_f('wait_while_decompressing', $filename));
|
||||
else
|
||||
print_success(get_lang('install') . " " . $filename . "...");
|
||||
echo "<p><a href=\"?m=addonsmanager&p=addons&state=refresh&home_id=$home_id&mod_id=$mod_id".
|
||||
"&ip=$ip&port=$port&addon_id=$addon_id&pid=$pid\">".get_lang('refresh')."</a></p>";
|
||||
$view->refresh("?m=addonsmanager&p=addons&state=refresh&home_id=$home_id&mod_id=$mod_id".
|
||||
|
|
@ -344,6 +522,15 @@ function exec_ogp_module() {
|
|||
'source_url' => $addon_info['url'],
|
||||
'installed_by' => $user_id,
|
||||
));
|
||||
scm_log_content_install_action(array(
|
||||
'addon_id' => (int)$addon_id,
|
||||
'addon_name' => isset($addon_info['name']) ? $addon_info['name'] : '',
|
||||
'content_type' => $install_method,
|
||||
'home_id' => (int)$home_id,
|
||||
'home_cfg_id' => (int)$home_info['home_cfg_id'],
|
||||
'target_path' => isset($addon_info['path']) ? (string)$addon_info['path'] : '',
|
||||
'action' => 'succeeded',
|
||||
));
|
||||
echo "<p><a href=\"?m=addonsmanager&p=user_addons&home_id=$home_id".
|
||||
"&mod_id=$mod_id&ip=$ip&port=$port\">".get_lang('back')."</a></p>";
|
||||
$view->refresh("?m=addonsmanager&p=user_addons&home_id=$home_id".
|
||||
|
|
|
|||
|
|
@ -41,32 +41,16 @@ function exec_ogp_module() {
|
|||
$addon_type_labels = get_server_content_categories(); // key => label
|
||||
$install_methods = scm_get_install_methods(); // install_method keys => labels
|
||||
|
||||
if (isset($_POST['create_addon']) AND isset($_POST['name']) AND $_POST['url']=="")
|
||||
if (isset($_POST['create_addon']))
|
||||
{
|
||||
print_failure(get_lang("fill_the_url_address_to_a_compressed_file"));
|
||||
}
|
||||
elseif(isset($_POST['create_addon']) AND isset($_POST['url']) AND $_POST['name']=="")
|
||||
{
|
||||
print_failure(get_lang("fill_the_addon_name"));
|
||||
}
|
||||
elseif(isset($_POST['create_addon']) AND isset($_POST['name']) and isset($_POST['url']) and empty($_POST['addon_type']) )
|
||||
{
|
||||
print_failure(get_lang("select_an_addon_type"));
|
||||
}
|
||||
elseif(isset($_POST['create_addon']) AND isset($_POST['name']) and isset($_POST['url']) and isset($_POST['addon_type']) and empty($_POST['home_cfg_id']) )
|
||||
{
|
||||
print_failure(get_lang("select_a_game_type"));
|
||||
}
|
||||
elseif (isset($_POST['create_addon']) AND isset($_POST['name']) AND isset($_POST['url']) AND isset($_POST['addon_type']) and isset($_POST['home_cfg_id']) )
|
||||
{
|
||||
$valid_install_methods = array_keys($install_methods);
|
||||
$fields['name'] = $_POST['name'];
|
||||
$fields['url'] = $_POST['url'];
|
||||
$fields['path'] = $_POST['path'];
|
||||
$fields['addon_type'] = $_POST['addon_type'];
|
||||
$fields['home_cfg_id'] = $_POST['home_cfg_id'];
|
||||
$fields['post_script'] = $_POST['post_script'];
|
||||
$fields['group_id'] = $_POST['group_id'];
|
||||
$fields['name'] = isset($_POST['name']) ? trim((string)$_POST['name']) : '';
|
||||
$fields['url'] = isset($_POST['url']) ? trim((string)$_POST['url']) : '';
|
||||
$fields['path'] = isset($_POST['path']) ? trim((string)$_POST['path']) : '';
|
||||
$fields['addon_type'] = isset($_POST['addon_type']) ? trim((string)$_POST['addon_type']) : '';
|
||||
$fields['home_cfg_id'] = isset($_POST['home_cfg_id']) ? (int)$_POST['home_cfg_id'] : 0;
|
||||
$fields['post_script'] = isset($_POST['post_script']) ? trim((string)$_POST['post_script']) : '';
|
||||
$fields['group_id'] = isset($_POST['group_id']) ? (int)$_POST['group_id'] : 0;
|
||||
$fields['install_method'] = in_array($_POST['install_method'], $valid_install_methods) ? $_POST['install_method'] : 'download_zip';
|
||||
$fields['content_version'] = isset($_POST['content_version']) ? $_POST['content_version'] : '';
|
||||
$fields['requires_stop'] = !empty($_POST['requires_stop']) ? 1 : 0;
|
||||
|
|
@ -74,11 +58,46 @@ function exec_ogp_module() {
|
|||
$fields['restart_after_install'] = !empty($_POST['restart_after_install']) ? 1 : 0;
|
||||
$fields['is_cacheable'] = !empty($_POST['is_cacheable']) ? 1 : 0;
|
||||
$fields['description'] = isset($_POST['description']) ? $_POST['description'] : '';
|
||||
if( is_numeric($db->resultInsertId( 'addons', $fields )) )
|
||||
$fields['workshop_item_id'] = isset($_POST['workshop_item_id']) ? trim((string)$_POST['workshop_item_id']) : '';
|
||||
$fields['workshop_app_id'] = isset($_POST['workshop_app_id']) ? trim((string)$_POST['workshop_app_id']) : '';
|
||||
$fields['target_path_template']= isset($_POST['target_path_template']) ? trim((string)$_POST['target_path_template']) : '';
|
||||
$fields['optional_folder_name']= isset($_POST['optional_folder_name']) ? trim((string)$_POST['optional_folder_name']) : '';
|
||||
$fields['config_edit_rule'] = isset($_POST['config_edit_rule']) ? trim((string)$_POST['config_edit_rule']) : '';
|
||||
$fields['launch_param_additions'] = isset($_POST['launch_param_additions']) ? trim((string)$_POST['launch_param_additions']) : '';
|
||||
|
||||
if ($fields['name'] === '')
|
||||
{
|
||||
print_success(get_lang_f("addon_has_been_created",$_POST['name']));
|
||||
if (isset($_POST['addon_id']) && (int)$_POST['addon_id'] > 0 && isset($_POST['edit']))
|
||||
$db->query("DELETE FROM OGP_DB_PREFIXaddons WHERE addon_id=" . (int)$_POST['addon_id']);
|
||||
print_failure(get_lang("fill_the_addon_name"));
|
||||
}
|
||||
elseif (empty($fields['addon_type']) || !in_array($fields['addon_type'], $addon_types))
|
||||
{
|
||||
print_failure(get_lang("select_an_addon_type"));
|
||||
}
|
||||
elseif (empty($fields['home_cfg_id']))
|
||||
{
|
||||
print_failure(get_lang("select_a_game_type"));
|
||||
}
|
||||
else
|
||||
{
|
||||
$validation_payload = array(
|
||||
'url' => $fields['url'],
|
||||
'path' => $fields['path'],
|
||||
'workshop_item_id' => $fields['workshop_item_id'],
|
||||
'target_path_template' => $fields['target_path_template'],
|
||||
'post_script' => $fields['post_script'],
|
||||
'config_edit_rule' => $fields['config_edit_rule'],
|
||||
);
|
||||
$validation_message = '';
|
||||
if (!scm_validate_install_method_payload($fields['install_method'], $validation_payload, $validation_message))
|
||||
{
|
||||
print_failure($validation_message);
|
||||
}
|
||||
elseif (is_numeric($db->resultInsertId('addons', $fields)))
|
||||
{
|
||||
print_success(get_lang_f("addon_has_been_created", $fields['name']));
|
||||
if (isset($_POST['addon_id']) && (int)$_POST['addon_id'] > 0 && isset($_POST['edit']))
|
||||
$db->query("DELETE FROM OGP_DB_PREFIXaddons WHERE addon_id=" . (int)$_POST['addon_id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -97,6 +116,12 @@ function exec_ogp_module() {
|
|||
$restart_after_install = isset($_POST['restart_after_install']) ? (int)$_POST['restart_after_install'] : 0;
|
||||
$is_cacheable = isset($_POST['is_cacheable']) ? (int)$_POST['is_cacheable'] : 0;
|
||||
$description = isset($_POST['description']) ? $_POST['description'] : "";
|
||||
$workshop_item_id = isset($_POST['workshop_item_id']) ? $_POST['workshop_item_id'] : "";
|
||||
$workshop_app_id = isset($_POST['workshop_app_id']) ? $_POST['workshop_app_id'] : "";
|
||||
$target_path_template = isset($_POST['target_path_template']) ? $_POST['target_path_template'] : "";
|
||||
$optional_folder_name = isset($_POST['optional_folder_name']) ? $_POST['optional_folder_name'] : "";
|
||||
$config_edit_rule = isset($_POST['config_edit_rule']) ? $_POST['config_edit_rule'] : "";
|
||||
$launch_param_additions = isset($_POST['launch_param_additions']) ? $_POST['launch_param_additions'] : "";
|
||||
|
||||
if (isset($_POST['addon_id']) && (int)$_POST['addon_id'] > 0 && isset($_POST['edit']))
|
||||
{
|
||||
|
|
@ -119,6 +144,12 @@ function exec_ogp_module() {
|
|||
$restart_after_install = isset($addon_info['restart_after_install']) ? (int)$addon_info['restart_after_install'] : 0;
|
||||
$is_cacheable = isset($addon_info['is_cacheable']) ? (int)$addon_info['is_cacheable'] : 0;
|
||||
$description = isset($addon_info['description']) ? $addon_info['description'] : "";
|
||||
$workshop_item_id = isset($addon_info['workshop_item_id']) ? $addon_info['workshop_item_id'] : "";
|
||||
$workshop_app_id = isset($addon_info['workshop_app_id']) ? $addon_info['workshop_app_id'] : "";
|
||||
$target_path_template = isset($addon_info['target_path_template']) ? $addon_info['target_path_template'] : "";
|
||||
$optional_folder_name = isset($addon_info['optional_folder_name']) ? $addon_info['optional_folder_name'] : "";
|
||||
$config_edit_rule = isset($addon_info['config_edit_rule']) ? $addon_info['config_edit_rule'] : "";
|
||||
$launch_param_additions = isset($addon_info['launch_param_additions']) ? $addon_info['launch_param_additions'] : "";
|
||||
}
|
||||
?>
|
||||
<form action="" method="post">
|
||||
|
|
@ -131,7 +162,25 @@ function exec_ogp_module() {
|
|||
<input type="text" value="<?php echo $name; ?>" name="name" size="85" title="<?php print_lang('addon_name_info'); ?>" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr id="scm-row-install-method">
|
||||
<td align="right">
|
||||
<b><?php print_lang('content_type'); ?></b>
|
||||
</td>
|
||||
<td align="left">
|
||||
<select name="install_method" id="scm-install-method">
|
||||
<?php
|
||||
$install_help = scm_get_install_method_help_text();
|
||||
foreach ((array)$install_methods as $method_key => $method_label) {
|
||||
$sel = ($method_key == $install_method) ? 'selected="selected"' : '';
|
||||
$help = isset($install_help[$method_key]) ? $install_help[$method_key] : '';
|
||||
echo '<option value="'.htmlspecialchars($method_key).'" data-help="'.htmlspecialchars($help, ENT_QUOTES, 'UTF-8').'" '.$sel.'>'.htmlspecialchars($method_label).'</option>'."\n";
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<div id="scm-install-method-help" style="color:#666;margin-top:4px;"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="scm-row-url">
|
||||
<td align="right">
|
||||
<b><?php print_lang('url'); ?></b>
|
||||
</td>
|
||||
|
|
@ -141,17 +190,50 @@ function exec_ogp_module() {
|
|||
</tr>
|
||||
<!-- Destination path — must be relative to the game server home directory.
|
||||
Path traversal (../) is not allowed; the agent enforces this. -->
|
||||
<tr>
|
||||
<tr id="scm-row-path">
|
||||
<td align="right">
|
||||
<b><?php print_lang('path'); ?></b>
|
||||
<b id="scm-path-label"><?php print_lang('path'); ?></b>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input type="text" value="<?php echo $path; ?>" name="path" size="85" title="<?php print_lang('path_info'); ?>" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr id="scm-row-workshop-id">
|
||||
<td align="right">
|
||||
<b><?php print_lang('post-script'); ?></b><br>
|
||||
<b><?php print_lang('workshop_id'); ?></b>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input type="text" value="<?php echo htmlspecialchars($workshop_item_id, ENT_QUOTES, 'UTF-8'); ?>" name="workshop_item_id" size="85" placeholder="e.g. 450814997" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="scm-row-workshop-app-id">
|
||||
<td align="right">
|
||||
<b>Workshop App ID</b>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input type="text" value="<?php echo htmlspecialchars($workshop_app_id, ENT_QUOTES, 'UTF-8'); ?>" name="workshop_app_id" size="85" placeholder="Optional override, e.g. 221100" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="scm-row-target-path-template">
|
||||
<td align="right">
|
||||
<b><?php print_lang('target_path_template'); ?></b>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input type="text" value="<?php echo htmlspecialchars($target_path_template, ENT_QUOTES, 'UTF-8'); ?>" name="target_path_template" size="85" placeholder="{SERVER_ROOT}/mods/{WORKSHOP_ID}" />
|
||||
<small style="color:#666;">Supported placeholders: {HOME_ID}, {SERVER_ROOT}, {GAME_ROOT}, {WORKSHOP_ID}, {WORKSHOP_APP_ID}, {STEAM_APP_ID}</small>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="scm-row-optional-folder-name">
|
||||
<td align="right">
|
||||
<b><?php print_lang('optional_folder_name'); ?></b>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input type="text" value="<?php echo htmlspecialchars($optional_folder_name, ENT_QUOTES, 'UTF-8'); ?>" name="optional_folder_name" size="85" placeholder="@MyWorkshopMod" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="scm-row-post-script">
|
||||
<td align="right">
|
||||
<b>Post-Install Script / Action</b><br>
|
||||
<u><?php print_lang('replacements'); ?></u><br>
|
||||
%home_path%<br>
|
||||
%home_name%<br>
|
||||
|
|
@ -166,6 +248,22 @@ function exec_ogp_module() {
|
|||
<textarea name="post_script" style="width:99%;height:175px;" title="<?php print_lang('post-script_info'); ?>" ><?php echo strip_real_escape_string($post_script); ?></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="scm-row-config-edit-rule">
|
||||
<td align="right">
|
||||
<b><?php print_lang('config_edit_rule'); ?></b>
|
||||
</td>
|
||||
<td align="left">
|
||||
<textarea name="config_edit_rule" style="width:99%;height:90px;" placeholder="Text/rules to append or apply to the target config."><?php echo htmlspecialchars($config_edit_rule, ENT_QUOTES, 'UTF-8'); ?></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="scm-row-launch-param-additions">
|
||||
<td align="right">
|
||||
<b><?php print_lang('launch_param_additions'); ?></b>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input type="text" value="<?php echo htmlspecialchars($launch_param_additions, ENT_QUOTES, 'UTF-8'); ?>" name="launch_param_additions" size="85" placeholder="-mod=@myMod;@anotherMod" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<b><?php print_lang('select_game_type'); ?></b>
|
||||
|
|
@ -241,23 +339,6 @@ function exec_ogp_module() {
|
|||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- ── Phase 2 fields ────────────────────────────────────────────────── -->
|
||||
<tr>
|
||||
<td align="right">
|
||||
<b>Install Method</b>
|
||||
</td>
|
||||
<td align="left">
|
||||
<select name="install_method">
|
||||
<?php
|
||||
foreach ((array)$install_methods as $method_key => $method_label) {
|
||||
$sel = ($method_key == $install_method) ? 'selected="selected"' : '';
|
||||
echo '<option value="'.htmlspecialchars($method_key).'" '.$sel.'>'.htmlspecialchars($method_label).'</option>'."\n";
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<small style="color:#666;"> The mechanism used to deliver this content to the server.</small>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<b>Content Version</b>
|
||||
|
|
@ -313,7 +394,6 @@ function exec_ogp_module() {
|
|||
</small>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- ── end Phase 2 fields ─────────────────────────────────────────────── -->
|
||||
<tr>
|
||||
<td colspan="2" align="center">
|
||||
<?php
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@
|
|||
|
||||
// Module general information
|
||||
$module_title = "Server Content Manager";
|
||||
$module_version = "2.2";
|
||||
$db_version = 4;
|
||||
$module_version = "2.3";
|
||||
$db_version = 5;
|
||||
$module_required = TRUE;
|
||||
$module_menus = array(
|
||||
array( 'subpage' => 'addons_manager', 'name' => 'Server Content Manager', 'group' => 'admin' )
|
||||
|
|
@ -165,4 +165,35 @@ $install_queries[3] = array(
|
|||
return true;
|
||||
},
|
||||
);
|
||||
|
||||
// ── db_version 5 : content-type specific metadata for Workshop/config/folder actions ──
|
||||
$install_queries[4] = array(
|
||||
function ($db) {
|
||||
$prefix = OGP_DB_PREFIX;
|
||||
$new_columns = array(
|
||||
'workshop_item_id' => "VARCHAR(64) NULL AFTER `description`",
|
||||
'workshop_app_id' => "VARCHAR(32) NULL AFTER `workshop_item_id`",
|
||||
'target_path_template' => "VARCHAR(255) NULL AFTER `workshop_app_id`",
|
||||
'optional_folder_name' => "VARCHAR(255) NULL AFTER `target_path_template`",
|
||||
'config_edit_rule' => "TEXT NULL AFTER `optional_folder_name`",
|
||||
'launch_param_additions' => "VARCHAR(255) NULL AFTER `config_edit_rule`",
|
||||
);
|
||||
foreach ($new_columns as $col => $definition) {
|
||||
$escaped_col = $db->realEscapeSingle($col);
|
||||
$escaped_table = $db->realEscapeSingle($prefix . 'addons');
|
||||
$check = $db->resultQuery(
|
||||
"SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = '{$escaped_table}'
|
||||
AND COLUMN_NAME = '{$escaped_col}'"
|
||||
);
|
||||
if (empty($check)) {
|
||||
if (!$db->query("ALTER TABLE `{$prefix}addons` ADD COLUMN `{$col}` {$definition}")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
);
|
||||
?>
|
||||
|
|
|
|||
|
|
@ -255,15 +255,146 @@ function scm_get_cache_mode($db)
|
|||
function scm_get_install_methods()
|
||||
{
|
||||
return array(
|
||||
'download_zip' => 'Download & extract archive (.zip / .tar.gz)',
|
||||
'download_file' => 'Download single file (no extraction)',
|
||||
'post_script' => 'Run post-script only (no download)',
|
||||
'steam_workshop' => 'Steam Workshop (via agent SteamCMD)',
|
||||
'minecraft_jar' => 'Minecraft server jar / version switcher',
|
||||
'profile_copy' => 'Copy stored profile directory',
|
||||
'download_zip' => 'Compressed file download',
|
||||
'download_file' => 'Direct file download',
|
||||
'steam_workshop' => 'Steam Workshop item',
|
||||
'post_script' => 'Script/action only',
|
||||
'config_edit' => 'Config edit only',
|
||||
'create_folder' => 'Folder/create path only',
|
||||
);
|
||||
}
|
||||
|
||||
function scm_get_install_method_help_text()
|
||||
{
|
||||
return array(
|
||||
'download_zip' => 'Downloads and extracts an archive into the target path.',
|
||||
'download_file' => 'Downloads a single file to the target path without extraction.',
|
||||
'steam_workshop' => 'Downloads/updates a Steam Workshop item and applies it to the server path.',
|
||||
'post_script' => 'Runs only the post-install script/action body (no download).',
|
||||
'config_edit' => 'Applies config edit rules to a target config file/path.',
|
||||
'create_folder' => 'Creates the target directory path only.',
|
||||
);
|
||||
}
|
||||
|
||||
function scm_get_install_method_required_fields()
|
||||
{
|
||||
return array(
|
||||
'download_zip' => array('url', 'path'),
|
||||
'download_file' => array('url', 'path'),
|
||||
'steam_workshop' => array('workshop_item_id', 'target_path_template'),
|
||||
'post_script' => array('post_script'),
|
||||
'config_edit' => array('path', 'config_edit_rule'),
|
||||
'create_folder' => array('path'),
|
||||
);
|
||||
}
|
||||
|
||||
function scm_get_install_method_validation_errors()
|
||||
{
|
||||
return array(
|
||||
'url' => 'Please enter a download URL.',
|
||||
'workshop_item_id' => 'Please enter a Workshop ID.',
|
||||
'target_path_template' => 'Please select a target install path.',
|
||||
'post_script' => 'Please enter a script/action body.',
|
||||
'config_edit_rule' => 'Please enter a config edit rule.',
|
||||
'path' => 'Please select a target install path.',
|
||||
);
|
||||
}
|
||||
|
||||
function scm_get_install_method_default($value = '')
|
||||
{
|
||||
$methods = scm_get_install_methods();
|
||||
$value = trim((string)$value);
|
||||
return isset($methods[$value]) ? $value : 'download_zip';
|
||||
}
|
||||
|
||||
function scm_validate_install_method_payload($install_method, array $payload, &$message = '')
|
||||
{
|
||||
$install_method = scm_get_install_method_default($install_method);
|
||||
$required = scm_get_install_method_required_fields();
|
||||
$errors = scm_get_install_method_validation_errors();
|
||||
if (!isset($required[$install_method])) {
|
||||
$message = 'Invalid install/content type selected.';
|
||||
return false;
|
||||
}
|
||||
foreach ($required[$install_method] as $field) {
|
||||
$value = isset($payload[$field]) ? trim((string)$payload[$field]) : '';
|
||||
if ($value === '') {
|
||||
$message = isset($errors[$field]) ? $errors[$field] : 'Missing required field.';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ($install_method === 'steam_workshop') {
|
||||
$wid = isset($payload['workshop_item_id']) ? trim((string)$payload['workshop_item_id']) : '';
|
||||
if ($wid === '' || !preg_match('/^[0-9]+$/', $wid)) {
|
||||
$message = 'Please enter a Workshop ID.';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$message = '';
|
||||
return true;
|
||||
}
|
||||
|
||||
function scm_build_placeholder_map(array $home_info, array $server_context = array(), array $overrides = array())
|
||||
{
|
||||
$home_id = (int)(isset($home_info['home_id']) ? $home_info['home_id'] : 0);
|
||||
$server_root = rtrim(clean_path((string)(isset($home_info['home_path']) ? $home_info['home_path'] : '')), '/');
|
||||
$game_root = $server_root;
|
||||
if (!empty($server_context['exe_location'])) {
|
||||
$exe_location = clean_path((string)$server_context['exe_location']);
|
||||
$exe_dir = dirname($exe_location);
|
||||
if ($exe_dir !== '.' && $exe_dir !== '/') {
|
||||
$game_root = clean_path($server_root . '/' . ltrim($exe_dir, '/'));
|
||||
}
|
||||
}
|
||||
$map = array(
|
||||
'{HOME_ID}' => (string)$home_id,
|
||||
'{SERVER_ROOT}' => $server_root,
|
||||
'{GAME_ROOT}' => $game_root,
|
||||
'{WORKSHOP_ID}' => '',
|
||||
'{WORKSHOP_APP_ID}' => '',
|
||||
'{STEAM_APP_ID}' => '',
|
||||
);
|
||||
foreach ($overrides as $key => $value) {
|
||||
$token = '{' . strtoupper(trim((string)$key, '{}')) . '}';
|
||||
$map[$token] = (string)$value;
|
||||
}
|
||||
return $map;
|
||||
}
|
||||
|
||||
function scm_apply_placeholders($template, array $placeholder_map)
|
||||
{
|
||||
$template = (string)$template;
|
||||
if ($template === '') {
|
||||
return '';
|
||||
}
|
||||
return str_replace(array_keys($placeholder_map), array_values($placeholder_map), $template);
|
||||
}
|
||||
|
||||
function scm_content_logs_dir()
|
||||
{
|
||||
return dirname(__FILE__) . '/logs';
|
||||
}
|
||||
|
||||
function scm_content_log_file()
|
||||
{
|
||||
return scm_content_logs_dir() . '/content_install.log';
|
||||
}
|
||||
|
||||
function scm_log_content_install_action(array $context)
|
||||
{
|
||||
$dir = scm_content_logs_dir();
|
||||
if (!is_dir($dir)) {
|
||||
@mkdir($dir, 0775, true);
|
||||
}
|
||||
$context['logged_at'] = date('Y-m-d H:i:s');
|
||||
$line = json_encode($context);
|
||||
if ($line === false) {
|
||||
$line = '{"logged_at":"' . date('Y-m-d H:i:s') . '","error":"json_encode_failed"}';
|
||||
}
|
||||
@error_log($line . PHP_EOL, 3, scm_content_log_file());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Idempotently ensures the Phase 2 schema is present.
|
||||
* Called from pages that use manifest / history data so that existing
|
||||
|
|
@ -290,6 +421,12 @@ function scm_ensure_phase2_schema($db)
|
|||
'restart_after_install' => "TINYINT(1) NOT NULL DEFAULT 0",
|
||||
'is_cacheable' => "TINYINT(1) NOT NULL DEFAULT 0",
|
||||
'description' => "TEXT NULL",
|
||||
'workshop_item_id' => "VARCHAR(64) NULL",
|
||||
'workshop_app_id' => "VARCHAR(32) NULL",
|
||||
'target_path_template' => "VARCHAR(255) NULL",
|
||||
'optional_folder_name' => "VARCHAR(255) NULL",
|
||||
'config_edit_rule' => "TEXT NULL",
|
||||
'launch_param_additions'=> "VARCHAR(255) NULL",
|
||||
);
|
||||
foreach ($new_columns as $col => $definition) {
|
||||
$escaped_col = $db->realEscapeSingle($col);
|
||||
|
|
@ -489,4 +626,3 @@ function scm_upsert_manifest($db, $home_id, $addon_id, array $fields = array())
|
|||
updated_at = NOW()"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ function scm_workshop_filter_existing_ids($db, $home_id, array $item_ids)
|
|||
return array_values($allowed);
|
||||
}
|
||||
|
||||
function scm_workshop_write_manifest_and_run($db, array $home_info, $server_xml, $action, array $item_ids, &$error = '')
|
||||
function scm_workshop_write_manifest_and_run($db, array $home_info, $server_xml, $action, array $item_ids, &$error = '', array $extra_manifest = array())
|
||||
{
|
||||
$error = '';
|
||||
if (empty($item_ids)) {
|
||||
|
|
@ -102,6 +102,9 @@ function scm_workshop_write_manifest_and_run($db, array $home_info, $server_xml,
|
|||
'workshop_app_id' => scm_extract_workshop_app_id($server_xml),
|
||||
'items' => array_values($item_ids),
|
||||
);
|
||||
if (!empty($extra_manifest)) {
|
||||
$manifest['extra'] = $extra_manifest;
|
||||
}
|
||||
$manifest_json = json_encode($manifest);
|
||||
if ($manifest_json === false) {
|
||||
$error = 'Failed to encode workshop manifest JSON.';
|
||||
|
|
@ -274,4 +277,3 @@ function scm_workshop_handle_action($db, array $home_info, $user_id, $action, $r
|
|||
$message = 'Invalid workshop action.';
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -577,3 +577,61 @@ function sw_apply_detected_profile_defaults($db, array $profile, array $detected
|
|||
);
|
||||
return $updated;
|
||||
}
|
||||
|
||||
function steam_workshop_resolve_paths($db, array $home_info, $workshop_id, $target_path_template = '', $optional_folder_name = '', $workshop_app_id_override = '')
|
||||
{
|
||||
$profile = sw_get_profile_for_home($db, (int)$home_info['home_id']);
|
||||
if (!$profile || !is_array($profile)) {
|
||||
return array('ok' => false, 'error' => 'No enabled Steam Workshop profile for this server home.');
|
||||
}
|
||||
$workshop_id = trim((string)$workshop_id);
|
||||
if ($workshop_id === '' || !preg_match('/^[0-9]+$/', $workshop_id)) {
|
||||
return array('ok' => false, 'error' => 'Invalid Workshop ID.');
|
||||
}
|
||||
$workshop_app_id = trim((string)$workshop_app_id_override);
|
||||
if ($workshop_app_id === '') {
|
||||
$workshop_app_id = (string)$profile['workshop_app_id'];
|
||||
}
|
||||
$folder_name = trim((string)$optional_folder_name);
|
||||
if ($folder_name === '') {
|
||||
$folder_name = '@' . $workshop_id;
|
||||
}
|
||||
$vars = array(
|
||||
'HOME_ID' => (int)$home_info['home_id'],
|
||||
'SERVER_ROOT' => rtrim((string)$home_info['home_path'], '/'),
|
||||
'GAME_ROOT' => rtrim((string)$home_info['home_path'], '/'),
|
||||
'WORKSHOP_ID' => $workshop_id,
|
||||
'WORKSHOP_APP_ID' => $workshop_app_id,
|
||||
'STEAM_APP_ID' => (string)$profile['steam_app_id'],
|
||||
'FOLDER_NAME' => $folder_name,
|
||||
'MOD_FOLDER' => $folder_name,
|
||||
);
|
||||
$target_template = trim((string)$target_path_template);
|
||||
if ($target_template === '') {
|
||||
$target_template = !empty($profile['install_path_template']) ? (string)$profile['install_path_template'] : '{SERVER_ROOT}/{MOD_FOLDER}';
|
||||
}
|
||||
$resolved_target = sw_apply_template($target_template, $vars);
|
||||
return array(
|
||||
'ok' => true,
|
||||
'profile' => $profile,
|
||||
'workshop_id' => $workshop_id,
|
||||
'workshop_app_id' => $workshop_app_id,
|
||||
'steam_app_id' => (string)$profile['steam_app_id'],
|
||||
'folder_name' => $folder_name,
|
||||
'target_path_template' => $target_template,
|
||||
'target_path_resolved' => $resolved_target,
|
||||
'vars' => $vars,
|
||||
);
|
||||
}
|
||||
|
||||
function steam_workshop_download_item($db, array $home_info, $workshop_id, $target_path_template = '', array $options = array())
|
||||
{
|
||||
$optional_folder_name = isset($options['optional_folder_name']) ? $options['optional_folder_name'] : '';
|
||||
$workshop_app_id = isset($options['workshop_app_id']) ? $options['workshop_app_id'] : '';
|
||||
return steam_workshop_resolve_paths($db, $home_info, $workshop_id, $target_path_template, $optional_folder_name, $workshop_app_id);
|
||||
}
|
||||
|
||||
function steam_workshop_install_item_to_home($db, array $home_info, $workshop_id, $target_path_template = '', array $options = array())
|
||||
{
|
||||
return steam_workshop_download_item($db, $home_info, $workshop_id, $target_path_template, $options);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1357,6 +1357,10 @@ function api_litefm()
|
|||
function api_addonsmanager()
|
||||
{
|
||||
global $request, $db, $user_info;
|
||||
require_once(MODULES.'addonsmanager/server_content_helpers.php');
|
||||
require_once(MODULES.'addonsmanager/workshop_action.php');
|
||||
if (file_exists(MODULES.'steam_workshop/includes/functions.php'))
|
||||
require_once(MODULES.'steam_workshop/includes/functions.php');
|
||||
|
||||
if($db->isModuleInstalled('addonsmanager') === FALSE)
|
||||
return array("status" => '349', "message" => "This function is not available because the module is not installed.");
|
||||
|
|
@ -1427,9 +1431,22 @@ function api_addonsmanager()
|
|||
|
||||
$addon_info = $addons_rows[0];
|
||||
|
||||
$install_method = scm_get_install_method_default(isset($addon_info['install_method']) ? $addon_info['install_method'] : 'download_zip');
|
||||
$validation_payload = array(
|
||||
'url' => isset($addon_info['url']) ? $addon_info['url'] : '',
|
||||
'path' => isset($addon_info['path']) ? $addon_info['path'] : '',
|
||||
'workshop_item_id' => isset($addon_info['workshop_item_id']) ? $addon_info['workshop_item_id'] : '',
|
||||
'target_path_template' => isset($addon_info['target_path_template']) ? $addon_info['target_path_template'] : '',
|
||||
'post_script' => isset($addon_info['post_script']) ? $addon_info['post_script'] : '',
|
||||
'config_edit_rule' => isset($addon_info['config_edit_rule']) ? $addon_info['config_edit_rule'] : '',
|
||||
);
|
||||
$validation_message = '';
|
||||
if (!scm_validate_install_method_payload($install_method, $validation_payload, $validation_message))
|
||||
return array("status" => '422', "message" => $validation_message);
|
||||
$url = $addon_info['url'];
|
||||
$filename = basename($url);
|
||||
|
||||
$post_script = '';
|
||||
if($addon_info['post_script'] != "")
|
||||
{
|
||||
$addon_info['post_script'] = strip_real_escape_string($addon_info['post_script']);
|
||||
|
|
@ -1461,7 +1478,45 @@ function api_addonsmanager()
|
|||
$post_script = preg_replace( "/\%incremental\%/i", $home_info['incremental'], $post_script);
|
||||
}
|
||||
|
||||
$pid = $remote->start_file_download($addon_info['url'], $home_info['home_path']."/".$addon_info['path'], $filename, "uncompress", $post_script);
|
||||
if ($install_method === 'steam_workshop') {
|
||||
scm_ensure_workshop_schema($db);
|
||||
$workshop_item_id = trim((string)$addon_info['workshop_item_id']);
|
||||
$workshop_error = '';
|
||||
$extra_manifest = array(
|
||||
'addon_id' => (int)$addon_id,
|
||||
'target_path_template' => isset($addon_info['target_path_template']) ? (string)$addon_info['target_path_template'] : '',
|
||||
'optional_folder_name' => isset($addon_info['optional_folder_name']) ? (string)$addon_info['optional_folder_name'] : '',
|
||||
'config_edit_rule' => isset($addon_info['config_edit_rule']) ? (string)$addon_info['config_edit_rule'] : '',
|
||||
'launch_param_additions' => isset($addon_info['launch_param_additions']) ? (string)$addon_info['launch_param_additions'] : '',
|
||||
);
|
||||
$ok = scm_workshop_write_manifest_and_run($db, $home_info, $server_xml, 'install', array($workshop_item_id), $workshop_error, $extra_manifest);
|
||||
if ($ok)
|
||||
return array("status" => "200", "message" => "Workshop content installed successfully.");
|
||||
return array("status" => "342", "message" => "Workshop install failed: ".$workshop_error);
|
||||
}
|
||||
if ($install_method === 'post_script') {
|
||||
$output = $remote->exec("cd " . escapeshellarg($home_info['home_path']) . " && /bin/bash -lc " . escapeshellarg((string)$post_script) . " ; echo __GSP_SCRIPT_EXIT:$?");
|
||||
if (is_string($output) && preg_match('/__GSP_SCRIPT_EXIT:(\d+)/', $output, $m) && (int)$m[1] === 0)
|
||||
return array("status" => "200", "message" => "Script/action completed.");
|
||||
return array("status" => "342", "message" => "Script/action failed.");
|
||||
}
|
||||
if ($install_method === 'config_edit' || $install_method === 'create_folder') {
|
||||
$path = trim((string)$addon_info['path']);
|
||||
if ($path === '')
|
||||
return array("status" => "422", "message" => "Please select a target install path.");
|
||||
$target = (strpos($path, '/') === 0) ? $path : clean_path(rtrim($home_info['home_path'], '/') . '/' . ltrim($path, '/'));
|
||||
if ($install_method === 'create_folder')
|
||||
$out = $remote->exec("mkdir -p " . escapeshellarg($target) . " && echo __GSP_FOLDER_OK");
|
||||
else {
|
||||
$rule = trim((string)$addon_info['config_edit_rule']);
|
||||
$out = $remote->exec("mkdir -p " . escapeshellarg(dirname($target)) . " && touch " . escapeshellarg($target) . " && printf %s " . escapeshellarg($rule . PHP_EOL) . " >> " . escapeshellarg($target) . " && echo __GSP_CONFIG_OK");
|
||||
}
|
||||
if (is_string($out))
|
||||
return array("status" => "200", "message" => "Content action completed.");
|
||||
return array("status" => "342", "message" => "Content action failed.");
|
||||
}
|
||||
$download_action = ($install_method === 'download_file') ? "" : "uncompress";
|
||||
$pid = $remote->start_file_download($addon_info['url'], $home_info['home_path']."/".$addon_info['path'], $filename, $download_action, $post_script);
|
||||
if($pid > 0)
|
||||
{
|
||||
$status = "200";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue