]> git.ipfire.org Git - thirdparty/squid.git/blob - lib/rfc1123.c
merging 2.3 branch changes
[thirdparty/squid.git] / lib / rfc1123.c
1
2 /*
3 * $Id: rfc1123.c,v 1.24 2000/03/27 21:56:21 wessels Exp $
4 *
5 * DEBUG:
6 * AUTHOR: Harvest Derived
7 *
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * ----------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * the Regents of the University of California. Please see the
16 * COPYRIGHT file for full details. Squid incorporates software
17 * developed and/or copyrighted by other sources. Please see the
18 * 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 #include "snprintf.h"
67
68 #define RFC850_STRFTIME "%A, %d-%b-%y %H:%M:%S GMT"
69 #define RFC1123_STRFTIME "%a, %d %b %Y %H:%M:%S GMT"
70
71 static int make_month(const char *s);
72 static int make_num(const char *s);
73
74 static char *month_names[12] =
75 {
76 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
77 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
78 };
79
80
81 static int
82 make_num(const char *s)
83 {
84 if (*s >= '0' && *s <= '9')
85 return 10 * (*s - '0') + *(s + 1) - '0';
86 else
87 return *(s + 1) - '0';
88 }
89
90 static int
91 make_month(const char *s)
92 {
93 int i;
94 char month[3];
95
96 month[0] = xtoupper(*s);
97 month[1] = xtolower(*(s + 1));
98 month[2] = xtolower(*(s + 2));
99
100 for (i = 0; i < 12; i++)
101 if (!strncmp(month_names[i], month, 3))
102 return i;
103 return 0;
104 }
105
106
107 time_t
108 parse_rfc1123(const char *str)
109 {
110 const char *s;
111 struct tm tm;
112 time_t t;
113
114 if (!str)
115 return -1;
116
117 memset(&tm, '\0', sizeof(struct tm));
118 if ((s = strchr(str, ','))) { /* Thursday, 10-Jun-93 01:29:59 GMT */
119 s++; /* or: Thu, 10 Jan 1993 01:29:59 GMT */
120 while (*s == ' ')
121 s++;
122 if (xisdigit(*s) && !xisdigit(*(s + 1))) /* backoff if only one digit */
123 s--;
124 if (strchr(s, '-')) { /* First format */
125 if ((int) strlen(s) < 18)
126 return -1;
127 tm.tm_mday = make_num(s);
128 tm.tm_mon = make_month(s + 3);
129 tm.tm_year = make_num(s + 7);
130 /*
131 * Y2K: Arjan de Vet <Arjan.deVet@adv.IAEhv.nl>
132 * if tm.tm_year < 70, assume it's after the year 2000.
133 */
134 if (tm.tm_year < 70)
135 tm.tm_year += 100;
136 tm.tm_hour = make_num(s + 10);
137 tm.tm_min = make_num(s + 13);
138 tm.tm_sec = make_num(s + 16);
139 } else { /* Second format */
140 if ((int) strlen(s) < 20)
141 return -1;
142 tm.tm_mday = make_num(s);
143 tm.tm_mon = make_month(s + 3);
144 tm.tm_year = (100 * make_num(s + 7) - 1900) + make_num(s + 9);
145 tm.tm_hour = make_num(s + 12);
146 tm.tm_min = make_num(s + 15);
147 tm.tm_sec = make_num(s + 18);
148
149 }
150 } else { /* Try the other format: */
151 s = str; /* Wed Jun 9 01:29:59 1993 GMT */
152 while (*s && *s == ' ')
153 s++;
154 if ((int) strlen(s) < 24)
155 return -1;
156 tm.tm_mday = make_num(s + 8);
157 tm.tm_mon = make_month(s + 4);
158 /* Y2K fix, richard.kettlewell@kewill.com */
159 tm.tm_year = atoi(s + 20) - 1900;
160 tm.tm_hour = make_num(s + 11);
161 tm.tm_min = make_num(s + 14);
162 tm.tm_sec = make_num(s + 17);
163 }
164 if (tm.tm_sec < 0 || tm.tm_sec > 59 ||
165 tm.tm_min < 0 || tm.tm_min > 59 ||
166 tm.tm_hour < 0 || tm.tm_hour > 23 ||
167 tm.tm_mday < 1 || tm.tm_mday > 31 ||
168 tm.tm_mon < 0 || tm.tm_mon > 11 ||
169 tm.tm_year < 70 || tm.tm_year > 120) {
170 return -1;
171 }
172 tm.tm_isdst = -1;
173
174 #ifdef HAVE_TIMEGM
175 t = timegm(&tm);
176 #elif HAVE_TM_GMTOFF
177 t = mktime(&tm);
178 {
179 struct tm *local = localtime(&t);
180 t += local->tm_gmtoff;
181 }
182 #else
183 /* some systems do not have tm_gmtoff so we fake it */
184 t = mktime(&tm);
185 {
186 time_t dst = 0;
187 #if defined (_TIMEZONE)
188 #elif defined (_timezone)
189 #elif defined(_SQUID_AIX_)
190 #else
191 extern time_t timezone;
192 #endif
193 /*
194 * The following assumes a fixed DST offset of 1 hour,
195 * which is probably wrong.
196 */
197 if (tm.tm_isdst > 0)
198 dst = -3600;
199 #ifdef _timezone
200 t -= (_timezone + dst);
201 #else
202 t -= (timezone + dst);
203 #endif
204 }
205 #endif
206 return t;
207 }
208
209 const char *
210 mkrfc1123(time_t t)
211 {
212 static char buf[128];
213
214 struct tm *gmt = gmtime(&t);
215
216 buf[0] = '\0';
217 strftime(buf, 127, RFC1123_STRFTIME, gmt);
218 return buf;
219 }
220
221 const char *
222 mkhttpdlogtime(const time_t * t)
223 {
224 static char buf[128];
225
226 struct tm *gmt = gmtime(t);
227
228 #ifndef USE_GMT
229 int gmt_min, gmt_hour, gmt_yday, day_offset;
230 size_t len;
231 struct tm *lt;
232 int min_offset;
233
234 /* localtime & gmtime may use the same static data */
235 gmt_min = gmt->tm_min;
236 gmt_hour = gmt->tm_hour;
237 gmt_yday = gmt->tm_yday;
238
239 lt = localtime(t);
240
241 day_offset = lt->tm_yday - gmt_yday;
242 /* wrap round on end of year */
243 if (day_offset > 1)
244 day_offset = -1;
245 else if (day_offset < -1)
246 day_offset = 1;
247
248 min_offset = day_offset * 1440 + (lt->tm_hour - gmt_hour) * 60
249 + (lt->tm_min - gmt_min);
250
251 len = strftime(buf, 127 - 5, "%d/%b/%Y:%H:%M:%S ", lt);
252 snprintf(buf + len, 128 - len, "%+03d%02d",
253 (min_offset / 60) % 24,
254 min_offset % 60);
255 #else /* USE_GMT */
256 buf[0] = '\0';
257 strftime(buf, 127, "%d/%b/%Y:%H:%M:%S -000", gmt);
258 #endif /* USE_GMT */
259
260 return buf;
261 }
262
263 #if 0
264 int
265 main()
266 {
267 char *x;
268 time_t t, pt;
269
270 t = time(NULL);
271 x = mkrfc1123(t);
272 printf("HTTP Time: %s\n", x);
273
274 pt = parse_rfc1123(x);
275 printf("Parsed: %d vs. %d\n", pt, t);
276 }
277
278 #endif