diff -r f8f63e944375 sys/src/cmd/upas/common/common.h --- a/sys/src/cmd/upas/common/common.h Fri Jul 17 16:53:20 2020 +0200 +++ b/sys/src/cmd/upas/common/common.h Sat Jul 18 23:30:43 2020 -0700 @@ -52,9 +52,6 @@ void mailfmtinstall(void); /* 'U' = 2047fmt */ #pragma varargck type "U" char* -/* totm.c */ -int fromtotm(char*, Tm*); - /* a pipe between parent and child*/ typedef struct{ Biobuf bb; diff -r f8f63e944375 sys/src/cmd/upas/common/folder.c --- a/sys/src/cmd/upas/common/folder.c Fri Jul 17 16:53:20 2020 +0200 +++ b/sys/src/cmd/upas/common/folder.c Sat Jul 18 23:30:43 2020 -0700 @@ -1,5 +1,7 @@ #include "common.h" +#define Ctimefmt "W MMM _D hh:mm:ss ZZZ YYYY" + enum{ Mbox = 1, Mdir, @@ -185,7 +187,7 @@ appendfolder(Biobuf *b, char *addr, int fd) { char *s; - int r; + int r, n; Biobuf bin; Folder *f; Tm tm; @@ -194,9 +196,10 @@ Bseek(f->out, 0, 2); Binit(&bin, fd, OREAD); s = Brdstr(&bin, '\n', 0); - if(!s || strncmp(s, "From ", 5)) + n = strlen(s); + if(!s || strncmp(s, "From ", 5) != 0) Bprint(f->out, "From %s %.28s\n", addr, ctime(f->t)); - else if(fromtotm(s, &tm) >= 0) + else if(n > 5 && tmparse(&tm, Ctimefmt, s + 5, nil, nil) != nil) f->t = tm2sec(&tm); if(s) Bwrite(f->out, s, strlen(s)); diff -r f8f63e944375 sys/src/cmd/upas/common/mkfile --- a/sys/src/cmd/upas/common/mkfile Fri Jul 17 16:53:20 2020 +0200 +++ b/sys/src/cmd/upas/common/mkfile Sat Jul 18 23:30:43 2020 -0700 @@ -10,7 +10,6 @@ fmt.$O\ libsys.$O\ process.$O\ - totm.$O\ HFILES=common.h\ sys.h\ diff -r f8f63e944375 sys/src/cmd/upas/common/totm.c --- a/sys/src/cmd/upas/common/totm.c Fri Jul 17 16:53:20 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -#include - -static char mtab[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; - -int -ctimetotm(char *s, Tm *tm) -{ - char buf[32]; - - if(strlen(s) < 28) - return -1; - snprint(buf, sizeof buf, "%s", s); - memset(tm, 0, sizeof *tm); - buf[7] = 0; - tm->mon = (strstr(mtab, buf+4) - mtab)/3; - tm->mday = atoi(buf+8); - tm->hour = atoi(buf+11); - tm->min = atoi(buf+14); - tm->sec = atoi(buf+17); - tm->zone[0] = buf[20]; - tm->zone[1] = buf[21]; - tm->zone[2] = buf[22]; - tm->year = atoi(buf+24) - 1900; - return 0; -} - -int -fromtotm(char *s, Tm *tm) -{ - char buf[256], *f[3]; - - snprint(buf, sizeof buf, "%s", s); - if(getfields(buf, f, nelem(f), 0, " ") != 3) - return -1; - return ctimetotm(f[2], tm); -} diff -r f8f63e944375 sys/src/cmd/upas/fs/strtotm.c --- a/sys/src/cmd/upas/fs/strtotm.c Fri Jul 17 16:53:20 2020 +0200 +++ b/sys/src/cmd/upas/fs/strtotm.c Sat Jul 18 23:30:43 2020 -0700 @@ -1,98 +1,25 @@ #include #include -static char* -skiptext(char *q) +int +strtotm(char *s, Tm *t) { - while(*q != '\0' && *q != ' ' && *q != '\t' && *q != '\r' && *q != '\n') - q++; - return q; + char **f, *fmt[] = { + "W MMM DD hh:mm:ss ?Z YYYY", + "?W ?DD ?MMM ?YYYY hh:mm:ss ?Z", + "?W ?DD ?MMM ?YYYY hh:mm:ss", + "?W, DD-?MM-YY", + "?DD ?MMM ?YYYY hh:mm:ss ?Z", + "?DD ?MMM ?YYYY hh:mm:ss", + "?DD-?MM-YY", + "?MMM/?DD/?YYYY hh:mm:ss ?Z", + "?MMM/?DD/?YYYY hh:mm:ss", + "?MMM/?DD/?YYYY", + nil, + }; + + for(f = fmt; *f; f++) + if(tmparse(t, *f, s, nil, nil) != nil) + return 0; + return -1; } - -static char* -skipwhite(char *q) -{ - while(*q == ' ' || *q == '\t' || *q == '\r' || *q == '\n') - q++; - return q; -} - -static char* months[] = { - "jan", "feb", "mar", "apr", - "may", "jun", "jul", "aug", - "sep", "oct", "nov", "dec" -}; - -int -strtotm(char *p, Tm *t) -{ - char *q, *r; - int j; - Tm tm; - int delta; - - delta = 0; - memset(&tm, 0, sizeof(tm)); - tm.mon = -1; - tm.hour = -1; - tm.min = -1; - tm.year = -1; - tm.mday = -1; - memcpy(tm.zone, "GMT", 3); - for(p = skipwhite(p); *p; p = skipwhite(q)){ - q = skiptext(p); - - /* look for time in hh:mm[:ss] */ - if(r = memchr(p, ':', q - p)){ - tm.hour = strtol(p, 0, 10); - tm.min = strtol(r + 1, 0, 10); - if(r = memchr(r + 1, ':', q - (r + 1))) - tm.sec = strtol(r + 1, 0, 10); - else - tm.sec = 0; - continue; - } - - /* look for month */ - for(j = 0; j < 12; j++) - if(cistrncmp(p, months[j], 3) == 0){ - tm.mon = j; - break; - } - if(j != 12) - continue; - - /* look for time zone [A-Z][A-Z]T */ - if(q - p == 3) - if(p[0] >= 'A' && p[0] <= 'Z') - if(p[1] >= 'A' && p[1] <= 'Z') - if(p[2] == 'T'){ - strecpy(tm.zone, tm.zone + 4, p); - continue; - } - - if(p[0] == '+'||p[0] == '-') - if(q - p == 5 && strspn(p + 1, "0123456789") == 4){ - delta = (((p[1] - '0')*10 + p[2] - '0')*60 + (p[3] - '0')*10 + p[4] - '0')*60; - if(p[0] == '-') - delta = -delta; - continue; - } - if(strspn(p, "0123456789") == q - p){ - j = strtol(p, nil, 10); - if(j >= 1 && j <= 31) - tm.mday = j; - if(j >= 1900) - tm.year = j - 1900; - continue; - } - //eprint("strtotm: garbage %.*s\n", utfnlen(p, q - p), p); - } - if(tm.mon < 0 || tm.year < 0 - || tm.hour < 0 || tm.min < 0 - || tm.mday < 0) - return -1; - - *t = *localtime(tm2sec(&tm) - delta); - return 0; -} diff -r f8f63e944375 sys/src/cmd/upas/imap4d/date.c --- a/sys/src/cmd/upas/imap4d/date.c Fri Jul 17 16:53:20 2020 +0200 +++ b/sys/src/cmd/upas/imap4d/date.c Sat Jul 18 23:30:43 2020 -0700 @@ -1,142 +1,10 @@ #include "imap4d.h" -static char *wdayname[] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -}; - -static char *monname[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -/* - * zone : [A-Za-z][A-Za-z][A-Za-z] some time zone names - * | [A-IK-Z] military time; rfc1123 says the rfc822 spec is wrong. - * | "UT" universal time - * | [+-][0-9][0-9][0-9][0-9] - * zones is the rfc-822 list of time zone names - */ -static Namedint zones[] = -{ - {"A", -1 * 3600}, - {"B", -2 * 3600}, - {"C", -3 * 3600}, - {"CDT", -5 * 3600}, - {"CST", -6 * 3600}, - {"D", -4 * 3600}, - {"E", -5 * 3600}, - {"EDT", -4 * 3600}, - {"EST", -5 * 3600}, - {"F", -6 * 3600}, - {"G", -7 * 3600}, - {"GMT", 0}, - {"H", -8 * 3600}, - {"I", -9 * 3600}, - {"K", -10 * 3600}, - {"L", -11 * 3600}, - {"M", -12 * 3600}, - {"MDT", -6 * 3600}, - {"MST", -7 * 3600}, - {"N", +1 * 3600}, - {"O", +2 * 3600}, - {"P", +3 * 3600}, - {"PDT", -7 * 3600}, - {"PST", -8 * 3600}, - {"Q", +4 * 3600}, - {"R", +5 * 3600}, - {"S", +6 * 3600}, - {"T", +7 * 3600}, - {"U", +8 * 3600}, - {"UT", 0}, - {"V", +9 * 3600}, - {"W", +10 * 3600}, - {"X", +11 * 3600}, - {"Y", +12 * 3600}, - {"Z", 0}, -}; - -static void -zone2tm(Tm *tm, char *s) -{ - int i; - Tm aux, *atm; - - if(*s == '+' || *s == '-'){ - i = strtol(s, &s, 10); - tm->tzoff = (i/100)*3600 + i%100; - strncpy(tm->zone, "", 4); - return; - } - - /* - * look it up in the standard rfc822 table - */ - strncpy(tm->zone, s, 3); - tm->zone[3] = 0; - tm->tzoff = 0; - for(i = 0; i < nelem(zones); i++){ - if(cistrcmp(zones[i].name, s) == 0){ - tm->tzoff = zones[i].v; - return; - } - } - - /* - * one last try: look it up in the current local timezone - * probe a couple of times to get daylight/standard time change. - */ - aux = *tm; - memset(aux.zone, 0, 4); - aux.hour--; - for(i = 0; i < 2; i++){ - atm = localtime(tm2sec(&aux)); - if(cistrcmp(tm->zone, atm->zone) == 0){ - tm->tzoff = atm->tzoff; - return; - } - aux.hour++; - } - - strncpy(tm->zone, "GMT", 4); - tm->tzoff = 0; -} - -/* - * hh[:mm[:ss]] - */ -static void -time2tm(Tm *tm, char *s) -{ - tm->hour = strtoul(s, &s, 10); - if(*s++ != ':') - return; - tm->min = strtoul(s, &s, 10); - if(*s++ != ':') - return; - tm->sec = strtoul(s, &s, 10); -} - -static int -dateindex(char *d, char **tab, int n) -{ - int i; - - for(i = 0; i < n; i++) - if(cistrcmp(d, tab[i]) == 0) - return i; - return -1; -} - int imap4date(Tm *tm, char *date) { - char *flds[4]; - - if(getfields(date, flds, 3, 0, "-") != 3) + if(tmparse(tm, "DD-?MM-YYYY hh:mm:ss ?Z", date, nil, nil) == nil) return 0; - - tm->mday = strtol(flds[0], nil, 10); - tm->mon = dateindex(flds[1], monname, 12); - tm->year = strtol(flds[2], nil, 10) - 1900; return 1; } @@ -146,29 +14,17 @@ ulong imap4datetime(char *date) { - char *flds[4], *sflds[4]; - ulong t; Tm tm; + vlong s; - if(getfields(date, flds, 4, 0, " ") != 3) - return ~0; - - if(!imap4date(&tm, flds[0])) - return ~0; - - if(getfields(flds[1], sflds, 3, 0, ":") != 3) - return ~0; - - tm.hour = strtol(sflds[0], nil, 10); - tm.min = strtol(sflds[1], nil, 10); - tm.sec = strtol(sflds[2], nil, 10); - - strcpy(tm.zone, "GMT"); - tm.yday = 0; - t = tm2sec(&tm); - zone2tm(&tm, flds[2]); - t -= tm.tzoff; - return t; + s = -1; + if(tmparse(&tm, "?DD-?MM-YYYY hh:mm:ss ?Z", date, nil, nil) != nil) + s = tmnorm(&tm); + else if(tmparse(&tm, "?W, ?DD-?MM-YYYY hh:mm:ss ?Z", date, nil, nil) != nil) + s = tmnorm(&tm); + if(s > 0 && s < (1ULL<<31)) + return s; + return ~0; } /* @@ -181,85 +37,18 @@ Tm* date2tm(Tm *tm, char *date) { - char *flds[7], *s, dstr[64]; - int n; - Tm gmt, *atm; + char **f, *fmts[] = { + "?W, ?DD ?MMM YYYY hh:mm:ss ?Z", + "?W ?M ?DD hh:mm:ss ?Z YYYY", + "?W, DD-?MM-YY hh:mm:ss ?Z", + "?DD ?MMM YYYY hh:mm:ss ?Z", + "?M ?DD hh:mm:ss ?Z YYYY", + "DD-?MM-YYYY hh:mm:ss ?Z", + nil, + }; - /* - * default date is Thu Jan 1 00:00:00 GMT 1970 - */ - tm->wday = 4; - tm->mday = 1; - tm->mon = 1; - tm->hour = 0; - tm->min = 0; - tm->sec = 0; - tm->year = 70; - strcpy(tm->zone, "GMT"); - tm->tzoff = 0; - - strncpy(dstr, date, sizeof dstr); - dstr[sizeof dstr - 1] = 0; - n = tokenize(dstr, flds, 7); - if(n != 6 && n != 5) - return nil; - - if(n == 5){ - for(n = 5; n >= 1; n--) - flds[n] = flds[n - 1]; - n = 5; - }else{ - /* - * Wday[,] - */ - s = strchr(flds[0], ','); - if(s != nil) - *s = 0; - tm->wday = dateindex(flds[0], wdayname, 7); - if(tm->wday < 0) - return nil; - } - - /* - * check for the two major formats: - * Month first or day first - */ - tm->mon = dateindex(flds[1], monname, 12); - if(tm->mon >= 0){ - tm->mday = strtoul(flds[2], nil, 10); - time2tm(tm, flds[3]); - zone2tm(tm, flds[4]); - tm->year = strtoul(flds[5], nil, 10); - if(strlen(flds[5]) > 2) - tm->year -= 1900; - }else{ - tm->mday = strtoul(flds[1], nil, 10); - tm->mon = dateindex(flds[2], monname, 12); - if(tm->mon < 0) - return nil; - tm->year = strtoul(flds[3], nil, 10); - if(strlen(flds[3]) > 2) - tm->year -= 1900; - time2tm(tm, flds[4]); - zone2tm(tm, flds[5]); - } - - if(n == 5){ - gmt = *tm; - strncpy(gmt.zone, "", 4); - gmt.tzoff = 0; - atm = gmtime(tm2sec(&gmt)); - tm->wday = atm->wday; - }else{ - /* - * Wday[,] - */ - s = strchr(flds[0], ','); - if(s != nil) - *s = 0; - tm->wday = dateindex(flds[0], wdayname, 7); - if(tm->wday < 0) - return nil; - } - return tm; + for(f = fmts; *f; f++) + if(tmparse(tm, *f, date, nil, nil) != nil) + return tm; + return nil; } diff -r f8f63e944375 sys/src/cmd/upas/imap4d/imap4d.c --- a/sys/src/cmd/upas/imap4d/imap4d.c Fri Jul 17 16:53:20 2020 +0200 +++ b/sys/src/cmd/upas/imap4d/imap4d.c Sat Jul 18 23:30:43 2020 -0700 @@ -215,6 +215,7 @@ Binit(&bin, dup(0, -1), OREAD); close(0); Binit(&bout, 1, OWRITE); + tmfmtinstall(); quotefmtinstall(); fmtinstall('F', Ffmt); fmtinstall('D', Dfmt); /* rfc822; # imap date %Z */ diff -r f8f63e944375 sys/src/cmd/upas/imap4d/print.c --- a/sys/src/cmd/upas/imap4d/print.c Fri Jul 17 16:53:20 2020 +0200 +++ b/sys/src/cmd/upas/imap4d/print.c Sat Jul 18 23:30:43 2020 -0700 @@ -90,40 +90,24 @@ return fmtstrcpy(f, encfs(buf, sizeof buf, s)); } -static char *day[] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", -}; - -static char *mon[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - int Dfmt(Fmt *f) { - char buf[128], *p, *e, *sgn, *fmt; - int off; - Tm *tm; + char buf[128], *fmt; + Tm *tm, t; tm = va_arg(f->args, Tm*); - if(tm == nil) - tm = localtime(time(0)); - sgn = "+"; - if(tm->tzoff < 0) - sgn = ""; - e = buf + sizeof buf; - p = buf; - off = (tm->tzoff/3600)*100 + (tm->tzoff/60)%60; + if(tm == nil){ + tz = tzload("local"); + tm = tmtime(&t, time(0), tz); + } if((f->flags & FmtSharp) == 0){ /* rfc822 style */ - fmt = "%.2d %s %.4d %.2d:%.2d:%.2d %s%.4d"; - p = seprint(p, e, "%s, ", day[tm->wday]); + fmt = "WW, DD MMM YYYY hh:mm:ss Z"; }else - fmt = "%2d-%s-%.4d %2.2d:%2.2d:%2.2d %s%4.4d"; - seprint(p, e, fmt, - tm->mday, mon[tm->mon], tm->year + 1900, tm->hour, tm->min, tm->sec, - sgn, off); + fmt = "DD-MMM-YYYY hh:mm:ss Z"; if(f->r == L'δ') - return fmtstrcpy(f, buf); + return fmtprint(f, "%τ", tmfmt(tm, fmt)); + snprint(buf, sizeof(buf), "%τ", tmfmt(tm, fmt)); return fmtprint(f, "%Z", buf); } diff -r f8f63e944375 sys/src/cmd/upas/marshal/marshal.c --- a/sys/src/cmd/upas/marshal/marshal.c Fri Jul 17 16:53:20 2020 +0200 +++ b/sys/src/cmd/upas/marshal/marshal.c Sat Jul 18 23:30:43 2020 -0700 @@ -140,6 +140,7 @@ char lastchar; char *replymsg; +#define Rfc822fmt "WW, DD MMM YYYY hh:mm:ss Z" enum { Ok = 0, @@ -208,6 +209,7 @@ hdrstring = nil; ccargc = bccargc = 0; + tmfmtinstall(); quotefmtinstall(); fmtinstall('Z', doublequote); fmtinstall('U', rfc2047fmt); @@ -792,29 +794,13 @@ Bterm(f); } -char *ascwday[] = -{ - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -}; - -char *ascmon[] = -{ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - int printdate(Biobuf *b) { - int tz; Tm *tm; tm = localtime(time(0)); - tz = (tm->tzoff/3600)*100 + (tm->tzoff/60)%60; - - return Bprint(b, "Date: %s, %d %s %d %2.2d:%2.2d:%2.2d %s%.4d\n", - ascwday[tm->wday], tm->mday, ascmon[tm->mon], 1900 + tm->year, - tm->hour, tm->min, tm->sec, tz>=0?"+":"", tz); + return Bprint(b, "Date: %τ\n", tmfmt(tm, Rfc822fmt)); } int @@ -1003,16 +989,10 @@ int printunixfrom(int fd) { - int tz; Tm *tm; tm = localtime(time(0)); - tz = (tm->tzoff/3600)*100 + (tm->tzoff/60)%60; - - return fprint(fd, "From %s %s %s %d %2.2d:%2.2d:%2.2d %s%.4d %d\n", - user, - ascwday[tm->wday], ascmon[tm->mon], tm->mday, - tm->hour, tm->min, tm->sec, tz>=0?"+":"", tz, 1900 + tm->year); + return fprint(fd, "From %s %τ\n", user, tmfmt(tm, Rfc822fmt)); } char *specialfile[] =