Skip to content
Snippets Groups Projects
js_bbs.cpp 101 KiB
Newer Older
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

 	if(!js_argc(cx, argc, 2))
		return(JS_FALSE);
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
rswindell's avatar
rswindell committed
		return(JS_FALSE);

		if(!JS_ValueToInt32(cx,argv[0],&node))
			return JS_FALSE;
	}
	if((js_msg=JS_ValueToString(cx, argv[1]))==NULL)
rswindell's avatar
rswindell committed
		return(JS_FALSE);

deuce's avatar
deuce committed
	JSSTRING_TO_MSTRING(cx, js_msg, msg, NULL);
rswindell's avatar
rswindell committed
		return(JS_FALSE);

	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(putnmsg(&sbbs->cfg,node,msg)==0));
deuce's avatar
deuce committed
	free(msg);
rswindell's avatar
rswindell committed

	return(JS_TRUE);
}

js_get_telegram(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
rswindell's avatar
rswindell committed
	sbbs_t*		sbbs;
deuce's avatar
deuce committed
	jsrefcount	rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
rswindell's avatar
rswindell committed
		return(JS_FALSE);

	usernumber=sbbs->useron.number;
	if(argc && JSVAL_IS_NUMBER(argv[0])) {
		if(!JS_ValueToInt32(cx,argv[0],&usernumber))
			return JS_FALSE;
	}
rswindell's avatar
rswindell committed
	sbbs->getsmsg(usernumber);
rswindell's avatar
rswindell committed

	return(JS_TRUE);
}

js_put_telegram(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
rswindell's avatar
rswindell committed
	sbbs_t*		sbbs;
rswindell's avatar
rswindell committed
	JSString*	js_msg;
	char*		msg;
deuce's avatar
deuce committed
	jsrefcount	rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

 	if(!js_argc(cx, argc, 2))
		return(JS_FALSE);
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
rswindell's avatar
rswindell committed
		return(JS_FALSE);

	if(argc && JSVAL_IS_NUMBER(argv[0])) {
		if(!JS_ValueToInt32(cx,argv[0],&usernumber))
			return JS_FALSE;
	}
	if((js_msg=JS_ValueToString(cx, argv[1]))==NULL)
rswindell's avatar
rswindell committed
		return(JS_FALSE);

deuce's avatar
deuce committed
	JSSTRING_TO_MSTRING(cx, js_msg, msg, NULL);
rswindell's avatar
rswindell committed
		return(JS_FALSE);

	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(putsmsg(&sbbs->cfg,usernumber,msg)==0));
deuce's avatar
deuce committed
	free(msg);
rswindell's avatar
rswindell committed

	return(JS_TRUE);
}

