From 0bdcdf09270631c24cadfa3fabccdb3917c24002 Mon Sep 17 00:00:00 2001
From: "Rob Swindell (on Windows 11)" <rob@synchro.net>
Date: Fri, 3 Jan 2025 19:10:55 -0800
Subject: [PATCH] Using parse_birthdate() whenever changing user's birthdate
 field via Baja/JS

This means that when writing user.birthdate (in JS) for example, we will
always save the field in the proper (YYYYMMDD) format. This fixes issue #855.

Remove use of SM_EURODATE from userdat.c.

This commit includes new @-code MINSPACE (minimum diskspace required to allow
uploads) too (unrelated change).
---
 src/sbbs3/atcodes.cpp |  7 ++++++-
 src/sbbs3/exec.cpp    |  2 +-
 src/sbbs3/js_user.c   | 10 +++++-----
 src/sbbs3/userdat.c   | 44 +++++++++++++++++++++++--------------------
 src/sbbs3/userdat.h   |  2 +-
 5 files changed, 37 insertions(+), 28 deletions(-)

diff --git a/src/sbbs3/atcodes.cpp b/src/sbbs3/atcodes.cpp
index cdf20b1471..915eed0a4a 100644
--- a/src/sbbs3/atcodes.cpp
+++ b/src/sbbs3/atcodes.cpp
@@ -1107,7 +1107,7 @@ const char* sbbs_t::atcode(const char* sp, char* str, size_t maxlen, int* pmode,
 		SAFECOPY(tmp, sp + 6);
 		c_unescape_str(tmp);
 		memset(&tm,0,sizeof(tm));
-		tm.tm_year = getbirthyear(useron.birth) - 1900;
+		tm.tm_year = getbirthyear(&cfg, useron.birth) - 1900;
 		tm.tm_mon = getbirthmonth(&cfg, useron.birth) - 1;
 		tm.tm_mday = getbirthday(&cfg, useron.birth);
 		mktime(&tm);
@@ -1377,6 +1377,11 @@ const char* sbbs_t::atcode(const char* sp, char* str, size_t maxlen, int* pmode,
 		return(str);
 	}
 
+	if(strcmp(sp, "MINSPACE") == 0) {
+		byte_count_to_str(cfg.min_dspace, str, maxlen);
+		return str;
+	}
+
 	if(!strcmp(sp,"UPBYTES")) {
 		safe_snprintf(str,maxlen,"%" PRIu64,useron.ulb);
 		return(str);
diff --git a/src/sbbs3/exec.cpp b/src/sbbs3/exec.cpp
index 24f7d34cd9..de869d2c1e 100644
--- a/src/sbbs3/exec.cpp
+++ b/src/sbbs3/exec.cpp
@@ -1723,7 +1723,7 @@ int sbbs_t::exec(csi_t *csi)
 					case USER_STRING_BIRTHDAY:
 						if(!getage(&cfg,csi->str))
 							break;
-						snprintf(useron.birth, sizeof useron.birth, "%.*s",LEN_BIRTH,csi->str);
+						parse_birthdate(&cfg, csi->str, useron.birth, sizeof useron.birth);
 						putuserstr(useron.number, USER_BIRTH
 							,useron.birth);
 						csi->logic=LOGIC_TRUE;
diff --git a/src/sbbs3/js_user.c b/src/sbbs3/js_user.c
index 4f0e7239eb..eacee68d2e 100644
--- a/src/sbbs3/js_user.c
+++ b/src/sbbs3/js_user.c
@@ -214,7 +214,7 @@ static JSBool js_user_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 			s=p->user->birth;
 			break;
 		case USER_PROP_BIRTHYEAR:
-			val = getbirthyear(p->user->birth);
+			val = getbirthyear(scfg, p->user->birth);
 			break;
 		case USER_PROP_BIRTHMONTH:
 			val = getbirthmonth(scfg, p->user->birth);
@@ -549,8 +549,8 @@ static JSBool js_user_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict,
 			putuserstr(scfg, p->user->number, USER_PHONE, str);
 			break;
 		case USER_PROP_BIRTH:
-			SAFECOPY(p->user->birth,str);
-			putuserstr(scfg, p->user->number, USER_BIRTH, str);
+			parse_birthdate(scfg, str, p->user->birth, sizeof p->user->birth);
+			putuserstr(scfg, p->user->number, USER_BIRTH, p->user->birth);
 			break;
 		case USER_PROP_BIRTHYEAR:
 			if(JS_ValueToECMAUint32(cx, *vp, &val))
@@ -558,11 +558,11 @@ static JSBool js_user_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict,
 			break;
 		case USER_PROP_BIRTHMONTH:
 			if(JS_ValueToECMAUint32(cx, *vp, &val))
-				putuserdec32(scfg, p->user->number, USER_BIRTH, isoDate_create(getbirthyear(p->user->birth), val, getbirthday(scfg, p->user->birth)));
+				putuserdec32(scfg, p->user->number, USER_BIRTH, isoDate_create(getbirthyear(scfg, p->user->birth), val, getbirthday(scfg, p->user->birth)));
 			break;
 		case USER_PROP_BIRTHDAY:
 			if(JS_ValueToECMAUint32(cx, *vp, &val))
-				putuserdec32(scfg, p->user->number, USER_BIRTH, isoDate_create(getbirthyear(p->user->birth), getbirthmonth(scfg, p->user->birth), val));
+				putuserdec32(scfg, p->user->number, USER_BIRTH, isoDate_create(getbirthyear(scfg, p->user->birth), getbirthmonth(scfg, p->user->birth), val));
 			break;
 		case USER_PROP_MODEM:
 			SAFECOPY(p->user->modem,str);
diff --git a/src/sbbs3/userdat.c b/src/sbbs3/userdat.c
index a714487664..4f01984374 100644
--- a/src/sbbs3/userdat.c
+++ b/src/sbbs3/userdat.c
@@ -897,7 +897,7 @@ int putusername(scfg_t* cfg, int number, const char *name)
 
 #define DECVAL(ch, mul)	(DEC_CHAR_TO_INT(ch) * (mul))
 
-int getbirthyear(const char* birth)
+int getbirthyear(scfg_t* cfg, const char* birth)
 {
 	if(IS_DIGIT(birth[2]))				// CCYYMMDD format
 		return DECVAL(birth[0], 1000)
@@ -910,7 +910,11 @@ int getbirthyear(const char* birth)
 	if(localtime_r(&now, &tm) == NULL)
 		return 0;
 	tm.tm_year += 1900;
-	int year = 1900 + DECVAL(birth[6], 10) + DECVAL(birth[7], 1);
+	int year = 1900;
+	if(cfg->sys_date_fmt == YYMMDD)
+		year += DECVAL(birth[0], 10) + DECVAL(birth[1], 1);
+	else // MMDDYY or DDMMYY
+		year += DECVAL(birth[6], 10) + DECVAL(birth[7], 1);
 	if(tm.tm_year - year > 105)
 		year += 100;
 	return year;
@@ -920,7 +924,7 @@ int getbirthmonth(scfg_t* cfg, const char* birth)
 {
 	if(IS_DIGIT(birth[5]))				// CCYYMMDD format
 		return DECVAL(birth[4], 10)	+ DECVAL(birth[5], 1);
-	if(cfg->sys_misc & SM_EURODATE) {	// DD/MM/YY format
+	if(cfg->sys_date_fmt != MMDDYY) {	// DD/MM/YY or YY/MM/DD format
 		return DECVAL(birth[3], 10) + DECVAL(birth[4], 1);
 	} else {							// MM/DD/YY format
 		return DECVAL(birth[0], 10) + DECVAL(birth[1], 1);
@@ -931,11 +935,15 @@ int getbirthday(scfg_t* cfg, const char* birth)
 {
 	if(IS_DIGIT(birth[5]))				// CCYYMMDD format
 		return DECVAL(birth[6], 10)	+ DECVAL(birth[7], 1);
-	if(cfg->sys_misc & SM_EURODATE) {	// DD/MM/YY format
-		return DECVAL(birth[0], 10) + DECVAL(birth[1], 1);
-	} else {							// MM/DD/YY format
-		return DECVAL(birth[3], 10) + DECVAL(birth[4], 1);
+	switch(cfg->sys_date_fmt) {
+		case DDMMYY:
+			return DECVAL(birth[0], 10) + DECVAL(birth[1], 1);
+		case MMDDYY:
+			return DECVAL(birth[3], 10) + DECVAL(birth[4], 1);
+		case YYMMDD:
+			return DECVAL(birth[6], 10) + DECVAL(birth[7], 1);
 	}
+	return 0;
 }
 
 // Always returns string in MM/DD/YY format
@@ -946,7 +954,7 @@ char* getbirthmmddyy(scfg_t* cfg, char sep, const char* birth, char* buf, size_t
 		, sep
 		, getbirthday(cfg, birth)
 		, sep
-		, getbirthyear(birth) % 100);
+		, getbirthyear(cfg, birth) % 100);
 	return buf;
 }
 
@@ -958,7 +966,7 @@ char* getbirthddmmyy(scfg_t* cfg, char sep, const char* birth, char* buf, size_t
 		, sep
 		, getbirthmonth(cfg, birth)
 		, sep
-		, getbirthyear(birth) % 100);
+		, getbirthyear(cfg, birth) % 100);
 	return buf;
 }
 
@@ -966,7 +974,7 @@ char* getbirthddmmyy(scfg_t* cfg, char sep, const char* birth, char* buf, size_t
 char* getbirthyymmdd(scfg_t* cfg, char sep, const char* birth, char* buf, size_t max)
 {
 	safe_snprintf(buf, max, "%02u%c%02u%c%02u"
-		, getbirthyear(birth) % 100
+		, getbirthyear(cfg, birth) % 100
 		, sep
 		, getbirthmonth(cfg, birth)
 		, sep
@@ -1006,7 +1014,7 @@ int getage(scfg_t* cfg, const char *birth)
 		return(0);
 
 	tm.tm_mon++;	/* convert to 1 based */
-	int year = getbirthyear(birth);
+	int year = getbirthyear(cfg, birth);
 	int age = (1900 + tm.tm_year) - year;
 	int mon = getbirthmonth(cfg, birth);
 	int day = getbirthday(cfg, birth);
@@ -1022,12 +1030,8 @@ int getage(scfg_t* cfg, const char *birth)
 /****************************************************************************/
 char* parse_birthdate(scfg_t* cfg, const char* birthdate, char* out, size_t maxlen)
 {
-	if (cfg->sys_date_fmt == YYMMDD)
-		safe_snprintf(out, maxlen, "%.4s%.2s%.2s", birthdate, birthdate + 5, birthdate + 8);
-	else if (cfg->sys_date_fmt == DDMMYY)
-		safe_snprintf(out, maxlen, "%.4s%.2s%.2s", birthdate + 6, birthdate + 3, birthdate);
-	else
-		safe_snprintf(out, maxlen, "%.4s%.2s%.2s", birthdate + 6, birthdate, birthdate + 3);
+	snprintf(out, maxlen, "%04u%02u%02u"
+		,getbirthyear(cfg, birthdate), getbirthmonth(cfg, birthdate), getbirthday(cfg, birthdate));
 	return out;
 }
 
@@ -1042,7 +1046,7 @@ char* format_birthdate(scfg_t* cfg, const char* birthdate, char* out, size_t max
 	if(*birthdate) {
 		if (cfg->sys_date_fmt == YYMMDD)
 			safe_snprintf(out, maxlen, "%04u%c%02u%c%02u"
-				, getbirthyear(birthdate)
+				, getbirthyear(cfg, birthdate)
 				, cfg->sys_date_sep
 				, getbirthmonth(cfg, birthdate)
 				, cfg->sys_date_sep
@@ -1053,14 +1057,14 @@ char* format_birthdate(scfg_t* cfg, const char* birthdate, char* out, size_t max
 				, cfg->sys_date_sep
 				, getbirthmonth(cfg, birthdate)
 				, cfg->sys_date_sep
-				, getbirthyear(birthdate));
+				, getbirthyear(cfg, birthdate));
 		else
 			safe_snprintf(out, maxlen, "%02u%c%02u%c%04u"
 				, getbirthmonth(cfg, birthdate)
 				, cfg->sys_date_sep
 				, getbirthday(cfg, birthdate)
 				, cfg->sys_date_sep
-				, getbirthyear(birthdate));
+				, getbirthyear(cfg, birthdate));
 	}
 	return out;
 }
diff --git a/src/sbbs3/userdat.h b/src/sbbs3/userdat.h
index 4f6077c05d..8d9ca1ffc4 100644
--- a/src/sbbs3/userdat.h
+++ b/src/sbbs3/userdat.h
@@ -77,7 +77,7 @@ DLLEXPORT bool	del_lastuser(scfg_t*);
 DLLEXPORT int	getage(scfg_t*, const char* birthdate);
 DLLEXPORT int	getbirthmonth(scfg_t*, const char* birthdate);
 DLLEXPORT int	getbirthday(scfg_t*, const char* birthdate);
-DLLEXPORT int	getbirthyear(const char* birthdate);
+DLLEXPORT int	getbirthyear(scfg_t*,const char* birthdate);
 DLLEXPORT char* getbirthdstr(scfg_t*, const char* birthdate, char* buf, size_t);
 DLLEXPORT char* getbirthmmddyy(scfg_t*, char sep, const char* birthdate, char* buf, size_t);
 DLLEXPORT char* getbirthddmmyy(scfg_t*, char sep, const char* birthdate, char* buf, size_t);
-- 
GitLab