Skip to content
Snippets Groups Projects
js_system.c 48.3 KiB
Newer Older
		else if(reason==NULL)
			reason=p;
		else if(host==NULL)
			host=p;
		else if(ip_addr==NULL)
			ip_addr=p;
		else if(to==NULL)
			to=p;
	*rval = BOOLEAN_TO_JSVAL(spamlog(cfg,prot,action,reason,host,ip_addr,to,from));
	return(JS_TRUE);
}

static JSBool
js_hacklog(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	uintN		i;
	char*		p;
	char*		prot=NULL;
	char*		user=NULL;
	char*		text=NULL;
	char*		host=NULL;
	SOCKADDR_IN	addr;
	scfg_t*		cfg;

	if((cfg=(scfg_t*)JS_GetPrivate(cx,obj))==NULL)
		return(JS_FALSE);

	memset(&addr,0,sizeof(addr));
	for(i=0;i<argc;i++) {
		if(JSVAL_IS_NUMBER(argv[i])) {
			JS_ValueToInt32(cx,argv[i],&i32);
			if(addr.sin_addr.s_addr==0)
			continue;
		}
		if(!JSVAL_IS_STRING(argv[i]))
			continue;
		p=JS_GetStringBytes(JS_ValueToString(cx, argv[i]));
		if(p==NULL)
			continue;
		if(prot==NULL)
			prot=p;
		else if(user==NULL)
			user=p;
		else if(text==NULL)
			text=p;
		else if(host==NULL)
			host=p;
	}
	*rval = BOOLEAN_TO_JSVAL(hacklog(cfg,prot,user,text,host,&addr));
	return(JS_TRUE);
}

