17dd7cddfSDavid du Colombier #include <u.h> 27dd7cddfSDavid du Colombier #include <libc.h> 37dd7cddfSDavid du Colombier #include <bio.h> 49a747e4fSDavid du Colombier #include <auth.h> 57dd7cddfSDavid du Colombier #include "imap4d.h" 67dd7cddfSDavid du Colombier 77dd7cddfSDavid du Colombier char * 87dd7cddfSDavid du Colombier wdayname[7] = 97dd7cddfSDavid du Colombier { 107dd7cddfSDavid du Colombier "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 117dd7cddfSDavid du Colombier }; 127dd7cddfSDavid du Colombier 137dd7cddfSDavid du Colombier char * 147dd7cddfSDavid du Colombier monname[12] = 157dd7cddfSDavid du Colombier { 167dd7cddfSDavid du Colombier "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 177dd7cddfSDavid du Colombier }; 187dd7cddfSDavid du Colombier 197dd7cddfSDavid du Colombier static void time2tm(Tm *tm, char *s); 207dd7cddfSDavid du Colombier static void zone2tm(Tm *tm, char *s); 217dd7cddfSDavid du Colombier static int dateindex(char *d, char **tab, int n); 227dd7cddfSDavid du Colombier 237dd7cddfSDavid du Colombier int 247dd7cddfSDavid du Colombier rfc822date(char *s, int n, Tm *tm) 257dd7cddfSDavid du Colombier { 267dd7cddfSDavid du Colombier char *plus; 277dd7cddfSDavid du Colombier int m; 287dd7cddfSDavid du Colombier 297dd7cddfSDavid du Colombier plus = "+"; 307dd7cddfSDavid du Colombier if(tm->tzoff < 0) 317dd7cddfSDavid du Colombier plus = ""; 327dd7cddfSDavid du Colombier m = 0; 337dd7cddfSDavid du Colombier if(tm->wday != 8){ 347dd7cddfSDavid du Colombier m = snprint(s, n, "%s, ", wdayname[tm->wday]); 357dd7cddfSDavid du Colombier if(m < 0) 367dd7cddfSDavid du Colombier return m; 377dd7cddfSDavid du Colombier } 387dd7cddfSDavid du Colombier return snprint(s+m, n-m, "%.2d %s %.4d %.2d:%.2d:%.2d %s%.4d", 397dd7cddfSDavid du Colombier tm->mday, monname[tm->mon], tm->year+1900, tm->hour, tm->min, tm->sec, 407dd7cddfSDavid du Colombier plus, (tm->tzoff/3600)*100 + (tm->tzoff/60)%60); 417dd7cddfSDavid du Colombier } 427dd7cddfSDavid du Colombier 437dd7cddfSDavid du Colombier int 447dd7cddfSDavid du Colombier imap4date(char *s, int n, Tm *tm) 457dd7cddfSDavid du Colombier { 467dd7cddfSDavid du Colombier char *plus; 477dd7cddfSDavid du Colombier 487dd7cddfSDavid du Colombier plus = "+"; 497dd7cddfSDavid du Colombier if(tm->tzoff < 0) 507dd7cddfSDavid du Colombier plus = ""; 517dd7cddfSDavid du Colombier return snprint(s, n, "%2d-%s-%.4d %2.2d:%2.2d:%2.2d %s%4.4d", 527dd7cddfSDavid du Colombier tm->mday, monname[tm->mon], tm->year+1900, tm->hour, tm->min, tm->sec, plus, (tm->tzoff/3600)*100 + (tm->tzoff/60)%60); 537dd7cddfSDavid du Colombier } 547dd7cddfSDavid du Colombier 557dd7cddfSDavid du Colombier int 567dd7cddfSDavid du Colombier imap4Date(Tm *tm, char *date) 577dd7cddfSDavid du Colombier { 587dd7cddfSDavid du Colombier char *flds[4]; 597dd7cddfSDavid du Colombier 607dd7cddfSDavid du Colombier if(getfields(date, flds, 3, 0, "-") != 3) 617dd7cddfSDavid du Colombier return 0; 627dd7cddfSDavid du Colombier 637dd7cddfSDavid du Colombier tm->mday = strtol(flds[0], nil, 10); 647dd7cddfSDavid du Colombier tm->mon = dateindex(flds[1], monname, 12); 657dd7cddfSDavid du Colombier tm->year = strtol(flds[2], nil, 10) - 1900; 667dd7cddfSDavid du Colombier return 1; 677dd7cddfSDavid du Colombier } 687dd7cddfSDavid du Colombier 697dd7cddfSDavid du Colombier /* 707dd7cddfSDavid du Colombier * parse imap4 dates 717dd7cddfSDavid du Colombier */ 727dd7cddfSDavid du Colombier ulong 737dd7cddfSDavid du Colombier imap4DateTime(char *date) 747dd7cddfSDavid du Colombier { 757dd7cddfSDavid du Colombier Tm tm; 767dd7cddfSDavid du Colombier char *flds[4], *sflds[4]; 777dd7cddfSDavid du Colombier ulong t; 787dd7cddfSDavid du Colombier 797dd7cddfSDavid du Colombier if(getfields(date, flds, 4, 0, " ") != 3) 807dd7cddfSDavid du Colombier return ~0; 817dd7cddfSDavid du Colombier 827dd7cddfSDavid du Colombier if(!imap4Date(&tm, flds[0])) 837dd7cddfSDavid du Colombier return ~0; 847dd7cddfSDavid du Colombier 857dd7cddfSDavid du Colombier if(getfields(flds[1], sflds, 3, 0, ":") != 3) 867dd7cddfSDavid du Colombier return ~0; 877dd7cddfSDavid du Colombier 887dd7cddfSDavid du Colombier tm.hour = strtol(sflds[0], nil, 10); 897dd7cddfSDavid du Colombier tm.min = strtol(sflds[1], nil, 10); 907dd7cddfSDavid du Colombier tm.sec = strtol(sflds[2], nil, 10); 917dd7cddfSDavid du Colombier 927dd7cddfSDavid du Colombier strcpy(tm.zone, "GMT"); 93*6b6b9ac8SDavid du Colombier tm.yday = 0; 947dd7cddfSDavid du Colombier t = tm2sec(&tm); 957dd7cddfSDavid du Colombier zone2tm(&tm, flds[2]); 967dd7cddfSDavid du Colombier t -= tm.tzoff; 977dd7cddfSDavid du Colombier return t; 987dd7cddfSDavid du Colombier } 997dd7cddfSDavid du Colombier 1007dd7cddfSDavid du Colombier /* 1017dd7cddfSDavid du Colombier * parse dates of formats 1027dd7cddfSDavid du Colombier * [Wkd[,]] DD Mon YYYY HH:MM:SS zone 1037dd7cddfSDavid du Colombier * [Wkd] Mon ( D|DD) HH:MM:SS zone YYYY 1047dd7cddfSDavid du Colombier * plus anything similar 1057dd7cddfSDavid du Colombier * return nil for a failure 1067dd7cddfSDavid du Colombier */ 1077dd7cddfSDavid du Colombier Tm* 1087dd7cddfSDavid du Colombier date2tm(Tm *tm, char *date) 1097dd7cddfSDavid du Colombier { 1107dd7cddfSDavid du Colombier Tm gmt, *atm; 1117dd7cddfSDavid du Colombier char *flds[7], *s, dstr[64]; 1127dd7cddfSDavid du Colombier int n; 1137dd7cddfSDavid du Colombier 1147dd7cddfSDavid du Colombier /* 1157dd7cddfSDavid du Colombier * default date is Thu Jan 1 00:00:00 GMT 1970 1167dd7cddfSDavid du Colombier */ 1177dd7cddfSDavid du Colombier tm->wday = 4; 1187dd7cddfSDavid du Colombier tm->mday = 1; 1197dd7cddfSDavid du Colombier tm->mon = 1; 1207dd7cddfSDavid du Colombier tm->hour = 0; 1217dd7cddfSDavid du Colombier tm->min = 0; 1227dd7cddfSDavid du Colombier tm->sec = 0; 1237dd7cddfSDavid du Colombier tm->year = 70; 1247dd7cddfSDavid du Colombier strcpy(tm->zone, "GMT"); 1257dd7cddfSDavid du Colombier tm->tzoff = 0; 1267dd7cddfSDavid du Colombier 1277dd7cddfSDavid du Colombier strncpy(dstr, date, sizeof(dstr)); 1287dd7cddfSDavid du Colombier dstr[sizeof(dstr)-1] = '\0'; 1297dd7cddfSDavid du Colombier n = tokenize(dstr, flds, 7); 1307dd7cddfSDavid du Colombier if(n != 6 && n != 5) 1317dd7cddfSDavid du Colombier return nil; 1327dd7cddfSDavid du Colombier 1337dd7cddfSDavid du Colombier if(n == 5){ 1347dd7cddfSDavid du Colombier for(n = 5; n >= 0; n--) 1357dd7cddfSDavid du Colombier flds[n] = flds[n - 1]; 1367dd7cddfSDavid du Colombier n = 5; 1377dd7cddfSDavid du Colombier }else{ 1387dd7cddfSDavid du Colombier /* 1397dd7cddfSDavid du Colombier * Wday[,] 1407dd7cddfSDavid du Colombier */ 1417dd7cddfSDavid du Colombier s = strchr(flds[0], ','); 1427dd7cddfSDavid du Colombier if(s != nil) 1437dd7cddfSDavid du Colombier *s = '\0'; 1447dd7cddfSDavid du Colombier tm->wday = dateindex(flds[0], wdayname, 7); 1457dd7cddfSDavid du Colombier if(tm->wday < 0) 1467dd7cddfSDavid du Colombier return nil; 1477dd7cddfSDavid du Colombier } 1487dd7cddfSDavid du Colombier 1497dd7cddfSDavid du Colombier /* 1507dd7cddfSDavid du Colombier * check for the two major formats: 1517dd7cddfSDavid du Colombier * Month first or day first 1527dd7cddfSDavid du Colombier */ 1537dd7cddfSDavid du Colombier tm->mon = dateindex(flds[1], monname, 12); 1547dd7cddfSDavid du Colombier if(tm->mon >= 0){ 1557dd7cddfSDavid du Colombier tm->mday = strtoul(flds[2], nil, 10); 1567dd7cddfSDavid du Colombier time2tm(tm, flds[3]); 1577dd7cddfSDavid du Colombier zone2tm(tm, flds[4]); 1587dd7cddfSDavid du Colombier tm->year = strtoul(flds[5], nil, 10); 1597dd7cddfSDavid du Colombier if(strlen(flds[5]) > 2) 1607dd7cddfSDavid du Colombier tm->year -= 1900; 1617dd7cddfSDavid du Colombier }else{ 1627dd7cddfSDavid du Colombier tm->mday = strtoul(flds[1], nil, 10); 1637dd7cddfSDavid du Colombier tm->mon = dateindex(flds[2], monname, 12); 1647dd7cddfSDavid du Colombier tm->year = strtoul(flds[3], nil, 10); 1657dd7cddfSDavid du Colombier if(strlen(flds[3]) > 2) 1667dd7cddfSDavid du Colombier tm->year -= 1900; 1677dd7cddfSDavid du Colombier time2tm(tm, flds[4]); 1687dd7cddfSDavid du Colombier zone2tm(tm, flds[5]); 1697dd7cddfSDavid du Colombier } 1707dd7cddfSDavid du Colombier 1717dd7cddfSDavid du Colombier if(n == 5){ 1727dd7cddfSDavid du Colombier gmt = *tm; 1737dd7cddfSDavid du Colombier strncpy(gmt.zone, "", 4); 1747dd7cddfSDavid du Colombier gmt.tzoff = 0; 1757dd7cddfSDavid du Colombier atm = gmtime(tm2sec(&gmt)); 1767dd7cddfSDavid du Colombier tm->wday = atm->wday; 1777dd7cddfSDavid du Colombier }else{ 1787dd7cddfSDavid du Colombier /* 1797dd7cddfSDavid du Colombier * Wday[,] 1807dd7cddfSDavid du Colombier */ 1817dd7cddfSDavid du Colombier s = strchr(flds[0], ','); 1827dd7cddfSDavid du Colombier if(s != nil) 1837dd7cddfSDavid du Colombier *s = '\0'; 1847dd7cddfSDavid du Colombier tm->wday = dateindex(flds[0], wdayname, 7); 1857dd7cddfSDavid du Colombier if(tm->wday < 0) 1867dd7cddfSDavid du Colombier return nil; 1877dd7cddfSDavid du Colombier } 1887dd7cddfSDavid du Colombier return tm; 1897dd7cddfSDavid du Colombier } 1907dd7cddfSDavid du Colombier 1917dd7cddfSDavid du Colombier /* 1927dd7cddfSDavid du Colombier * zone : [A-Za-z][A-Za-z][A-Za-z] some time zone names 1937dd7cddfSDavid du Colombier * | [A-IK-Z] military time; rfc1123 says the rfc822 spec is wrong. 1947dd7cddfSDavid du Colombier * | "UT" universal time 1957dd7cddfSDavid du Colombier * | [+-][0-9][0-9][0-9][0-9] 1967dd7cddfSDavid du Colombier * zones is the rfc-822 list of time zone names 1977dd7cddfSDavid du Colombier */ 1987dd7cddfSDavid du Colombier static NamedInt zones[] = 1997dd7cddfSDavid du Colombier { 2007dd7cddfSDavid du Colombier {"A", -1 * 3600}, 2017dd7cddfSDavid du Colombier {"B", -2 * 3600}, 2027dd7cddfSDavid du Colombier {"C", -3 * 3600}, 2037dd7cddfSDavid du Colombier {"CDT", -5 * 3600}, 2047dd7cddfSDavid du Colombier {"CST", -6 * 3600}, 2057dd7cddfSDavid du Colombier {"D", -4 * 3600}, 2067dd7cddfSDavid du Colombier {"E", -5 * 3600}, 2077dd7cddfSDavid du Colombier {"EDT", -4 * 3600}, 2087dd7cddfSDavid du Colombier {"EST", -5 * 3600}, 2097dd7cddfSDavid du Colombier {"F", -6 * 3600}, 2107dd7cddfSDavid du Colombier {"G", -7 * 3600}, 2117dd7cddfSDavid du Colombier {"GMT", 0}, 2127dd7cddfSDavid du Colombier {"H", -8 * 3600}, 2137dd7cddfSDavid du Colombier {"I", -9 * 3600}, 2147dd7cddfSDavid du Colombier {"K", -10 * 3600}, 2157dd7cddfSDavid du Colombier {"L", -11 * 3600}, 2167dd7cddfSDavid du Colombier {"M", -12 * 3600}, 2177dd7cddfSDavid du Colombier {"MDT", -6 * 3600}, 2187dd7cddfSDavid du Colombier {"MST", -7 * 3600}, 2197dd7cddfSDavid du Colombier {"N", +1 * 3600}, 2207dd7cddfSDavid du Colombier {"O", +2 * 3600}, 2217dd7cddfSDavid du Colombier {"P", +3 * 3600}, 2227dd7cddfSDavid du Colombier {"PDT", -7 * 3600}, 2237dd7cddfSDavid du Colombier {"PST", -8 * 3600}, 2247dd7cddfSDavid du Colombier {"Q", +4 * 3600}, 2257dd7cddfSDavid du Colombier {"R", +5 * 3600}, 2267dd7cddfSDavid du Colombier {"S", +6 * 3600}, 2277dd7cddfSDavid du Colombier {"T", +7 * 3600}, 2287dd7cddfSDavid du Colombier {"U", +8 * 3600}, 2297dd7cddfSDavid du Colombier {"UT", 0}, 2307dd7cddfSDavid du Colombier {"V", +9 * 3600}, 2317dd7cddfSDavid du Colombier {"W", +10 * 3600}, 2327dd7cddfSDavid du Colombier {"X", +11 * 3600}, 2337dd7cddfSDavid du Colombier {"Y", +12 * 3600}, 2347dd7cddfSDavid du Colombier {"Z", 0}, 2357dd7cddfSDavid du Colombier {nil, 0} 2367dd7cddfSDavid du Colombier }; 2377dd7cddfSDavid du Colombier 2387dd7cddfSDavid du Colombier static void 2397dd7cddfSDavid du Colombier zone2tm(Tm *tm, char *s) 2407dd7cddfSDavid du Colombier { 2417dd7cddfSDavid du Colombier Tm aux, *atm; 2427dd7cddfSDavid du Colombier int i; 2437dd7cddfSDavid du Colombier 2447dd7cddfSDavid du Colombier if(*s == '+' || *s == '-'){ 2457dd7cddfSDavid du Colombier i = strtol(s, &s, 10); 2467dd7cddfSDavid du Colombier tm->tzoff = (i / 100) * 3600 + i % 100; 2477dd7cddfSDavid du Colombier strncpy(tm->zone, "", 4); 2487dd7cddfSDavid du Colombier return; 2497dd7cddfSDavid du Colombier } 2507dd7cddfSDavid du Colombier 2517dd7cddfSDavid du Colombier /* 2527dd7cddfSDavid du Colombier * look it up in the standard rfc822 table 2537dd7cddfSDavid du Colombier */ 2547dd7cddfSDavid du Colombier strncpy(tm->zone, s, 3); 2557dd7cddfSDavid du Colombier tm->zone[3] = '\0'; 2567dd7cddfSDavid du Colombier tm->tzoff = 0; 2577dd7cddfSDavid du Colombier for(i = 0; zones[i].name != nil; i++){ 2587dd7cddfSDavid du Colombier if(cistrcmp(zones[i].name, s) == 0){ 2597dd7cddfSDavid du Colombier tm->tzoff = zones[i].v; 2607dd7cddfSDavid du Colombier return; 2617dd7cddfSDavid du Colombier } 2627dd7cddfSDavid du Colombier } 2637dd7cddfSDavid du Colombier 2647dd7cddfSDavid du Colombier /* 2657dd7cddfSDavid du Colombier * one last try: look it up in the current local timezone 2667dd7cddfSDavid du Colombier * probe a couple of times to get daylight/standard time change. 2677dd7cddfSDavid du Colombier */ 2687dd7cddfSDavid du Colombier aux = *tm; 2697dd7cddfSDavid du Colombier memset(aux.zone, 0, 4); 2707dd7cddfSDavid du Colombier aux.hour--; 2717dd7cddfSDavid du Colombier for(i = 0; i < 2; i++){ 2727dd7cddfSDavid du Colombier atm = localtime(tm2sec(&aux)); 2737dd7cddfSDavid du Colombier if(cistrcmp(tm->zone, atm->zone) == 0){ 2747dd7cddfSDavid du Colombier tm->tzoff = atm->tzoff; 2757dd7cddfSDavid du Colombier return; 2767dd7cddfSDavid du Colombier } 2777dd7cddfSDavid du Colombier aux.hour++; 2787dd7cddfSDavid du Colombier } 2797dd7cddfSDavid du Colombier 2807dd7cddfSDavid du Colombier strncpy(tm->zone, "GMT", 4); 2817dd7cddfSDavid du Colombier tm->tzoff = 0; 2827dd7cddfSDavid du Colombier } 2837dd7cddfSDavid du Colombier 2847dd7cddfSDavid du Colombier /* 2857dd7cddfSDavid du Colombier * hh[:mm[:ss]] 2867dd7cddfSDavid du Colombier */ 2877dd7cddfSDavid du Colombier static void 2887dd7cddfSDavid du Colombier time2tm(Tm *tm, char *s) 2897dd7cddfSDavid du Colombier { 2907dd7cddfSDavid du Colombier tm->hour = strtoul(s, &s, 10); 2917dd7cddfSDavid du Colombier if(*s++ != ':') 2927dd7cddfSDavid du Colombier return; 2937dd7cddfSDavid du Colombier tm->min = strtoul(s, &s, 10); 2947dd7cddfSDavid du Colombier if(*s++ != ':') 2957dd7cddfSDavid du Colombier return; 2967dd7cddfSDavid du Colombier tm->sec = strtoul(s, &s, 10); 2977dd7cddfSDavid du Colombier } 2987dd7cddfSDavid du Colombier 2997dd7cddfSDavid du Colombier static int 3007dd7cddfSDavid du Colombier dateindex(char *d, char **tab, int n) 3017dd7cddfSDavid du Colombier { 3027dd7cddfSDavid du Colombier int i; 3037dd7cddfSDavid du Colombier 3047dd7cddfSDavid du Colombier for(i = 0; i < n; i++) 3057dd7cddfSDavid du Colombier if(cistrcmp(d, tab[i]) == 0) 3067dd7cddfSDavid du Colombier return i; 3077dd7cddfSDavid du Colombier return -1; 3087dd7cddfSDavid du Colombier } 309