From 1cac2c8a4ae11946e37d7e1af5a380d6bc9b4fbf Mon Sep 17 00:00:00 2001
From: Rob Swindell <rob@synchro.net>
Date: Wed, 23 Mar 2022 21:07:24 -0700
Subject: [PATCH] Support user credits and transfer stats > 4GB in total

Credits and daily free credits are accurate to the byte up to (a maximum) of 18446744073709551615 (that's 18 Exbibytes - 1).

User's upload and download byte stats are now similarly extended in maximum range, but the accuracy is only "to the byte" for values less than 10,000,000,000. Beyond that value, the accuracy declines, but is generally pretty damn accurate (to 4 decimal places beyond the nearest multiple of a power of 1024), so I don't expect that to be an issue. This method of storing upload/download byte stats allowed me to use the same 10-character user record fields in the user.dat file.

As a side-effect of this enhancements:
* User and file credit values are now expressed in multiples of powers of 1024 (e.g. 4.0G rather than 4,294,967,296).
* Free credits per day per security level has now been extended from 32 to 64-bits (to accommodate values >= 4GB).
* adjustuserrec() now longer takes the record length since we can easily determine that automatically and don't need more "sources of truth" that can be out-of-sync (e.g. the U_CDT field length going from 10 to 20 chars with this change).
* setting the stage for locale-dependent thousands-separators (e.g. space instead of comma) - currently still hard-coded to comma
* more/better support for files > 4GB in size (e.g. in the batch download queue)
* user_t ulong fields changed to either uint32_t or uint64_t - I didn't realize how many long/ulong's remained in the code (which are sometmies 32-bit, sometimes 64-bit) - ugh
* Steve's ultoac() function renamed to u32toac() and created a C++ wrapper that still uses the old name, for homage
---
 src/sbbs3/atcodes.cpp     |  26 +++----
 src/sbbs3/bat_xfer.cpp    |  27 +++----
 src/sbbs3/chat.cpp        |   6 +-
 src/sbbs3/chk_ar.cpp      |   6 +-
 src/sbbs3/data.cpp        |   4 +-
 src/sbbs3/download.cpp    |   6 +-
 src/sbbs3/exec.cpp        |   4 +-
 src/sbbs3/file.cpp        |  12 +--
 src/sbbs3/filedat.c       |   2 +-
 src/sbbs3/filelist.c      |   7 +-
 src/sbbs3/ftpsrvr.c       |  12 +--
 src/sbbs3/getmsg.cpp      |  12 +--
 src/sbbs3/js_user.c       |  22 ++++--
 src/sbbs3/listfile.cpp    |   2 +-
 src/sbbs3/logon.cpp       |   6 +-
 src/sbbs3/netmail.cpp     |   4 +-
 src/sbbs3/pack_qwk.cpp    |   2 +-
 src/sbbs3/qwk.cpp         |   2 +-
 src/sbbs3/readmsgs.cpp    |   2 +-
 src/sbbs3/sbbs.h          |   2 +
 src/sbbs3/sbbsdefs.h      |  33 +++++----
 src/sbbs3/scfg/scfgsys.c  |  10 +--
 src/sbbs3/scfgdefs.h      |   2 +-
 src/sbbs3/scfglib1.c      |   9 ++-
 src/sbbs3/scfgsave.c      |   8 +-
 src/sbbs3/str.cpp         |  38 ++++++----
 src/sbbs3/str_util.c      |  12 +--
 src/sbbs3/str_util.h      |   4 +-
 src/sbbs3/text_defaults.c |  15 ++--
 src/sbbs3/uedit/uedit.c   |  38 +++++-----
 src/sbbs3/upload.cpp      |   8 +-
 src/sbbs3/userdat.c       | 149 +++++++++++++++++++++++---------------
 src/sbbs3/userdat.h       |   7 +-
 src/sbbs3/useredit.cpp    |  50 +++++++------
 src/sbbs3/xtrn.cpp        |   2 +-
 src/sbbs3/xtrn_sec.cpp    |  12 +--
 36 files changed, 315 insertions(+), 248 deletions(-)

diff --git a/src/sbbs3/atcodes.cpp b/src/sbbs3/atcodes.cpp
index f189baee21..458bcdb35e 100644
--- a/src/sbbs3/atcodes.cpp
+++ b/src/sbbs3/atcodes.cpp
@@ -1175,12 +1175,12 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen, long* pmode, bool
 	}
 
 	if(!strcmp(sp,"UPBYTES")) {
-		safe_snprintf(str,maxlen,"%lu",useron.ulb);
+		safe_snprintf(str,maxlen,"%" PRIu64,useron.ulb);
 		return(str);
 	}
 
 	if(!strcmp(sp,"UPK")) {
-		safe_snprintf(str,maxlen,"%lu",useron.ulb/1024L);
+		safe_snprintf(str,maxlen,"%" PRIu64,useron.ulb/1024L);
 		return(str);
 	}
 
@@ -1190,12 +1190,12 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen, long* pmode, bool
 	}
 
 	if(!strcmp(sp,"DLBYTES")) {
-		safe_snprintf(str,maxlen,"%lu",useron.dlb);
+		safe_snprintf(str,maxlen,"%" PRIu64,useron.dlb);
 		return(str);
 	}
 
 	if(!strcmp(sp,"DOWNK")) {
-		safe_snprintf(str,maxlen,"%lu",useron.dlb/1024L);
+		safe_snprintf(str,maxlen,"%" PRIu64,useron.dlb/1024L);
 		return(str);
 	}
 
@@ -1247,37 +1247,37 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen, long* pmode, bool
 	/* MAXDL */
 
 	if(!strcmp(sp,"MAXDK") || !strcmp(sp,"DLKLIMIT") || !strcmp(sp,"KBLIMIT")) {
-		safe_snprintf(str,maxlen,"%lu",cfg.level_freecdtperday[useron.level]/1024L);
+		safe_snprintf(str,maxlen,"%" PRIu64,cfg.level_freecdtperday[useron.level]/1024L);
 		return(str);
 	}
 
 	if(!strcmp(sp,"DAYBYTES")) {    /* amt of free cdts used today */
-		safe_snprintf(str,maxlen,"%lu",cfg.level_freecdtperday[useron.level]-useron.freecdt);
+		safe_snprintf(str,maxlen,"%" PRIu64,cfg.level_freecdtperday[useron.level]-useron.freecdt);
 		return(str);
 	}
 
 	if(!strcmp(sp,"BYTELIMIT")) {
-		safe_snprintf(str,maxlen,"%ld", (long)cfg.level_freecdtperday[useron.level]);
+		safe_snprintf(str,maxlen,"%" PRIu64, cfg.level_freecdtperday[useron.level]);
 		return(str);
 	}
 
 	if(!strcmp(sp,"KBLEFT")) {
-		safe_snprintf(str,maxlen,"%lu",(useron.cdt+useron.freecdt)/1024L);
+		safe_snprintf(str,maxlen,"%" PRIu64,(useron.cdt+useron.freecdt)/1024ULL);
 		return(str);
 	}
 
 	if(!strcmp(sp,"BYTESLEFT")) {
-		safe_snprintf(str,maxlen,"%lu",useron.cdt+useron.freecdt);
+		safe_snprintf(str,maxlen,"%" PRIu64,useron.cdt+useron.freecdt);
 		return(str);
 	}
 
 	if(strcmp(sp, "CREDITS") == 0) {
-		safe_snprintf(str, maxlen, "%lu", useron.cdt);
+		safe_snprintf(str, maxlen, "%" PRIu64, useron.cdt);
 		return str;
 	}
 
 	if(strcmp(sp, "FREECDT") == 0) {
-		safe_snprintf(str, maxlen, "%lu", useron.freecdt);
+		safe_snprintf(str, maxlen, "%" PRIu64, useron.freecdt);
 		return str;
 	}
 
@@ -1716,11 +1716,11 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen, long* pmode, bool
 		else if(!strcmp(sp,"ULS"))
 			safe_snprintf(str,maxlen,"%lu", (ulong)stats.uls);
 		else if(!strcmp(sp,"ULB"))
-			safe_snprintf(str,maxlen,"%lu", (ulong)stats.ulb);
+			safe_snprintf(str,maxlen,"%" PRIu64, stats.ulb);
 		else if(!strcmp(sp,"DLS"))
 			safe_snprintf(str,maxlen,"%lu", (ulong)stats.dls);
 		else if(!strcmp(sp,"DLB"))
-			safe_snprintf(str,maxlen,"%lu", (ulong)stats.dlb);
+			safe_snprintf(str,maxlen,"%" PRIu64, stats.dlb);
 		else if(!strcmp(sp,"PTODAY"))
 			safe_snprintf(str,maxlen,"%lu", (ulong)stats.ptoday);
 		else if(!strcmp(sp,"ETODAY"))
diff --git a/src/sbbs3/bat_xfer.cpp b/src/sbbs3/bat_xfer.cpp
index f34a3ef208..9ad5fba71b 100644
--- a/src/sbbs3/bat_xfer.cpp
+++ b/src/sbbs3/bat_xfer.cpp
@@ -124,10 +124,10 @@ void sbbs_t::batchmenu()
 						getfiletime(&cfg, &f);
 						bprintf(text[DownloadQueueLstFmt],i+1
 							,filename
-							,i64toac(f.cost, tmp)
-							,i64toac(f.size, str)
+							,byte_estimate_to_str(f.cost, tmp, sizeof(tmp), 1, 1)
+							,byte_estimate_to_str(f.size, str, sizeof(str), 1, 1)
 							,cur_cps
-								? sectostr((uint)(f.size/(ulong)cur_cps),tmp2)
+								? sectostr((uint)(f.size/(uint64_t)cur_cps), tmp2)
 								: "??:??:??"
 							,datestr(f.time)
 						);
@@ -136,9 +136,9 @@ void sbbs_t::batchmenu()
 						smb_freefilemem(&f);
 					}
 					bprintf(text[DownloadQueueTotals]
-						,ultoac((ulong)totalcdt,tmp),ultoac((ulong)totalsize,str),cur_cps
-						? sectostr((ulong)totalsize/(ulong)cur_cps,tmp2)
-						: "??:??:??"); 
+						,byte_estimate_to_str(totalcdt, tmp, sizeof(tmp), 1, 1)
+						,byte_estimate_to_str(totalsize, str, sizeof(tmp), 1, 1)
+						,cur_cps ? sectostr((uint)(totalsize/(uint64_t)cur_cps), tmp2) : "??:??:??"); 
 				} else
 					bputs(text[DownloadQueueIsEmpty]);
 				iniFreeStringList(filenames);
@@ -253,7 +253,7 @@ BOOL sbbs_t::start_batch_download()
 		return result;
 	}
 
-	int64_t totalcdt = 0;
+	uint64_t totalcdt = 0;
 	for(size_t i=0; filenames[i] != NULL; ++i) {
 		file_t f = {{}};
 		if(batch_file_load(&cfg, ini, filenames[i], &f)) {
@@ -261,9 +261,9 @@ BOOL sbbs_t::start_batch_download()
 			smb_freefilemem(&f);
 		}
 	}
-	if(totalcdt > (int64_t)(useron.cdt+useron.freecdt)) {
+	if(totalcdt > useron.cdt+useron.freecdt) {
 		bprintf(text[YouOnlyHaveNCredits]
-			,ultoac(useron.cdt+useron.freecdt,tmp));
+			,u64toac(useron.cdt+useron.freecdt,tmp));
 		iniFreeStringList(ini);
 		iniFreeStringList(filenames);
 		return(FALSE); 
@@ -690,7 +690,7 @@ bool sbbs_t::addtobatdl(file_t* f)
 			totalcost += f->cost;
 		if(totalcost > useron.cdt+useron.freecdt) {
 			bprintf(text[CantAddToQueue],f->name);
-			bprintf(text[YouOnlyHaveNCredits],ultoac(useron.cdt+useron.freecdt,tmp));
+			bprintf(text[YouOnlyHaveNCredits],u64toac(useron.cdt+useron.freecdt,tmp));
 		} else {
 			totalsize += f->size;
 			if(!(cfg.dir[f->dir]->misc&DIR_TFREE) && cur_cps)
@@ -701,9 +701,10 @@ bool sbbs_t::addtobatdl(file_t* f)
 			} else {
 				if(batch_file_add(&cfg, useron.number, XFER_BATCH_DOWNLOAD, f)) {
 					bprintf(text[FileAddedToBatDlQueue]
-						,f->name, strListCount(filenames) + 1, cfg.max_batdn, i64toac(totalcost,tmp)
-						,i64toac(totalsize,tmp2)
-						,sectostr((ulong)(totalsize/MAX((ulong)cur_cps, 1)),str));
+						,f->name, strListCount(filenames) + 1, cfg.max_batdn
+						,byte_estimate_to_str(totalcost, tmp, sizeof(tmp), 1, 1)
+						,byte_estimate_to_str(totalsize, tmp2, sizeof(tmp2), 1, 1)
+						,sectostr((uint)(totalsize/MAX((uint64_t)cur_cps, 1)),str));
 					result = true;
 				}
 			}
diff --git a/src/sbbs3/chat.cpp b/src/sbbs3/chat.cpp
index 2ffe4ca8a6..f8290fcd82 100644
--- a/src/sbbs3/chat.cpp
+++ b/src/sbbs3/chat.cpp
@@ -1666,7 +1666,7 @@ void sbbs_t::guruchat(char* line, char* gurubuf, int gurunum, char* last_answer)
 							break;
 						case 'D':
                     		if(sys_status&SS_USERON) {
-								SAFECAT(theanswer,ultoac(useron.dlb,tmp));
+								SAFECAT(theanswer,u64toac(useron.dlb,tmp));
 							} else {
 								SAFECAT(theanswer,"0");
 							}
@@ -1730,7 +1730,7 @@ void sbbs_t::guruchat(char* line, char* gurubuf, int gurunum, char* last_answer)
 							break;
 						case 'U':
                     		if(sys_status&SS_USERON) {
-								SAFECAT(theanswer,ultoac(useron.ulb,tmp));
+								SAFECAT(theanswer,u64toac(useron.ulb,tmp));
 							} else {
 								SAFECAT(theanswer,"0");
 							}
@@ -1751,7 +1751,7 @@ void sbbs_t::guruchat(char* line, char* gurubuf, int gurunum, char* last_answer)
 							break;
 						case '$':   /* Credits */
                     		if(sys_status&SS_USERON) {
-								SAFECAT(theanswer,ultoac(useron.cdt,tmp));
+								SAFECAT(theanswer,u64toac(useron.cdt,tmp));
 							} else {
 								SAFECAT(theanswer,"0");
 							}
diff --git a/src/sbbs3/chk_ar.cpp b/src/sbbs3/chk_ar.cpp
index 2318b03b6c..6d3433417b 100644
--- a/src/sbbs3/chk_ar.cpp
+++ b/src/sbbs3/chk_ar.cpp
@@ -25,7 +25,7 @@ bool sbbs_t::ar_exp(const uchar **ptrptr, user_t* user, client_t* client)
 {
 	bool	result,_not,_or,equal;
 	uint	i,n,artype,age;
-	ulong	l;
+	uint64_t l;
 	struct tm tm;
 	const char*	p;
 
@@ -294,7 +294,7 @@ bool sbbs_t::ar_exp(const uchar **ptrptr, user_t* user, client_t* client)
 				}
 				break;
 			case AR_CREDIT:
-				l=(ulong)i*1024UL;
+				l = i * 1024UL;
 				if((equal && user->cdt+user->freecdt!=l)
 					|| (!equal && user->cdt+user->freecdt<l))
 					result=_not;
@@ -303,7 +303,7 @@ bool sbbs_t::ar_exp(const uchar **ptrptr, user_t* user, client_t* client)
 				(*ptrptr)++;
 				if(!result) {
 					noaccess_str=text[NoAccessCredit];
-					noaccess_val=l; 
+					noaccess_val=(long)l; 
 				}
 				break;
 			case AR_NODE:
diff --git a/src/sbbs3/data.cpp b/src/sbbs3/data.cpp
index 18a8218540..428d74bf23 100644
--- a/src/sbbs3/data.cpp
+++ b/src/sbbs3/data.cpp
@@ -225,8 +225,8 @@ ulong sbbs_t::gettimeleft(bool handle_out_of_time)
 				SAFEPRINTF(tmp,text[Convert100ktoNminQ],cfg.cdt_min_value);
 				if(yesno(tmp)) {
 					logline("  ","Credit to Minute Conversion");
-					useron.min=adjustuserrec(&cfg,useron.number,U_MIN,10,cfg.cdt_min_value);
-					useron.cdt=adjustuserrec(&cfg,useron.number,U_CDT,10,-(102400L));
+					useron.min=(uint32_t)adjustuserrec(&cfg,useron.number,U_MIN,cfg.cdt_min_value);
+					useron.cdt=adjustuserrec(&cfg,useron.number,U_CDT,-(102400LL));
 					SAFEPRINTF(str,"Credit Adjustment: %ld",-(102400L));
 					logline("$-",str);
 					SAFEPRINTF(str,"Minute Adjustment: %u",cfg.cdt_min_value);
diff --git a/src/sbbs3/download.cpp b/src/sbbs3/download.cpp
index 1db61078e5..669d7ce629 100644
--- a/src/sbbs3/download.cpp
+++ b/src/sbbs3/download.cpp
@@ -68,7 +68,7 @@ void sbbs_t::notdownloaded(off_t size, time_t start, time_t end)
 		&& end-start>=(double)(size/cur_cps)*(double)cfg.leech_pct/100.0) {
 		lprintf(LOG_ERR, "Node %d Possible use of leech protocol (leech=%u  downloads=%u)"
 			,cfg.node_num, useron.leech+1,useron.dls);
-		useron.leech=(uchar)adjustuserrec(&cfg,useron.number,U_LEECH,2,1);
+		useron.leech=(uchar)adjustuserrec(&cfg,useron.number,U_LEECH,1);
 	}
 }
 
@@ -393,8 +393,8 @@ bool sbbs_t::sendfile(char* fname, char prot, const char* desc, bool autohang)
 		off_t length = flength(fname);
 		logon_dlb += length;	/* Update stats */
 		logon_dls++;
-		useron.dls = (ushort)adjustuserrec(&cfg, useron.number, U_DLS, 5, 1);
-		useron.dlb = adjustuserrec(&cfg,useron.number, U_DLB, 10, (long)length);
+		useron.dls = (ushort)adjustuserrec(&cfg, useron.number, U_DLS, 1);
+		useron.dlb = (uint32_t)adjustuserrec(&cfg,useron.number, U_DLB, length);
 		char bytes[32];
 		ultoac((ulong)length, bytes);
 		bprintf(text[FileNBytesSent], getfname(fname), bytes);
diff --git a/src/sbbs3/exec.cpp b/src/sbbs3/exec.cpp
index 9e6f9b8f8b..6d5167c79a 100644
--- a/src/sbbs3/exec.cpp
+++ b/src/sbbs3/exec.cpp
@@ -1433,12 +1433,12 @@ int sbbs_t::exec(csi_t *csi)
 				if(l<0)
 					subtract_cdt(&cfg,&useron,-l);
 				else
-					useron.cdt=adjustuserrec(&cfg,useron.number,U_CDT,10,l);
+					useron.cdt=adjustuserrec(&cfg,useron.number,U_CDT,l);
 				csi->ip+=2;
 				return(0);
 			case CS_ADJUST_USER_MINUTES:
 				i=*(short *)csi->ip;
-				useron.min=adjustuserrec(&cfg,useron.number,U_MIN,10,i);
+				useron.min=(uint32_t)adjustuserrec(&cfg,useron.number,U_MIN,i);
 				csi->ip+=2;
 				return(0);
 			case CS_GETNUM:
diff --git a/src/sbbs3/file.cpp b/src/sbbs3/file.cpp
index 9a2059a6cc..6483776e4b 100644
--- a/src/sbbs3/file.cpp
+++ b/src/sbbs3/file.cpp
@@ -39,11 +39,11 @@ void sbbs_t::showfileinfo(file_t* f, bool show_extdesc)
 	bprintf(P_TRUNCATE, text[FiFilename],f->name);
 
 	if(getfilesize(&cfg, f) >= 0)
-		bprintf(P_TRUNCATE, text[FiFileSize], i64toac(f->size,tmp)
+		bprintf(P_TRUNCATE, text[FiFileSize], u64toac(f->size,tmp)
 			, byte_estimate_to_str(f->size, tmp2, sizeof(tmp2), /* units: */1024, /* precision: */1));
 
 	bprintf(P_TRUNCATE, text[FiCredits]
-		,(cfg.dir[f->dir]->misc&DIR_FREE || !f->cost) ? "FREE" : i64toac(f->cost,tmp));
+		,(cfg.dir[f->dir]->misc&DIR_FREE || !f->cost) ? "FREE" : u64toac(f->cost,tmp));
 	if(getfilesize(&cfg, f) > 0 &&  (uint64_t)f->size == smb_getfilesize(&f->idx)) {
 #if 0 // I don't think anyone cares about the CRC-16 checksum value of a file
 		if(f->file_idx.hash.flags & SMB_HASH_CRC16) {
@@ -178,7 +178,7 @@ bool sbbs_t::removefcdt(file_t* f)
 			&& f->hdr.times_downloaded)  /* all downloads */
 			cdt+=((ulong)((long)f->hdr.times_downloaded
 				*f->cost*(cfg.dir[f->dir]->dn_pct/100.0))/cur_cps)/60;
-		adjustuserrec(&cfg,u,U_MIN,10,-cdt);
+		adjustuserrec(&cfg,u,U_MIN,-cdt);
 		sprintf(str,"%lu minute",cdt);
 		sprintf(tmp,text[FileRemovedUserMsg]
 			,f->name,cdt ? str : text[No]);
@@ -199,14 +199,14 @@ bool sbbs_t::removefcdt(file_t* f)
 				return false;
 			cdt = atol(str); 
 		}
-		adjustuserrec(&cfg,u,U_CDT,10,-cdt);
+		adjustuserrec(&cfg,u,U_CDT,-cdt);
 		sprintf(tmp,text[FileRemovedUserMsg]
 			,f->name,cdt ? ultoac(cdt,str) : text[No]);
 		putsmsg(&cfg,u,tmp);
 	}
 
-	adjustuserrec(&cfg,u,U_ULB,10,(long)-f->size);
-	adjustuserrec(&cfg,u,U_ULS,5,-1);
+	adjustuserrec(&cfg,u,U_ULB,-f->size);
+	adjustuserrec(&cfg,u,U_ULS,-1);
 	return(true);
 }
 
diff --git a/src/sbbs3/filedat.c b/src/sbbs3/filedat.c
index 2721d9d61e..ae598427c2 100644
--- a/src/sbbs3/filedat.c
+++ b/src/sbbs3/filedat.c
@@ -1286,7 +1286,7 @@ char* cmdstr(scfg_t* cfg, user_t* user, const char* instr, const char* fpath
                     break;
                 case '$':   /* Credits */
 					if(user!=NULL)
-						strncat(cmd,ultoa(user->cdt+user->freecdt,str,10), avail);
+						strncat(cmd,_ui64toa(user->cdt+user->freecdt,str,10), avail);
                     break;
                 case '%':   /* %% for percent sign */
                     strncat(cmd,"%", avail);
diff --git a/src/sbbs3/filelist.c b/src/sbbs3/filelist.c
index b2eadb5012..c0fa9a0e0a 100644
--- a/src/sbbs3/filelist.c
+++ b/src/sbbs3/filelist.c
@@ -57,7 +57,7 @@ int lprintf(int level, const char *fmat, ...)
 	return(chcount);
 }
 
-char* byteStr(unsigned long value)
+char* byteStr(uint64_t value)
 {
 	static char tmp[128];
 
@@ -109,8 +109,9 @@ int main(int argc, char **argv)
 	int 	i,j,dirnum,libnum,desc_off,lines,nots=0;
 	char*	omode="w";
 	char*	pattern=NULL;
-	ulong	m,misc=0,total_cdt=0,total_files=0,dir_files;
+	ulong	m,misc=0,total_files=0,dir_files;
 	uint64_t cdt;
+	uint64_t total_cdt=0;
 	long	max_age=0;
 	FILE*	out=NULL;
 
@@ -450,7 +451,7 @@ int main(int argc, char **argv)
 	}
 
 	if(misc&TOT && !(misc&AUTO))
-		fprintf(out,"TOTALS\n------\n%lu credits/bytes in %lu files.\n"
+		fprintf(out,"TOTALS\n------\n%" PRIu64 " credits/bytes in %lu files.\n"
 			,total_cdt,total_files);
 	printf("\nDone.\n");
 	return(0);
diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c
index 6fc323c791..17bfca6d28 100644
--- a/src/sbbs3/ftpsrvr.c
+++ b/src/sbbs3/ftpsrvr.c
@@ -775,12 +775,12 @@ static void send_thread(void* arg)
 						l=0;
 					if(scfg.dir[f.dir]->misc&DIR_CDTMIN && cps) { /* Give min instead of cdt */
 						mod=((ulong)(l*(scfg.dir[f.dir]->dn_pct/100.0))/cps)/60;
-						adjustuserrec(&scfg,uploader.number,U_MIN,10,mod);
+						adjustuserrec(&scfg,uploader.number,U_MIN,mod);
 						sprintf(tmp,"%lu minute",mod);
 					} else {
 						mod=(ulong)(l*(scfg.dir[f.dir]->dn_pct/100.0));
-						adjustuserrec(&scfg,uploader.number,U_CDT,10,mod);
-						ultoac(mod,tmp);
+						adjustuserrec(&scfg,uploader.number,U_CDT,mod);
+						u32toac(mod,tmp,',');
 					}
 					if(!(scfg.dir[f.dir]->misc&DIR_QUIET)) {
 						const char* prefix = xfer.filepos ? "partially FTP-" : "FTP-";
@@ -1071,11 +1071,11 @@ static void receive_thread(void* arg)
 			user_uploaded(&scfg, xfer.user, (!xfer.append && xfer.filepos==0) ? 1:0, total);
 			if(scfg.dir[f.dir]->up_pct && scfg.dir[f.dir]->misc&DIR_CDTUL) { /* credit for upload */
 				if(scfg.dir[f.dir]->misc&DIR_CDTMIN && cps)    /* Give min instead of cdt */
-					xfer.user->min=adjustuserrec(&scfg,xfer.user->number,U_MIN,10
+					xfer.user->min=(uint32_t)adjustuserrec(&scfg,xfer.user->number,U_MIN
 						,((ulong)(total*(scfg.dir[f.dir]->up_pct/100.0))/cps)/60);
 				else
-					xfer.user->cdt=adjustuserrec(&scfg,xfer.user->number,U_CDT,10
-						,(ulong)(cdt*(scfg.dir[f.dir]->up_pct/100.0))); 
+					xfer.user->cdt=adjustuserrec(&scfg,xfer.user->number,U_CDT
+						,cdt*(uint64_t)(scfg.dir[f.dir]->up_pct/100.0)); 
 			}
 			if(!(scfg.dir[f.dir]->misc&DIR_NOSTAT))
 				inc_sys_upload_stats(&scfg, 1, (ulong)total);
diff --git a/src/sbbs3/getmsg.cpp b/src/sbbs3/getmsg.cpp
index 0923a4269d..6197e69e2a 100644
--- a/src/sbbs3/getmsg.cpp
+++ b/src/sbbs3/getmsg.cpp
@@ -409,17 +409,17 @@ void sbbs_t::download_msg_attachments(smb_t* smb, smbmsg_t* msg, bool del)
 				if(!fexistcase(fpath) && msg->idx.from)
 					SAFEPRINTF3(fpath,"%sfile/%04u.out/%s"  /* path is path/fname */
 						,cfg.data_dir, msg->idx.from,tp);
-				long length=(long)flength(fpath);
+				off_t length=flength(fpath);
 				if(length<1)
 					bprintf(text[FileDoesNotExist], tp);
 				else if(!(useron.exempt&FLAG('T')) && cur_cps && !SYSOP
-					&& length/(long)cur_cps>(time_t)timeleft)
+					&& length/cur_cps>(time_t)timeleft)
 					bputs(text[NotEnoughTimeToDl]);
 				else {
 					char 	tmp[512];
 					int		i;
 					SAFEPRINTF2(str, text[DownloadAttachedFileQ]
-						,getfname(fpath),ultoac(length,tmp));
+						,getfname(fpath),u64toac(length,tmp));
 					if(length>0L && text[DownloadAttachedFileQ][0] && yesno(str)) {
 						{	/* Remote User */
 							xfer_prot_menu(XFER_DOWNLOAD);
@@ -444,11 +444,11 @@ void sbbs_t::download_msg_attachments(smb_t* smb, smbmsg_t* msg, bool del)
 									logon_dlb+=length;	/* Update stats */
 									logon_dls++;
 									useron.dls=(ushort)adjustuserrec(&cfg,useron.number
-										,U_DLS,5,1);
+										,U_DLS,1);
 									useron.dlb=adjustuserrec(&cfg,useron.number
-										,U_DLB,10,length);
+										,U_DLB,length);
 									bprintf(text[FileNBytesSent]
-										,getfname(fpath),ultoac(length,tmp));
+										,getfname(fpath),u64toac(length,tmp));
 									SAFEPRINTF(str
 										,"downloaded attached file: %s"
 										,getfname(fpath));
diff --git a/src/sbbs3/js_user.c b/src/sbbs3/js_user.c
index 4ad482bd10..6e91e515f3 100644
--- a/src/sbbs3/js_user.c
+++ b/src/sbbs3/js_user.c
@@ -262,20 +262,25 @@ static JSBool js_user_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 			val=p->user->ptoday;
 			break;
 		case USER_PROP_ULB:
-			val=p->user->ulb;
+			*vp = DOUBLE_TO_JSVAL((jsdouble)p->user->ulb);
+			JS_RESUMEREQUEST(cx, rc);
+			return JS_TRUE;	/* intentional early return */
 			break;
 		case USER_PROP_ULS:
 			val=p->user->uls;
 			break;
 		case USER_PROP_DLB:
-			val=p->user->dlb;
+			*vp = DOUBLE_TO_JSVAL((jsdouble)p->user->dlb);
+			JS_RESUMEREQUEST(cx, rc);
+			return JS_TRUE;	/* intentional early return */
 			break;
 		case USER_PROP_DLS:
 			val=p->user->dls;
 			break;
 		case USER_PROP_CDT:
-			val=p->user->cdt;
-			break;
+			*vp = DOUBLE_TO_JSVAL((jsdouble)p->user->cdt);
+			JS_RESUMEREQUEST(cx, rc);
+			return JS_TRUE;	/* intentional early return */
 		case USER_PROP_MIN:
 			val=p->user->min;
 			break;
@@ -327,8 +332,9 @@ static JSBool js_user_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 			break;
 
 		case USER_PROP_FREECDT:
-			val=p->user->freecdt;
-			break;
+			*vp = DOUBLE_TO_JSVAL((jsdouble)p->user->freecdt);
+			JS_RESUMEREQUEST(cx, rc);
+			return JS_TRUE;	/* intentional early return */
 		case USER_PROP_XEDIT:
 			if(p->user->xedit>0 && p->user->xedit<=scfg->total_xedits)
 				s=scfg->xedit[p->user->xedit-1]->code;
@@ -722,11 +728,11 @@ static JSBool js_user_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict,
 			rc=JS_SUSPENDREQUEST(cx);
 			break;
 		case USER_PROP_CDT:	
-			p->user->cdt=strtoul(str,NULL,0);
+			p->user->cdt=strtoull(str,NULL,0);
 			putuserrec(scfg,p->user->number,U_CDT,0,str);
 			break;
 		case USER_PROP_FREECDT:
-			p->user->freecdt=strtoul(str,NULL,0);
+			p->user->freecdt=strtoull(str,NULL,0);
 			putuserrec(scfg,p->user->number,U_FREECDT,0,str);
 			break;
 		case USER_PROP_MIN:	
diff --git a/src/sbbs3/listfile.cpp b/src/sbbs3/listfile.cpp
index 8b99f3b268..552e887de5 100644
--- a/src/sbbs3/listfile.cpp
+++ b/src/sbbs3/listfile.cpp
@@ -940,7 +940,7 @@ int sbbs_t::listfileinfo(uint dirnum, const char *filespec, long mode)
 				&& f->cost>(useron.cdt+useron.freecdt)) {
 				SYNC;
 				bprintf(text[YouOnlyHaveNCredits]
-					,ultoac(useron.cdt+useron.freecdt,tmp));
+					,u64toac(useron.cdt+useron.freecdt,tmp));
 				mnemonics(text[QuitOrNext]);
 				if(getkeys("\rQ",0)=='Q') {
 					found=-1;
diff --git a/src/sbbs3/logon.cpp b/src/sbbs3/logon.cpp
index 626630f029..e8ef49151c 100644
--- a/src/sbbs3/logon.cpp
+++ b/src/sbbs3/logon.cpp
@@ -241,9 +241,9 @@ bool sbbs_t::logon()
 				getfilesize(&cfg, &f);
 				bprintf(text[FileAddedToBatDlQueue]
 					,f.name, i + 1, cfg.max_batdn
-					,ultoac((ulong)f.cost,tmp)
-					,ultoac((ulong)f.size,tmp2)
-					,sectostr((ulong)f.size / (ulong)cur_cps,str));
+					,byte_estimate_to_str(f.cost, tmp, sizeof(tmp), 1, 1)
+					,byte_estimate_to_str(f.size, tmp2, sizeof(tmp2), 1, 1)
+					,sectostr((uint)(f.size / (uint64_t)cur_cps),str));
 				smb_freefilemem(&f);
 			} else
 				batch_file_remove(&cfg, useron.number, XFER_BATCH_DOWNLOAD, filename);
diff --git a/src/sbbs3/netmail.cpp b/src/sbbs3/netmail.cpp
index 375fcf6081..5dcf191d3d 100644
--- a/src/sbbs3/netmail.cpp
+++ b/src/sbbs3/netmail.cpp
@@ -338,9 +338,9 @@ bool sbbs_t::netmail(const char *into, const char *title, long mode, smb_t* resm
 		return false;
 	}
 
-	useron.emails = (ushort)adjustuserrec(&cfg, useron.number, U_EMAILS, 0, 1);
+	useron.emails = (ushort)adjustuserrec(&cfg, useron.number, U_EMAILS, 1);
 	logon_emails++;
-	useron.etoday = (ushort)adjustuserrec(&cfg, useron.number, U_ETODAY, 0, 1);
+	useron.etoday = (ushort)adjustuserrec(&cfg, useron.number, U_ETODAY, 1);
 	if(!(useron.exempt&FLAG('S')))
 		subtract_cdt(&cfg,&useron,cfg.netmail_cost);
 
diff --git a/src/sbbs3/pack_qwk.cpp b/src/sbbs3/pack_qwk.cpp
index 0da138a1fd..8bf391660d 100644
--- a/src/sbbs3/pack_qwk.cpp
+++ b/src/sbbs3/pack_qwk.cpp
@@ -657,7 +657,7 @@ bool sbbs_t::pack_qwk(char *packet, ulong *msgcnt, bool prepack)
 			if(!is_download_free(&cfg, f.dir, &useron, &client)) {
 				if(totalcdt + f.cost > (uint64_t)(useron.cdt+useron.freecdt)) {
 					bprintf(text[YouOnlyHaveNCredits]
-						,ultoac(useron.cdt+useron.freecdt,tmp));
+						,u64toac(useron.cdt+useron.freecdt,tmp));
 					batch_file_remove(&cfg, useron.number, XFER_BATCH_DOWNLOAD, filename);
 					continue;
 				}
diff --git a/src/sbbs3/qwk.cpp b/src/sbbs3/qwk.cpp
index 6a50324adc..f45336d277 100644
--- a/src/sbbs3/qwk.cpp
+++ b/src/sbbs3/qwk.cpp
@@ -584,7 +584,7 @@ void sbbs_t::qwk_sec()
 
 			off_t l=flength(str);
 			bprintf(text[FiFilename], getfname(str));
-			bprintf(text[FiFileSize], ultoac((ulong)l,tmp)
+			bprintf(text[FiFileSize], u64toac(l,tmp)
 				, byte_estimate_to_str(l, tmp2, sizeof(tmp2), /* units: */1024, /* precision: */1));
 
 			if(l>0L && cur_cps)
diff --git a/src/sbbs3/readmsgs.cpp b/src/sbbs3/readmsgs.cpp
index 13c94fa298..f52165688e 100644
--- a/src/sbbs3/readmsgs.cpp
+++ b/src/sbbs3/readmsgs.cpp
@@ -903,7 +903,7 @@ int sbbs_t::scanposts(uint subnum, long mode, const char *find)
 							if(!stricmp(cfg.sub[subnum]->misc&SUB_NAME
 								? useron.name : useron.alias, msg.from))
 								useron.posts=(ushort)adjustuserrec(&cfg,useron.number
-									,U_POSTS,5,-1); 
+									,U_POSTS,-1); 
 						} 
 					}
 					smb_unlocksmbhdr(&smb);
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index dabf50743a..ef00b37610 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -722,6 +722,8 @@ public:
 	bool	chkpass(char *pass, user_t* user, bool unique);
 	char *	cmdstr(const char *instr, const char *fpath, const char *fspec, char *outstr, long mode = EX_UNSPECIFIED);
 	char	cmdstr_output[512];
