From 7f9b4c1b5ff655f67b274afdf9212e2a2b0805a0 Mon Sep 17 00:00:00 2001
From: "Rob Swindell (on Windows 11)" <rob@synchro.net>
Date: Thu, 10 Apr 2025 23:36:10 -0700
Subject: [PATCH] Add new methods: system.check_realname() and
 system.check_password()

These are wrappers around the userdat API functions, suitable for servers
to do prospective new user string validation.
---
 src/sbbs3/js_system.c | 64 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/src/sbbs3/js_system.c b/src/sbbs3/js_system.c
index 5b2ebc7e07..fe72db1320 100644
--- a/src/sbbs3/js_system.c
+++ b/src/sbbs3/js_system.c
@@ -2038,6 +2038,62 @@ js_chkname(JSContext *cx, uintN argc, jsval *arglist)
 	return JS_TRUE;
 }
 
+static JSBool
+js_chkrealname(JSContext *cx, uintN argc, jsval *arglist)
+{
+	JSObject * obj = JS_THIS_OBJECT(cx, arglist);
+	jsval *    argv = JS_ARGV(cx, arglist);
+	char*      str;
+	jsrefcount rc;
+
+	if (js_argcIsInsufficient(cx, argc, 1))
+		return JS_FALSE;
+	if (JSVAL_NULL_OR_VOID(argv[0])) {
+		JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
+		return JS_TRUE;
+	}
+	JSVALUE_TO_ASTRING(cx, argv[0], str, (LEN_ALIAS > LEN_NAME)?LEN_ALIAS + 2:LEN_NAME + 2, NULL);
+
+	js_system_private_t* sys;
+	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
+		return JS_FALSE;
+
+	rc = JS_SUSPENDREQUEST(cx);
+	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(check_realname(sys->cfg, str)));
+	JS_RESUMEREQUEST(cx, rc);
+
+	return JS_TRUE;
+}
+
+static JSBool
+js_chkpassword(JSContext *cx, uintN argc, jsval *arglist)
+{
+	JSObject * obj = JS_THIS_OBJECT(cx, arglist);
+	jsval *    argv = JS_ARGV(cx, arglist);
+	char*      str;
+	jsrefcount rc;
+
+	if (js_argcIsInsufficient(cx, argc, 1))
+		return JS_FALSE;
+	if (JSVAL_NULL_OR_VOID(argv[0])) {
+		JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
+		return JS_TRUE;
+	}
+	JSVALUE_TO_ASTRING(cx, argv[0], str, (LEN_ALIAS > LEN_NAME)?LEN_ALIAS + 2:LEN_NAME + 2, NULL);
+
+	js_system_private_t* sys;
+	if ((sys = (js_system_private_t*)js_GetClassPrivate(cx, obj, &js_system_class)) == NULL)
+		return JS_FALSE;
+
+	rc = JS_SUSPENDREQUEST(cx);
+	bool result = check_pass(sys->cfg, str, /* user: */NULL, /* unique: */false, /* reason: */NULL)
+		              && !trashcan(sys->cfg, str, "password");
+	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(result));
+	JS_RESUMEREQUEST(cx, rc);
+
+	return JS_TRUE;
+}
+
 static JSBool
 js_chkfname(JSContext *cx, uintN argc, jsval *arglist)
 {
@@ -2339,6 +2395,14 @@ static jsSyncMethodSpec js_system_functions[] = {
 	 , 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_realname",  js_chkrealname,     1,  JSTYPE_BOOLEAN, JSDOCSTR("name")
+	 , JSDOCSTR("Check that the provided real user name string is suitable for a new user account, "
+		        "returns <tt>true</tt> if it is valid")
+	 , 321},
+	{"check_password",  js_chkpassword,     1,  JSTYPE_BOOLEAN, JSDOCSTR("password")
+	 , JSDOCSTR("Check that the provided string is suitable for a new user password, "
+		        "returns <tt>true</tt> if it meets the system criteria for a user password")
+	 , 321},
 	{"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")
-- 
GitLab