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

Synchronet classic shell ported to JS with helper library: shell_lib.js

This mimics default.src very closely, even the curious clear-screens before
the menu displays only when in non-expert mode (?).

I'll likely be using this to recreate some other command shells.

There's a couple of RIP-specific calls to getlines in default.src that I did
not port over (yet).

This commit fixes issue #526 for Nelgin (and any other JavaScript devs).

Note: this file supercedes default.bin, so beware if you have customized
default.src (and built your own custom default.bin), you'll want to move
those to your mods directory to continue to use them.

Another nail in Baja's coffin.
parent be3f42f0
No related branches found
No related tags found
1 merge request!463MRC mods by Codefenix (2024-10-20)
Pipeline #3933 passed
// Default/Classic Synchronet Command Shell
// replaces default.src/bin
// @format.tab-size 4
"use strict";
require("sbbsdefs.js", "K_UPPER");
require("userdefs.js", "UFLAG_T");
require("nodedefs.js", "NODE_MAIN");
require("key_defs.js", "KEY_UP");
require("text.js", "Pause");
bbs.revert_text(Pause);
load("termsetup.js");
var shell = load({}, "shell_lib.js");
const help_key = '?';
// If user has unlimited time, display time-used rather than time-remaining
const time_code = user.security.exemptions & UFLAG_T ? "@TUSED@" : "@TLEFT@";
const main_menu = {
file: "main",
eval: 'bbs.main_cmds++',
node_action: NODE_MAIN,
prompt: "\x01-\x01c\xfe \x01b\x01hMain \x01n\x01c\xfe \x01h" + time_code +
" \x01n\x01c[\x01h@GN@\x01n\x01c] @GRP@\x01\\ [\x01h@SN@\x01n\x01c] @SUB@: \x01n",
num_input: shell.get_sub_num,
slash_num_input: shell.get_grp_num,
command: {
'A': { eval: 'bbs.auto_msg()' },
'/A': { exec: 'avatar_chooser.js'
,ars: 'ANSI and not GUEST'
,err: '\r\nSorry, only regular users with ANSI terminals can do that.\r\n' },
'B': { eval: 'bbs.scan_subs(SCAN_BACK)'
,msg: '\r\n\x01c\x01hBrowse/New Message Scan\r\n' },
'C': { eval: 'bbs.chat_sec()' },
'D': { eval: 'bbs.user_config(); exit()' },
'E': { exec: 'email_sec.js' },
'F': { eval: 'bbs.scan_subs(SCAN_FIND)'
,msg: '\r\n\x01c\x01hFind Text in Messages\r\n' },
'/F': { eval: 'bbs.scan_subs(SCAN_FIND, /* all */true)' },
'G': { eval: 'bbs.text_sec()' },
'I': { eval: 'shell.main_info()' },
'J': { eval: 'shell.select_msg_area()' },
'L': { eval: 'bbs.list_msgs()' },
'/L': { eval: 'bbs.list_nodes()' },
'M': { eval: 'bbs.time_bank()' },
'N': { eval: 'bbs.scan_subs(SCAN_NEW)'
,msg: '\r\n\x01c\x01hNew Message Scan\r\n' },
'/N': { eval: 'bbs.scan_subs(SCAN_NEW, /* all */true)' },
'O': { eval: 'shell.logoff(/* fast: */false)' },
'/O': { eval: 'shell.logoff(/* fast: */true)' },
'P': { eval: 'bbs.post_msg()' },
'/P': { exec: 'postpoll.js' },
'Q': { eval: 'bbs.qwk_sec()' },
'R': { eval: 'bbs.scan_msgs()' },
'S': { eval: 'bbs.scan_subs(SCAN_TOYOU)'
,msg: '\r\n\x01c\x01hScan for Messages Posted to You\r\n' },
'/S': { eval: 'bbs.scan_subs(SCAN_TOYOU, /* all */true)' },
'U': { eval: 'shell.list_users()' },
'/U': { eval: 'bbs.list_users(UL_ALL)' },
'V': { exec: 'scanpolls.js' },
'/V': { exec: 'scanpolls.js', args: ['all'] },
'W': { eval: 'bbs.whos_online()' },
'X': { eval: 'bbs.xtrn_sec()' },
'/X': { eval: 'exit(0)' },
'Z': { eval: 'bbs.scan_subs(SCAN_NEW | SCAN_CONT)'
,msg: '\r\n\x01c\x01hContinuous New Message Scan\r\n' },
'/Z': { eval: 'bbs.scan_subs(SCAN_NEW | SCAN_CONT, /* all */true)' },
'*': { eval: 'shell.show_subs(bbs.curgrp)' },
'/*': { eval: 'shell.show_grps()' },
'&': { exec: 'msgscancfg.js' },
'!': { eval: 'bbs.menu("sysmain")'
,ars: 'SYSOP or EXEMPT Q or I or N' },
'#': { msg: '\r\n\x01c\x01hType the actual number, not the symbol.\r\n' },
'/#': { msg: '\r\n\x01c\x01hType the actual number, not the symbol.\r\n' },
},
nav: {
'\r': { },
'T': { eval: 'shell.enter_file_section(); menu = file_menu' },
'>': { eval: 'shell.sub_up()' },
'}': { eval: 'shell.sub_up()' },
')': { eval: 'shell.sub_up()' },
'+': { eval: 'shell.sub_up()' },
'=': { eval: 'shell.sub_up()' },
'<': { eval: 'shell.sub_down()' },
'{': { eval: 'shell.sub_down()' },
'(': { eval: 'shell.sub_down()' },
'-': { eval: 'shell.sub_down()' },
']': { eval: 'shell.grp_up()' },
'[': { eval: 'shell.grp_down()' },
},
};
// Can't do these statically through initialization:
main_menu.nav[KEY_UP] = { eval: 'shell.sub_up()' };
main_menu.nav[KEY_DOWN] = { eval: 'shell.sub_down()' };
main_menu.nav[KEY_RIGHT] = { eval: 'shell.grp_up()' };
main_menu.nav[KEY_LEFT] = { eval: 'shell.grp_down()' };
const file_menu = {
file: "transfer",
eval: 'bbs.file_cmds++',
node_action: NODE_XFER,
prompt: "\x01-\x01c\xfe \x01b\x01hFile \x01n\x01c\xfe \x01h" + time_code +
" \x01n\x01c(\x01h@LN@\x01n\x01c) @LIB@\x01\\ (\x01h@DN@\x01n\x01c) @DIR@: \x01n",
num_input: shell.get_dir_num,
slash_num_input: shell.get_lib_num,
command: {
'B': { eval: 'bbs.batch_menu()' },
'C': { eval: 'bbs.chat_sec()' },
'D': { eval: 'shell.download_files()'
,msg: '\r\n\x01c\x01hDownload File(s)\r\n'
,ars: 'REST NOT D' },
'/D': { eval: 'shell.download_user_files()'
,msg: '\r\n\x01c\x01hDownload File(s) from User(s)\r\n'
,ars: 'REST NOT D' },
'E': { eval: 'shell.view_file_info(FI_INFO)'
,msg: '\r\n\x01c\x01hList Extended File Information\r\n' },
'F': { eval: 'bbs.scan_dirs(FL_FINDDESC);'
,msg: '\r\n\x01c\x01hFind Text in File Descriptions (no wildcards)\r\n' },
'/F': { eval: 'bbs.scan_dirs(FL_FINDDESC, /* all: */true);' },
'I': { eval: 'shell.file_info()' },
'J': { eval: 'shell.select_file_area()' },
'L': { eval: 'shell.list_files()' },
'/L': { eval: 'bbs.list_nodes()' },
'N': { eval: 'bbs.scan_dirs(FL_ULTIME)'
,msg: '\r\n\x01c\x01hNew File Scan\r\n' },
'/N': { eval: 'bbs.scan_dirs(FL_ULTIME, /* all */true)' },
'O': { eval: 'shell.logoff(/* fast: */false)' },
'/O': { eval: 'shell.logoff(/* fast: */true)' },
'R': { eval: 'shell.view_file_info(FI_REMOVE)'
,msg: '\r\n\x01c\x01hRemove/Edit File(s)\r\n' },
'S': { eval: 'bbs.scan_dirs(FL_NO_HDR)'
,msg: '\r\n\x01c\x01hSearch for Filename(s)\r\n' },
'/S': { eval: 'bbs.scan_dirs(FL_NO_HDR, /* all */true) ' },
'T': { eval: 'bbs.temp_xfer()' },
'U': { eval: 'shell.upload_file()'
,msg: '\r\n\x01c\x01hUpload File\r\n' },
'/U': { eval: 'shell.upload_user_file()'
,msg: '\r\n\x01c\x01hUpload File to User\r\n' },
'V': { eval: 'shell.view_files()'
,msg: '\r\n\x01c\x01hView File(s)\r\n' },
'W': { eval: 'bbs.whos_online()' },
'Z': { eval: 'shell.upload_sysop_file()'
,msg: '\r\n\x01c\x01hUpload File to Sysop\r\n' },
'*': { eval: 'shell.show_dirs(bbs.curlib)' },
'/*': { eval: 'shell.show_libs()' },
'&': { exec: 'filescancfg.js' },
'!': { eval: 'bbs.menu("sysxfer")' },
'#': { msg: '\r\n\x01c\x01hType the actual number, not the symbol.\r\n' },
'/#': { msg: '\r\n\x01c\x01hType the actual number, not the symbol.\r\n' },
},
nav: {
'\r': { },
'Q': { eval: 'menu = main_menu' },
'>': { eval: 'shell.dir_up()' },
'}': { eval: 'shell.dir_up()' },
')': { eval: 'shell.dir_up()' },
'+': { eval: 'shell.dir_up()' },
'=': { eval: 'shell.dir_up()' },
'<': { eval: 'shell.dir_down()' },
'{': { eval: 'shell.dir_down()' },
'(': { eval: 'shell.dir_down()' },
'-': { eval: 'shell.dir_down()' },
']': { eval: 'shell.lib_up()' },
'[': { eval: 'shell.lib_down()' },
},
};
// Can't do these statically through initialization:
file_menu.nav[KEY_UP] = { eval: 'shell.dir_up()' };
file_menu.nav[KEY_DOWN] = { eval: 'shell.dir_down()' };
file_menu.nav[KEY_RIGHT] = { eval: 'shell.lib_up()' };
file_menu.nav[KEY_LEFT] = { eval: 'shell.lib_down()' };
var menu = main_menu;
var last_str_cmd = "";
// The menu-display/command-prompt loop
while(bbs.online && !js.terminated) {
if(!(user.settings & USER_EXPERT)) {
console.clear();
bbs.menu(menu.file);
}
bbs.node_action = menu.node_action;
bbs.nodesync();
eval(menu.eval);
console.crlf();
console.aborted = false;
console.putmsg(menu.prompt, P_SAVEATR);
var cmd = console.getkey(K_UPPER);
log("cmd = " + ascii(cmd));
if(cmd > ' ')
console.print(cmd);
if(cmd == ';') {
cmd = console.getstr();
if(cmd == '!')
cmd = last_str_cmd;
js.exec("str_cmds.js", {}, cmd);
last_str_cmd = cmd;
console.line_counter = 0;
continue;
}
if(cmd == '/') {
cmd = console.getkey(K_UPPER);
console.print(cmd);
if(cmd >= '1' && cmd <= '9') {
menu.slash_num_input(cmd);
continue;
}
cmd = '/' + cmd;
}
if(cmd >= '1' && cmd <= '9') {
menu.num_input(cmd);
continue;
}
if(cmd > ' ') {
bbs.log_key(cmd, /* comma: */true);
}
if(menu.nav[cmd]) {
if(menu.nav[cmd].eval)
eval(menu.nav[cmd].eval);
continue;
}
console.crlf();
console.line_counter = 0;
if(cmd == help_key) {
if(user.settings & USER_EXPERT)
bbs.menu(menu.file);
continue;
}
var menu_cmd = menu.command[cmd];
if(!menu_cmd) {
console.print("\r\n\x01c\x01hUnrecognized command.");
if(user.settings & USER_EXPERT)
console.print(" Hit '\x01i" + help_key + "\x01n\x01c\x01h' for a menu.");
console.crlf();
continue;
}
if(!bbs.compare_ars(menu_cmd.ars))
console.print(menu_cmd.err);
else {
if(menu_cmd.msg)
console.print(menu_cmd.msg);
if(menu_cmd.eval)
eval(menu_cmd.eval);
if(menu_cmd.exec) {
if(menu_cmd.args)
js.exec.apply(null, [menu_cmd.exec, {}].concat(menu_cmd.args));
else
js.exec(menu_cmd.exec, {});
}
}
}
// Library for writing command shells
// portions derived from classic_shell.js, default.src, and exec*.cpp
// @format.tab-size 4
"use strict";
require("text.js", "DownloadBatchQ");
require("sbbsdefs.js", "USER_EXPERT");
// Build list of current subs/dirs in each group/library
// This hack is required because the 'bbs' object doesn't expose the current
// sub/dir for any group/library except the current
var curgrp = bbs.curgrp;
var curlib = bbs.curlib;
var cursub = [];
var curdir = [];
var usrsubs = [];
var usrdirs = [];
var usrgrps = msg_area.grp_list.length;
var usrlibs = file_area.lib_list.length;
for(var i = 0; i < usrgrps; ++i) {
bbs.curgrp = i;
cursub[i] = bbs.cursub;
usrsubs[i] = msg_area.grp_list[i].sub_list.length;
}
for(var i = 0; i < usrlibs; ++i) {
bbs.curlib = i;
curdir[i] = bbs.curdir;
usrdirs[i] = file_area.lib_list[i].dir_list.length;
}
bbs.curgrp = curgrp;
bbs.curlib = curlib;
function get_num(str, max)
{
var num = Number(str);
while(bbs.online && !js.terminated) {
if(num * 10 > max)
break;
var ch = console.getkey(K_UPPER);
if(ch < '0' || ch > '9') {
if(ch > ' ')
console.ungetstr(ch);
break;
}
console.print(ch);
num *= 10;
num += Number(ch);
if(num > max)
return 0;
}
return num;
}
function get_grp_num(str)
{
var num = get_num(str, usrgrps);
if(num > 0)
bbs.curgrp = num -1;
}
function get_sub_num(str)
{
var num = get_num(str, usrsubs[bbs.curgrp]);
if(num > 0)
bbs.cursub = num - 1;
}
function get_lib_num(str)
{
var num = get_num(str, usrlibs);
if(num > 0)
bbs.curlib = num -1;
}
function get_dir_num(str)
{
var num = get_num(str, usrdirs[bbs.curlib]);
if(num > 0)
bbs.curdir = num - 1;
}
// List Message Groups
function show_grps()
{
if(msg_area.grp_list.length < 1)
return;
if(bbs.menu("grps", P_NOERROR))
return;
console.print(bbs.text(GrpLstHdr));
for(var i=0; i < msg_area.grp_list.length && !console.aborted; i++) {
if(i == bbs.curgrp)
console.print('*');
else console.print(' ');
if(i<9) console.print(' ');
console.add_hotspot(i+1);
console.print(format(bbs.text(GrpLstFmt), i+1
,msg_area.grp_list[i].description, "", msg_area.grp_list[i].sub_list.length));
}
}
function show_subs(grp)
{
if(msg_area.grp_list.length < 1)
return;
if(bbs.menu("subs" + msg_area.grp_list[grp].number, P_NOERROR))
return;
console.crlf();
console.print(format(bbs.text(SubLstHdr), msg_area.grp_list[grp].description));
for(var i=0; i < usrsubs[grp] && !console.aborted; ++i) {
if(i==cursub[grp]) console.print('*');
else console.print(' ');
var str = format(bbs.text(SubLstFmt),i+1
,msg_area.grp_list[grp].sub_list[i].description, ""
,msg_area.grp_list[grp].sub_list[i].posts);
if(i<9) console.print(' ');
if(i<99) console.print(' ');
console.add_hotspot(i+1);
console.print(str);
}
}
function select_msg_area()
{
if(usrgrps < 1)
return;
while(bbs.online) {
var j=0;
if(usrgrps > 1) {
show_grps();
console.mnemonics(format(bbs.text(JoinWhichGrp), bbs.curgrp + 1));
j=console.getnum(usrgrps);
console.clear_hotspots();
if(j==-1)
return;
if(!j)
j=bbs.curgrp;
else
j--;
}
show_subs(j);
console.mnemonics(format(bbs.text(JoinWhichSub), cursub[j]+1));
i=console.getnum(usrsubs[j]);
console.clear_hotspots();
if(i==-1) {
if(usrgrps==1)
return;
continue;
}
if(!i)
i=cursub[j];
else
i--;
bbs.curgrp=j;
bbs.cursub=i;
return;
}
return;
}
// List File Libraries
function show_libs()
{
if(file_area.lib_list.length < 1)
return;
if(bbs.menu("libs", P_NOERROR))
return;
console.print(bbs.text(LibLstHdr));
for(var i=0; i < file_area.lib_list.length && !console.aborted; i++) {
if(i == bbs.curlib)
console.print('*');
else console.print(' ');
if(i<9) console.print(' ');
console.add_hotspot(i+1);
console.print(format(bbs.text(LibLstFmt), i+1
,file_area.lib_list[i].description, "", file_area.lib_list[i].dir_list.length));
}
}
function show_dirs(lib)
{
if(file_area.lib_list.length < 1)
return;
if(bbs.menu("dirs" + file_area.lib_list[lib].number, P_NOERROR))
return;
console.crlf();
console.print(format(bbs.text(DirLstHdr), file_area.lib_list[lib].description));
for(var i=0; i < usrdirs[lib] && !console.aborted; ++i) {
if(i==curdir[lib]) console.print('*');
else console.print(' ');
var str = format(bbs.text(DirLstFmt),i+1
,file_area.lib_list[lib].dir_list[i].description, ""
,file_area.lib_list[lib].dir_list[i].files);
if(i<9) console.print(' ');
if(i<99) console.print(' ');
console.add_hotspot(i+1);
console.print(str);
}
}
function select_file_area()
{
var usrlibs = file_area.lib_list.length;
if(usrlibs < 1)
return;
while(bbs.online) {
var j=0;
if(usrlibs > 1) {
show_libs();
console.mnemonics(format(bbs.text(JoinWhichGrp), bbs.curlib + 1));
j=console.getnum(usrlibs);
console.clear_hotspots();
if(j==-1)
return;
if(!j)
j=bbs.curlib;
else
j--;
}
show_dirs(j);
console.mnemonics(format(bbs.text(JoinWhichDir), curdir[j]+1));
i=console.getnum(usrdirs[j]);
console.clear_hotspots();
if(i==-1) {
if(usrlibs==1)
return;
continue;
}
if(!i)
i=curdir[j];
else
i--;
bbs.curlib=j;
bbs.curdir=i;
return;
}
return;
}
function main_info()
{
while(bbs.online && !js.terminate) {
if(!(user.settings & USER_EXPERT))
bbs.menu("maininfo");
bbs.nodesync();
console.print("\r\n\x01y\x01hInfo: \x01n");
var key = console.getkeys("?QISVY\r");
bbs.log_key(key);
switch(key) {
case '?':
if(user.settings & USER_EXPERT)
bbs.menu("maininfo");
break;
case 'I':
bbs.sys_info();
break;
case 'S':
bbs.sub_info();
break;
case 'Y':
bbs.user_info();
break;
case 'V':
bbs.ver();
break;
default:
return;
}
}
}
// Prompts for new-file-scan the first time the user enters the file section
function enter_file_section()
{
if(bbs.file_cmds > 0)
return;
if(!(user.settings & USER_ASK_NSCAN))
return;
console.crlf(2);
if(console.yesno("Search all libraries for new files"))
bbs.scan_dirs(FL_ULTIME, /* all */true);
}
function file_info()
{
var key;
while(1) {
if(!(user.settings & USER_EXPERT))
bbs.menu("xferinfo");
// async
console.print("\r\n\x01y\x01hInfo: \x01n");
key=console.getkeys("?TYDUQ\r");
bbs.log_key(key);
switch(key) {
case '?':
if(user.settings & USER_EXPERT)
bbs.menu("xferinfo");
break;
case 'T':
bbs.xfer_policy();
break;
case 'Y':
bbs.user_info();
break;
case 'D':
bbs.dir_info();
break;
case 'U':
bbs.list_users(UL_DIR);
break;
case 'Q':
default:
return;
}
}
}
function list_users()
{
console.print("\r\n\x01c\x01hList Users\r\n");
console.mnemonics("\r\n~Logons Today, ~Yesterday, ~Sub-board, or ~All: ");
switch(console.getkeys("LSAY\r")) {
case 'L':
bbs.list_logons();
break;
case 'Y':
bbs.exec("?logonlist -y");
break;
case 'S':
bbs.list_users(UL_SUB);
break;
case 'A':
bbs.list_users(UL_ALL);
break;
}
}
function list_files()
{
var result = bbs.list_files();
if(result < 0)
return;
if(result == 0)
console.print(bbs.text(EmptyDir));
else
console.print(format(bbs.text(NFilesListed), result));
}
function view_file_info(mode)
{
var str=bbs.get_filespec();
if(!str)
return;
if(!bbs.list_file_info(file_area.lib_list[bbs.curlib].dir_list[bbs.curdir].number, str, mode)) {
var s=0;
console.print(bbs.text(SearchingAllDirs));
for(var i=0; i<file_area.lib_list[bbs.curlib].dir_list.length; i++) {
if(i!=bbs.curdir &&
(s=bbs.list_file_info(file_area.lib_list[bbs.curlib].dir_list[i].number, str, mode))!=0) {
if(s==-1 || str.indexOf('?')!=-1 || str.indexOf('*')!=-1) {
return;
}
}
}
console.print(bbs.text(SearchingAllLibs));
for(var i=0; i<file_area.lib_list.length; i++) {
if(i==bbs.curlib)
continue;
for(j=0; j<file_area.lib_list[i].dir_list.length; j++) {
if((s=bbs.list_file_info(file_area.lib_list[i].dir_list[j].number, str, mode))!=0) {
if(s==-1 || str.indexOf('?')!=-1 || str.indexOf('*')!=-1) {
return;
}
}
}
}
}
}
function view_files()
{
var str=bbs.get_filespec();
if(!str)
return;
if(!bbs.list_files(file_area.lib_list[bbs.curlib].dir_list[bbs.curdir].number, str, FL_VIEW)) {
console.print(bbs.text(SearchingAllDirs));
for(var i=0; i<file_area.lib_list[bbs.curlib].dir_list.length; i++) {
if(i==bbs.curdir)
continue;
if(bbs.list_files(file_area.lib_list[bbs.curlib].dir_list[i].number, str, FL_VIEW))
break;
}
if(i<file_area.lib_list[bbs.curlib].dir_list.length)
return;
console.print(bbs.text(SearchingAllLibs));
for(var i=0; i<file_area.lib_list.length; i++) {
if(i==bbs.curlib)
continue;
for(j=0; j<file_area.lib_list[i].dir_list.length; j++) {
if(bbs.list_files(file_area.lib_list[i].dir_list[j].number, str, FL_VIEW))
return;
}
}
}
}
function sub_up()
{
if(bbs.cursub == msg_area.grp_list[bbs.curgrp].sub_list.length - 1)
bbs.cursub = 0;
else
bbs.cursub++;
cursub[bbs.curgrp] = bbs.cursub;
}
function sub_down()
{
if(bbs.cursub == 0)
bbs.cursub = msg_area.grp_list[bbs.curgrp].sub_list.length - 1;
else
bbs.cursub--;
cursub[bbs.curgrp] = bbs.cursub;
}
function grp_up()
{
if(bbs.curgrp == msg_area.grp_list.length - 1)
bbs.curgrp = 0;
else
bbs.curgrp++;
}
function grp_down()
{
if(bbs.curgrp == 0)
bbs.curgrp = msg_area.grp_list.length - 1;
else
bbs.curgrp--;
}
function dir_up()
{
if(bbs.curdir == file_area.lib_list[bbs.curlib].dir_list.length - 1)
bbs.curdir = 0;
else
bbs.curdir++;
curdir[bbs.curdir] = bbs.curdir;
}
function dir_down()
{
if(bbs.curdir == 0)
bbs.curdir = file_area.lib_list[bbs.curlib].dir_list.length - 1;
else
bbs.curdir--;
curdir[bbs.curdir] = bbs.curdir;
}
function lib_up()
{
if(bbs.curlib == file_area.lib_list.length - 1)
bbs.curlib = 0;
else
bbs.curlib++;
}
function lib_down()
{
if(bbs.curlib == 0)
bbs.curlib = file_area.lib_list.length - 1;
else
bbs.curlib--;
}
function logoff(fast)
{
if(bbs.batch_dnload_total && console.yesno(bbs.text(DownloadBatchQ)))
bbs.batch_download();
else {
if(fast)
bbs.hangup();
else
bbs.logoff(/* prompt: */true);
}
}
function upload_file()
{
bbs.menu("upload");
var i=0xffff; /* INVALID_DIR */
if(usrlibs) {
i = file_area.lib_list[bbs.curlib].dir_list[bbs.curdir].number;
if(file_area.upload_dir != undefined
&& !file_area.lib_list[bbs.curlib].dir_list[bbs.curdir].can_upload)
i = file_area.upload_dir.number;
}
else {
if(file_area.upload_dir != undefined)
i = file_area.upload_dir.number;
}
bbs.upload_file(i);
}
function upload_user_file()
{
if(file_area.user_dir == undefined)
console.print(bbs.text(NoUserDir));
else
bbs.upload_file(file_area.user_dir.number);
}
function upload_sysop_file()
{
if(file_area.sysop_dir == undefined)
console.print(bbs.text(NoSysopDir));
else
bbs.upload_file(file_area.sysop_dir.number);
}
function download_files()
{
if(bbs.batch_dnload_total && console.yesno(bbs.text(DownloadBatchQ))) {
bbs.batch_download();
return;
}
view_file_info(FI_DOWNLOAD);
}
function download_user_files()
{
if(file_area.user_dir == undefined)
console.print(bbs.text(NoUserDir));
else {
if(!bbs.list_file_info(file_area.user_dir, FI_USERXFER))
console.print(bbs.text(NoFilesForYou));
}
}
this;
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