Skip to content
Snippets Groups Projects
js_system.c 85 KiB
Newer Older
	JSObject *           obj = JS_THIS_OBJECT(cx, arglist);
	jsval *              argv = JS_ARGV(cx, arglist);
	char*                p;
	JSString*            js_str;
	jsrefcount           rc;

	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	js_system_private_t* sys;
	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
	if ((js_str = JS_ValueToString(cx, argv[0])) == NULL) {
		JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(0));
	JSSTRING_TO_ASTRING(cx, js_str, p, (LEN_ALIAS > LEN_NAME) ? LEN_ALIAS + 2:LEN_NAME + 2, NULL);
	if (p == NULL) {
		JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(0));
	rc = JS_SUSPENDREQUEST(cx);
	JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(find_login_id(sys->cfg, p)));
	JS_RESUMEREQUEST(cx, rc);
static JSBool
js_trashcan(JSContext *cx, uintN argc, jsval *arglist)
	JSObject *           obj = JS_THIS_OBJECT(cx, arglist);
	jsval *              argv = JS_ARGV(cx, arglist);
	char*                str;
	char*                can = NULL;
	JSString*            js_str;
	JSString*            js_can;
	jsrefcount           rc;
	BOOL                 ret;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
	if ((js_can = JS_ValueToString(cx, argv[0])) == NULL) {
		JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(JS_FALSE));
	if ((js_str = JS_ValueToString(cx, argv[1])) == NULL) {
		JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(JS_FALSE));
deuce's avatar
deuce committed
	JSSTRING_TO_MSTRING(cx, js_can, can, NULL);
	HANDLE_PENDING(cx, can);
		JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(JS_FALSE));
deuce's avatar
deuce committed
	JSSTRING_TO_MSTRING(cx, js_str, str, NULL);
	if (JS_IsExceptionPending(cx)) {
deuce's avatar
deuce committed
		free(can);
		return JS_FALSE;
	}
deuce's avatar
deuce committed
		free(can);
		JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(JS_FALSE));
	rc = JS_SUSPENDREQUEST(cx);
	ret = trashcan(sys->cfg, str, can);
deuce's avatar
deuce committed
	free(can);
	free(str);
deuce's avatar
deuce committed
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
js_findstr(JSContext *cx, uintN argc, jsval *arglist)
	jsval *    argv = JS_ARGV(cx, arglist);
	char*      str;
	char*      fname = NULL;
	JSString*  js_str;
	JSString*  js_fname;
	jsrefcount rc;
	BOOL       ret;
	str_list_t list = NULL;

	if (JSVAL_IS_OBJECT(argv[0]) && !JSVAL_IS_NULL(argv[0])) {
		JSObject* array = JSVAL_TO_OBJECT(argv[0]);
		if (array == NULL || !JS_IsArrayObject(cx, array))
		jsuint    count;
		if (!JS_GetArrayLength(cx, array, &count))
		char*     tmp = NULL;
		size_t    tmplen = 0;
		for (jsuint i = 0; i < count; i++) {
			if (!JS_GetElement(cx, array, i, &val))
			if (!JSVAL_IS_STRING(val))   /* must be an array of strings */
				break;
			JSVALUE_TO_RASTRING(cx, val, tmp, &tmplen, NULL);
			HANDLE_PENDING(cx, tmp);
			strListPush(&list, tmp);
		}
		free(tmp);
		if ((js_fname = JS_ValueToString(cx, argv[0])) == NULL) {
			JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(JS_FALSE));
		}
		JSSTRING_TO_MSTRING(cx, js_fname, fname, NULL);
		HANDLE_PENDING(cx, fname);
		if (fname == NULL) {
			JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(JS_FALSE));
	if ((js_str = JS_ValueToString(cx, argv[1])) == NULL) {
		JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(JS_FALSE));
		free(fname);
deuce's avatar
deuce committed
	JSSTRING_TO_MSTRING(cx, js_str, str, NULL);
	if (JS_IsExceptionPending(cx)) {
deuce's avatar
deuce committed
		free(fname);
		return JS_FALSE;
	}
deuce's avatar
deuce committed
		free(fname);
		JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(JS_FALSE));
	rc = JS_SUSPENDREQUEST(cx);
	if (list != NULL)
		ret = findstr_in_list(str, list, NULL);
	else
		ret = findstr(str, fname);
deuce's avatar
deuce committed
	free(str);
	free(fname);
	strListFree(&list);
