Newer
Older
rc = JS_SUSPENDREQUEST(cx);
JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(!illegal_filename(fname)
&& allowed_filename(sys->cfg, fname)
&& !trashcan(sys->cfg, fname, "file")));
JS_RESUMEREQUEST(cx, rc);
free(fname);
return JS_TRUE;
}
static JSBool
js_safest_fname(JSContext *cx, uintN argc, jsval *arglist)
{
jsval * argv = JS_ARGV(cx, arglist);
char* fname = NULL;
jsrefcount rc;
JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
if (argc < 1 || !JSVAL_IS_STRING(argv[0]))
return JS_TRUE;
JSVALUE_TO_MSTRING(cx, argv[0], fname, NULL);
return JS_FALSE;
rc = JS_SUSPENDREQUEST(cx);
JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(safest_filename(fname)));
JS_RESUMEREQUEST(cx, rc);
free(fname);
return JS_TRUE;
}
static JSBool
js_illegal_fname(JSContext *cx, uintN argc, jsval *arglist)
{
jsval * argv = JS_ARGV(cx, arglist);
char* fname = NULL;
jsrefcount rc;
JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
if (argc < 1 || !JSVAL_IS_STRING(argv[0]))
return JS_TRUE;
JSVALUE_TO_MSTRING(cx, argv[0], fname, NULL);
return JS_FALSE;
rc = JS_SUSPENDREQUEST(cx);
JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(illegal_filename(fname)));
JS_RESUMEREQUEST(cx, rc);
free(fname);
return JS_TRUE;
}
static JSBool
js_allowed_fname(JSContext *cx, uintN argc, jsval *arglist)
{
JSObject * obj = JS_THIS_OBJECT(cx, arglist);
jsval * argv = JS_ARGV(cx, arglist);
char* fname = NULL;
jsrefcount rc;
JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
if (argc < 1 || !JSVAL_IS_STRING(argv[0]))
return JS_TRUE;
js_system_private_t* sys;
if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
return JS_FALSE;
JSVALUE_TO_MSTRING(cx, argv[0], fname, NULL);
return JS_FALSE;
rc = JS_SUSPENDREQUEST(cx);
JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(allowed_filename(sys->cfg, fname)));
JS_RESUMEREQUEST(cx, rc);
free(fname);
return JS_TRUE;
}
#endif
static JSBool
js_chkpid(JSContext *cx, uintN argc, jsval *arglist)
{
jsval * argv = JS_ARGV(cx, arglist);
int32 pid = 0;
jsrefcount rc;
JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
if (!js_argc(cx, argc, 1))
if (JSVAL_NULL_OR_VOID(argv[0])) {
JS_ReportError(cx, "Invalid argument");
return JS_FALSE;
}
JS_ValueToInt32(cx, argv[0], &pid);
rc = JS_SUSPENDREQUEST(cx);
JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(check_pid(pid)));
JS_RESUMEREQUEST(cx, rc);
}
static JSBool
js_killpid(JSContext *cx, uintN argc, jsval *arglist)
{
jsval * argv = JS_ARGV(cx, arglist);
int32 pid = 0;
jsrefcount rc;
JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
if (!js_argc(cx, argc, 1))
if (JSVAL_NULL_OR_VOID(argv[0])) {
JS_ReportError(cx, "Invalid argument");
return JS_FALSE;
}
JS_ValueToInt32(cx, argv[0], &pid);
rc = JS_SUSPENDREQUEST(cx);
JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(terminate_pid(pid)));
JS_RESUMEREQUEST(cx, rc);
}
static JSBool
js_text(JSContext *cx, uintN argc, jsval *arglist)
{
JSObject* obj = JS_THIS_OBJECT(cx, arglist);
jsval* argv = JS_ARGV(cx, arglist);
uint32 i = 0;
JS_SET_RVAL(cx, arglist, JSVAL_NULL);
if (!js_argc(cx, argc, 1))
return JS_FALSE;
if (JSVAL_NULL_OR_VOID(argv[0])) {
JS_ReportError(cx, "Invalid argument");
return JS_FALSE;
}
js_system_private_t* sys;
if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
return JS_FALSE;
if (sys->cfg == NULL || sys->cfg->text == NULL)
return JS_TRUE;
if (JSVAL_IS_NUMBER(argv[0])) {
if (!JS_ValueToECMAUint32(cx, argv[0], &i))

Rob Swindell
committed
return JS_FALSE;
} else {
JSString* js_str = JS_ValueToString(cx, argv[0]);

Rob Swindell
committed
return JS_FALSE;

Rob Swindell
committed
JSSTRING_TO_MSTRING(cx, js_str, id, NULL);
i = get_text_num(id) + 1; // Note: this is a non-caching look-up!
free(id);
}
if (i > 0 && i <= TOTAL_TEXT) {
JSString* js_str = JS_NewStringCopyZ(cx, sys->cfg->text[i - 1]);
return JS_FALSE;
JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
}
return JS_TRUE;
}
static jsSyncMethodSpec js_system_functions[] = {
#ifndef JSDOOR
{"username", js_username, 1, JSTYPE_STRING, JSDOCSTR("user_number")
, JSDOCSTR("Return name of user in specified user record <i>number</i>, or empty string if not found")
, 311},
{"alias", js_alias, 1, JSTYPE_STRING, JSDOCSTR("alias")
, JSDOCSTR("Return name of user that matches alias (if found in <tt>ctrl/alias.cfg</tt>)")
, 310},
{"find_login_id", js_find_login_id, 1, JSTYPE_NUMBER, JSDOCSTR("user-id")
, JSDOCSTR("Find a user's login ID (alias, real name, or number), returns matching user record number or 0 if not found")
, 32000},
{"matchuser", js_matchuser, 1, JSTYPE_NUMBER, JSDOCSTR("username [,sysop_alias=true]")
, 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")
, 310},
{"matchuserdata", js_matchuserdata, 2, JSTYPE_NUMBER, JSDOCSTR("field, data [,<i>bool</i> match_del=false] [,<i>number</i> usernumber, <i>bool</i> match_next=false]")
, JSDOCSTR("Search user database for data in a specific field (see <tt>U_*</tt> in <tt>sbbsdefs.js</tt>).<br>"
"If <i>match_del</i> is <tt>true</tt>, deleted user records are searched, "
"returns first matching user record number, optional <i>usernumber</i> specifies user record to skip, "
"or record at which to begin searching if optional <i>match_next</i> is <tt>true</tt>.")
, 310},
#endif
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
{"trashcan", js_trashcan, 2, JSTYPE_BOOLEAN, JSDOCSTR("basename, find_string")
, JSDOCSTR("Search <tt>text/<i>basename</i>.can</tt> for pseudo-regexp")
, 310},
{"findstr", js_findstr, 2, JSTYPE_BOOLEAN, JSDOCSTR("path/filename or <i>array</i> of strings, find_string")
, JSDOCSTR("Search any trashcan/filter file or array of pattern strings (in <tt>*.can</tt> format) for <i>find_string</i>")
, 310},
{"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")
, 310},
{"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")
, 310},
{"datestr", js_datestr, 0, JSTYPE_STRING, JSDOCSTR("[time=<i>current</i>]")
, JSDOCSTR("Convert time_t integer into a short (8 character) date string, in either numeric or verbal format (depending on system preference), "
"defaults to current date if <i>time</i> not specified. "
"If <i>time</i> is a string in numeric date format, returns the parsed time_t value as a number.")
, 310},
{"secondstr", js_secondstr, 0, JSTYPE_STRING, JSDOCSTR("seconds")
, JSDOCSTR("Convert elapsed time in seconds into a string in <tt>hh:mm:ss</tt> format")
, 310},
#ifndef JSDOOR
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
{"spamlog", js_spamlog, 6, JSTYPE_BOOLEAN, JSDOCSTR("[protocol, action, reason, host, ip, to, from]")
, JSDOCSTR("Log a suspected SPAM attempt")
, 310},
{"hacklog", js_hacklog, 5, JSTYPE_BOOLEAN, JSDOCSTR("[protocol, user, text, host, ip, port]")
, JSDOCSTR("Log a suspected hack attempt")
, 310},
{"filter_ip", js_filter_ip, 4, JSTYPE_BOOLEAN, JSDOCSTR("[protocol, reason, host, ip, username, filename] [<i>number</i> duration-in-seconds]")
, JSDOCSTR("Add an IP address (with comment) to an IP filter file. If filename is not specified, the ip.can file is used")
, 311},
{"get_node", js_get_node, 1, JSTYPE_OBJECT, JSDOCSTR("node_number")
, JSDOCSTR("Read a node data record all at once (and leaving the record unlocked) "
"returning an object matching the elements of <tt>system.node_list</tt>")
, 31702},
{"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")
, 311},
{"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")
, 310},
{"get_telegram", js_get_telegram, 1, JSTYPE_STRING, JSDOCSTR("user_number")
, JSDOCSTR("Return any short text messages waiting for the specified user")
, 311},
{"put_telegram", js_put_telegram, 2, JSTYPE_BOOLEAN, JSDOCSTR("user_number, message_text")
, JSDOCSTR("Send a user a short text message, delivered immediately or during next logon")
, 310},
{"notify", js_notify, 2, JSTYPE_BOOLEAN, JSDOCSTR("user_number, subject [,message_text]")
, JSDOCSTR("Notify a user or operator via both email and a short text message about an important event")
, 31801},
{"newuser", js_new_user, 1, JSTYPE_ALIAS },
{"new_user", js_new_user, 1, JSTYPE_OBJECT, JSDOCSTR("name/alias [,client object]")
, JSDOCSTR("Create a new user record, returns a new <a href=#User_object>User object</a> representing the new user account, on success.<br>"
"returns an numeric error code on failure")
, 310},
{"del_user", js_del_user, 1, JSTYPE_BOOLEAN, JSDOCSTR("user_number")
, JSDOCSTR("Delete the specified user account")
, 316},
#endif
{"exec", js_sys_exec, 0, JSTYPE_NUMBER, JSDOCSTR("command-line")
, JSDOCSTR("Execute a native system/shell command-line, returns <i>0</i> on success")
, 311},
{"popen", js_popen, 0, JSTYPE_ARRAY, JSDOCSTR("command-line")
, JSDOCSTR("Execute a native system/shell command-line, returns array of captured output lines on success "
"(<b>only functional on UNIX systems</b>)")
, 311},
#ifndef JSDOOR
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
{"check_syspass", js_chksyspass, 1, JSTYPE_BOOLEAN, JSDOCSTR("password")
, JSDOCSTR("Compare the supplied <i>password</i> against the system password and returns <tt>true</tt> if it matches")
, 311},
{"check_name", js_chkname, 1, JSTYPE_BOOLEAN, JSDOCSTR("name/alias")
, JSDOCSTR("Check that the provided name/alias string is suitable for a new user account, "
"returns <tt>true</tt> if it is valid")
, 315},
{"check_filename", js_chkfname, 1, JSTYPE_BOOLEAN, JSDOCSTR("filename")
, JSDOCSTR("Verify that the specified <i>filename</i> string is legal and allowed for upload by users "
"(based on system configuration and filter files), returns <tt>true</tt> if the filename is allowed")
, 31902},
{"allowed_filename", js_allowed_fname, 1, JSTYPE_BOOLEAN, JSDOCSTR("filename")
, JSDOCSTR("Verify that the specified <i>filename</i> string is allowed for upload by users "
"(based on system configuration), returns <tt>true</tt> if the filename is allowed")
, 31902},
{"safest_filename", js_safest_fname, 1, JSTYPE_BOOLEAN, JSDOCSTR("filename")
, JSDOCSTR("Verify that the specified <i>filename</i> string contains only the safest subset of characters")
, 31902},
{"illegal_filename", js_illegal_fname, 1, JSTYPE_BOOLEAN, JSDOCSTR("filename")
, JSDOCSTR("Check if the specified <i>filename</i> string contains illegal characters or sequences, "
"returns <tt>true</tt> if it is an illegal filename")
, 31902},
#endif
{"check_pid", js_chkpid, 1, JSTYPE_BOOLEAN, JSDOCSTR("process-ID")
, JSDOCSTR("Check that the provided process ID is a valid executing process on the system, "
"returns <tt>true</tt> if it is valid")
, 315},
{"terminate_pid", js_killpid, 1, JSTYPE_BOOLEAN, JSDOCSTR("process-ID")
, JSDOCSTR("Terminate executing process on the system with the specified process ID, "
"returns <tt>true</tt> on success")
, 315},
{"text", js_text, 1, JSTYPE_STRING, JSDOCSTR("<i>number</i> index or <i>string</i> id")
, JSDOCSTR("Return specified text string (see <tt>bbs.text()</tt> for details)<br>"
"The <i>string</i> id support was added in v3.20.")
, 31802},
/* node properties */
enum {
/* raw node_t fields */
NODE_PROP_STATUS
, NODE_PROP_VSTATUS
, NODE_PROP_ERRORS
, NODE_PROP_ACTION
, NODE_PROP_ACTIVITY
, NODE_PROP_USERON
, NODE_PROP_CONNECTION
, NODE_PROP_MISC
, NODE_PROP_AUX
, NODE_PROP_EXTAUX
, NODE_PROP_DIR
#ifdef BUILD_JSDOCS
static const char* node_prop_desc[] = {
"Status (see <tt>nodedefs.js</tt> for valid values)"
, "Verbal status - <small>READ ONLY</small>"
, "Error counter"
, "Current user action (see <tt>nodedefs.js</tt>)"
, "Current user activity - <small>READ ONLY</small>y"
, "Current user number"
, "Connection speed (<tt>0xffff</tt> = Telnet or RLogin)"
, "Miscellaneous bit-flags (see <tt>nodedefs.js</tt>)"
, "Auxiliary value"
, "Extended auxiliary value"
, "Node directory - <small>READ ONLY</small>"
, NULL
static JSBool js_node_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
char tmp[128];
jsval idval;
uint node_num;
jsint tiny;
node_t node;
JSObject* sysobj;
JSObject* node_list;
jsrefcount rc;
JSString* js_str;
JS_IdToValue(cx, id, &idval);
tiny = JSVAL_TO_INT(idval);
if ((node_list = JS_GetParent(cx, obj)) == NULL)
if ((sysobj = JS_GetParent(cx, node_list)) == NULL)
js_system_private_t* sys;
if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, sysobj, &js_system_class)) == NULL)
return JS_FALSE;
node_num = (uintptr_t)JS_GetPrivate(cx, obj) >> 1;
rc = JS_SUSPENDREQUEST(cx);
memset(&node, 0, sizeof(node));
if (getnodedat(sys->cfg, node_num, &node, /* lockit: */ FALSE, &sys->nodefile) != 0) {
JS_RESUMEREQUEST(cx, rc);
JS_RESUMEREQUEST(cx, rc);
sys->nodegets++;
case NODE_PROP_STATUS:
*vp = INT_TO_JSVAL((int)node.status);
break;
case NODE_PROP_VSTATUS:
if ((js_str = JS_NewStringCopyZ(cx, node_vstatus(sys->cfg, &node, tmp, sizeof tmp))) == NULL)
*vp = STRING_TO_JSVAL(js_str);
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_ACTIVITY:
if ((js_str = JS_NewStringCopyZ(cx, node_activity(sys->cfg, &node, tmp, sizeof tmp, node_num))) == NULL)
*vp = STRING_TO_JSVAL(js_str);
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:
*vp = UINT_TO_JSVAL(node.extaux);
case NODE_PROP_DIR:
if ((js_str = JS_NewStringCopyZ(cx, sys->cfg->node_path[node_num - 1])) == NULL)
*vp = STRING_TO_JSVAL(js_str);
break;
static JSBool js_node_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
jsval idval;
uint node_num;
jsint val = 0;
jsint tiny;
node_t node;
JSObject* sysobj;
JSObject* node_list;
jsrefcount rc;
if ((node_list = JS_GetParent(cx, obj)) == NULL)
if ((sysobj = JS_GetParent(cx, node_list)) == NULL)
js_system_private_t* sys;
if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, sysobj, &js_system_class)) == NULL)
return JS_FALSE;
node_num = (uintptr_t)JS_GetPrivate(cx, obj) >> 1;
rc = JS_SUSPENDREQUEST(cx);
memset(&node, 0, sizeof(node));
if (getnodedat(sys->cfg, node_num, &node, /* lockit: */ TRUE, &sys->nodefile)) {
JS_RESUMEREQUEST(cx, rc);
JS_RESUMEREQUEST(cx, rc);
if (JSVAL_IS_NUMBER(*vp))
JS_IdToValue(cx, id, &idval);
tiny = JSVAL_TO_INT(idval);
rc = JS_SUSPENDREQUEST(cx);
node.status = (BYTE)val;
case NODE_PROP_ERRORS:
node.errors = (BYTE)val;
case NODE_PROP_ACTION:
node.action = (BYTE)val;
case NODE_PROP_USERON:
node.useron = (WORD)val;
break;
case NODE_PROP_CONNECTION:
node.connection = (WORD)val;
case NODE_PROP_MISC:
node.misc = (WORD)val;
case NODE_PROP_AUX:
node.aux = (WORD)val;
case NODE_PROP_EXTAUX:
putnodedat(sys->cfg, node_num, &node, /* closeit: */ FALSE, sys->nodefile);
mqtt_putnodedat(sys->mqtt, node_num, &node);
JS_RESUMEREQUEST(cx, rc);
static jsSyncPropertySpec js_node_properties[] = {
/* name, tinyid, flags, ver */
{ "status", NODE_PROP_STATUS, JSPROP_ENUMERATE, 310 },
{ "vstatus", NODE_PROP_VSTATUS, JSPROP_ENUMERATE | JSPROP_READONLY, 320 },
{ "errors", NODE_PROP_ERRORS, JSPROP_ENUMERATE, 310 },
{ "action", NODE_PROP_ACTION, JSPROP_ENUMERATE, 310 },
{ "activity", NODE_PROP_ACTIVITY, JSPROP_ENUMERATE | JSPROP_READONLY, 320 },
{ "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 },
{ "dir", NODE_PROP_DIR, JSPROP_ENUMERATE | JSPROP_READONLY, 315 },
static JSBool js_node_resolve(JSContext *cx, JSObject *obj, jsid id)
char* name = NULL;
JSBool ret;
if (id != JSID_VOID && id != JSID_EMPTY) {
if (JSVAL_IS_STRING(idval)) {
JSSTRING_TO_MSTRING(cx, JSVAL_TO_STRING(idval), name, NULL);
HANDLE_PENDING(cx, name);
ret = js_SyncResolve(cx, obj, name, js_node_properties, NULL, NULL, 0);
if (name)
}
static JSBool js_node_enumerate(JSContext *cx, JSObject *obj)
{
return js_node_resolve(cx, obj, JSID_VOID);
"Node" /* name */
, JSCLASS_HAS_PRIVATE /* flags */
, JS_PropertyStub /* addProperty */
, JS_PropertyStub /* delProperty */
, js_node_get /* getProperty */
, js_node_set /* setProperty */
, js_node_enumerate /* enumerate */
, js_node_resolve /* resolve */
, JS_ConvertStub /* convert */
, JS_FinalizeStub /* finalize */
if (name == NULL || strcmp(name, (PropName)) == 0) { \
val = UINT_TO_JSVAL((PropValue)); \
JS_DefineProperty(cx, obj, (PropName), val, NULL, NULL, JSPROP_ENUMERATE); \
if (name) { \
free(name); \
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) { \
free(name); \
} \
} \
else if (name) { \
#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) { \
free(name); \
} \
} \
else if (name) { \
#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) { \
free(name); \
} \
} \
else if (name) { \
static JSBool js_system_resolve(JSContext *cx, JSObject *obj, jsid id)
char* name = NULL;
jsval val;
char str[256];
JSString* js_str;
JSBool ret;
#ifndef JSDOOR
JSObject* newobj;
JSObject* nodeobj;
int i;
#endif
if (id != JSID_VOID && id != JSID_EMPTY) {
if (JSVAL_IS_STRING(idval)) {
JSSTRING_TO_MSTRING(cx, JSVAL_TO_STRING(idval), name, NULL);
HANDLE_PENDING(cx, name);
/****************************/
/* static string properties */
LAZY_STRFUNC("revision", sprintf(str, "%c", REVISION), str);
LAZY_STRFUNC_TRUNCSP("beta_version", SAFECOPY(str, beta_version), str);
if (name == NULL || strcmp(name, "full_version") == 0) {
sprintf(str, "%s%c%s", VERSION, REVISION, beta_version);
strcat(str, " Debug");
if (name)
free(name);
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;
/* Numeric version properties */
LAZY_INTEGER("version_num", VERSION_NUM);
LAZY_INTEGER("version_hex", VERSION_HEX);
/* Git repo details */
LAZY_STRING("git_branch", git_branch);
LAZY_STRING("git_hash", git_hash);
LAZY_STRING("git_date", git_date);
LAZY_INTEGER("git_time", (uint32_t)git_time);
LAZY_STRING("architecture", ARCHITECTURE_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, sizeof(str)));
#ifndef JSDOOR
if (name == NULL || strcmp(name, "fido_addr_list") == 0) {
if (name)
free(name);
js_system_private_t* sys;
if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
return JS_FALSE;
if ((newobj = JS_NewArrayObject(cx, 0, NULL)) == NULL)
if (!JS_SetParent(cx, newobj, obj))
if (!JS_DefineProperty(cx, obj, "fido_addr_list", OBJECT_TO_JSVAL(newobj)
, NULL, NULL, JSPROP_ENUMERATE))
for (i = 0; i < sys->cfg->total_faddrs; i++) {
val = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, smb_faddrtoa(&sys->cfg->faddr[i], str)));
if (name)
return JS_TRUE;
if (name == NULL || strcmp(name, "stats") == 0) {
if (name)
free(name);
js_system_private_t* sys;
if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
return JS_FALSE;
newobj = JS_DefineObject(cx, obj, "stats", &js_sysstats_class, NULL
, JSPROP_ENUMERATE | JSPROP_READONLY);
JS_SetPrivate(cx, newobj, sys);
js_DescribeSyncObject(cx, newobj, "System statistics", 310);
js_CreateArrayOfStrings(cx, newobj, "_property_desc_list", sysstat_prop_desc, JSPROP_READONLY);
#endif
if (name)
return JS_TRUE;
if (name == NULL || strcmp(name, "node_list") == 0) {
if (name)
free(name);
js_system_private_t* sys;
if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
return JS_FALSE;
if ((newobj = JS_NewArrayObject(cx, 0, NULL)) == NULL)
if (!JS_SetParent(cx, newobj, obj))
if (!JS_DefineProperty(cx, obj, "node_list", OBJECT_TO_JSVAL(newobj)
, NULL, NULL, JSPROP_ENUMERATE))
for (i = 0; i < sys->cfg->sys_nodes && i < sys->cfg->sys_lastnode; i++) {
nodeobj = JS_NewObject(cx, &js_node_class, NULL, newobj);
/* Store node number */
/* We have to shift it to make it look like a pointer to JS. :-( */
if (!JS_SetPrivate(cx, nodeobj, (char*)(((uintptr_t)i + 1) << 1)))
if (i == 0) {
js_DescribeSyncObject(cx, nodeobj, "Terminal Server 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))
if (name)
return JS_TRUE;
#endif
ret = js_SyncResolve(cx, obj, name, js_system_properties, js_system_functions, NULL, 0);
if (name)
free(name);
static JSBool js_system_enumerate(JSContext *cx, JSObject *obj)
{
return js_system_resolve(cx, obj, JSID_VOID);
static void js_system_finalize(JSContext *cx, JSObject *obj)
{
js_system_private_t* sys;
if ((sys = (js_system_private_t*)JS_GetPrivate(cx, obj)) == NULL)
return;
CLOSE_OPEN_FILE(sys->nodefile);
free(sys);
JS_SetPrivate(cx, obj, NULL);
}

Rob Swindell
committed
JSBool js_CreateTextProperties(JSContext* cx, JSObject* parent)
{
jsval val;
if (!JS_GetProperty(cx, parent, "text", &val))
return JS_FALSE;
JSObject* text = JSVAL_TO_OBJECT(val);
return JS_FALSE;

Rob Swindell
committed
for (int i = 0; i < TOTAL_TEXT; ++i) {
val = INT_TO_JSVAL(i + 1);
if (!JS_SetProperty(cx, text, text_id[i], &val))

Rob Swindell
committed
return JS_FALSE;
}
return JS_TRUE;
}
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_system_finalize /* finalize */
JSObject* js_CreateSystemObject(JSContext* cx, JSObject* parent
, scfg_t* cfg, time_t uptime, char* host_name, char* socklib_desc, struct mqtt* mqtt)
jsval val;
JSObject* sysobj;
JSString* js_str;
char str[256];
sysobj = JS_DefineObject(cx, parent, "system", &js_system_class, NULL
, JSPROP_ENUMERATE | JSPROP_READONLY);
if (sysobj == NULL)
js_system_private_t* sys;
if ((sys = calloc(sizeof(*sys), 1)) == NULL)
return NULL;
sys->cfg = cfg;
sys->nodefile = -1;
if (!JS_SetPrivate(cx, sysobj, sys))
/****************************/
/* static string properties */
#ifndef JSDOOR
if ((js_str = JS_NewStringCopyZ(cx, host_name)) == NULL)
if (!JS_SetProperty(cx, sysobj, "host_name", &val))
#endif
if ((js_str = JS_NewStringCopyZ(cx, socklib_version(str, sizeof str, socklib_desc))) == NULL)
if (!JS_SetProperty(cx, sysobj, "socket_lib", &val))
val = DOUBLE_TO_JSVAL((double)uptime);
if (!JS_SetProperty(cx, sysobj, "uptime", &val))

Rob Swindell
committed
js_CreateTextProperties(cx, sysobj);
#ifdef BUILD_JSDOCS
js_DescribeSyncObject(cx, sysobj, "Global system-related properties and methods", 310);
js_CreateArrayOfStrings(cx, sysobj, "_property_desc_list", sys_prop_desc, JSPROP_READONLY);
#endif /* JAVSCRIPT */