|  | #include <u.h> | 
|  | #include <libc.h> | 
|  | #include <httpd.h> | 
|  |  | 
|  | /* | 
|  | * print dates in the format | 
|  | * Wkd, DD Mon YYYY HH:MM:SS GMT | 
|  | * parse dates of formats | 
|  | * Wkd, DD Mon YYYY HH:MM:SS GMT | 
|  | * Weekday, DD-Mon-YY HH:MM:SS GMT | 
|  | * Wkd Mon ( D|DD) HH:MM:SS YYYY | 
|  | * plus anything similar | 
|  | */ | 
|  | static char * | 
|  | weekdayname[7] = | 
|  | { | 
|  | "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" | 
|  | }; | 
|  | static char * | 
|  | wdayname[7] = | 
|  | { | 
|  | "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" | 
|  | }; | 
|  |  | 
|  | static char * | 
|  | monname[12] = | 
|  | { | 
|  | "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" | 
|  | }; | 
|  |  | 
|  | static	int	dateindex(char*, char**, int); | 
|  |  | 
|  | static int | 
|  | dtolower(int c) | 
|  | { | 
|  | if(c >= 'A' && c <= 'Z') | 
|  | return c - 'A' + 'a'; | 
|  | return c; | 
|  | } | 
|  |  | 
|  | static int | 
|  | disalpha(int c) | 
|  | { | 
|  | return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z'; | 
|  | } | 
|  |  | 
|  | static int | 
|  | disdig(int c) | 
|  | { | 
|  | return c >= '0' && c <= '9'; | 
|  | } | 
|  |  | 
|  | int | 
|  | hdatefmt(Fmt *f) | 
|  | { | 
|  | Tm *tm; | 
|  | ulong t; | 
|  |  | 
|  | t = va_arg(f->args, ulong); | 
|  | tm = gmtime(t); | 
|  | return fmtprint(f, "%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT", | 
|  | wdayname[tm->wday], tm->mday, monname[tm->mon], tm->year+1900, | 
|  | tm->hour, tm->min, tm->sec); | 
|  | } | 
|  |  | 
|  | static char* | 
|  | dateword(char *date, char *buf) | 
|  | { | 
|  | char *p; | 
|  | int c; | 
|  |  | 
|  | p = buf; | 
|  | while(!disalpha(c = *date) && !disdig(c) && c) | 
|  | date++; | 
|  | while(disalpha(c = *date)){ | 
|  | if(p - buf < 30) | 
|  | *p++ = dtolower(c); | 
|  | date++; | 
|  | } | 
|  | *p = 0; | 
|  | return date; | 
|  | } | 
|  |  | 
|  | static int | 
|  | datenum(char **d) | 
|  | { | 
|  | char *date; | 
|  | int c, n; | 
|  |  | 
|  | date = *d; | 
|  | while(!disdig(c = *date) && c) | 
|  | date++; | 
|  | if(c == 0){ | 
|  | *d = date; | 
|  | return -1; | 
|  | } | 
|  | n = 0; | 
|  | while(disdig(c = *date)){ | 
|  | n = n * 10 + c - '0'; | 
|  | date++; | 
|  | } | 
|  | *d = date; | 
|  | return n; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * parse a date and return the seconds since the epoch | 
|  | * return 0 for a failure | 
|  | */ | 
|  | ulong | 
|  | hdate2sec(char *date) | 
|  | { | 
|  | Tm tm; | 
|  | char buf[32]; | 
|  |  | 
|  | /* | 
|  | * Weekday|Wday | 
|  | */ | 
|  | date = dateword(date, buf); | 
|  | tm.wday = dateindex(buf, wdayname, 7); | 
|  | if(tm.wday < 0) | 
|  | tm.wday = dateindex(buf, weekdayname, 7); | 
|  | if(tm.wday < 0) | 
|  | return 0; | 
|  |  | 
|  | /* | 
|  | * check for the two major formats | 
|  | */ | 
|  | date = dateword(date, buf); | 
|  | tm.mon = dateindex(buf, monname, 12); | 
|  | if(tm.mon >= 0){ | 
|  | /* | 
|  | * MM | 
|  | */ | 
|  | tm.mday = datenum(&date); | 
|  | if(tm.mday < 1 || tm.mday > 31) | 
|  | return 0; | 
|  |  | 
|  | /* | 
|  | * HH:MM:SS | 
|  | */ | 
|  | tm.hour = datenum(&date); | 
|  | if(tm.hour < 0 || tm.hour >= 24) | 
|  | return 0; | 
|  | tm.min = datenum(&date); | 
|  | if(tm.min < 0 || tm.min >= 60) | 
|  | return 0; | 
|  | tm.sec = datenum(&date); | 
|  | if(tm.sec < 0 || tm.sec >= 60) | 
|  | return 0; | 
|  |  | 
|  | /* | 
|  | * YYYY | 
|  | */ | 
|  | tm.year = datenum(&date); | 
|  | if(tm.year < 70 || tm.year > 99 && tm.year < 1970) | 
|  | return 0; | 
|  | if(tm.year >= 1970) | 
|  | tm.year -= 1900; | 
|  | }else{ | 
|  | /* | 
|  | * MM-Mon-(YY|YYYY) | 
|  | */ | 
|  | tm.mday = datenum(&date); | 
|  | if(tm.mday < 1 || tm.mday > 31) | 
|  | return 0; | 
|  | date = dateword(date, buf); | 
|  | tm.mon = dateindex(buf, monname, 12); | 
|  | if(tm.mon < 0 || tm.mon >= 12) | 
|  | return 0; | 
|  | tm.year = datenum(&date); | 
|  | if(tm.year < 70 || tm.year > 99 && tm.year < 1970) | 
|  | return 0; | 
|  | if(tm.year >= 1970) | 
|  | tm.year -= 1900; | 
|  |  | 
|  | /* | 
|  | * HH:MM:SS | 
|  | */ | 
|  | tm.hour = datenum(&date); | 
|  | if(tm.hour < 0 || tm.hour >= 24) | 
|  | return 0; | 
|  | tm.min = datenum(&date); | 
|  | if(tm.min < 0 || tm.min >= 60) | 
|  | return 0; | 
|  | tm.sec = datenum(&date); | 
|  | if(tm.sec < 0 || tm.sec >= 60) | 
|  | return 0; | 
|  |  | 
|  | /* | 
|  | * timezone | 
|  | */ | 
|  | dateword(date, buf); | 
|  | if(strncmp(buf, "gmt", 3) != 0) | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | strcpy(tm.zone, "GMT"); | 
|  | tm.tzoff = 0; | 
|  | tm.yday = 0; | 
|  | return tm2sec(&tm); | 
|  | } | 
|  |  | 
|  | 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; | 
|  | } |