From 050a2985f915b64bff41ed2dc10c2ec1b7e9f655 Mon Sep 17 00:00:00 2001
From: rswindell <>
Date: Wed, 17 Nov 2004 01:52:35 +0000
Subject: [PATCH] JS_THREADSAFE is now defined in sbbs.h - this change requires
 a cvs update in the include directory to get the new include/mozilla/nspr
 header files (or js_internal.c will fail to compile)! savemsg() now uses
 smb_addmsg() for most of it's functionality. savemsg() now accepts an
 optional client_t* argument, if non-NULL will automatically call
 msg_client_hfields(). MsgBase.save_msg() method now accepts an optional
 client object argument to automatically set the security log header fields
 (sender IP addres, hostname, protocol, and port).

---
 src/sbbs3/bulkmail.cpp |   5 +-
 src/sbbs3/js_msgbase.c |  13 ++-
 src/sbbs3/mailsrvr.c   |   7 +-
 src/sbbs3/postmsg.cpp  | 249 +++++++++--------------------------------
 src/sbbs3/sbbs.dsp     |   4 +-
 src/sbbs3/sbbs.h       |   7 +-
 6 files changed, 72 insertions(+), 213 deletions(-)

diff --git a/src/sbbs3/bulkmail.cpp b/src/sbbs3/bulkmail.cpp
index 9ece843802..29ba313a02 100644
--- a/src/sbbs3/bulkmail.cpp
+++ b/src/sbbs3/bulkmail.cpp
@@ -100,9 +100,6 @@ bool sbbs_t::bulkmail(uchar *ar)
 	smb_hfield_str(&msg,SENDEREXT,str);
 	msg.idx.from=useron.number;
 
-	/* Security logging */
-	msg_client_hfields(&msg,&client);
-
 	smb_hfield_str(&msg,SUBJECT,title);
 	msg.idx.subj=smb_subject_crc(title);
 
@@ -111,7 +108,7 @@ bool sbbs_t::bulkmail(uchar *ar)
 
 	memset(&smb,0,sizeof(smb));
 	smb.subnum=INVALID_SUB;	/* mail database */
