diff --git a/src/sbbs3/js_file_area.c b/src/sbbs3/js_file_area.c
index c75bf10096e03f2673bc86b6d7ab41b2db06fbc1..2d742aa50bb866e1e9802d4ba1a711d50c502330 100644
--- a/src/sbbs3/js_file_area.c
+++ b/src/sbbs3/js_file_area.c
@@ -8,7 +8,7 @@
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
  *																			*
- * Copyright 2003 Rob Swindell - http://www.synchro.net/copyright.html		*
+ * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html		*
  *																			*
  * This program is free software; you can redistribute it and/or			*
  * modify it under the terms of the GNU General Public License				*
@@ -42,7 +42,8 @@
 #ifdef _DEBUG
 
 static char* lib_prop_desc[] = {
-	 "library number"
+	 "index into lib_list array"
+	,"unique number for this library"
 	,"library name"
 	,"library description"
 	,"library access requirements"
@@ -52,7 +53,9 @@ static char* lib_prop_desc[] = {
 
 static char* dir_prop_desc[] = {
 
-	 "directory number"
+	 "index into dir_list array"
+	,"unique number for this directory"
+	,"library index"
 	,"library number"
 	,"library name"
 	,"directory internal code"
@@ -97,8 +100,9 @@ JSObject* DLLCALL js_CreateFileAreaObject(JSContext* cx, JSObject* parent, scfg_
 	JSObject*	dir_list;
 	JSString*	js_str;
 	jsval		val;
-	jsuint		index;
-	uint		l,d,ln,dn;
+	jsuint		lib_index;
+	jsuint		dir_index;
+	uint		l,d;
 
 	/* Return existing object if it's already been created */
 	if(JS_GetProperty(cx,parent,"file_area",&val) && val!=JSVAL_VOID)
@@ -151,7 +155,7 @@ JSObject* DLLCALL js_CreateFileAreaObject(JSContext* cx, JSObject* parent, scfg_
 	if(!JS_SetProperty(cx, areaobj, "lib_list", &val)) 
 		return(NULL);
 
-	for(l=ln=0;l<cfg->total_libs;l++) {
+	for(l=0;l<cfg->total_libs;l++) {
 #if 0
 		if(user==NULL && (*cfg->lib[l]->ar)!=AR_NULL)
 			continue;
@@ -162,11 +166,11 @@ JSObject* DLLCALL js_CreateFileAreaObject(JSContext* cx, JSObject* parent, scfg_
 		if((libobj=JS_NewObject(cx, NULL, NULL, NULL))==NULL)
 			return(NULL);
 
-		if(!JS_GetArrayLength(cx, lib_list, &index))
+		if(!JS_GetArrayLength(cx, lib_list, &lib_index))
 			return(NULL);
 
 		val=OBJECT_TO_JSVAL(libobj);
-		if(!JS_SetElement(cx, lib_list, index, &val))
+		if(!JS_SetElement(cx, lib_list, lib_index, &val))
 			return(NULL);
 
 		/* Add as property (associative array element) */
@@ -174,7 +178,11 @@ JSObject* DLLCALL js_CreateFileAreaObject(JSContext* cx, JSObject* parent, scfg_
 			,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE))
 			return(NULL);
 
-		val=INT_TO_JSVAL(ln);
+		val=INT_TO_JSVAL(lib_index);
+		if(!JS_SetProperty(cx, libobj, "index", &val))
+			return(NULL);
+
+		val=INT_TO_JSVAL(l);
 		if(!JS_SetProperty(cx, libobj, "number", &val))
 			return(NULL);
 
@@ -228,11 +236,11 @@ JSObject* DLLCALL js_CreateFileAreaObject(JSContext* cx, JSObject* parent, scfg_
 			if((dirobj=JS_NewObject(cx, NULL, NULL, NULL))==NULL)
 				return(NULL);
 
-			if(!JS_GetArrayLength(cx, dir_list, &index))	/* inexplicable exception here on Jul-6-2001 */
-				return(NULL);								/* and again on Aug-7-2001 and Oct-21-2001 */
+			if(!JS_GetArrayLength(cx, dir_list, &dir_index))
+				return(NULL);								
 
 			val=OBJECT_TO_JSVAL(dirobj);
-			if(!JS_SetElement(cx, dir_list, index, &val))
+			if(!JS_SetElement(cx, dir_list, dir_index, &val))
 				return(NULL);
 
 			/* Add as property (associative array element) */
@@ -240,12 +248,19 @@ JSObject* DLLCALL js_CreateFileAreaObject(JSContext* cx, JSObject* parent, scfg_
 				,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE))
 				return(NULL);
 
-			val=INT_TO_JSVAL(dn);
+			val=INT_TO_JSVAL(dir_index);
+			if(!JS_SetProperty(cx, dirobj, "index", &val))
+				return(NULL);
+
+			val=INT_TO_JSVAL(d);
 			if(!JS_SetProperty(cx, dirobj, "number", &val))
 				return(NULL);
-			dn++;
 
-			val=INT_TO_JSVAL(ln);
+			val=INT_TO_JSVAL(lib_index);
+			if(!JS_SetProperty(cx, dirobj, "lib_index", &val))
+				return(NULL);
+
+			val=INT_TO_JSVAL(cfg->dir[d]->lib);
 			if(!JS_SetProperty(cx, dirobj, "lib_number", &val))
 				return(NULL);
 
@@ -406,12 +421,11 @@ JSObject* DLLCALL js_CreateFileAreaObject(JSContext* cx, JSObject* parent, scfg_
 #ifdef _DEBUG
 		js_CreateArrayOfStrings(cx, libobj, "_property_desc_list", lib_prop_desc, JSPROP_READONLY);
 #endif
-		ln++;
 	}
 
 #ifdef _DEBUG
-	js_DescribeSyncObject(cx,alldirs,"Associative array of all libraries (use name as index)",312);
-	JS_DefineProperty(cx,alldirs,"_dont_document",JSVAL_TRUE,NULL,NULL,JSPROP_READONLY);
+	js_DescribeSyncObject(cx,alllibs,"Associative array of all libraries (use name as index)",312);
+	JS_DefineProperty(cx,alllibs,"_dont_document",JSVAL_TRUE,NULL,NULL,JSPROP_READONLY);
 #endif
 
 #ifdef _DEBUG
diff --git a/src/sbbs3/js_msg_area.c b/src/sbbs3/js_msg_area.c
index ed966ce054b89e21dbd21aa9f79ac10754a99fe0..8da3a50aabe7f38f9a3f789c4fa0c51995f7e5ea 100644
--- a/src/sbbs3/js_msg_area.c
+++ b/src/sbbs3/js_msg_area.c
@@ -8,7 +8,7 @@
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
  *																			*
- * Copyright 2003 Rob Swindell - http://www.synchro.net/copyright.html		*
+ * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html		*
  *																			*
  * This program is free software; you can redistribute it and/or			*
  * modify it under the terms of the GNU General Public License				*
@@ -46,7 +46,8 @@ enum {	/* msg_area Object Properties */
 #ifdef _DEBUG
 
 static char* msg_grp_prop_desc[] = {
-	 "group number"
+	 "index into grp_list array"
+	,"unique number for this message group"
 	,"group name"
 	,"group description"
 	,"group access requirements"
@@ -55,7 +56,9 @@ static char* msg_grp_prop_desc[] = {
 
 static char* msg_area_prop_desc[] = {
 
-	 "sub-board number"
+	 "index into sub_list array"
+	,"group's index into grp_list array"
+	,"unique number for this sub-board"
 	,"group number"
 	,"group name"
 	,"sub-board internal code"
@@ -89,8 +92,7 @@ static char* msg_area_prop_desc[] = {
 };
 #endif
 
-BOOL DLLCALL js_CreateMsgAreaProperties(JSContext* cx, scfg_t* cfg, JSObject* subobj, uint subnum
-										,uint usrgrpnum, uint usrsubnum)
+BOOL DLLCALL js_CreateMsgAreaProperties(JSContext* cx, scfg_t* cfg, JSObject* subobj, uint subnum)
 {
 	char		str[128];
 	int			c;
@@ -103,11 +105,11 @@ BOOL DLLCALL js_CreateMsgAreaProperties(JSContext* cx, scfg_t* cfg, JSObject* su
 
 	sub=cfg->sub[subnum];
 
-	if(!JS_DefineProperty(cx, subobj, "number", INT_TO_JSVAL(usrsubnum)
+	if(!JS_DefineProperty(cx, subobj, "number", INT_TO_JSVAL(subnum)
 		,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
 		return(FALSE);
 
-	if(!JS_DefineProperty(cx, subobj, "grp_number", INT_TO_JSVAL(usrgrpnum)
+	if(!JS_DefineProperty(cx, subobj, "grp_number", INT_TO_JSVAL(sub->grp)
 		,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
 		return(FALSE);
 
@@ -333,8 +335,9 @@ JSObject* DLLCALL js_CreateMsgAreaObject(JSContext* cx, JSObject* parent, scfg_t
 	JSObject*	sub_list;
 	JSString*	js_str;
 	jsval		val;
-	jsuint		index;
-	uint		l,d,gn,sn;
+	jsuint		grp_index;
+	jsuint		sub_index;
+	uint		l,d;
 
 	/* Return existing object if it's already been created */
 	if(JS_GetProperty(cx,parent,"msg_area",&val) && val!=JSVAL_VOID)
@@ -374,7 +377,7 @@ JSObject* DLLCALL js_CreateMsgAreaObject(JSContext* cx, JSObject* parent, scfg_t
 	if(!JS_SetProperty(cx, areaobj, "grp_list", &val)) 
 		return(NULL);
 
-	for(l=gn=0;l<cfg->total_grps;l++) {
+	for(l=0;l<cfg->total_grps;l++) {
 
 #if 0
 		if(user==NULL && (*cfg->grp[l]->ar)!=AR_NULL)
@@ -386,11 +389,11 @@ JSObject* DLLCALL js_CreateMsgAreaObject(JSContext* cx, JSObject* parent, scfg_t
 		if((grpobj=JS_NewObject(cx, NULL, NULL, NULL))==NULL)
 			return(NULL);
 
-		if(!JS_GetArrayLength(cx, grp_list, &index))
+		if(!JS_GetArrayLength(cx, grp_list, &grp_index))
 			return(NULL);
 
 		val=OBJECT_TO_JSVAL(grpobj);
-		if(!JS_SetElement(cx, grp_list, index, &val))
+		if(!JS_SetElement(cx, grp_list, grp_index, &val))
 			return(NULL);
 
 		/* Add as property (associative array element) */
@@ -398,7 +401,11 @@ JSObject* DLLCALL js_CreateMsgAreaObject(JSContext* cx, JSObject* parent, scfg_t
 			,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE))
 			return(NULL);
 
-		val=INT_TO_JSVAL(gn);
+		val=INT_TO_JSVAL(grp_index);
+		if(!JS_SetProperty(cx, grpobj, "index", &val))
+			return(NULL);
+
+		val=INT_TO_JSVAL(l);
 		if(!JS_SetProperty(cx, grpobj, "number", &val))
 			return(NULL);
 
@@ -448,11 +455,11 @@ JSObject* DLLCALL js_CreateMsgAreaObject(JSContext* cx, JSObject* parent, scfg_t
 			if(subscan!=NULL)
 				JS_SetPrivate(cx,subobj,&subscan[d]);
 
-			if(!JS_GetArrayLength(cx, sub_list, &index))
+			if(!JS_GetArrayLength(cx, sub_list, &sub_index))
 				return(NULL);							
 
 			val=OBJECT_TO_JSVAL(subobj);
-			if(!JS_SetElement(cx, sub_list, index, &val))
+			if(!JS_SetElement(cx, sub_list, sub_index, &val))
 				return(NULL);
 
 			/* Add as property (associative array element) */
@@ -460,7 +467,15 @@ JSObject* DLLCALL js_CreateMsgAreaObject(JSContext* cx, JSObject* parent, scfg_t
 				,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE))
 				return(NULL);
 
-			if(!js_CreateMsgAreaProperties(cx, cfg, subobj, d, gn, sn++))
+			val=INT_TO_JSVAL(sub_index);
+			if(!JS_SetProperty(cx, subobj, "index", &val))
+				return(NULL);
+
+			val=INT_TO_JSVAL(grp_index);
+			if(!JS_SetProperty(cx, subobj, "grp_index", &val))
+				return(NULL);
+
+			if(!js_CreateMsgAreaProperties(cx, cfg, subobj, d))
 				return(NULL);
 			
 			if(user==NULL || chk_ar(cfg,cfg->sub[d]->read_ar,user))
@@ -515,11 +530,10 @@ JSObject* DLLCALL js_CreateMsgAreaObject(JSContext* cx, JSObject* parent, scfg_t
 #ifdef _DEBUG
 		js_CreateArrayOfStrings(cx, grpobj, "_property_desc_list", msg_grp_prop_desc, JSPROP_READONLY);
 #endif
-		gn++;
 	}
 
 #ifdef _DEBUG
-	js_DescribeSyncObject(cx,allsubs,"Associative array of all groups (use name as index)",312);
+	js_DescribeSyncObject(cx,allgrps,"Associative array of all groups (use name as index)",312);
 	JS_DefineProperty(cx,allgrps,"_dont_document",JSVAL_TRUE,NULL,NULL,JSPROP_READONLY);
 #endif
 
diff --git a/src/sbbs3/js_xtrn_area.c b/src/sbbs3/js_xtrn_area.c
index 2372e7c039db8688c17de50d4632de9b383ceffa..b110413f46b34f536ad4f09a85f1ccd56d67d204 100644
--- a/src/sbbs3/js_xtrn_area.c
+++ b/src/sbbs3/js_xtrn_area.c
@@ -8,7 +8,7 @@
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
  *																			*
- * Copyright 2003 Rob Swindell - http://www.synchro.net/copyright.html		*
+ * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html		*
  *																			*
  * This program is free software; you can redistribute it and/or			*
  * modify it under the terms of the GNU General Public License				*
@@ -43,7 +43,8 @@
 
 static char* xtrn_sec_prop_desc[] = {
 
-	 "external program section number"
+	 "index into sec_list array"
+	,"unique number for this external program section"
 	,"external program section internal code"
 	,"external program section name"
 	,"external program section access requirements"
@@ -52,7 +53,12 @@ static char* xtrn_sec_prop_desc[] = {
 
 static char* xtrn_prog_prop_desc[] = {
 
-	 "internal code"
+	 "index into prog_list array"
+	,"program number"
+	,"progarm section index"
+	,"program section number"
+	,"program section internal code"
+	,"internal code"
 	,"name"
 	,"command-line"
 	,"clean-up command-line"
@@ -66,8 +72,6 @@ static char* xtrn_prog_prop_desc[] = {
 	,"maximum time allowed in program"
 	,"execution cost (credits to run this program)"
 	/* Insert here */
-	,"program number"
-	,"program section number"
 	,"user has sufficient access to run this program"
 	,NULL
 };
@@ -180,6 +184,7 @@ JSObject* DLLCALL js_CreateXtrnAreaObject(JSContext* cx, JSObject* parent, scfg_
 										  ,user_t* user)
 {
 	JSObject*	areaobj;
+	JSObject*	allsec;
 	JSObject*	allprog;
 	JSObject*	secobj;
 	JSObject*	progobj;
@@ -191,7 +196,8 @@ JSObject* DLLCALL js_CreateXtrnAreaObject(JSContext* cx, JSObject* parent, scfg_
 	JSObject*	prog_list;
 	JSString*	js_str;
 	jsval		val;
-	jsuint		index;
+	jsuint		sec_index;
+	jsuint		prog_index;
 	uint		l,d;
 
 	/* Return existing object if it's already been created */
@@ -208,6 +214,15 @@ JSObject* DLLCALL js_CreateXtrnAreaObject(JSContext* cx, JSObject* parent, scfg_
 	js_DescribeSyncObject(cx,areaobj,"External Program Areas",310);
 #endif
 
+	/* xtrn_area.sec[] */
+	if((allsec=JS_NewObject(cx,NULL,NULL,areaobj))==NULL)
+		return(NULL);
+
+	val=OBJECT_TO_JSVAL(allsec);
+	if(!JS_SetProperty(cx, areaobj, "sec", &val))
+		return(NULL);
+
+	/* xtrn_area.prog[] */
 	if((allprog=JS_NewObject(cx,NULL,NULL,areaobj))==NULL)
 		return(NULL);
 
@@ -215,7 +230,7 @@ JSObject* DLLCALL js_CreateXtrnAreaObject(JSContext* cx, JSObject* parent, scfg_
 	if(!JS_SetProperty(cx, areaobj, "prog", &val))
 		return(NULL);
 
-	/* sec_list[] */
+	/* xtrn_area.sec_list[] */
 	if((sec_list=JS_NewArrayObject(cx, 0, NULL))==NULL) 
 		return(NULL);
 
@@ -234,11 +249,20 @@ JSObject* DLLCALL js_CreateXtrnAreaObject(JSContext* cx, JSObject* parent, scfg_
 		if((secobj=JS_NewObject(cx, NULL, NULL, NULL))==NULL)
 			return(NULL);
 
-		if(!JS_GetArrayLength(cx, sec_list, &index))
+		if(!JS_GetArrayLength(cx, sec_list, &sec_index))
 			return(NULL);
 
 		val=OBJECT_TO_JSVAL(secobj);
-		if(!JS_SetElement(cx, sec_list, index, &val))
+		if(!JS_SetElement(cx, sec_list, sec_index, &val))
+			return(NULL);
+
+		/* Add as property (associative array element) */
+		if(!JS_DefineProperty(cx, allsec, cfg->xtrnsec[l]->code, val
+			,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE))
+			return(NULL);
+
+		val=INT_TO_JSVAL(sec_index);
+		if(!JS_SetProperty(cx, secobj, "index", &val))
 			return(NULL);
 
 		val=INT_TO_JSVAL(l);
@@ -288,11 +312,11 @@ JSObject* DLLCALL js_CreateXtrnAreaObject(JSContext* cx, JSObject* parent, scfg_
 			if((progobj=JS_NewObject(cx, NULL, NULL, NULL))==NULL)
 				return(NULL);
 
-			if(!JS_GetArrayLength(cx, prog_list, &index))
+			if(!JS_GetArrayLength(cx, prog_list, &prog_index))
 				return(NULL);							
 
 			val=OBJECT_TO_JSVAL(progobj);
-			if(!JS_SetElement(cx, prog_list, index, &val))
+			if(!JS_SetElement(cx, prog_list, prog_index, &val))
 				return(NULL);
 
 			/* Add as property (associative array element) */
@@ -300,21 +324,33 @@ JSObject* DLLCALL js_CreateXtrnAreaObject(JSContext* cx, JSObject* parent, scfg_
 				,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE))
 				return(NULL);
 
-			if(!js_CreateXtrnProgProperties(cx, progobj, cfg->xtrn[d]))
+			val=INT_TO_JSVAL(prog_index);
+			if(!JS_SetProperty(cx, progobj, "index", &val))
 				return(NULL);
 
 			val=INT_TO_JSVAL(d);
 			if(!JS_SetProperty(cx, progobj, "number", &val))
 				return(NULL);
 
-			val=INT_TO_JSVAL(cfg->xtrn[d]->sec);
+			val=INT_TO_JSVAL(sec_index);
+			if(!JS_SetProperty(cx, progobj, "sec_index", &val))
+				return(NULL);
+
+			val=INT_TO_JSVAL(l);
 			if(!JS_SetProperty(cx, progobj, "sec_number", &val))
 				return(NULL);
 
+			val=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,cfg->xtrnsec[l]->code));
+			if(!JS_SetProperty(cx, progobj, "sec_code", &val))
+				return(NULL);
+
+			if(!js_CreateXtrnProgProperties(cx, progobj, cfg->xtrn[d]))
+				return(NULL);
+
 			if(user==NULL || chk_ar(cfg,cfg->xtrn[d]->run_ar,user))
-				val=BOOLEAN_TO_JSVAL(JS_TRUE);
+				val=JSVAL_TRUE;
 			else
-				val=BOOLEAN_TO_JSVAL(JS_FALSE);
+				val=JSVAL_FALSE;
 			if(!JS_SetProperty(cx, progobj, "can_run", &val))
 				return(NULL);
 
@@ -330,6 +366,10 @@ JSObject* DLLCALL js_CreateXtrnAreaObject(JSContext* cx, JSObject* parent, scfg_
 	}
 
 #ifdef _DEBUG
+
+	js_DescribeSyncObject(cx,allsec,"Associative array of all external program sections (use internal code as index)",312);
+	JS_DefineProperty(cx,allsec,"_dont_document",JSVAL_TRUE,NULL,NULL,JSPROP_READONLY);
+
 	js_DescribeSyncObject(cx,allprog,"Associative array of all external programs (use internal code as index)",311);
 	JS_DefineProperty(cx,allprog,"_dont_document",JSVAL_TRUE,NULL,NULL,JSPROP_READONLY);
 #endif
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index fa6ec0d357cc73a7a2f39d697ed015a337d1bc05..097afa3fed59f5d38ff5622436628653f950417f 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -987,8 +987,7 @@ extern "C" {
 	DLLEXPORT JSObject* DLLCALL js_CreateMsgAreaObject(JSContext* cx, JSObject* parent, scfg_t* cfg
 													,user_t* user, subscan_t* subscan);
 	DLLEXPORT BOOL		DLLCALL js_CreateMsgAreaProperties(JSContext* cx, scfg_t* cfg
-													,JSObject* subobj, uint subnum
-													,uint usrgrpnum, uint usrsubnum);
+													,JSObject* subobj, uint subnum);
 
 	/* js_xtrn_area.c */
 	DLLEXPORT JSObject* DLLCALL js_CreateXtrnAreaObject(JSContext* cx, JSObject* parent, scfg_t* cfg