steam fix copy
This commit is contained in:
parent
f7d4c3e11b
commit
8ab665ce3c
5 changed files with 129 additions and 70 deletions
|
|
@ -42,8 +42,8 @@ define('LANG_open_workshop_page', "Open Workshop page");
|
||||||
define('LANG_unable_to_contact_steam_workshop', "Unable to contact the Steam Workshop.");
|
define('LANG_unable_to_contact_steam_workshop', "Unable to contact the Steam Workshop.");
|
||||||
define('LANG_unable_to_parse_steam_workshop_response', "Unable to parse the Steam Workshop response.");
|
define('LANG_unable_to_parse_steam_workshop_response', "Unable to parse the Steam Workshop response.");
|
||||||
define('LANG_failed_to_fetch_workshop_item_details', "Failed to fetch Workshop item details for %s.");
|
define('LANG_failed_to_fetch_workshop_item_details', "Failed to fetch Workshop item details for %s.");
|
||||||
define('LANG_copy_from_existing_workshop_config', "Copy From Existing Workshop Config");
|
define('LANG_copy_from_existing_workshop_config', "Copy Settings From Existing Workshop Config");
|
||||||
define('LANG_copy_from_existing_workshop_config_info', "Copy an existing Workshop XML into the currently selected game and OS configuration.");
|
define('LANG_copy_from_existing_workshop_config_info', "Copies Workshop configuration fields only. This does not copy installed mods or game server files.");
|
||||||
define('LANG_select_config_to_copy', "Select config to copy");
|
define('LANG_select_config_to_copy', "Select config to copy");
|
||||||
define('LANG_copy_selected_config', "Copy Selected Config");
|
define('LANG_copy_selected_config', "Copy Selected Config");
|
||||||
define('LANG_confirm_copy_workshop_config', "Confirm Workshop config copy");
|
define('LANG_confirm_copy_workshop_config', "Confirm Workshop config copy");
|
||||||
|
|
@ -51,7 +51,7 @@ define('LANG_workshop_config_copy_confirm_info', "Copy %s into %s and overwrite
|
||||||
define('LANG_invalid_workshop_config_copy_source', "Invalid Workshop config source.");
|
define('LANG_invalid_workshop_config_copy_source', "Invalid Workshop config source.");
|
||||||
define('LANG_cannot_copy_workshop_config_to_itself', "Cannot copy a Workshop config onto itself.");
|
define('LANG_cannot_copy_workshop_config_to_itself', "Cannot copy a Workshop config onto itself.");
|
||||||
define('LANG_failed_to_copy_workshop_config', "Failed to copy the selected Workshop config.");
|
define('LANG_failed_to_copy_workshop_config', "Failed to copy the selected Workshop config.");
|
||||||
define('LANG_workshop_config_copied', "Copied Workshop config %s to %s.");
|
define('LANG_workshop_config_copied', "Copied Workshop configuration settings from %s to %s.");
|
||||||
define('LANG_select_game', "Select Game");
|
define('LANG_select_game', "Select Game");
|
||||||
define('LANG_save_config', "Save Config");
|
define('LANG_save_config', "Save Config");
|
||||||
define('LANG_mod_key_not_found_from_xml', "Mod key %s not found from xml.");
|
define('LANG_mod_key_not_found_from_xml', "Mod key %s not found from xml.");
|
||||||
|
|
|
||||||
|
|
@ -102,46 +102,93 @@ function steam_workshop_list_existing_configs()
|
||||||
return $configs;
|
return $configs;
|
||||||
}
|
}
|
||||||
|
|
||||||
function steam_workshop_get_existing_config_options($exclude_filename = '')
|
function steam_workshop_get_config_display_label($filename, $config, $friendly_names = array())
|
||||||
|
{
|
||||||
|
$label = isset($friendly_names[$filename]) && trim((string)$friendly_names[$filename]) !== '' ? (string)$friendly_names[$filename].' - '.$filename : $filename;
|
||||||
|
$meta = array();
|
||||||
|
if(isset($config['workshop_id']) && $config['workshop_id'] !== '')
|
||||||
|
$meta[] = 'Workshop '.$config['workshop_id'];
|
||||||
|
if(isset($config['download_method']) && $config['download_method'] !== '')
|
||||||
|
$meta[] = $config['download_method'];
|
||||||
|
if(isset($config['mods_path']) && $config['mods_path'] !== '')
|
||||||
|
$meta[] = 'mods_path='.$config['mods_path'];
|
||||||
|
if(!empty($meta))
|
||||||
|
$label .= ' ['.implode(' | ', $meta).']';
|
||||||
|
return $label;
|
||||||
|
}
|
||||||
|
|
||||||
|
function steam_workshop_get_existing_config_options($exclude_filename = '', $friendly_names = array())
|
||||||
{
|
{
|
||||||
$options = array('' => get_lang('select_config_to_copy'));
|
$options = array('' => get_lang('select_config_to_copy'));
|
||||||
foreach(steam_workshop_list_existing_configs() as $basename => $config)
|
foreach(steam_workshop_list_existing_configs() as $basename => $config)
|
||||||
{
|
{
|
||||||
if($basename === $exclude_filename)
|
if($basename === $exclude_filename)
|
||||||
continue;
|
continue;
|
||||||
$label = $basename;
|
$options[$basename] = steam_workshop_get_config_display_label($basename, $config, $friendly_names);
|
||||||
$meta = array();
|
|
||||||
if($config['workshop_id'] !== '')
|
|
||||||
$meta[] = 'Workshop '.$config['workshop_id'];
|
|
||||||
if($config['download_method'] !== '')
|
|
||||||
$meta[] = $config['download_method'];
|
|
||||||
if($config['mods_path'] !== '')
|
|
||||||
$meta[] = 'mods_path='.$config['mods_path'];
|
|
||||||
if(!empty($meta))
|
|
||||||
$label .= ' ['.implode(' | ', $meta).']';
|
|
||||||
$options[$basename] = $label;
|
|
||||||
}
|
}
|
||||||
return $options;
|
return $options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function steam_workshop_is_safe_config_filename($filename)
|
||||||
|
{
|
||||||
|
$filename = (string)$filename;
|
||||||
|
if($filename === '')
|
||||||
|
return false;
|
||||||
|
if(strpos($filename, '/') !== false || strpos($filename, '\\') !== false || strpos($filename, '..') !== false)
|
||||||
|
return false;
|
||||||
|
if(pathinfo($filename, PATHINFO_EXTENSION) !== 'xml')
|
||||||
|
return false;
|
||||||
|
return preg_match('/^[A-Za-z0-9._-]+\.xml$/', $filename) === 1;
|
||||||
|
}
|
||||||
|
|
||||||
function steam_workshop_get_safe_config_copy_paths($selected_source, $destination_file)
|
function steam_workshop_get_safe_config_copy_paths($selected_source, $destination_file)
|
||||||
{
|
{
|
||||||
$selected_source = basename((string)$selected_source);
|
|
||||||
$destination_file = basename((string)$destination_file);
|
|
||||||
$config_dir = realpath(steam_workshop_get_configs_dir());
|
$config_dir = realpath(steam_workshop_get_configs_dir());
|
||||||
if($config_dir === false || $selected_source === '' || $destination_file === '')
|
$selected_source = (string)$selected_source;
|
||||||
|
$destination_file = (string)$destination_file;
|
||||||
|
if($config_dir === false || !steam_workshop_is_safe_config_filename($selected_source) || !steam_workshop_is_safe_config_filename($destination_file))
|
||||||
return array(false, false);
|
return array(false, false);
|
||||||
|
|
||||||
$source_path = realpath($config_dir.'/'.$selected_source);
|
$source_path = realpath($config_dir.'/'.$selected_source);
|
||||||
$destination_path = $config_dir.'/'.$destination_file;
|
$destination_path = $config_dir.'/'.$destination_file;
|
||||||
if($source_path === false || strpos($source_path, $config_dir.DIRECTORY_SEPARATOR) !== 0)
|
if($source_path === false || strpos($source_path, $config_dir.DIRECTORY_SEPARATOR) !== 0)
|
||||||
return array(false, false);
|
return array(false, false);
|
||||||
if(pathinfo($source_path, PATHINFO_EXTENSION) !== 'xml' || pathinfo($destination_path, PATHINFO_EXTENSION) !== 'xml')
|
if(file_exists($destination_path))
|
||||||
return array(false, false);
|
{
|
||||||
|
$destination_realpath = realpath($destination_path);
|
||||||
|
if($destination_realpath === false || strpos($destination_realpath, $config_dir.DIRECTORY_SEPARATOR) !== 0)
|
||||||
|
return array(false, false);
|
||||||
|
$destination_path = $destination_realpath;
|
||||||
|
}
|
||||||
|
|
||||||
return array($source_path, $destination_path);
|
return array($source_path, $destination_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function steam_workshop_copy_config_settings_only($source_path, $destination_path)
|
||||||
|
{
|
||||||
|
$source = new DOMDocument();
|
||||||
|
$source->preserveWhiteSpace = false;
|
||||||
|
if(!@$source->load($source_path) || !$source->documentElement)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$destination = new DOMDocument('1.0', 'UTF-8');
|
||||||
|
$destination->formatOutput = true;
|
||||||
|
$root = $destination->createElement('workshop_settings');
|
||||||
|
$destination->appendChild($root);
|
||||||
|
|
||||||
|
foreach($source->documentElement->childNodes as $child)
|
||||||
|
{
|
||||||
|
if($child->nodeType !== XML_ELEMENT_NODE)
|
||||||
|
continue;
|
||||||
|
if($child->nodeName === 'mods')
|
||||||
|
continue;
|
||||||
|
$root->appendChild($destination->importNode($child, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
$root->appendChild($destination->createElement('mods'));
|
||||||
|
return $destination->save($destination_path) !== false;
|
||||||
|
}
|
||||||
|
|
||||||
function steam_workshop_request($url, $context, &$error = "")
|
function steam_workshop_request($url, $context, &$error = "")
|
||||||
{
|
{
|
||||||
$response = @file_get_contents($url, false, $context);
|
$response = @file_get_contents($url, false, $context);
|
||||||
|
|
|
||||||
|
|
@ -93,12 +93,57 @@ function steam_workshop_admin_hidden_state($values)
|
||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function steam_workshop_admin_get_game_options($db, &$workshop_config_labels)
|
||||||
|
{
|
||||||
|
$games = array(0 => get_lang('select_game'));
|
||||||
|
$workshop_config_labels = array();
|
||||||
|
$game_cfgs = $db->getGameCfgs();
|
||||||
|
foreach($game_cfgs as $game_cfg)
|
||||||
|
{
|
||||||
|
$server_xml = read_server_config(SERVER_CONFIG_LOCATION."/".$game_cfg['home_cfg_file']);
|
||||||
|
if(isset($server_xml->installer) and $server_xml->installer == "steamcmd")
|
||||||
|
{
|
||||||
|
$cfgMods = $db->getCfgMods($game_cfg['home_cfg_id']);
|
||||||
|
foreach($cfgMods as $cfgMod)
|
||||||
|
{
|
||||||
|
$mod_xml = xml_get_mod($server_xml, $cfgMod['mod_key']);
|
||||||
|
if(isset($mod_xml->installer_name) and !in_array((string)$mod_xml->installer_name, get_blacklist()))
|
||||||
|
{
|
||||||
|
preg_match('/(linux|win)(32|64)?/i', $game_cfg['game_key'], $matches);
|
||||||
|
if(empty($matches[1]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(strtolower($matches[1]) == 'linux')
|
||||||
|
$os = "Linux";
|
||||||
|
elseif(strtolower($matches[1]) == 'win')
|
||||||
|
$os = "Windows";
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(isset($matches[2]) and strtolower($matches[2]) == '64')
|
||||||
|
$arch = "64";
|
||||||
|
else
|
||||||
|
$arch = "32";
|
||||||
|
|
||||||
|
$modname = strtolower($cfgMod['mod_name']) == "none"? "":" [MOD:" . $cfgMod['mod_name']."]";
|
||||||
|
$friendly_name = $game_cfg['game_name'] . " (" . $os . " " . $arch . "bits)$modname";
|
||||||
|
$games[$game_cfg['home_cfg_id'].'-'.$cfgMod['mod_cfg_id'].'-'.$os] = $friendly_name;
|
||||||
|
$workshop_config_labels[(string)$mod_xml->installer_name."_".$os.".xml"] = $friendly_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $games;
|
||||||
|
}
|
||||||
|
|
||||||
function exec_ogp_module()
|
function exec_ogp_module()
|
||||||
{
|
{
|
||||||
|
|
||||||
Global $db,$view;
|
Global $db,$view;
|
||||||
echo '<h2>Steam Workshop</h2>';
|
echo '<h2>Steam Workshop</h2>';
|
||||||
define('CONFIGS', "modules/steam_workshop/game_configs/");
|
define('CONFIGS', "modules/steam_workshop/game_configs/");
|
||||||
|
$workshop_config_labels = array();
|
||||||
|
$games = steam_workshop_admin_get_game_options($db, $workshop_config_labels);
|
||||||
|
|
||||||
if(isset($_REQUEST['home_cfg_id-mod_cfg_id-os']))
|
if(isset($_REQUEST['home_cfg_id-mod_cfg_id-os']))
|
||||||
list($home_cfg_id, $mod_cfg_id, $os) = explode('-', $_REQUEST['home_cfg_id-mod_cfg_id-os']);
|
list($home_cfg_id, $mod_cfg_id, $os) = explode('-', $_REQUEST['home_cfg_id-mod_cfg_id-os']);
|
||||||
|
|
@ -149,11 +194,13 @@ function exec_ogp_module()
|
||||||
steam_workshop_admin_save_xml($xml_file, $_POST, $removed_ids);
|
steam_workshop_admin_save_xml($xml_file, $_POST, $removed_ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isset($_POST['copy_selected_config']) || isset($_POST['confirm_copy_config']))
|
if(isset($_POST['copy_selected_config']))
|
||||||
{
|
{
|
||||||
|
$copy_source_filename = isset($_POST['copy_source_config']) ? (string)$_POST['copy_source_config'] : '';
|
||||||
|
$destination_filename = basename($xml_file);
|
||||||
list($source_path, $destination_path) = steam_workshop_get_safe_config_copy_paths(
|
list($source_path, $destination_path) = steam_workshop_get_safe_config_copy_paths(
|
||||||
isset($_POST['copy_source_config']) ? $_POST['copy_source_config'] : '',
|
$copy_source_filename,
|
||||||
basename($xml_file)
|
$destination_filename
|
||||||
);
|
);
|
||||||
if($source_path === false || $destination_path === false)
|
if($source_path === false || $destination_path === false)
|
||||||
{
|
{
|
||||||
|
|
@ -163,19 +210,13 @@ function exec_ogp_module()
|
||||||
{
|
{
|
||||||
print_failure(get_lang('cannot_copy_workshop_config_to_itself'));
|
print_failure(get_lang('cannot_copy_workshop_config_to_itself'));
|
||||||
}
|
}
|
||||||
elseif(file_exists($destination_path) && !isset($_POST['confirm_copy_config']))
|
elseif(steam_workshop_copy_config_settings_only($source_path, $destination_path))
|
||||||
{
|
{
|
||||||
echo "<div class='info' style='margin:10px 0;padding:10px;'><strong>".get_lang('confirm_copy_workshop_config')."</strong><br>".
|
$configs = steam_workshop_list_existing_configs();
|
||||||
get_lang_f('workshop_config_copy_confirm_info', basename($source_path), basename($destination_path)).
|
$source_filename = basename($source_path);
|
||||||
"<form method='post' action='?m=steam_workshop&p=workshop_admin'>".
|
$source_label = isset($configs[$source_filename]) ? steam_workshop_get_config_display_label($source_filename, $configs[$source_filename], $workshop_config_labels) : $source_filename;
|
||||||
"<input type='hidden' name='home_cfg_id-mod_cfg_id-os' value='".steam_workshop_h($_REQUEST['home_cfg_id-mod_cfg_id-os'])."' />".
|
$destination_label = isset($configs[$destination_filename]) ? steam_workshop_get_config_display_label($destination_filename, $configs[$destination_filename], $workshop_config_labels) : (isset($workshop_config_labels[$destination_filename]) ? $workshop_config_labels[$destination_filename].' - '.$destination_filename : $destination_filename);
|
||||||
"<input type='hidden' name='copy_source_config' value='".steam_workshop_h(basename($source_path))."' />".
|
print_success(get_lang_f('workshop_config_copied', steam_workshop_h($source_label), steam_workshop_h($destination_label)));
|
||||||
"<button type='submit' class='btn btn-sm btn-warning mt-2' name='confirm_copy_config' value='1'>".get_lang('copy_selected_config')."</button>".
|
|
||||||
"</form></div>";
|
|
||||||
}
|
|
||||||
elseif(@copy($source_path, $destination_path))
|
|
||||||
{
|
|
||||||
print_success(get_lang_f('workshop_config_copied', basename($source_path), basename($destination_path)));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -220,38 +261,6 @@ function exec_ogp_module()
|
||||||
'uninstall' => isset($uninstall) ? $uninstall : '',
|
'uninstall' => isset($uninstall) ? $uninstall : '',
|
||||||
);
|
);
|
||||||
|
|
||||||
$game_cfgs = $db->getGameCfgs();
|
|
||||||
$games[0] = get_lang('select_game');
|
|
||||||
foreach($game_cfgs as $game_cfg)
|
|
||||||
{
|
|
||||||
$server_xml = read_server_config(SERVER_CONFIG_LOCATION."/".$game_cfg['home_cfg_file']);
|
|
||||||
if(isset($server_xml->installer) and $server_xml->installer == "steamcmd")
|
|
||||||
{
|
|
||||||
$cfgMods = $db->getCfgMods($game_cfg['home_cfg_id']);
|
|
||||||
foreach($cfgMods as $cfgMod)
|
|
||||||
{
|
|
||||||
$mod_xml = xml_get_mod($server_xml, $cfgMod['mod_key']);
|
|
||||||
if(isset($mod_xml->installer_name) and !in_array((string)$mod_xml->installer_name, get_blacklist()))
|
|
||||||
{
|
|
||||||
preg_match('/(linux|win)(32|64)?/i', $game_cfg['game_key'], $matches);
|
|
||||||
|
|
||||||
if(strtolower($matches[1]) == 'linux')
|
|
||||||
$os = "Linux";
|
|
||||||
elseif(strtolower($matches[1]) == 'win')
|
|
||||||
$os = "Windows";
|
|
||||||
if(isset($matches[2]) and strtolower($matches[2]) == '64')
|
|
||||||
$arch = "64";
|
|
||||||
else
|
|
||||||
$arch = "32";
|
|
||||||
|
|
||||||
$modname = strtolower($cfgMod['mod_name']) == "none"? "":" [MOD:" . $cfgMod['mod_name']."]";
|
|
||||||
|
|
||||||
$games[$game_cfg['home_cfg_id'].'-'.$cfgMod['mod_cfg_id'].'-'.$os] = $game_cfg['game_name'] . " (" . $os . " " . $arch . "bits)$modname";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$download_methods = array("steamcmd", "steamapi");
|
$download_methods = array("steamcmd", "steamapi");
|
||||||
|
|
||||||
$ft = new FormTable();
|
$ft = new FormTable();
|
||||||
|
|
@ -260,12 +269,12 @@ function exec_ogp_module()
|
||||||
$ft->add_custom_field('game', create_drop_box_from_array_onchange($games, "home_cfg_id-mod_cfg_id-os", @$_REQUEST['home_cfg_id-mod_cfg_id-os']));
|
$ft->add_custom_field('game', create_drop_box_from_array_onchange($games, "home_cfg_id-mod_cfg_id-os", @$_REQUEST['home_cfg_id-mod_cfg_id-os']));
|
||||||
if(isset($home_cfg_id) and isset($mod_cfg_id))
|
if(isset($home_cfg_id) and isset($mod_cfg_id))
|
||||||
{
|
{
|
||||||
$copy_options = steam_workshop_get_existing_config_options(isset($xml_file) ? basename($xml_file) : '');
|
$copy_options = steam_workshop_get_existing_config_options(isset($xml_file) ? basename($xml_file) : '', $workshop_config_labels);
|
||||||
echo "<div class='info' style='margin:10px 0;padding:10px;'><strong>".get_lang('copy_from_existing_workshop_config')."</strong><br>".
|
echo "<div class='info' style='margin:10px 0;padding:10px;'><strong>".get_lang('copy_from_existing_workshop_config')."</strong><br>".
|
||||||
get_lang('copy_from_existing_workshop_config_info').
|
get_lang('copy_from_existing_workshop_config_info').
|
||||||
"<form method='post' action='?m=steam_workshop&p=workshop_admin' style='margin-top:8px;' autocomplete='off'>".
|
"<form method='post' action='?m=steam_workshop&p=workshop_admin' style='margin-top:8px;' autocomplete='off'>".
|
||||||
"<input type='hidden' name='home_cfg_id-mod_cfg_id-os' value='".steam_workshop_h($_REQUEST['home_cfg_id-mod_cfg_id-os'])."' />".
|
"<input type='hidden' name='home_cfg_id-mod_cfg_id-os' value='".steam_workshop_h($_REQUEST['home_cfg_id-mod_cfg_id-os'])."' />".
|
||||||
create_drop_box_from_array($copy_options, "copy_source_config", '').
|
create_drop_box_from_array($copy_options, "copy_source_config", '', false).
|
||||||
" <button type='submit' class='btn btn-sm btn-secondary' name='copy_selected_config' value='1'>".get_lang('copy_selected_config')."</button>".
|
" <button type='submit' class='btn btn-sm btn-secondary' name='copy_selected_config' value='1'>".get_lang('copy_selected_config')."</button>".
|
||||||
"</form></div>";
|
"</form></div>";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ The dedicated module still provides:
|
||||||
- monitor-button access from Game Monitor
|
- monitor-button access from Game Monitor
|
||||||
- per-game Workshop configuration files
|
- per-game Workshop configuration files
|
||||||
- uninstall and admin support pages
|
- uninstall and admin support pages
|
||||||
|
- admin copy support for copying Workshop configuration settings between XML configs without copying installed mods or server files
|
||||||
- optional regex/config-file editing for games that need automatic mod-list updates
|
- optional regex/config-file editing for games that need automatic mod-list updates
|
||||||
- post-install-only workflows for games that only need a move/copy script
|
- post-install-only workflows for games that only need a move/copy script
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,9 @@ Dedicated Steam Workshop support for game servers.
|
||||||
- use `workshop_admin.php` for module administration
|
- use `workshop_admin.php` for module administration
|
||||||
- `File Path` and the regex/mod-string fields are optional
|
- `File Path` and the regex/mod-string fields are optional
|
||||||
- a blank `File Path` means post-install and uninstall scripts run without any automatic config-file editing
|
- a blank `File Path` means post-install and uninstall scripts run without any automatic config-file editing
|
||||||
- the admin page can copy one existing XML config into the currently selected game/OS config
|
- the admin page can copy configuration settings from one existing XML config into the currently selected game/OS config
|
||||||
|
- copied settings include Workshop App ID, download method, anonymous login, paths, regex/config-edit fields, post-install script, and uninstall script
|
||||||
|
- copied settings do not include installed mods, cached mod lists, game server files, or any files from a game home directory
|
||||||
|
|
||||||
## Search Backend
|
## Search Backend
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue