--------------------- PatchSet 2558 Date: 2001/06/18 20:46:54 Author: serassio Branch: nt-2_3 Tag: (none) Log: Backport from 2.4 of a bug fix Members: lib/rfc1123.c:1.1.1.3.4.1.2.1->1.1.1.3.4.1.2.2 Index: squid/lib/rfc1123.c =================================================================== RCS file: /cvsroot/squid-sf//squid/lib/rfc1123.c,v retrieving revision 1.1.1.3.4.1.2.1 retrieving revision 1.1.1.3.4.1.2.2 diff -u -r1.1.1.3.4.1.2.1 -r1.1.1.3.4.1.2.2 --- squid/lib/rfc1123.c 6 Jan 2001 12:40:10 -0000 1.1.1.3.4.1.2.1 +++ squid/lib/rfc1123.c 18 Jun 2001 20:46:54 -0000 1.1.1.3.4.1.2.2 @@ -1,6 +1,6 @@ /* - * $Id: rfc1123.c,v 1.1.1.3.4.1.2.1 2001/01/06 12:40:10 hno Exp $ + * $Id: rfc1123.c,v 1.1.1.3.4.1.2.2 2001/06/18 20:46:54 serassio Exp $ * * DEBUG: * AUTHOR: Harvest Derived @@ -61,6 +61,7 @@ #if HAVE_SYS_TIME_H #include #endif +#include "assert.h" #include "util.h" #include "snprintf.h" @@ -68,6 +69,8 @@ #define RFC850_STRFTIME "%A, %d-%b-%y %H:%M:%S GMT" #define RFC1123_STRFTIME "%a, %d %b %Y %H:%M:%S GMT" +static const char *const w_space = " \t\r\n"; + static int make_month(const char *s); static int make_num(const char *s); @@ -103,85 +106,152 @@ return 0; } +static int +tmSaneValues(struct tm *tm) +{ + if (tm->tm_sec < 0 || tm->tm_sec > 59) + return 0; + if (tm->tm_min < 0 || tm->tm_min > 59) + return 0; + if (tm->tm_hour < 0 || tm->tm_hour > 23) + return 0; + if (tm->tm_mday < 1 || tm->tm_mday > 31) + return 0; + if (tm->tm_mon < 0 || tm->tm_mon > 11) + return 0; + if (tm->tm_year < 70 || tm->tm_year > 120) + return 0; + return 1; +} -time_t -parse_rfc1123(const char *str) +static struct tm * +parse_date1(const char *str) { + /* Thursday, 10-Jun-93 01:29:59 GMT */ + const char *s; + static struct tm tm; + assert(NULL != str); + memset(&tm, '\0', sizeof(struct tm)); + s = strchr(str, ','); + if (NULL == s) + return NULL; + while (*s == ' ') + s++; + /* backup if month is only one digit */ + if (xisdigit(*s) && !xisdigit(*(s + 1))) + s--; + if (!strchr(s, '-')) + return NULL; + if ((int) strlen(s) < 18) + return NULL; + memset(&tm, '\0', sizeof(tm)); + tm.tm_mday = make_num(s); + tm.tm_mon = make_month(s + 3); + tm.tm_year = make_num(s + 7); + /* + * Y2K: Arjan de Vet + * if tm.tm_year < 70, assume it's after the year 2000. + */ + if (tm.tm_year < 70) + tm.tm_year += 100; + tm.tm_hour = make_num(s + 10); + tm.tm_min = make_num(s + 13); + tm.tm_sec = make_num(s + 16); + return tmSaneValues(&tm) ? &tm : NULL; +} + +static struct tm * +parse_date2(const char *str) +{ + /* Thu, 10 Jan 1993 01:29:59 GMT */ const char *s; struct tm tm; - time_t t; + assert(NULL != str); + memset(&tm, '\0', sizeof(struct tm)); + s = strchr(str, ','); + if (NULL == s) + return NULL; + while (*s == ' ') + s++; + /* backup if month is only one digit */ + if (xisdigit(*s) && !xisdigit(*(s + 1))) + s--; + if (strchr(s, '-')) + return NULL; + if ((int) strlen(s) < 20) + return NULL; + memset(&tm, '\0', sizeof(tm)); + tm.tm_mday = make_num(s); + tm.tm_mon = make_month(s + 3); + tm.tm_year = (100 * make_num(s + 7) - 1900) + make_num(s + 9); + tm.tm_hour = make_num(s + 12); + tm.tm_min = make_num(s + 15); + tm.tm_sec = make_num(s + 18); + return tmSaneValues(&tm) ? &tm : NULL; +} - if (!str) - return -1; +static struct tm * +parse_date3(const char *str) +{ + /* Wed Jun 9 01:29:59 1993 GMT */ + static struct tm tm; + char *s; + static char buf[128]; + while (*str && *str == ' ') + str++; + xstrncpy(buf, str, 128); + if (NULL == (s = strtok(buf, w_space))) + return NULL; + if (NULL == (s = strtok(NULL, w_space))) + return NULL; + tm.tm_mon = make_month(s); + if (NULL == (s = strtok(NULL, w_space))) + return NULL; + tm.tm_mday = atoi(s); + if (NULL == (s = strtok(NULL, ":"))) + return NULL; + tm.tm_hour = atoi(s); + if (NULL == (s = strtok(NULL, ":"))) + return NULL; + tm.tm_min = atoi(s); + if (NULL == (s = strtok(NULL, w_space))) + return NULL; + tm.tm_sec = atoi(s); + if (NULL == (s = strtok(NULL, w_space))) + return NULL; + /* Y2K fix, richard.kettlewell@kewill.com */ + tm.tm_year = atoi(s) - 1900; + return tmSaneValues(&tm) ? &tm : NULL; +} - memset(&tm, '\0', sizeof(struct tm)); - if ((s = strchr(str, ','))) { /* Thursday, 10-Jun-93 01:29:59 GMT */ - s++; /* or: Thu, 10 Jan 1993 01:29:59 GMT */ - while (*s == ' ') - s++; - if (xisdigit(*s) && !xisdigit(*(s + 1))) /* backoff if only one digit */ - s--; - if (strchr(s, '-')) { /* First format */ - if ((int) strlen(s) < 18) - return -1; - tm.tm_mday = make_num(s); - tm.tm_mon = make_month(s + 3); - tm.tm_year = make_num(s + 7); - /* - * Y2K: Arjan de Vet - * if tm.tm_year < 70, assume it's after the year 2000. - */ - if (tm.tm_year < 70) - tm.tm_year += 100; - tm.tm_hour = make_num(s + 10); - tm.tm_min = make_num(s + 13); - tm.tm_sec = make_num(s + 16); - } else { /* Second format */ - if ((int) strlen(s) < 20) +time_t +parse_rfc1123(const char *str) +{ + struct tm *tm; + time_t t; + if (NULL == str) + return -1; + tm = parse_date1(str); + if (NULL == tm) { + tm = parse_date2(str); + if (NULL == tm) { + tm = parse_date3(str); + if (NULL == tm) return -1; - tm.tm_mday = make_num(s); - tm.tm_mon = make_month(s + 3); - tm.tm_year = (100 * make_num(s + 7) - 1900) + make_num(s + 9); - tm.tm_hour = make_num(s + 12); - tm.tm_min = make_num(s + 15); - tm.tm_sec = make_num(s + 18); - } - } else { /* Try the other format: */ - s = str; /* Wed Jun 9 01:29:59 1993 GMT */ - while (*s && *s == ' ') - s++; - if ((int) strlen(s) < 24) - return -1; - tm.tm_mday = make_num(s + 8); - tm.tm_mon = make_month(s + 4); - /* Y2K fix, richard.kettlewell@kewill.com */ - tm.tm_year = atoi(s + 20) - 1900; - tm.tm_hour = make_num(s + 11); - tm.tm_min = make_num(s + 14); - tm.tm_sec = make_num(s + 17); } - if (tm.tm_sec < 0 || tm.tm_sec > 59 || - tm.tm_min < 0 || tm.tm_min > 59 || - tm.tm_hour < 0 || tm.tm_hour > 23 || - tm.tm_mday < 1 || tm.tm_mday > 31 || - tm.tm_mon < 0 || tm.tm_mon > 11 || - tm.tm_year < 70 || tm.tm_year > 120) { - return -1; - } - tm.tm_isdst = -1; - + tm->tm_isdst = -1; #ifdef HAVE_TIMEGM - t = timegm(&tm); + t = timegm(tm); #elif HAVE_TM_GMTOFF - t = mktime(&tm); + t = mktime(tm); { struct tm *local = localtime(&t); t += local->tm_gmtoff; } #else /* some systems do not have tm_gmtoff so we fake it */ - t = mktime(&tm); + t = mktime(tm); { time_t dst = 0; #if defined (_TIMEZONE) @@ -194,7 +264,7 @@ * The following assumes a fixed DST offset of 1 hour, * which is probably wrong. */ - if (tm.tm_isdst > 0) + if (tm->tm_isdst > 0) dst = -3600; #ifdef _timezone t -= (_timezone + dst);