Skip to content
Snippets Groups Projects
Commit 5f341763 authored by Rob Swindell's avatar Rob Swindell :speech_balloon:
Browse files

Merge branch 'master' of gitlab.synchro.net:main/sbbs

parents 483c86de 4322be29
No related branches found
No related tags found
1 merge request!463MRC mods by Codefenix (2024-10-20)
Pipeline #927 passed
......@@ -940,15 +940,18 @@ BinkP.prototype.close = function()
this.sendCmd(this.command.M_EOB);
}
// Attempt a super-duper graceful shutdown to prevent RST...
this.sock.is_writeable = false;
remain = this.timeout;
end = time() + remain;
do {
if (this.sock.recv(2048, remain) == 0)
break;
remain = end - time();
} while (remain > 0);
this.sock.close();
if (this.sock !== undefined) {
this.sock.is_writeable = false;
remain = this.timeout;
end = time() + remain;
do {
if (this.sock.recv(2048, remain) == 0)
break;
remain = end - time();
} while (remain > 0);
this.sock.close();
this.sock = undefined;
}
}
this.tx_queue.forEach(function(file) {
file.file.close();
......
/**
* Custom External Program Menu Library for Custom External Program Menus
* by Michael Long mlong innerrealmbbs.us
*
* This provides common functionality for retrieving menus used by
* the loadable module xtrnmenu.js and by the web interface
* 099-xtrnmenu-games.xjs
*/
"use strict";
load("sbbsdefs.js", "K_NONE");
/* text.dat entries */
require("text.js", "XtrnProgLstFmt");
function ExternalMenus() {
this.options = {};
this.xtrn_custommenu_options = {};
this.menuconfig = {};
this.getOptions();
this.getMenuConfig();
}
ExternalMenus.prototype.getMenuConfig = function() {
var config_file = new File(system.ctrl_dir + "xtrnmenu.cfg");
var config_src;
this.menuconfig = undefined;
if (config_file.open('r+')) {
config_src = config_file.read();
config_file.close();
}
if (typeof config_src !== "undefined") {
this.menuconfig = JSON.parse(config_src.toString());
}
}
ExternalMenus.prototype.getOptions = function(menutype, menuid) {
if (typeof menutype === "undefined") {
menutype = 'custommenu';
}
// Get xtrn_sec options from modopts.ini [xtrn_sec]
if ((this.options = load({}, "modopts.js", "xtrn_sec")) == null) {
this.options = { multicolumn: true, sort: false };
}
// Get xtrn_custommenu options from modopts.ini [xtrn_custommenu]
if ((this.xtrn_custommenu_options = load({}, "modopts.js", "xtrnmenu")) == null) {
this.xtrn_custommenu_options = { };
}
// in all cases, we start with the xtrn_sec options as the base and set the defaults
if (this.options.multicolumn === undefined)
this.options.multicolumn = true;
if (this.options.multicolumn_separator === undefined)
this.options.multicolumn_separator = " ";
if (this.options.multicolumn_fmt === undefined)
this.options.multicolumn_fmt = system.text(XtrnProgLstFmt);
if (this.options.singlecolumn_fmt === undefined)
this.options.singlecolumn_fmt = "\x01h\x01c%3u \xb3 \x01n\x01c%s\x01h ";
if (this.options.singlecolumn_margin == undefined)
this.options.singlecolumn_margin = 7;
if (typeof bbs !== "undefined") {
if (this.options.singlecolumn_height == undefined)
this.options.singlecolumn_height = console.screen_rows - this.options.singlecolumn_margin;
// override and turn off multicolumn if terminal width is less than 80
if (console.screen_columns < 80)
options.multicolumn = false;
}
if (this.options.restricted_user_msg === undefined)
this.options.restricted_user_msg = system.text(R_ExternalPrograms);
if (this.options.no_programs_msg === undefined)
this.options.no_programs_msg = system.text(NoXtrnPrograms);
if (this.options.header_fmt === undefined)
this.options.header_fmt = system.text(XtrnProgLstHdr);
if (this.options.titles === undefined)
this.options.titles = system.text(XtrnProgLstTitles);
if (this.options.underline === undefined)
this.options.underline = system.text(XtrnProgLstUnderline);
if (this.options.which === undefined)
this.options.which = system.text(WhichXtrnProg);
if (this.options.clear_screen === undefined)
this.options.clear_screen = true;
if (this.options.section_fmt === undefined)
this.options.section_fmt = "\x01y\x01g%3d:\x01n\x01g %s"
if (this.options.section_header_fmt === undefined)
this.options.section_header_fmt = "\x01-\x01gSelect \x01hExternal Program Section\x01-\x01g:"
if (this.options.section_which === undefined)
this.options.section_which = "\r\n\x01-\x01gWhich, \x01w\x01h~Q\x01n\x01guit or [1]: \x01h"
// if its a custom menu, then override with custommenu_options
if (menutype == 'custommenu') {
if (typeof this.xtrn_custommenu_options.multicolumn_fmt !== "undefined") {
this.options.multicolumn_fmt = this.xtrn_custommenu_options.multicolumn_fmt;
} else {
// cannot default to xtrn_sec multicolumn_fmt due to use of %u instead of %s
this.options.multicolumn_fmt = "\x01h\x01c%3s \xb3 \x01n\x01c%-32.32s\x01h ";
}
if (typeof this.xtrn_custommenu_options.singlecolumn_fmt !== "undefined") {
this.options.singlecolumn_fmt = this.xtrn_custommenu_options.singlecolumn_fmt;
} else {
// cannot default to xtrn_sec multicolumn_fmt due to use of %u instead of %s
this.options.singlecolumn_fmt = "\x01h\x01c%3s \xb3 \x01n\x01c%s\x01h ";
}
this.options.header_fmt = (typeof this.xtrn_custommenu_options.header_fmt !== "undefined")
? this.xtrn_custommenu_options.header_fmt : this.options.header_fmt;
this.options.titles = (typeof this.xtrn_custommenu_options.titles !== "undefined")
? this.xtrn_custommenu_options.titles : this.options.titles;
this.options.which = (typeof this.xtrn_custommenu_options.which !== "undefined")
? this.xtrn_custommenu_options.which : this.options.which;
this.options.underline = (typeof this.xtrn_custommenu_options.underline !== "undefined")
? this.xtrn_custommenu_options.underline : this.options.underline;
this.options.multicolumn_separator = (typeof this.xtrn_custommenu_options.multicolumn_separator !== "undefined")
? this.xtrn_custommenu_options.multicolumn_separator : this.options.multicolumn_separator;
this.options.multicolumn = (typeof this.xtrn_custommenu_options.multicolumn !== "undefined")
? this.xtrn_custommenu_options.multicolumn : this.options.multicolumn;
this.options.sort = (typeof this.xtrn_custommenu_options.sort !== "undefined")
? this.xtrn_custommenu_options.sort : this.options.sort;
this.options.clear_screen = (typeof this.xtrn_custommenu_options.clear_screen !== "undefined")
? this.xtrn_custommenu_options.clear_screen : this.options.clear_screen;
this.options.singlecolumn_margin = (typeof this.xtrn_custommenu_options.singlecolumn_margin !== "undefined")
? this.xtrn_custommenu_options.singlecolumn_margin : this.options.singlecolumn_margin;
if (typeof bbs !== "undefined") {
this.options.singlecolumn_height = (typeof this.xtrn_custommenu_options.singlecolumn_height !== "undefined")
? this.xtrn_custommenu_options.singlecolumn_height : this.options.singlecolumn_height;
}
// no need to override restricted_user_msg or no_programs_msg - these
// will be the same for both types of menus
// Allow overriding on a per-menu basis
var menuoptions = load({}, "modopts.js", "xtrnmenu:" + menuid);
if ((typeof menuid !== "undefined") && (menuoptions != null)) {
for (var m in menuoptions) {
this.options[m] = menuoptions[m];
}
}
}
// these options only apply to terminals/consoles
// the intention is to obtain all the mod_opts options for xtrn_sec, and
// override if a custom menu global setting is set
//// The following are used for the enhanced custom menu functionality
if (this.options.custom_menu_not_found_msg === undefined) {
this.options.custom_menu_not_found_msg = "Menu %MENUID% not found";
}
if (this.options.custom_menu_program_not_found_msg === undefined) {
this.options.custom_menu_program_not_found_msg = "Program %PROGRAMID% not found";
}
return this.options;
}
// return a custom menu object
ExternalMenus.prototype.getMenu = function(menuid) {
// grab the specified menu, or get the main menu
if ((typeof menuid === "undefined") || !menuid) {
menuid = "main";
} else {
menuid = menuid.toLowerCase();
}
var menu;
if ((typeof this.menuconfig !== "undefined") && (typeof this.menuconfig.menus !== "undefined")) {
this.menuconfig.menus.some(function (indmenu) {
if (indmenu.id.toLowerCase() == menuid) {
menu = indmenu;
}
});
}
if (!menu && (menuid == "main")) {
// no custom menus defined, make one to mimic old behavior
var menuitems = [];
var i;
xtrn_area.sec_list.forEach(function (sec) {
if (sec.can_access) {
menuitems.push({
"input": i,
"target": sec.code,
"type": "xtrnmenu",
"title": sec.name,
"access_string": sec.ars
});
i++;
}
});
menu = {
"id": "main",
"title": "Main Menu",
"items": menuitems
};
}
return menu;
}
// return a section menu object (stock synchronet external door section)
ExternalMenus.prototype.getSectionMenu = function(menuid) {
// grab the specified menu, or get the main menu
if ((typeof menuid === "undefined") || !menuid) {
return false;
}
var menuitems = [];
var menu, title;
xtrn_area.sec_list.some(function (sec) {
if (sec.code.toLowerCase() == menuid.toLowerCase()) {
title = sec.name;
if (!sec.can_access || sec.prog_list.length < 1) {
return false;
}
var i = 1;
sec.prog_list.some(function (prog) {
menuitems.push({
'input' : i,
'target': prog.code,
'title': prog.name,
'type': 'xtrnprog',
'access_string': prog.ars,
'cost': prog.cost
});
i++;
});
if (menuitems.length > 0) {
menu = {
'id': menuid,
'title': title,
'items': menuitems,
};
}
return;
}
});
return menu;
}
// Sort the menu items according to options
ExternalMenus.prototype.getSortedItems = function(menuobj) {
var sort_type;
if ((typeof menuobj.sort_type !== "undefined") && menuobj.sort_type) {
sort_type = menuobj.sort_type; // "name" or "key"
} else {
sort_type = this.options.sort; // bool
}
// first, build a new menu with only options they have access to
var menuitemsfiltered = [];
for (i in menuobj.items) {
switch (menuobj.items[i].type) {
case 'xtrnmenu':
for (j in xtrn_area.sec_list) {
if (xtrn_area.sec_list[j].code.toUpperCase() == menuobj.items[i].target.toUpperCase()) {
if (xtrn_area.sec_list[j].can_access) {
menuitemsfiltered.push(menuobj.items[i]);
}
}
}
break;
case 'xtrnprog':
for (j in xtrn_area.sec_list) {
for (var k in xtrn_area.sec_list[j].prog_list) {
if (xtrn_area.sec_list[j].prog_list[k].code.toUpperCase() == menuobj.items[i].target.toUpperCase()) {
if (xtrn_area.sec_list[j].prog_list[k].can_access) {
menuitemsfiltered.push(menuobj.items[i]);
}
}
}
}
break;
case 'custommenu':
default:
if ((typeof menuobj.items[i].access_string === "undefined") || !menuobj.items[i].access_string) {
// no access string defined, everyone gets access
menuitemsfiltered.push(menuobj.items[i]);
} else {
if (user.compare_ars(menuobj.items[i].access_string)) {
// they have access
menuitemsfiltered.push(menuobj.items[i]);
}
}
break;
}
}
// if no custom input keys are specified for an input, then assign a numeric input
// this would mimic the built-in external section menu functionality
// but this is only assigned on sort_type key because if the sort type is for
// titles, we need to sort by title first before assigning the sequential numbers
var sortind = 0;
// make sure we only use the next available number for automatic assignment
for (i in menuitemsfiltered) {
if (!isNaN(menuitemsfiltered[i].input)) {
if (menuitemsfiltered[i].input > sortind) {
sortind = menuitemsfiltered[i].input;
}
}
}
sortind++;
if (sort_type == "key") {
for (i in menuitemsfiltered) {
if (!menuitemsfiltered[i].input) {
menuitemsfiltered[i].input = sortind;
sortind++;
}
}
}
if (sort_type) {
switch (sort_type) {
case "key":
menuitemsfiltered.sort(this.sort_by_input);
break;
default:
case "title":
case "name":
menuitemsfiltered.sort(this.sort_by_title);
break;
}
}
// if this is a sort by title and the key is empty, it will be assigned the next available number
// this is to support auto-generated inputs like is done on the built-in section menus
// however, to keep the numeric keys in order, the numbers could not be pre-assigned like it done
// on the sort_type key
for (i in menuitemsfiltered) {
if ((sort_type !== "key") && !menuitemsfiltered[i].input) {
menuitemsfiltered[i].input = sortind;
sortind++;
}
}
return menuitemsfiltered;
}
// Original sort function used by external_program_menu and external_section_menu
ExternalMenus.prototype.sort_by_name = function(a, b) {
if(a.name.toLowerCase()>b.name.toLowerCase()) return 1;
if(a.name.toLowerCase()<b.name.toLowerCase()) return -1;
return 0;
}
// Sort by title - used by external_section_menu_custom
ExternalMenus.prototype.sort_by_title = function(a, b) {
if (a.title.toLowerCase() < b.title.toLowerCase()) {
return -1;
}
if (a.title.toLowerCase() > b.title.toLowerCase()) {
return 1;
}
return 0;
}
// Sort by input key - used by external_section_menu_custom
ExternalMenus.prototype.sort_by_input = function(a, b) {
if (a.input.toString().toLowerCase() < b.input.toString().toLowerCase()) {
return -1;
}
if (a.input.toString().toLowerCase() > b.input.toString().toLowerCase()) {
return 1;
}
return 0;
}
/**
* Xtrn Menu Mod
* Custom External Program Menus
* by Michael Long mlong innerrealmbbs.us
*
* This is the loadable module that displays the custom external menus
* in terminal server (telnet/rlogin/ssh)
*
* To jump to a specific menu, pass the ID as an argument
*
* To set options, add to modopts.ini [xtrnmenu]
*
* See instructions at http://wiki.synchro.net/module:xtrnmenu
*/
"use strict";
require("sbbsdefs.js", "K_NONE");
load("xtrnmenulib.js");
var options, xsec = -1;
//// Main
var ExternalMenus = new ExternalMenus();
const menuconfig = ExternalMenus.menuconfig;
{
var i,j;
for(i in argv) {
for(j in xtrn_area.sec_list) {
if(argv[i].toLowerCase()==xtrn_area.sec_list[j].code)
xsec=j;
}
}
}
if (xsec > -1) {
// if its the id of a standard section menu, send it to the
// stock menu
js.exec("xtrn_sec.js", {}, xsec);
} else if (typeof argv[0] !== "undefined") {
// if its not a section menu, assume it is a custom menu
external_section_menu_custom(argv[0]);
} else {
// main custom menu
external_section_menu_custom();
}
// Renders the top-level external menu
function external_section_menu_custom(menuid)
{
var i, menucheck, menuobj, item_multicolumn_fmt, item_singlecolumn_fmt,
cost, multicolumn, menuitemsfiltered = [];
var validkeys = []; // valid chars on menu selection
var keymax = 0; // max integer allowed on menu selection
var options = ExternalMenus.getOptions('custommenu', menuid);
menuobj = ExternalMenus.getMenu(menuid);
// Allow overriding auto-format on a per-menu basis
var multicolumn_fmt = options.multicolumn_fmt;
var singlecolumn_fmt = options.singlecolumn_fmt;
while (bbs.online) {
console.aborted = false;
if (typeof menuobj === "undefined") {
doerror(options.custom_menu_not_found_msg.replace('%MENUID%', menuid));
break;
}
if (options.clear_screen) {
console.clear(LIGHTGRAY);
}
if (user.security.restrictions&UFLAG_X) {
write(options.restricted_user_msg);
break;
}
if (!xtrn_area.sec_list.length) {
write(options.no_programs_msg);
break;
}
var keyin;
system.node_list[bbs.node_num-1].aux = 0; /* aux is 0, only if at menu */
bbs.node_action = NODE_XTRN;
bbs.node_sync();
menuitemsfiltered = ExternalMenus.getSortedItems(menuobj);
if (!bbs.menu("xtrnmenu_head_" + menuid, P_NOERROR) && !bbs.menu("xtrnmenu_head", P_NOERROR)) {
bbs.menu("xtrn_head", P_NOERROR);
}
// if file exists text/menu/xtrnmenu_(menuid).[rip|ans|mon|msg|asc],
// then display that, otherwise dynamiic
if (!bbs.menu("xtrnmenu_" + menuid, P_NOERROR)) {
// if no custom menu file in text/menu, create a dynamic one
multicolumn = options.multicolumn && menuitemsfiltered.length > options.singlecolumn_height;
printf(options.header_fmt, menuobj.title);
if(options.titles.trimRight() != '')
write(options.titles);
if(multicolumn) {
write(options.multicolumn_separator);
if (options.titles.trimRight() != '')
write(options.titles);
}
if(options.underline.trimRight() != '') {
console.crlf();
write(options.underline);
}
if(multicolumn) {
write(options.multicolumn_separator);
if (options.underline.trimRight() != '')
write(options.underline);
}
console.crlf();
// n is the number of items for the 1st column
var n;
if (multicolumn) {
n = Math.floor(menuitemsfiltered.length / 2) + (menuitemsfiltered.length & 1);
} else {
n = menuitemsfiltered.length;
}
// j is the index for each menu item on 2nd column
var j = n; // start j at the first item for 2nd column
for (i = 0; i < n && !console.aborted; i++) {
cost = "";
if (menuitemsfiltered[i].type == "xtrnprog") {
// if its an external program, get the cost
cost = xtrn_area.prog[menuitemsfiltered[i].target.toLowerCase()].cost;
}
console.add_hotspot(menuitemsfiltered[i].input.toString());
validkeys.push(menuitemsfiltered[i].input.toString());
var intCheck = Number(menuitemsfiltered[i].input);
if (!intCheck.isNaN) {
if (intCheck > keymax) {
keymax = menuitemsfiltered[i].input;
}
}
// allow overriding format on a per-item basis
// great for featuring a specific game
var checkkey = menuitemsfiltered[i].target + '-multicolumn_fmt';
checkkey = checkkey.toLowerCase();
item_multicolumn_fmt = (typeof options[checkkey] !== "undefined") ?
options[checkkey] : options.multicolumn_fmt;
checkkey = menuitemsfiltered[i].target + '-singlecolumn_fmt'
checkkey = checkkey.toLowerCase();
item_singlecolumn_fmt = (typeof options[checkkey] !== "undefined") ?
options[checkkey] : options.singlecolumn_fmt;
printf(multicolumn ? item_multicolumn_fmt : item_singlecolumn_fmt,
menuitemsfiltered[i].input.toString().toUpperCase(),
menuitemsfiltered[i].title,
cost
);
if (multicolumn) {
if ((typeof(menuitemsfiltered[j]) !== "undefined")) {
validkeys.push(menuitemsfiltered[j].input.toString());
var intCheck = Number(menuitemsfiltered[j].input);
if (!intCheck.isNaN) {
if (intCheck > keymax) {
keymax = menuitemsfiltered[j].input;
}
}
// allow overriding format on a per-item basis
// great for featuring a specific game
var checkkey = menuitemsfiltered[j].target + '-multicolumn_fmt';
checkkey = checkkey.toLowerCase();
item_multicolumn_fmt = (typeof options[checkkey] !== "undefined") ?
options[checkkey] : options.multicolumn_fmt;
checkkey = menuitemsfiltered[j].target + '-singlecolumn_fmt'
checkkey = checkkey.toLowerCase();
write(options.multicolumn_separator);
console.add_hotspot(menuitemsfiltered[j].input.toString());
printf(item_multicolumn_fmt,
menuitemsfiltered[j].input.toString().toUpperCase(),
menuitemsfiltered[j].title,
cost
);
} else {
write(options.multicolumn_separator);
}
j++;
}
console.crlf();
}
if (!bbs.menu("xtrnmenu_tail_" + menuid, P_NOERROR) && !bbs.menu("xtrnmenu_tail", P_NOERROR)) {
bbs.menu("xtrn_tail", P_NOERROR);
}
bbs.node_sync();
console.mnemonics(options.which);
}
validkeys.push('q');
keyin = console.getkeys(validkeys, keymax, K_NONE);
keyin = keyin.toString().toLowerCase();
if (keyin) {
// q for quit
if (keyin == "q") {
console.clear();
break;
}
menuitemsfiltered.some(function (menuitemfiltered) {
var menutarget = menuitemfiltered.target.toLowerCase();
var menuinput = menuitemfiltered.input.toString().toLowerCase();
if (menuinput == keyin) {
switch (menuitemfiltered.type) {
// custom menu, defined in xtrnmenu.json
case 'custommenu':
external_section_menu_custom(menutarget);
return true;
// external program section
case 'xtrnmenu':
js.exec("xtrn_sec.js", {}, menutarget);
//js.exec(js.exec_dir + 'xtrn_sec.js ' + menutarget)
return true;
// external program
case 'xtrnprog':
// run the external program
if (typeof xtrn_area.prog[menutarget] !== "undefined") {
bbs.exec_xtrn(menutarget);
return true;
} else {
doerror(options.custom_menu_program_not_found_msg.replace('%PROGRAMID%', menutarget));
}
break;
} //switch
} // if menu item matched keyin
}); // foreach menu item
} // if keyin
} // main bbs.online loop
}
// Display error message to console and save to log
function doerror(msg)
{
console.crlf();
log(LOG_ERR, msg);
console.putmsg('\x01+\x01h\x01r' +msg + ". The sysop has been notified." + '\x01-\r\n');
}
This diff is collapsed.
<!--HIDDEN:Games-->
<?xjs
/**
* Web Display for Custom External Program Menus
* by Michael Long mlong innerrealmbbs.us
*
* See wiki at http://wiki.synchro.net/module:xtrnmenumod
*/
load("ftelnethelper.js");
load('sbbsdefs.js');
load("xtrnmenulib.js");
load(settings.web_lib + 'ftelnet.js');
load(settings.web_lib + 'request.js');
var ExternalMenus = new ExternalMenus();
if (typeof settings.xtrn_blacklist === 'string') {
settings.xtrn_blacklist = settings.xtrn_blacklist.toLowerCase().split(',');
} else {
settings.xtrn_blacklist = [];
}
var menuitems = [];
?>
<style>.fTelnetStatusBar { display : none; }</style>
<a name="fTelnet"></a>
<div id="fTelnetContainer" class="fTelnetContainer" style="margin-bottom:1em;"></div>
<div id="xtrn-list" class="list-group">
<?xjs
var menuobj;
if ((Request.get_param('type') == 'xtrnmenu') && Request.has_param('target')) {
menuobj = ExternalMenus.getSectionMenu(Request.get_param('target'));
} else {
if (Request.has_param('target')) {
menuobj = ExternalMenus.getMenu(Request.get_param('target'));
} else {
menuobj = ExternalMenus.getMenu('main');
}
}
if ((typeof menuobj === "undefined") || !menuobj
|| (typeof menuobj.items === "undefined") || (menuobj.items.length < 1)) {
writeln("<h4>" + ExternalMenus.options.no_programs_msg + "</h4>");
} else if (user.security.restrictions&UFLAG_X) {
writeln("<h4>" + options.restricted_user_msg + "</h4>");
} else {
// ok to display menu
writeln("<h4>" + menuobj.title + "</h4>");
var menuitemsfiltered = ExternalMenus.getSortedItems(menuobj);
menuitemsfiltered.forEach(function (menuitem) {
if (settings.xtrn_blacklist.indexOf(menuitem.target.toLowerCase()) > -1) {
return;
}
menuitems.push({
'itemtitle': menuitem.title,
'itemtype': menuitem.type,
'itemtarget': menuitem.target
});
});
}
?>
</div>
<script id="fTelnetScript" src="<?xjs write(get_url()); ?>"></script>
<script type="text/javascript">
var wsp = <?xjs write(settings.wsp || GetWebSocketServicePort()); ?>;
var wssp = <?xjs write(settings.wssp || GetWebSocketServicePort(true)); ?>;
var Options = new fTelnetOptions();
Options.BareLFtoCRLF = false;
Options.BitsPerSecond = 57600;
Options.ConnectionType = 'rlogin';
Options.Emulation = 'ansi-bbs';
Options.Enter = '\r';
Options.Font = 'CP437';
Options.ForceWss = false;
Options.Hostname = '<?xjs write(http_request.vhost); ?>';
Options.LocalEcho = false;
Options.Port = location.protocol == 'https:' ? wssp : wsp;
Options.RLoginClientUsername = '<?xjs write(user.security.password); ?>';
Options.RLoginServerUsername = '<?xjs write(user.alias); ?>';
Options.ScreenColumns = 80;
Options.ScreenRows = 25;
Options.SplashScreen = Options.SplashScreen = '<?xjs write(get_splash()); ?>';
Options.WebSocketUrlPath = '?Port=<?xjs write(GetRLoginPort()); ?>';
var fTelnet = new fTelnetClient('fTelnetContainer', Options);
fTelnet.OnConnectionClose = function () {
window.location.reload();
};
async function launchXtrn() {
var code = event.srcElement.id;
await v4_get('./api/system.ssjs?call=set-xtrn-intent&code=' + code);
fTelnet._Options.RLoginTerminalType = 'xtrn=' + code;
fTelnet.Connect();
}
var menuitems = <?xjs write(JSON.stringify(menuitems)); ?>;
var currentTarget = "<?xjs Request.write_param('target'); ?>";
var currentType = "<?xjs Request.write_param('type'); ?>";
var currentTitle = `<?xjs write(menuobj.title) ?>`;
if (currentTitle && !currentTarget) {
// main menu - store title for breadcrumb
sessionStorage.setItem("mainmenu", currentTitle);
}
var div = $('#xtrn-list');
menuitems.forEach(function (menuitem) {
var a = document.createElement('a');
$(a).addClass("list-group-item");
$(a).addClass("striped");
a.text = menuitem.itemtitle;
if (menuitem.itemtype == "xtrnprog") {
a.href = "#fTelnet";
a.id = menuitem.itemtarget;
a.onclick = function () { launchXtrn(); };
} else {
a.href = "/?page=<?xjs Request.write_param('page') ?>&type=" +menuitem.itemtype
+ "&target=" + menuitem.itemtarget;
a.onclick = function () {
sessionStorage.setItem('prev:' + menuitem.itemtarget.toLowerCase(), '<?xjs Request.write_param('target')?>');
sessionStorage.setItem('prevtype:' + menuitem.itemtarget.toLowerCase(), '<?xjs Request.write_param('type')?>');
sessionStorage.setItem('prevtitle:' + menuitem.itemtarget.toLowerCase(), currentTitle);
};
}
$(div).append(a);
});
// breadcrumb
var prevTarget = sessionStorage.getItem('prev:' + currentTarget.toLowerCase());
var prevType = sessionStorage.getItem('prevtype:' + currentTarget.toLowerCase());
var prevTitle = sessionStorage.getItem('prevtitle:' + currentTarget.toLowerCase());
if (prevType && prevTarget && prevTitle) {
$('#xtrn-list').prepend('<ol class="breadcrumb"><a href="/?page=<?xjs Request.write_param('page') ?>&type=' + prevType
+ '&target=' + prevTarget + '">' + prevTitle + '</a></ol>');
} else if (currentTarget) {
// level 2, not main menu
var mainmenuTitle = sessionStorage.getItem('mainmenu');
if (!mainmenuTitle) {
mainmenuTitle = 'Games';
}
$('#xtrn-list').prepend('<ol class="breadcrumb"><a href="/?page=<?xjs Request.write_param('page') ?>">' + mainmenuTitle + '</a></ol>');
}
</script>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment