Skip to content
Snippets Groups Projects
js_bbs.cpp 139 KiB
Newer Older
/* Synchronet JavaScript "bbs" Object */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
 *																			*
 * This program is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU General Public License				*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

#include "sbbs.h"
#include "filedat.h"

#ifdef JAVASCRIPT

/*****************************/
/* BBS Object Properites */
/*****************************/
enum {
	BBS_PROP_SYS_STATUS
	, BBS_PROP_STARTUP_OPT
	, BBS_PROP_ANSWER_TIME
	, BBS_PROP_LOGON_TIME
	, BBS_PROP_START_TIME
	, BBS_PROP_NS_TIME
	, BBS_PROP_LAST_NS_TIME
	, BBS_PROP_ONLINE
	, BBS_PROP_TIMELEFT
	, BBS_PROP_EVENT_TIME
	, BBS_PROP_EVENT_CODE

	, BBS_PROP_FIRST_NODE
	, BBS_PROP_LAST_NODE

	, BBS_PROP_NODE_NUM
	, BBS_PROP_NODE_SETTINGS
	, BBS_PROP_NODE_STATUS
	, BBS_PROP_NODE_ERRORS
	, BBS_PROP_NODE_ACTION
	, BBS_PROP_NODE_USERON
	, BBS_PROP_NODE_CONNECTION
	, BBS_PROP_NODE_MISC
	, BBS_PROP_NODE_AUX
	, BBS_PROP_NODE_EXTAUX
	, BBS_PROP_NODE_VAL_USER

	, BBS_PROP_LOGON_ULB
	, BBS_PROP_LOGON_DLB
	, BBS_PROP_LOGON_ULS
	, BBS_PROP_LOGON_DLS
	, BBS_PROP_LOGON_POSTS
	, BBS_PROP_LOGON_EMAILS
	, BBS_PROP_LOGON_FBACKS
	, BBS_PROP_POSTS_READ

	, BBS_PROP_MENU_DIR
	, BBS_PROP_MENU_FILE
	, BBS_PROP_MAIN_CMDS
	, BBS_PROP_FILE_CMDS

	, BBS_PROP_CURGRP
	, BBS_PROP_CURSUB
	, BBS_PROP_CURSUB_CODE
	, BBS_PROP_CURLIB
	, BBS_PROP_CURDIR
	, BBS_PROP_CURDIR_CODE

	, BBS_PROP_CONNECTION        /* READ ONLY */
	, BBS_PROP_RLOGIN_NAME
	, BBS_PROP_RLOGIN_PASS
	, BBS_PROP_RLOGIN_TERM
	, BBS_PROP_CLIENT_NAME

	, BBS_PROP_ERRORLEVEL        /* READ ONLY */
	, BBS_PROP_SMB_GROUP
	, BBS_PROP_SMB_GROUP_DESC
	, BBS_PROP_SMB_GROUP_NUM
	, BBS_PROP_SMB_SUB
	, BBS_PROP_SMB_SUB_DESC
	, BBS_PROP_SMB_SUB_CODE
	, BBS_PROP_SMB_SUB_NUM
	, BBS_PROP_SMB_ATTR
	, BBS_PROP_SMB_LAST_MSG
	, BBS_PROP_SMB_TOTAL_MSGS
	, BBS_PROP_SMB_MSGS
	, BBS_PROP_SMB_CURMSG    // writable
	, BBS_PROP_MSG_TO
	, BBS_PROP_MSG_TO_EXT
	, BBS_PROP_MSG_TO_NET
	, BBS_PROP_MSG_TO_AGENT
	, BBS_PROP_MSG_FROM
	, BBS_PROP_MSG_FROM_EXT
	, BBS_PROP_MSG_FROM_NET
	, BBS_PROP_MSG_FROM_BBSID
	, BBS_PROP_MSG_FROM_AGENT
	, BBS_PROP_MSG_REPLYTO
	, BBS_PROP_MSG_REPLYTO_EXT
	, BBS_PROP_MSG_REPLYTO_NET
	, BBS_PROP_MSG_REPLYTO_AGENT
	, BBS_PROP_MSG_SUBJECT
	, BBS_PROP_MSG_DATE
	, BBS_PROP_MSG_TIMEZONE
	, BBS_PROP_MSG_DATE_IMPORTED
	, BBS_PROP_MSG_ATTR
	, BBS_PROP_MSG_AUXATTR
	, BBS_PROP_MSG_NETATTR
	, BBS_PROP_MSG_OFFSET
	, BBS_PROP_MSG_NUMBER    // writable
	, BBS_PROP_MSG_EXPIRATION
	, BBS_PROP_MSG_FORWARDED
	, BBS_PROP_MSG_THREAD_ID
	, BBS_PROP_MSG_THREAD_BACK
	, BBS_PROP_MSG_THREAD_NEXT
	, BBS_PROP_MSG_THREAD_FIRST
	, BBS_PROP_MSG_ID
	, BBS_PROP_MSG_REPLY_ID
	, BBS_PROP_MSG_DELIVERY_ATTEMPTS

	, BBS_PROP_MSGHDR_TOS
	, BBS_PROP_DOWNLOAD_CPS
	, BBS_PROP_BATCH_UPLOAD_TOTAL
	, BBS_PROP_BATCH_DNLOAD_TOTAL
	/* READ ONLY */
	, BBS_PROP_FILE_NAME
	, BBS_PROP_FILE_DESC
	, BBS_PROP_FILE_DIR
	, BBS_PROP_FILE_ATTR
	, BBS_PROP_FILE_DATE
	, BBS_PROP_FILE_SIZE
	, BBS_PROP_FILE_CREDITS
	, BBS_PROP_FILE_ULER
	, BBS_PROP_FILE_DATE_ULED
	, BBS_PROP_FILE_DATE_DLED
	, BBS_PROP_FILE_TIMES_DLED

	, BBS_PROP_COMMAND_STR
static const char* bbs_prop_desc[] = {
	"System status bit-flags (see <tt>SS_*</tt> in <tt>sbbsdefs.js</tt> for bit definitions)"
	, "Startup options bit-flags (see <tt>BBS_OPT_*</tt> in <tt>sbbsdefs.js</tt> for bit definitions)"
	, "Answer time, in <i>time_t</i> format"
	, "Logon time, in <i>time_t</i> format"
	, "Time from which user's time left is calculated, in <i>time_t</i> format"
	, "Current file new-scan time, in <i>time_t</i> format"
	, "Previous file new-scan time, in <i>time_t</i> format"
	, "Online (see <tt>ON_*</tt> in <tt>sbbsdefs.js</tt> for valid values)"
	, "Time left (in seconds)"
	, "Time of next exclusive event (in <i>time_t</i> format), or 0 if none"
	, "Internal code of next exclusive event"

	, "First node number (of this instance of Synchronet)"
	, "Last node number (of this instance of Synchronet)"

	, "Current node number"
	, "Current node settings bit-flags (see <tt>NM_*</tt> in <tt>sbbsdefs.js</tt> for bit definitions)"
	, "Current node status value (see <tt>nodedefs.js</tt> for valid values)"
	, "Current node error counter"
	, "Current node action (see <tt>nodedefs.js</tt> for valid values)"
	, "Current node user number (<i>useron</i> value)"
	, "Current node connection type (see <tt>nodedefs.js</tt> for valid values)"
	, "Current node misc value (see <tt>nodedefs.js</tt> for valid values)"
	, "Current node aux value"
	, "Current node extended aux (<i>extaux</i>) value"
	, "Validation feedback user for this node (or 0 for no validation feedback required)"

	, "Bytes uploaded during this session"
	, "Bytes downloaded during this session"
	, "Files uploaded during this session"
	, "Files downloaded during this session"
	, "Messages posted during this session"
	, "E-mails sent during this session"
	, "Feedback messages sent during this session"
	, "Messages read during this session"

	, "Menu subdirectory (overrides default)"
	, "Menu file (overrides default)"
	, "Total main menu commands received from user during this session"
	, "Total file menu commands received from user during this session"

	, "Current message group"
	, "Current message sub-board"
	, "Current message sub-board internal code"
	, "Current file library"
	, "Current file directory"
	, "Current file directory internal code"

	, "Remote connection type"
	, "Login name given during RLogin negotiation"
	, "Password specified during RLogin negotiation"
	, "Terminal specified during RLogin negotiation"
	, "Client name"

	, "Error level returned from last executed external program"
	/* READ ONLY */
	, "Message group name of message being read"
	, "Message group description of message being read"
	, "Message group number of message being read"
	, "Sub-board name of message being read"
	, "Sub-board description of message being read"
	, "Sub-board internal code of message being read"
	, "Sub-board number of message being read"
	, "Message base attributes"
	, "Highest message number in message base"
	, "Total number of messages in message base"
	, "Number of messages loaded from message base"
	, "Current message number in message base"

	/* READ ONLY */
	, "Message recipient name"
	, "Message recipient extension"
	, "Message recipient network address"
	, "Message recipient agent type"
	, "Message sender name"
	, "Message sender extension"
	, "Message sender network address"
	, "Message sender BBS ID"
	, "Message sender agent type"
	, "Message reply-to name"
	, "Message reply-to extension"
	, "Message reply-to network address"
	, "Message reply-to agent type"
	, "Message subject"
	, "Message date/time"
	, "Message time zone"
	, "Message date/time imported"
	, "Message attributes"
	, "Message auxiliary attributes"
	, "Message network attributes"
	, "Message header offset"
	, "Message number (unique, monotonically incrementing)"
	, "Message expiration"
	, "Message forwarded"
	, "Message thread identifier (0 if unknown)"
	, "Message thread, back message number"
	, "Message thread, next message number"
	, "Message thread, message number of first reply to this message"
	, "Message identifier"
	, "Message replied-to identifier"
	, "Message delivery attempt counter"

	, "Message header displayed at top-of-screen"

	, "File name"
	, "File description"
	, "File directory (number)"
	, "File attribute flags"
	, "File date"
	, "File size (in bytes)"
	, "File credit value"
	, "File uploader (user name)"
	, "File upload date"
	, "File last-download date"
	, "File download count"

	, "Most recent file download rate (in characters/bytes per second)"
	, "Number of files in batch upload queue"
	, "Number of files in batch download queue"

	, "Current command shell/module <i>command string</i> value"
	, NULL
};
extern JSClass     js_bbs_class; // defined later
static sbbs_t *js_GetPrivate(JSContext *cx, JSObject *obj)
	return (sbbs_t *)js_GetClassPrivate(cx, obj, &js_bbs_class);
static JSBool js_bbs_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
	jsval       idval;
	char        tmp[128];
	const char* p = NULL;
	const char* nulstr = "";
	uint32      val = 0;
	jsint       tiny;
	sbbs_t*     sbbs;
	jsrefcount  rc;
	if ((sbbs = js_GetPrivate(cx, obj)) == NULL)
	JS_IdToValue(cx, id, &idval);
	tiny = JSVAL_TO_INT(idval);
		case BBS_PROP_SYS_STATUS:
			val = sbbs->sys_status;
			break;
		case BBS_PROP_STARTUP_OPT:
			val = sbbs->startup->options;
			break;
		case BBS_PROP_ANSWER_TIME:
			val = (uint32)sbbs->answertime;
			break;
		case BBS_PROP_LOGON_TIME:
			val = (uint32)sbbs->logontime;
			val = (uint32)sbbs->starttime;
		case BBS_PROP_NS_TIME:
			val = (uint32)sbbs->ns_time;
			break;
		case BBS_PROP_LAST_NS_TIME:
			val = (uint32)sbbs->last_ns_time;
		case BBS_PROP_ONLINE:
			val = sbbs->online;
		case BBS_PROP_TIMELEFT:
			rc = JS_SUSPENDREQUEST(cx);
			val = sbbs->gettimeleft(false);
			val = (uint32)sbbs->event_time;
			p = sbbs->event_code;
		case BBS_PROP_FIRST_NODE:
			val = sbbs->startup->first_node;
			break;
		case BBS_PROP_LAST_NODE:
			val = sbbs->startup->last_node;
			break;

		case BBS_PROP_NODE_NUM:
			val = sbbs->cfg.node_num;
rswindell's avatar
rswindell committed
		case BBS_PROP_NODE_SETTINGS:
			val = sbbs->cfg.node_misc;
rswindell's avatar
rswindell committed
		case BBS_PROP_NODE_STATUS:
			val = sbbs->thisnode.status;
rswindell's avatar
rswindell committed
			break;
		case BBS_PROP_NODE_ERRORS:
			val = sbbs->thisnode.errors;
rswindell's avatar
rswindell committed
			break;
rswindell's avatar
rswindell committed
		case BBS_PROP_NODE_ACTION:
			val = sbbs->action;
rswindell's avatar
rswindell committed
			break;
rswindell's avatar
rswindell committed
		case BBS_PROP_NODE_USERON:
			val = sbbs->thisnode.useron;
rswindell's avatar
rswindell committed
			break;
		case BBS_PROP_NODE_CONNECTION:
			val = sbbs->thisnode.connection;
rswindell's avatar
rswindell committed
			break;
		case BBS_PROP_NODE_MISC:
			val = sbbs->thisnode.misc;
rswindell's avatar
rswindell committed
			break;
		case BBS_PROP_NODE_AUX:
			val = sbbs->thisnode.aux;
rswindell's avatar
rswindell committed
			break;
		case BBS_PROP_NODE_EXTAUX:
			val = sbbs->thisnode.extaux;
rswindell's avatar
rswindell committed
			break;

		case BBS_PROP_NODE_VAL_USER:
			val = sbbs->cfg.valuser;
			break;

		case BBS_PROP_LOGON_ULB:
			val = (uint32_t)sbbs->logon_ulb;  // TODO: fix for > 4GB!
			break;
		case BBS_PROP_LOGON_DLB:
			val = (uint32_t)sbbs->logon_dlb;  // TODO: fix for > 4GB!
			break;
		case BBS_PROP_LOGON_ULS:
			val = (uint32_t)sbbs->logon_uls;  // TODO: fix for > 4GB!
			break;
		case BBS_PROP_LOGON_DLS:
			val = (uint32_t)sbbs->logon_dls;  // TODO: fix for > 4GB!
			break;
		case BBS_PROP_LOGON_POSTS:
			val = sbbs->logon_posts;
			break;
		case BBS_PROP_LOGON_EMAILS:
			val = sbbs->logon_emails;
			break;
		case BBS_PROP_LOGON_FBACKS:
			val = sbbs->logon_fbacks;
			break;
		case BBS_PROP_POSTS_READ:
			val = sbbs->posts_read;
			break;

		case BBS_PROP_MENU_DIR:
			p = sbbs->menu_dir;
		case BBS_PROP_MENU_FILE:
			p = sbbs->menu_file;
		case BBS_PROP_MAIN_CMDS:
			val = sbbs->main_cmds;
rswindell's avatar
rswindell committed
		case BBS_PROP_FILE_CMDS:
			val = sbbs->xfer_cmds;
			val = sbbs->curgrp;
			break;
		case BBS_PROP_CURSUB:
			if (sbbs->curgrp < sbbs->usrgrps)
				val = sbbs->cursub[sbbs->curgrp];
		case BBS_PROP_CURSUB_CODE:
			if (sbbs->subnum_is_valid(sbbs->cursubnum))
				p = sbbs->cfg.sub[sbbs->cursubnum]->code;
			val = sbbs->curlib;
			break;
		case BBS_PROP_CURDIR:
			if (sbbs->curlib < sbbs->usrlibs)
				val = sbbs->curdir[sbbs->curlib];
		case BBS_PROP_CURDIR_CODE:
			if (sbbs->dirnum_is_valid(sbbs->curdirnum))
				p = sbbs->cfg.dir[sbbs->curdirnum]->code;
		case BBS_PROP_CONNECTION:
			p = sbbs->connection;
		case BBS_PROP_RLOGIN_NAME:
			p = sbbs->rlogin_name;
		case BBS_PROP_RLOGIN_PASS:
			p = sbbs->rlogin_pass;
		case BBS_PROP_RLOGIN_TERM:
			p = sbbs->rlogin_term;
		case BBS_PROP_CLIENT_NAME:
			p = sbbs->client_name;
			val = sbbs->errorlevel;
		/* Currently Open Message Base (sbbs.smb) */
		case BBS_PROP_SMB_GROUP:
			if (!subnum_is_valid(&sbbs->cfg, sbbs->smb.subnum))
				p = nulstr;
				p = sbbs->cfg.grp[sbbs->cfg.sub[sbbs->smb.subnum]->grp]->sname;
			if (!subnum_is_valid(&sbbs->cfg, sbbs->smb.subnum))
				p = nulstr;
				p = sbbs->cfg.grp[sbbs->cfg.sub[sbbs->smb.subnum]->grp]->lname;
			if (sbbs->subnum_is_valid(sbbs->smb.subnum)) {
				for (ugrp = 0; ugrp < sbbs->usrgrps; ugrp++)
					if (sbbs->usrgrp[ugrp] == sbbs->cfg.sub[sbbs->smb.subnum]->grp)
			if (!subnum_is_valid(&sbbs->cfg, sbbs->smb.subnum))
				p = nulstr;
				p = sbbs->cfg.sub[sbbs->smb.subnum]->sname;
			if (!subnum_is_valid(&sbbs->cfg, sbbs->smb.subnum))
				p = nulstr;
				p = sbbs->cfg.sub[sbbs->smb.subnum]->lname;
			if (!subnum_is_valid(&sbbs->cfg, sbbs->smb.subnum))
				p = nulstr;
				p = sbbs->cfg.sub[sbbs->smb.subnum]->code;
			if (sbbs->usrsubs && sbbs->subnum_is_valid(sbbs->smb.subnum)) {
				for (ugrp = 0; ugrp < sbbs->usrgrps; ugrp++)
					if (sbbs->usrgrp[ugrp] == sbbs->cfg.sub[sbbs->smb.subnum]->grp)
				for (usub = 0; usub < sbbs->usrsubs[ugrp]; usub++)
					if (sbbs->usrsub[ugrp][usub] == sbbs->smb.subnum)
			val = sbbs->smb.status.attr;
			val = sbbs->smb.status.last_msg;
			val = sbbs->smb.status.total_msgs;
			val = sbbs->smb.msgs;
			break;
		case BBS_PROP_SMB_CURMSG:
			val = sbbs->smb.curmsg;

		/* Currently Displayed Message Header (sbbs.current_msg) */
		case BBS_PROP_MSG_TO:
			if (sbbs->current_msg_to == NULL)
				p = nulstr;
				p = sbbs->current_msg_to;
			if (sbbs->current_msg == NULL || sbbs->current_msg->to_ext == NULL)
				p = nulstr;
				p = sbbs->current_msg->to_ext;
			if (sbbs->current_msg == NULL || sbbs->current_msg->to_net.type == NET_NONE)
				p = nulstr;
				p = smb_netaddrstr(&sbbs->current_msg->to_net, tmp);
			if (sbbs->current_msg != NULL)
				val = sbbs->current_msg->to_agent;
			if (sbbs->current_msg_from == NULL)
				p = nulstr;
				p = sbbs->current_msg_from;
			if (sbbs->current_msg == NULL || sbbs->current_msg->from_ext == NULL)
				p = nulstr;
				p = sbbs->current_msg->from_ext;
			if (sbbs->current_msg == NULL || sbbs->current_msg->from_net.type == NET_NONE)
				p = nulstr;
				p = smb_netaddrstr(&sbbs->current_msg->from_net, tmp);
		case BBS_PROP_MSG_FROM_BBSID:
			if (sbbs->current_msg == NULL || sbbs->current_msg->ftn_bbsid == NULL)
				p = nulstr;
			else // Should we return only the last ID of the QWKnet route here?
				p = sbbs->current_msg->ftn_bbsid;
			break;
			if (sbbs->current_msg != NULL)
				val = sbbs->current_msg->from_agent;
			if (sbbs->current_msg == NULL || sbbs->current_msg->replyto == NULL)
				p = nulstr;
				p = sbbs->current_msg->replyto;
			if (sbbs->current_msg == NULL || sbbs->current_msg->replyto_ext == NULL)
				p = nulstr;
				p = sbbs->current_msg->replyto_ext;
			if (sbbs->current_msg == NULL || sbbs->current_msg->replyto_net.type == NET_NONE)
				p = nulstr;
				p = smb_netaddrstr(&sbbs->current_msg->replyto_net, tmp);
			if (sbbs->current_msg != NULL)
				val = sbbs->current_msg->replyto_agent;
			if (sbbs->current_msg_subj == NULL)
				p = nulstr;
				p = sbbs->current_msg_subj;
			if (sbbs->current_msg != NULL)
				val = (uint32)smb_time(sbbs->current_msg->hdr.when_written);
			if (sbbs->current_msg != NULL)
				val = sbbs->current_msg->hdr.when_written.zone;
			if (sbbs->current_msg != NULL)
				val = sbbs->current_msg->hdr.when_imported.time;
			if (sbbs->current_msg != NULL)
				val = sbbs->current_msg->hdr.attr;
			if (sbbs->current_msg != NULL)
				val = sbbs->current_msg->hdr.auxattr;
			if (sbbs->current_msg != NULL)
				val = sbbs->current_msg->hdr.netattr;
			if (sbbs->current_msg != NULL)
				val = sbbs->current_msg->idx_offset;
			if (sbbs->current_msg != NULL)
				val = sbbs->current_msg->hdr.number;
				val = sbbs->current_msg_number;
			if (sbbs->current_msg != NULL)
				val = sbbs->current_msg->expiration;
			if (sbbs->current_msg != NULL)
				val = sbbs->current_msg->forwarded;
			if (sbbs->current_msg != NULL)
				val = sbbs->current_msg->hdr.thread_id;
			if (sbbs->current_msg != NULL)
				val = sbbs->current_msg->hdr.thread_back;
			if (sbbs->current_msg != NULL)
				val = sbbs->current_msg->hdr.thread_next;
			if (sbbs->current_msg != NULL)
				val = sbbs->current_msg->hdr.thread_first;
			break;
		case BBS_PROP_MSG_DELIVERY_ATTEMPTS:
			if (sbbs->current_msg != NULL)
				val = sbbs->current_msg->hdr.delivery_attempts;
			if (sbbs->current_msg == NULL || sbbs->current_msg->id == NULL)
				p = nulstr;
				p = sbbs->current_msg->id;
			break;
		case BBS_PROP_MSG_REPLY_ID:
			if (sbbs->current_msg == NULL || sbbs->current_msg->reply_id == NULL)
				p = nulstr;
				p = sbbs->current_msg->reply_id;
		case BBS_PROP_MSGHDR_TOS:
			val = sbbs->msghdr_tos;
			break;
		/* Currently Displayed File (sbbs.current_file) */
		case BBS_PROP_FILE_NAME:
			if (sbbs->current_file == NULL)
				p = nulstr;
				p = sbbs->current_file->name;
			break;
		case BBS_PROP_FILE_DESC:
			if (sbbs->current_file == NULL)
				p = nulstr;
				p = sbbs->current_file->desc;
			break;
		case BBS_PROP_FILE_ULER:
			if (sbbs->current_file == NULL)
				p = nulstr;
				p = sbbs->current_file->from;
			break;
		case BBS_PROP_FILE_DATE:
			if (sbbs->current_file == NULL)
				p = nulstr;
				val = (uint32)sbbs->current_file->time;
			break;
		case BBS_PROP_FILE_DATE_ULED:
			if (sbbs->current_file == NULL)
				p = nulstr;
				val = sbbs->current_file->hdr.when_imported.time;
			break;
		case BBS_PROP_FILE_DATE_DLED:
			if (sbbs->current_file == NULL)
				p = nulstr;
				val = sbbs->current_file->hdr.last_downloaded;
			break;
		case BBS_PROP_FILE_TIMES_DLED:
			if (sbbs->current_file == NULL)
				p = nulstr;
				val = sbbs->current_file->hdr.times_downloaded;
			break;
		case BBS_PROP_FILE_SIZE:
			if (sbbs->current_file == NULL)
				p = nulstr;
			else // TODO: fix for 64-bit file sizes
				val = (uint32)sbbs->current_file->size;
			break;
		case BBS_PROP_FILE_CREDITS:
			if (sbbs->current_file == NULL)
				p = nulstr;
				val = (uint32_t)sbbs->current_file->cost; // TODO (cost is now 64-bit)
			break;
		case BBS_PROP_FILE_DIR:
			if (sbbs->current_file == NULL)
				p = nulstr;
				val = sbbs->current_file->dir;
			break;
		case BBS_PROP_FILE_ATTR:
			if (sbbs->current_file == NULL)
				p = nulstr;
				val = sbbs->current_file->hdr.attr;
		case BBS_PROP_DOWNLOAD_CPS:
			val = sbbs->cur_cps;
			break;
			break;
		case BBS_PROP_BATCH_DNLOAD_TOTAL:
			p = sbbs->main_csi.str;
		default:
	if (p != NULL) {
		JSString* js_str = JS_NewStringCopyZ(cx, p);
		if (js_str == NULL)
		*vp = STRING_TO_JSVAL(js_str);
	} else
		*vp = UINT_TO_JSVAL(val);
static JSBool js_bbs_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
	jsval     idval;
	char*     p = NULL;
	uint32    val = 0;
	jsint     tiny;
	JSString* js_str;
	sbbs_t*   sbbs;
	if ((sbbs = js_GetPrivate(cx, obj)) == NULL)
	JS_IdToValue(cx, id, &idval);
	tiny = JSVAL_TO_INT(idval);
	if (JSVAL_IS_NUMBER(*vp) || JSVAL_IS_BOOLEAN(*vp)) {
		if (!JS_ValueToECMAUint32(cx, *vp, &val))
	else if (JSVAL_IS_STRING(*vp)) {
		if ((js_str = JS_ValueToString(cx, *vp)) == NULL)
deuce's avatar
deuce committed
		JSSTRING_TO_MSTRING(cx, js_str, p, NULL);
rswindell's avatar
rswindell committed
	}
		case BBS_PROP_SYS_STATUS:
			sbbs->sys_status = val;
			break;
		case BBS_PROP_STARTUP_OPT:
			sbbs->startup->options = val;
			break;
		case BBS_PROP_ANSWER_TIME:
			sbbs->answertime = val;
			break;
		case BBS_PROP_LOGON_TIME:
			sbbs->logontime = val;
			sbbs->starttime = val;
		case BBS_PROP_NS_TIME:
			sbbs->ns_time = val;
			break;
		case BBS_PROP_LAST_NS_TIME:
			sbbs->last_ns_time = val;
		case BBS_PROP_ONLINE:
			sbbs->online = val;
rswindell's avatar
rswindell committed
		case BBS_PROP_NODE_SETTINGS:
			sbbs->cfg.node_misc = val;
rswindell's avatar
rswindell committed
		case BBS_PROP_NODE_ACTION:
			sbbs->action = (uchar)val;
rswindell's avatar
rswindell committed
			break;
		case BBS_PROP_NODE_VAL_USER:
			sbbs->cfg.valuser = (ushort)val;
			break;
		case BBS_PROP_LOGON_ULB:
			sbbs->logon_ulb = val;
			break;
		case BBS_PROP_LOGON_DLB:
			sbbs->logon_dlb = val;
			break;
		case BBS_PROP_LOGON_ULS:
			sbbs->logon_uls = val;
			break;
		case BBS_PROP_LOGON_DLS:
			sbbs->logon_dls = val;
			break;
		case BBS_PROP_LOGON_POSTS:
			sbbs->logon_posts = val;
			break;
		case BBS_PROP_LOGON_EMAILS:
			sbbs->logon_emails = val;
		case BBS_PROP_LOGON_FBACKS:
			sbbs->logon_fbacks = val;
		case BBS_PROP_POSTS_READ:
			sbbs->posts_read = val;
		case BBS_PROP_MENU_DIR:
			if (p != NULL)
				SAFECOPY(sbbs->menu_dir, p);
		case BBS_PROP_MENU_FILE:
			if (p != NULL)
				SAFECOPY(sbbs->menu_file, p);
		case BBS_PROP_MAIN_CMDS:
			sbbs->main_cmds = val;
rswindell's avatar
rswindell committed
		case BBS_PROP_FILE_CMDS:
			sbbs->xfer_cmds = val;
		case BBS_PROP_SMB_CURMSG:
			sbbs->smb.curmsg = val;
			break;
		case BBS_PROP_MSG_NUMBER:
			sbbs->current_msg_number = val;
			break;
			if (p != NULL) {   /* set by name */
				for (i = 0; i < sbbs->usrgrps; i++)
					if (!stricmp(sbbs->cfg.grp[sbbs->usrgrp[i]]->sname, p))
				if (i < sbbs->usrgrps)
					sbbs->curgrp = i;
			if ((int)val < sbbs->cfg.total_grps && (int)val < sbbs->usrgrps)
				sbbs->curgrp = val;
			break;
		case BBS_PROP_CURSUB:
		case BBS_PROP_CURSUB_CODE:
			if (p != NULL) {   /* set by code */
				for (int i = 0; i < sbbs->usrgrps; i++)
					for (int j = 0; j < sbbs->usrsubs[i]; j++)
						if (!stricmp(sbbs->cfg.sub[sbbs->usrsub[i][j]]->code, p)) {
							sbbs->curgrp = i;
							sbbs->cursub[i] = j;
			if (sbbs->curgrp < sbbs->cfg.total_grps && (int)val < sbbs->usrsubs[sbbs->curgrp])
				sbbs->cursub[sbbs->curgrp] = val;
			break;
		case BBS_PROP_CURLIB:
			if (p != NULL) {   /* set by name */
				for (i = 0; i < sbbs->usrlibs; i++)
					if (!stricmp(sbbs->cfg.lib[sbbs->usrlib[i]]->sname, p))
				if (i < sbbs->usrlibs)
					sbbs->curlib = i;
			if ((int)val < sbbs->cfg.total_libs && (int)val < sbbs->usrlibs)
				sbbs->curlib = val;
			break;
		case BBS_PROP_CURDIR:
		case BBS_PROP_CURDIR_CODE:
			if (p != NULL) {   /* set by code */
				for (int i = 0; i < sbbs->usrlibs; i++)
					for (int j = 0; j < sbbs->usrdirs[i]; j++)
						if (!stricmp(sbbs->cfg.dir[sbbs->usrdir[i][j]]->code, p)) {
							sbbs->curlib = i;
							sbbs->curdir[i] = j;
			if (sbbs->curlib < sbbs->cfg.total_libs && (int)val < sbbs->usrdirs[sbbs->curlib])
				sbbs->curdir[sbbs->curlib] = val;
		case BBS_PROP_RLOGIN_NAME:
			if (p != NULL)
				SAFECOPY(sbbs->rlogin_name, p);
		case BBS_PROP_RLOGIN_PASS:
			if (p != NULL)
				SAFECOPY(sbbs->rlogin_pass, p);
		case BBS_PROP_RLOGIN_TERM:
			if (p != NULL)
				SAFECOPY(sbbs->rlogin_term, p);
		case BBS_PROP_CLIENT_NAME:
			if (p != NULL)
				SAFECOPY(sbbs->client_name, p);
				strlcpy(sbbs->main_csi.str, p, 1024);
		default:
deuce's avatar
deuce committed
				free(p);
deuce's avatar
deuce committed
		free(p);

	if (sbbs->usrgrps)
		sbbs->cursubnum = sbbs->usrsub[sbbs->curgrp][sbbs->cursub[sbbs->curgrp]];   /* Used for ARS */
		sbbs->cursubnum = INVALID_SUB;
	if (sbbs->usrlibs)
		sbbs->curdirnum = sbbs->usrdir[sbbs->curlib][sbbs->curdir[sbbs->curlib]];   /* Used for ARS */
		sbbs->curdirnum = INVALID_DIR;