]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libhttpd/date.c
merge
[plan9front.git] / sys / src / libhttpd / date.c
1 #include <u.h>
2 #include <libc.h>
3 #include <httpd.h>
4
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 };
24
25 static char *
26 monname[12] =
27 {
28         "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
29 };
30
31 static  int     dateindex(char*, char**, int);
32
33 static int
34 dtolower(int c)
35 {
36         if(c >= 'A' && c <= 'Z')
37                 return c - 'A' + 'a';
38         return c;
39 }
40
41 static int
42 disalpha(int c)
43 {
44         return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z';
45 }
46
47 static int
48 disdig(int c)
49 {
50         return c >= '0' && c <= '9';
51 }
52
53 int
54 hdatefmt(Fmt *f)
55 {
56         Tm *tm;
57         ulong t;
58
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 }
65
66 static char*
67 dateword(char *date, char *buf)
68 {
69         char *p;
70         int c;
71
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 }
83
84 static int
85 datenum(char **d)
86 {
87         char *date;
88         int c, n;
89
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++;
101         }
102         *d = date;
103         return n;
104 }
105
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)
112 {
113         Tm tm;
114         char buf[32];
115
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;
125
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;
138
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;
151
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;
176
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;
189
190                 /*
191                  * timezone
192                  */
193                 dateword(date, buf);
194                 if(strncmp(buf, "gmt", 3) != 0)
195                         return 0;
196         }
197
198         strcpy(tm.zone, "GMT");
199         tm.tzoff = 0;
200         tm.yday = 0;
201         return tm2sec(&tm);
202 }
203
204 static int
205 dateindex(char *d, char **tab, int n)
206 {
207         int i;
208
209         for(i = 0; i < n; i++)
210                 if(cistrcmp(d, tab[i]) == 0)
211                         return i;
212         return -1;
213 }