+	char*	ultoac(uint32_t, char*, char sep=',');
+	char*	u64toac(uint64_t, char*, char sep=',');
 
 	void	subinfo(uint subnum);
 	void	dirinfo(uint dirnum);
diff --git a/src/sbbs3/sbbsdefs.h b/src/sbbs3/sbbsdefs.h
index 591f455bec..36c9f23616 100644
--- a/src/sbbs3/sbbsdefs.h
+++ b/src/sbbs3/sbbsdefs.h
@@ -510,13 +510,14 @@ typedef enum {						/* Values for xtrn_t.event				*/
 #define LEN_FDESC		58	/* File description (summary) 					*/
 #define LEN_EXTDESC		5000	/* Extended file description				*/
 #define LEN_TITLE		70	/* Message title								*/
-#define LEN_MAIN_CMD	28	/* Unused Storage in user.dat					*/
+#define LEN_CDT			20	/* Maximum credit length: 18446744073709551616	*/
+#define LEN_MAIN_CMD	8	/* Unused Storage in user.dat					*/
 #define LEN_COLS		3
 #define LEN_ROWS		3
 #define LEN_PASS		40
 #define MIN_PASS_LEN	 4
 #define RAND_PASS_LEN	 8
-#define LEN_SCAN_CMD	35
+#define LEN_SCAN_CMD	15
 #define LEN_IPADDR		45
 #define LEN_CID 		45	/* Caller ID (phone number) 					*/
 #define LEN_ARSTR		40	/* Max length of Access Requirement string		*/
@@ -565,8 +566,8 @@ typedef enum {						/* Values for xtrn_t.event				*/
 #define U_ULS       U_ULB+10
 #define U_DLB       U_ULS+5
 #define U_DLS       U_DLB+10
-#define U_CDT		U_DLS+5
-#define U_MIN		U_CDT+10
+#define U_OLDCDT	U_DLS+5
+#define U_MIN		U_OLDCDT+10
 
 #define U_LEVEL 	U_MIN+10+2 	/* Offset to Security Level    */
 #define U_FLAGS1	U_LEVEL+2  	/* Offset to Flags */
@@ -583,12 +584,14 @@ typedef enum {						/* Values for xtrn_t.event				*/
 #define U_CURXTRN	U_CURSUB+16 /* Current xtrn (internal code) */
 #define U_ROWS		U_CURXTRN+8+2
 #define U_COLS		U_ROWS+LEN_ROWS
-#define U_MAIN_CMD	U_COLS+LEN_COLS	/* unused */
+#define U_CDT		U_COLS+LEN_COLS	/* unused */
+#define U_MAIN_CMD	U_CDT+LEN_CDT
 #define U_PASS		U_MAIN_CMD+LEN_MAIN_CMD
-#define U_SCAN_CMD	U_PASS+LEN_PASS+2  				/* unused */
-#define U_IPADDR	U_SCAN_CMD+LEN_SCAN_CMD 		/* unused */
-#define U_FREECDT	U_IPADDR+LEN_IPADDR+2
-#define U_FLAGS3	U_FREECDT+10 	/* Flag set #3 */
+#define U_FREECDT	U_PASS+LEN_PASS+2
+#define U_SCAN_CMD	U_FREECDT+LEN_CDT  				/* unused */
+#define U_IPADDR	U_SCAN_CMD+LEN_SCAN_CMD
+#define U_OLDFREECDT U_IPADDR+LEN_IPADDR+2			/* unused */
+#define U_FLAGS3	U_OLDFREECDT+10 	/* Flag set #3 */
 #define U_FLAGS4	U_FLAGS3+8 	/* Flag set #4 */
 #define U_XEDIT 	U_FLAGS4+8 	/* External editor (code  */
 #define U_SHELL 	U_XEDIT+8  	/* Command shell (code  */
@@ -1007,7 +1010,7 @@ typedef struct {						/* Users information */
 	int		rows,               		/* Rows on terminal (0 = auto-detect) */
 			cols;						/* Columns on terminal (0 = auto-detect) */
 
-	ulong	misc,						/* Misc. bits - ANSI, Deleted etc. */
+	uint32_t misc,						/* Misc. bits - ANSI, Deleted etc. */
 			qwk,						/* QWK settings */
 			chat,						/* Chat defaults */
 			flags1, 					/* Flag set #1 */
@@ -1016,11 +1019,11 @@ typedef struct {						/* Users information */
 			flags4, 					/* Flag set #4 */
 			exempt,						/* Exemption Flags */
 			rest,						/* Restriction Flags */
-			ulb,						/* Total bytes uploaded */
-			dlb,						/* Total bytes downloaded */
-			cdt,						/* Credits */
-			min,						/* Minutes */
-			freecdt;					/* Free credits (renewed daily) */
+			min;						/* Minutes */
+	uint64_t cdt;						/* Credits */
+	uint64_t freecdt;					/* Free credits (renewed daily) */
+	uint64_t ulb;						/* Total bytes uploaded */
+	uint64_t dlb;						/* Total bytes downloaded */
 	time32_t firston,					/* Date/Time first called */
 			laston, 					/* Last logoff date/time */
 			expire, 					/* Expiration date */
diff --git a/src/sbbs3/scfg/scfgsys.c b/src/sbbs3/scfg/scfgsys.c
index 6d35ada31d..88a1501432 100644
--- a/src/sbbs3/scfg/scfgsys.c
+++ b/src/sbbs3/scfg/scfgsys.c
@@ -891,9 +891,9 @@ void sys_cfg(void)
 					sprintf(opt[i++],"%-27.27s%s","Expiration Days"
 						,ultoa(cfg.new_expire,str,10));
 
-					ultoac(cfg.new_cdt,str);
+					u32toac(cfg.new_cdt,str,',');
 					sprintf(opt[i++],"%-27.27s%s","Credits",str);
-					ultoac(cfg.new_min,str);
+					u32toac(cfg.new_min,str,',');
 					sprintf(opt[i++],"%-27.27s%s","Minutes",str);
 					sprintf(opt[i++],"%-27.27s%s","Editor"
 						,cfg.new_xedit);
@@ -1367,7 +1367,7 @@ void sys_cfg(void)
 						,cfg.new_sif);
 					sprintf(opt[i++],"%-27.27s%s","Output SIF Questionnaire"
 						,cfg.new_sof);
-					ultoac(cfg.cdt_per_dollar,str);
+					u32toac(cfg.cdt_per_dollar,str,',');
 					sprintf(opt[i++],"%-27.27s%s","Credits Per Dollar",str);
 					sprintf(opt[i++],"%-27.27s%u","Minutes Per 100k Credits"
 						,cfg.cdt_min_value);
@@ -1951,9 +1951,9 @@ void sys_cfg(void)
 								byte_count_to_str(cfg.level_freecdtperday[i], tmp, sizeof(tmp));
 								if(uifc.input(WIN_MID|WIN_SAV,0,0
 									,"Free Credits Awarded Per Day"
-									,tmp,10
+									,tmp,19
 									,K_EDIT|K_UPPER) > 0)
-									cfg.level_freecdtperday[i] = (int32_t)parse_byte_count(tmp, 1);
+									cfg.level_freecdtperday[i] = parse_byte_count(tmp, 1);
 								break;
 							case 7:
 								j=0;
diff --git a/src/sbbs3/scfgdefs.h b/src/sbbs3/scfgdefs.h
index f86c20517b..9e6e619df2 100644
--- a/src/sbbs3/scfgdefs.h
+++ b/src/sbbs3/scfgdefs.h
@@ -528,7 +528,7 @@ typedef struct
 					level_linespermsg[100],
 					level_postsperday[100],
 					level_emailperday[100];
-	int32_t			level_freecdtperday[100];
+	uint64_t		level_freecdtperday[100];
 	int32_t			level_misc[100];
 	char 			expired_level;	/* Expired user's ML */
 	uint32_t		expired_flags1; /* Flags from set #1 to remove when expired */
diff --git a/src/sbbs3/scfglib1.c b/src/sbbs3/scfglib1.c
index 7b98e1e3f0..9204302269 100644
--- a/src/sbbs3/scfglib1.c
+++ b/src/sbbs3/scfglib1.c
@@ -299,18 +299,21 @@ BOOL read_main_cfg(scfg_t* cfg, char* error, size_t maxerrlen)
 	/***************************/
 
 	for(i=0;i<100 && !feof(instream);i++) {
+		uint32_t freecdt32;
 		get_int(cfg->level_timeperday[i],instream);
 		get_int(cfg->level_timepercall[i],instream);
 		get_int(cfg->level_callsperday[i],instream);
-		get_int(cfg->level_freecdtperday[i],instream);
+		get_int(freecdt32,instream);
 		get_int(cfg->level_linespermsg[i],instream);
 		get_int(cfg->level_postsperday[i],instream);
 		get_int(cfg->level_emailperday[i],instream);
 		get_int(cfg->level_misc[i],instream);
 		get_int(cfg->level_expireto[i],instream);
+		get_int(cfg->level_freecdtperday[i],instream);
+		if(freecdt32)
+			cfg->level_freecdtperday[i] = freecdt32;
 		get_int(c,instream);
-		for(j=0;j<5;j++)
-			get_int(n,instream); 
+		get_int(n,instream); 
 	}
 	if(i!=100) {
 		safe_snprintf(error, maxerrlen,"Insufficient User Level Information: "
diff --git a/src/sbbs3/scfgsave.c b/src/sbbs3/scfgsave.c
index 29d00d7ce9..e1b3b19db2 100644
--- a/src/sbbs3/scfgsave.c
+++ b/src/sbbs3/scfgsave.c
@@ -280,18 +280,20 @@ BOOL write_main_cfg(scfg_t* cfg, int backup_level)
 
 	c=0;
 	for(i=0;i<100 && !feof(stream);i++) {
+		uint32_t l = 0;
 		put_int(cfg->level_timeperday[i],stream);
 		put_int(cfg->level_timepercall[i],stream);
 		put_int(cfg->level_callsperday[i],stream);
-		put_int(cfg->level_freecdtperday[i],stream);
+		put_int(l,stream);	// Used to be freecdtperday (32-bit)
 		put_int(cfg->level_linespermsg[i],stream);
 		put_int(cfg->level_postsperday[i],stream);
 		put_int(cfg->level_emailperday[i],stream);
 		put_int(cfg->level_misc[i],stream);
 		put_int(cfg->level_expireto[i],stream);
+		put_int(cfg->level_freecdtperday[i],stream);
 		put_int(c,stream);
-		for(j=0;j<5;j++)
-			put_int(n,stream); }
+		put_int(n,stream);
+	}
 
 	/* Command Shells */
 
diff --git a/src/sbbs3/str.cpp b/src/sbbs3/str.cpp
index 0939273a9b..7c605ff345 100644
--- a/src/sbbs3/str.cpp
+++ b/src/sbbs3/str.cpp
@@ -922,12 +922,12 @@ void sbbs_t::user_info()
 		,getmail(&cfg,useron.number,/* Sent: */FALSE, /* SPAM: */FALSE),useron.etoday);
 	CRLF;
 	bprintf(text[UserUploads]
-		,ultoac(useron.ulb,tmp),useron.uls);
+		,byte_estimate_to_str(useron.ulb, tmp, sizeof(tmp), 1, 1),useron.uls);
 	bprintf(text[UserDownloads]
-		,ultoac(useron.dlb,tmp),useron.dls,nulstr);
-	bprintf(text[UserCredits],ultoac(useron.cdt,tmp)
-		,ultoac(useron.freecdt,tmp2)
-		,ultoac(cfg.level_freecdtperday[useron.level],str));
+		,byte_estimate_to_str(useron.dlb, tmp, sizeof(tmp), 1, 1),useron.dls,nulstr);
+	bprintf(text[UserCredits],byte_estimate_to_str(useron.cdt, tmp, sizeof(tmp), 1, 1)
+		,byte_estimate_to_str(useron.freecdt,tmp2, sizeof(tmp2), 1, 1)
+		,byte_estimate_to_str(cfg.level_freecdtperday[useron.level], str, sizeof(str), 1, 1));
 	bprintf(text[UserMinutes],ultoac(useron.min,tmp));
 }
 
@@ -1166,8 +1166,8 @@ void sbbs_t::time_bank(void)
 		s=getnum(s);
 		if(s>0) {
 			logline("  ","Minute Bank Deposit");
-			useron.min=adjustuserrec(&cfg,useron.number,U_MIN,10,s);
-			useron.ttoday=(ushort)adjustuserrec(&cfg,useron.number,U_TTODAY,10,s);
+			useron.min=(uint32_t)adjustuserrec(&cfg,useron.number,U_MIN,s);
+			useron.ttoday=(ushort)adjustuserrec(&cfg,useron.number,U_TTODAY,s);
 			sprintf(str,"Minute Adjustment: %u",s*cfg.cdt_min_value);
 			logline("*+",str); 
 		} 
@@ -1176,27 +1176,27 @@ void sbbs_t::time_bank(void)
 	if(!(cfg.sys_misc&SM_NOCDTCVT)) {
 		bprintf(text[ConversionRate],cfg.cdt_min_value);
 		bprintf(text[UserCredits]
-			,ultoac(useron.cdt,tmp)
-			,ultoac(useron.freecdt,tmp2)
-			,ultoac(cfg.level_freecdtperday[useron.level],str));
+			,u64toac(useron.cdt,tmp)
+			,u64toac(useron.freecdt,tmp2)
+			,u64toac(cfg.level_freecdtperday[useron.level],str));
 		bprintf(text[UserMinutes],ultoac(useron.min,tmp));
 		if(useron.cdt/102400L<1L) {
-			bprintf(text[YouOnlyHaveNCredits],ultoac(useron.cdt,tmp));
+			bprintf(text[YouOnlyHaveNCredits],u64toac(useron.cdt,tmp));
 			return; 
 		}
 		if(cfg.max_minutes && useron.min>=cfg.max_minutes) {
 			bputs(text[YouHaveTooManyMinutes]);
 			return; 
 		}
-		s=useron.cdt/102400L;
+		s=(uint32_t)(useron.cdt/102400L);
 		if(cfg.max_minutes)
 			while(s>0 && (s*cfg.cdt_min_value)+useron.min>cfg.max_minutes) s--;
 		bprintf(text[CreditsToMin],s);
 		s=getnum(s);
 		if(s>0) {
 			logline("  ","Credit to Minute Conversion");
-			useron.cdt=adjustuserrec(&cfg,useron.number,U_CDT,10,-(s*102400L));
-			useron.min=adjustuserrec(&cfg,useron.number,U_MIN,10,s*(int)cfg.cdt_min_value);
+			useron.cdt=adjustuserrec(&cfg,useron.number,U_CDT,-(s*102400L));
+			useron.min=(uint32_t)adjustuserrec(&cfg,useron.number,U_MIN,s*(int)cfg.cdt_min_value);
 			sprintf(str,"Credit Adjustment: %ld",-(s*102400L));
 			logline("$-",str);
 			sprintf(str,"Minute Adjustment: %u",s*cfg.cdt_min_value);
@@ -1284,3 +1284,13 @@ char* sbbs_t::server_host_name(void)
 {
 	return startup->host_name[0] ? startup->host_name : cfg.sys_inetaddr;
 }
+
+char* sbbs_t::ultoac(uint32_t val, char* str, char sep)
+{
+	return ::u32toac(val, str, sep);
+}
+
+char* sbbs_t::u64toac(uint64_t val, char* str, char sep)
+{
+	return ::u64toac(val, str, sep);
+}
diff --git a/src/sbbs3/str_util.c b/src/sbbs3/str_util.c
index 64b85ef4f7..9991892fbd 100644
--- a/src/sbbs3/str_util.c
+++ b/src/sbbs3/str_util.c
@@ -476,9 +476,9 @@ str_list_t trashcan_list(scfg_t* cfg, const char* name)
 
 /****************************************************************************/
 /* Returns in 'string' a character representation of the number in l with   */
-/* commas.																	*/
+/* thousands separators (e.g. commas).										*/
 /****************************************************************************/
-char* ultoac(ulong l, char *string)
+char* u32toac(uint32_t l, char *string, char sep)
 {
 	char str[256];
 	int i,j,k;
@@ -490,24 +490,24 @@ char* ultoac(ulong l, char *string)
 	for(k=1;i>-1;k++) {
 		string[j--]=str[i--];
 		if(j>0 && !(k%3))
-			string[j--]=','; 
+			string[j--]=sep; 
 	}
 	return(string);
 }
 
-char* i64toac(int64_t l, char *string)
+char* u64toac(uint64_t l, char *string, char sep)
 {
 	char str[256];
 	int i,j,k;
 
-	_i64toa(l,str,10);
+	_ui64toa(l,str,10);
 	i=strlen(str)-1;
 	j=i/3+1+i;
 	string[j--]=0;
 	for(k=1;i>-1;k++) {
 		string[j--]=str[i--];
 		if(j>0 && !(k%3))
-			string[j--]=','; 
+			string[j--]=sep; 
 	}
 	return string;
 }
diff --git a/src/sbbs3/str_util.h b/src/sbbs3/str_util.h
index 269b13e911..5b9e4b44a4 100644
--- a/src/sbbs3/str_util.h
+++ b/src/sbbs3/str_util.h
@@ -63,8 +63,8 @@ DLLEXPORT char *	net_addr(net_t* net);
 DLLEXPORT BOOL		valid_ctrl_a_attr(char a);
 DLLEXPORT BOOL		valid_ctrl_a_code(char a);
 DLLEXPORT size_t	strip_invalid_attr(char *str);
-DLLEXPORT char *	ultoac(ulong l,char *str);
-DLLEXPORT char *	i64toac(int64_t, char *str);
+DLLEXPORT char *	u32toac(uint32_t, char*, char sep);
+DLLEXPORT char *	u64toac(uint64_t, char*, char sep);
 DLLEXPORT char *	rot13(char* str);
 DLLEXPORT uint32_t	str_to_bits(uint32_t currval, const char *str);
 DLLEXPORT BOOL		str_has_ctrl(const char*);
diff --git a/src/sbbs3/text_defaults.c b/src/sbbs3/text_defaults.c
index b2d2500a67..a1863252a1 100644
--- a/src/sbbs3/text_defaults.c
+++ b/src/sbbs3/text_defaults.c
@@ -719,15 +719,14 @@ const char * const text_defaults[TOTAL_TEXT]={
 		"\x67\x20\x20\x20\x3a\x20\x01\x68\x25\x2d\x35\x75\x20\x20\x20\x20\x20\x01\x6e\x01\x63\x54\x6f\x64\x61\x79\x20\x3a\x20\x01\x68\x25"
 		"\x75\x0d\x0a" // 431 UserEmails
 	,"\x01\x6e\x01\x63\x4e\x65\x74\x4d\x61\x69\x6c\x20\x20\x20\x3a\x20\x01\x68\x25\x73\x0d\x0a" // 432 UserNetMail
-	,"\x01\x6e\x01\x63\x55\x70\x6c\x6f\x61\x64\x73\x20\x20\x20\x3a\x20\x01\x68\x25\x31\x33\x2e\x31\x33\x73\x20\x01\x6e\x01\x63\x62\x79"
-		"\x74\x65\x73\x20\x69\x6e\x20\x01\x68\x25\x75\x20\x01\x6e\x01\x63\x66\x69\x6c\x65\x73\x0d\x0a" // 433 UserUploads
-	,"\x01\x6e\x01\x63\x44\x6f\x77\x6e\x6c\x6f\x61\x64\x73\x20\x3a\x20\x01\x68\x25\x31\x33\x2e\x31\x33\x73\x20\x01\x6e\x01\x63\x62\x79"
-		"\x74\x65\x73\x20\x69\x6e\x20\x01\x68\x25\x75\x20\x01\x6e\x01\x63\x66\x69\x6c\x65\x73\x20\x25\x73\x0d\x0a" // 434 UserDownloads
+	,"\x01\x6e\x01\x63\x55\x70\x6c\x6f\x61\x64\x73\x20\x20\x20\x3a\x20\x01\x68\x25\x39\x2e\x39\x73\x20\x01\x6e\x01\x63\x62\x79\x74\x65"
+		"\x73\x20\x69\x6e\x20\x01\x68\x25\x75\x20\x01\x6e\x01\x63\x66\x69\x6c\x65\x73\x0d\x0a" // 433 UserUploads
+	,"\x01\x6e\x01\x63\x44\x6f\x77\x6e\x6c\x6f\x61\x64\x73\x20\x3a\x20\x01\x68\x25\x39\x2e\x39\x73\x20\x01\x6e\x01\x63\x62\x79\x74\x65"
+		"\x73\x20\x69\x6e\x20\x01\x68\x25\x75\x20\x01\x6e\x01\x63\x66\x69\x6c\x65\x73\x20\x25\x73\x0d\x0a" // 434 UserDownloads
 	,"\x2d\x20\x4c\x65\x65\x63\x68\x3a\x20\x01\x72\x01\x68\x01\x69\x25\x75\x01\x6e" // 435 UserLeech
-	,"\x01\x6e\x01\x63\x43\x72\x65\x64\x69\x74\x73\x20\x20\x20\x3a\x20\x01\x68\x25\x31\x33\x2e\x31\x33\x73\x20\x01\x6e\x01\x63\x66\x72"
-		"\x65\x65\x3a\x20\x01\x68\x25\x73\x20\x01\x6e\x01\x63\x28\x01\x68\x25\x73\x20\x01\x6e\x01\x63\x70\x65\x72\x20\x64\x61\x79\x29\x0d"
-		"\x0a" // 436 UserCredits
-	,"\x01\x6e\x01\x63\x4d\x69\x6e\x75\x74\x65\x73\x20\x20\x20\x3a\x20\x01\x68\x25\x31\x33\x2e\x31\x33\x73\x0d\x0a" // 437 UserMinutes
+	,"\x01\x6e\x01\x63\x43\x72\x65\x64\x69\x74\x73\x20\x20\x20\x3a\x20\x01\x68\x25\x39\x2e\x39\x73\x20\x01\x6e\x01\x63\x66\x72\x65\x65"
+		"\x3a\x20\x01\x68\x25\x73\x20\x01\x6e\x01\x63\x28\x01\x68\x25\x73\x20\x01\x6e\x01\x63\x70\x65\x72\x20\x64\x61\x79\x29\x0d\x0a" // 436 UserCredits
+	,"\x01\x6e\x01\x63\x4d\x69\x6e\x75\x74\x65\x73\x20\x20\x20\x3a\x20\x01\x68\x25\x39\x2e\x39\x73\x0d\x0a" // 437 UserMinutes
 	,"\x0d\x0a\x01\x6e\x01\x63\x53\x65\x63\x20\x4c\x65\x76\x65\x6c\x20\x3a\x20\x01\x68\x25\x64\x0d\x0a" // 438 UeditSecLevel
 	,"\x01\x6e\x01\x63\x46\x6c\x61\x67\x73\x20\x23\x31\x20\x20\x3a\x20\x01\x68\x25\x2d\x32\x36\x73\x20\x20\x20\x01\x6e\x01\x63\x46\x6c"
 		"\x61\x67\x73\x20\x23\x33\x20\x20\x3a\x20\x01\x68\x25\x73\x0d\x0a\x01\x6e\x01\x63\x46\x6c\x61\x67\x73\x20\x23\x32\x20\x20\x3a\x20"
diff --git a/src/sbbs3/uedit/uedit.c b/src/sbbs3/uedit/uedit.c
index 3a362e7bc2..837108ebde 100644
--- a/src/sbbs3/uedit/uedit.c
+++ b/src/sbbs3/uedit/uedit.c
@@ -1002,9 +1002,9 @@ int edit_stats(scfg_t *cfg, user_t *user)
 		sprintf(opt[i++],"Time On Last Call  %hu",user->tlast);
 		sprintf(opt[i++],"Extra Time Today   %hu",user->textra);
 		sprintf(opt[i++],"Total Downloads    %hu",user->dls);
-		sprintf(opt[i++],"Downloaded Bytes   %lu",user->dlb);
+		sprintf(opt[i++],"Downloaded Bytes   %" PRIu64,user->dlb);
 		sprintf(opt[i++],"Total Uploads      %hu",user->uls);
-		sprintf(opt[i++],"Uploaded Bytes     %lu",user->ulb);
+		sprintf(opt[i++],"Uploaded Bytes     %" PRIu64,user->ulb);
 		sprintf(opt[i++],"Leech Downloads    %u",user->leech);
 		sprintf(opt[i++],"Password Modified  %s",user->pwmod?timestr(cfg, user->pwmod, str):"Never");
 		opt[i][0]=0;
@@ -1183,11 +1183,11 @@ int edit_stats(scfg_t *cfg, user_t *user)
 			case 15:
 				/* Downloaded Bytes */
 				GETUSERDAT(cfg,user);
-				sprintf(str,"%lu",user->dlb);
-				uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0,"Downloaded Bytes",str,10,K_EDIT|K_NUMBER);
+				sprintf(str,"%" PRIu64,user->dlb);
+				uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0,"Downloaded Bytes",str,20,K_EDIT|K_NUMBER);
 				if(uifc.changes) {
-					user->dlb=strtoul(str,NULL,10);
-					putuserrec(cfg,user->number,U_DLB,10,ultoa(user->dlb,str,10));
+					user->dlb=strtoull(str,NULL,10);
+					putuserrec(cfg,user->number,U_DLB,10,userbytestr(user->dlb,str));
 				}
 				break;
 			case 16:
@@ -1203,11 +1203,11 @@ int edit_stats(scfg_t *cfg, user_t *user)
 			case 17:
 				/* Uploaded Bytes */
 				GETUSERDAT(cfg,user);
-				sprintf(str,"%lu",user->ulb);
-				uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0,"Uploaded Bytes",str,10,K_EDIT|K_NUMBER);
+				sprintf(str,"%" PRIu64,user->ulb);
+				uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0,"Uploaded Bytes",str,20,K_EDIT|K_NUMBER);
 				if(uifc.changes) {
 					user->ulb=strtoul(str,NULL,10);
-					putuserrec(cfg,user->number,U_ULB,10,ultoa(user->ulb,str,10));
+					putuserrec(cfg,user->number,U_ULB,10,userbytestr(user->ulb,str));
 				}
 				break;
 			case 18:
@@ -1278,8 +1278,8 @@ int edit_security(scfg_t *cfg, user_t *user)
 		sprintf(opt[i++],"Flag Set 4    %s",ltoaf(user->flags4,str));
 		sprintf(opt[i++],"Exemptions    %s",ltoaf(user->exempt,str));
 		sprintf(opt[i++],"Restrictions  %s",ltoaf(user->rest,str));
-		sprintf(opt[i++],"Credits       %lu",user->cdt);
-		sprintf(opt[i++],"Free Credits  %lu",user->freecdt);
+		sprintf(opt[i++],"Credits       %" PRIu64,user->cdt);
+		sprintf(opt[i++],"Free Credits  %" PRIu64,user->freecdt);
 		sprintf(opt[i++],"Minutes       %lu",user->min);
 		opt[i][0]=0;
 		switch(uifc.list(WIN_MID|WIN_ACT,0,0,0,&j,0,"Security Settings",opt)) {
@@ -1369,21 +1369,21 @@ int edit_security(scfg_t *cfg, user_t *user)
 			case 8:
 				/* Credits */
 				GETUSERDAT(cfg,user);
-				sprintf(str,"%lu",user->cdt);
-				uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0,"Credits",str,10,K_EDIT|K_NUMBER);
+				sprintf(str,"%" PRIu64,user->cdt);
+				uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0,"Credits",str,LEN_CDT,K_EDIT|K_NUMBER);
 				if(uifc.changes) {
-					user->cdt=strtoul(str,NULL,10);
-					putuserrec(cfg,user->number,U_CDT,10,ultoa(user->cdt,str,10));
+					user->cdt=strtoull(str,NULL,10);
+					putuserrec(cfg,user->number,U_CDT,0,_ui64toa(user->cdt,str,10));
 				}
 				break;
 			case 9:
 				/* Free Credits */
 				GETUSERDAT(cfg,user);
