Skip to content
Snippets Groups Projects
js_bbs.cpp 131 KiB
Newer Older
#define PROP_READONLY JSPROP_ENUMERATE|JSPROP_READONLY
static jsSyncPropertySpec js_bbs_properties[] = {
/*		 name				,tinyid					,flags				,ver	*/

	{	"sys_status"		,BBS_PROP_SYS_STATUS	,JSPROP_ENUMERATE	,310},
	{	"startup_options"	,BBS_PROP_STARTUP_OPT	,JSPROP_ENUMERATE	,310},
	{	"answer_time"		,BBS_PROP_ANSWER_TIME	,JSPROP_ENUMERATE	,310},
	{	"logon_time"		,BBS_PROP_LOGON_TIME	,JSPROP_ENUMERATE	,310},
	{	"start_time"		,BBS_PROP_START_TIME	,JSPROP_ENUMERATE	,314},
	{	"new_file_time"		,BBS_PROP_NS_TIME		,JSPROP_ENUMERATE	,310},
	{	"last_new_file_time",BBS_PROP_LAST_NS_TIME	,JSPROP_ENUMERATE	,310},
	{	"online"			,BBS_PROP_ONLINE		,JSPROP_ENUMERATE	,310},
	{	"timeleft"			,BBS_PROP_TIMELEFT		,JSPROP_READONLY	,310},	/* alias */
	{	"time_left"			,BBS_PROP_TIMELEFT		,PROP_READONLY		,311},
	{	"event_time"		,BBS_PROP_EVENT_TIME	,PROP_READONLY		,311},
	{	"event_code"		,BBS_PROP_EVENT_CODE	,PROP_READONLY		,311},
	{	"first_node"		,BBS_PROP_FIRST_NODE	,PROP_READONLY		,320},
	{	"last_node"			,BBS_PROP_LAST_NODE		,PROP_READONLY		,320},
	{	"node_num"			,BBS_PROP_NODE_NUM		,PROP_READONLY		,310},
rswindell's avatar
rswindell committed
	{	"node_settings"		,BBS_PROP_NODE_SETTINGS	,JSPROP_ENUMERATE	,310},
	{	"node_status"		,BBS_PROP_NODE_STATUS	,PROP_READONLY		,31700},
	{	"node_errors"		,BBS_PROP_NODE_ERRORS	,PROP_READONLY		,31700},
	{	"node_action"		,BBS_PROP_NODE_ACTION	,JSPROP_ENUMERATE	,310},
rswindell's avatar
rswindell committed
	{	"node_useron"		,BBS_PROP_NODE_USERON	,PROP_READONLY		,31700},
	{	"node_connection"	,BBS_PROP_NODE_CONNECTION,PROP_READONLY		,31700},
	{	"node_misc"			,BBS_PROP_NODE_MISC		,PROP_READONLY		,31700},
	{	"node_aux"			,BBS_PROP_NODE_AUX		,PROP_READONLY		,31700},
	{	"node_extaux"		,BBS_PROP_NODE_EXTAUX	,PROP_READONLY		,31700},
	{	"node_val_user"		,BBS_PROP_NODE_VAL_USER	,JSPROP_ENUMERATE	,310},
	{	"logon_ulb"			,BBS_PROP_LOGON_ULB		,JSPROP_ENUMERATE	,310},
	{	"logon_dlb"			,BBS_PROP_LOGON_DLB		,JSPROP_ENUMERATE	,310},
	{	"logon_uls"			,BBS_PROP_LOGON_ULS		,JSPROP_ENUMERATE	,310},
	{	"logon_dls"			,BBS_PROP_LOGON_DLS		,JSPROP_ENUMERATE	,310},
	{	"logon_posts"		,BBS_PROP_LOGON_POSTS	,JSPROP_ENUMERATE	,310},
	{	"logon_emails"		,BBS_PROP_LOGON_EMAILS	,JSPROP_ENUMERATE	,310},
	{	"logon_fbacks"		,BBS_PROP_LOGON_FBACKS	,JSPROP_ENUMERATE	,310},
	{	"posts_read"		,BBS_PROP_POSTS_READ	,JSPROP_ENUMERATE	,310},
	{	"menu_dir"			,BBS_PROP_MENU_DIR		,JSPROP_ENUMERATE	,310},
	{	"menu_file"			,BBS_PROP_MENU_FILE		,JSPROP_ENUMERATE	,310},
	{	"main_cmds"			,BBS_PROP_MAIN_CMDS		,JSPROP_ENUMERATE	,310},
	{	"file_cmds"			,BBS_PROP_FILE_CMDS		,JSPROP_ENUMERATE	,310},
	{	"curgrp"			,BBS_PROP_CURGRP		,JSPROP_ENUMERATE	,310},
	{	"cursub"			,BBS_PROP_CURSUB		,JSPROP_ENUMERATE	,310},
	{	"cursub_code"		,BBS_PROP_CURSUB_CODE	,JSPROP_ENUMERATE	,314},
	{	"curlib"			,BBS_PROP_CURLIB		,JSPROP_ENUMERATE	,310},
	{	"curdir"			,BBS_PROP_CURDIR		,JSPROP_ENUMERATE	,310},
	{	"curdir_code"		,BBS_PROP_CURDIR_CODE	,JSPROP_ENUMERATE	,314},
	{	"connection"		,BBS_PROP_CONNECTION	,PROP_READONLY		,310},
	{	"rlogin_name"		,BBS_PROP_RLOGIN_NAME	,JSPROP_ENUMERATE	,310},
	{	"rlogin_password"	,BBS_PROP_RLOGIN_PASS	,JSPROP_ENUMERATE	,315},
	{	"rlogin_terminal"	,BBS_PROP_RLOGIN_TERM	,JSPROP_ENUMERATE	,316},
	{	"client_name"		,BBS_PROP_CLIENT_NAME	,JSPROP_ENUMERATE	,310},
	{	"errorlevel"		,BBS_PROP_ERRORLEVEL	,PROP_READONLY		,312},

	{	"smb_group"			,BBS_PROP_SMB_GROUP			,PROP_READONLY	,310},
	{	"smb_group_desc"	,BBS_PROP_SMB_GROUP_DESC	,PROP_READONLY	,310},
	{	"smb_group_number"	,BBS_PROP_SMB_GROUP_NUM		,PROP_READONLY	,310},
	{	"smb_sub"			,BBS_PROP_SMB_SUB			,PROP_READONLY	,310},
	{	"smb_sub_desc"		,BBS_PROP_SMB_SUB_DESC		,PROP_READONLY	,310},
	{	"smb_sub_code"		,BBS_PROP_SMB_SUB_CODE		,PROP_READONLY	,310},
	{	"smb_sub_number"	,BBS_PROP_SMB_SUB_NUM		,PROP_READONLY	,310},
	{	"smb_attr"			,BBS_PROP_SMB_ATTR			,PROP_READONLY	,310},
	{	"smb_last_msg"		,BBS_PROP_SMB_LAST_MSG		,PROP_READONLY	,310},
	{	"smb_total_msgs"	,BBS_PROP_SMB_TOTAL_MSGS	,PROP_READONLY	,310},
	{	"smb_msgs"			,BBS_PROP_SMB_MSGS			,PROP_READONLY	,310},
	{	"smb_curmsg"		,BBS_PROP_SMB_CURMSG		,JSPROP_ENUMERATE, 310},
	{	"msg_to"			,BBS_PROP_MSG_TO			,PROP_READONLY	,310},
	{	"msg_to_ext"		,BBS_PROP_MSG_TO_EXT		,PROP_READONLY	,310},
	{	"msg_to_net"		,BBS_PROP_MSG_TO_NET		,PROP_READONLY	,310},
	{	"msg_to_agent"		,BBS_PROP_MSG_TO_AGENT		,PROP_READONLY	,310},
	{	"msg_from"			,BBS_PROP_MSG_FROM			,PROP_READONLY	,310},
	{	"msg_from_ext"		,BBS_PROP_MSG_FROM_EXT		,PROP_READONLY	,310},
	{	"msg_from_net"		,BBS_PROP_MSG_FROM_NET		,PROP_READONLY	,310},
	{	"msg_from_bbsid"	,BBS_PROP_MSG_FROM_BBSID	,PROP_READONLY	,31802},
	{	"msg_from_agent"	,BBS_PROP_MSG_FROM_AGENT	,PROP_READONLY	,310},
	{	"msg_replyto"		,BBS_PROP_MSG_REPLYTO		,PROP_READONLY	,310},
	{	"msg_replyto_ext"	,BBS_PROP_MSG_REPLYTO_EXT	,PROP_READONLY	,310},
	{	"msg_replyto_net"	,BBS_PROP_MSG_REPLYTO_NET	,PROP_READONLY	,310},
	{	"msg_replyto_agent"	,BBS_PROP_MSG_REPLYTO_AGENT	,PROP_READONLY	,310},
	{	"msg_subject"		,BBS_PROP_MSG_SUBJECT		,PROP_READONLY	,310},
	{	"msg_date"			,BBS_PROP_MSG_DATE			,PROP_READONLY	,310},
	{	"msg_timezone"		,BBS_PROP_MSG_TIMEZONE		,PROP_READONLY	,310},
	{	"msg_date_imported"	,BBS_PROP_MSG_DATE_IMPORTED	,PROP_READONLY	,310},
	{	"msg_attr"			,BBS_PROP_MSG_ATTR			,PROP_READONLY	,310},
	{	"msg_auxattr"		,BBS_PROP_MSG_AUXATTR		,PROP_READONLY	,310},
	{	"msg_netattr"		,BBS_PROP_MSG_NETATTR		,PROP_READONLY	,310},
	{	"msg_offset"		,BBS_PROP_MSG_OFFSET		,PROP_READONLY	,310},
	{	"msg_number"		,BBS_PROP_MSG_NUMBER		,JSPROP_ENUMERATE ,310},
	{	"msg_expiration"	,BBS_PROP_MSG_EXPIRATION	,PROP_READONLY	,310},
	{	"msg_forwarded"		,BBS_PROP_MSG_FORWARDED		,PROP_READONLY	,310},
	{	"msg_thread_id"		,BBS_PROP_MSG_THREAD_BACK	,PROP_READONLY	,316},
	{	"msg_thread_back"	,BBS_PROP_MSG_THREAD_BACK	,PROP_READONLY	,312},
	{	"msg_thread_orig"	,BBS_PROP_MSG_THREAD_BACK	,JSPROP_READONLY,310},	/* alias */
	{	"msg_thread_next"	,BBS_PROP_MSG_THREAD_NEXT	,PROP_READONLY	,310},
	{	"msg_thread_first"	,BBS_PROP_MSG_THREAD_FIRST	,PROP_READONLY	,310},
	{	"msg_id"			,BBS_PROP_MSG_ID			,PROP_READONLY	,310},
	{	"msg_reply_id"		,BBS_PROP_MSG_REPLY_ID		,PROP_READONLY	,310},
	{	"msg_delivery_attempts"	,BBS_PROP_MSG_DELIVERY_ATTEMPTS
	{	"msghdr_top_of_screen"	,BBS_PROP_MSGHDR_TOS	,PROP_READONLY	,31702},

	{	"file_name"			,BBS_PROP_FILE_NAME			,PROP_READONLY	,317},
	{	"file_description"	,BBS_PROP_FILE_DESC			,PROP_READONLY	,317},
	{	"file_dir_number"	,BBS_PROP_FILE_DIR			,PROP_READONLY	,317},
	{	"file_attr"			,BBS_PROP_FILE_ATTR			,PROP_READONLY	,317},
	{	"file_date"			,BBS_PROP_FILE_DATE			,PROP_READONLY	,317},
	{	"file_size"			,BBS_PROP_FILE_SIZE			,PROP_READONLY	,317},
	{	"file_credits"		,BBS_PROP_FILE_CREDITS		,PROP_READONLY	,317},
	{	"file_uploader"		,BBS_PROP_FILE_ULER			,PROP_READONLY	,317},
	{	"file_upload_date"	,BBS_PROP_FILE_DATE_ULED	,PROP_READONLY	,317},
	{	"file_download_date",BBS_PROP_FILE_DATE_DLED	,PROP_READONLY	,317},
	{	"file_download_count",BBS_PROP_FILE_TIMES_DLED	,PROP_READONLY	,317},

	{	"download_cps"		,BBS_PROP_DOWNLOAD_CPS		,PROP_READONLY	,320},
	{	"batch_upload_total",BBS_PROP_BATCH_UPLOAD_TOTAL,PROP_READONLY	,310},
	{	"batch_dnload_total",BBS_PROP_BATCH_DNLOAD_TOTAL,PROP_READONLY	,310},
rswindell's avatar
rswindell committed
	{	"command_str"		,BBS_PROP_COMMAND_STR		,JSPROP_ENUMERATE, 314},
/* Utility functions */
static uint get_subnum(JSContext* cx, sbbs_t* sbbs, jsval *argv, int argc, int pos)
	if(argc>pos && JSVAL_IS_STRING(argv[pos])) {
deuce's avatar
deuce committed
		char * p;

deuce's avatar
deuce committed
		JSSTRING_TO_ASTRING(cx, JSVAL_TO_STRING(argv[pos]), p, LEN_EXTCODE+2, NULL);
		for(subnum=0;subnum<sbbs->cfg.total_subs;subnum++)
			if(!stricmp(sbbs->cfg.sub[subnum]->code,p))
				break;
	} else if(argc>pos && JSVAL_IS_NUMBER(argv[pos])) {
		uint32 i;
		if(!JS_ValueToECMAUint32(cx,argv[pos],&i))
	else if(sbbs->usrgrps>0)
		subnum=sbbs->usrsub[sbbs->curgrp][sbbs->cursub[sbbs->curgrp]];

	return(subnum);
}

static uint get_dirnum(JSContext* cx, sbbs_t* sbbs, jsval val, bool dflt)
		dirnum=sbbs->usrdir[sbbs->curlib][sbbs->curdir[sbbs->curlib]];

	if(!dflt) {
deuce's avatar
deuce committed
			JSSTRING_TO_ASTRING(cx, JSVAL_TO_STRING(val), p, LEN_EXTCODE+2, NULL);
			for(dirnum=0;dirnum<sbbs->cfg.total_dirs;dirnum++)
				if(!stricmp(sbbs->cfg.dir[dirnum]->code,p))
					break;
		} else if(JSVAL_IS_NUMBER(val)) {
			uint32 i;
			if(!JS_ValueToECMAUint32(cx,val,&i))
		}
		else if(sbbs->usrlibs>0)
			dirnum=sbbs->usrdir[sbbs->curlib][sbbs->curdir[sbbs->curlib]];
	}

/**************************/
/* bbs Object Methods */
/**************************/

static JSBool
js_menu(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
    JSString*	str;
 	sbbs_t*		sbbs;
deuce's avatar
deuce committed
	jsrefcount	rc;
deuce's avatar
deuce committed
	char		*menu;
	int32		mode = P_NONE;
	JSObject*	obj = JS_GetScopeChain(cx);
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
 	str = JS_ValueToString(cx, argv[0]);
 	if (!str)
 		return(JS_FALSE);
	uintN argn = 1;
	if(argc > argn && JSVAL_IS_NUMBER(argv[argn])) {
		if(!JS_ValueToInt32(cx,argv[argn], &mode))
			return JS_FALSE;
		argn++;
	}
	if(argc > argn && JSVAL_IS_OBJECT(argv[argn])) {
		if((obj = JSVAL_TO_OBJECT(argv[argn])) == NULL)
			return JS_FALSE;
		argn++;
	}

deuce's avatar
deuce committed
	JSSTRING_TO_MSTRING(cx, str, menu, NULL);
	if(!menu)
		return JS_FALSE;
	bool result = sbbs->menu(menu, mode, obj);
deuce's avatar
deuce committed
	free(menu);
	JS_SET_RVAL(cx, arglist, result ? JSVAL_TRUE : JSVAL_FALSE);
    return(JS_TRUE);
}
rswindell's avatar
rswindell committed
static JSBool
js_menu_exists(JSContext *cx, uintN argc, jsval *arglist)
{
	jsval *argv=JS_ARGV(cx, arglist);
    JSString*	str;
 	sbbs_t*		sbbs;
	jsrefcount	rc;
	char		*menu;

 	if(!js_argc(cx, argc, 1))
		return(JS_FALSE);

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

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

	JSSTRING_TO_MSTRING(cx, str, menu, NULL);
	if(!menu)
		return JS_FALSE;
	rc=JS_SUSPENDREQUEST(cx);
	bool result = sbbs->menu_exists(menu);
	free(menu);
	JS_RESUMEREQUEST(cx, rc);

	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(result));

    return(JS_TRUE);
}


