diff --git a/src/sbbs3/js_system.c b/src/sbbs3/js_system.c
index 456b0d15890b8bac4cde8f1819fba2480ca7eaee..52cc72e556bc31354bb2976e34ac1a5ade534996 100644
--- a/src/sbbs3/js_system.c
+++ b/src/sbbs3/js_system.c
@@ -813,7 +813,8 @@ js_matchuserdata(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *r
 	int			len;
 	scfg_t*		cfg;
 	jsrefcount	rc;
-	BOOL		match_all=FALSE;
+	BOOL		match_next=FALSE;
+	int 		argnum=2;
 
 	if((cfg=(scfg_t*)JS_GetPrivate(cx,obj))==NULL)
 		return(JS_FALSE);
@@ -832,45 +833,82 @@ js_matchuserdata(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *r
 		return(JS_TRUE);
 	}
 
-	if(argc>2)
-		JS_ValueToInt32(cx,argv[2],&usernumber);
+	if(JSVAL_IS_NUMBER(argv[argnum]))
+		JS_ValueToInt32(cx, argv[argnum++], &usernumber);
+	if(JSVAL_IS_BOOLEAN(argv[argnum]))
+		JS_ValueToBoolean(cx, argv[argnum], &match_next);
 		
 	if((p=JS_GetStringBytes(js_str))==NULL) {
 		*rval = INT_TO_JSVAL(0);
 		return(JS_TRUE);
 	}
 	
-	if(argc > 3)
-		JS_ValueToBoolean(cx,argv[3],&match_all);
+	rc=JS_SUSPENDREQUEST(cx);
+	*rval = INT_TO_JSVAL(userdatdupe(cfg,usernumber,offset,len,p,FALSE,match_next));
+	JS_RESUMEREQUEST(cx, rc);
+	return(JS_TRUE);
+}
+
+static JSBool
+js_matchallusers(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+	char*		p;
+	JSString*	js_str;
+	int32		offset=0;
+	int32		usernumber=0;
+	int			len;
+	scfg_t*		cfg;
+	jsrefcount	rc;
+	JSObject* 	array;
+	jsval		val;
+	int 		result;
+	jsint 		line=0;
+
+	if((cfg=(scfg_t*)JS_GetPrivate(cx,obj))==NULL)
+		return(JS_FALSE);
+
+	JS_ValueToInt32(cx,argv[0],&offset);
+	rc=JS_SUSPENDREQUEST(cx);
+	len=user_rec_len(offset);
+	JS_RESUMEREQUEST(cx, rc);
+	
+	if(len<0) {
+		JS_ReportError(cx,"Invalid user data offset: %d", offset);
+		return(JS_FALSE);
+	}
+
+	if((js_str=JS_ValueToString(cx, argv[1]))==NULL) {
+		*rval = INT_TO_JSVAL(0);
+		return(JS_TRUE);
+	}
+
+	if((p=JS_GetStringBytes(js_str))==NULL) {
+		*rval = INT_TO_JSVAL(0);
+		return(JS_TRUE);
+	}
 	
-	if(match_all == FALSE) {
+	if((array=JS_NewArrayObject(cx,0,NULL))==NULL)
+		return(JS_FALSE);
+		
+	while(1) {
 		rc=JS_SUSPENDREQUEST(cx);
-		*rval = INT_TO_JSVAL(userdatdupe(cfg,usernumber,offset,len,p,FALSE,FALSE));
-		JS_RESUMEREQUEST(cx, rc);
-	} else {
-		JSObject* 	array;
-		jsval		val;
-		int 		retval;
-		jsint 		line=0;
-		if((array=JS_NewArrayObject(cx,0,NULL))==NULL)
-			return(JS_FALSE);
-		while(1) {
-			rc=JS_SUSPENDREQUEST(cx);
-			retval=userdatdupe(cfg,usernumber++,offset,len,p,FALSE,TRUE);
-			if(retval > 0) {
-				val = INT_TO_JSVAL(retval);
-				if(!JS_SetElement(cx, array, line++, &val)) {
-					JS_RESUMEREQUEST(cx, rc);
-					break;
-				}
-				usernumber=retval;
-				retval=0;
-			} else
+		result=userdatdupe(cfg,usernumber,offset,len,p,FALSE,TRUE);
+		if(result > 0) {
+			val = INT_TO_JSVAL(result);
+			if(!JS_SetElement(cx, array, line++, &val)) {
+				JS_RESUMEREQUEST(cx, rc);
 				break;
+			}
+			usernumber=result;
+			result=0;
+		} else {
 			JS_RESUMEREQUEST(cx, rc);
+			break;
 		}
-		*rval = OBJECT_TO_JSVAL(array);
+		JS_RESUMEREQUEST(cx, rc);
 	}
+	
+	*rval = OBJECT_TO_JSVAL(array);
 	return(JS_TRUE);
 }
 
@@ -1559,12 +1597,17 @@ static jsSyncMethodSpec js_system_functions[] = {
 		" or 0 if not found, matches well-known sysop aliases by default")
 	,310
 	},		
-	{"matchuserdata",	js_matchuserdata,	2,	JSTYPE_ARRAY,	JSDOCSTR("field, data [,usernumber, match_all=<tt>false</tt>]")
-	,JSDOCSTR("search user database for data in a specific field (specified by offset), "
+	{"matchuserdata",	js_matchuserdata,	2,	JSTYPE_NUMBER,	JSDOCSTR("field, data [,usernumber, match_next=<tt>false</tt>]")
+	,JSDOCSTR("search user database for data in a specific field (see <tt>U_*</tt> in <tt>sbbsdefs.js</tt>), "
 		"returns first matching user record number, optional <i>usernumber</i> specifies user record to skip, "
-		"or record at which to begin searching if optional match_all is <i>true</i>")
+		"or record at which to begin searching if optional <i>match_next</i> is <tt>true</tt>")
 	,310
 	},
+	{"matchallusers",	js_matchallusers,	2,	JSTYPE_ARRAY,	JSDOCSTR("field, data")
+	,JSDOCSTR("search user database for data in a specific field (see <tt>U_*</tt> in <tt>sbbsdefs.js</tt>), "
+		"returns an array of matching user record numbers")
+	,315
+	},
 	{"trashcan",		js_trashcan,		2,	JSTYPE_BOOLEAN,	JSDOCSTR("path/filename, find_string")
 	,JSDOCSTR("search text/filename.can for pseudo-regexp")
 	,310
@@ -1636,7 +1679,7 @@ static jsSyncMethodSpec js_system_functions[] = {
 	,311
 	},
 	{"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")
+	,JSDOCSTR("compares the supplied <i>password</i> against the system password and returns <i>true</i> if it matches")
 	,311
 	},
 	{"check_name",		js_chkname,			1,	JSTYPE_BOOLEAN,	JSDOCSTR("name/alias")