-				sprintf(str,"%lu",user->freecdt);
-				uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0,"Free Credits",str,10,K_EDIT|K_NUMBER);
+				sprintf(str,"%" PRIu64,user->freecdt);
+				uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0,"Free Credits",str,LEN_CDT,K_EDIT|K_NUMBER);
 				if(uifc.changes) {
-					user->freecdt=strtoul(str,NULL,10);
-					putuserrec(cfg,user->number,U_FREECDT,10,ultoa(user->freecdt,str,10));
+					user->freecdt=strtoull(str,NULL,10);
+					putuserrec(cfg,user->number,U_FREECDT,0,_ui64toa(user->freecdt,str,10));
 				}
 				break;
 			case 10:
diff --git a/src/sbbs3/upload.cpp b/src/sbbs3/upload.cpp
index 92217d759d..f55d00ba36 100644
--- a/src/sbbs3/upload.cpp
+++ b/src/sbbs3/upload.cpp
@@ -172,7 +172,7 @@ bool sbbs_t::uploadfile(file_t* f)
 		f->hdr.attr |= MSG_ANONYMOUS;
 	smb_hfield_bin(f, SMB_COST, length);
 	smb_hfield_str(f, SENDER, useron.alias);
-	bprintf(text[FileNBytesReceived],f->name, i64toac(length,tmp));
+	bprintf(text[FileNBytesReceived],f->name, u64toac(length,tmp));
 	if(!addfile(&cfg, f->dir, f, ext, /* metadata: */NULL, &client))
 		return false;
 
@@ -188,11 +188,11 @@ bool sbbs_t::uploadfile(file_t* f)
 	user_uploaded(&cfg, &useron, 1, length);
 	if(cfg.dir[f->dir]->up_pct && cfg.dir[f->dir]->misc&DIR_CDTUL) { /* credit for upload */
 		if(cfg.dir[f->dir]->misc&DIR_CDTMIN && cur_cps)    /* Give min instead of cdt */
-			useron.min=adjustuserrec(&cfg,useron.number,U_MIN,10
+			useron.min=(uint32_t)adjustuserrec(&cfg,useron.number,U_MIN
 				,((ulong)(length*(cfg.dir[f->dir]->up_pct/100.0))/cur_cps)/60);
 		else
-			useron.cdt=adjustuserrec(&cfg,useron.number,U_CDT,10
-				,(ulong)(f->cost * (cfg.dir[f->dir]->up_pct/100.0))); 
+			useron.cdt=adjustuserrec(&cfg,useron.number,U_CDT
+				,(int64_t)(f->cost * (cfg.dir[f->dir]->up_pct/100.0))); 
 	}
 
 	user_event(EVENT_UPLOAD);
diff --git a/src/sbbs3/userdat.c b/src/sbbs3/userdat.c
index 12110077c0..0cf64c521d 100644
--- a/src/sbbs3/userdat.c
+++ b/src/sbbs3/userdat.c
@@ -321,11 +321,14 @@ int parseuserdat(scfg_t* cfg, char *userdat, user_t *user)
 	getrec(userdat,U_FBACKS,5,str); user->fbacks=atoi(str);
 	getrec(userdat,U_ETODAY,5,str); user->etoday=atoi(str);
 	getrec(userdat,U_PTODAY,5,str); user->ptoday=atoi(str);
-	getrec(userdat,U_ULB,10,str); user->ulb=strtoul(str, NULL, 10);
+	getrec(userdat,U_ULB,10,str); user->ulb=parse_byte_count(str, 1);
 	getrec(userdat,U_ULS,5,str); user->uls=atoi(str);
-	getrec(userdat,U_DLB,10,str); user->dlb=strtoul(str, NULL, 10);
+	getrec(userdat,U_DLB,10,str); user->dlb=parse_byte_count(str, 1);
 	getrec(userdat,U_DLS,5,str); user->dls=atoi(str);
-	getrec(userdat,U_CDT,10,str); user->cdt=strtoul(str, NULL, 10);
+	getrec(userdat,U_CDT,LEN_CDT,str);
+	if(str[0] < '0' || str[0] > '9')
+		getrec(userdat,U_OLDCDT,10,str);
+	user->cdt=strtoull(str, NULL, 10);
 	getrec(userdat,U_MIN,10,str); user->min=strtoul(str, NULL, 10);
 	getrec(userdat,U_LEVEL,2,str); user->level=atoi(str);
 	getrec(userdat,U_FLAGS1,8,str); user->flags1=ahtoul(str);
@@ -359,8 +362,10 @@ int parseuserdat(scfg_t* cfg, char *userdat, user_t *user)
 	getrec(userdat,U_CURDIR,sizeof(user->curdir)-1,user->curdir);
 	getrec(userdat,U_CURXTRN,8,user->curxtrn);
 
-	getrec(userdat,U_FREECDT,10,str);
-	user->freecdt=strtoul(str, NULL, 10);
+	getrec(userdat,U_FREECDT,LEN_CDT,str);
+	if(str[0] < '0' || str[0] > '9')
+		getrec(userdat,U_OLDFREECDT,10,str);
+	user->freecdt=strtoull(str, NULL, 10);
 
 	getrec(userdat,U_XEDIT,8,str);
 	for(i=0;i<cfg->total_xedits;i++)
@@ -499,6 +504,14 @@ int is_user_online(scfg_t* cfg, uint usernumber)
 	return 0;
 }
 
+char* userbytestr(uint64_t bytes, char* str)
+{
+	_ui64toa(bytes, str, 10);
+	if(strlen(str) > 10)
+		byte_estimate_to_str(bytes, str, 10 + 1, 1, 4); // +1 for NUL terminator
+	return str;
+}
+
 /****************************************************************************/
 /* Writes into user.number's slot in user.dat data in structure 'user'      */
 /* Called from functions newuser, useredit and main                         */
@@ -560,11 +573,11 @@ int putuserdat(scfg_t* cfg, user_t* user)
 	putrec(userdat,U_PTODAY,5,ultoa(user->ptoday,str,10));
 	putrec(userdat,U_PTODAY+5,2,crlf);
 
-	putrec(userdat,U_ULB,10,ultoa(user->ulb,str,10));
+	putrec(userdat,U_ULB,10,userbytestr(user->ulb, str));
 	putrec(userdat,U_ULS,5,ultoa(user->uls,str,10));
-	putrec(userdat,U_DLB,10,ultoa(user->dlb,str,10));
+	putrec(userdat,U_DLB,10,userbytestr(user->dlb, str));
 	putrec(userdat,U_DLS,5,ultoa(user->dls,str,10));
-	putrec(userdat,U_CDT,10,ultoa(user->cdt,str,10));
+	putrec(userdat,U_CDT,LEN_CDT,_ui64toa(user->cdt,str,10));
 	putrec(userdat,U_MIN,10,ultoa(user->min,str,10));
 	putrec(userdat,U_MIN+10,2,crlf);
 
@@ -592,7 +605,7 @@ int putuserdat(scfg_t* cfg, user_t* user)
 
 	putrec(userdat,U_IPADDR+LEN_IPADDR,2,crlf);
 
-	putrec(userdat,U_FREECDT,10,ultoa(user->freecdt,str,10));
+	putrec(userdat,U_FREECDT,LEN_CDT,_ui64toa(user->freecdt,str,10));
 
 	putrec(userdat,U_FLAGS3,8,ultoa(user->flags3,str,16));
 	putrec(userdat,U_FLAGS4,8,ultoa(user->flags4,str,16));
