Hi,

I'm answering to myself in order to submit an updated version of my
patch, fixing the original distance bug, but also adding support for
another space+one-digit day format (for the two-digit year formats).

Some code style fixes are also included in this patch. If you don't like
the mix of bug fixing, enhancements and code style fixes, I can split
this patch into several patches to clarify all this stuff.

Comments and reviews are, of course, very welcome. I hope this patch can
be part of the just-released apr-util.

Regards,
- Sam

-- 
Maxime Petazzoni (http://www.bulix.org)
 -- gone crazy, back soon. leave message.
Index: test/Makefile.in
===================================================================
--- test/Makefile.in    (revision 233337)
+++ test/Makefile.in    (working copy)
@@ -2,7 +2,7 @@
 
 INCLUDES = @APRUTIL_PRIV_INCLUDES@ @APR_INCLUDES@ @APRUTIL_INCLUDES@
 
-PROGRAMS = testall testdbm testdate testxml testrmm \
+PROGRAMS = testall testdbm testdate testdaterfc testxml testrmm \
           testreslist testqueue testxlate dbd
 TARGETS = $(PROGRAMS)
 
@@ -48,6 +48,11 @@
 testdate: $(testdate_OBJECTS) $(testdate_LDADD)
        $(LINK) $(APRUTIL_LDFLAGS) $(testdate_OBJECTS) $(testdate_LDADD) 
$(PROGRAM_DEPENDENCIES)
 
+testdaterfc_OBJECTS = testdaterfc.lo
+testdaterfc_LDADD =  $(TARGET_LIB_PATH)
+testdaterfc: $(testdaterfc_OBJECTS) $(testdaterfc_LDADD)
+       $(LINK) $(APRUTIL_LDFLAGS) $(testdaterfc_OBJECTS) $(testdaterfc_LDADD) 
$(PROGRAM_DEPENDENCIES)
+
 testxml_OBJECTS = testxml.lo
 testxml_LDADD =  $(TARGET_LIB_PATH)
 testxml: $(testxml_OBJECTS) $(testxml_LDADD)
Index: test/testdaterfc.c
===================================================================
--- test/testdaterfc.c  (revision 0)
+++ test/testdaterfc.c  (revision 0)
@@ -0,0 +1,58 @@
+/** testdaterfc.c: an apr_date_parse_rfc() function tester.
+ *
+ * Compile with the following line :
+ * gcc -I${prefix}/include/apr -g -O2 -Wall       \
+ *   testdaterfc.c -o testdaterfc                 \
+ *   `${prefix}/bin/apr-config --includes --libs  \
+ *     --cflags --ldflags --cppflags --link-ld`   \
+ *   `${prefix}/bin/apu-config --includes --libs  \
+ *     --link-ld`
+ *
+ * Run with :
+ * LD_LIBRARY_PATH=${prefix}/lib ./testdaterfc
+ *
+ * Maxime Petazzoni, August 2005
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "apr_date.h"
+
+/* Data samples. This is a good sample of what I've seen this
+   far. Feel free to add cases here. */
+char *data[] = {
+  "Mon, 27 Feb 1995 20:49:44 -0800",
+  "Fri,  1 Jul 2005 11:34:25 -0400",
+  "Monday, 27-Feb-95 20:49:44 -0800",
+  "Tue, 4 Mar 1997 12:43:52 +0200",
+  "Mon, 27 Feb 95 20:49:44 -0800",
+  "Tue,  4 Mar 97 12:43:52 +0200",
+  "Tue, 4 Mar 97 12:43:52 +0200",
+  "Mon, 27 Feb 95 20:49 GMT",
+  "Tue, 4 Mar 97 12:43 GMT",
+  NULL };
+
+int main(int argc, char **argv)
+{
+    apr_time_t date;
+    char *str_date;
+    int i = 0;
+
+    while (data[i]) {
+        /* Parse date string into an apr_time_t */
+        date = apr_date_parse_rfc(data[i]);
+
+        /* Fetch back and RFC 822 formatted date string */
+        str_date = calloc(APR_RFC822_DATE_LEN, sizeof(char));
+        apr_rfc822_date(str_date, date);
+
+        /* Print all relevant material */
+        printf("%s %"APR_OFF_T_FMT" %s\n", str_date, date, data[i]);
+       free(str_date);
+
+        i++;
+    }
+
+    return 0;
+}
Index: misc/apr_date.c
===================================================================
--- misc/apr_date.c     (revision 233337)
+++ misc/apr_date.c     (working copy)
@@ -335,21 +335,22 @@
         return APR_DATE_BAD;
 
     /* Not all dates have text months at the beginning. */
-    if (!apr_isdigit(date[0]))
-    {
+    if (!apr_isdigit(date[0])) {
         while (*date && apr_isspace(*date)) /* Find first non-whitespace char 
*/
             ++date;
 
-        if (*date == '\0') 
+        if (*date == '\0')
             return APR_DATE_BAD;
 
         if ((date = strchr(date, ' ')) == NULL)   /* Find space after weekday 
*/
             return APR_DATE_BAD;
 
-        ++date;    /* Now pointing to first char after space, which should be 
*/    }
+        ++date;
+    }
 
     /* start of the actual date information for all 11 formats. */
-    if (apr_date_checkmask(date, "## @$$ #### ##:##:## *")) {   /* RFC 1123 
format */
+    if (apr_date_checkmask(date, "## @$$ #### ##:##:## *")) {
+        /* RFC 1123 format */
         ds.tm_year = ((date[7] - '0') * 10 + (date[8] - '0') - 19) * 100;
 
         if (ds.tm_year < 0)
@@ -361,11 +362,12 @@
 
         monstr = date + 3;
         timstr = date + 12;
-        gmtstr = date + 20;
+        gmtstr = date + 21;
 
         TIMEPARSE_STD(ds, timstr);
     }
-    else if (apr_date_checkmask(date, "[EMAIL PROTECTED] ##:##:## *")) {/* RFC 
850 format  */
+    else if (apr_date_checkmask(date, "[EMAIL PROTECTED] ##:##:## *")) {
+        /* RFC 850 format */
         ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0');
 
         if (ds.tm_year < 70)
@@ -382,7 +384,7 @@
     else if (apr_date_checkmask(date, "@$$ ~# ##:##:## ####*")) {
         /* asctime format */
         ds.tm_year = ((date[16] - '0') * 10 + (date[17] - '0') - 19) * 100;
-        if (ds.tm_year < 0) 
+        if (ds.tm_year < 0)
             return APR_DATE_BAD;
 
         ds.tm_year += ((date[18] - '0') * 10) + (date[19] - '0');
@@ -418,7 +420,9 @@
     }
     else if (apr_date_checkmask(date, "## @$$ ## ##:##:## *")) {
         /* This is the old RFC 1123 date format - many many years ago, people
-         * used two-digit years.  Oh, how foolish.  */
+         * used two-digit years.  Oh, how foolish.
+         *
+         * Two-digit day, two-digit year version. */
         ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0');
 
         if (ds.tm_year < 70)
@@ -431,10 +435,30 @@
         gmtstr = date + 19;
 
         TIMEPARSE_STD(ds, timstr);
-    } 
+    }
+    else if (apr_date_checkmask(date, " # @$$ ## ##:##:## *")) {
+        /* This is the old RFC 1123 date format - many many years ago, people
+         * used two-digit years.  Oh, how foolish.
+         *
+         * Space + one-digit day, two-digit year version.*/
+        ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0');
+
+        if (ds.tm_year < 70)
+            ds.tm_year += 100;
+
+        ds.tm_mday = (date[1] - '0');
+
+        monstr = date + 3;
+        timstr = date + 10;
+        gmtstr = date + 19;
+
+        TIMEPARSE_STD(ds, timstr);
+    }
     else if (apr_date_checkmask(date, "# @$$ ## ##:##:## *")) {
         /* This is the old RFC 1123 date format - many many years ago, people
-         * used two-digit years.  Oh, how foolish.  */
+         * used two-digit years.  Oh, how foolish.
+         *
+         * One-digit day, two-digit year version. */
         ds.tm_year = ((date[6] - '0') * 10) + (date[7] - '0');
 
         if (ds.tm_year < 70)
@@ -447,7 +471,7 @@
         gmtstr = date + 18;
 
         TIMEPARSE_STD(ds, timstr);
-    } 
+    }
     else if (apr_date_checkmask(date, "## @$$ ## ##:## *")) {
         /* Loser format.  This is quite bogus.  */
         ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0');
@@ -462,7 +486,7 @@
         gmtstr = NULL;
 
         TIMEPARSE(ds, timstr[0],timstr[1], timstr[3],timstr[4], '0','0');
-    } 
+    }
     else if (apr_date_checkmask(date, "# @$$ ## ##:## *")) {
         /* Loser format.  This is quite bogus.  */
         ds.tm_year = ((date[6] - '0') * 10) + (date[7] - '0');
@@ -494,7 +518,7 @@
         TIMEPARSE(ds, '0',timstr[1], timstr[3],timstr[4], timstr[6],timstr[7]);
     }
     else if (apr_date_checkmask(date, "# @$$ ## #:##:## *")) {
-         /* Loser format.  This is quite bogus.  */
+        /* Loser format.  This is quite bogus.  */
         ds.tm_year = ((date[6] - '0') * 10) + (date[7] - '0');
 
         if (ds.tm_year < 70)
@@ -508,7 +532,7 @@
 
         TIMEPARSE(ds, '0',timstr[1], timstr[3],timstr[4], timstr[6],timstr[7]);
     }
-    else if (apr_date_checkmask(date, " # @$$ #### ##:##:## *")) {   
+    else if (apr_date_checkmask(date, " # @$$ #### ##:##:## *")) {
         /* RFC 1123 format with a space instead of a leading zero. */
         ds.tm_year = ((date[7] - '0') * 10 + (date[8] - '0') - 19) * 100;
 
@@ -521,7 +545,7 @@
 
         monstr = date + 3;
         timstr = date + 12;
-        gmtstr = date + 20;
+        gmtstr = date + 21;
 
         TIMEPARSE_STD(ds, timstr);
     }
@@ -549,7 +573,7 @@
     if (ds.tm_mday <= 0 || ds.tm_mday > 31)
         return APR_DATE_BAD;
 
-    if ((ds.tm_hour > 23) || (ds.tm_min > 59) || (ds.tm_sec > 61)) 
+    if ((ds.tm_hour > 23) || (ds.tm_min > 59) || (ds.tm_sec > 61))
         return APR_DATE_BAD;
 
     mint = (monstr[0] << 16) | (monstr[1] << 8) | monstr[2];
@@ -583,34 +607,33 @@
      * If there is any confusion, tm_gmtoff will remain 0.
      */
     ds.tm_gmtoff = 0;
-    if (gmtstr && *gmtstr != '\0') {
-        /* Do we have a GMT? */
-        if (*(++gmtstr) != '\0') {
-            int offset;
-            switch (*(gmtstr++)) {
-            case '-':
-                offset = atoi(gmtstr);
-                ds.tm_gmtoff -= (offset / 100) * 60 * 60;
-                ds.tm_gmtoff -= (offset % 100) * 60;
-                break;
-            case '+':
-                offset = atoi(gmtstr);
-                ds.tm_gmtoff += (offset / 100) * 60 * 60;
-                ds.tm_gmtoff += (offset % 100) * 60;
-                break;
-            }
+
+    /* Do we have a timezone ? */
+    if (gmtstr) {
+        int offset;
+        switch (*gmtstr) {
+        case '-':
+            offset = atoi(gmtstr+1);
+            ds.tm_gmtoff -= (offset / 100) * 60 * 60;
+            ds.tm_gmtoff -= (offset % 100) * 60;
+            break;
+        case '+':
+            offset = atoi(gmtstr+1);
+            ds.tm_gmtoff += (offset / 100) * 60 * 60;
+            ds.tm_gmtoff += (offset % 100) * 60;
+            break;
         }
     }
 
-    /* apr_time_exp_get uses tm_usec field, but it hasn't been set yet. 
+    /* apr_time_exp_get uses tm_usec field, but it hasn't been set yet.
      * It should be safe to just zero out this value.
      * tm_usec is the number of microseconds into the second.  HTTP only
      * cares about second granularity.
      */
     ds.tm_usec = 0;
 
-    if (apr_time_exp_gmt_get(&result, &ds) != APR_SUCCESS) 
+    if (apr_time_exp_gmt_get(&result, &ds) != APR_SUCCESS)
         return APR_DATE_BAD;
-    
+
     return result;
 }

Attachment: signature.asc
Description: Digital signature

Reply via email to