static JSBool
js_filter_ip(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	uintN		i;
	char*		p;
	char*		prot=NULL;
	char*		reason=NULL;
	char*		host=NULL;
	char*		ip_addr=NULL;
	char*		from=NULL;
	scfg_t*		cfg;

	if((cfg=(scfg_t*)JS_GetPrivate(cx,obj))==NULL)
		return(JS_FALSE);

	for(i=0;i<argc;i++) {
		if(!JSVAL_IS_STRING(argv[i]))
			continue;
		p=JS_GetStringBytes(JS_ValueToString(cx, argv[i]));
		if(p==NULL)
			continue;
		if(prot==NULL)
			prot=p;
		else if(reason==NULL)
			reason=p;
		else if(host==NULL)
			host=p;
		else if(ip_addr==NULL)
			ip_addr=p;
		else if(from==NULL)
			from=p;
	*rval = BOOLEAN_TO_JSVAL(filter_ip(cfg,prot,reason,host,ip_addr,from,fname));
	return(JS_TRUE);
}

static JSBool
js_get_node_message(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char*		buf;
	int32		node_num;
	JSString*	js_str;
	scfg_t*		cfg;

	*rval = JSVAL_NULL;

	if((cfg=(scfg_t*)JS_GetPrivate(cx,obj))==NULL)
		return(JS_FALSE);

	node_num=cfg->node_num;
	if(argc) 
		JS_ValueToInt32(cx,argv[0],&node_num);
	if(node_num<1)
		node_num=1;

	if((buf=getnmsg(cfg,node_num))==NULL)
		return(JS_TRUE);

	js_str=JS_NewStringCopyZ(cx, buf);
	free(buf);

	if(js_str==NULL)
		return(JS_FALSE);
	*rval = STRING_TO_JSVAL(js_str);
	return(JS_TRUE);
}


static JSBool
js_put_node_message(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	JSString*	js_msg;
	char*		msg;
	scfg_t*		cfg;

	if((cfg=(scfg_t*)JS_GetPrivate(cx,obj))==NULL)
		return(JS_FALSE);

	JS_ValueToInt32(cx,argv[0],&node);
	if(node<1)
		node=1;

	if((js_msg=JS_ValueToString(cx, argv[1]))==NULL) 
		return(JS_FALSE);

	if((msg=JS_GetStringBytes(js_msg))==NULL) 
		return(JS_FALSE);

	*rval = BOOLEAN_TO_JSVAL(putnmsg(cfg,node,msg)==0);
static JSBool
js_get_telegram(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char*		buf;
	int32		usernumber=1;
	JSString*	js_str;
	scfg_t*		cfg;

	*rval = JSVAL_NULL;

	if((cfg=(scfg_t*)JS_GetPrivate(cx,obj))==NULL)
		return(JS_FALSE);

	JS_ValueToInt32(cx,argv[0],&usernumber);
	if(usernumber<1)
		usernumber=1;

	if((buf=getsmsg(cfg,usernumber))==NULL)
		return(JS_TRUE);

	js_str=JS_NewStringCopyZ(cx, buf);
	free(buf);

	if(js_str==NULL)
		return(JS_FALSE);
	*rval = STRING_TO_JSVAL(js_str);
	return(JS_TRUE);
}

static JSBool
js_put_telegram(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	JSString*	js_msg;
	char*		msg;
	scfg_t*		cfg;

	if((cfg=(scfg_t*)JS_GetPrivate(cx,obj))==NULL)
		return(JS_FALSE);

	JS_ValueToInt32(cx,argv[0],&usernumber);
	if(usernumber<1)
		usernumber=1;

	if((js_msg=JS_ValueToString(cx, argv[1]))==NULL) 
		return(JS_FALSE);

	if((msg=JS_GetStringBytes(js_msg))==NULL) 
		return(JS_FALSE);

	*rval = BOOLEAN_TO_JSVAL(putsmsg(cfg,usernumber,msg)==0);
static JSBool
js_new_user(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char*		alias;
	int			i;
	scfg_t*		cfg;
	user_t		user;
	JSObject*	userobj;

	if((cfg=(scfg_t*)JS_GetPrivate(cx,obj))==NULL)
		return(JS_FALSE);

	alias=JS_GetStringBytes(JS_ValueToString(cx,argv[0]));

	memset(&user,0,sizeof(user));

	SAFECOPY(user.alias,alias);

	/* statistics */
	user.firston=user.laston=user.pwmod=time(NULL);

	/* security */
	user.level=cfg->new_level;
	user.flags1=cfg->new_flags1;
	user.flags2=cfg->new_flags2;
	user.flags3=cfg->new_flags3;
	user.flags4=cfg->new_flags4;
	user.rest=cfg->new_rest;
	user.exempt=cfg->new_exempt;

	user.cdt=cfg->new_cdt;
	user.min=cfg->new_min;
	user.freecdt=cfg->level_freecdtperday[user.level];
	if(cfg->new_expire)
		user.expire=user.firston+((long)cfg->new_expire*24L*60L*60L);
	else
		user.expire=0;

	/* settings */
	if(cfg->total_fcomps)
		strcpy(user.tmpext,cfg->fcomp[0]->ext);
	else
		strcpy(user.tmpext,"ZIP");

	user.shell=cfg->new_shell;
	user.misc=cfg->new_misc|(AUTOTERM|COLOR);
	user.prot=cfg->new_prot;
	for(i=0;i<cfg->total_xedits;i++)
		if(!stricmp(cfg->xedit[i]->code,cfg->new_xedit) && chk_ar(cfg,cfg->xedit[i]->ar,&user))
			break;
	if(i<cfg->total_xedits)
		user.xedit=i+1;

		userobj=js_CreateUserObject(cx, obj, cfg, NULL, user.number);
		*rval = OBJECT_TO_JSVAL(userobj);
	} else
		*rval = INT_TO_JSVAL(i);

	return(JS_TRUE);
}

static JSBool
js_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	*rval = INT_TO_JSVAL(system(JS_GetStringBytes(JS_ValueToString(cx, argv[0]))));
	
	return(JS_TRUE);
}

static JSBool
js_popen(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char		str[1024];
	char*		cmd;
	FILE*		fp;
	jsint		line=0;
	jsval		val;
	JSObject*	array;
	JSString*	js_str;

	if(argc<1)
		return(JS_TRUE);

	if((array=JS_NewArrayObject(cx,0,NULL))==NULL)
		return(JS_FALSE);

	cmd=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
	if((fp=popen(cmd,"r"))==NULL)
		return(JS_TRUE);
	while(!feof(fp)) {
		if(fgets(str,sizeof(str),fp)==NULL)
			break;
		if((js_str=JS_NewStringCopyZ(cx,str))==NULL)
			break;
		val=STRING_TO_JSVAL(js_str);
        if(!JS_SetElement(cx, array, line++, &val))
			break;
	}
	pclose(fp);

    *rval = OBJECT_TO_JSVAL(array);

    return(JS_TRUE);
}

static JSBool
js_chksyspass(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	scfg_t*		cfg;

	if((cfg=(scfg_t*)JS_GetPrivate(cx,obj))==NULL)
		return(JS_FALSE);

	*rval = BOOLEAN_TO_JSVAL(stricmp(JS_GetStringBytes(JS_ValueToString(cx, argv[0]))
								,cfg->sys_pass)==0);
	
	return(JS_TRUE);
}

static JSBool 
js_chkname(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char*	str;
	scfg_t*	cfg;

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

	if((cfg=(scfg_t*)JS_GetPrivate(cx,obj))==NULL)
		return(JS_FALSE);
	*rval = BOOLEAN_TO_JSVAL(check_name(cfg,str));

	return(JS_TRUE);
}
static jsSyncMethodSpec js_system_functions[] = {
	{"username",		js_username,		1,	JSTYPE_STRING,	JSDOCSTR("number")
	,JSDOCSTR("returns name of user in specified user record <i>number</i>, or empty string if not found")
rswindell's avatar
rswindell committed
	{"alias",			js_alias,			1,	JSTYPE_STRING,	JSDOCSTR("alias")
	,JSDOCSTR("returns name of user that matches alias (if found in <tt>ctrl/alias.cfg</tt>)")
rswindell's avatar
rswindell committed
	{"matchuser",		js_matchuser,		1,	JSTYPE_NUMBER,	JSDOCSTR("username [,sysop_alias=<tt>true</tt>]")
	,JSDOCSTR("exact user name matching, returns number of user whose name/alias matches <i>username</i> "
		" or 0 if not found, matches well-known sysop aliases by default")
	{"matchuserdata",	js_matchuserdata,	2,	JSTYPE_NUMBER,	JSDOCSTR("field, data [,usernumber]")
	,JSDOCSTR("search user database for data in a specific field (specified by offset), "
		"returns first matching user record number, optional <i>usernumber</i> specifies user record to skip")
rswindell's avatar
rswindell committed
	{"trashcan",		js_trashcan,		2,	JSTYPE_BOOLEAN,	JSDOCSTR("path/filename, find_string")
	,JSDOCSTR("search text/filename.can for pseudo-regexp")
rswindell's avatar
rswindell committed
	{"findstr",			js_findstr,			2,	JSTYPE_BOOLEAN,	JSDOCSTR("path/filename, find_string")
	,JSDOCSTR("search any file for pseudo-regexp")
rswindell's avatar
rswindell committed
	{"zonestr",			js_zonestr,			0,	JSTYPE_STRING,	JSDOCSTR("[timezone=<i>local</i>]")
	,JSDOCSTR("convert time zone integer to string, defaults to system timezone if <i>timezone</i> not specified")
rswindell's avatar
rswindell committed
	{"timestr",			js_timestr,			0,	JSTYPE_STRING,	JSDOCSTR("[time=<i>current</i>]")
	,JSDOCSTR("convert time_t integer into a time string, "
		"defaults to current time if <i>time</i> not specified")
rswindell's avatar
rswindell committed
	{"datestr",			js_datestr,			0,	JSTYPE_STRING,	JSDOCSTR("[time=<i>current</i>]")
	,JSDOCSTR("convert time_t integer into a date string (in either <tt>MM/DD/YY</tt> or <tt>DD/MM/YY</tt> format), "
		"defaults to current date if <i>time</i> not specified. "
		"If <i>time</i> is a string in the appropriate format, returns the time_t.")
	{"secondstr",		js_secondstr,		0,	JSTYPE_STRING,	JSDOCSTR("seconds")
	,JSDOCSTR("convert elapsed time in seconds into a string in <tt>hh:mm:ss</tt> format")
	{"spamlog",			js_spamlog,			6,	JSTYPE_BOOLEAN,	JSDOCSTR("[protocol, action, reason, host, ip, to, from]")
	,JSDOCSTR("log a suspected SPAM attempt")
	{"hacklog",			js_hacklog,			5,	JSTYPE_BOOLEAN,	JSDOCSTR("[protocol, user, text, host, ip, port]")
	,JSDOCSTR("log a suspected hack attempt")
	{"filter_ip",		js_filter_ip,		4,	JSTYPE_BOOLEAN,	JSDOCSTR("[protocol, reason, host, ip, username]")
	,JSDOCSTR("add an IP address (with comment) to the system's IP filter file")
rswindell's avatar
rswindell committed
	{"get_node_message",js_get_node_message,0,	JSTYPE_STRING,	JSDOCSTR("node_number")
	,JSDOCSTR("read any messages waiting for the specified node and return in a single string")
rswindell's avatar
rswindell committed
	{"put_node_message",js_put_node_message,2,	JSTYPE_BOOLEAN,	JSDOCSTR("node_number, message_text")
	,JSDOCSTR("send a node a short text message, delivered immediately")
rswindell's avatar
rswindell committed
	{"get_telegram",	js_get_telegram,	1,	JSTYPE_STRING,	JSDOCSTR("user_number")
	,JSDOCSTR("returns any short text messages waiting for the specified user")
rswindell's avatar
rswindell committed
	{"put_telegram",	js_put_telegram,	2,	JSTYPE_BOOLEAN,	JSDOCSTR("user_number, message_text")
	,JSDOCSTR("sends a user a short text message, delivered immediately or during next logon")
	{"newuser",			js_new_user,		1,	JSTYPE_ALIAS },
	{"new_user",		js_new_user,		1,	JSTYPE_OBJECT,	JSDOCSTR("name/alias")
	,JSDOCSTR("creates a new user record, returns a new <a href=#User>User</a> object representing the new user account, on success.<br>"
	"returns an numeric error code on failure")
	{"exec",			js_exec,			1,	JSTYPE_NUMBER,	JSDOCSTR("command-line")
	,JSDOCSTR("executes a native system/shell command-line, returns <i>0</i> on success")
	},
	{"popen",			js_popen,			0,	JSTYPE_ARRAY,	JSDOCSTR("command-line")
	,JSDOCSTR("executes a native system/shell command-line, returns array of captured output lines on success "
		"(<b>only functional on UNIX systems</b>)")
rswindell's avatar
rswindell committed
	{"check_syspass",	js_chksyspass,		1,	JSTYPE_BOOLEAN,	JSDOCSTR("password")
	,JSDOCSTR("compares the supplied <i>password</i> against the system password and return's <i>true</i> if it matches")
	{"check_name",		js_chkname,			1,	JSTYPE_BOOLEAN,	JSDOCSTR("name/alias")
	,JSDOCSTR("checks that the provided name/alias string is suitable for a new user account, "
		"returns <i>true</i> if it is valid")
/* node properties */
enum {
	/* raw node_t fields */
	 NODE_PROP_STATUS
	,NODE_PROP_ERRORS
	,NODE_PROP_ACTION
	,NODE_PROP_USERON
	,NODE_PROP_CONNECTION
	,NODE_PROP_MISC
	,NODE_PROP_AUX
	,NODE_PROP_EXTAUX
};

static char* node_prop_desc[] = {
	 "status (see <tt>nodedefs.js</tt> for valid values)"
	,"error counter"
	,"current user action (see <tt>nodedefs.js</tt>)"
	,"current user number"
	,"connection speed (<tt>0xffff</tt> = Telnet or RLogin)"
	,"miscellaneous bitfield (see <tt>nodedefs.js</tt>)"
	,"auxillary value"
	,"extended auxillary value"
static JSBool js_node_get(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
	uint		node_num;
    jsint       tiny;
	node_t		node;
	scfg_t*		cfg;
	JSObject*	sysobj;
	JSObject*	node_list;

	tiny = JSVAL_TO_INT(id);

	if((node_list=JS_GetParent(cx, obj))==NULL)
		return(JS_FALSE);

	if((sysobj=JS_GetParent(cx, node_list))==NULL)
		return(JS_FALSE);

	if((cfg=(scfg_t*)JS_GetPrivate(cx,sysobj))==NULL)
		return(JS_FALSE);

	node_num=(uint)JS_GetPrivate(cx,obj)>>1;

	memset(&node,0,sizeof(node));
	if(getnodedat(cfg, node_num, &node, NULL))
		return(JS_TRUE);
	
    switch(tiny) {
		case NODE_PROP_STATUS:
			*vp = INT_TO_JSVAL((int)node.status);
			break;
		case NODE_PROP_ERRORS:	
			*vp = INT_TO_JSVAL((int)node.errors);
			break;
		case NODE_PROP_ACTION:	
			*vp = INT_TO_JSVAL((int)node.action);
			break;
		case NODE_PROP_USERON:	
			*vp = INT_TO_JSVAL((int)node.useron);
			break;
		case NODE_PROP_CONNECTION:
			*vp = INT_TO_JSVAL((int)node.connection);
			break;
		case NODE_PROP_MISC:		
			*vp = INT_TO_JSVAL((int)node.misc);
			break;
		case NODE_PROP_AUX:		
			*vp = INT_TO_JSVAL((int)node.aux);
			break;
		case NODE_PROP_EXTAUX:	
			JS_NewNumberValue(cx,node.extaux,vp);
			break;
	}
	return(JS_TRUE);
}

static JSBool js_node_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
	uint		node_num;
	jsint		val=0;
    jsint       tiny;
	node_t		node;
	scfg_t*		cfg;
	JSObject*	sysobj;
	JSObject*	node_list;

	if((node_list=JS_GetParent(cx, obj))==NULL)
		return(JS_FALSE);

	if((sysobj=JS_GetParent(cx, node_list))==NULL)
		return(JS_FALSE);

	if((cfg=(scfg_t*)JS_GetPrivate(cx,sysobj))==NULL)
		return(JS_FALSE);

	node_num=(uint)JS_GetPrivate(cx,obj)>>1;

	memset(&node,0,sizeof(node));
	if(getnodedat(cfg, node_num, &node, &file)) 
		JS_ValueToInt32(cx, *vp, &val);

	tiny = JSVAL_TO_INT(id);
	
    switch(tiny) {
		case NODE_PROP_STATUS:
			break;
		case NODE_PROP_ERRORS:	
			break;
		case NODE_PROP_ACTION:	
			break;
		case NODE_PROP_USERON:	
			break;
		case NODE_PROP_CONNECTION:
			break;
		case NODE_PROP_MISC:		
			break;
		case NODE_PROP_AUX:		
			break;
		case NODE_PROP_EXTAUX:	
			node.extaux=val;
			break;
	}
static jsSyncPropertySpec js_node_properties[] = {
/*		 name,						tinyid,					flags,				ver	*/

/* raw node_t fields */
	{	"status",					NODE_PROP_STATUS,		JSPROP_ENUMERATE,	310 },
	{	"errors",					NODE_PROP_ERRORS,		JSPROP_ENUMERATE,	310 },
	{	"action",					NODE_PROP_ACTION,		JSPROP_ENUMERATE,	310 },
	{	"useron",					NODE_PROP_USERON,		JSPROP_ENUMERATE,	310 },
	{	"connection",				NODE_PROP_CONNECTION,	JSPROP_ENUMERATE,	310 },
	{	"misc",						NODE_PROP_MISC,			JSPROP_ENUMERATE,	310 },
	{	"aux",						NODE_PROP_AUX,			JSPROP_ENUMERATE,	310 },
	{	"extaux",					NODE_PROP_EXTAUX,		JSPROP_ENUMERATE,	310 },
deuce's avatar
deuce committed
static JSBool js_node_resolve(JSContext *cx, JSObject *obj, jsval id)
{
	char*			name=NULL;

	if(id != JSVAL_NULL)
		name=JS_GetStringBytes(JSVAL_TO_STRING(id));

	return(js_SyncResolve(cx, obj, name, js_node_properties, NULL, NULL, 0));
}

static JSBool js_node_enumerate(JSContext *cx, JSObject *obj)
{
	return(js_node_resolve(cx, obj, JSVAL_NULL));
}

static JSClass js_node_class = {
     "Node"					/* name			*/
    ,JSCLASS_HAS_PRIVATE	/* flags		*/
	,JS_PropertyStub		/* addProperty	*/
	,JS_PropertyStub		/* delProperty	*/
	,js_node_get			/* getProperty	*/
	,js_node_set			/* setProperty	*/
deuce's avatar
deuce committed
	,js_node_enumerate		/* enumerate	*/
	,js_node_resolve		/* resolve		*/
	,JS_ConvertStub			/* convert		*/
	,JS_FinalizeStub		/* finalize		*/
};

deuce's avatar
deuce committed
#define LAZY_INTEGER(PropName, PropValue) \
	if(name==NULL || strcmp(name, (PropName))==0) { \
		JS_NewNumberValue(cx,(PropValue),&val); \
		JS_DefineProperty(cx, obj, (PropName), val, NULL,NULL,JSPROP_ENUMERATE); \
		if(name) return(JS_TRUE); \
	}
deuce's avatar
deuce committed
#define LAZY_STRING(PropName, PropValue) \
	if(name==NULL || strcmp(name, (PropName))==0) { \
		if((js_str=JS_NewStringCopyZ(cx, (PropValue)))!=NULL) { \
			JS_DefineProperty(cx, obj, PropName, STRING_TO_JSVAL(js_str), NULL, NULL, JSPROP_ENUMERATE); \
			if(name) return(JS_TRUE); \
		} \
		else if(name) return(JS_TRUE); \
	}
deuce's avatar
deuce committed
#define LAZY_STRFUNC(PropName, Function, PropValue) \
	if(name==NULL || strcmp(name, (PropName))==0) { \
		Function; \
		if((js_str=JS_NewStringCopyZ(cx, (PropValue)))!=NULL) { \
			JS_DefineProperty(cx, obj, PropName, STRING_TO_JSVAL(js_str), NULL, NULL, JSPROP_ENUMERATE); \
			if(name) return(JS_TRUE); \
		} \
		else if(name) return(JS_TRUE); \
	}
deuce's avatar
deuce committed
#define LAZY_STRFUNC_TRUNCSP(PropName, Function, PropValue) \
	if(name==NULL || strcmp(name, (PropName))==0) { \
		Function; \
		if((js_str=JS_NewStringCopyZ(cx, truncsp(PropValue)))!=NULL) { \
			JS_DefineProperty(cx, obj, PropName, STRING_TO_JSVAL(js_str), NULL, NULL, JSPROP_ENUMERATE); \
			if(name) return(JS_TRUE); \
		} \
		else if(name) return(JS_TRUE); \
	}
deuce's avatar
deuce committed
static JSBool js_system_resolve(JSContext *cx, JSObject *obj, jsval id)
{
	char*		name=NULL;
	jsval		val;
	char		str[256];
	JSString*	js_str;
	JSObject*	newobj;
	JSObject*	nodeobj;
	scfg_t* 	cfg;
	uint		i;
deuce's avatar
deuce committed
	if(id != JSVAL_NULL)
		name=JS_GetStringBytes(JSVAL_TO_STRING(id));
	/****************************/
	/* static string properties */
deuce's avatar
deuce committed
	LAZY_STRING("version", VERSION);
	LAZY_STRFUNC("revision", sprintf(str,"%c",REVISION), str);
	LAZY_STRFUNC_TRUNCSP("beta_version", SAFECOPY(str, beta_version), str);
deuce's avatar
deuce committed
	if(name==NULL || strcmp(name, "full_version")==0) {
		sprintf(str,"%s%c%s",VERSION,REVISION,beta_version);
		truncsp(str);
#if defined(_DEBUG)
deuce's avatar
deuce committed
		strcat(str," Debug");
deuce's avatar
deuce committed
		if((js_str=JS_NewStringCopyZ(cx, str))!=NULL) {
			val = STRING_TO_JSVAL(js_str);
			JS_SetProperty(cx, obj, "full_version", &val);
			if(name) return(JS_TRUE);
		}
		else if(name) return(JS_TRUE);
	}
deuce's avatar
deuce committed
	LAZY_STRING("version_notice", VERSION_NOTICE);
deuce's avatar
deuce committed
	LAZY_INTEGER("version_num", VERSION_NUM);
	LAZY_INTEGER("version_hex", VERSION_HEX);
deuce's avatar
deuce committed
	LAZY_STRING("platform", PLATFORM_DESC);
	LAZY_STRFUNC("msgbase_lib", sprintf(str,"SMBLIB %s",smb_lib_ver()), str);
	LAZY_STRFUNC("compiled_with", DESCRIBE_COMPILER(str), str);
	LAZY_STRFUNC("compiled_when", sprintf(str,"%s %.5s",__DATE__,__TIME__), str);
	LAZY_STRING("copyright", COPYRIGHT_NOTICE);
	LAZY_STRING("js_version", (char *)JS_GetImplementationVersion());
	LAZY_STRING("os_version", os_version(str));
deuce's avatar
deuce committed
	/* fido_addr_list property */
	if(name==NULL || strcmp(name, "fido_addr_list")==0) {
		if((cfg=(scfg_t*)JS_GetPrivate(cx,obj))==NULL)
			return(JS_FALSE);
deuce's avatar
deuce committed
		if((newobj=JS_NewArrayObject(cx, 0, NULL))==NULL)
			return(JS_FALSE);
		if(!JS_SetParent(cx, newobj, obj))
			return(JS_FALSE);

deuce's avatar
deuce committed
		if(!JS_DefineProperty(cx, obj, "fido_addr_list", OBJECT_TO_JSVAL(newobj)
			, NULL, NULL, JSPROP_ENUMERATE))
			return(JS_FALSE);
deuce's avatar
deuce committed
		for(i=0;i<cfg->total_faddrs;i++) {
			val=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,smb_faddrtoa(&cfg->faddr[i],str)));
			JS_SetElement(cx, newobj, i, &val);
		}
		if(name) return(JS_TRUE);
	}
deuce's avatar
deuce committed
	if(name==NULL || strcmp(name, "stats")==0) {
		if((cfg=(scfg_t*)JS_GetPrivate(cx,obj))==NULL)
			return(JS_FALSE);
deuce's avatar
deuce committed
		newobj = JS_DefineObject(cx, obj, "stats", &js_sysstats_class, NULL
			,JSPROP_ENUMERATE|JSPROP_READONLY);
deuce's avatar
deuce committed
		if(newobj==NULL)
			return(JS_FALSE);
deuce's avatar
deuce committed
		JS_SetPrivate(cx, newobj, cfg);	/* Store a pointer to scfg_t */
	}
deuce's avatar
deuce committed
	/* node_list property */
	if(name==NULL || strcmp(name, "node_list")==0) {
		if((cfg=(scfg_t*)JS_GetPrivate(cx,obj))==NULL)
			return(JS_FALSE);
deuce's avatar
deuce committed
		if((newobj=JS_NewArrayObject(cx, 0, NULL))==NULL) 
			return(JS_FALSE);
		if(!JS_SetParent(cx, newobj, obj))
			return(JS_FALSE);

deuce's avatar
deuce committed
		if(!JS_DefineProperty(cx, obj, "node_list", OBJECT_TO_JSVAL(newobj)
			, NULL, NULL, JSPROP_ENUMERATE))
			return(JS_FALSE);
deuce's avatar
deuce committed
		for(i=0;i<cfg->sys_nodes && i<cfg->sys_lastnode;i++) {
deuce's avatar
deuce committed
			nodeobj = JS_NewObject(cx, &js_node_class, NULL, newobj);

			if(nodeobj==NULL)
				return(JS_FALSE);

			/* Store node number */
			/* We have to shift it to make it look like a pointer to JS. :-( */
			if(!JS_SetPrivate(cx, nodeobj, (char*)((i+1)<<1)))
				return(JS_FALSE);
deuce's avatar
deuce committed
	#ifdef BUILD_JSDOCS
			if(i==0) {
				js_DescribeSyncObject(cx,nodeobj,"BBS node listing",310);
				js_CreateArrayOfStrings(cx, nodeobj, "_property_desc_list", node_prop_desc, JSPROP_READONLY);
			}
	#endif

			val=OBJECT_TO_JSVAL(nodeobj);
			if(!JS_SetElement(cx, newobj, i, &val))
				return(JS_FALSE);
		}
		if(name) return(JS_TRUE);
deuce's avatar
deuce committed
	return(js_SyncResolve(cx, obj, name, js_system_properties, js_system_functions, NULL, 0));
}
deuce's avatar
deuce committed
static JSBool js_system_enumerate(JSContext *cx, JSObject *obj)
{
	return(js_node_resolve(cx, obj, JSVAL_NULL));
}
deuce's avatar
deuce committed
static JSClass js_system_class = {
     "System"				/* name			*/
    ,JSCLASS_HAS_PRIVATE	/* flags		*/
	,JS_PropertyStub		/* addProperty	*/
	,JS_PropertyStub		/* delProperty	*/
	,js_system_get			/* getProperty	*/
	,js_system_set			/* setProperty	*/
	,js_system_enumerate	/* enumerate	*/
	,js_system_resolve		/* resolve		*/
	,JS_ConvertStub			/* convert		*/
	,JS_FinalizeStub		/* finalize		*/
};
deuce's avatar
deuce committed
JSObject* DLLCALL js_CreateSystemObject(JSContext* cx, JSObject* parent
										,scfg_t* cfg, time_t uptime, char* host_name, char* socklib_desc)
{
	jsval		val;
	JSObject*	sysobj;
	JSObject*	statsobj;
	JSString*	js_str;
	char		str[256];
deuce's avatar
deuce committed
	sysobj = JS_DefineObject(cx, parent, "system", &js_system_class, NULL
		,JSPROP_ENUMERATE|JSPROP_READONLY);
deuce's avatar
deuce committed
	if(sysobj==NULL)
deuce's avatar
deuce committed
	if(!JS_SetPrivate(cx, sysobj, cfg))	/* Store a pointer to scfg_t */
deuce's avatar
deuce committed
	/****************************/
	/* static string properties */
	if((js_str=JS_NewStringCopyZ(cx, host_name))==NULL)
		return(NULL);
	val = STRING_TO_JSVAL(js_str);
	if(!JS_SetProperty(cx, sysobj, "host_name", &val))
		return(NULL);
deuce's avatar
deuce committed
	if((js_str=JS_NewStringCopyZ(cx, socklib_version(str, socklib_desc)))==NULL)
		return(NULL);
	val = STRING_TO_JSVAL(js_str);
	if(!JS_SetProperty(cx, sysobj, "socket_lib", &val))
		return(NULL);
deuce's avatar
deuce committed
	/***********************/
deuce's avatar
deuce committed
	JS_NewNumberValue(cx,uptime,&val);
	if(!JS_SetProperty(cx, sysobj, "uptime", &val))
		return(NULL);
deuce's avatar
deuce committed
	js_DescribeSyncObject(cx,sysobj,"Global system-related properties and methods",310);
	js_CreateArrayOfStrings(cx, sysobj, "_property_desc_list", sys_prop_desc, JSPROP_READONLY);
deuce's avatar
deuce committed
#ifdef BUILD_JSDOCS
	js_DescribeSyncObject(cx,statsobj,"System statistics",310);
	js_CreateArrayOfStrings(cx, statsobj, "_property_desc_list", sysstat_prop_desc, JSPROP_READONLY);
#endif
#endif	/* JAVSCRIPT */