Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <httpd.h>
5 /*
6 * print dates in the format
7 * Wkd, DD Mon YYYY HH:MM:SS GMT
8 * parse dates of formats
9 * Wkd, DD Mon YYYY HH:MM:SS GMT
10 * Weekday, DD-Mon-YY HH:MM:SS GMT
11 * Wkd Mon ( D|DD) HH:MM:SS YYYY
12 * plus anything similar
13 */
14 static char *
15 weekdayname[7] =
16 {
17 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
18 };
19 static char *
20 wdayname[7] =
21 {
22 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
23 };
25 static char *
26 monname[12] =
27 {
28 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
29 };
31 static int dateindex(char*, char**, int);
33 static int
34 dtolower(int c)
35 {
36 if(c >= 'A' && c <= 'Z')
37 return c - 'A' + 'a';
38 return c;
39 }
41 static int
42 disalpha(int c)
43 {
44 return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z';
45 }
47 static int
48 disdig(int c)
49 {
50 return c >= '0' && c <= '9';
51 }
53 int
54 hdatefmt(Fmt *f)
55 {
56 Tm *tm;
57 ulong t;
59 t = va_arg(f->args, ulong);
60 tm = gmtime(t);
61 return fmtprint(f, "%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
62 wdayname[tm->wday], tm->mday, monname[tm->mon], tm->year+1900,
63 tm->hour, tm->min, tm->sec);
64 }
66 static char*
67 dateword(char *date, char *buf)
68 {
69 char *p;
70 int c;
72 p = buf;
73 while(!disalpha(c = *date) && !disdig(c) && c)
74 date++;
75 while(disalpha(c = *date)){
76 if(p - buf < 30)
77 *p++ = dtolower(c);
78 date++;
79 }
80 *p = 0;
81 return date;
82 }
84 static int
85 datenum(char **d)
86 {
87 char *date;
88 int c, n;
90 date = *d;
91 while(!disdig(c = *date) && c)
92 date++;
93 if(c == 0){
94 *d = date;
95 return -1;
96 }
97 n = 0;
98 while(disdig(c = *date)){
99 n = n * 10 + c - '0';
100 date++;
102 *d = date;
103 return n;
106 /*
107 * parse a date and return the seconds since the epoch
108 * return 0 for a failure
109 */
110 ulong
111 hdate2sec(char *date)
113 Tm tm;
114 char buf[32];
116 /*
117 * Weekday|Wday
118 */
119 date = dateword(date, buf);
120 tm.wday = dateindex(buf, wdayname, 7);
121 if(tm.wday < 0)
122 tm.wday = dateindex(buf, weekdayname, 7);
123 if(tm.wday < 0)
124 return 0;
126 /*
127 * check for the two major formats
128 */
129 date = dateword(date, buf);
130 tm.mon = dateindex(buf, monname, 12);
131 if(tm.mon >= 0){
132 /*
133 * MM
134 */
135 tm.mday = datenum(&date);
136 if(tm.mday < 1 || tm.mday > 31)
137 return 0;
139 /*
140 * HH:MM:SS
141 */
142 tm.hour = datenum(&date);
143 if(tm.hour < 0 || tm.hour >= 24)
144 return 0;
145 tm.min = datenum(&date);
146 if(tm.min < 0 || tm.min >= 60)
147 return 0;
148 tm.sec = datenum(&date);
149 if(tm.sec < 0 || tm.sec >= 60)
150 return 0;
152 /*
153 * YYYY
154 */
155 tm.year = datenum(&date);
156 if(tm.year < 70 || tm.year > 99 && tm.year < 1970)
157 return 0;
158 if(tm.year >= 1970)
159 tm.year -= 1900;
160 }else{
161 /*
162 * MM-Mon-(YY|YYYY)
163 */
164 tm.mday = datenum(&date);
165 if(tm.mday < 1 || tm.mday > 31)
166 return 0;
167 date = dateword(date, buf);
168 tm.mon = dateindex(buf, monname, 12);
169 if(tm.mon < 0 || tm.mon >= 12)
170 return 0;
171 tm.year = datenum(&date);
172 if(tm.year < 70 || tm.year > 99 && tm.year < 1970)
173 return 0;
174 if(tm.year >= 1970)
175 tm.year -= 1900;
177 /*
178 * HH:MM:SS
179 */
180 tm.hour = datenum(&date);
181 if(tm.hour < 0 || tm.hour >= 24)
182 return 0;
183 tm.min = datenum(&date);
184 if(tm.min < 0 || tm.min >= 60)
185 return 0;
186 tm.sec = datenum(&date);
187 if(tm.sec < 0 || tm.sec >= 60)
188 return 0;
190 /*
191 * timezone
192 */
193 dateword(date, buf);
194 if(strncmp(buf, "gmt", 3) != 0)
195 return 0;
198 strcpy(tm.zone, "GMT");
199 tm.tzoff = 0;
200 tm.yday = 0;
201 return tm2sec(&tm);
204 static int
205 dateindex(char *d, char **tab, int n)
207 int i;
209 for(i = 0; i < n; i++)
210 if(cistrcmp(d, tab[i]) == 0)
211 return i;
212 return -1;