js_cmdstr(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
deuce's avatar
deuce committed
	const char	*def="";
	char*		fpath=(char *)def;
	char*		fspec=(char *)def;
deuce's avatar
deuce committed
	jsrefcount	rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

 	if(!js_argc(cx, argc, 1))
		return(JS_FALSE);
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
		return(JS_FALSE);

 	js_str = JS_ValueToString(cx, argv[0]);
 	if (!js_str)
 		return(JS_FALSE);

deuce's avatar
deuce committed
	JSSTRING_TO_MSTRING(cx, js_str, p, NULL);

	for(uintN i=1;i<argc;i++) {
		if(JSVAL_IS_STRING(argv[i])) {
			js_str = JS_ValueToString(cx, argv[i]);
deuce's avatar
deuce committed
			if(fpath==def) {
				JSSTRING_TO_MSTRING(cx, js_str, fpath, NULL);
				if(fpath==NULL) {
					if(fspec != def)
						free(fspec);
deuce's avatar
deuce committed
					return JS_FALSE;
deuce's avatar
deuce committed
			}
			else if(fspec==def) {
				JSSTRING_TO_MSTRING(cx, js_str, fspec, NULL);
				if(fspec==NULL) {
					if(fpath != def)
						free(fpath);
deuce's avatar
deuce committed
					return JS_FALSE;
	char* cmd = sbbs->cmdstr(p, fpath, fspec, NULL);
	free(p);
deuce's avatar
deuce committed
	if(fpath != def)
		free(fpath);
	if(fspec != def)
		free(fspec);
	if((js_str=JS_NewStringCopyZ(cx, cmd))==NULL)
		return(JS_FALSE);
	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
js_getfilespec(JSContext *cx, uintN argc, jsval *arglist)
deuce's avatar
deuce committed
	jsrefcount	rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
		JS_SET_RVAL(cx, arglist,JSVAL_NULL);
	else {
		JSString* js_str = JS_NewStringCopyZ(cx, p);
		if(js_str==NULL)
			return(JS_FALSE);
		JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
js_listfiles(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
deuce's avatar
deuce committed
	const char	*def=ALLFILES;
deuce's avatar
deuce committed
	char*		fspec=(char *)def;
	uint		dirnum;
    JSString*	js_str;
	sbbs_t*		sbbs;
deuce's avatar
deuce committed
	jsrefcount	rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
	dirnum=get_dirnum(cx,sbbs,argv[0], argc == 0);

	if(dirnum>=sbbs->cfg.total_dirs) {
		JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(0));
		return(JS_TRUE);
	}

	for(uintN i=1;i<argc;i++) {
		if(JSVAL_IS_NUMBER(argv[i])) {
			if(!JS_ValueToInt32(cx,argv[i],&mode)) {
				if(fspec != def)
					FREE_AND_NULL(fspec);
		else if(JSVAL_IS_STRING(argv[i])) {
			js_str = JS_ValueToString(cx, argv[i]);
			JSSTRING_TO_MSTRING(cx, js_str, afspec, NULL);
			if(afspec==NULL)
deuce's avatar
deuce committed
				return JS_FALSE;
	if(!(mode&(FL_FINDDESC|FL_EXFIND)))
	JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(sbbs->listfiles(dirnum,fspec,0 /* tofile */,mode)));
js_listfileinfo(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
deuce's avatar
deuce committed
	const char	*def=ALLFILES;
	char*		fspec=(char *)def;
	uint		dirnum;
    JSString*	js_str;
	sbbs_t*		sbbs;
deuce's avatar
deuce committed
	jsrefcount	rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
	dirnum=get_dirnum(cx,sbbs,argv[0], argc == 0);

	if(dirnum>=sbbs->cfg.total_dirs) {
		JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(0));
		return(JS_TRUE);
	}

	for(uintN i=1;i<argc;i++) {
		if(JSVAL_IS_NUMBER(argv[i])) {
			if(!JS_ValueToInt32(cx,argv[i],&mode))
				return JS_FALSE;
		}
		else if(JSVAL_IS_STRING(argv[i])) {
			js_str = JS_ValueToString(cx, argv[i]);
			if(fspec != def && fspec != NULL)
				free(fspec);
deuce's avatar
deuce committed
			JSSTRING_TO_MSTRING(cx, js_str, fspec, NULL);
			if(fspec==NULL)
				return JS_FALSE;
	JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(sbbs->listfileinfo(dirnum,padfname(fspec,buf),mode)));
deuce's avatar
deuce committed
	if(fspec != def)
		free(fspec);
js_postmsg(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
deuce's avatar
deuce committed
	jsrefcount	rc;
	JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
	subnum=get_subnum(cx,sbbs,argv,argc,0);
	if(subnum>=sbbs->cfg.total_subs) 	// invalid sub-board
		if(JSVAL_IS_NUMBER(argv[n])) {
			if(!JS_ValueToInt32(cx,argv[n],&mode))
				return JS_FALSE;
		}
		else if(JSVAL_IS_OBJECT(argv[n])) {
			if((hdrobj=JSVAL_TO_OBJECT(argv[n]))==NULL)
				return(JS_TRUE);
			remsg=&msg;
			if(!js_ParseMsgHeaderObject(cx,hdrobj,remsg))
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->postmsg(subnum,remsg,mode)));
js_msgscan_cfg(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
deuce's avatar
deuce committed
	jsrefcount	rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
	if(argc && JSVAL_IS_NUMBER(argv[0])) {
		if(!JS_ValueToInt32(cx,argv[0],&mode))
			return JS_FALSE;
	}
js_msgscan_ptrs(JSContext *cx, uintN argc, jsval *arglist)
deuce's avatar
deuce committed
	jsrefcount	rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
js_msgscan_reinit(JSContext *cx, uintN argc, jsval *arglist)
deuce's avatar
deuce committed
	jsrefcount	rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
	for(uint i=0;i<sbbs->cfg.total_subs;i++) {
		sbbs->subscan[i].ptr=sbbs->subscan[i].sav_ptr;
		sbbs->subscan[i].last=sbbs->subscan[i].sav_last;
	}
	sbbs->bputs(sbbs->text[MsgPtrsInitialized]);
js_scansubs(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
deuce's avatar
deuce committed
	jsrefcount	rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
		if(JSVAL_IS_NUMBER(argv[i])) {
			if(!JS_ValueToInt32(cx,argv[i],&mode))
				return JS_FALSE;
		}
		else if(JSVAL_IS_BOOLEAN(argv[i]))
			all=JSVAL_TO_BOOLEAN(argv[i]);
	}

	if(all)
		sbbs->scanallsubs(mode);
	else
		sbbs->scansubs(mode);
js_scandirs(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
deuce's avatar
deuce committed
	jsrefcount	rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
		if(JSVAL_IS_NUMBER(argv[i])) {
			if(!JS_ValueToInt32(cx,argv[i],&mode))
				return JS_FALSE;
		}
		else if(JSVAL_IS_BOOLEAN(argv[i]))
			all=JSVAL_TO_BOOLEAN(argv[i]);
	}

	if(all)
		sbbs->scanalldirs(mode);
	else
		sbbs->scandirs(mode);
js_scanposts(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
deuce's avatar
deuce committed
	const char	*def="";
	char*		find=(char *)def;
deuce's avatar
deuce committed
	jsrefcount	rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
	subnum=get_subnum(cx,sbbs,argv,argc,0);

	if(subnum>=sbbs->cfg.total_subs) {	// invalid sub-board
		JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
		if(JSVAL_IS_NUMBER(argv[i])) {
			if(!JS_ValueToInt32(cx,argv[i],&mode)) {
				if(find != def)
					free(find);
deuce's avatar
deuce committed
		else if(JSVAL_IS_STRING(argv[i]) && find==def) {
			JSVALUE_TO_MSTRING(cx, argv[i], find, NULL);
			if(find==NULL)
				return JS_FALSE;
		}
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->scanposts(subnum,mode,find)==0));
deuce's avatar
deuce committed
	if(find != def)
		free(find);
js_listmsgs(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
deuce's avatar
deuce committed
	const char	*def="";
	char*		find=(char *)def;
	uint		subnum;
	sbbs_t*		sbbs;
	uintN		argn=0;
deuce's avatar
deuce committed
	jsrefcount	rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
	JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(0));
	subnum=get_subnum(cx,sbbs,argv,argc,argn++);

	if(subnum>=sbbs->cfg.total_subs) 	// invalid sub-board
		return(JS_TRUE);

	if(argc > argn && JSVAL_IS_NUMBER(argv[argn])) {
		if(!JS_ValueToInt32(cx,argv[argn++],&mode))
			return JS_FALSE;
	}
	if(argc > argn && JSVAL_IS_NUMBER(argv[argn])) {
		if(!JS_ValueToInt32(cx,argv[argn++],&start))
			return JS_FALSE;
	}
deuce's avatar
deuce committed
	if(argc > argn && JSVAL_IS_STRING(argv[argn])) {
		JSVALUE_TO_MSTRING(cx, argv[argn++], find, NULL);
		if(find==NULL)
			return JS_FALSE;
	}
	JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(sbbs->listsub(subnum,mode,start,find)));
deuce's avatar
deuce committed
	if(find != def)
		free(find);
js_getnstime(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
deuce's avatar
deuce committed
	jsrefcount	rc;
	JS_SET_RVAL(cx, arglist, JSVAL_NULL);
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
	if(argc && JSVAL_IS_NUMBER(argv[0])) {
		int32 i;
		if(!JS_ValueToInt32(cx,argv[0],&i))
deuce's avatar
deuce committed
	if(sbbs->inputnstime(&t)==true) {
		JS_SET_RVAL(cx, arglist,DOUBLE_TO_JSVAL((double)t));
js_select_shell(JSContext *cx, uintN argc, jsval *arglist)
deuce's avatar
deuce committed
	jsrefcount	rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->select_shell()));
js_select_editor(JSContext *cx, uintN argc, jsval *arglist)
deuce's avatar
deuce committed
	jsrefcount	rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->select_editor()));
js_get_time_left(JSContext *cx, uintN argc, jsval *arglist)
deuce's avatar
deuce committed
	jsrefcount	rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
	JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(sbbs->gettimeleft()));
js_chk_ar(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
deuce's avatar
deuce committed
	char		*p;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
deuce's avatar
deuce committed
	JSVALUE_TO_MSTRING(cx, argv[0], p, NULL);
deuce's avatar
deuce committed
	if(p==NULL)
		return JS_FALSE;

	rc=JS_SUSPENDREQUEST(cx);
deuce's avatar
deuce committed
	ar = arstr(NULL,p,&sbbs->cfg);
deuce's avatar
deuce committed
	free(p);
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->chk_ar(ar,&sbbs->useron,&sbbs->client)));

	if(ar!=NULL && ar!=nular)
		free(ar);
	JS_RESUMEREQUEST(cx, rc);

	return JS_TRUE;
}

static JSBool
js_select_node(JSContext *cx, uintN argc, jsval *arglist)
{
	jsval *argv=JS_ARGV(cx, arglist);
	sbbs_t*		sbbs;
	jsrefcount	rc;
	BOOL		all = FALSE;

	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
		return(JS_FALSE);

	if(argc > 0 && JSVAL_IS_BOOLEAN(argv[0]))
		all = JSVAL_TO_BOOLEAN(argv[0]);

	rc=JS_SUSPENDREQUEST(cx);
	JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(sbbs->getnodetopage(all, /* telegram: */FALSE)));
	JS_RESUMEREQUEST(cx, rc);

	return JS_TRUE;
}

static JSBool
js_select_user(JSContext *cx, uintN argc, jsval *arglist)
{
	sbbs_t*		sbbs;
	jsrefcount	rc;

	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
		return(JS_FALSE);

	rc=JS_SUSPENDREQUEST(cx);
	JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(sbbs->getnodetopage(/* all: */FALSE, /* telegram: */TRUE)));
	JS_RESUMEREQUEST(cx, rc);

	return JS_TRUE;
}

static jsSyncMethodSpec js_bbs_functions[] = {
rswindell's avatar
rswindell committed
	{"atcode",			js_atcode,			1,	JSTYPE_STRING,	JSDOCSTR("code_string")
rswindell's avatar
rswindell committed
	,JSDOCSTR("returns @-code value, specified <i>code</i> string does not include @ character delimiters")
rswindell's avatar
rswindell committed
	/* text.dat */
rswindell's avatar
rswindell committed
	{"text",			js_text,			1,	JSTYPE_STRING,	JSDOCSTR("line_number")
rswindell's avatar
rswindell committed
	,JSDOCSTR("returns specified text string from text.dat")
rswindell's avatar
rswindell committed
	{"replace_text",	js_replace_text,	2,	JSTYPE_BOOLEAN,	JSDOCSTR("line_number, string text")
rswindell's avatar
rswindell committed
	,JSDOCSTR("replaces specified text string in memory")
rswindell's avatar
rswindell committed
	{"revert_text",		js_revert_text,		1,	JSTYPE_BOOLEAN,	JSDOCSTR("[line_number=<i>all</i>]")
rswindell's avatar
rswindell committed
	,JSDOCSTR("reverts specified text string to original text string; "
rswindell's avatar
rswindell committed
		"if <i>line_number</i> unspecified, reverts all text lines")
rswindell's avatar
rswindell committed
	{"load_text",		js_load_text,		1,	JSTYPE_BOOLEAN,	JSDOCSTR("base_filename")
	,JSDOCSTR("load an alternate text.dat from ctrl directory, automatically appends '.dat' to basefilename")
rswindell's avatar
rswindell committed
	/* procedures */
	{"newuser",			js_newuser,			0,	JSTYPE_VOID,	JSDOCSTR("")
rswindell's avatar
rswindell committed
	,JSDOCSTR("interactive new user procedure")
	{"login",			js_login,			4,	JSTYPE_BOOLEAN,	JSDOCSTR("user_name [,password_prompt] [,user_password] [,system_password]")
	,JSDOCSTR("login with <i>user_name</i>, displaying <i>password_prompt</i> for user's password (if required), "
	"optionally supplying the user's password and the system password as arguments so as to not be prompted")
	{"logon",			js_logon,			0,	JSTYPE_BOOLEAN,	JSDOCSTR("")
rswindell's avatar
rswindell committed
	,JSDOCSTR("interactive logon procedure")
	{"logoff",			js_logoff,			1,	JSTYPE_VOID,	JSDOCSTR("[prompt=<i>true</i>]")
	,JSDOCSTR("interactive logoff procedure, pass <i>false</i> for <i>prompt</i> argument to avoid yes/no prompt")
	,315
	{"logout",			js_logout,			0,	JSTYPE_VOID,	JSDOCSTR("")
rswindell's avatar
rswindell committed
	,JSDOCSTR("non-interactive logout procedure")
	{"hangup",			js_hangup,			0,	JSTYPE_VOID,	JSDOCSTR("")
rswindell's avatar
rswindell committed
	,JSDOCSTR("hangup (disconnect) immediately")
	{"node_sync",		js_nodesync,		0,	JSTYPE_ALIAS },
	{"nodesync",		js_nodesync,		0,	JSTYPE_VOID,	JSDOCSTR("")
	,JSDOCSTR("synchronize with node database, checks for messages, interruption, etc. (AKA node_sync)")
	{"auto_msg",		js_automsg,			0,	JSTYPE_VOID,	JSDOCSTR("")
rswindell's avatar
rswindell committed
	,JSDOCSTR("read/create system's auto-message")
	{"time_bank",		js_time_bank,		0,	JSTYPE_VOID,	JSDOCSTR("")
	,JSDOCSTR("enter the time banking system")
	{"qwk_sec",			js_qwk_sec,			0,	JSTYPE_VOID,	JSDOCSTR("")
rswindell's avatar
rswindell committed
	,JSDOCSTR("enter the QWK message packet upload/download/config section")
	{"text_sec",		js_text_sec,		0,	JSTYPE_VOID,	JSDOCSTR("")
	,JSDOCSTR("enter the text files section")
	{"xtrn_sec",		js_xtrn_sec,		0,	JSTYPE_VOID,	JSDOCSTR("")
	,JSDOCSTR("enter the external programs section")
	{"xfer_policy",		js_xfer_policy,		0,	JSTYPE_VOID,	JSDOCSTR("")
	,JSDOCSTR("display the file transfer policy")
	{"batch_menu",		js_batchmenu,		0,	JSTYPE_VOID,	JSDOCSTR("")
	,JSDOCSTR("enter the batch file transfer menu")
	{"batch_download",	js_batchdownload,	0,	JSTYPE_BOOLEAN,	JSDOCSTR("")
rswindell's avatar
rswindell committed
	,JSDOCSTR("start a batch download")
rswindell's avatar
rswindell committed
	{"batch_add_list",	js_batchaddlist,	1,	JSTYPE_VOID,	JSDOCSTR("list_filename")
	,JSDOCSTR("add file list to batch download queue")
	{"send_file",		js_sendfile,		1,	JSTYPE_BOOLEAN,	JSDOCSTR("filename [,protocol]")
	,JSDOCSTR("send specified filename (complete path) to user via user-prompted "
		"(or optionally specified) protocol")
	,314
	{"receive_file",	js_recvfile,		1,	JSTYPE_BOOLEAN,	JSDOCSTR("filename [,protocol]")
	,JSDOCSTR("received specified filename (complete path) frome user via user-prompted "
		"(or optionally specified) protocol")
	,314
	{"temp_xfer",		js_temp_xfer,		0,	JSTYPE_VOID,	JSDOCSTR("")
	,JSDOCSTR("enter the temporary file tranfer menu")
	{"user_sync",		js_user_sync,		0,	JSTYPE_VOID,	JSDOCSTR("")
	,JSDOCSTR("read the current user data from the database")
	{"user_config",		js_user_config,		0,	JSTYPE_VOID,	JSDOCSTR("")
	,JSDOCSTR("enter the user settings configuration menu")
	{"sys_info",		js_sys_info,		0,	JSTYPE_VOID,	JSDOCSTR("")
	,JSDOCSTR("display system information")
rswindell's avatar
rswindell committed
	{"sub_info",		js_sub_info,		1,	JSTYPE_VOID,	JSDOCSTR("[sub-board=<i>current</i>]")
rswindell's avatar
rswindell committed
	,JSDOCSTR("display message sub-board information (current <i>sub-board</i>, if unspecified)")
rswindell's avatar
rswindell committed
	{"dir_info",		js_dir_info,		0,	JSTYPE_VOID,	JSDOCSTR("[directory=<i>current</i>]")
rswindell's avatar
rswindell committed
	,JSDOCSTR("display file directory information (current <i>directory</i>, if unspecified)")
	{"user_info",		js_user_info,		0,	JSTYPE_VOID,	JSDOCSTR("")
	,JSDOCSTR("display current user information")
	{"ver",				js_ver,				0,	JSTYPE_VOID,	JSDOCSTR("")
	,JSDOCSTR("display software version information")
	{"sys_stats",		js_sys_stats,		0,	JSTYPE_VOID,	JSDOCSTR("")
	,JSDOCSTR("display system statistics")
rswindell's avatar
rswindell committed
	{"node_stats",		js_node_stats,		0,	JSTYPE_VOID,	JSDOCSTR("[node_number=<i>current</i>]")
	,JSDOCSTR("display current (or specified) node statistics")
rswindell's avatar
rswindell committed
	{"list_users",		js_userlist,		0,	JSTYPE_VOID,	JSDOCSTR("[mode=<tt>UL_ALL</tt>]")
	,JSDOCSTR("display user list"
	"(see <tt>UL_*</tt> in <tt>sbbsdefs.js</tt> for valid <i>mode</i> values)")
rswindell's avatar
rswindell committed
	{"edit_user",		js_useredit,		0,	JSTYPE_VOID,	JSDOCSTR("[user_number=<i>current</i>]")
	,JSDOCSTR("enter the user editor")
	{"change_user",		js_change_user,		0,	JSTYPE_VOID,	JSDOCSTR("")
	,JSDOCSTR("change to a different user")
	{"list_logons",		js_logonlist,		0,	JSTYPE_VOID,	JSDOCSTR("")
	,JSDOCSTR("display the logon list")
rswindell's avatar
rswindell committed
	{"read_mail",		js_readmail,		0,	JSTYPE_VOID,	JSDOCSTR("[which=<tt>MAIL_YOUR</tt>] [,user_number=<i>current</i>] [,loadmail_mode=<tt>0</tt>]")
	,JSDOCSTR("read private e-mail"
	"(see <tt>MAIL_*</tt> in <tt>sbbsdefs.js</tt> for valid <i>which</i> values)")
rswindell's avatar
rswindell committed
	{"email",			js_email,			1,	JSTYPE_BOOLEAN,	JSDOCSTR("to_user_number [,mode=<tt>WM_EMAIL</tt>] [,top=<i>none</i>] [,subject=<i>none</i>]")
	,JSDOCSTR("send private e-mail to a local user")
rswindell's avatar
rswindell committed
	{"netmail",			js_netmail,			1,	JSTYPE_BOOLEAN,	JSDOCSTR("address [,mode=<tt>WM_NONE</tt>] [,subject=<i>none</i>]")
	,JSDOCSTR("send private netmail")
	{"bulk_mail",		js_bulkmail,		0,	JSTYPE_VOID,	JSDOCSTR("[ars]")
rswindell's avatar
rswindell committed
	,JSDOCSTR("send bulk private e-mail, if <i>ars</i> not specified, prompt for destination users")
rswindell's avatar
rswindell committed
	{"upload_file",		js_upload_file,		1,	JSTYPE_BOOLEAN,	JSDOCSTR("[directory=<i>current</i>]")
rswindell's avatar
rswindell committed
	,JSDOCSTR("upload file to file directory specified by number or internal code")
rswindell's avatar
rswindell committed
	{"bulk_upload",		js_bulkupload,		1,	JSTYPE_BOOLEAN,	JSDOCSTR("[directory=<i>current</i>]")
rswindell's avatar
rswindell committed
	,JSDOCSTR("add files (already in local storage path) to file directory "
		"specified by number or internal code")
rswindell's avatar
rswindell committed
	{"resort_dir",		js_resort_dir,		1,	JSTYPE_BOOLEAN,	JSDOCSTR("[directory=<i>current</i>]")
rswindell's avatar
rswindell committed
	,JSDOCSTR("re-sort the file directory specified by number or internal code)")
	{"list_files",		js_listfiles,		1,	JSTYPE_NUMBER,	JSDOCSTR("[directory=<i>current</i>] [,filespec=<tt>\"*.*\"</tt> or search_string] [,mode=<tt>FL_NONE</tt>]")
rswindell's avatar
rswindell committed
	,JSDOCSTR("list files in the specified file directory, "
		"optionally specifying a file specification (wildcards) or a description search string, "
		"and <i>mode</i> (bitfield)")
rswindell's avatar
rswindell committed
	{"list_file_info",	js_listfileinfo,	1,	JSTYPE_NUMBER,	JSDOCSTR("[directory=<i>current</i>] [,filespec=<tt>\"*.*\"</tt>] [,mode=<tt>FI_INFO</tt>]")
	,JSDOCSTR("list extended file information for files in the specified file directory")
rswindell's avatar
rswindell committed
	{"post_msg",		js_postmsg,			1,	JSTYPE_BOOLEAN,	JSDOCSTR("[sub-board=<i>current</i>] [,mode=<tt>WM_MODE</tt>] [,object reply_header]")
rswindell's avatar
rswindell committed
	,JSDOCSTR("post a message in the specified message sub-board (number or internal code) "
		"with optinal <i>mode</i> (bitfield)<br>"
		"If <i>reply_header</i> is specified (a header object returned from <i>MsgBase.get_msg_header()</i>), that header "
		"will be used for the in-reply-to header fields (this argument added in v3.13)")
	,313
rswindell's avatar
rswindell committed
	{"cfg_msg_scan",	js_msgscan_cfg,		0,	JSTYPE_VOID,	JSDOCSTR("[type=<tt>SCAN_CFG_NEW</tt>]")
	,JSDOCSTR("configure message scan "
		"(<i>type</i> is either <tt>SCAN_CFG_NEW</tt> or <tt>SCAN_CFG_TOYOU</tt>)")
	{"cfg_msg_ptrs",	js_msgscan_ptrs,	0,	JSTYPE_VOID,	JSDOCSTR("")
	,JSDOCSTR("change message scan pointer values")
	{"reinit_msg_ptrs",	js_msgscan_reinit,	0,	JSTYPE_VOID,	JSDOCSTR("")
	,JSDOCSTR("re-initialize new message scan pointers")
rswindell's avatar
rswindell committed
	{"scan_subs",		js_scansubs,		0,	JSTYPE_VOID,	JSDOCSTR("[mode=<tt>SCAN_NEW</tt>] [,all=<tt>false</tt>]")
	,JSDOCSTR("scan sub-boards for messages")
rswindell's avatar
rswindell committed
	{"scan_dirs",		js_scandirs,		0,	JSTYPE_VOID,	JSDOCSTR("[mode=<tt>FL_NONE</tt>] [,all=<tt>false</tt>]")
	,JSDOCSTR("scan directories for files")
	{"scan_posts",		js_scanposts,		1,	JSTYPE_ALIAS },
	{"scan_msgs",		js_scanposts,		1,	JSTYPE_BOOLEAN,	JSDOCSTR("[sub-board=<i>current</i>] [,mode=<tt>SCAN_READ</tt>] [,string find]")
	,JSDOCSTR("scan messages in the specified message sub-board (number or internal code), "
		"optionally search for 'find' string (AKA scan_posts)")
	{"list_msgs",		js_listmsgs,		1,	JSTYPE_NUMBER,	JSDOCSTR("[sub-board=<i>current</i>] [,mode=<tt>SCAN_READ</tt>] [,message_number=<tt>0</tt>] [,string find]")
	,JSDOCSTR("list messages in the specified message sub-board (number or internal code), "
		"optionally search for 'find' string, returns number of messages listed")
rswindell's avatar
rswindell committed
	/* menuing */
	{"menu",			js_menu,			1,	JSTYPE_VOID,	JSDOCSTR("base_filename")
rswindell's avatar
rswindell committed
	,JSDOCSTR("display a menu file from the text/menu directory")
rswindell's avatar
rswindell committed
	{"log_key",			js_logkey,			1,	JSTYPE_BOOLEAN,	JSDOCSTR("key [,comma=<tt>false</tt>]")
	,JSDOCSTR("log key to node.log (comma optional)")
	{"log_str",			js_logstr,			1,	JSTYPE_BOOLEAN,	JSDOCSTR("text")
	,JSDOCSTR("log string to node.log")
rswindell's avatar
rswindell committed
	/* users */
	{"finduser",		js_finduser,		1,	JSTYPE_NUMBER,	JSDOCSTR("username_or_number")
rswindell's avatar
rswindell committed
	,JSDOCSTR("find user name (partial name support), interactive")
	{"trashcan",		js_trashcan,		2,	JSTYPE_BOOLEAN,	JSDOCSTR("base_filename, search_string")
	,JSDOCSTR("search file for psuedo-regexp (search string) in trashcan file (text/base_filename.can)")
rswindell's avatar
rswindell committed
	/* xtrn programs/modules */
rswindell's avatar
rswindell committed
	{"exec",			js_exec,			2,	JSTYPE_NUMBER,	JSDOCSTR("cmdline [,mode=<tt>EX_NONE</tt>] [,string startup_dir]")
	,JSDOCSTR("execute a program, optionally changing current directory to <i>startup_dir</i> "
	"(see <tt>EX_*</tt> in <tt>sbbsdefs.js</tt> for valid <i>mode</i> bits)")
	{"exec_xtrn",		js_exec_xtrn,		1,	JSTYPE_BOOLEAN,	JSDOCSTR("xtrn_number_or_code")
rswindell's avatar
rswindell committed
	,JSDOCSTR("execute external program by number or internal code")
rswindell's avatar
rswindell committed
	{"user_event",		js_user_event,		1,	JSTYPE_BOOLEAN,	JSDOCSTR("event_type")
	,JSDOCSTR("execute user event by event type "
	"(see <tt>EVENT_*</tt> in <tt>sbbsdefs.js</tt> for valid values)")
rswindell's avatar
rswindell committed
	{"telnet_gate",		js_telnet_gate,		1,	JSTYPE_VOID,	JSDOCSTR("address [,mode=<tt>TG_NONE</tt>]")
	,JSDOCSTR("external Telnet gateway (see <tt>TG_*</tt> in <tt>sbbsdefs.js</tt> for valid <i>mode</i> bits)")
	{"rlogin_gate",		js_rlogin_gate,		1,	JSTYPE_VOID,	JSDOCSTR("address [,client-user-name=<tt>user.alias</tt>, server-user-name=<tt>user.name</tt>, terminal=<tt>console.terminal</tt>] [,mode=<tt>TG_NONE</tt>]")