From 0c9513fdddfaee3a8ad10c106a013cd6501c5b86 Mon Sep 17 00:00:00 2001
From: Rob Swindell <rob@synchro.net>
Date: Tue, 22 Feb 2022 21:59:18 -0800
Subject: [PATCH] Save instant message history (notifications and telegrams)

This should address issue (feature request) #196.

The last 20 sets of displayed messages are stored as data/msgs/<user-num>.last.#.msg. This number is currently hard-coded, but could be configurable in the future. I say "sets" because messages are batched-up and displayed together normally, unless a user is actively polling for new users (e.g. while at the Ctrl-P/PrivateMsg prompt).

This involved getting rid of some copy/pasta in sbbs_t:getsmsg() as well by creating/using/reusing readsmsg().
---
 src/sbbs3/getnode.cpp | 29 +++--------------------------
 src/sbbs3/userdat.c   | 28 ++++++++++++++++++++++++----
 src/sbbs3/userdat.h   |  1 +
 3 files changed, 28 insertions(+), 30 deletions(-)

diff --git a/src/sbbs3/getnode.cpp b/src/sbbs3/getnode.cpp
index 8f65c874d7..cfb28ba38b 100644
--- a/src/sbbs3/getnode.cpp
+++ b/src/sbbs3/getnode.cpp
@@ -342,9 +342,7 @@ int sbbs_t::getnodeext(uint number, char *ext)
 /****************************************************************************/
 int sbbs_t::getsmsg(int usernumber, bool clearline)
 {
-	char	str[MAX_PATH+1], *buf;
-    int		file;
-    long	length;
+	char	*buf;
 	node_t	node;
 	int		i;
 
@@ -360,35 +358,14 @@ int sbbs_t::getsmsg(int usernumber, bool clearline)
 		} 
 	}
 
-	SAFEPRINTF2(str,"%smsgs/%4.4u.msg",cfg.data_dir,usernumber);
-	if(flength(str)<1L)
-		return(0);
-	if((file=nopen(str,O_RDWR))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_RDWR);
-		return(errno); 
-	}
-	length=(long)filelength(file);
-	if((buf=(char *)malloc(length+1))==NULL) {
-		close(file);
-		errormsg(WHERE,ERR_ALLOC,str,length+1);
-		return(-1); 
-	}
-	if(lread(file,buf,length)!=length) {
-		close(file);
-		free(buf);
-		errormsg(WHERE,ERR_READ,str,length);
-		return(errno); 
-	}
-	chsize(file,0L);
-	close(file);
-	buf[length]=0;
+	if((buf = readsmsg(&cfg, usernumber)) == NULL)
+		return -1;
 	getnodedat(cfg.node_num,&thisnode,0);
 	if(clearline)
 		this->clearline();
 	else
 		if(column)
 			CRLF;
-	strip_invalid_attr(buf);
 	putmsg(buf,P_NOATCODES);
 	free(buf);
 
diff --git a/src/sbbs3/userdat.c b/src/sbbs3/userdat.c
index 23ea41c2fd..b24030f99c 100644
--- a/src/sbbs3/userdat.c
+++ b/src/sbbs3/userdat.c
@@ -1416,10 +1416,8 @@ int putsmsg(scfg_t* cfg, int usernumber, char *strin)
 /****************************************************************************/
 char* getsmsg(scfg_t* cfg, int usernumber)
 {
-	char	str[MAX_PATH+1], *buf;
 	int		i;
     int		file = -1;
-    long	length;
 	node_t	node;
 
 	if(!VALID_CFG(cfg) || usernumber<1)
@@ -1438,6 +1436,21 @@ char* getsmsg(scfg_t* cfg, int usernumber)
 	}
 	CLOSE_OPEN_FILE(file);
 
+	return readsmsg(cfg, usernumber);
+}
+
+/****************************************************************************/
+/* Returns any short messages waiting for user number, buffer must be freed */
+/****************************************************************************/
+char* readsmsg(scfg_t* cfg, int usernumber)
+{
+	char	str[MAX_PATH+1], *buf;
+    int		file;
+    long	length;
+
+	if(!VALID_CFG(cfg) || usernumber<1)
+		return(NULL);
+
 	SAFEPRINTF2(str,"%smsgs/%4.4u.msg",cfg->data_dir,usernumber);
 	if(flength(str)<1L)
 		return(NULL);
@@ -1458,6 +1471,13 @@ char* getsmsg(scfg_t* cfg, int usernumber)
 	buf[length]=0;
 	strip_invalid_attr(buf);
 
+	SAFEPRINTF2(str, "%smsgs/%4.4u.last.msg", cfg->data_dir, usernumber);
+	backup(str, 19, /* rename: */true);
+	if((file = nopen(str, O_WRONLY|O_CREAT|O_APPEND)) != -1) {
+		(void)write(file, buf, length);
+		close(file);
+	}
+
 	return(buf);	/* caller must free */
 }
 
@@ -2803,14 +2823,14 @@ int newuserdat(scfg_t* cfg, user_t* user)
 	delfiles(str,tmp, /* keep: */0);
 	SAFEPRINTF(str,"%suser",cfg->data_dir);
 	delfiles(str,tmp, /* keep: */0);
+	SAFEPRINTF(str,"%smsgs",cfg->data_dir);
+	delfiles(str,tmp, /* keep: */0);
 	SAFEPRINTF2(str,"%suser/%04u",cfg->data_dir,user->number);
 	delfiles(str,ALLFILES, /* keep: */0);
 	rmdir(str);
 
 	SAFEPRINTF2(str,"%suser/ptrs/%04u.ixb",cfg->data_dir,user->number); /* msg ptrs */
 	remove(str);
-	SAFEPRINTF2(str,"%smsgs/%04u.msg",cfg->data_dir,user->number); /* delete short msg */
-	remove(str);
 
 	/* Update daily statistics database (for system and node) */
 
diff --git a/src/sbbs3/userdat.h b/src/sbbs3/userdat.h
index b3aaed0fe1..0537f3e97d 100644
--- a/src/sbbs3/userdat.h
+++ b/src/sbbs3/userdat.h
@@ -69,6 +69,7 @@ DLLEXPORT void	printnodedat(scfg_t*, uint number, node_t* node);
 DLLEXPORT int	is_user_online(scfg_t*, uint usernumber);
 DLLEXPORT void	packchatpass(char *pass, node_t* node);
 DLLEXPORT char* unpackchatpass(char *pass, node_t* node);
+DLLEXPORT char* readsmsg(scfg_t*, int usernumber);
 DLLEXPORT char* getsmsg(scfg_t*, int usernumber);
 DLLEXPORT int	putsmsg(scfg_t*, int usernumber, char *strin);
 DLLEXPORT char* getnmsg(scfg_t*, int node_num);
-- 
GitLab