Commit d369a2b7 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

- Introducing Jamie Lokier's function for date to epoch conversion used in the

  date parser function. This makes our function less dependent on system-
  provided functions and instead we do all the magic ourselves. We also no
  longer depend on the TZ environment variable.
parent a5f4cfc6
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -7,6 +7,25 @@
                                  Changelog

Daniel Stenberg (23 Sep 2008)
- Introducing Jamie Lokier's function for date to epoch conversion used in the
  date parser function. This makes our function less dependent on system-
  provided functions and instead we do all the magic ourselves. We also no
  longer depend on the TZ environment variable. Switching to our own converter
  has some side-effect and they are noted here for future reference (taken
  from a mail by mr Lokier):

  time_t is not measured in seconds in the ANSI C standard - or even counted
  uniformly - weird platforms can use other numeric representations of dates
  in time_t - hence the difftime() function.

  On POSIX time_t is measured in UTC seconds, which means not including leap
  seconds.  But it's mentioned in a few places that some old POSIX-ish
  environments include leap seconds in their time_t counts...

  I'm pretty sure [the new implementation is] correct on anything truly POSIX.
  And it's obviously a lot less dependent on platform quirks and corner cases
  in many ways than the mktime() version.

- Rob Crittenden brought a patch to "add some locking for thread-safety to NSS
  implementation".

+3 −1
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ This release includes the following bugfixes:
 o recv() failures cause CURLE_RECV_ERROR
 o SFTP over SOCKS crash fixed
 o thread-safety issues addressed for NSS-powered libcurls
 o removed the use of mktime() and gmtime(_r)() in date parsing and conversions

This release includes the following known bugs:

@@ -40,6 +41,7 @@ advice from friends like these:

 Keith Mok, Yang Tse, Daniel Fandrich, Guenter Knauf, Dmitriy Sergeyev,
 Linus Nielsen Feltzing, Martin Drasar, Stefan Krause, Dmitry Kurochkin,
 Mike Revi, Andres Garcia, Michael Goffioul, Markus Moeller, Rob Crittenden
 Mike Revi, Andres Garcia, Michael Goffioul, Markus Moeller, Rob Crittenden,
 Jamie Lokier

        Thanks! (and sorry if I forgot to mention someone)
+40 −32
Original line number Diff line number Diff line
@@ -222,6 +222,38 @@ enum assume {
  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;

  if(tm->tm_year < 70)
    /* we don't support years before 1970 as they will cause this function
       to return a negative value */
    return -1;

  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;
@@ -247,7 +279,8 @@ static time_t parsedate(const char *date)
      /* 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) {
@@ -374,45 +407,20 @@ static time_t parsedate(const char *date)
  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 */
+0 −1
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ curl_getdate() testing
# using one of the 'right' zones that take into account leap seconds
# which causes the cookie expiry times to be different.
<setenv>
TZ=GMT
</setenv>
 <command>
nothing