rswindell's avatar
rswindell committed
static JSBool
js_hangup(JSContext *cx, uintN argc, jsval *arglist)
rswindell's avatar
rswindell committed
{
	sbbs_t*		sbbs;
deuce's avatar
deuce committed
	jsrefcount	rc;
rswindell's avatar
rswindell committed

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

rswindell's avatar
rswindell committed
	sbbs->hangup();
rswindell's avatar
rswindell committed

	return(JS_TRUE);
}

rswindell's avatar
rswindell committed
static JSBool
js_nodesync(JSContext *cx, uintN argc, jsval *arglist)
rswindell's avatar
rswindell committed
{
	jsval*		argv=JS_ARGV(cx, arglist);
rswindell's avatar
rswindell committed
	sbbs_t*		sbbs;
deuce's avatar
deuce committed
	jsrefcount	rc;
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
rswindell's avatar
rswindell committed
		return(JS_FALSE);

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

	sbbs->getnodedat(sbbs->cfg.node_num,&sbbs->thisnode);
	sbbs->nodesync(clearline ? true : false);
rswindell's avatar
rswindell committed

	return(JS_TRUE);
}

static JSBool
js_exec(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
	sbbs_t*		sbbs;
    JSString*	cmd;
	JSString*	startup_dir=NULL;
	char*		p_startup_dir=NULL;
deuce's avatar
deuce committed
	jsrefcount	rc;
	char*		cstr;
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
		return(JS_FALSE);

 	if(!js_argc(cx, argc, 1))
		return(JS_FALSE);
	if((cmd=JS_ValueToString(cx, argv[0]))==NULL)
		return(JS_FALSE);

	for(i=1;i<argc;i++) {
		if(JSVAL_IS_NUMBER(argv[i])) {
			if(!JS_ValueToECMAUint32(cx,argv[i],&mode))
		else if(JSVAL_IS_STRING(argv[i]))
			startup_dir=JS_ValueToString(cx,argv[i]);
	}

deuce's avatar
deuce committed
	if(startup_dir!=NULL) {
		JSSTRING_TO_MSTRING(cx, startup_dir, p_startup_dir, NULL);
		if(p_startup_dir==NULL)
			return JS_FALSE;
	}
deuce's avatar
deuce committed
	JSSTRING_TO_MSTRING(cx, cmd, cstr, NULL);
	if(cstr==NULL) {
		FREE_AND_NULL(p_startup_dir);
deuce's avatar
deuce committed
		return JS_FALSE;
	JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(sbbs->external(cstr,mode,p_startup_dir)));
deuce's avatar
deuce committed
	free(cstr);
	if(p_startup_dir)
		free(p_startup_dir);
    return(JS_TRUE);
}

js_exec_xtrn(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
	char*		code;
	sbbs_t*		sbbs;
deuce's avatar
deuce committed
	jsrefcount	rc;
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
	if(!js_argc(cx, argc, 1))
		return JS_FALSE;

	if(JSVAL_IS_STRING(argv[0])) {
		JSVALUE_TO_ASTRING(cx,argv[0],code, LEN_CODE+2, NULL);
		if(code==NULL)
			return(JS_FALSE);

		for(i=0;i<sbbs->cfg.total_xtrns;i++)
			if(!stricmp(sbbs->cfg.xtrn[i]->code,code))
				break;
	} else if(JSVAL_IS_NUMBER(argv[0])) {
	if(i < 0 || i >= sbbs->cfg.total_xtrns) {
		JS_ReportError(cx, "Invalid external program specified");
		return JS_FALSE;
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->exec_xtrn(i)));
	return(JS_TRUE);
}

static JSBool
js_user_event(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
deuce's avatar
deuce committed
	jsrefcount	rc;
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
	if(argc && JSVAL_IS_NUMBER(argv[0])) {
		if(!JS_ValueToECMAUint32(cx,argv[0],&i))
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->user_event((user_event_t)i)));
static JSBool
js_checkfname(JSContext *cx, uintN argc, jsval *arglist)
{
	jsval *argv = JS_ARGV(cx, arglist);
	sbbs_t*		sbbs;
	char*		fname = NULL;
	jsrefcount	rc;

	JS_SET_RVAL(cx, arglist, JSVAL_FALSE);

	if(argc < 1 || !JSVAL_IS_STRING(argv[0]))
		return JS_TRUE;

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

	JSVALUE_TO_MSTRING(cx, argv[0], fname, NULL);
	if(fname == NULL)
		return JS_FALSE;

	rc=JS_SUSPENDREQUEST(cx);
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->checkfname(fname)));
	JS_RESUMEREQUEST(cx, rc);
	free(fname);

	return JS_TRUE;
}

static JSBool
js_chksyspass(JSContext *cx, uintN argc, jsval *arglist)
	sbbs_t*		sbbs;
deuce's avatar
deuce committed
	jsrefcount	rc;
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
		return(JS_FALSE);

	if (argc) {
		JSString* str = JS_ValueToString(cx, argv[0]);
		JSSTRING_TO_ASTRING(cx, str, sys_pw, sizeof(sbbs->cfg.sys_pass)+2, NULL);
	}

	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->chksyspass(sys_pw)));
	return(JS_TRUE);
}
js_chkpass(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
deuce's avatar
deuce committed
	char*		cstr;
	jsrefcount	rc;
	bool		unique = false;
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
 	if(!js_argc(cx, argc, 1))
		return(JS_FALSE);
	if(argc > 1 && JSVAL_IS_BOOLEAN(argv[1]))
		unique = JSVAL_TO_BOOLEAN(argv[1]);

	JSString* str=JS_ValueToString(cx,argv[0]);

deuce's avatar
deuce committed
	JSSTRING_TO_ASTRING(cx, str, cstr, LEN_PASS+2, NULL);
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->chkpass(cstr,&sbbs->useron, unique)));
js_text(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
Rob Swindell's avatar
Rob Swindell committed
	bool		dflt = false;
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
	JS_SET_RVAL(cx, arglist, JSVAL_NULL);
	if(argc > 0) {
		if(JSVAL_IS_NUMBER(argv[0])) {
			if(!JS_ValueToECMAUint32(cx,argv[0],&i))
				return JS_FALSE;
		} else {
			JSString* js_str = JS_ValueToString(cx, argv[0]);
			if(js_str == NULL)
				return JS_FALSE;
			char* id = nullptr;
			JSSTRING_TO_MSTRING(cx, js_str, id, NULL);
			i = sbbs->get_text_num(id) + 1;
			free(id);
		}
		if(argc > 1 && JSVAL_IS_BOOLEAN(argv[1]))
Rob Swindell's avatar
Rob Swindell committed
			dflt = JSVAL_TO_BOOLEAN(argv[1]);
	if(i > 0 && i <= TOTAL_TEXT) {
Rob Swindell's avatar
Rob Swindell committed
		JSString* js_str = JS_NewStringCopyZ(cx, dflt ? sbbs->text_sav[i - 1] : sbbs->text[i - 1]);
		if(js_str==NULL)
			return(JS_FALSE);
		JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
js_replace_text(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
 	if(!js_argc(cx, argc, 2))
		return(JS_FALSE);
		if(!JS_ValueToECMAUint32(cx,argv[0],&i))
	if(i < 1 || i > TOTAL_TEXT)

	if(sbbs->text[i]!=sbbs->text_sav[i] && sbbs->text[i]!=nulstr)
		free(sbbs->text[i]);
deuce's avatar
deuce committed
	JSVALUE_TO_MSTRING(cx, argv[1], p, NULL);
deuce's avatar
deuce committed
	if(p==NULL)
deuce's avatar
deuce committed
		return(JS_FALSE);
		sbbs->text[i]=(char*)nulstr;
		JS_SET_RVAL(cx, arglist, JSVAL_TRUE);
deuce's avatar
deuce committed
		sbbs->text[i]=p;
		JS_SET_RVAL(cx, arglist, JSVAL_TRUE);
js_revert_text(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
	if(argc && JSVAL_IS_NUMBER(argv[0])) {
		if(!JS_ValueToECMAUint32(cx,argv[0],&i))
		for(i=0;i<TOTAL_TEXT;i++) {
			if(sbbs->text[i]!=sbbs->text_sav[i] && sbbs->text[i]!=nulstr)
				free(sbbs->text[i]);
			sbbs->text[i]=sbbs->text_sav[i];
		}
	} else {
		if(sbbs->text[i]!=sbbs->text_sav[i] && sbbs->text[i]!=nulstr)
			free(sbbs->text[i]);
		sbbs->text[i]=sbbs->text_sav[i];
	}

	JS_SET_RVAL(cx, arglist, JSVAL_TRUE);
js_load_text(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
	int			i;
	char		path[MAX_PATH+1];
	FILE*		stream;
	JSString*	js_str;
	sbbs_t*		sbbs;
deuce's avatar
deuce committed
	char*		cstr;
	jsrefcount	rc;
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
		return(JS_FALSE);

	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

 	if(!js_argc(cx, argc, 1))
		return(JS_FALSE);
	if((js_str=JS_ValueToString(cx, argv[0]))==NULL) {
		JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
deuce's avatar
deuce committed
	JSSTRING_TO_MSTRING(cx, js_str, cstr, NULL);
	if(!cstr)
		return JS_FALSE;
	for(i=0;i<TOTAL_TEXT;i++) {
		if(sbbs->text[i]!=sbbs->text_sav[i]) {
			if(sbbs->text[i]!=nulstr)
				free(sbbs->text[i]);
			sbbs->text[i]=sbbs->text_sav[i];
deuce's avatar
deuce committed
		,sbbs->cfg.ctrl_dir,cstr);
deuce's avatar
deuce committed
	free(cstr);

	if((stream=fnopen(NULL,path,O_RDONLY))==NULL) {
		JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
		return(JS_TRUE);
	}
	for(i=0;i<TOTAL_TEXT && !feof(stream);i++) {
		if((sbbs->text[i]=readtext(NULL,stream,i))==NULL) {
		}
		if(!strcmp(sbbs->text[i],sbbs->text_sav[i])) {	/* If identical */
			free(sbbs->text[i]);					/* Don't alloc */
			sbbs->text[i]=sbbs->text_sav[i];
		}
		else if(sbbs->text[i][0]==0) {
			free(sbbs->text[i]);
			sbbs->text[i]=(char*)nulstr;
		JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
		JS_SET_RVAL(cx, arglist, JSVAL_TRUE);
Rob Swindell's avatar
Rob Swindell committed
static JSBool
js_load_user_text(JSContext* cx, uintN argc, jsval* arglist)
{
	sbbs_t*		sbbs;
	jsrefcount	rc;
	bool		result;

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

	rc = JS_SUSPENDREQUEST(cx);
	result = sbbs->load_user_text();
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(result));
	JS_RESUMEREQUEST(cx, rc);

	return(JS_TRUE);
}

js_atcode(JSContext *cx, uintN argc, jsval *arglist)
	jsval *argv=JS_ARGV(cx, arglist);
deuce's avatar
deuce committed
	jsrefcount	rc;
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
		return(JS_FALSE);

 	if(!js_argc(cx, argc, 1))
		return(JS_FALSE);
deuce's avatar
deuce committed
	JSVALUE_TO_MSTRING(cx, argv[0], instr, NULL);
	if(instr==NULL)
		return(JS_FALSE);

	cp = sbbs->formatted_atcode(instr, str, sizeof(str));
deuce's avatar
deuce committed
	free(instr);
		JS_SET_RVAL(cx, arglist, JSVAL_NULL);
		JSString* js_str = JS_NewStringCopyZ(cx, cp);
		if(js_str==NULL)
			return(JS_FALSE);
		JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
static JSBool
js_expand_atcodes(JSContext* cx, uintN argc, jsval* arglist)
{
	jsval* argv = JS_ARGV(cx, arglist);
	sbbs_t* sbbs;
	char	result[256] = "";
	char*	instr;
	jsrefcount	rc;

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

	smbmsg_t* msg = (smbmsg_t*)sbbs->current_msg;

	if (!js_argc(cx, argc, 1))
		return JS_FALSE;

	JSVALUE_TO_MSTRING(cx, argv[0], instr, NULL);
	if (instr == NULL)
		return JS_FALSE;

	if(argc > 1 && (JSVAL_IS_OBJECT(argv[1]) && !JSVAL_IS_NULL(argv[1]))) {
		if((hdrobj = JSVAL_TO_OBJECT(argv[1])) == NULL) {
			free(instr);
		}
		if(!js_GetMsgHeaderObjectPrivates(cx, hdrobj, /* smb_t: */NULL, &msg, /* post: */NULL)) {
			free(instr);
	sbbs->expand_atcodes(instr, result, sizeof result, msg);
	free(instr);
	JS_RESUMEREQUEST(cx, rc);
	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, result)));

	return JS_TRUE;
}
rswindell's avatar
rswindell committed
static JSBool
js_logkey(JSContext *cx, uintN argc, jsval *arglist)
rswindell's avatar
rswindell committed
{
	jsval *argv=JS_ARGV(cx, arglist);
rswindell's avatar
rswindell committed
	char*		p;
	JSBool		comma=false;
	JSString*	js_str;
	sbbs_t*		sbbs;
deuce's avatar
deuce committed
	jsrefcount	rc;
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
rswindell's avatar
rswindell committed
		return(JS_FALSE);

rswindell's avatar
rswindell committed
	if((js_str=JS_ValueToString(cx, argv[0]))==NULL) {
		JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
rswindell's avatar
rswindell committed
		return(JS_TRUE);
	}

	if(argc>1)
		JS_ValueToBoolean(cx,argv[1],&comma);
deuce's avatar
deuce committed
	JSSTRING_TO_MSTRING(cx, js_str, p, NULL);
deuce's avatar
deuce committed
	if(p==NULL) {
		JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
rswindell's avatar
rswindell committed
		return(JS_TRUE);
	}

rswindell's avatar
rswindell committed
	sbbs->logch(*p
		,comma ? true:false	// This is a dumb bool conversion to make BC++ happy
		);
deuce's avatar
deuce committed
	free(p);
	JS_SET_RVAL(cx, arglist, JSVAL_TRUE);
rswindell's avatar
rswindell committed
	return(JS_TRUE);
}

static JSBool
js_logstr(JSContext *cx, uintN argc, jsval *arglist)
rswindell's avatar
rswindell committed
{
	jsval *argv=JS_ARGV(cx, arglist);
rswindell's avatar
rswindell committed
	char*		p;
	JSString*	js_str;
	sbbs_t*		sbbs;
deuce's avatar
deuce committed
	jsrefcount	rc;
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
		return(JS_FALSE);

	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

 	if(!js_argc(cx, argc, 1))
		return(JS_FALSE);
rswindell's avatar
rswindell committed
	if((js_str=JS_ValueToString(cx, argv[0]))==NULL) {
		JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
rswindell's avatar
rswindell committed
		return(JS_TRUE);
	}

deuce's avatar
deuce committed
	JSSTRING_TO_MSTRING(cx, js_str, p, NULL);
deuce's avatar
deuce committed
	if(p==NULL) {
		JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
rswindell's avatar
rswindell committed
		return(JS_TRUE);
	}

rswindell's avatar
rswindell committed
	sbbs->log(p);
deuce's avatar
deuce committed
	free(p);
	JS_SET_RVAL(cx, arglist, JSVAL_TRUE);
rswindell's avatar
rswindell committed
	return(JS_TRUE);
}

static JSBool
js_finduser(JSContext *cx, uintN argc, jsval *arglist)
rswindell's avatar
rswindell committed
{
	jsval *argv=JS_ARGV(cx, arglist);
rswindell's avatar
rswindell committed
	char*		p;
	JSString*	js_str;
	sbbs_t*		sbbs;
deuce's avatar
deuce committed
	jsrefcount	rc;
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
		return(JS_FALSE);

 	if(!js_argc(cx, argc, 1))
		return(JS_FALSE);
rswindell's avatar
rswindell committed
	if((js_str=JS_ValueToString(cx, argv[0]))==NULL) {
		JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(0));
rswindell's avatar
rswindell committed
		return(JS_TRUE);
	}

deuce's avatar
deuce committed
	JSSTRING_TO_MSTRING(cx, js_str, p, NULL);
deuce's avatar
deuce committed
	if(p==NULL) {
		JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(0));
rswindell's avatar
rswindell committed
		return(JS_TRUE);
	}

rswindell's avatar
rswindell committed
	JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(sbbs->finduser(p, /* silent_failure: */true)));
deuce's avatar
deuce committed
	free(p);
rswindell's avatar
rswindell committed
	return(JS_TRUE);
}

static JSBool
js_trashcan(JSContext *cx, uintN argc, jsval *arglist)
rswindell's avatar
rswindell committed
{
	jsval *argv=JS_ARGV(cx, arglist);
rswindell's avatar
rswindell committed
	char*		str;
	char*		can;
	JSString*	js_str;
	JSString*	js_can;
	sbbs_t*		sbbs;
deuce's avatar
deuce committed
	jsrefcount	rc;
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
		return(JS_FALSE);

 	if(!js_argc(cx, argc, 2))
		return(JS_FALSE);
rswindell's avatar
rswindell committed
	if((js_can=JS_ValueToString(cx, argv[0]))==NULL) {
		JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
rswindell's avatar
rswindell committed
		return(JS_TRUE);
	}

	if((js_str=JS_ValueToString(cx, argv[1]))==NULL) {
		JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
rswindell's avatar
rswindell committed
		return(JS_TRUE);
	}

deuce's avatar
deuce committed
	JSSTRING_TO_MSTRING(cx, js_can, can, NULL);
deuce's avatar
deuce committed
	if(can==NULL) {
		JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
rswindell's avatar
rswindell committed
		return(JS_TRUE);
	}

deuce's avatar
deuce committed
	JSSTRING_TO_MSTRING(cx, js_str, str, NULL);
deuce's avatar
deuce committed
	if(str==NULL) {
deuce's avatar
deuce committed
		free(can);
		JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
rswindell's avatar
rswindell committed
		return(JS_TRUE);
	}

	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->trashcan(str,can)));
deuce's avatar
deuce committed
	free(can);
	free(str);
rswindell's avatar
rswindell committed
	return(JS_TRUE);
}

static JSBool
js_newuser(JSContext *cx, uintN argc, jsval *arglist)
rswindell's avatar
rswindell committed
{
	sbbs_t*		sbbs;
deuce's avatar
deuce committed
	jsrefcount	rc;
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
rswindell's avatar
rswindell committed
		return(JS_FALSE);

	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->newuser()));
rswindell's avatar
rswindell committed
	return(JS_TRUE);
}

static JSBool
js_logon(JSContext *cx, uintN argc, jsval *arglist)
rswindell's avatar
rswindell committed
{
	sbbs_t*		sbbs;
deuce's avatar
deuce committed
	jsrefcount	rc;
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
rswindell's avatar
rswindell committed
		return(JS_FALSE);

	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->logon()));
rswindell's avatar
rswindell committed
	return(JS_TRUE);
}

static JSBool
js_login(JSContext *cx, uintN argc, jsval *arglist)
rswindell's avatar
rswindell committed
{
	jsval *argv=JS_ARGV(cx, arglist);
rswindell's avatar
rswindell committed
	char*		name;
	char*		pw_prompt = NULL;
	char*		user_pw = NULL;
	char*		sys_pw = NULL;
rswindell's avatar
rswindell committed
	JSString*	js_name;
rswindell's avatar
rswindell committed
	JSString*	js_pw_prompt = NULL;
	JSString*	js_user_pw = NULL;
	JSString*	js_sys_pw = NULL;
rswindell's avatar
rswindell committed
	sbbs_t*		sbbs;
deuce's avatar
deuce committed
	jsrefcount	rc;
	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
		return(JS_FALSE);

 	if(!js_argc(cx, argc, 2))
		return(JS_FALSE);

	if((js_name=JS_ValueToString(cx, argv[0]))==NULL)
rswindell's avatar
rswindell committed
		return(JS_FALSE);

rswindell's avatar
rswindell committed
	if(argc > 1)
		js_pw_prompt = JS_ValueToString(cx, argv[1]);
	if(argc > 2)
		js_user_pw = JS_ValueToString(cx, argv[2]);
	if(argc > 3)
		js_sys_pw = JS_ValueToString(cx, argv[3]);
deuce's avatar
deuce committed
	JSSTRING_TO_ASTRING(cx, js_name, name, (LEN_ALIAS > LEN_NAME) ? LEN_ALIAS+2 : LEN_NAME+2, NULL);
rswindell's avatar
rswindell committed
		return(JS_FALSE);

	JSSTRING_TO_MSTRING(cx, js_pw_prompt, pw_prompt, NULL);
	JSSTRING_TO_MSTRING(cx, js_user_pw, user_pw, NULL);