]> git.ipfire.org Git - thirdparty/squid.git/blame - lib/rfc1123.c
SourceFormat: enforcement
[thirdparty/squid.git] / lib / rfc1123.c
CommitLineData
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 70static int make_month(const char *s);
71static int make_num(const char *s);
cf49df4b 72
26ac0430 73static const char *month_names[12] = {
cf49df4b 74 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
75 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
76};
77
78
79static int
0ee4272b 80make_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
88static int
0ee4272b 89make_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 104static int
105tmSaneValues(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 120static struct tm *
e1381638
AJ
121parse_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 152static struct tm *
e1381638 153parse_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 196time_t
197parse_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 245const char *
cf49df4b 246mkrfc1123(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 257const char *
38cac3c8 258mkhttpdlogtime(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
300int
301main()
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