diff --git a/src/sbbs3/atcodes.cpp b/src/sbbs3/atcodes.cpp index cb17d8d5a332581fae0631070ce87832d4913351..7c7088218b5f2773038e5f80dba32b74cff02e39 100644 --- a/src/sbbs3/atcodes.cpp +++ b/src/sbbs3/atcodes.cpp @@ -712,7 +712,7 @@ const char* sbbs_t::atcode(const char* sp, char* str, size_t maxlen, int* pmode, } if(strcmp(sp, "DATEFMT") == 0) { - return cfg.sys_misc&SM_EURODATE ? "DD/MM/YY" : "MM/DD/YY"; + return date_format(&cfg); } if(strcmp(sp, "BDATEFMT") == 0 || strcmp(sp, "BIRTHFMT") == 0) { diff --git a/src/sbbs3/date_str.c b/src/sbbs3/date_str.c index be4ea57087d8c4dfc99b8bd29eea6c9505aebdbb..8170c448a12cac0349a34f4eaacd51e3fca36e19 100644 --- a/src/sbbs3/date_str.c +++ b/src/sbbs3/date_str.c @@ -26,6 +26,20 @@ const char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; const char *mon[]={"Jan","Feb","Mar","Apr","May","Jun" ,"Jul","Aug","Sep","Oct","Nov","Dec"}; +/****************************************************************************/ +/****************************************************************************/ +const char* date_format(scfg_t* cfg) +{ + switch (cfg->sys_date_fmt) { + case DDMMYY: return "DD/MM/YY"; + case MMDDYY: return "MM/DD/YY"; + case YYMMDD: return "YY/MM/DD"; + } + return "????????"; +} + +#define DECVAL(ch, mul) (DEC_CHAR_TO_INT(ch) * (mul)) + /****************************************************************************/ /* Converts a date string in format MM/DD/YY into unix time format */ /****************************************************************************/ @@ -60,17 +74,23 @@ time32_t dstrtounix(scfg_t* cfg, const char *instr) } memset(&tm,0,sizeof(tm)); - tm.tm_year=((p[6]&0xf)*10)+(p[7]&0xf); + if (cfg->sys_date_fmt == YYMMDD) { + tm.tm_year = DECVAL(p[0], 10) + DECVAL(p[1], 1); + tm.tm_mon = DECVAL(p[3], 10) + DECVAL(p[4], 1); + tm.tm_mday = DECVAL(p[6], 10) + DECVAL(p[7], 1); + } else { + tm.tm_year=((p[6]&0xf)*10)+(p[7]&0xf); + if(cfg->sys_date_fmt == DDMMYY) { + tm.tm_mon=((p[3]&0xf)*10)+(p[4]&0xf); + tm.tm_mday=((p[0]&0xf)*10)+(p[1]&0xf); + } + else { + tm.tm_mon=((p[0]&0xf)*10)+(p[1]&0xf); + tm.tm_mday=((p[3]&0xf)*10)+(p[4]&0xf); + } + } if (tm.tm_year<Y2K_2DIGIT_WINDOW) tm.tm_year+=100; - if(cfg->sys_misc&SM_EURODATE) { - tm.tm_mon=((p[3]&0xf)*10)+(p[4]&0xf); - tm.tm_mday=((p[0]&0xf)*10)+(p[1]&0xf); - } - else { - tm.tm_mon=((p[0]&0xf)*10)+(p[1]&0xf); - tm.tm_mday=((p[3]&0xf)*10)+(p[4]&0xf); - } if (tm.tm_mon) tm.tm_mon--; /* zero-based month field */ tm.tm_isdst=-1; /* Do not adjust for DST */ @@ -98,7 +118,10 @@ char* unixtodstr(scfg_t* cfg, time32_t t, char *str) } if(tm.tm_mday>31) tm.tm_mday=1; - if(cfg->sys_misc&SM_EURODATE) + if (cfg->sys_date_fmt == YYMMDD) + sprintf(str,"%02u/%02u/%02u" + ,TM_YEAR(tm.tm_year), tm.tm_mon+1, tm.tm_mday); + else if(cfg->sys_date_fmt == DDMMYY) sprintf(str,"%02u/%02u/%02u",tm.tm_mday,tm.tm_mon+1 ,TM_YEAR(tm.tm_year)); else diff --git a/src/sbbs3/date_str.h b/src/sbbs3/date_str.h index 8f43fc72ab441dd9532efa25f326a645f8e948a6..71b65d1457492cec9c6c572bbda3ba3dc6ce1c45 100644 --- a/src/sbbs3/date_str.h +++ b/src/sbbs3/date_str.h @@ -32,6 +32,7 @@ extern "C" { extern const char* wday[]; /* abbreviated weekday names */ extern const char* mon[]; /* abbreviated month names */ +DLLEXPORT const char* date_format(scfg_t*); DLLEXPORT char * zonestr(short zone); DLLEXPORT time32_t dstrtounix(scfg_t*, const char *str); DLLEXPORT char * unixtodstr(scfg_t*, time32_t, char *str); diff --git a/src/sbbs3/newuser.cpp b/src/sbbs3/newuser.cpp index e80e1a4f925b8c62b5e8e9c1f7e491d800440f1a..2eb1a01c5673435713fb13c0ba9be6605e491c0a 100644 --- a/src/sbbs3/newuser.cpp +++ b/src/sbbs3/newuser.cpp @@ -283,7 +283,7 @@ BOOL sbbs_t::newuser() while((cfg.uq&UQ_BIRTH) && online && text[EnterYourBirthday][0]) { bprintf(text[EnterYourBirthday], birthdate_format(&cfg)); format_birthdate(&cfg, useron.birth, str, sizeof(str)); - if(gettmplt(str, "nn/nn/nnnn", K_EDIT) < 10) + if(gettmplt(str, cfg.sys_date_fmt == YYMMDD ? "nnnn/nn/nn" : "nn/nn/nnnn", K_EDIT) < 10) continue; int age = getage(&cfg, parse_birthdate(&cfg, str, tmp, sizeof(tmp))); if(age >= 0 && age <= 200) { // TODO: Configurable min/max user age diff --git a/src/sbbs3/sbbsdefs.h b/src/sbbs3/sbbsdefs.h index 6f6d2954837184a08d56fd1a8ff2e0d9e87ede07..fc900917cf337e6bf3c0bb3517b9c965b480fdb4 100644 --- a/src/sbbs3/sbbsdefs.h +++ b/src/sbbs3/sbbsdefs.h @@ -132,7 +132,7 @@ | UQ_REALNAME) // Different bits in sys_misc -#define SM_CLOSED (1<<0) // System is clsoed to New Users +#define SM_CLOSED (1<<0) // System is closed to New Users #define SM_SYSSTAT (1<<1) // Sysops activity included in statistics #define SM_NOSYSINFO (1<<2) // Suppress system info display at logon #define SM_PWEDIT (1<<3) // Allow users to change their passwords @@ -149,7 +149,7 @@ #define SM_AUTO_DST (1<<14) // Automatic Daylight Savings Toggle (US) #define SM_R_SYSOP (1<<15) // Allow remote sysop login/commands #define SM_QUOTE_EM (1<<16) // Allow quoting of e-mail -#define SM_EURODATE (1<<17) // European date format (DD/MM/YY) +#define SM_EURODATE (1<<17) // European date format (DD/MM/YY) - DEPRECATED #define SM_MILITARY (1<<18) // Military (24hr) time format #define SM_TIMEBANK (1<<19) // Allow time bank functions #define SM_FILE_EM (1<<20) // Allow file attachments in E-mail diff --git a/src/sbbs3/scfg/scfgsys.c b/src/sbbs3/scfg/scfgsys.c index 94e3357639f8c525346e0d754cfd229fbdd0df5d..b07cc7d8a78d2911f9519028b212306944a21679 100644 --- a/src/sbbs3/scfg/scfgsys.c +++ b/src/sbbs3/scfg/scfgsys.c @@ -1315,23 +1315,22 @@ int edit_sys_timefmt(int page, int total) int edit_sys_datefmt(int page, int total) { int mode = WIN_SAV | WIN_MID; - int i = (cfg.sys_misc & SM_EURODATE) ? 1:0; - char* opts[3] = { "MM/DD/YY", "DD/MM/YY", NULL }; + int i = cfg.sys_date_fmt; + char* opts[] = { "MM/DD/YY", "DD/MM/YY", "YY/MM/DD", NULL }; uifc.helpbuf= "`Date Display Format:`\n" "\n" "If you would like abbreviated dates to be displayed in the traditional\n" "U.S. date format of month first, choose `MM/DD/YY`. If you prefer the\n" "European traditional date format of day first, choose `DD/MM/YY`.\n" + "If you and your users would prefer year first, choose `YY/MM/DD`.\n" ; if(page) mode = wiz_help(page, total, uifc.helpbuf); i=uifc.list(mode,0,10,0,&i,0 ,"Date Display Format", opts); - if(i == 0) - cfg.sys_misc &= ~SM_EURODATE; - else if(i == 1) - cfg.sys_misc |= SM_EURODATE; + if(i >= 0) + cfg.sys_date_fmt = i; return i; } @@ -1656,6 +1655,7 @@ void sys_cfg(void) snprintf(opt[i++],MAX_OPLN,"%-20s%s %s","Local Time Zone" ,smb_zonestr(cfg.sys_timezone,NULL) ,SMB_TZ_HAS_DST(cfg.sys_timezone) && cfg.sys_misc&SM_AUTO_DST ? "(Auto-DST)" : ""); + snprintf(opt[i++],MAX_OPLN,"%-20s%s","Local Date Format", date_format(&cfg)); snprintf(opt[i++],MAX_OPLN,"%-20s%s","Operator",cfg.sys_op); strcpy(opt[i++],"Notifications..."); @@ -1698,12 +1698,15 @@ void sys_cfg(void) edit_sys_timezone(false, false); break; case 3: - edit_sys_operator(false, false); + edit_sys_datefmt(false, false); break; case 4: + edit_sys_operator(false, false); + break; + case 5: cfg_notify(); break; - case 5: /* Toggle Options */ + case 6: /* Toggle Options */ done=0; while(!done) { i=0; @@ -1721,8 +1724,6 @@ void sys_cfg(void) ,cfg.sys_misc&SM_LISTLOC ? "Yes" : "No"); snprintf(opt[i++], MAX_OPLN, "%-33.33s%s","Military (24 hour) Time Format" ,cfg.sys_misc&SM_MILITARY ? "Yes" : "No"); - snprintf(opt[i++], MAX_OPLN, "%-33.33s%s","European Date Format (DD/MM/YY)" - ,cfg.sys_misc&SM_EURODATE ? "Yes" : "No"); snprintf(opt[i++], MAX_OPLN, "%-33.33s%s","Display Sys Info During Logon" ,cfg.sys_misc&SM_NOSYSINFO ? "No" : "Yes"); snprintf(opt[i++], MAX_OPLN, "%-33.33s%s","Display Node List During Logon" @@ -1841,9 +1842,6 @@ void sys_cfg(void) edit_sys_timefmt(false, false); break; case 7: - edit_sys_datefmt(false, false); - break; - case 8: i=cfg.sys_misc&SM_NOSYSINFO ? 1:0; uifc.helpbuf= "`Display System Information During Logon:`\n" @@ -1860,7 +1858,7 @@ void sys_cfg(void) cfg.sys_misc|=SM_NOSYSINFO; } break; - case 9: + case 8: i=cfg.sys_misc&SM_NONODELIST ? 1:0; uifc.helpbuf= "`Display Active Node List During Logon:`\n" @@ -1880,7 +1878,7 @@ void sys_cfg(void) } } break; - case 6: /* New User Values */ + case 7: /* New User Values */ done=0; while(!done) { i=0; @@ -2260,7 +2258,7 @@ void sys_cfg(void) } } break; - case 7: + case 8: uifc.helpbuf= "`New User Questions/Prompts:`\n" "\n" @@ -2393,10 +2391,10 @@ void sys_cfg(void) } } break; - case 8: + case 9: security_cfg(); break; - case 9: /* Advanced Options */ + case 10: /* Advanced Options */ done=0; while(!done) { i=0; @@ -2827,7 +2825,7 @@ void sys_cfg(void) } } break; - case 10: /* Loadable Modules */ + case 11: /* Loadable Modules */ done=0; while(!done) { i=0; diff --git a/src/sbbs3/scfgdefs.h b/src/sbbs3/scfgdefs.h index 5e66b59c9754147ca14a0a10428d46aca860d5c6..6383895d6ef6f6ed70ed611400ecffc1e54f9ff0 100644 --- a/src/sbbs3/scfgdefs.h +++ b/src/sbbs3/scfgdefs.h @@ -384,6 +384,8 @@ struct mqtt_cfg { } tls; }; +enum date_fmt { MMDDYY, DDMMYY, YYMMDD }; + typedef struct { DWORD size; /* sizeof(scfg_t) */ @@ -460,6 +462,7 @@ typedef struct char sys_inetaddr[128]; /* System's internet address */ char sys_location[41]; /* System Location */ int16_t sys_timezone; /* Time Zone of BBS */ + enum date_fmt sys_date_fmt; char sys_daily[LEN_CMD+1]; /* Daily event */ char sys_logon[LEN_CMD+1]; /* Logon event */ char sys_logout[LEN_CMD+1]; /* Logoff event */ diff --git a/src/sbbs3/scfglib1.c b/src/sbbs3/scfglib1.c index 2f475eacf70fb14c8992a590e0767d7e7ccc04a2..75774bb42cfb6830dde23d50599a2158d8e9be33 100644 --- a/src/sbbs3/scfglib1.c +++ b/src/sbbs3/scfglib1.c @@ -102,6 +102,7 @@ BOOL read_main_cfg(scfg_t* cfg, char* error, size_t maxerrlen) cfg->sys_timezone = iniGetInt16(ini, ROOT_SECTION, "timezone", 0); cfg->sys_misc = iniGetUInteger(ini, ROOT_SECTION, "settings", 0); + cfg->sys_date_fmt = iniGetInteger(ini, ROOT_SECTION, "date_fmt", cfg->sys_misc & SM_EURODATE ? DDMMYY : MMDDYY); cfg->sys_login = iniGetUInteger(ini, ROOT_SECTION, "login", 0); cfg->sys_pwdays = iniGetInteger(ini, ROOT_SECTION, "pwdays", 0); cfg->sys_deldays = iniGetInteger(ini, ROOT_SECTION, "deldays", 0); diff --git a/src/sbbs3/scfgsave.c b/src/sbbs3/scfgsave.c index 2e4a3a794c2514358742af39aea17307ef7cfec7..47a993c9be6b7e24fe5218ecfe78afc2bb113297 100644 --- a/src/sbbs3/scfgsave.c +++ b/src/sbbs3/scfgsave.c @@ -122,6 +122,7 @@ BOOL write_main_cfg(scfg_t* cfg) iniSetUInteger(&ini, ROOT_SECTION, "password_timeout", cfg->sys_pass_timeout, NULL); iniSetInt16(&ini, ROOT_SECTION, "timezone", cfg->sys_timezone, NULL); iniSetHexInt(&ini, ROOT_SECTION, "settings", cfg->sys_misc, NULL); + iniSetUInteger(&ini, ROOT_SECTION, "date_fmt", cfg->sys_date_fmt, NULL); iniSetHexInt(&ini, ROOT_SECTION, "login", cfg->sys_login, NULL); iniSetUInteger(&ini, ROOT_SECTION, "lastnode", cfg->sys_lastnode, NULL); iniSetUInteger(&ini, ROOT_SECTION, "pwdays", cfg->sys_pwdays, NULL); diff --git a/src/sbbs3/userdat.c b/src/sbbs3/userdat.c index ca41ec1f26e65a50985e9b5a6c2ce4e8c6c7ccb6..be3c246ce42614cfc18a0f99f828da303368afa6 100644 --- a/src/sbbs3/userdat.c +++ b/src/sbbs3/userdat.c @@ -953,9 +953,21 @@ char* getbirthddmmyy(scfg_t* cfg, const char* birth, char* buf, size_t max) return buf; } +// Always returns string in YY/MM/DD format +char* getbirthyymmdd(scfg_t* cfg, const char* birth, char* buf, size_t max) +{ + safe_snprintf(buf, max, "%02u/%02u/%02u" + , getbirthyear(birth) % 100 + , getbirthmonth(cfg, birth) + , getbirthday(cfg, birth)); + return buf; +} + char* getbirthdstr(scfg_t* cfg, const char* birth, char* buf, size_t max) { - if(cfg->sys_misc & SM_EURODATE) + if(cfg->sys_date_fmt == YYMMDD) + getbirthyymmdd(cfg, birth, buf, max); + else if(cfg->sys_date_fmt == DDMMYY) getbirthddmmyy(cfg, birth, buf, max); else getbirthmmddyy(cfg, birth, buf, max); @@ -991,11 +1003,13 @@ int getage(scfg_t* cfg, const char *birth) } /****************************************************************************/ -/* Converts from either MM/DD/YYYYY or DD/MM/YYYY to YYYYMMDD */ +/* Converts from MM/DD/YYYYY, DD/MM/YYYY, or YYYY/MM/DD to YYYYMMDD */ /****************************************************************************/ char* parse_birthdate(scfg_t* cfg, const char* birthdate, char* out, size_t maxlen) { - if(cfg->sys_misc & SM_EURODATE) + if (cfg->sys_date_fmt == YYMMDD) + safe_snprintf(out, maxlen, "%.4s%.2s%.2s", birthdate, birthdate + 3, birthdate + 6); + 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); @@ -1003,7 +1017,7 @@ char* parse_birthdate(scfg_t* cfg, const char* birthdate, char* out, size_t maxl } /****************************************************************************/ -/* Converts from user birth date to either MM/DD/YYYYY or DD/MM/YYYY */ +/* Converts from user birth date to MM/DD/YYYYY, DD/MM/YYYY, or YYYY/MM/DD */ /****************************************************************************/ char* format_birthdate(scfg_t* cfg, const char* birthdate, char* out, size_t maxlen) { @@ -1011,7 +1025,10 @@ char* format_birthdate(scfg_t* cfg, const char* birthdate, char* out, size_t max return NULL; *out = '\0'; if(*birthdate) { - if(cfg->sys_misc & SM_EURODATE) + if (cfg->sys_date_fmt == YYMMDD) + safe_snprintf(out, maxlen, "%04u/%02u/%02u" + , getbirthyear(birthdate), getbirthmonth(cfg, birthdate), getbirthday(cfg, birthdate)); + else if (cfg->sys_date_fmt == DDMMYY) safe_snprintf(out, maxlen, "%02u/%02u/%04u" ,getbirthday(cfg, birthdate), getbirthmonth(cfg, birthdate), getbirthyear(birthdate)); else @@ -1023,7 +1040,12 @@ char* format_birthdate(scfg_t* cfg, const char* birthdate, char* out, size_t max const char* birthdate_format(scfg_t* cfg) { - return cfg->sys_misc&SM_EURODATE ? "DD/MM/YYYY" : "MM/DD/YYYY"; + switch (cfg->sys_date_fmt) { + case MMDDYY: return "MM/DD/YYYY"; + case DDMMYY: return "DD/MM/YYYY"; + case YYMMDD: return "YYYY/MM/DD"; + } + return "??????????"; } /****************************************************************************/ diff --git a/src/sbbs3/userdat.h b/src/sbbs3/userdat.h index 6b87703db0167f277a3301fa5e9147c02736ae71..dd25df51c0fbf66d14b591a9db186d5a570d3879 100644 --- a/src/sbbs3/userdat.h +++ b/src/sbbs3/userdat.h @@ -65,6 +65,7 @@ DLLEXPORT int getbirthyear(const char* birthdate); DLLEXPORT char* getbirthdstr(scfg_t*, const char* birthdate, char* buf, size_t); DLLEXPORT char* getbirthmmddyy(scfg_t*, const char* birthdate, char* buf, size_t); DLLEXPORT char* getbirthddmmyy(scfg_t*, const char* birthdate, char* buf, size_t); +DLLEXPORT char* getbirthyymmdd(scfg_t*, const char* birthdate, char* buf, size_t); DLLEXPORT char* parse_birthdate(scfg_t*, const char* birthdate, char* out, size_t); DLLEXPORT char* format_birthdate(scfg_t*, const char* birthdate, char* out, size_t); DLLEXPORT const char* birthdate_format(scfg_t*);