deuce's avatar
deuce committed
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
static JSBool
js_zonestr(JSContext *cx, uintN argc, jsval *arglist)
	JSObject *           obj = JS_THIS_OBJECT(cx, arglist);
	jsval *              argv = JS_ARGV(cx, arglist);
	JSString*            js_str;
	short                zone;
	int32                val = 0;
	jsrefcount           rc;
	char*                cstr;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
	if (argc < 1)
		zone = sys_timezone(sys->cfg);
		JS_ValueToInt32(cx, argv[0], &val);
		zone = (short)val;
	rc = JS_SUSPENDREQUEST(cx);
	cstr = smb_zonestr(zone, NULL);
	if ((js_str = JS_NewStringCopyZ(cx, cstr)) == NULL)
	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
/* Returns a ctime()-like string in the system-preferred time format */
js_timestr(JSContext *cx, uintN argc, jsval *arglist)
	JSObject *           obj = JS_THIS_OBJECT(cx, arglist);
	jsval *              argv = JS_ARGV(cx, arglist);
	char                 str[128];
	jsdouble             ti;
	JSString*            js_str;
	jsrefcount           rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
	if (argc < 1)
		ti = (jsdouble)time(NULL);  /* use current time */
	if (!JS_ValueToNumber(cx, argv[0], &ti))
		return JS_TRUE;
	rc = JS_SUSPENDREQUEST(cx);
	timestr(sys->cfg, (time32_t)ti, str);
	if ((js_str = JS_NewStringCopyZ(cx, str)) == NULL)
	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
