From acd808d37895d4ea45a46ba561a1bc3a490ff21f Mon Sep 17 00:00:00 2001
From: Rob Swindell <rob@synchro.net>
Date: Fri, 28 Jan 2022 00:07:36 -0800
Subject: [PATCH] Use sbbs.ini [web] FileVPathPrefix to configure web filebase
 prefix

It bothered Deuce having a web server setting in scfg_t/SCFG->File Options, so I moved this setting to [web_]startup_t and the sbbs.ini file.

The downside is that file_area.web_file_prefix is no longer available to JS environments outside of the web server and terminal server, but meh, probably not going to use it elsewhere anyway? I can imagine use cases for JSexec scripts to want to generate URLs to filebase files. If that ends up being a need, they'll have to find and parse the "right" sbbs.ini file to determine the vpath prefix.
---
 src/sbbs3/js_file_area.c  | 31 +++++++++++++++----------------
 src/sbbs3/js_user.c       |  4 ++--
 src/sbbs3/main.cpp        |  4 ++--
 src/sbbs3/sbbs.h          |  4 ++--
 src/sbbs3/sbbs_ini.c      |  7 +++++++
 src/sbbs3/scfg/scfgxfr1.c | 20 --------------------
 src/sbbs3/scfgdefs.h      |  1 -
 src/sbbs3/scfglib2.c      |  5 +----
 src/sbbs3/scfgsave.c      |  6 +-----
 src/sbbs3/startup.h       |  1 +
 src/sbbs3/websrvr.c       | 10 +++++-----
 src/sbbs3/websrvr.h       |  1 +
 12 files changed, 37 insertions(+), 57 deletions(-)

