]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
DW:
authorwessels <>
Wed, 8 Nov 2000 06:37:35 +0000 (06:37 +0000)
committerwessels <>
Wed, 8 Nov 2000 06:37:35 +0000 (06:37 +0000)
 - Changes prompted by bug report that "Wed Aug 9 11:36:06 2000" could
   not be parsed.  The parse_rfc1123() code assumed there was an extra
   space after Aug and before "9".

   This change breaks the parsing into smaller functions to make the
   code easier to read and understand.

   I changed parsing of the "third" date format (asctime()) to use
   a buffer copy and strtok.  This makes it more flexible.  For example,
   we don't have to require strlen(s) < 24.

lib/rfc1123.c

index f63eb6bbb15b0f3a32e2d2b51ad8e7b70f97dad1..f43c25dee6ae6f7cacb35c974c6c9d4e5f3d3016 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: rfc1123.c,v 1.25 2000/10/20 23:50:59 hno Exp $
+ * $Id: rfc1123.c,v 1.26 2000/11/07 23:37:35 wessels Exp $
  *
  * DEBUG: 
  * AUTHOR: Harvest Derived
@@ -61,6 +61,7 @@
 #if HAVE_SYS_TIME_H
 #include <sys/time.h>
 #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 @@ make_month(const char *s)
     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 <Arjan.deVet@adv.IAEhv.nl>
+     * 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 <Arjan.deVet@adv.IAEhv.nl>
-            * 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)
@@ -195,7 +265,7 @@ parse_rfc1123(const char *str)
         * 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;
 #if defined ( _timezone) || defined(_SQUID_CYGWIN_)
        t -= (_timezone + dst);