]>
Commit | Line | Data |
---|---|---|
164f7660 | 1 | |
cf49df4b | 2 | /* |
b6a2f15e | 3 | * $Id: rfc1123.c,v 1.23 1999/04/15 06:15:38 wessels Exp $ |
cf49df4b | 4 | * |
5 | * DEBUG: | |
6 | * AUTHOR: Harvest Derived | |
7 | * | |
42c04c16 | 8 | * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ |
e25c139f | 9 | * ---------------------------------------------------------- |
cf49df4b | 10 | * |
11 | * Squid is the result of efforts by numerous individuals from the | |
12 | * Internet community. Development is led by Duane Wessels of the | |
e25c139f | 13 | * National Laboratory for Applied Network Research and funded by the |
14 | * National Science Foundation. Squid is Copyrighted (C) 1998 by | |
15 | * Duane Wessels and the University of California San Diego. Please | |
16 | * see the COPYRIGHT file for full details. Squid incorporates | |
17 | * software developed and/or copyrighted by other sources. Please see | |
18 | * the CREDITS file for full details. | |
cf49df4b | 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 | |
cbdec147 | 32 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
e25c139f | 33 | * |
cf49df4b | 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 | |
c68e9c6b | 46 | #if HAVE_STDLIB_H |
47 | #include <stdlib.h> | |
48 | #endif | |
cf49df4b | 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 | ||
cf49df4b | 65 | #include "util.h" |
5e2e108b | 66 | #include "snprintf.h" |
cf49df4b | 67 | |
2a8a7464 | 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 | ||
f5b8bbc4 | 71 | static int make_month(const char *s); |
72 | static int make_num(const char *s); | |
cf49df4b | 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 | |
0ee4272b | 82 | make_num(const char *s) |
cf49df4b | 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 | |
0ee4272b | 91 | make_month(const char *s) |
cf49df4b | 92 | { |
93 | int i; | |
0ee4272b | 94 | char month[3]; |
cf49df4b | 95 | |
b6a2f15e | 96 | month[0] = xtoupper(*s); |
97 | month[1] = xtolower(*(s + 1)); | |
98 | month[2] = xtolower(*(s + 2)); | |
cf49df4b | 99 | |
100 | for (i = 0; i < 12; i++) | |
0ee4272b | 101 | if (!strncmp(month_names[i], month, 3)) |
cf49df4b | 102 | return i; |
103 | return 0; | |
104 | } | |
105 | ||
106 | ||
107 | time_t | |
0ee4272b | 108 | parse_rfc1123(const char *str) |
cf49df4b | 109 | { |
0ee4272b | 110 | const char *s; |
cf49df4b | 111 | struct tm tm; |
112 | time_t t; | |
113 | ||
114 | if (!str) | |
115 | return -1; | |
116 | ||
7446ea01 | 117 | memset(&tm, '\0', sizeof(struct tm)); |
cf49df4b | 118 | if ((s = strchr(str, ','))) { /* Thursday, 10-Jun-93 01:29:59 GMT */ |
119 | s++; /* or: Thu, 10 Jan 1993 01:29:59 GMT */ | |
14227516 | 120 | while (*s == ' ') |
cf49df4b | 121 | s++; |
b6a2f15e | 122 | if (xisdigit(*s) && !xisdigit(*(s + 1))) /* backoff if only one digit */ |
14227516 | 123 | s--; |
cf49df4b | 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); | |
72367f90 | 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; | |
cf49df4b | 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); | |
c68e9c6b | 158 | /* Y2K fix, richard.kettlewell@kewill.com */ |
159 | tm.tm_year = atoi(s + 20) - 1900; | |
cf49df4b | 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 | { | |
f2d03c5f | 179 | struct tm *local = localtime(&t); |
cf49df4b | 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; | |
44965270 | 187 | #if defined (_TIMEZONE) |
188 | #elif defined (_timezone) | |
189 | #elif defined(_SQUID_AIX_) | |
190 | #else | |
cf49df4b | 191 | extern time_t timezone; |
9b6dbb2a | 192 | #endif |
cf49df4b | 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; | |
9b6dbb2a | 199 | #ifdef _timezone |
200 | t -= (_timezone + dst); | |
201 | #else | |
cf49df4b | 202 | t -= (timezone + dst); |
9b6dbb2a | 203 | #endif |
cf49df4b | 204 | } |
205 | #endif | |
206 | return t; | |
207 | } | |
208 | ||
0ee4272b | 209 | const char * |
cf49df4b | 210 | mkrfc1123(time_t t) |
211 | { | |
212 | static char buf[128]; | |
213 | ||
214 | struct tm *gmt = gmtime(&t); | |
215 | ||
216 | buf[0] = '\0'; | |
2a8a7464 | 217 | strftime(buf, 127, RFC1123_STRFTIME, gmt); |
cf49df4b | 218 | return buf; |
219 | } | |
220 | ||
0ee4272b | 221 | const char * |
38cac3c8 | 222 | mkhttpdlogtime(const time_t * t) |
cf49df4b | 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); | |
cf49df4b | 240 | |
c308daa0 | 241 | day_offset = lt->tm_yday - gmt_yday; |
cf49df4b | 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 | ||
c308daa0 | 248 | min_offset = day_offset * 1440 + (lt->tm_hour - gmt_hour) * 60 |
249 | + (lt->tm_min - gmt_min); | |
250 | ||
cf49df4b | 251 | len = strftime(buf, 127 - 5, "%d/%b/%Y:%H:%M:%S ", lt); |
0e473d70 | 252 | snprintf(buf + len, 128 - len, "%+03d%02d", |
cf49df4b | 253 | (min_offset / 60) % 24, |
254 | min_offset % 60); | |
255 | #else /* USE_GMT */ | |
256 | buf[0] = '\0'; | |
2a8a7464 | 257 | strftime(buf, 127, "%d/%b/%Y:%H:%M:%S -000", gmt); |
cf49df4b | 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 |