Newer
Older
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_INT(argv[i])) {
if(addr.sin_addr.s_addr==0)
addr.sin_addr.s_addr=JSVAL_TO_INT(argv[i]);
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
else
addr.sin_port=(ushort)JSVAL_TO_INT(argv[i]);
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* ip_addr=NULL;
char* from=NULL;
char* fname=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(ip_addr==NULL)
ip_addr=p;
else if(from==NULL)
from=p;
else if(fname==NULL)
fname=p;
*rval = BOOLEAN_TO_JSVAL(filter_ip(cfg,prot,reason,host,ip_addr,from,fname));
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
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)
{
int32 node=1;
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);
return(JS_TRUE);
}
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
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)
{
int32 usernumber=1;
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);
return(JS_TRUE);
}
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
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));
user.sex=SP;
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;
user.qwk=QWK_DEFAULT;
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;
i=newuserdat(cfg,&user);
if(i==0) {
userobj=js_CreateUserObject(cx, obj, cfg, "user", 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_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 jsMethodSpec 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")
},
{"alias", js_alias, 1, JSTYPE_STRING, JSDOCSTR("string alias")
,JSDOCSTR("returns name of user that matches alias (if found in <tt>ctrl/alias.cfg</tt>)")
{"matchuser", js_matchuser, 1, JSTYPE_NUMBER, JSDOCSTR("string username [,bool sysop_alias]")
,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")
},
{"trashcan", js_trashcan, 2, JSTYPE_BOOLEAN, JSDOCSTR("string filename, search")
,JSDOCSTR("search text/filename.can for pseudo-regexp")
{"findstr", js_findstr, 2, JSTYPE_BOOLEAN, JSDOCSTR("string filename, search")
,JSDOCSTR("search any file for pseudo-regexp")
{"zonestr", js_zonestr, 0, JSTYPE_STRING, JSDOCSTR("[timezone]")
,JSDOCSTR("convert time zone integer to string, defaults to system timezone if <i>timezone</i> not specified")
{"timestr", js_timestr, 0, JSTYPE_STRING, JSDOCSTR("[time]")
,JSDOCSTR("convert time_t integer into a time string, "
"defaults to current time if <i>time</i> not specified")
{"datestr", js_datestr, 0, JSTYPE_STRING, JSDOCSTR("[time]")
,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")
{"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]")
{"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")
{"get_node_message",js_get_node_message,0, JSTYPE_STRING, JSDOCSTR("number node")
,JSDOCSTR("read any messages waiting for the specified node and return in a single string")
},
{"put_node_message",js_put_node_message,2, JSTYPE_BOOLEAN, JSDOCSTR("number node, string message")
,JSDOCSTR("send a node a short text message, delivered immediately")
{"get_telegram", js_get_telegram, 1, JSTYPE_STRING, JSDOCSTR("number user")
,JSDOCSTR("returns any short text messages waiting for the specified user")
},
{"put_telegram", js_put_telegram, 2, JSTYPE_BOOLEAN, JSDOCSTR("number user, string message")
,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")
},
{"exec", js_exec, 1, JSTYPE_NUMBER, JSDOCSTR("command-line")
,JSDOCSTR("executes a native system/shell command-line, returns 0 on success")
},
{"check_syspass", js_chksyspass, 1, JSTYPE_BOOLEAN, JSDOCSTR("string password")
,JSDOCSTR("compares the supplied <i>password</i> against the system password and return's <i>true</i> if it matches")
},
/* 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
};
#ifdef _DEBUG
static char* node_prop_desc[] = {
"status (see <tt>nodedefs.js</tt> for valid values)"
,"current user action (see <tt>nodedefs.js</tt>)"
,"connection speed (<tt>0xffff</tt> = Telnet or RLogin)"
,"miscellaneous bitfield (see <tt>nodedefs.js</tt>)"
,"auxillary value"
,"extended auxillary value"
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
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))
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
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;
int file;
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))
if(JSVAL_IS_INT(*vp))
JS_ValueToInt32(cx, *vp, &val);
tiny = JSVAL_TO_INT(id);
switch(tiny) {
case NODE_PROP_STATUS:
node.status=(BYTE)val;
break;
case NODE_PROP_ERRORS:
node.errors=(BYTE)val;
break;
case NODE_PROP_ACTION:
node.action=(BYTE)val;
break;
case NODE_PROP_USERON:
node.useron=(WORD)val;
break;
case NODE_PROP_CONNECTION:
node.connection=(WORD)val;
node.misc=(WORD)val;
node.aux=(WORD)val;
break;
case NODE_PROP_EXTAUX:
node.extaux=val;
break;
}
putnodedat(cfg,node_num,&node,file);
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
return(JS_TRUE);
}
static struct JSPropertySpec js_node_properties[] = {
/* name, tinyid, flags, getter, setter */
/* raw node_t fields */
{ "status", NODE_PROP_STATUS, JSPROP_ENUMERATE, NULL, NULL },
{ "errors", NODE_PROP_ERRORS, JSPROP_ENUMERATE, NULL, NULL },
{ "action", NODE_PROP_ACTION, JSPROP_ENUMERATE, NULL, NULL },
{ "useron", NODE_PROP_USERON, JSPROP_ENUMERATE, NULL, NULL },
{ "connection", NODE_PROP_CONNECTION, JSPROP_ENUMERATE, NULL, NULL },
{ "misc", NODE_PROP_MISC, JSPROP_ENUMERATE, NULL, NULL },
{ "aux", NODE_PROP_AUX, JSPROP_ENUMERATE, NULL, NULL },
{ "extaux", NODE_PROP_EXTAUX, JSPROP_ENUMERATE, NULL, NULL },
{0}
};
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 */
,JS_EnumerateStub /* enumerate */
,JS_ResolveStub /* resolve */
,JS_ConvertStub /* convert */
,JS_FinalizeStub /* finalize */
};
JSObject* DLLCALL js_CreateSystemObject(JSContext* cx, JSObject* parent
,scfg_t* cfg, time_t uptime, char* host_name)
{
char str[256];
uint i;
jsval val;
JSObject* sysobj;
JSObject* statsobj;
JSObject* nodeobj;
JSObject* node_list;
sysobj = JS_DefineObject(cx, parent, "system", &js_system_class, NULL
,JSPROP_ENUMERATE|JSPROP_READONLY);
if(sysobj==NULL)
return(NULL);
if(!JS_SetPrivate(cx, sysobj, cfg)) /* Store a pointer to scfg_t */
return(NULL);
if(!JS_DefineProperties(cx, sysobj, js_system_properties))
return(NULL);
if (!js_DefineMethods(cx, sysobj, js_system_functions, FALSE))
js_DescribeObject(cx,sysobj,"Global system-related properties and methods");
js_CreateArrayOfStrings(cx, sysobj, "_property_desc_list", sys_prop_desc, JSPROP_READONLY);
#endif
/****************************/
/* 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);
if((js_str=JS_NewStringCopyZ(cx, VERSION))==NULL)
return(NULL);
val = STRING_TO_JSVAL(js_str);
if(!JS_SetProperty(cx, sysobj, "version", &val))
return(NULL);
sprintf(str,"%c",REVISION);
if((js_str=JS_NewStringCopyZ(cx, str))==NULL)
return(NULL);
val = STRING_TO_JSVAL(js_str);
if(!JS_SetProperty(cx, sysobj, "revision", &val))
return(NULL);
SAFECOPY(str,beta_version);
truncsp(str);
if((js_str=JS_NewStringCopyZ(cx, str))==NULL)
return(NULL);
val = STRING_TO_JSVAL(js_str);
if(!JS_SetProperty(cx, sysobj, "beta_version", &val))
return(NULL);
sprintf(str,"%s%c%s",VERSION,REVISION,beta_version);
truncsp(str);
#if defined(_DEBUG)
strcat(str," Debug");
#endif
if((js_str=JS_NewStringCopyZ(cx, str))==NULL)
return(NULL);
val = STRING_TO_JSVAL(js_str);
if(!JS_SetProperty(cx, sysobj, "full_version", &val))
return(NULL);
if((js_str=JS_NewStringCopyZ(cx, VERSION_NOTICE))==NULL)
return(NULL);
val = STRING_TO_JSVAL(js_str);
if(!JS_SetProperty(cx, sysobj, "version_notice", &val))
return(NULL);
if((js_str=JS_NewStringCopyZ(cx, PLATFORM_DESC))==NULL)
return(NULL);
val = STRING_TO_JSVAL(js_str);
if(!JS_SetProperty(cx, sysobj, "platform", &val))
return(NULL);
if((js_str=JS_NewStringCopyZ(cx, socklib_version(str)))==NULL)
return(NULL);
val = STRING_TO_JSVAL(js_str);
if(!JS_SetProperty(cx, sysobj, "socket_lib", &val))
return(NULL);
sprintf(str,"SMBLIB %s",smb_lib_ver());
if((js_str=JS_NewStringCopyZ(cx, str))==NULL)
return(NULL);
val = STRING_TO_JSVAL(js_str);
if(!JS_SetProperty(cx, sysobj, "msgbase_lib", &val))
return(NULL);
if((js_str=JS_NewStringCopyZ(cx, str))==NULL)
return(NULL);
val = STRING_TO_JSVAL(js_str);
if(!JS_SetProperty(cx, sysobj, "compiled_with", &val))
return(NULL);
sprintf(str,"%s %.5s",__DATE__,__TIME__);
if((js_str=JS_NewStringCopyZ(cx, str))==NULL)
return(NULL);
val = STRING_TO_JSVAL(js_str);
if(!JS_SetProperty(cx, sysobj, "compiled_when", &val))
return(NULL);
if((js_str=JS_NewStringCopyZ(cx, COPYRIGHT_NOTICE))==NULL)
return(NULL);
val = STRING_TO_JSVAL(js_str);
if(!JS_SetProperty(cx, sysobj, "copyright", &val))
return(NULL);
if((js_str=JS_NewStringCopyZ(cx
,(char *)JS_GetImplementationVersion()))==NULL)
return(NULL);
val = STRING_TO_JSVAL(js_str);
if(!JS_SetProperty(cx, sysobj, "js_version", &val))
return(NULL);
if((js_str=JS_NewStringCopyZ(cx,os_version(str)))==NULL)
return(NULL);
val = STRING_TO_JSVAL(js_str);
if(!JS_SetProperty(cx, sysobj, "os_version", &val))
return(NULL);
/***********************/
val = INT_TO_JSVAL(uptime);
if(!JS_SetProperty(cx, sysobj, "uptime", &val))
return(NULL);
statsobj = JS_DefineObject(cx, sysobj, "stats", &js_sysstats_class, NULL
,JSPROP_ENUMERATE|JSPROP_READONLY);
if(statsobj==NULL)
return(NULL);
JS_SetPrivate(cx, statsobj, cfg); /* Store a pointer to scfg_t */
if(!JS_DefineProperties(cx, statsobj, js_sysstats_properties))
return(NULL);
js_DescribeObject(cx,statsobj,"System statistics");
js_CreateArrayOfStrings(cx, statsobj, "_property_desc_list", sysstat_prop_desc, JSPROP_READONLY);
#endif
/* node_list property */
if((node_list=JS_NewArrayObject(cx, 0, NULL))==NULL)
return(NULL);
if(!JS_DefineProperty(cx, sysobj, "node_list", OBJECT_TO_JSVAL(node_list)
, NULL, NULL, JSPROP_ENUMERATE))
return(NULL);
for(i=0;i<cfg->sys_nodes && i<cfg->sys_lastnode;i++) {
nodeobj = JS_NewObject(cx, &js_node_class, NULL, node_list);
if(nodeobj==NULL)
return(NULL);
/* 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(NULL);
if(!JS_DefineProperties(cx, nodeobj, js_node_properties))
return(NULL);
js_DescribeObject(cx,nodeobj,"BBS node listing");
js_CreateArrayOfStrings(cx, nodeobj, "_property_desc_list", node_prop_desc, JSPROP_READONLY);
val=OBJECT_TO_JSVAL(nodeobj);
if(!JS_SetElement(cx, node_list, i, &val))
return(NULL);
}
return(sysobj);
}