From df5c57e7014c87bf0521c19ff7b2297609e351da Mon Sep 17 00:00:00 2001
From: Rob <rob@synchro.net>
Date: Sun, 4 Oct 2020 20:24:09 -0700
Subject: [PATCH] Support strftime format arguments to DATE/TIME codes

- DATE: (alias: TIME:)
- BDATE:
- PWDATE:
- SINCE:
- LASTON:
- FIRSTON:
- LASTNEW:
- EXPDATE:
---
 src/sbbs3/atcodes.cpp | 84 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

diff --git a/src/sbbs3/atcodes.cpp b/src/sbbs3/atcodes.cpp
index b9fe0d3f7f..e6ec877b61 100644
--- a/src/sbbs3/atcodes.cpp
+++ b/src/sbbs3/atcodes.cpp
@@ -554,6 +554,16 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen, long* pmode, bool
 		return(unixtodstr(&cfg,time32(NULL),str));
 	}
 
+	if(strncmp(sp, "DATE:", 5) == 0 || strncmp(sp, "TIME:", 5) == 0) {
+		sp += 5;
+		c_unescape_str(sp);
+		now = time(NULL);
+		memset(&tm, 0, sizeof(tm));
+		localtime_r(&now, &tm);
+		strftime(str, maxlen, sp, &tm);
+		return str;
+	}
+
 	if(!strcmp(sp,"DATETIME"))
 		return(timestr(time(NULL)));
 
@@ -824,6 +834,18 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen, long* pmode, bool
 	if(!strcmp(sp,"BDATE"))
 		return getbirthdstr(&cfg, useron.birth, str, maxlen);
 
+	if(strncmp(sp, "BDATE:", 6) == 0) {
+		sp += 6;
+		c_unescape_str(sp);
+		memset(&tm,0,sizeof(tm));
+		tm.tm_year = getbirthyear(useron.birth) - 1900;
+		tm.tm_mon = getbirthmonth(&cfg, useron.birth) - 1;
+		tm.tm_mday = getbirthday(&cfg, useron.birth);
+		mktime(&tm);
+		strftime(str, maxlen, sp, &tm);
+		return str;
+	}
+
 	if(!strcmp(sp,"AGE")) {
 		safe_snprintf(str,maxlen,"%u",getage(&cfg,useron.birth));
 		return(str);
@@ -843,6 +865,16 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen, long* pmode, bool
 	if(strcmp(sp, "PWDATE") == 0 || strcmp(sp, "MEMO") == 0)
 		return(unixtodstr(&cfg,useron.pwmod,str));
 
+	if(strncmp(sp, "PWDATE:", 7) == 0) {
+		sp += 7;
+		c_unescape_str(sp);
+		memset(&tm, 0, sizeof(tm));
+		time_t date = useron.pwmod;
+		localtime_r(&date, &tm);
+		strftime(str, maxlen, sp, &tm);
+		return str;
+	}
+
 	if(!strcmp(sp,"SEC") || !strcmp(sp,"SECURITY")) {
 		safe_snprintf(str,maxlen,"%u",useron.level);
 		return(str);
@@ -851,6 +883,16 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen, long* pmode, bool
 	if(!strcmp(sp,"SINCE"))
 		return(unixtodstr(&cfg,useron.firston,str));
 
+	if(strncmp(sp, "SINCE:", 6) == 0) {
+		sp += 6;
+		c_unescape_str(sp);
+		memset(&tm, 0, sizeof(tm));
+		time_t date = useron.firston;
+		localtime_r(&date, &tm);
+		strftime(str, maxlen, sp, &tm);
+		return str;
+	}
+
 	if(!strcmp(sp,"TIMEON") || !strcmp(sp,"TIMEUSED")) {
 		now=time(NULL);
 		safe_snprintf(str,maxlen,"%lu",(ulong)(now-logontime)/60L);
@@ -915,6 +957,16 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen, long* pmode, bool
 	if(!strcmp(sp,"LASTDATEON"))
 		return(unixtodstr(&cfg,useron.laston,str));
 
+	if(strncmp(sp, "LASTON:", 7) == 0) {
+		sp += 7;
+		c_unescape_str(sp);
+		memset(&tm, 0, sizeof(tm));
+		time_t date = useron.laston;
+		localtime_r(&date, &tm);
+		strftime(str, maxlen, sp, &tm);
+		return str;
+	}
+
 	if(!strcmp(sp,"LASTTIMEON")) {
 		memset(&tm,0,sizeof(tm));
 		localtime32(&useron.laston,&tm);
@@ -935,6 +987,16 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen, long* pmode, bool
 	if(!strcmp(sp,"FIRSTDATEON"))
 		return(unixtodstr(&cfg,useron.firston,str));
 
+	if(strncmp(sp, "FIRSTON:", 8) == 0) {
+		sp += 8;
+		c_unescape_str(sp);
+		memset(&tm, 0, sizeof(tm));
+		time_t date = useron.firston;
+		localtime_r(&date, &tm);
+		strftime(str, maxlen, sp, &tm);
+		return str;
+	}
+
 	if(!strcmp(sp,"FIRSTTIMEON")) {
 		memset(&tm,0,sizeof(tm));
 		localtime32(&useron.firston,&tm);
@@ -1072,6 +1134,16 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen, long* pmode, bool
 	if(!strcmp(sp,"LASTNEW"))
 		return(unixtodstr(&cfg,(time32_t)ns_time,str));
 
+	if(strncmp(sp, "LASTNEW:", 8) == 0) {
+		sp += 8;
+		c_unescape_str(sp);
+		memset(&tm, 0, sizeof(tm));
+		time_t date = ns_time;
+		localtime_r(&date, &tm);
+		strftime(str, maxlen, sp, &tm);
+		return str;
+	}
+
 	if(!strcmp(sp,"NEWFILETIME"))
 		return(timestr(ns_time));
 
@@ -1132,6 +1204,18 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen, long* pmode, bool
 	if(!strcmp(sp,"EXDATE") || !strcmp(sp,"EXPDATE"))
 		return(unixtodstr(&cfg,useron.expire,str));
 
+	if(strncmp(sp, "EXPDATE:", 8) == 0) {
+		if(!useron.expire)
+			return nulstr;
+		sp += 8;
+		c_unescape_str(sp);
+		memset(&tm, 0, sizeof(tm));
+		time_t date = useron.expire;
+		localtime_r(&date, &tm);
+		strftime(str, maxlen, sp, &tm);
+		return str;
+	}
+
 	if(!strcmp(sp,"EXPDAYS")) {
 		now=time(NULL);
 		l=(long)(useron.expire-now);
-- 
GitLab