@@ -1609,7 +1622,7 @@ static BOOL ar_exp(scfg_t* cfg, uchar **ptrptr, user_t* user, client_t* client)
 {
 	BOOL	result,not,or,equal;
 	uint	i,n,artype=AR_LEVEL,age;
-	ulong	l;
+	uint64_t l;
 	time_t	now;
 	struct tm tm;
 	const char*	p;
@@ -1830,7 +1843,7 @@ static BOOL ar_exp(scfg_t* cfg, uchar **ptrptr, user_t* user, client_t* client)
 					result=!not;
 				break;
 			case AR_CREDIT:
-				l=(ulong)i*1024UL;
+				l = i * 1024UL;
 				if(user==NULL
 					|| (equal && user->cdt+user->freecdt!=l)
 					|| (!equal && user->cdt+user->freecdt<l))
@@ -2319,12 +2332,12 @@ int putuserrec(scfg_t* cfg, int usernumber, int start, int length, const char *s
 /* Updates user 'usernumber's record (numeric string) by adding 'adj' to it */
 /* returns the new value.													*/
 /****************************************************************************/
-ulong adjustuserrec(scfg_t* cfg, int usernumber, int start, int length, long adj)
+uint64_t adjustuserrec(scfg_t* cfg, int usernumber, int start, int64_t adj)
 {
 	char str[256],path[256];
 	char tmp[32];
 	int i,c,file;
-	ulong val;
+	uint64_t val;
 
 	if(!VALID_CFG(cfg) || usernumber<1)
 		return(0);
@@ -2340,12 +2353,10 @@ ulong adjustuserrec(scfg_t* cfg, int usernumber, int start, int length, long adj
 
 	(void)lseek(file,(long)((long)(usernumber-1)*U_LEN)+start,SEEK_SET);
 
-	if(length < 1) { /* auto-length */
-		length=user_rec_len(start);
-		if(length < 1) {
-			close(file);
-			return 0;
-		}
+	int length=user_rec_len(start);
+	if(length < 1) {
+		close(file);
+		return 0;
 	}
 
 	i=0;
@@ -2369,14 +2380,26 @@ ulong adjustuserrec(scfg_t* cfg, int usernumber, int start, int length, long adj
 	for(c=0;c<length;c++)
 		if(str[c]==ETX || str[c]==CR) break;
 	str[c]=0;
-	if(length > 5) {
+	if(start == U_ULB || start == U_DLB || length > 10) {
+		if(start == U_ULB || start == U_DLB)
+			val = parse_byte_count(str, 1);
+		else
+			val = strtoull(str, NULL, 10);
+		if(adj<0L && val<(uint64_t)-adj)		/* don't go negative */
+			val=0;
+		else if(adj > 0 && val + adj < val)
+			val = UINT64_MAX;
+		else
+			val += (uint64_t)adj;
+	}
+	else if(length > 5) {
 		val = strtoul(str, NULL, 10);
-		if(adj<0L && val<(ulong)-adj)		/* don't go negative */
+		if(adj<0L && val<(uint32_t)-adj)		/* don't go negative */
 			val=0;
 		else if(adj > 0 && val + adj < val)
-			val = ULONG_MAX;
+			val = UINT32_MAX;
 		else
-			val += (ulong)adj;
+			val += (uint32_t)adj;
 	} else {
 		ushort sval = (ushort)strtoul(str, NULL, 10);
 		if(adj < 0L && sval < (ushort)-adj)		/* don't go negative */
@@ -2388,7 +2411,11 @@ ulong adjustuserrec(scfg_t* cfg, int usernumber, int start, int length, long adj
 		val = sval;
 	}
 	(void)lseek(file,(long)((long)(usernumber-1)*U_LEN)+start,SEEK_SET);
-	putrec(str,0,length,ultoa(val,tmp,10));
+	if(start == U_ULB || start == U_DLB)
+		userbytestr(val, tmp);
+	else
+		_ui64toa(val,tmp,10);
+	putrec(str,0,length,tmp);
 	if(write(file,str,length)!=length) {
 		unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
 		close(file);
@@ -2404,27 +2431,30 @@ ulong adjustuserrec(scfg_t* cfg, int usernumber, int start, int length, long adj
 /* Subtract credits from the current user online, accounting for the new    */
 /* "free credits" field.                                                    */
 /****************************************************************************/
-void subtract_cdt(scfg_t* cfg, user_t* user, long amt)
+void subtract_cdt(scfg_t* cfg, user_t* user, uint64_t amt)
 {
 	char tmp[64];
-    long mod;
+    int64_t mod;
 
 	if(!amt || user==NULL)
 		return;
 	if(user->freecdt) {
-		if((ulong)amt>user->freecdt) {      /* subtract both credits and */
+		if(amt > user->freecdt) {      /* subtract both credits and */
 			mod=amt-user->freecdt;   /* free credits */
-			putuserrec(cfg, user->number,U_FREECDT,10,"0");
+			putuserrec(cfg, user->number,U_FREECDT,0,"0");
 			user->freecdt=0;
-			user->cdt=adjustuserrec(cfg, user->number,U_CDT,10,-mod);
+			user->cdt=adjustuserrec(cfg, user->number,U_CDT,-mod);
 		} else {                          /* subtract just free credits */
 			user->freecdt-=amt;
-			putuserrec(cfg, user->number,U_FREECDT,10
-				,ultoa(user->freecdt,tmp,10));
+			putuserrec(cfg, user->number,U_FREECDT,0
+				,_ui64toa(user->freecdt,tmp,10));
 		}
 	}
-	else    /* no free credits */
-		user->cdt=adjustuserrec(cfg, user->number,U_CDT,10,-amt);
+	else {  /* no free credits */
+		if(amt > INT64_MAX)
+			amt = INT64_MAX;
+		user->cdt=adjustuserrec(cfg, user->number,U_CDT,-(int64_t)amt);
+	}
 }
 
 BOOL user_posted_msg(scfg_t* cfg, user_t* user, int count)
@@ -2432,8 +2462,8 @@ BOOL user_posted_msg(scfg_t* cfg, user_t* user, int count)
 	if(user==NULL)
 		return(FALSE);
 
-	user->posts	=(ushort)adjustuserrec(cfg, user->number, U_POSTS, 5, count);
-	user->ptoday=(ushort)adjustuserrec(cfg, user->number, U_PTODAY, 5, count);
+	user->posts	=(ushort)adjustuserrec(cfg, user->number, U_POSTS, count);
+	user->ptoday=(ushort)adjustuserrec(cfg, user->number, U_PTODAY, count);
 
 	return(TRUE);
 }
@@ -2444,10 +2474,10 @@ BOOL user_sent_email(scfg_t* cfg, user_t* user, int count, BOOL feedback)
 		return(FALSE);
 
 	if(feedback)
-		user->fbacks=(ushort)adjustuserrec(cfg, user->number, U_FBACKS, 5, count);
+		user->fbacks=(ushort)adjustuserrec(cfg, user->number, U_FBACKS, count);
 	else
-		user->emails=(ushort)adjustuserrec(cfg, user->number, U_EMAILS, 5, count);
-	user->etoday=(ushort)adjustuserrec(cfg, user->number, U_ETODAY, 5, count);
+		user->emails=(ushort)adjustuserrec(cfg, user->number, U_EMAILS, count);
+	user->etoday=(ushort)adjustuserrec(cfg, user->number, U_ETODAY, count);
 
 	return(TRUE);
 }
@@ -2457,8 +2487,8 @@ BOOL user_downloaded(scfg_t* cfg, user_t* user, int files, off_t bytes)
 	if(user==NULL)
 		return(FALSE);
 
-	user->dls=(ushort)adjustuserrec(cfg, user->number, U_DLS, 5, files);
-	user->dlb=adjustuserrec(cfg, user->number, U_DLB, 10, (long)bytes);
+	user->dls=(ushort)adjustuserrec(cfg, user->number, U_DLS, files);
+	user->dlb=adjustuserrec(cfg, user->number, U_DLB, bytes);
 
 	return(TRUE);
 }
@@ -2511,16 +2541,16 @@ BOOL user_downloaded_file(scfg_t* cfg, user_t* user, client_t* client,
 		&& uploader.number != user->number 
 		&& getuserdat(cfg, &uploader) == 0
 		&& (uint32_t)uploader.firston < f.hdr.when_imported.time) {
-		ulong l = (ulong)f.cost;
+		uint64_t l = f.cost;
 		if(!(cfg->dir[dirnum]->misc&DIR_CDTDL))	/* Don't give credits on d/l */
 			l=0;
-		ulong mod=(ulong)(l*(cfg->dir[dirnum]->dn_pct/100.0));
-		adjustuserrec(cfg, uploader.number, U_CDT, 10, mod);
+		uint64_t mod=(uint64_t)(l*(cfg->dir[dirnum]->dn_pct/100.0));
+		adjustuserrec(cfg, uploader.number, U_CDT, mod);
 		if(cfg->text != NULL && !(cfg->dir[dirnum]->misc&DIR_QUIET)) {
 			char str[256];
 			char tmp[128];
 			char prefix[128]="";
-			ultoac(mod,tmp);
+			u64toac(mod,tmp,',');
 			const char* alias = user->alias[0] ? user->alias : cfg->text[UNKNOWN_USER];
 			char username[64];
 			if(client != NULL && uploader.level >= SYSOP_LEVEL) {
@@ -2530,7 +2560,7 @@ BOOL user_downloaded_file(scfg_t* cfg, user_t* user, client_t* client,
 					SAFEPRINTF2(username,"%s [%s]", alias, client->addr);
 			} else
 				SAFECOPY(username, alias);
-			if(strcmp(cfg->dir[dirnum]->code, "TEMP") == 0 || bytes < (ulong)f.size)
+			if(strcmp(cfg->dir[dirnum]->code, "TEMP") == 0 || bytes < f.size)
 				SAFECOPY(prefix, cfg->text[Partially]);
 			if(client != NULL) {
 				SAFECAT(prefix, client->protocol);
@@ -2555,10 +2585,10 @@ BOOL user_downloaded_file(scfg_t* cfg, user_t* user, client_t* client,
 	/****************************/
 	user_downloaded(cfg, user, /* files: */1, bytes);
 	if(!is_download_free(cfg, dirnum, user, client))
-		subtract_cdt(cfg, user, (long)f.cost);
+		subtract_cdt(cfg, user, f.cost);
 
 	if(!(cfg->dir[dirnum]->misc&DIR_NOSTAT))
-		inc_sys_download_stats(cfg, /* files: */1, (ulong)bytes);
+		inc_sys_download_stats(cfg, /* files: */1, (ulong)bytes); // TODO: remove ulong typecast
 
 	smb_freefilemem(&f);
 	return TRUE;
@@ -2570,13 +2600,13 @@ BOOL user_uploaded(scfg_t* cfg, user_t* user, int files, off_t bytes)
 	if(user==NULL)
 		return(FALSE);
 
-	user->uls=(ushort)adjustuserrec(cfg, user->number, U_ULS, 5, files);
-	user->ulb=adjustuserrec(cfg, user->number, U_ULB, 10, (long)bytes);
+	user->uls=(ushort)adjustuserrec(cfg, user->number, U_ULS, files);
+	user->ulb=adjustuserrec(cfg, user->number, U_ULB, bytes);
 
 	return(TRUE);
 }
 
-BOOL user_adjust_credits(scfg_t* cfg, user_t* user, long amount)
+BOOL user_adjust_credits(scfg_t* cfg, user_t* user, int64_t amount)
 {
 	if(user==NULL)
 		return(FALSE);
@@ -2584,7 +2614,7 @@ BOOL user_adjust_credits(scfg_t* cfg, user_t* user, long amount)
 	if(amount<0)	/* subtract */
 		subtract_cdt(cfg, user, -amount);
 	else			/* add */
-		user->cdt=adjustuserrec(cfg, user->number, U_CDT, 10, amount);
+		user->cdt=adjustuserrec(cfg, user->number, U_CDT, amount);
 
 	return(TRUE);
 }
@@ -2594,7 +2624,7 @@ BOOL user_adjust_minutes(scfg_t* cfg, user_t* user, long amount)
 	if(user==NULL)
 		return(FALSE);
 
-	user->min=adjustuserrec(cfg, user->number, U_MIN, 10, amount);
+	user->min=(uint32_t)adjustuserrec(cfg, user->number, U_MIN, amount);
 
 	return(TRUE);
 }
@@ -2618,8 +2648,8 @@ BOOL logoutuserdat(scfg_t* cfg, user_t* user, time_t now, time_t logontime)
 
 	putuserrec(cfg,user->number,U_LASTON,8,ultoa((ulong)now,str,16));
 	putuserrec(cfg,user->number,U_TLAST,5,ultoa(user->tlast,str,10));
-	adjustuserrec(cfg,user->number,U_TIMEON,5,user->tlast);
-	adjustuserrec(cfg,user->number,U_TTODAY,5,user->tlast);
+	adjustuserrec(cfg,user->number,U_TIMEON,user->tlast);
+	adjustuserrec(cfg,user->number,U_TTODAY,user->tlast);
 
 	/* Convert time_t to struct tm */
 	if(localtime_r(&now,&tm_now)==NULL)
@@ -2655,8 +2685,8 @@ void resetdailyuserdat(scfg_t* cfg, user_t* user, BOOL write)
 	if(write) putuserrec(cfg,user->number,U_PTODAY,5,"0");
 	/* free credits per day */
 	user->freecdt=cfg->level_freecdtperday[user->level];
-	if(write) putuserrec(cfg,user->number,U_FREECDT,10
-		,ultoa(user->freecdt,str,10));
+	if(write) putuserrec(cfg,user->number,U_FREECDT,0
+		,_ui64toa(user->freecdt,str,10));
 	/* time used today */
 	user->ttoday=0;
 	if(write) putuserrec(cfg,user->number,U_TTODAY,5,"0");
@@ -2933,11 +2963,14 @@ int user_rec_len(int offset)
 		/* 32-bit integers (10 decimal digits) */
 		case U_ULB:
 		case U_DLB:
-		case U_CDT:
 		case U_MIN:
-		case U_FREECDT:
 			return(10);
 
+		/* 64-bit integers (20 decimal digits) */
+		case U_CDT:
+		case U_FREECDT:
+			return 20;
+
 		/* 3 char strings */
 		case U_TMPEXT:
 			return(3);
diff --git a/src/sbbs3/userdat.h b/src/sbbs3/userdat.h
index b8e4509e81..0ca7ac0239 100644
--- a/src/sbbs3/userdat.h
+++ b/src/sbbs3/userdat.h
@@ -81,12 +81,13 @@ DLLEXPORT uint	userdatdupe(scfg_t*, uint usernumber, uint offset, uint datlen, c
 
 DLLEXPORT BOOL	chk_ar(scfg_t*, uchar* str, user_t*, client_t*); /* checks access requirements */
 
+DLLEXPORT char* userbytestr(uint64_t bytes, char* str);
 DLLEXPORT int	getuserrec(scfg_t*, int usernumber, int start, int length, char *str);
 DLLEXPORT int	putuserrec(scfg_t*, int usernumber, int start, int length, const char *str);
-DLLEXPORT ulong	adjustuserrec(scfg_t*, int usernumber, int start, int length, long adj);
+DLLEXPORT uint64_t adjustuserrec(scfg_t*, int usernumber, int start, int64_t adj);
 DLLEXPORT BOOL	logoutuserdat(scfg_t*, user_t*, time_t now, time_t logontime);
 DLLEXPORT void	resetdailyuserdat(scfg_t*, user_t*, BOOL write);
-DLLEXPORT void	subtract_cdt(scfg_t*, user_t*, long amt);
+DLLEXPORT void	subtract_cdt(scfg_t*, user_t*, uint64_t amt);
 DLLEXPORT int	user_rec_len(int offset);
 DLLEXPORT BOOL	can_user_access_all_libs(scfg_t*, user_t*, client_t*);
 DLLEXPORT BOOL	can_user_access_all_dirs(scfg_t*, uint libnum, user_t*, client_t*);
@@ -133,7 +134,7 @@ DLLEXPORT BOOL	user_downloaded(scfg_t*, user_t*, int files, off_t bytes);
 DLLEXPORT BOOL	user_downloaded_file(scfg_t*, user_t*, client_t*, uint dirnum, const char* filename, off_t bytes);
 
 DLLEXPORT BOOL	user_uploaded(scfg_t*, user_t*, int files, off_t bytes);
-DLLEXPORT BOOL	user_adjust_credits(scfg_t*, user_t*, long amount);
+DLLEXPORT BOOL	user_adjust_credits(scfg_t*, user_t*, int64_t amount);
 DLLEXPORT BOOL	user_adjust_minutes(scfg_t*, user_t*, long amount);
 
 DLLEXPORT time_t gettimeleft(scfg_t*, user_t*, time_t starttime);
diff --git a/src/sbbs3/useredit.cpp b/src/sbbs3/useredit.cpp
index c3521a081a..e83c649181 100644
--- a/src/sbbs3/useredit.cpp
+++ b/src/sbbs3/useredit.cpp
@@ -45,6 +45,7 @@ void sbbs_t::useredit(int usernumber)
 	float	f;
 	long	l;
 	long	kmode = K_LINE|K_EDIT|K_AUTODEL|K_TRIM;
+	int64_t adj;
 	user_t	user;
 	struct	tm tm;
 
@@ -125,14 +126,15 @@ void sbbs_t::useredit(int usernumber)
 		bprintf(text[UserEmails]
 			,user.emails,user.fbacks,getmail(&cfg,user.number,/* Sent: */FALSE, /* SPAM: */FALSE),user.etoday);
 
-		bprintf(text[UserUploads],ultoac(user.ulb,tmp),user.uls);
+		bprintf(text[UserUploads], byte_estimate_to_str(user.ulb, tmp, sizeof(tmp), 1, 1), user.uls);
 		if(user.leech)
 			SAFEPRINTF(str,text[UserLeech],user.leech);
 		else
 			str[0]=0;
-		bprintf(text[UserDownloads],ultoac(user.dlb,tmp),user.dls,str);
-		bprintf(text[UserCredits],ultoac(user.cdt,tmp)
-			,ultoac(user.freecdt,tmp2),ultoac(cfg.level_freecdtperday[user.level],str));
+		bprintf(text[UserDownloads],byte_estimate_to_str(user.dlb, tmp, sizeof(tmp), 1, 1) ,user.dls,str);
+		bprintf(text[UserCredits],byte_estimate_to_str(user.cdt, tmp, sizeof(tmp), 1, 1)
+			,byte_estimate_to_str(user.freecdt, tmp2, sizeof(tmp2), 1, 1)
+			,byte_estimate_to_str(cfg.level_freecdtperday[user.level], str, sizeof(str), 1, 1));
 		bprintf(text[UserMinutes],ultoac(user.min,tmp));
 		bprintf(text[UeditSecLevel],user.level);
 		bprintf(text[UeditFlags],ltoaf(user.flags1,tmp),ltoaf(user.flags3,tmp2)
@@ -433,9 +435,11 @@ void sbbs_t::useredit(int usernumber)
 				break;
 			case 'U':
 				bputs(text[UeditUlBytes]);
-				ultoa(user.ulb,str,10);
-				if(getstr(str,10,K_NUMBER|K_LINE|K_EDIT|K_AUTODEL))
-					putuserrec(&cfg,user.number,U_ULB,10,str);
+				_ui64toa(user.ulb,str,10);
+				if(getstr(str,19,K_UPPER|K_LINE|K_EDIT|K_AUTODEL)) {
+					user.ulb = parse_byte_count(str, 1);
+					putuserrec(&cfg,user.number,U_ULB,10,userbytestr(user.ulb, str));
+				}
 				if(sys_status&SS_ABORT)
 					break;
 				bputs(text[UeditUploads]);
@@ -445,9 +449,11 @@ void sbbs_t::useredit(int usernumber)
 				if(sys_status&SS_ABORT)
 					break;
 				bputs(text[UeditDlBytes]);
-				ultoa(user.dlb,str,10);
-				if(getstr(str,10,K_NUMBER|K_LINE|K_EDIT|K_AUTODEL))
-					putuserrec(&cfg,user.number,U_DLB,10,str);
+				_ui64toa(user.dlb,str,10);
+				if(getstr(str,19,K_UPPER|K_LINE|K_EDIT|K_AUTODEL)) {
+					user.dlb = parse_byte_count(str, 1);
+					putuserrec(&cfg,user.number,U_DLB,10,userbytestr(user.dlb, str));
+				}
 				if(sys_status&SS_ABORT)
 					break;
 				bputs(text[UeditDownloads]);
@@ -540,15 +546,13 @@ void sbbs_t::useredit(int usernumber)
 				break;
 			case '+':
 				bputs(text[ModifyCredits]);
-				getstr(str,10,K_UPPER|K_LINE);
-				l=atol(str);
-				if(strstr(str,"M"))
-					l*=0x100000L;
-				else if(strstr(str,"K"))
-					l*=1024;
-				else if(strstr(str,"$"))
-					l*=cfg.cdt_per_dollar;
-				adjustuserrec(&cfg, user.number, U_CDT, 10, l);
+				if(getstr(str,10,K_UPPER|K_LINE)) {
+					if(strstr(str,"$"))
+						adj = strtoll(str, NULL, 10) * cfg.cdt_per_dollar;
+					else
+						adj = parse_byte_count(str, 1);
+					adjustuserrec(&cfg, user.number, U_CDT, adj);
+				}
 				break;
 			case '*':
 				bputs(text[ModifyMinutes]);
@@ -572,9 +576,11 @@ void sbbs_t::useredit(int usernumber)
 				break;
 			case '$':
 				bputs(text[UeditCredits]);
-				ultoa(user.cdt,str,10);
-				if(getstr(str,10,K_NUMBER|K_LINE))
-					putuserrec(&cfg,user.number,U_CDT,10,str);
+				_ui64toa(user.cdt,str,10);
+				if(getstr(str,19,K_UPPER|K_LINE|K_EDIT|K_AUTODEL)) {
+					user.cdt = parse_byte_count(str, 1);
+					putuserrec(&cfg,user.number,U_CDT,0,userbytestr(user.cdt, str));
+				}
 				break;
 			case '/':
 				bputs(text[SearchStringPrompt]);
diff --git a/src/sbbs3/xtrn.cpp b/src/sbbs3/xtrn.cpp
index 2dcca277da..3e457ee53b 100644
--- a/src/sbbs3/xtrn.cpp
+++ b/src/sbbs3/xtrn.cpp
@@ -2082,7 +2082,7 @@ char* sbbs_t::cmdstr(const char *instr, const char *fpath, const char *fspec, ch
                     strncat(cmd,str, avail);
                     break;
                 case '$':   /* Credits */
-                    strncat(cmd,ultoa(useron.cdt+useron.freecdt,str,10), avail);
+                    strncat(cmd,_ui64toa(useron.cdt+useron.freecdt,str,10), avail);
                     break;
                 case '%':   /* %% for percent sign */
                     strncat(cmd,"%", avail);
diff --git a/src/sbbs3/xtrn_sec.cpp b/src/sbbs3/xtrn_sec.cpp
index 518ccc8ab0..7f1313ec9f 100644
--- a/src/sbbs3/xtrn_sec.cpp
+++ b/src/sbbs3/xtrn_sec.cpp
@@ -567,7 +567,7 @@ void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tl
 		unixtodstr(&cfg,(time32_t)logontime,tmp);
 		exitinfo.LoginDate = tmp;
 		exitinfo.TimeLimit = cfg.level_timepercall[useron.level];
-		exitinfo.Credit = useron.cdt;
+		exitinfo.Credit = (uint32_t)MIN(useron.cdt, UINT32_MAX);
 		exitinfo.UserRecNum = useron.number;
 		exitinfo.WantChat = (sys_status & SS_SYSPAGE);
 		exitinfo.ScreenClear = (useron.misc & CLRSCRN);
@@ -771,8 +771,8 @@ void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tl
 		user.fixed.RegExpDate = unixtojulian(useron.expire);
 		user.fixed.ExpSecurityLevel = cfg.expired_level;
 		user.fixed.LastConference = cursubnum;
-		user.fixed.ulTotDnldBytes = useron.dlb;
-		user.fixed.ulTotUpldBytes = useron.ulb;
+		user.fixed.ulTotDnldBytes = (uint32_t)MIN(useron.dlb, UINT32_MAX);
+		user.fixed.ulTotUpldBytes = (uint32_t)MIN(useron.ulb, UINT32_MAX);
 		user.fixed.DeleteFlag = INT_TO_BOOL(useron.misc & DELETED);
 		user.fixed.RecNum = useron.number;
 		user.fixed.MsgsLeft = useron.posts + useron.emails + useron.fbacks;
@@ -1066,7 +1066,7 @@ void sbbs_t::moduserdat(uint xtrnnum)
 				truncsp(str);
 				mod=atol(str)*1024L;
 				if(mod) {
-					useron.dlb=adjustuserrec(&cfg,useron.number,U_DLB,10,mod);
+					useron.dlb=adjustuserrec(&cfg,useron.number,U_DLB,mod);
 					subtract_cdt(&cfg,&useron,mod); 
 				} 
 			}
@@ -1125,7 +1125,7 @@ void sbbs_t::moduserdat(uint xtrnnum)
 			}
 			logline(tmp,str);
 			if(mod>0L)			/* always add to real cdt */
-				useron.cdt=adjustuserrec(&cfg,useron.number,U_CDT,10,mod);
+				useron.cdt=adjustuserrec(&cfg,useron.number,U_CDT,mod);
 			else
 				subtract_cdt(&cfg,&useron,-mod); /* subtract from free cdt first */
 		}
@@ -1176,7 +1176,7 @@ void sbbs_t::moduserdat(uint xtrnnum)
 			if(mod) {
 				SAFEPRINTF(str,"Minute Adjustment: %s",ultoac(mod,tmp));
 				logline("*+",str);
-				useron.min=adjustuserrec(&cfg,useron.number,U_MIN,10,mod); 
+				useron.min=(uint32_t)adjustuserrec(&cfg,useron.number,U_MIN,mod); 
 			} 
 		}
 		if(fgets(str,81,stream)) {		/* flags #3 */
-- 
GitLab