mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
- 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:
parent
a5f4cfc612
commit
d369a2b775
19
CHANGES
19
CHANGES
@ -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".
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user