/* Convert between string and time_t representations of date */
js_datestr(JSContext *cx, uintN argc, jsval *arglist)
	JSObject *           obj = JS_THIS_OBJECT(cx, arglist);
	jsval *              argv = JS_ARGV(cx, arglist);
	char                 str[128];
	time32_t             t;
	JSString*            js_str;
	char *               p;
	enum date_fmt        fmt;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
	if (argc < 1)
		t = time32(NULL); /* use current time */
		if (JSVAL_IS_STRING(argv[0])) {  /* convert from string to time_t? */
deuce's avatar
deuce committed
			JSVALUE_TO_ASTRING(cx, argv[0], p, 10, NULL);
			JS_SET_RVAL(cx, arglist, DOUBLE_TO_JSVAL((double)dstrtounix(fmt, p)));
		JS_ValueToECMAUint32(cx, argv[0], (uint32_t*)&t);
	if ((js_str = JS_NewStringCopyZ(cx, datestr(sys->cfg, t, str))) == NULL)
	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
js_secondstr(JSContext *cx, uintN argc, jsval *arglist)
	jsval *   argv = JS_ARGV(cx, arglist);
	char      str[128];
	uint32_t  t = 0;
	JSString* js_str;
	JS_SET_RVAL(cx, arglist, JSVAL_NULL);
	if (!js_argc(cx, argc, 1))
	if (JSVAL_NULL_OR_VOID(argv[0])) {
		JS_ReportError(cx, "Invalid argument");
		return JS_FALSE;
	}
	JS_ValueToECMAUint32(cx, argv[0], &t);
	sectostr(t, str);
	if ((js_str = JS_NewStringCopyZ(cx, str)) == NULL)
	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
js_spamlog(JSContext *cx, uintN argc, jsval *arglist)
	JSObject *           obj = JS_THIS_OBJECT(cx, arglist);
	jsval *              argv = JS_ARGV(cx, arglist);
	uintN                i;
	char*                p = NULL;
	char*                prot = NULL;
	char*                action = NULL;
	char*                reason = NULL;
	char*                host = NULL;
	char*                ip_addr = NULL;
	char*                to = NULL;
	char*                from = NULL;
	jsrefcount           rc;
	BOOL                 ret;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
	for (i = 0; i < argc && from == NULL; i++) {
		if (!JSVAL_IS_STRING(argv[i]))
		JSVALUE_TO_MSTRING(cx, argv[i], p, NULL);
		if (p == NULL || JS_IsExceptionPending(cx)) {
			free(prot);
			free(action);
			free(reason);
			free(host);
			free(ip_addr);
			free(to);
			free(p);
			return JS_FALSE;
		if (prot == NULL)
			prot = p;
		else if (action == NULL)
			action = p;
		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;
	rc = JS_SUSPENDREQUEST(cx);
	ret = spamlog(sys->cfg, sys->mqtt, prot, action, reason, host, ip_addr, to, from);
	free(prot);
	free(action);
	free(reason);
	free(host);
	free(ip_addr);
	free(to);
	free(from);
deuce's avatar
deuce committed
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
js_hacklog(JSContext *cx, uintN argc, jsval *arglist)
	JSObject *           obj = JS_THIS_OBJECT(cx, arglist);
	jsval *              argv = JS_ARGV(cx, arglist);
	uintN                i;
	int32                i32 = 0;
	char*                p = NULL;
	char*                prot = NULL;
	char*                user = NULL;
	char*                text = NULL;
	char*                host = NULL;
	union xp_sockaddr    addr;
	jsrefcount           rc;
	BOOL                 ret;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
	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.in.sin_addr.s_addr == 0)
				addr.in.sin_addr.s_addr = i32;
				addr.in.sin_port = (ushort)i32;
		if (!JSVAL_IS_STRING(argv[i]))
deuce's avatar
deuce committed
			JSVALUE_TO_MSTRING(cx, argv[i], p, NULL);
			if (JS_IsExceptionPending(cx) || p == NULL) {
				free(prot);
				free(user);
				free(text);
				free(p);
deuce's avatar
deuce committed
				return JS_FALSE;
			}
			if (prot == NULL)
				prot = p;
			else if (user == NULL)
				user = p;
			else if (text == NULL)
				text = p;
	rc = JS_SUSPENDREQUEST(cx);
	ret = hacklog(sys->cfg, sys->mqtt, prot, user, text, host, &addr);
	free(prot);
	free(user);
	free(text);
	free(host);
deuce's avatar
deuce committed
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
static JSBool
js_filter_ip(JSContext *cx, uintN argc, jsval *arglist)
	JSObject *           obj = JS_THIS_OBJECT(cx, arglist);
	jsval *              argv = JS_ARGV(cx, arglist);
	uintN                i;
	char*                p = NULL;
	char*                prot = NULL;
	char*                reason = NULL;
	char*                host = NULL;
	char*                ip_addr = NULL;
	char*                from = NULL;
	char*                fname = NULL;
	jsint                duration = 0;
	jsrefcount           rc;
	BOOL                 ret;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
	for (i = 0; i < argc && fname == NULL; i++) {
		if (JSVAL_IS_NUMBER(argv[i])) {
			JS_ValueToInt32(cx, argv[i], &duration);
			continue;
		}
		if (!JSVAL_IS_STRING(argv[i]))
			continue;
		JSVALUE_TO_MSTRING(cx, argv[i], p, NULL);
		if (JS_IsExceptionPending(cx) || p == NULL) {
			free(prot);
			free(reason);
			free(host);
			free(ip_addr);
			free(from);
			free(p);
			return JS_FALSE;
		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;
	rc = JS_SUSPENDREQUEST(cx);
	ret = filter_ip(sys->cfg, prot, reason, host, ip_addr, from, fname, duration);
	free(prot);
	free(reason);
	free(host);
	free(ip_addr);
	free(from);
	free(fname);
deuce's avatar
deuce committed
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
static JSBool
js_get_node(JSContext *cx, uintN argc, jsval *arglist)
{
	char                 str[128];
	JSObject*            obj = JS_THIS_OBJECT(cx, arglist);
	JSObject*            nodeobj;
	jsval*               argv = JS_ARGV(cx, arglist);
	node_t               node = {0};
	int32                node_num;
	jsrefcount           rc;

	JS_SET_RVAL(cx, arglist, JSVAL_NULL);

	js_system_private_t* sys;
	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
	scfg_t*              cfg = sys->cfg;
	node_num = cfg->node_num;
	if (argc)  {
		if (!JS_ValueToInt32(cx, argv[0], &node_num))
			return JS_TRUE;
	}
	if (node_num < 1)
		node_num = 1;
	rc = JS_SUSPENDREQUEST(cx);
	int retval = getnodedat(sys->cfg, node_num, &node, /* lockit: */ FALSE, &sys->nodefile);
	sys->nodegets++;
	JS_RESUMEREQUEST(cx, rc);
		JS_ReportError(cx, "getnodat(%d) returned %d", node_num, retval);
		return JS_TRUE;
	}
	if ((nodeobj = JS_NewObject(cx, NULL, NULL, obj)) == NULL) {
		JS_ReportError(cx, "JS_NewObject failure");
		return JS_TRUE;
	}
	JS_DefineProperty(cx, nodeobj, "status", INT_TO_JSVAL((int)node.status), NULL, NULL, JSPROP_ENUMERATE);
	JS_DefineProperty(cx, nodeobj, "vstatus", STRING_TO_JSVAL(JS_NewStringCopyZ(cx, node_vstatus(sys->cfg, &node, str, sizeof str))), NULL, NULL, JSPROP_ENUMERATE);
	JS_DefineProperty(cx, nodeobj, "errors", INT_TO_JSVAL((int)node.errors), NULL, NULL, JSPROP_ENUMERATE);
	JS_DefineProperty(cx, nodeobj, "action", INT_TO_JSVAL((int)node.action), NULL, NULL, JSPROP_ENUMERATE);
	JS_DefineProperty(cx, nodeobj, "activity", STRING_TO_JSVAL(JS_NewStringCopyZ(cx, node_activity(sys->cfg, &node, str, sizeof str, node_num))), NULL, NULL, JSPROP_ENUMERATE);
	JS_DefineProperty(cx, nodeobj, "useron", INT_TO_JSVAL((int)node.useron), NULL, NULL, JSPROP_ENUMERATE);
	JS_DefineProperty(cx, nodeobj, "connection", INT_TO_JSVAL((int)node.connection), NULL, NULL, JSPROP_ENUMERATE);
	JS_DefineProperty(cx, nodeobj, "misc", INT_TO_JSVAL((int)node.misc), NULL, NULL, JSPROP_ENUMERATE);
	JS_DefineProperty(cx, nodeobj, "aux", INT_TO_JSVAL((int)node.aux), NULL, NULL, JSPROP_ENUMERATE);
	JS_DefineProperty(cx, nodeobj, "extaux", INT_TO_JSVAL((int)node.extaux), NULL, NULL, JSPROP_ENUMERATE);
	JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(nodeobj));
	return JS_TRUE;
}

js_get_node_message(JSContext *cx, uintN argc, jsval *arglist)
	JSObject *           obj = JS_THIS_OBJECT(cx, arglist);
	jsval *              argv = JS_ARGV(cx, arglist);
	char*                buf;
	int32                node_num;
	JSString*            js_str;
	jsrefcount           rc;
	JS_SET_RVAL(cx, arglist, JSVAL_NULL);
	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
	scfg_t*              cfg = sys->cfg;
	node_num = cfg->node_num;
	if (argc)
		JS_ValueToInt32(cx, argv[0], &node_num);
	if (node_num < 1)
		node_num = 1;
	rc = JS_SUSPENDREQUEST(cx);
	buf = getnmsg(sys->cfg, node_num);
	js_str = JS_NewStringCopyZ(cx, buf);
	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
js_put_node_message(JSContext *cx, uintN argc, jsval *arglist)
	JSObject *           obj = JS_THIS_OBJECT(cx, arglist);
	jsval *              argv = JS_ARGV(cx, arglist);
	int32                node = 1;
	JSString*            js_msg;
	char*                msg = NULL;
	jsrefcount           rc;
	BOOL                 ret;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
	JS_ValueToInt32(cx, argv[0], &node);
	if (node < 1)
		node = 1;
	if ((js_msg = JS_ValueToString(cx, argv[1])) == NULL)
deuce's avatar
deuce committed
	JSSTRING_TO_MSTRING(cx, js_msg, msg, NULL);
	HANDLE_PENDING(cx, msg);
	rc = JS_SUSPENDREQUEST(cx);
	ret = putnmsg(sys->cfg, node, msg) == 0;
deuce's avatar
deuce committed
	free(msg);
deuce's avatar
deuce committed
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
js_get_telegram(JSContext *cx, uintN argc, jsval *arglist)
	JSObject *           obj = JS_THIS_OBJECT(cx, arglist);
	jsval *              argv = JS_ARGV(cx, arglist);
	char*                buf;
	int32                usernumber = 1;
	JSString*            js_str;
	jsrefcount           rc;
	JS_SET_RVAL(cx, arglist, JSVAL_NULL);
	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
	JS_ValueToInt32(cx, argv[0], &usernumber);
	if (usernumber < 1)
		usernumber = 1;
	rc = JS_SUSPENDREQUEST(cx);
	buf = getsmsg(sys->cfg, usernumber);
	js_str = JS_NewStringCopyZ(cx, buf);
	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
js_put_telegram(JSContext *cx, uintN argc, jsval *arglist)
	JSObject *           obj = JS_THIS_OBJECT(cx, arglist);
	jsval *              argv = JS_ARGV(cx, arglist);
	int32                usernumber = 1;
	JSString*            js_msg;
	char*                msg = NULL;
	jsrefcount           rc;
	BOOL                 ret;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
	JS_ValueToInt32(cx, argv[0], &usernumber);
	if (usernumber < 1)
		usernumber = 1;
	if ((js_msg = JS_ValueToString(cx, argv[1])) == NULL)
deuce's avatar
deuce committed
	JSSTRING_TO_MSTRING(cx, js_msg, msg, NULL);
	HANDLE_PENDING(cx, msg);
	rc = JS_SUSPENDREQUEST(cx);
	ret = putsmsg(sys->cfg, usernumber, msg) == 0;
deuce's avatar
deuce committed
	free(msg);
deuce's avatar
deuce committed
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
static JSBool
js_notify(JSContext *cx, uintN argc, jsval *arglist)
{
	JSObject *           obj = JS_THIS_OBJECT(cx, arglist);
	jsval *              argv = JS_ARGV(cx, arglist);
	int32                usernumber = 1;
	JSString*            js_subj;
	JSString*            js_msg;
	char*                subj;
	char*                msg = NULL;
	jsrefcount           rc;
	BOOL                 ret;

	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	js_system_private_t* sys;
	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
	JS_ValueToInt32(cx, argv[0], &usernumber);
	if (usernumber < 1)
		usernumber = 1;
	if ((js_subj = JS_ValueToString(cx, argv[1])) == NULL)
	if (argc > 2) {
		if ((js_msg = JS_ValueToString(cx, argv[2])) == NULL)
			return JS_FALSE;

		JSSTRING_TO_MSTRING(cx, js_msg, msg, NULL);
		HANDLE_PENDING(cx, msg);
			return JS_TRUE;
	}

	JSSTRING_TO_MSTRING(cx, js_subj, subj, NULL);
	HANDLE_PENDING(cx, subj);
	if (subj == NULL) {
	rc = JS_SUSPENDREQUEST(cx);
	ret = notify(sys->cfg, usernumber, subj, msg) == 0;
	free(subj);
	free(msg);
	JS_RESUMEREQUEST(cx, rc);
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));

	return JS_TRUE;
}

js_new_user(JSContext *cx, uintN argc, jsval *arglist)
	JSObject *           obj = JS_THIS_OBJECT(cx, arglist);
	jsval *              argv = JS_ARGV(cx, arglist);
	char*                alias;
	int                  i;
	uintN                n;
	user_t               user;
	JSObject*            userobj;
	JSObject*            objarg;
	JSClass*             cl;
	jsrefcount           rc;
	client_t*            client = NULL;
	jsval                val;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
	scfg_t*              cfg = sys->cfg;
	if (!js_argc(cx, argc, 1))
	if (JSVAL_NULL_OR_VOID(argv[0])) {
		JS_ReportError(cx, "Invalid argument");
		return JS_FALSE;
	}
	JSVALUE_TO_ASTRING(cx, argv[0], alias, LEN_ALIAS + 2, NULL);
	rc = JS_SUSPENDREQUEST(cx);
	if (!check_name(cfg, alias)) {
		JS_ReportError(cx, "Invalid or duplicate user alias: %s", alias);
	memset(&user, 0, sizeof(user));
	for (n = 0; n < argc; n++) {
		if (JSVAL_IS_OBJECT(argv[n])) {
			objarg = JSVAL_TO_OBJECT(argv[n]);
			if (objarg != NULL && (cl = JS_GetClass(cx, objarg)) != NULL && strcmp(cl->name, "Client") == 0) {
				client = JS_GetPrivate(cx, objarg);
	// Find and use the global client object if possible...
	if (client == NULL) {
		if (JS_GetProperty(cx, JS_GetGlobalObject(cx), "client", &val) && !JSVAL_NULL_OR_VOID(val)) {
			if (objarg != NULL && (cl = JS_GetClass(cx, objarg)) != NULL && strcmp(cl->name, "Client") == 0)
				client = JS_GetPrivate(cx, objarg);
	if (client != NULL) {
		SAFECOPY(user.modem, client->protocol);
		SAFECOPY(user.comp, client->host);
		SAFECOPY(user.ipaddr, client->addr);
	SAFECOPY(user.alias, alias);
	newuserdefaults(cfg, &user);
	i = newuserdat(cfg, &user);
	if (i == 0) {
		userobj = js_CreateUserObject(cx, obj, NULL, &user, /* client: */ NULL, /* global_user: */ FALSE, (struct mqtt*)NULL);
		JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(userobj));
		JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(i));
static JSBool
js_del_user(JSContext *cx, uintN argc, jsval *arglist)
{
	JSObject *           obj = JS_THIS_OBJECT(cx, arglist);
	jsval *              argv = JS_ARGV(cx, arglist);
	jsrefcount           rc;
	int32                n;
	user_t               user;
	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
	if (!JS_ValueToInt32(cx, argv[0], &n))
	user.number = n;
	rc = JS_SUSPENDREQUEST(cx);
	JS_SET_RVAL(cx, arglist, JSVAL_FALSE);  /* fail, by default */
	if (getuserdat(sys->cfg, &user) == 0
	    && putusermisc(sys->cfg, n, user.misc | DELETED) == 0
	    && putusername(sys->cfg, n, nulstr) == 0)
		JS_SET_RVAL(cx, arglist, JSVAL_TRUE);   /* success */
js_sys_exec(JSContext *cx, uintN argc, jsval *arglist)
	jsval *    argv = JS_ARGV(cx, arglist);
	jsrefcount rc;
	char *     cmd = NULL;
	int        ret;
deuce's avatar
deuce committed
	JSVALUE_TO_MSTRING(cx, argv[0], cmd, NULL);
	HANDLE_PENDING(cx, cmd);
deuce's avatar
deuce committed
		JS_ReportError(cx, "Illegal NULL command");
		return JS_FALSE;
	}
		free(cmd);
		JS_ReportError(cx, "Missing or invalid argument");
		return JS_FALSE;
	}
	rc = JS_SUSPENDREQUEST(cx);
	ret = system(cmd);
deuce's avatar
deuce committed
	free(cmd);
deuce's avatar
deuce committed
	JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(ret));
js_popen(JSContext *cx, uintN argc, jsval *arglist)
	jsval *    argv = JS_ARGV(cx, arglist);
	char       str[1024];
	char*      cmd = NULL;
	FILE*      fp;
	jsint      line = 0;
	jsval      val;
	JSObject*  array;
	JSString*  js_str;
	jsrefcount rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if (!js_argc(cx, argc, 1))
	if (JSVAL_NULL_OR_VOID(argv[0])) {
		JS_ReportError(cx, "Invalid argument");
		return JS_FALSE;
	}
	if ((array = JS_NewArrayObject(cx, 0, NULL)) == NULL)
deuce's avatar
deuce committed
	JSVALUE_TO_MSTRING(cx, argv[0], cmd, NULL);
	HANDLE_PENDING(cx, cmd);
deuce's avatar
deuce committed
		JS_ReportError(cx, "Illegal NULL command");
		return JS_FALSE;
	}
	rc = JS_SUSPENDREQUEST(cx);
	if ((fp = popen(cmd, "r")) == NULL) {
deuce's avatar
deuce committed
		free(cmd);
deuce's avatar
deuce committed
	free(cmd);
	while (!feof(fp)) {
		if (fgets(str, sizeof(str), fp) == NULL)
		if ((js_str = JS_NewStringCopyZ(cx, str)) == NULL) {
			rc = JS_SUSPENDREQUEST(cx);
		val = STRING_TO_JSVAL(js_str);
		if (!JS_SetElement(cx, array, line++, &val)) {
			rc = JS_SUSPENDREQUEST(cx);
		rc = JS_SUSPENDREQUEST(cx);
	JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(array));
js_chksyspass(JSContext *cx, uintN argc, jsval *arglist)
	JSObject *           obj = JS_THIS_OBJECT(cx, arglist);
	jsval *              argv = JS_ARGV(cx, arglist);
	char *               pass;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
	JSVALUE_TO_ASTRING(cx, argv[0], pass, LEN_PASS + 2, NULL); // +2 is so overly long passwords fail.
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(stricmp(pass, sys->cfg->sys_pass) == 0));
js_chkname(JSContext *cx, uintN argc, jsval *arglist)
	JSObject * obj = JS_THIS_OBJECT(cx, arglist);
	jsval *    argv = JS_ARGV(cx, arglist);
	char*      str;
	jsrefcount rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	JSVALUE_TO_ASTRING(cx, argv[0], str, (LEN_ALIAS > LEN_NAME)?LEN_ALIAS + 2:LEN_NAME + 2, NULL);
	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
	rc = JS_SUSPENDREQUEST(cx);
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(check_name(sys->cfg, str)));

static JSBool
js_chkfname(JSContext *cx, uintN argc, jsval *arglist)
{
	JSObject * obj = JS_THIS_OBJECT(cx, arglist);
	jsval *    argv = JS_ARGV(cx, arglist);
	char*      fname = NULL;
	jsrefcount rc;
	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);