- 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.
This commit is contained in:
19
CHANGES
19
CHANGES
@@ -7,6 +7,25 @@
|
|||||||
Changelog
|
Changelog
|
||||||
|
|
||||||
Daniel Stenberg (23 Sep 2008)
|
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
|
- Rob Crittenden brought a patch to "add some locking for thread-safety to NSS
|
||||||
implementation".
|
implementation".
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ This release includes the following bugfixes:
|
|||||||
o recv() failures cause CURLE_RECV_ERROR
|
o recv() failures cause CURLE_RECV_ERROR
|
||||||
o SFTP over SOCKS crash fixed
|
o SFTP over SOCKS crash fixed
|
||||||
o thread-safety issues addressed for NSS-powered libcurls
|
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:
|
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,
|
Keith Mok, Yang Tse, Daniel Fandrich, Guenter Knauf, Dmitriy Sergeyev,
|
||||||
Linus Nielsen Feltzing, Martin Drasar, Stefan Krause, Dmitry Kurochkin,
|
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)
|
Thanks! (and sorry if I forgot to mention someone)
|
||||||
|
|||||||
@@ -222,6 +222,38 @@ enum assume {
|
|||||||
DATE_TIME
|
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)
|
static time_t parsedate(const char *date)
|
||||||
{
|
{
|
||||||
time_t t = 0;
|
time_t t = 0;
|
||||||
@@ -247,7 +279,8 @@ static time_t parsedate(const char *date)
|
|||||||
/* a name coming up */
|
/* a name coming up */
|
||||||
char buf[32]="";
|
char buf[32]="";
|
||||||
size_t len;
|
size_t len;
|
||||||
sscanf(date, "%31[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]", buf);
|
sscanf(date, "%31[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]",
|
||||||
|
buf);
|
||||||
len = strlen(buf);
|
len = strlen(buf);
|
||||||
|
|
||||||
if(wdaynum == -1) {
|
if(wdaynum == -1) {
|
||||||
@@ -374,45 +407,20 @@ static time_t parsedate(const char *date)
|
|||||||
tm.tm_yday = 0;
|
tm.tm_yday = 0;
|
||||||
tm.tm_isdst = 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'.
|
architectures that feature 64 bit 'long'.
|
||||||
|
|
||||||
Some systems have 64 bit time_t and deal with years beyond 2038. However,
|
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
|
even on some of the systems with 64 bit time_t mktime() returns -1 for
|
||||||
03:14:07 UTC, January 19, 2038. (Such as AIX 5100-06)
|
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) */
|
/* time zone adjust (cast t to int to compare to negative one) */
|
||||||
if(-1 != (int)t) {
|
if(-1 != (int)t) {
|
||||||
struct tm *gmt;
|
|
||||||
long delta;
|
|
||||||
time_t t2;
|
|
||||||
|
|
||||||
#ifdef HAVE_GMTIME_R
|
/* Add the time zone diff between local time zone and GMT. */
|
||||||
/* thread-safe version */
|
long delta = (long)(tzoff!=-1?tzoff:0);
|
||||||
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));
|
|
||||||
|
|
||||||
if((delta>0) && (t + delta < t))
|
if((delta>0) && (t + delta < t))
|
||||||
return -1; /* time_t overflow */
|
return -1; /* time_t overflow */
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ curl_getdate() testing
|
|||||||
# using one of the 'right' zones that take into account leap seconds
|
# using one of the 'right' zones that take into account leap seconds
|
||||||
# which causes the cookie expiry times to be different.
|
# which causes the cookie expiry times to be different.
|
||||||
<setenv>
|
<setenv>
|
||||||
TZ=GMT
|
|
||||||
</setenv>
|
</setenv>
|
||||||
<command>
|
<command>
|
||||||
nothing
|
nothing
|
||||||
|
|||||||
Reference in New Issue
Block a user