]>
Commit | Line | Data |
---|---|---|
164f7660 | 1 | |
cf49df4b | 2 | /* |
262a0e14 | 3 | * $Id$ |
cf49df4b | 4 | * |
26ac0430 | 5 | * DEBUG: |
cf49df4b | 6 | * AUTHOR: Harvest Derived |
7 | * | |
2b6662ba | 8 | * SQUID Web Proxy Cache http://www.squid-cache.org/ |
e25c139f | 9 | * ---------------------------------------------------------- |
cf49df4b | 10 | * |
2b6662ba | 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. | |
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. | |
26ac0430 | 24 | * |
cf49df4b | 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. | |
26ac0430 | 29 | * |
cf49df4b | 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" |
66 | ||
2a8a7464 | 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 | ||
f5b8bbc4 | 70 | static int make_month(const char *s); |
71 | static int make_num(const char *s); | |
cf49df4b | 72 | |
26ac0430 | 73 | static const char *month_names[12] = { |
cf49df4b | 74 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", |
75 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" | |
76 | }; | |
77 | ||
78 | ||
79 | static int | |
0ee4272b | 80 | make_num(const char *s) |
cf49df4b | 81 | { |
82 | if (*s >= '0' && *s <= '9') | |
26ac0430 | 83 | return 10 * (*s - '0') + *(s + 1) - '0'; |
cf49df4b | 84 | else |
26ac0430 | 85 | return *(s + 1) - '0'; |
cf49df4b | 86 | } |
87 | ||
88 | static int | |
0ee4272b | 89 | make_month(const char *s) |
cf49df4b | 90 | { |
91 | int i; | |
0ee4272b | 92 | char month[3]; |
cf49df4b | 93 | |
b6a2f15e | 94 | month[0] = xtoupper(*s); |
95 | month[1] = xtolower(*(s + 1)); | |
96 | month[2] = xtolower(*(s + 2)); | |
cf49df4b | 97 | |
98 | for (i = 0; i < 12; i++) | |
26ac0430 AJ |
99 | if (!strncmp(month_names[i], month, 3)) |
100 | return i; | |
506f9cfe | 101 | return -1; |
cf49df4b | 102 | } |
103 | ||
2b79de37 | 104 | static int |
105 | tmSaneValues(struct tm *tm) | |
106 | { | |
107 | if (tm->tm_sec < 0 || tm->tm_sec > 59) | |
26ac0430 | 108 | return 0; |
2b79de37 | 109 | if (tm->tm_min < 0 || tm->tm_min > 59) |
26ac0430 | 110 | return 0; |
2b79de37 | 111 | if (tm->tm_hour < 0 || tm->tm_hour > 23) |
26ac0430 | 112 | return 0; |
2b79de37 | 113 | if (tm->tm_mday < 1 || tm->tm_mday > 31) |
26ac0430 | 114 | return 0; |
2b79de37 | 115 | if (tm->tm_mon < 0 || tm->tm_mon > 11) |
26ac0430 | 116 | return 0; |
737e901b | 117 | return 1; |
2b79de37 | 118 | } |
cf49df4b | 119 | |
2b79de37 | 120 | static struct tm * |
e1381638 AJ |
121 | parse_date_elements(const char *day, const char *month, const char *year, |
122 | const char *time, const char *zone) { | |
2b79de37 | 123 | static struct tm tm; |
506f9cfe | 124 | char *t; |
125 | memset(&tm, 0, sizeof(tm)); | |
2b79de37 | 126 | |
506f9cfe | 127 | if (!day || !month || !year || !time) |
26ac0430 | 128 | return NULL; |
506f9cfe | 129 | tm.tm_mday = atoi(day); |
130 | tm.tm_mon = make_month(month); | |
131 | if (tm.tm_mon < 0) | |
26ac0430 | 132 | return NULL; |
506f9cfe | 133 | tm.tm_year = atoi(year); |
134 | if (strlen(year) == 4) | |
26ac0430 | 135 | tm.tm_year -= 1900; |
506f9cfe | 136 | else if (tm.tm_year < 70) |
26ac0430 | 137 | tm.tm_year += 100; |
506f9cfe | 138 | else if (tm.tm_year > 19000) |
26ac0430 | 139 | tm.tm_year -= 19000; |
506f9cfe | 140 | tm.tm_hour = make_num(time); |
141 | t = strchr(time, ':'); | |
142 | if (!t) | |
26ac0430 | 143 | return NULL; |
506f9cfe | 144 | t++; |
145 | tm.tm_min = atoi(t); | |
146 | t = strchr(t, ':'); | |
147 | if (t) | |
26ac0430 | 148 | tm.tm_sec = atoi(t + 1); |
2b79de37 | 149 | return tmSaneValues(&tm) ? &tm : NULL; |
150 | } | |
cf49df4b | 151 | |
2b79de37 | 152 | static struct tm * |
e1381638 | 153 | parse_date(const char *str) { |
506f9cfe | 154 | struct tm *tm; |
a69938ae | 155 | static char tmp[64]; |
506f9cfe | 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 | ||
a69938ae | 164 | xstrncpy(tmp, str, 64); |
165 | ||
506f9cfe | 166 | for (t = strtok(tmp, ", "); t; t = strtok(NULL, ", ")) { |
26ac0430 AJ |
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; | |
506f9cfe | 190 | } |
191 | tm = parse_date_elements(day, month, year, time, zone); | |
192 | ||
506f9cfe | 193 | return tm; |
2b79de37 | 194 | } |
cf49df4b | 195 | |
2b79de37 | 196 | time_t |
197 | parse_rfc1123(const char *str) | |
198 | { | |
199 | struct tm *tm; | |
200 | time_t t; | |
201 | if (NULL == str) | |
26ac0430 | 202 | return -1; |
506f9cfe | 203 | tm = parse_date(str); |
204 | if (!tm) | |
26ac0430 | 205 | return -1; |
2b79de37 | 206 | tm->tm_isdst = -1; |
cf49df4b | 207 | #ifdef HAVE_TIMEGM |
2b79de37 | 208 | t = timegm(tm); |
6a9f6389 | 209 | #elif HAVE_TM_TM_GMTOFF |
2b79de37 | 210 | t = mktime(tm); |
737e901b | 211 | if (t != -1) { |
26ac0430 AJ |
212 | struct tm *local = localtime(&t); |
213 | t += local->tm_gmtoff; | |
cf49df4b | 214 | } |
215 | #else | |
216 | /* some systems do not have tm_gmtoff so we fake it */ | |
2b79de37 | 217 | t = mktime(tm); |
737e901b | 218 | if (t != -1) { |
26ac0430 | 219 | time_t dst = 0; |
44965270 | 220 | #if defined (_TIMEZONE) |
221 | #elif defined (_timezone) | |
222 | #elif defined(_SQUID_AIX_) | |
b05490a8 | 223 | #elif defined(_SQUID_CYGWIN_) |
0ef0f1de | 224 | #elif defined(_SQUID_MSWIN_) |
c83a7446 | 225 | #elif defined(_SQUID_SGI_) |
44965270 | 226 | #else |
e1381638 | 227 | extern long timezone; |
9b6dbb2a | 228 | #endif |
26ac0430 AJ |
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; | |
ec4daaa5 | 235 | #if defined ( _timezone) || defined(_SQUID_WIN32_) |
26ac0430 | 236 | t -= (_timezone + dst); |
9b6dbb2a | 237 | #else |
e1381638 | 238 | t -= (timezone + dst); |
9b6dbb2a | 239 | #endif |
cf49df4b | 240 | } |
241 | #endif | |
242 | return t; | |
243 | } | |
244 | ||
0ee4272b | 245 | const char * |
cf49df4b | 246 | mkrfc1123(time_t t) |
247 | { | |
248 | static char buf[128]; | |
249 | ||
250 | struct tm *gmt = gmtime(&t); | |
251 | ||
252 | buf[0] = '\0'; | |
2a8a7464 | 253 | strftime(buf, 127, RFC1123_STRFTIME, gmt); |
cf49df4b | 254 | return buf; |
255 | } | |
256 | ||
0ee4272b | 257 | const char * |
38cac3c8 | 258 | mkhttpdlogtime(const time_t * t) |
cf49df4b | 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); | |
cf49df4b | 276 | |
c308daa0 | 277 | day_offset = lt->tm_yday - gmt_yday; |
cf49df4b | 278 | /* wrap round on end of year */ |
279 | if (day_offset > 1) | |
26ac0430 | 280 | day_offset = -1; |
cf49df4b | 281 | else if (day_offset < -1) |
26ac0430 | 282 | day_offset = 1; |
cf49df4b | 283 | |
c308daa0 | 284 | min_offset = day_offset * 1440 + (lt->tm_hour - gmt_hour) * 60 |
26ac0430 | 285 | + (lt->tm_min - gmt_min); |
c308daa0 | 286 | |
cf49df4b | 287 | len = strftime(buf, 127 - 5, "%d/%b/%Y:%H:%M:%S ", lt); |
0e473d70 | 288 | snprintf(buf + len, 128 - len, "%+03d%02d", |
26ac0430 AJ |
289 | (min_offset / 60) % 24, |
290 | min_offset % 60); | |
cf49df4b | 291 | #else /* USE_GMT */ |
292 | buf[0] = '\0'; | |
2a8a7464 | 293 | strftime(buf, 127, "%d/%b/%Y:%H:%M:%S -000", gmt); |
cf49df4b | 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 |