-	i=savemsg(&cfg, &smb, &msg, msgbuf);
+	i=savemsg(&cfg, &smb, &msg, &client, msgbuf);
 	free(msgbuf);
 	if(i!=0) {
 		smb_close(&smb);
diff --git a/src/sbbs3/js_msgbase.c b/src/sbbs3/js_msgbase.c
index 56ef4dfbfe..b8a25bf641 100644
--- a/src/sbbs3/js_msgbase.c
+++ b/src/sbbs3/js_msgbase.c
@@ -1302,8 +1302,10 @@ js_save_msg(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 	JSObject*	hdr=NULL;
 	JSObject*	objarg;
 	JSObject*	rcpt_list=NULL;
+	JSClass*	cl;
 	smbmsg_t	rcpt_msg;
 	smbmsg_t	msg;
+	client_t*	client=NULL;
 	jsval		open_rval;
 	private_t*	p;
 
@@ -1329,6 +1331,10 @@ js_save_msg(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 	for(n=0;n<argc;n++) {
 		if(JSVAL_IS_OBJECT(argv[n])) {
 			objarg = JSVAL_TO_OBJECT(argv[n]);
+			if((cl=JS_GetClass(cx,objarg))!=NULL && strcmp(cl->name,"Client")==0) {
+				client=JS_GetPrivate(cx,objarg);
+				continue;
+			}
 			if(JS_IsArrayObject(cx, objarg)) {		/* recipient_list is an array of objects */
 				if(body!=NULL && rcpt_list==NULL) {	/* body text already specified */
 					rcpt_list = objarg;
@@ -1363,7 +1369,7 @@ js_save_msg(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
 		if(body[0])
 			truncsp(body);
-		if(savemsg(scfg, &(p->smb), &msg, body)==0)
+		if(savemsg(scfg, &(p->smb), &msg, client, body)==0)
 			*rval = JSVAL_TRUE;
 
 		if(rcpt_list!=NULL) {	/* Sending to a list of recipients */
@@ -1624,7 +1630,7 @@ static jsSyncMethodSpec js_msgbase_functions[] = {
 	,JSDOCSTR("mark message as deleted")
 	,311
 	},
-	{"save_msg",		js_save_msg,		2, JSTYPE_BOOLEAN,	JSDOCSTR("object header [,body_text] [,array rcpt_list]")
+	{"save_msg",		js_save_msg,		2, JSTYPE_BOOLEAN,	JSDOCSTR("object header [,client] [,body_text] [,array rcpt_list]")
 	,JSDOCSTR("create a new message in message base, the <i>header</i> object may contain the following properties:<br>"
 	"<table>"
 	"<tr><td><tt>subject</tt><td>Message subject <i>(required)</i>"
@@ -1676,6 +1682,9 @@ static jsSyncMethodSpec js_msgbase_functions[] = {
 	"<tr><td><tt>field_list[].data</tt><td>Other SMB header fields (data)"
 	"</table>"
 	"<br>"
+	"The optional <i>client</i> argument is an instance of the <i>Client</i> class to be used for the "
+	"security log header fields (e.g. sender IP addres, hostname, protocol, and port). "
+	"<br>"
 	"The optional <i>rcpt_list</i> is an array of objects that specifies multiple recipients "
 	"for a single message (e.g. bulk e-mail). Each object in the array may include the following header properties "
 	"(described above): <br>"
diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c
index a4c45c1be8..7d05c87e51 100644
--- a/src/sbbs3/mailsrvr.c
+++ b/src/sbbs3/mailsrvr.c
@@ -2322,9 +2322,6 @@ static void smtp_thread(void* arg)
 					msg.idx.subj=smb_subject_crc(p);
 				}
 
-				/* Security logging */
-				msg_client_hfields(&msg,&client);
-
 				length=filelength(fileno(msgtxt))-ftell(msgtxt);
 
 				if(startup->max_msg_size && length>startup->max_msg_size) {
@@ -2367,7 +2364,7 @@ static void smtp_thread(void* arg)
 					smb_hfield_str(&msg, RECIPIENT, rcpt_name);
 
 					smb.subnum=subnum;
-					if((i=savemsg(&scfg, &smb, &msg, msgbuf))!=SMB_SUCCESS) {
+					if((i=savemsg(&scfg, &smb, &msg, &client, msgbuf))!=SMB_SUCCESS) {
 						lprintf(LOG_WARNING,"%04d !SMTP ERROR %d (%s) saving message"
 							,socket,i,smb.last_error);
 						sockprintf(socket, "452 ERROR %d (%s) saving message"
@@ -2386,7 +2383,7 @@ static void smtp_thread(void* arg)
 
 				/* E-mail */
 				smb.subnum=INVALID_SUB;
-				i=savemsg(&scfg, &smb, &msg, msgbuf);
+				i=savemsg(&scfg, &smb, &msg, &client, msgbuf);
 				free(msgbuf);
 				if(i!=SMB_SUCCESS) {
 					smb_close(&smb);
diff --git a/src/sbbs3/postmsg.cpp b/src/sbbs3/postmsg.cpp
index 004674884e..97bd58fed6 100644
--- a/src/sbbs3/postmsg.cpp
+++ b/src/sbbs3/postmsg.cpp
@@ -422,6 +422,9 @@ extern "C" int DLLCALL msg_client_hfields(smbmsg_t* msg, client_t* client)
 {
 	int i;
 
+	if(client==NULL)
+		return(-1);
+
 	if((i=smb_hfield_str(msg,SENDERIPADDR,client->addr))!=SMB_SUCCESS)
 		return(i);
 	if((i=smb_hfield_str(msg,SENDERHOSTNAME,client->host))!=SMB_SUCCESS)
@@ -431,23 +434,14 @@ extern "C" int DLLCALL msg_client_hfields(smbmsg_t* msg, client_t* client)
 	return smb_hfield(msg,SENDERPORT,sizeof(client->port),&client->port);
 }
 
-extern "C" int DLLCALL savemsg(scfg_t* cfg, smb_t* smb, smbmsg_t* msg, char* msgbuf)
+extern "C" int DLLCALL savemsg(scfg_t* cfg, smb_t* smb, smbmsg_t* msg, client_t* client, char* msgbuf)
 {
-	char	pad=0;
 	char	pid[128];
 	char	msg_id[256];
-	char*	lzhbuf=NULL;
-	ushort	xlat;
-	int		xlatlen;
+	ushort	xlat=XLAT_NONE;
 	int 	i;
-	int		storage;
-	long	lzhlen;
-	BOOL	lzh=FALSE;
-	ulong	l;
-	ulong	length;
-	long	offset;
-	ulong	crc=0xffffffff;
-	smbmsg_t remsg;
+	int		storage=SMB_SELFPACK;
+	long	dupechk_hashes=SMB_HASH_SOURCE_ALL;
 
 	if(msg==NULL)
 		return(SMB_FAILURE);
@@ -462,209 +456,70 @@ extern "C" int DLLCALL savemsg(scfg_t* cfg, smb_t* smb, smbmsg_t* msg, char* msg
 			return(i);
 	}
 
-	if(filelength(fileno(smb->shd_fp))<1) {	 /* Create it if it doesn't exist */
-		if(smb->subnum==INVALID_SUB) {
-			smb->status.max_crcs=cfg->mail_maxcrcs;
-			smb->status.max_age=cfg->mail_maxage;
-			smb->status.max_msgs=0;
-			smb->status.attr=SMB_EMAIL;
-		} else {
-			smb->status.max_crcs=cfg->sub[smb->subnum]->maxcrcs;
-			smb->status.max_msgs=cfg->sub[smb->subnum]->maxmsgs;
-			smb->status.max_age=cfg->sub[smb->subnum]->maxage;
-			smb->status.attr=cfg->sub[smb->subnum]->misc&SUB_HYPER ? SMB_HYPERALLOC : 0;
-		}
-		if((i=smb_create(smb))!=SMB_SUCCESS) 
-			return(i);
+	if(smb->subnum==INVALID_SUB) {	/* e-mail */
 
-		/* If msgbase doesn't exist, we can't be adding a header to an existing msg */
-		msg->hdr.total_dfields=0;
-	}
-	if((i=smb_locksmbhdr(smb))!=SMB_SUCCESS) 
-		return(i);
+		smb->status.max_crcs=cfg->mail_maxcrcs;
+		smb->status.max_age=cfg->mail_maxage;
+		smb->status.max_msgs=0;	/* unlimited */
+		smb->status.attr=SMB_EMAIL;
 
-	if((i=smb_getstatus(smb))!=SMB_SUCCESS) {
-		smb_unlocksmbhdr(smb);
-		return(i);
-	}
+		if(cfg->sys_misc&SM_FASTMAIL)
+			storage=SMB_FASTALLOC;
 
-	if(msg->hdr.total_dfields==0) {
+	} else {	/* sub-board */
 
-		if(msgbuf==NULL)
-			return(SMB_FAILURE);
+		smb->status.max_crcs=cfg->sub[smb->subnum]->maxcrcs;
+		smb->status.max_msgs=cfg->sub[smb->subnum]->maxmsgs;
+		smb->status.max_age=cfg->sub[smb->subnum]->maxage;
+		smb->status.attr=0;
 
-		length=strlen(msgbuf);
-
-		/* Remove white-space from end of message text */
-		while(length && (uchar)msgbuf[length-1]<=' ')
-			length--;
-
-		/* Calculate CRC-32 of message text (before encoding, if any) */
-		if(smb->status.max_crcs) {
-			for(l=0;l<length;l++)
-				crc=ucrc32(msgbuf[l],crc); 
-			crc=~crc;
-		}
-
-		/* LZH compress? */
-		if(smb->subnum!=INVALID_SUB && cfg->sub[smb->subnum]->misc&SUB_LZH 
-			&& length+sizeof(xlat)>=SDT_BLOCK_LEN
-			&& (lzhbuf=(char *)LMALLOC(length*2))!=NULL) {
-			lzhlen=lzh_encode((uchar *)msgbuf,length,(uchar *)lzhbuf);
-			if(lzhlen>1
-				&& smb_datblocks(lzhlen+(sizeof(xlat)*2)) 
-					< smb_datblocks(length+sizeof(xlat))) {
-				length=lzhlen+sizeof(xlat); 	/* Compressable */
-				lzh=TRUE;
-				msgbuf=lzhbuf; 
-			}
-		}
+		if(cfg->sub[smb->subnum]->misc&SUB_HYPER)
+			storage = smb->status.attr = SMB_HYPERALLOC;
+		else if(cfg->sub[smb->subnum]->misc&SUB_FAST)
+			storage = SMB_FASTALLOC;
 
-		length+=sizeof(xlat);	/* xlat string terminator */
-
-		if(length&0x80000000) {
-			smb_unlocksmbhdr(smb);
-			sprintf(smb->last_error,"message length: 0x%lX",length);
-			FREE_AND_NULL(lzhbuf);
-			return(-1);
-		}
-
-		/* Allocate Data Blocks */
-		if(smb->status.attr&SMB_HYPERALLOC) {
-			offset=smb_hallocdat(smb);
-			storage=SMB_HYPERALLOC; 
-		} else {
-			if((i=smb_open_da(smb))!=SMB_SUCCESS) {
-				smb_unlocksmbhdr(smb);
-				FREE_AND_NULL(lzhbuf);
-				return(i);
-			}
-			if((smb->subnum==INVALID_SUB && cfg->sys_misc&SM_FASTMAIL)
-				|| (smb->subnum!=INVALID_SUB && cfg->sub[smb->subnum]->misc&SUB_FAST)) {
-				offset=smb_fallocdat(smb,length,1);
-				storage=SMB_FASTALLOC; 
-			} else {
-				offset=smb_allocdat(smb,length,1);
-				storage=SMB_SELFPACK; 
-			}
-			smb_close_da(smb); 
-		}
-
-		if(offset<0) {
-			smb_unlocksmbhdr(smb);
-			FREE_AND_NULL(lzhbuf);
-			return((int)offset);
-		}
-
-		smb_fseek(smb->sdt_fp,offset,SEEK_SET);
-		xlatlen=0;
-		if(lzh) {
+		if(cfg->sub[smb->subnum]->misc&SUB_LZH)
 			xlat=XLAT_LZH;
-			smb_fwrite(smb,&xlat,sizeof(xlat),smb->sdt_fp);
-			xlatlen+=sizeof(xlat);
-		}
-		xlat=XLAT_NONE;
-		smb_fwrite(smb,&xlat,sizeof(xlat),smb->sdt_fp);
-		xlatlen+=sizeof(xlat);
-
-		smb_fwrite(smb,msgbuf,length-xlatlen,smb->sdt_fp);
-		for(l=length;l%SDT_BLOCK_LEN;l++)
-			smb_fwrite(smb,&pad,1,smb->sdt_fp);
-
-		fflush(smb->sdt_fp);
 
-		FREE_AND_NULL(lzhbuf);
+		/* enforce anonymous/private posts only */
+ 		if(cfg->sub[smb->subnum]->misc&SUB_PONLY)
+ 			msg->hdr.attr|=MSG_PRIVATE;
+ 		if(cfg->sub[smb->subnum]->misc&SUB_AONLY)
+ 			msg->hdr.attr|=MSG_ANONYMOUS;
 
-		/* Add CRC to CRC history (and check for duplicates) */
-		if(smb->status.max_crcs) {
-			i=smb_addcrc(smb,crc);
-			if(i) {
-				smb_freemsgdat(smb,offset,length,1);
-				smb_unlocksmbhdr(smb);
-				return(i);
-			} 
-		}
-		msg->hdr.offset=offset;
-		smb_dfield(msg,TEXT_BODY,length);
 	}
 
-	msg->hdr.version=smb_ver();
 	if(msg->hdr.when_imported.time==0) {
 		msg->hdr.when_imported.time=time(NULL);
 		msg->hdr.when_imported.zone=sys_timezone(cfg);
 	}
 	if(msg->hdr.when_written.time==0)	/* Uninitialized */
 		msg->hdr.when_written = msg->hdr.when_imported;
-	msg->idx.time=msg->hdr.when_imported.time;
-	msg->idx.number=smb->status.last_msg+1; /* this *should* be the new message number */
-
-	if(smb->subnum!=INVALID_SUB) {	/* enforce anonymous/private posts only */
-		if(cfg->sub[smb->subnum]->misc&SUB_PONLY)
-			msg->hdr.attr|=MSG_PRIVATE;
-		if(cfg->sub[smb->subnum]->misc&SUB_AONLY)
-			msg->hdr.attr|=MSG_ANONYMOUS;
-	}
-
-	if(smb_get_hfield(msg,FIDOPID,NULL)==NULL) 	/* Don't create duplicate PIDs */
-		smb_hfield_str(msg,FIDOPID,program_id(pid));
-
-	/* Generate default (RFC822) message-id  */
-	if(smb_get_hfield(msg,RFC822MSGID,NULL)==NULL) {
-		SAFECOPY(msg_id,get_msgid(cfg,smb->subnum,msg));
-		smb_hfield_str(msg,RFC822MSGID,msg_id);
-	}
-
-	/* Generate FTN MSGID */
-	if(smb->subnum!=INVALID_SUB && cfg->sub[smb->subnum]->misc&SUB_FIDO
-		&& smb_get_hfield(msg,FIDOMSGID,NULL)==NULL) {
-		SAFECOPY(msg_id,ftn_msgid(cfg->sub[smb->subnum],msg));
-		smb_hfield_str(msg,FIDOMSGID,msg_id);
-	}
-
-	if(msg->to==NULL)	/* no recipient, don't add header (required for bulkmail) */
-		return(smb_unlocksmbhdr(smb));
-
-	/* Look-up thread_back if Reply-ID was specified */
-	if(msg->hdr.thread_back==0 && msg->reply_id!=NULL) {
-		if(smb_getmsgidx_by_msgid(smb,&remsg,msg->reply_id)==SMB_SUCCESS)
-			msg->hdr.thread_back=remsg.idx.number;	/* needed for threading backward */
-	}
-
-	/* Auto-thread linkage */
-	if(msg->hdr.thread_back) {
-		memset(&remsg,0,sizeof(remsg));
-		remsg.hdr.number=msg->hdr.thread_back;
-		if((i=smb_getmsgidx(smb, &remsg))!=SMB_SUCCESS)	/* invalid thread origin */
-			return(i);
-
-		if((i=smb_lockmsghdr(smb,&remsg))!=SMB_SUCCESS)
-			return(i);
-
-		if((i=smb_getmsghdr(smb, &remsg))!=SMB_SUCCESS) {
-			smb_unlockmsghdr(smb, &remsg); 
-			return(i);
-		}
-
-		/* Add RFC-822 Reply-ID (generate if necessary) */
-		if(msg->reply_id==NULL)
-			smb_hfield_str(msg,RFC822REPLYID,get_msgid(cfg,smb->subnum,&remsg));
-
-		/* Add FidoNet Reply if original message has FidoNet MSGID */
-		if(msg->ftn_reply==NULL && remsg.ftn_msgid!=NULL)
-			smb_hfield_str(msg,FIDOREPLYID,remsg.ftn_msgid);
-
-		i=smb_updatethread(smb, &remsg, smb->status.last_msg+1);
-		smb_unlockmsghdr(smb, &remsg);
-		smb_freemsgmem(&remsg);
-
-		if(i!=SMB_SUCCESS)
-			return(i); 
-	}
 
-	if((i=smb_addmsghdr(smb,msg,storage))==SMB_SUCCESS) // calls smb_unlocksmbhdr() 
+	if(smb->status.max_crcs==0)	/* no CRC checking means no body text dupe checking */
+		dupechk_hashes&=~(1<<SMB_HASH_SOURCE_BODY);
+
+	if(client!=NULL)
+		msg_client_hfields(msg,client);
+ 
+ 	if(smb_get_hfield(msg,FIDOPID,NULL)==NULL) 	/* Don't create duplicate PIDs */
+ 		smb_hfield_str(msg,FIDOPID,program_id(pid));
+ 
+ 	/* Generate default (RFC822) message-id  */
+ 	if(smb_get_hfield(msg,RFC822MSGID,NULL)==NULL) {
+ 		SAFECOPY(msg_id,get_msgid(cfg,smb->subnum,msg));
+ 		smb_hfield_str(msg,RFC822MSGID,msg_id);
+ 	}
+ 
+ 	/* Generate FTN MSGID */
+ 	if(smb->subnum!=INVALID_SUB && cfg->sub[smb->subnum]->misc&SUB_FIDO
+ 		&& smb_get_hfield(msg,FIDOMSGID,NULL)==NULL) {
+ 		SAFECOPY(msg_id,ftn_msgid(cfg->sub[smb->subnum],msg));
+ 		smb_hfield_str(msg,FIDOMSGID,msg_id);
+ 	}
+
+	if((i=smb_addmsg(smb,msg,storage,dupechk_hashes,xlat,(uchar*)msgbuf,NULL))==SMB_SUCCESS)
 		signal_sub_sem(cfg,smb->subnum);
-	else
-		smb_freemsg_dfields(smb,msg,1);
 
 	return(i);
 }
diff --git a/src/sbbs3/sbbs.dsp b/src/sbbs3/sbbs.dsp
index d86b7b3b1f..517cfcbc34 100644
--- a/src/sbbs3/sbbs.dsp
+++ b/src/sbbs3/sbbs.dsp
@@ -43,7 +43,7 @@ RSC=rc.exe
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SBBS_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include\mozilla\js" /I "..\xpdev" /I "..\smblib" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SBBS" /D "SBBS_EXPORTS" /D "SMB_EXPORTS" /D "JAVASCRIPT" /D "RINGBUF_SEM" /FR /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include\mozilla\js" /I "..\..\include\mozilla\nspr" /I "..\xpdev" /I "..\smblib" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SBBS" /D "SBBS_EXPORTS" /D "SMB_EXPORTS" /D "JAVASCRIPT" /D "RINGBUF_SEM" /FR /FD /c
 # SUBTRACT CPP /YX
 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
@@ -70,7 +70,7 @@ LINK32=link.exe
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SBBS_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\include\mozilla\js" /I "..\xpdev" /I "..\smblib" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SBBS" /D "SBBS_EXPORTS" /D "SMB_EXPORTS" /D "JAVASCRIPT" /D "RINGBUF_SEM" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\include\mozilla\js" /I "..\..\include\mozilla\nspr" /I "..\xpdev" /I "..\smblib" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SBBS" /D "SBBS_EXPORTS" /D "SMB_EXPORTS" /D "JAVASCRIPT" /D "RINGBUF_SEM" /FR /YX /FD /GZ /c
 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
 # ADD BASE RSC /l 0x409 /d "_DEBUG"
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index 9b6cf8b0e6..e0b4946dc8 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -96,6 +96,7 @@
 		#define XP_PC
 		#define XP_WIN
 	#endif
+	#define JS_THREADSAFE	/* Required! */
 	#include <jsapi.h>
 	#include <jsprf.h>		/* JS-safe sprintf functions */
 #endif
@@ -788,9 +789,9 @@ extern "C" {
 	DLLEXPORT void		DLLCALL delfattach(scfg_t*, smbmsg_t*);
 
 	/* postmsg.cpp */
-	DLLEXPORT int		DLLCALL savemsg(scfg_t* cfg, smb_t* smb, smbmsg_t* msg, char* msgbuf);
-	DLLEXPORT void		DLLCALL signal_sub_sem(scfg_t* cfg, uint subnum);
-	DLLEXPORT int		DLLCALL msg_client_hfields(smbmsg_t* msg, client_t* client);
+	DLLEXPORT int		DLLCALL savemsg(scfg_t*, smb_t*, smbmsg_t*, client_t*, char* msgbuf);
+	DLLEXPORT void		DLLCALL signal_sub_sem(scfg_t*, uint subnum);
+	DLLEXPORT int		DLLCALL msg_client_hfields(smbmsg_t*, client_t*);
 
 	/* filedat.c */
 	DLLEXPORT BOOL		DLLCALL getfileixb(scfg_t* cfg, file_t* f);
-- 
GitLab