diff --git a/src/sbbs3/js_file_area.c b/src/sbbs3/js_file_area.c
index 8b122e89f4..0f32966242 100644
--- a/src/sbbs3/js_file_area.c
+++ b/src/sbbs3/js_file_area.c
@@ -37,7 +37,7 @@ static char* lib_prop_desc[] = {
 	,"library name"
 	,"library description"
 	,"library access requirements"
-	,"library link (for HTML index)"
+	,"library virtual path (for FTP or HTTP access)"
 	,"user has sufficient access to this library's directories <i>(introduced in v3.18)</i>"
 	,"internal code prefix (for directories) <i>(introduced in v3.18c)</i>"
 	,NULL
@@ -70,7 +70,7 @@ static char* dir_prop_desc[] = {
 	,"configured maximum age (in days) of files before expiration"
 	,"percent of file size awarded uploader in credits upon file upload"
 	,"percent of file size awarded uploader in credits upon subsequent downloads"
-	,"directory link (for HTML index)"
+	,"virtual path (for FTP or HTTP access)"
 	,"number of files currently in this directory <i>(introduced in v3.18c)</i>"
 	,"timestamp of file base index of this directory <i>(introduced in v3.19)</i>"
 	,"user has sufficient access to view this directory (e.g. list files) <i>(introduced in v3.18)</i>"
@@ -89,7 +89,7 @@ struct js_file_area_priv {
 	scfg_t		*cfg;
 	user_t		*user;
 	client_t	*client;
-	char		*html_index_file;
+	const char	*web_file_prefix;
 	uint		dirnum;
 };
 
@@ -101,7 +101,6 @@ js_file_area_finalize(JSContext *cx, JSObject *obj)
 	if((p=(struct js_file_area_priv*)JS_GetPrivate(cx,obj))==NULL)
 		return;
 
-	free(p->html_index_file);
 	free(p);
 	JS_SetPrivate(cx,obj,NULL);
 }
@@ -234,9 +233,13 @@ JSBool js_file_area_resolve(JSContext* cx, JSObject* areaobj, jsid id)
 	if(name==NULL || strcmp(name, "web_vpath_prefix")==0) {
 		if(name)
 			free(name);
-		if((js_str=JS_NewStringCopyZ(cx, p->cfg->web_file_prefix))==NULL)
-			return JS_FALSE;
-		val=STRING_TO_JSVAL(js_str);
+		if(p->web_file_prefix == NULL)
+			val = JSVAL_VOID;
+		else {
+			if((js_str=JS_NewStringCopyZ(cx, p->web_file_prefix))==NULL)
+				return JS_FALSE;
+			val=STRING_TO_JSVAL(js_str);
+		}
 		JS_DefineProperty(cx, areaobj, "web_vpath_prefix", val, NULL, NULL, JSPROP_ENUMERATE);
 		if(name)
 			return(JS_TRUE);
@@ -322,7 +325,7 @@ JSBool js_file_area_resolve(JSContext* cx, JSObject* areaobj, jsid id)
 			if(!JS_SetProperty(cx, libobj, "ars", &val))
 				return JS_FALSE;
 
-			sprintf(vpath,"/%s/%s",p->cfg->lib[l]->vdir,p->html_index_file);
+			sprintf(vpath,"/%s/",p->cfg->lib[l]->vdir);
 			if((js_str=JS_NewStringCopyZ(cx, vpath))==NULL)
 				return JS_FALSE;
 			val=STRING_TO_JSVAL(js_str);
@@ -362,7 +365,6 @@ JSBool js_file_area_resolve(JSContext* cx, JSObject* areaobj, jsid id)
 					continue;
 				*np = *p;
 				np->dirnum = d;
-				np->html_index_file = NULL;
 				JS_SetPrivate(cx, dirobj, np);
 
 				val=OBJECT_TO_JSVAL(dirobj);
@@ -529,10 +531,10 @@ JSBool js_file_area_resolve(JSContext* cx, JSObject* areaobj, jsid id)
 				if(!JS_SetProperty(cx, dirobj, "download_credit_pct", &val))
 					return JS_FALSE;
 
-				sprintf(vpath,"/%s/%s/%s"
+				sprintf(vpath,"/%s/%s/"
 					,p->cfg->lib[l]->vdir
 					,p->cfg->dir[d]->vdir
-					,p->html_index_file);
+					);
 				if((js_str=JS_NewStringCopyZ(cx, vpath))==NULL)
 					return JS_FALSE;
 				val=STRING_TO_JSVAL(js_str);
@@ -634,7 +636,7 @@ static JSClass js_file_area_class = {
 };
 
 DLLEXPORT JSObject* js_CreateFileAreaObject(JSContext* cx, JSObject* parent, scfg_t* cfg
-					,user_t* user, client_t* client, char* html_index_file) {
+					,user_t* user, client_t* client, const char* web_file_prefix) {
 	JSObject* obj;
 	struct js_file_area_priv *p;
 
@@ -652,12 +654,9 @@ DLLEXPORT JSObject* js_CreateFileAreaObject(JSContext* cx, JSObject* parent, scf
 	p->cfg = cfg;
 	p->user = user;
 	p->client = client;
-	if (html_index_file == NULL)
-		html_index_file = "";
-	p->html_index_file = strdup(html_index_file);
+	p->web_file_prefix = web_file_prefix;
 
 	if(!JS_SetPrivate(cx, obj, p)) {
-		free(p->html_index_file);
 		free(p);
 		return(NULL);
 	}
diff --git a/src/sbbs3/js_user.c b/src/sbbs3/js_user.c
index f59af948e3..fc3ab8c314 100644
--- a/src/sbbs3/js_user.c
+++ b/src/sbbs3/js_user.c
@@ -1660,11 +1660,11 @@ JSObject* js_CreateUserObject(JSContext* cx, JSObject* parent, scfg_t* cfg, char
 /****************************************************************************/
 JSBool
 js_CreateUserObjects(JSContext* cx, JSObject* parent, scfg_t* cfg, user_t* user, client_t* client
-					 ,char* html_index_file, subscan_t* subscan)
+					 ,const char* web_file_vpath_prefix, subscan_t* subscan)
 {
 	if(js_CreateUserObject(cx,parent,cfg,"user",user,client,/* global_user */TRUE)==NULL)
 		return(JS_FALSE);
-	if(js_CreateFileAreaObject(cx,parent,cfg,user,client,html_index_file)==NULL) 
+	if(js_CreateFileAreaObject(cx,parent,cfg,user,client,web_file_vpath_prefix)==NULL) 
 		return(JS_FALSE);
 	if(js_CreateMsgAreaObject(cx,parent,cfg,user,client,subscan)==NULL) 
 		return(JS_FALSE);
diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp
index 00cc40e73f..79834ea5c0 100644
--- a/src/sbbs3/main.cpp
+++ b/src/sbbs3/main.cpp
@@ -1401,7 +1401,7 @@ bool sbbs_t::js_create_user_objects(JSContext* cx, JSObject* glob)
 	bool result = false;
 	if(cx != NULL) {
 		JS_BEGINREQUEST(cx);
-		if(!js_CreateUserObjects(cx, glob, &cfg, &useron, &client, NULL, subscan))
+		if(!js_CreateUserObjects(cx, glob, &cfg, &useron, &client, startup->web_file_vpath_prefix, subscan))
 			lprintf(LOG_ERR,"!JavaScript ERROR creating user objects");
 		else
 			result = true;
@@ -1506,7 +1506,7 @@ extern "C" BOOL js_CreateCommonObjects(JSContext* js_cx
 			break;
 
 		/* Area Objects */
-		if(!js_CreateUserObjects(js_cx, *glob, cfg, /* user: */NULL, client, /* html_index_fname: */NULL, /* subscan: */NULL))
+		if(!js_CreateUserObjects(js_cx, *glob, cfg, /* user: */NULL, client, startup->web_file_vpath_prefix, /* subscan: */NULL))
 			break;
 
 		success=TRUE;
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index 39f6823ee7..66320f60a5 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -1376,11 +1376,11 @@ extern "C" {
 	DLLEXPORT JSObject* js_CreateUserObject(JSContext* cx, JSObject* parent, scfg_t* cfg
 													,char* name, user_t* user, client_t* client, BOOL global_user);
 	DLLEXPORT JSBool	js_CreateUserObjects(JSContext* cx, JSObject* parent, scfg_t* cfg
-													,user_t* user, client_t* client, char* html_index_file
+													,user_t* user, client_t* client, const char* web_file_vpath_prefix
 													,subscan_t* subscan);
 	/* js_file_area.c */
 	DLLEXPORT JSObject* js_CreateFileAreaObject(JSContext* cx, JSObject* parent, scfg_t* cfg
-													,user_t* user, client_t* client, char* html_index_file);
+													,user_t* user, client_t* client, const char* web_file_vpath_prefix);
 
 	/* js_msg_area.c */
 	DLLEXPORT JSObject* js_CreateMsgAreaObject(JSContext* cx, JSObject* parent, scfg_t* cfg
diff --git a/src/sbbs3/sbbs_ini.c b/src/sbbs3/sbbs_ini.c
index d649714696..dcd5da9c4e 100644
--- a/src/sbbs3/sbbs_ini.c
+++ b/src/sbbs3/sbbs_ini.c
@@ -63,6 +63,7 @@ static const char*	strJavaScriptLoadPath		="JavaScriptLoadPath";
 static const char*	strJavaScriptOptions		="JavaScriptOptions";
 static const char*	strSemFileCheckFrequency	="SemFileCheckFrequency";
 static const char*	strIniFileName				="iniFileName";
+static const char*  strFileVpathPrefix			="FileVPathPrefix";
 
 #define DEFAULT_LOG_LEVEL				LOG_DEBUG
 #define DEFAULT_BIND_RETRY_COUNT		2
@@ -455,6 +456,8 @@ void sbbs_read_ini(
 
 		bbs->login_attempt = get_login_attempt_settings(list, section, global);
 		bbs->max_concurrent_connections = iniGetInteger(list, section, strMaxConConn, 0);
+
+		SAFECOPY(bbs->web_file_vpath_prefix, iniGetString(list, "web", strFileVpathPrefix, nulstr, value));
 	}
 
 	/***********************************************************************/
@@ -711,6 +714,8 @@ void sbbs_read_ini(
 			,iniGetString(list,section,"Authentication",WEB_DEFAULT_AUTH_LIST,value));
 		SAFECOPY(web->logfile_base
 			,iniGetString(list,section,"HttpLogFile",nulstr,value));
+		SAFECOPY(web->file_vpath_prefix
+			,iniGetString(list, section, strFileVpathPrefix, nulstr, value));
 
 		SAFECOPY(web->default_cgi_content
 			,iniGetString(list,section,"DefaultCGIContent",WEB_DEFAULT_CGI_CONTENT,value));
@@ -1263,6 +1268,8 @@ BOOL sbbs_write_ini(
 			break;
 		if(!iniSetString(lp,section,"HttpLogFile",web->logfile_base,&style))
 			break;
+		if(!iniSetString(lp,section,strFileVpathPrefix, web->file_vpath_prefix, &style))
+			break;
 
 		if(!iniSetString(lp,section,"DefaultCGIContent",web->default_cgi_content,&style))
 			break;
diff --git a/src/sbbs3/scfg/scfgxfr1.c b/src/sbbs3/scfg/scfgxfr1.c
index b81589fa19..b15e6ca0da 100644
--- a/src/sbbs3/scfg/scfgxfr1.c
+++ b/src/sbbs3/scfg/scfgxfr1.c
@@ -77,8 +77,6 @@ void xfer_opts()
 				,cfg.file_misc & FM_SPACES ? "In" : "Ex");
 		sprintf(opt[i++], "%-33.33s%u characters", "Allowed Filename Length", cfg.filename_maxlen);
 		sprintf(opt[i++], "%-33.33s%s", "Allowed Filename Characters", str);
-		sprintf(opt[i++], "%-33.33s%s", "Web File Virtual Path Prefix"
-			, cfg.web_file_prefix[0] ? cfg.web_file_prefix : "<disabled>");
 		strcpy(opt[i++],"Viewable Files...");
 		strcpy(opt[i++],"Testable Files...");
 		strcpy(opt[i++],"Download Events...");
@@ -298,24 +296,6 @@ void xfer_opts()
 						break;
 				}
 				break;
-			case __COUNTER__:
-				uifc.helpbuf=
-					"`Web File Virtual Path Prefix:`\n"
-					"\n"
-					"The virtual path prefix to your file transfer areas (filebases)\n"
-					"accessible via HTTP or HTTPS using the Synchronet Web Server.\n"
-					"\n"
-					"A prefix beginning and ending in a slash (e.g. `/files/`) is recommended.\n"
-					"\n"
-					"A prefix of just '`/`' would interpret `all` web requests as filebase access\n"
-					"requests.\n"
-					"\n"
-					"Setting this to an empty string disables access to your filebases from\n"
-					"the Synchronet Web Server.\n"
-				;
-				uifc.input(WIN_MID,0,0,"Web File Virtual Path Prefix"
-					,cfg.web_file_prefix, sizeof(cfg.web_file_prefix)-1, K_EDIT);
-				break;
 			case __COUNTER__: 	/* Viewable file types */
 				while(1) {
 					for(i=0;i<cfg.total_fviews && i<MAX_OPTS;i++)
diff --git a/src/sbbs3/scfgdefs.h b/src/sbbs3/scfgdefs.h
index 20535fa88a..f86c20517b 100644
--- a/src/sbbs3/scfgdefs.h
+++ b/src/sbbs3/scfgdefs.h
@@ -465,7 +465,6 @@ typedef struct
 	int32_t 		file_misc;			/* File Misc Settings */
 	int32_t			xtrn_misc;			/* External Programs Misc Settings */
 	uint16_t		filename_maxlen;	/* Maximum filename length */
-	char			web_file_prefix[33];
 
 	char			node_comspec[LEN_CMD+1];	/* DOS COMMAND.COM to use */
 	char			node_editor[LEN_CMD+1]; /* Local text editor command line to use */
diff --git a/src/sbbs3/scfglib2.c b/src/sbbs3/scfglib2.c
index 5be38d93d6..01f67e040a 100644
--- a/src/sbbs3/scfglib2.c
+++ b/src/sbbs3/scfglib2.c
@@ -61,11 +61,8 @@ BOOL read_file_cfg(scfg_t* cfg, char* error, size_t maxerrlen)
 	get_int(cfg->filename_maxlen, instream);
 	if(cfg->filename_maxlen == 0)
 		cfg->filename_maxlen = SMB_FILEIDX_NAMELEN;
-	get_str(cfg->web_file_prefix, instream);
 
-	// Padding (NULs):
-	get_int(c,instream);
-	for(i=0;i<12;i++)
+	for(i=0;i<29;i++)
 		get_int(n,instream);
 
 	/**************************/
diff --git a/src/sbbs3/scfgsave.c b/src/sbbs3/scfgsave.c
index 830d6b2f64..29d00d7ce9 100644
--- a/src/sbbs3/scfgsave.c
+++ b/src/sbbs3/scfgsave.c
@@ -661,12 +661,8 @@ BOOL write_file_cfg(scfg_t* cfg, int backup_level)
 	put_int(cfg->leech_sec,stream);
 	put_int(cfg->file_misc,stream);
 	put_int(cfg->filename_maxlen, stream);
-	put_str(cfg->web_file_prefix, stream);
-	// Padding (NULs)
-	c=0;
-	put_int(c, stream);
 	n=0;
-	for(i=0;i<12;i++)
+	for(i=0;i<29;i++)
 		put_int(n,stream);
 
 	/* Extractable File Types */
diff --git a/src/sbbs3/startup.h b/src/sbbs3/startup.h
index 6c0c5cba3f..b90e10e066 100644
--- a/src/sbbs3/startup.h
+++ b/src/sbbs3/startup.h
@@ -126,6 +126,7 @@ typedef struct {
     char    dosemuconf_path[INI_MAX_VALUE_LEN];
     char	temp_dir[INI_MAX_VALUE_LEN];
 	char	ini_fname[INI_MAX_VALUE_LEN];
+	char	web_file_vpath_prefix[INI_MAX_VALUE_LEN];
 
 	/* Miscellaneous */
 	BOOL    usedosemu;
diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c
index 7519753f9a..e3ae6e52ca 100644
--- a/src/sbbs3/websrvr.c
+++ b/src/sbbs3/websrvr.c
@@ -1640,7 +1640,7 @@ BOOL http_checkuser(http_session_t * session)
 		JS_BEGINREQUEST(session->js_cx);
 		if(session->user.number>0) {
 			if(!js_CreateUserObjects(session->js_cx, session->js_glob, &scfg, &session->user, &session->client
-				,NULL /* ftp index file */, session->subscan /* subscan */)) {
+				,startup->file_vpath_prefix, session->subscan /* subscan */)) {
 				JS_ENDREQUEST(session->js_cx);
 				lprintf(LOG_ERR,"%04d !JavaScript ERROR creating user objects",session->socket);
 				send_error(session,__LINE__,"500 Error initializing JavaScript User Objects");
@@ -1649,7 +1649,7 @@ BOOL http_checkuser(http_session_t * session)
 		}
 		else {
 			if(!js_CreateUserObjects(session->js_cx, session->js_glob, &scfg, /* user: */NULL, &session->client
-				,NULL /* ftp index file */, session->subscan /* subscan */)) {
+				,startup->file_vpath_prefix, session->subscan /* subscan */)) {
 				JS_ENDREQUEST(session->js_cx);
 				lprintf(LOG_ERR,"%04d !ERROR initializing JavaScript User Objects",session->socket);
 				send_error(session,__LINE__,"500 Error initializing JavaScript User Objects");
@@ -3143,7 +3143,7 @@ static BOOL get_fullpath(http_session_t * session)
 		}
 	}
 
-	if(scfg.web_file_prefix[0] && strncmp(session->req.physical_path, scfg.web_file_prefix, strlen(scfg.web_file_prefix)) == 0) {
+	if(startup->file_vpath_prefix[0] && strncmp(session->req.physical_path, startup->file_vpath_prefix, strlen(startup->file_vpath_prefix)) == 0) {
 		session->filebase_access = TRUE;
 		return TRUE;
 	}
@@ -3530,7 +3530,7 @@ static void read_webctrl_section(FILE *file, char *section, http_session_t *sess
 
 static bool resolve_filebase_path(http_session_t* session, char* path)
 {
-	uint dir = getdir_from_vpath(&scfg, path + strlen(scfg.web_file_prefix), &session->user, &session->client, false);
+	uint dir = getdir_from_vpath(&scfg, path + strlen(startup->file_vpath_prefix), &session->user, &session->client, false);
 	if(dir >= scfg.total_dirs)
 		return false;
 	char filename[MAX_PATH + 1];
@@ -5515,7 +5515,7 @@ js_login(JSContext *cx, uintN argc, jsval *arglist)
 
 	/* user-specific objects */
 	if(!js_CreateUserObjects(session->js_cx, session->js_glob, &scfg, &session->user, &session->client
-		,NULL /* ftp index file */, session->subscan /* subscan */)) {
+		,startup->file_vpath_prefix, session->subscan /* subscan */)) {
 		lprintf(LOG_ERR,"%04d !JavaScript ERROR creating user objects",session->socket);
 		send_error(session,__LINE__,"500 Error initializing JavaScript User Objects");
 		return(FALSE);
diff --git a/src/sbbs3/websrvr.h b/src/sbbs3/websrvr.h
index ea2b63e017..9b470cd9cb 100644
--- a/src/sbbs3/websrvr.h
+++ b/src/sbbs3/websrvr.h
@@ -68,6 +68,7 @@ typedef struct {
     char**	index_file_name;						/* Index filenames */
 	char	logfile_base[INI_MAX_VALUE_LEN];		/* Logfile base name (date is appended) */
 	char	ini_fname[INI_MAX_VALUE_LEN];
+	char	file_vpath_prefix[INI_MAX_VALUE_LEN];
 
 	/* Misc */
     char	host_name[128];
-- 
GitLab