]> git.ipfire.org Git - thirdparty/squid.git/blob - lib/rfc1123.c
SourceFormat: enforcement
[thirdparty/squid.git] / lib / rfc1123.c
1
2 /*
3 * $Id$
4 *
5 * DEBUG:
6 * AUTHOR: Harvest Derived
7 *
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 *
34 */
35
36 #include "config.h"
37
38
39 /*
40 * Adapted from HTSUtils.c in CERN httpd 3.0 (http://info.cern.ch/httpd/)
41 * by Darren Hardy <hardy@cs.colorado.edu>, November 1994.
42 */
43 #if HAVE_STDIO_H
44 #include <stdio.h>
45 #endif
46 #if HAVE_STDLIB_H
47 #include <stdlib.h>
48 #endif
49 #if HAVE_STRING_H
50 #include <string.h>
51 #endif
52 #if HAVE_CTYPE_H
53 #include <ctype.h>
54 #endif
55 #if HAVE_SYS_TYPES_H
56 #include <sys/types.h>
57 #endif
58 #if HAVE_TIME_H
59 #include <time.h>
60 #endif
61 #if HAVE_SYS_TIME_H
62 #include <sys/time.h>
63 #endif
64
65 #include "util.h"
66
67 #define RFC850_STRFTIME "%A, %d-%b-%y %H:%M:%S GMT"
68 #define RFC1123_STRFTIME "%a, %d %b %Y %H:%M:%S GMT"
69
70 static int make_month(const char *s);
71 static int make_num(const char *s);
72
73 static const char *month_names[12] = {
74 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
75 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
76 };
77
78
79 static int
80 make_num(const char *s)
81 {
82 if (*s >= '0' && *s <= '9')
83 return 10 * (*s - '0') + *(s + 1) - '0';
84 else
85 return *(s + 1) - '0';
86 }
87
88 static int
89 make_month(const char *s)
90 {
91 int i;
92 char month[3];
93
94 month[0] = xtoupper(*s);
95 month[1] = xtolower(*(s + 1));
96 month[2] = xtolower(*(s + 2));
97
98 for (i = 0; i < 12; i++)
99 if (!strncmp(month_names[i], month, 3))
100 return i;
101 return -1;
102 }
103
104 static int
105 tmSaneValues(struct tm *tm)
106 {
107 if (tm->tm_sec < 0 || tm->tm_sec > 59)
108 return 0;
109 if (tm->tm_min < 0 || tm->tm_min > 59)
110 return 0;
111 if (tm->tm_hour < 0 || tm->tm_hour > 23)
112 return 0;
113 if (tm->tm_mday < 1 || tm->tm_mday > 31)
114 return 0;
115 if (tm->tm_mon < 0 || tm->tm_mon > 11)
116 return 0;
117 return 1;
118 }
119
120 static struct tm *
121 parse_date_elements(const char *day, const char *month, const char *year,
122 const char *time, const char *zone) {
123 static struct tm tm;
124 char *t;
125 memset(&tm, 0, sizeof(tm));
126
127 if (!day || !month || !year || !time)
128 return NULL;
129 tm.tm_mday = atoi(day);
130 tm.tm_mon = make_month(month);
131 if (tm.tm_mon < 0)
132 return NULL;
133 tm.tm_year = atoi(year);
134 if (strlen(year) == 4)
135 tm.tm_year -= 1900;
136 else if (tm.tm_year < 70)
137 tm.tm_year += 100;
138 else if (tm.tm_year > 19000)
139 tm.tm_year -= 19000;
140 tm.tm_hour = make_num(time);
141 t = strchr(time, ':');
142 if (!t)
143 return NULL;
144 t++;
145 tm.tm_min = atoi(t);
146 t = strchr(t, ':');
147 if (t)
148 tm.tm_sec = atoi(t + 1);
149 return tmSaneValues(&tm) ? &tm : NULL;
150 }
151
152 static struct tm *
153 parse_date(const char *str) {
154 struct tm *tm;
155 static char tmp[64];
156 char *t;
157 char *wday = NULL;
158 char *day = NULL;
159 char *month = NULL;
160 char *year = NULL;
161 char *time = NULL;
162 char *zone = NULL;
163
164 xstrncpy(tmp, str, 64);
165
166 for (t = strtok(tmp, ", "); t; t = strtok(NULL, ", ")) {
167 if (xisdigit(*t)) {
168 if (!day) {
169 day = t;
170 t = strchr(t, '-');
171 if (t) {
172 *t++ = '\0';
173 month = t;
174 t = strchr(t, '-');
175 if (!t)
176 return NULL;
177 *t++ = '\0';
178 year = t;
179 }
180 } else if (strchr(t, ':'))
181 time = t;
182 else if (!year)
183 year = t;
184 } else if (!wday)
185 wday = t;
186 else if (!month)
187 month = t;
188 else if (!zone)
189 zone = t;
190 }
191 tm = parse_date_elements(day, month, year, time, zone);
192
193 return tm;
194 }
195
196 time_t
197 parse_rfc1123(const char *str)
198 {
199 struct tm *tm;
200 time_t t;
201 if (NULL == str)
202 return -1;
203 tm = parse_date(str);
204 if (!tm)
205 return -1;
206 tm->tm_isdst = -1;
207 #ifdef HAVE_TIMEGM
208 t = timegm(tm);
209 #elif HAVE_TM_TM_GMTOFF
210 t = mktime(tm);
211 if (t != -1) {
212 struct tm *local = localtime(&t);
213 t += local->tm_gmtoff;
214 }
215 #else
216 /* some systems do not have tm_gmtoff so we fake it */
217 t = mktime(tm);
218 if (t != -1) {
219 time_t dst = 0;
220 #if defined (_TIMEZONE)
221 #elif defined (_timezone)
222 #elif defined(_SQUID_AIX_)
223 #elif defined(_SQUID_CYGWIN_)
224 #elif defined(_SQUID_MSWIN_)
225 #elif defined(_SQUID_SGI_)
226 #else
227 extern long timezone;
228 #endif
229 /*
230 * The following assumes a fixed DST offset of 1 hour,
231 * which is probably wrong.
232 */
233 if (tm->tm_isdst > 0)
234 dst = -3600;
235 #if defined ( _timezone) || defined(_SQUID_WIN32_)
236 t -= (_timezone + dst);
237 #else
238 t -= (timezone + dst);
239 #endif
240 }
241 #endif
242 return t;
243 }
244
245 const char *
246 mkrfc1123(time_t t)
247 {
248 static char buf[128];
249
250 struct tm *gmt = gmtime(&t);
251
252 buf[0] = '\0';
253 strftime(buf, 127, RFC1123_STRFTIME, gmt);
254 return buf;
255 }
256
257 const char *
258 mkhttpdlogtime(const time_t * t)
259 {
260 static char buf[128];
261
262 struct tm *gmt = gmtime(t);
263
264 #ifndef USE_GMT
265 int gmt_min, gmt_hour, gmt_yday, day_offset;
266 size_t len;
267 struct tm *lt;
268 int min_offset;
269
270 /* localtime & gmtime may use the same static data */
271 gmt_min = gmt->tm_min;
272 gmt_hour = gmt->tm_hour;
273 gmt_yday = gmt->tm_yday;
274
275 lt = localtime(t);
276
277 day_offset = lt->tm_yday - gmt_yday;
278 /* wrap round on end of year */
279 if (day_offset > 1)
280 day_offset = -1;
281 else if (day_offset < -1)
282 day_offset = 1;
283
284 min_offset = day_offset * 1440 + (lt->tm_hour - gmt_hour) * 60
285 + (lt->tm_min - gmt_min);
286
287 len = strftime(buf, 127 - 5, "%d/%b/%Y:%H:%M:%S ", lt);
288 snprintf(buf + len, 128 - len, "%+03d%02d",
289 (min_offset / 60) % 24,
290 min_offset % 60);
291 #else /* USE_GMT */
292 buf[0] = '\0';
293 strftime(buf, 127, "%d/%b/%Y:%H:%M:%S -000", gmt);
294 #endif /* USE_GMT */
295
296 return buf;
297 }
298
299 #if 0
300 int
301 main()
302 {
303 char *x;
304 time_t t, pt;
305
306 t = time(NULL);
307 x = mkrfc1123(t);
308 printf("HTTP Time: %s\n", x);
309
310 pt = parse_rfc1123(x);
311 printf("Parsed: %d vs. %d\n", pt, t);
312 }
313
314 #endif