Index: lib/parsedate.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/parsedate.c,v
retrieving revision 1.28
diff -u -r1.28 parsedate.c
--- lib/parsedate.c	22 Jun 2008 06:57:00 -0000	1.28
+++ lib/parsedate.c	8 Sep 2008 11:16:16 -0000
@@ -221,6 +221,33 @@
   DATE_TIME
 };
 
+/* struct tm to time since epoch in GMT time zone */
+static time_t my_timegm(struct tm * tm)
+{
+  int month_days_cumulative [12] =
+    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+  int month, year, leap_days;
+
+  year = tm->tm_year + 1900;
+  month = tm->tm_mon;
+  if (month < 0) {
+    year += (11 - month) / 12;
+    month = 11 - (11 - month) % 12;
+  }
+  else if (month >= 12) {
+    year -= month / 12;
+    month = month % 12;
+  }
+
+  leap_days = year - (tm->tm_mon <= 1);
+  leap_days = ((leap_days / 4) - (leap_days / 100) + (leap_days / 400)
+               - (1969 / 4) + (1969 / 100) - (1969 / 400));
+
+  return ((((time_t) (year - 1970) * 365
+            + leap_days + month_days_cumulative [month] + tm->tm_mday - 1) * 24
+           + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec;
+}
+
 static time_t parsedate(const char *date)
 {
   time_t t = 0;
@@ -246,7 +273,8 @@
       /* a name coming up */
       char buf[32]="";
       size_t len;
-      sscanf(date, "%31[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]", buf);
+      sscanf(date, "%31[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]",
+             buf);
       len = strlen(buf);
 
       if(wdaynum == -1) {
@@ -373,45 +401,20 @@
   tm.tm_yday = 0;
   tm.tm_isdst = 0;
 
-  /* mktime() returns a time_t. time_t is often 32 bits, even on many
+  /* my_timegm() returns a time_t. time_t is often 32 bits, even on many
      architectures that feature 64 bit 'long'.
 
      Some systems have 64 bit time_t and deal with years beyond 2038. However,
-     even some of the systems with 64 bit time_t returns -1 for dates beyond
-     03:14:07 UTC, January 19, 2038. (Such as AIX 5100-06)
+     even on some of the systems with 64 bit time_t mktime() returns -1 for
+     dates beyond 03:14:07 UTC, January 19, 2038. (Such as AIX 5100-06)
   */
-  t = mktime(&tm);
+  t = my_timegm(&tm);
 
   /* time zone adjust (cast t to int to compare to negative one) */
   if(-1 != (int)t) {
-    struct tm *gmt;
-    long delta;
-    time_t t2;
-
-#ifdef HAVE_GMTIME_R
-    /* thread-safe version */
-    struct tm keeptime2;
-    gmt = (struct tm *)gmtime_r(&t, &keeptime2);
-    if(!gmt)
-      return -1; /* illegal date/time */
-    t2 = mktime(gmt);
-#else
-    /* It seems that at least the MSVC version of mktime() doesn't work
-       properly if it gets the 'gmt' pointer passed in (which is a pointer
-       returned from gmtime() pointing to static memory), so instead we copy
-       the tm struct to a local struct and pass a pointer to that struct as
-       input to mktime(). */
-    struct tm gmt2;
-    gmt = gmtime(&t); /* use gmtime_r() if available */
-    if(!gmt)
-      return -1; /* illegal date/time */
-    gmt2 = *gmt;
-    t2 = mktime(&gmt2);
-#endif
 
-    /* Add the time zone diff (between the given timezone and GMT) and the
-       diff between the local time zone and GMT. */
-    delta = (long)((tzoff!=-1?tzoff:0) + (t - t2));
+    /* Add the time zone diff between local time zone and GMT. */
+    long delta = (long)(tzoff!=-1?tzoff:0);
 
     if((delta>0) && (t + delta < t))
       return -1; /* time_t overflow */
