From f6433211ae9afb30ec461e6633dafc6d8c77eaa9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 11 Sep 2004 09:24:02 +0000 Subject: getdate replacement code. smaller, slicker, faster. --- lib/parsedate.c | 329 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) create mode 100644 lib/parsedate.c (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c new file mode 100644 index 000000000..8c734211d --- /dev/null +++ b/lib/parsedate.c @@ -0,0 +1,329 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * $Id$ + ***************************************************************************/ +/* + RFC 2616 3.3.1 + + Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 + Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 + Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format + + we support dates without week day name: + + 06 Nov 1994 08:49:37 GMT + 06-Nov-94 08:49:37 GMT + Nov 6 08:49:37 1994 + + and without the time zone (we always assume GMT): + + 06 Nov 1994 08:49:37 + 06-Nov-94 08:49:37 + + or even in weird order: + + 1994 Nov 6 08:49:37 (curl_getdate() and GNU date fails) + 08:49:37 06-Nov-94 + 94 6 Nov 08:49:37 (curl_getdate() and GNU date fails) + +*/ +#include "setup.h" +#include +#include +#include + +#ifdef HAVE_STDLIB_H +#include /* for strtol() */ +#endif + +#include + + +#include "parsedate.h" + +static const char *wkday[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; +static const char *weekday[] = { "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday", "Sunday" }; +static const char *month[]= { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", + "Aug", "Sep", "Oct", "Nov", "Dec" }; + +static const char *tz[]= { "GMT", "UTC" }; + +/* returns: + -1 no day + 0 monday - 6 sunday +*/ + +static int checkday(char *check, size_t len) +{ + int i; + const char **what; + bool found= FALSE; + if(len > 3) + what = &weekday[0]; + else + what = &wkday[0]; + for(i=0; i<7; i++) { + if(curl_strequal(check, what[0])) { + found=TRUE; + break; + } + what++; + } + return found?i:-1; +} + +static int checkmonth(char *check) +{ + int i; + const char **what; + bool found= FALSE; + + what = &month[0]; + for(i=0; i<12; i++) { + if(curl_strequal(check, what[0])) { + found=TRUE; + break; + } + what++; + } + return found?i:-1; +} + +static int checktz(char *check) +{ + int i; + const char **what; + bool found= FALSE; + + what = &tz[0]; + for(i=0; i<2; i++) { + if(curl_strequal(check, what[0])) { + found=TRUE; + break; + } + what++; + } + return found?i:-1; +} + +static void skip(const char **date) +{ + /* skip everything that aren't letters or digits */ + while(**date && !isalnum((int)**date)) + (*date)++; +} + +#define TM_YEAR_ORIGIN 1900 + +/* Yield A - B, measured in seconds. (from getdate.y) */ +static long +difftm (struct tm *a, struct tm *b) +{ + int ay = a->tm_year + (TM_YEAR_ORIGIN - 1); + int by = b->tm_year + (TM_YEAR_ORIGIN - 1); + long days = ( + /* difference in day of year */ + a->tm_yday - b->tm_yday + /* + intervening leap days */ + + ((ay >> 2) - (by >> 2)) + - (ay / 100 - by / 100) + + ((ay / 100 >> 2) - (by / 100 >> 2)) + /* + difference in years * 365 */ + + (long) (ay - by) * 365 + ); + return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour)) + + (a->tm_min - b->tm_min)) + + (a->tm_sec - b->tm_sec)); +} + +enum assume { + DATE_MDAY, + DATE_YEAR, + DATE_TIME +}; + +time_t Curl_parsedate(const char *date) +{ + time_t t = 0; + int wdaynum=-1; /* day of the week number, 0-6 (mon-sun) */ + int monnum=-1; /* month of the year number, 0-11 */ + long mdaynum=-1; /* day of month, 1 - 31 */ + int hournum=-1; + int minnum=-1; + int secnum=-1; + long yearnum=-1; + int tznum=-1; + struct tm tm; + enum assume dignext = DATE_MDAY; + + int part = 0; /* max 6 parts */ + + while(part < 6) { + bool found=FALSE; + + skip(&date); + + if(isalpha((int)*date)) { + /* a name coming up */ + char buf[32]=""; + size_t len; + sscanf(date, "%31[^ ,\n\t-]", buf); + len = strlen(buf); + + if(wdaynum == -1) { + wdaynum = checkday(buf, len); + if(wdaynum != -1) + found = TRUE; + } + if(!found && (monnum == -1)) { + monnum = checkmonth(buf); + if(monnum != -1) + found = TRUE; + } + + if(!found && (tznum == -1)) { + /* this just must be a time zone string */ + tznum = checktz(buf); + if(tznum != -1) + found = TRUE; + } + + if(!found) + return -1; /* bad string */ + + date += len; + } + else if(isdigit((int)*date)) { + /* a digit */ + long val; + char *end; + if((secnum == -1) && + (3 == sscanf(date, "%02d:%02d:%02d", &hournum, &minnum, &secnum))) { + /* time stamp! */ + date += 8; + found = TRUE; + } + else { + val = strtol(date, &end, 10); + + if((dignext == DATE_MDAY) && (mdaynum == -1)) { + if((val > 0) && (val<32)) { + mdaynum = val; + found = TRUE; + } + dignext = DATE_YEAR; + } + + if(!found && (dignext == DATE_YEAR) && (yearnum == -1)) { + yearnum = val; + found = TRUE; + if(yearnum < 1900) { + if (yearnum > 70) + yearnum += 1900; + else + yearnum += 2000; + } + if(mdaynum == -1) + dignext = DATE_MDAY; + } + + if(!found) + return -1; + + date = end; + } + } + + part++; + } + + tm.tm_sec = secnum; + tm.tm_min = minnum; + tm.tm_hour = hournum; + tm.tm_mday = mdaynum; + tm.tm_mon = monnum; + tm.tm_year = yearnum - 1900; + tm.tm_wday = 0; + tm.tm_yday = 0; + tm.tm_isdst = 0; + + t = mktime(&tm); + + /* We have the time-stamp now, but in our local time zone, we must now + adjust it to GMT. */ + { + struct tm *gmt; + long delta; +#ifdef HAVE_GMTIME_R + /* thread-safe version */ + struct tm keeptime2; + gmt = (struct tm *)gmtime_r(&t, &keeptime2); +#else + gmt = gmtime(&t); /* use gmtime_r() if available */ +#endif + delta = difftm(&tm, gmt); + + if(t + delta < t) + return -1; /* time_t overflow */ + + t += delta; + } + + return t; +} + +time_t curl_getdate(const char *p, const time_t *now) +{ + (void)now; + return Curl_parsedate(p); +} + +#ifdef TESTIT + +int main(void) +{ + char buffer[1024]; + char cmd[1024]; + time_t t; + + while(fgets(buffer, sizeof(buffer), stdin)) { + size_t len = strlen(buffer); + + buffer[len-1]=0; /* cut off newline */ + + t = curl_getdate(buffer, NULL); + + printf("curl_getdate(): %d\n", t); + + sprintf(cmd, "date -d \"%s\" +%%s", buffer); + + printf("GNU date:\n"); + system(cmd); + + t = parse_a_date(buffer); + printf("parse_a_date: %d\n===================\n\n", t); + } + + return 0; +} + +#endif -- cgit v1.2.1 From 17acdb5acf4dbb7e6a56bbb777780a7051beb4e7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 11 Sep 2004 13:07:42 +0000 Subject: slightly better but still lacks --- lib/parsedate.c | 51 ++++++++++++++------------------------------------- 1 file changed, 14 insertions(+), 37 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 8c734211d..787507f6f 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -62,10 +62,10 @@ static const char *wkday[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; static const char *weekday[] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }; -static const char *month[]= { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", - "Aug", "Sep", "Oct", "Nov", "Dec" }; +const char *Curl_month[]= { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", + "Aug", "Sep", "Oct", "Nov", "Dec" }; -static const char *tz[]= { "GMT", "UTC" }; +static const char *tz[]= { "GMT", "UTC", "MET" }; /* returns: -1 no day @@ -97,7 +97,7 @@ static int checkmonth(char *check) const char **what; bool found= FALSE; - what = &month[0]; + what = &Curl_month[0]; for(i=0; i<12; i++) { if(curl_strequal(check, what[0])) { found=TRUE; @@ -256,6 +256,15 @@ time_t Curl_parsedate(const char *date) part++; } + if(-1 == secnum) + secnum = minnum = hournum = 0; /* no time, make it zero */ + + if((-1 == mdaynum) || + (-1 == monnum) || + (-1 == yearnum)) + /* lacks vital info, fail */ + return -1; + tm.tm_sec = secnum; tm.tm_min = minnum; tm.tm_hour = hournum; @@ -268,8 +277,7 @@ time_t Curl_parsedate(const char *date) t = mktime(&tm); - /* We have the time-stamp now, but in our local time zone, we must now - adjust it to GMT. */ + /* time zone adjust */ { struct tm *gmt; long delta; @@ -296,34 +304,3 @@ time_t curl_getdate(const char *p, const time_t *now) (void)now; return Curl_parsedate(p); } - -#ifdef TESTIT - -int main(void) -{ - char buffer[1024]; - char cmd[1024]; - time_t t; - - while(fgets(buffer, sizeof(buffer), stdin)) { - size_t len = strlen(buffer); - - buffer[len-1]=0; /* cut off newline */ - - t = curl_getdate(buffer, NULL); - - printf("curl_getdate(): %d\n", t); - - sprintf(cmd, "date -d \"%s\" +%%s", buffer); - - printf("GNU date:\n"); - system(cmd); - - t = parse_a_date(buffer); - printf("parse_a_date: %d\n===================\n\n", t); - } - - return 0; -} - -#endif -- cgit v1.2.1 From ade8e47a8c4092c47081c2f9c6adbd968ee87dc7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 11 Sep 2004 19:16:34 +0000 Subject: more docs and fixed the delta compared to GMT that prevented test case 141 to work with this --- lib/parsedate.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 787507f6f..00498a013 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -21,6 +21,8 @@ * $Id$ ***************************************************************************/ /* + A brief summary of the date string formats this parser groks: + RFC 2616 3.3.1 Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 @@ -33,17 +35,28 @@ 06-Nov-94 08:49:37 GMT Nov 6 08:49:37 1994 - and without the time zone (we always assume GMT): + without the time zone (we always assume GMT): 06 Nov 1994 08:49:37 06-Nov-94 08:49:37 - or even in weird order: + weird order: 1994 Nov 6 08:49:37 (curl_getdate() and GNU date fails) - 08:49:37 06-Nov-94 + GMT 08:49:37 06-Nov-94 Sunday 94 6 Nov 08:49:37 (curl_getdate() and GNU date fails) + time left out: + + 1994 Nov 6 + 06-Nov-94 + Sun Nov 6 94 + + odd separators: + + 1994.Nov.6 + Sun/Nov/6/94/GMT + */ #include "setup.h" #include @@ -132,6 +145,7 @@ static void skip(const char **date) (*date)++; } +#if 0 #define TM_YEAR_ORIGIN 1900 /* Yield A - B, measured in seconds. (from getdate.y) */ @@ -154,6 +168,7 @@ difftm (struct tm *a, struct tm *b) + (a->tm_min - b->tm_min)) + (a->tm_sec - b->tm_sec)); } +#endif enum assume { DATE_MDAY, @@ -177,7 +192,7 @@ time_t Curl_parsedate(const char *date) int part = 0; /* max 6 parts */ - while(part < 6) { + while(*date && (part < 6)) { bool found=FALSE; skip(&date); @@ -186,7 +201,7 @@ time_t Curl_parsedate(const char *date) /* a name coming up */ char buf[32]=""; size_t len; - sscanf(date, "%31[^ ,\n\t-]", buf); + sscanf(date, "%31[A-Za-z]", buf); len = strlen(buf); if(wdaynum == -1) { @@ -281,6 +296,8 @@ time_t Curl_parsedate(const char *date) { struct tm *gmt; long delta; + time_t t2; + #ifdef HAVE_GMTIME_R /* thread-safe version */ struct tm keeptime2; @@ -288,7 +305,16 @@ time_t Curl_parsedate(const char *date) #else gmt = gmtime(&t); /* use gmtime_r() if available */ #endif +#if 0 + /* previous involved version (that bugs?) */ delta = difftm(&tm, gmt); +#endif + + t2 = mktime(gmt); + delta = t - t2; + + /* if we would like to adjust to a different input time zone than GMT, + we would add that to the delta value right here */ if(t + delta < t) return -1; /* time_t overflow */ -- cgit v1.2.1 From 7885264b293c1909b07f9aa08896337c85c2e432 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 13 Sep 2004 07:45:19 +0000 Subject: Since many users probably already use local time strings as input, I now made it deal with named time zones as well as mail-style +0200 ones. Seems to work fine. I'm comparing with GNU date command: date -d [date] -u +%s --- lib/parsedate.c | 115 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 92 insertions(+), 23 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 00498a013..fe2cd1ea1 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -78,7 +78,58 @@ static const char *weekday[] = { "Monday", "Tuesday", "Wednesday", "Thursday", const char *Curl_month[]= { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; -static const char *tz[]= { "GMT", "UTC", "MET" }; +struct tzinfo { + const char *name; + int offset; /* +/- in minutes */ +}; + +/* Here's a bunch of frequently used time zone names. These were supported + by the old getdate parser. */ +static const struct tzinfo tz[]= { + {"GMT", 0}, /* Greenwich Mean */ + {"UTC", 0}, /* Universal (Coordinated) */ + {"WET", 0}, /* Western European */ + {"BST", 0}, /* British Summer */ + {"WAT", 60}, /* West Africa */ + {"AST", 240}, /* Atlantic Standard */ + {"ADT", 240}, /* Atlantic Daylight */ + {"EST", 300}, /* Eastern Standard */ + {"EDT", 300}, /* Eastern Daylight */ + {"CST", 360}, /* Central Standard */ + {"CDT", 360}, /* Central Daylight */ + {"MST", 420}, /* Mountain Standard */ + {"MDT", 420}, /* Mountain Daylight */ + {"PST", 480}, /* Pacific Standard */ + {"PDT", 480}, /* Pacific Daylight */ + {"YST", 540}, /* Yukon Standard */ + {"YDT", 540}, /* Yukon Daylight */ + {"HST", 600}, /* Hawaii Standard */ + {"HDT", 600}, /* Hawaii Daylight */ + {"CAT", 600}, /* Central Alaska */ + {"AHST", 600}, /* Alaska-Hawaii Standard */ + {"NT", 660}, /* Nome */ + {"IDLW", 720}, /* International Date Line West */ + {"CET", -60}, /* Central European */ + {"MET", -60}, /* Middle European */ + {"MEWT", -60}, /* Middle European Winter */ + {"MEST", -120}, /* Middle European Summer */ + {"CEST", -120}, /* Central European Summer */ + {"MESZ", -60}, /* Middle European Summer */ + {"FWT", -60}, /* French Winter */ + {"FST", -60}, /* French Summer */ + {"EET", -120}, /* Eastern Europe, USSR Zone 1 */ + {"WAST", -420}, /* West Australian Standard */ + {"WADT", -420}, /* West Australian Daylight */ + {"CCT", -480}, /* China Coast, USSR Zone 7 */ + {"JST", -540}, /* Japan Standard, USSR Zone 8 */ + {"EAST", -600}, /* Eastern Australian Standard */ + {"EADT", -600}, /* Eastern Australian Daylight */ + {"GST", -600}, /* Guam Standard, USSR Zone 9 */ + {"NZT", -720}, /* New Zealand */ + {"NZST", -720}, /* New Zealand Standard */ + {"NZDT", -720}, /* New Zealand Daylight */ + {"IDLE", -720}, /* International Date Line East */ +}; /* returns: -1 no day @@ -118,24 +169,27 @@ static int checkmonth(char *check) } what++; } - return found?i:-1; + return found?i:-1; /* return the offset or -1, no real offset is -1 */ } +/* return the time zone offset between GMT and the input one, in number + of seconds or -1 if the timezone wasn't found/legal */ + static int checktz(char *check) { - int i; - const char **what; + unsigned int i; + const struct tzinfo *what; bool found= FALSE; - what = &tz[0]; - for(i=0; i<2; i++) { - if(curl_strequal(check, what[0])) { + what = tz; + for(i=0; i< sizeof(tz)/sizeof(tz[0]); i++) { + if(curl_strequal(check, what->name)) { found=TRUE; break; } what++; } - return found?i:-1; + return found?what->offset*60:-1; } static void skip(const char **date) @@ -156,17 +210,17 @@ difftm (struct tm *a, struct tm *b) int by = b->tm_year + (TM_YEAR_ORIGIN - 1); long days = ( /* difference in day of year */ - a->tm_yday - b->tm_yday + a->tm_yday - b->tm_yday /* + intervening leap days */ - + ((ay >> 2) - (by >> 2)) - - (ay / 100 - by / 100) - + ((ay / 100 >> 2) - (by / 100 >> 2)) + + ((ay >> 2) - (by >> 2)) + - (ay / 100 - by / 100) + + ((ay / 100 >> 2) - (by / 100 >> 2)) /* + difference in years * 365 */ - + (long) (ay - by) * 365 + + (long) (ay - by) * 365 ); return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour)) - + (a->tm_min - b->tm_min)) - + (a->tm_sec - b->tm_sec)); + + (a->tm_min - b->tm_min)) + + (a->tm_sec - b->tm_sec)); } #endif @@ -186,9 +240,10 @@ time_t Curl_parsedate(const char *date) int minnum=-1; int secnum=-1; long yearnum=-1; - int tznum=-1; + int tzoff=-1; struct tm tm; enum assume dignext = DATE_MDAY; + const char *indate = date; /* save the original pointer */ int part = 0; /* max 6 parts */ @@ -215,10 +270,10 @@ time_t Curl_parsedate(const char *date) found = TRUE; } - if(!found && (tznum == -1)) { + if(!found && (tzoff == -1)) { /* this just must be a time zone string */ - tznum = checktz(buf); - if(tznum != -1) + tzoff = checktz(buf); + if(tzoff != -1) found = TRUE; } @@ -240,6 +295,20 @@ time_t Curl_parsedate(const char *date) else { val = strtol(date, &end, 10); + if( ((end - date) == 4) && + (val < 1300) && + (indate< date) && + ((date[-1] == '+' || date[-1] == '-'))) { + /* four digits and a value less than 1300 and it is preceeded with + a plus or minus. This is a time zone indication. */ + found = TRUE; + tzoff = (val/100 * 60 + val%100)*60; + + /* the + and - prefix indicates the local time compared to GMT, + this we need ther reversed math to get what we want */ + tzoff = date[-1]=='+'?-tzoff:tzoff; + } + if((dignext == DATE_MDAY) && (mdaynum == -1)) { if((val > 0) && (val<32)) { mdaynum = val; @@ -311,12 +380,12 @@ time_t Curl_parsedate(const char *date) #endif t2 = mktime(gmt); - delta = t - t2; - /* if we would like to adjust to a different input time zone than GMT, - we would add that to the delta value right here */ + /* Add the time zone diff (between the given timezone and GMT) and the + diff between the local time zone and GMT. */ + delta = (tzoff!=-1?tzoff:0) + (t - t2); - if(t + delta < t) + if((delta>0) && (t + delta < t)) return -1; /* time_t overflow */ t += delta; -- cgit v1.2.1 From b85a036e4a26c6c9da054e2f6e6fd1bbed2850cf Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 13 Sep 2004 07:57:12 +0000 Subject: added more examples/docs in the top comment --- lib/parsedate.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index fe2cd1ea1..29d8b1a68 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -35,7 +35,7 @@ 06-Nov-94 08:49:37 GMT Nov 6 08:49:37 1994 - without the time zone (we always assume GMT): + without the time zone: 06 Nov 1994 08:49:37 06-Nov-94 08:49:37 @@ -52,11 +52,21 @@ 06-Nov-94 Sun Nov 6 94 - odd separators: + unusual separators: 1994.Nov.6 Sun/Nov/6/94/GMT + commonly used time zone names: + + Sun, 06 Nov 1994 08:49:37 CET + 06 Nov 1994 08:49:37 EST + + time zones specified using RFC822 style: + + Sun, 12 Sep 2004 15:05:58 -0700 + Sat, 11 Sep 2004 21:32:11 +0200 + */ #include "setup.h" #include -- cgit v1.2.1 From 2e7dcc1e2ae6101d23ea4e6f050ef5b7ffcea4c2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 13 Sep 2004 20:40:27 +0000 Subject: support for YYYYMMDD added, which allows us to keep using the lib/ftp.c code I was previously #ifdef'ing to a different look when this parser is used --- lib/parsedate.c | 65 ++++++++++++++++++++++++--------------------------------- 1 file changed, 27 insertions(+), 38 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 29d8b1a68..165272f0e 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -42,9 +42,9 @@ weird order: - 1994 Nov 6 08:49:37 (curl_getdate() and GNU date fails) + 1994 Nov 6 08:49:37 (GNU date fails) GMT 08:49:37 06-Nov-94 Sunday - 94 6 Nov 08:49:37 (curl_getdate() and GNU date fails) + 94 6 Nov 08:49:37 (GNU date fails) time left out: @@ -67,6 +67,11 @@ Sun, 12 Sep 2004 15:05:58 -0700 Sat, 11 Sep 2004 21:32:11 +0200 + compact numerical date strings ISO846-style: + + 20040912 15:05:58 -0700 + 20040911 +0200 + */ #include "setup.h" #include @@ -79,9 +84,10 @@ #include - #include "parsedate.h" +static time_t Curl_parsedate(const char *date); + static const char *wkday[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; static const char *weekday[] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }; @@ -209,38 +215,13 @@ static void skip(const char **date) (*date)++; } -#if 0 -#define TM_YEAR_ORIGIN 1900 - -/* Yield A - B, measured in seconds. (from getdate.y) */ -static long -difftm (struct tm *a, struct tm *b) -{ - int ay = a->tm_year + (TM_YEAR_ORIGIN - 1); - int by = b->tm_year + (TM_YEAR_ORIGIN - 1); - long days = ( - /* difference in day of year */ - a->tm_yday - b->tm_yday - /* + intervening leap days */ - + ((ay >> 2) - (by >> 2)) - - (ay / 100 - by / 100) - + ((ay / 100 >> 2) - (by / 100 >> 2)) - /* + difference in years * 365 */ - + (long) (ay - by) * 365 - ); - return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour)) - + (a->tm_min - b->tm_min)) - + (a->tm_sec - b->tm_sec)); -} -#endif - enum assume { DATE_MDAY, DATE_YEAR, DATE_TIME }; -time_t Curl_parsedate(const char *date) +static time_t Curl_parsedate(const char *date) { time_t t = 0; int wdaynum=-1; /* day of the week number, 0-6 (mon-sun) */ @@ -305,10 +286,11 @@ time_t Curl_parsedate(const char *date) else { val = strtol(date, &end, 10); - if( ((end - date) == 4) && - (val < 1300) && - (indate< date) && - ((date[-1] == '+' || date[-1] == '-'))) { + if((tzoff == -1) && + ((end - date) == 4) && + (val < 1300) && + (indate< date) && + ((date[-1] == '+' || date[-1] == '-'))) { /* four digits and a value less than 1300 and it is preceeded with a plus or minus. This is a time zone indication. */ found = TRUE; @@ -319,7 +301,18 @@ time_t Curl_parsedate(const char *date) tzoff = date[-1]=='+'?-tzoff:tzoff; } - if((dignext == DATE_MDAY) && (mdaynum == -1)) { + if(((end - date) == 8) && + (yearnum == -1) && + (monnum == -1) && + (mdaynum == -1)) { + /* 8 digits, no year, month or day yet. This is YYYYMMDD */ + found = TRUE; + yearnum = val/10000; + monnum = (val%10000)/100-1; /* month is 0 - 11 */ + mdaynum = val%100; + } + + if(!found && (dignext == DATE_MDAY) && (mdaynum == -1)) { if((val > 0) && (val<32)) { mdaynum = val; found = TRUE; @@ -384,10 +377,6 @@ time_t Curl_parsedate(const char *date) #else gmt = gmtime(&t); /* use gmtime_r() if available */ #endif -#if 0 - /* previous involved version (that bugs?) */ - delta = difftm(&tm, gmt); -#endif t2 = mktime(gmt); -- cgit v1.2.1 From adbe3eefb61b3dd75ab1a5823b8527097ad5a528 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 13 Sep 2004 20:49:27 +0000 Subject: and moved back the month array to a static one since the ftp code won't need it anymore --- lib/parsedate.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 165272f0e..a9fa982bf 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -84,15 +84,13 @@ #include -#include "parsedate.h" - static time_t Curl_parsedate(const char *date); static const char *wkday[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; static const char *weekday[] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }; -const char *Curl_month[]= { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", - "Aug", "Sep", "Oct", "Nov", "Dec" }; +static const char *month[]= { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", + "Aug", "Sep", "Oct", "Nov", "Dec" }; struct tzinfo { const char *name; @@ -177,7 +175,7 @@ static int checkmonth(char *check) const char **what; bool found= FALSE; - what = &Curl_month[0]; + what = &month[0]; for(i=0; i<12; i++) { if(curl_strequal(check, what[0])) { found=TRUE; -- cgit v1.2.1 From f71b3f48a16e5d62079ad013adb2b96560a1c1fe Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 15 Sep 2004 07:28:04 +0000 Subject: Replaced the former date parser with a rewrite. No more yacc/bison needed. --- lib/parsedate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index a9fa982bf..0c54f9f45 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -67,7 +67,7 @@ Sun, 12 Sep 2004 15:05:58 -0700 Sat, 11 Sep 2004 21:32:11 +0200 - compact numerical date strings ISO846-style: + compact numerical date strings: 20040912 15:05:58 -0700 20040911 +0200 -- cgit v1.2.1 From 2de62cb06f5f7abdbcc55fc219bf86d8433125ec Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 20 Sep 2004 13:21:48 +0000 Subject: less long => int implicit conversion warnings --- lib/parsedate.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 0c54f9f45..836340c07 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -224,11 +224,11 @@ static time_t Curl_parsedate(const char *date) time_t t = 0; int wdaynum=-1; /* day of the week number, 0-6 (mon-sun) */ int monnum=-1; /* month of the year number, 0-11 */ - long mdaynum=-1; /* day of month, 1 - 31 */ + int mdaynum=-1; /* day of month, 1 - 31 */ int hournum=-1; int minnum=-1; int secnum=-1; - long yearnum=-1; + int yearnum=-1; int tzoff=-1; struct tm tm; enum assume dignext = DATE_MDAY; @@ -273,7 +273,7 @@ static time_t Curl_parsedate(const char *date) } else if(isdigit((int)*date)) { /* a digit */ - long val; + int val; char *end; if((secnum == -1) && (3 == sscanf(date, "%02d:%02d:%02d", &hournum, &minnum, &secnum))) { @@ -282,7 +282,7 @@ static time_t Curl_parsedate(const char *date) found = TRUE; } else { - val = strtol(date, &end, 10); + val = (int)strtol(date, &end, 10); if((tzoff == -1) && ((end - date) == 4) && -- cgit v1.2.1 From cd73a733c78b7ab7b4e3ccaca9350bbcce124142 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 11 Nov 2004 09:26:09 +0000 Subject: dates from 2038 or later now return 0x7fffffff when 32 bit time_t is used --- lib/parsedate.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 836340c07..e9e860fe6 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -350,6 +350,12 @@ static time_t Curl_parsedate(const char *date) /* lacks vital info, fail */ return -1; +#if SIZEOF_TIME_T < 5 + /* 32 bit time_t can only hold dates to the beginning of 2038 */ + if(yearnum > 2037) + return 0x7fffffff; +#endif + tm.tm_sec = secnum; tm.tm_min = minnum; tm.tm_hour = hournum; -- cgit v1.2.1 From c0d448f7783638354a7bb981e40dde0af4e8ad9d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 29 Nov 2004 08:10:10 +0000 Subject: if gmtime() returns NULL, this returns -1 to bail out nicely --- lib/parsedate.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index e9e860fe6..e3637ee75 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -381,6 +381,8 @@ static time_t Curl_parsedate(const char *date) #else gmt = gmtime(&t); /* use gmtime_r() if available */ #endif + if(!gmt) + return -1; /* illegal date/time */ t2 = mktime(gmt); -- cgit v1.2.1 From 80d301257c8b02dc2691fa8283bc02c1c84c06a3 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Mon, 20 Dec 2004 18:23:43 +0000 Subject: Make some more arrays of pointers const. --- lib/parsedate.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index e3637ee75..198f70101 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -86,11 +86,14 @@ static time_t Curl_parsedate(const char *date); -static const char *wkday[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; -static const char *weekday[] = { "Monday", "Tuesday", "Wednesday", "Thursday", +static const char * const wkday[] = + {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; +static const char * const weekday[] = + { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }; -static const char *month[]= { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", - "Aug", "Sep", "Oct", "Nov", "Dec" }; +static const char * const month[]= + { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; struct tzinfo { const char *name; @@ -153,7 +156,7 @@ static const struct tzinfo tz[]= { static int checkday(char *check, size_t len) { int i; - const char **what; + const char * const *what; bool found= FALSE; if(len > 3) what = &weekday[0]; @@ -172,7 +175,7 @@ static int checkday(char *check, size_t len) static int checkmonth(char *check) { int i; - const char **what; + const char * const *what; bool found= FALSE; what = &month[0]; -- cgit v1.2.1 From e7cefd684b2d5e1f3710eb24babc0b9974095c97 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 11 Feb 2005 00:03:49 +0000 Subject: Removed all uses of strftime() since it uses the localised version of the week day names and month names and servers don't like that. --- lib/parsedate.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 198f70101..063d0c44a 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -86,14 +86,14 @@ static time_t Curl_parsedate(const char *date); -static const char * const wkday[] = - {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; +const char * const Curl_wkday[] = +{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; static const char * const weekday[] = - { "Monday", "Tuesday", "Wednesday", "Thursday", - "Friday", "Saturday", "Sunday" }; -static const char * const month[]= - { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; +{ "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday", "Sunday" }; +const char * const Curl_month[]= +{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; struct tzinfo { const char *name; @@ -161,7 +161,7 @@ static int checkday(char *check, size_t len) if(len > 3) what = &weekday[0]; else - what = &wkday[0]; + what = &Curl_wkday[0]; for(i=0; i<7; i++) { if(curl_strequal(check, what[0])) { found=TRUE; @@ -178,7 +178,7 @@ static int checkmonth(char *check) const char * const *what; bool found= FALSE; - what = &month[0]; + what = &Curl_month[0]; for(i=0; i<12; i++) { if(curl_strequal(check, what[0])) { found=TRUE; -- cgit v1.2.1 From 8a96aec5673b9ba4787cef1319c105facbe82a40 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 8 Mar 2005 16:31:56 +0000 Subject: mktime() 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) --- lib/parsedate.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 063d0c44a..de6cdb11b 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -369,10 +369,17 @@ static time_t Curl_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 + 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) + */ t = mktime(&tm); /* time zone adjust */ - { + if(-1 != t) { struct tm *gmt; long delta; time_t t2; -- cgit v1.2.1 From ab4086bc244bf3267976e9f0193e5ed4430190d8 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 31 Mar 2005 07:02:02 +0000 Subject: Updated the copyright year since changes have been this year. --- lib/parsedate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index de6cdb11b..26f573fdd 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2005, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms -- cgit v1.2.1 From 6b1220b61d5ed2481dbf31714a68be6ef6eed3da Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 26 Apr 2005 13:08:49 +0000 Subject: Cory Nelson's work on nuking compiler warnings when building on x64 with VS2005. --- lib/parsedate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 26f573fdd..52529848d 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -398,7 +398,7 @@ static time_t Curl_parsedate(const char *date) /* Add the time zone diff (between the given timezone and GMT) and the diff between the local time zone and GMT. */ - delta = (tzoff!=-1?tzoff:0) + (t - t2); + delta = (long)((tzoff!=-1?tzoff:0) + (t - t2)); if((delta>0) && (t + delta < t)) return -1; /* time_t overflow */ -- cgit v1.2.1 From d49c1442970642ba0daf2654b54dca971c83fd8c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 5 Jul 2005 14:57:41 +0000 Subject: Gisle Vanem came up with a nice little work-around for bug #1230118. It seems the Windows (MSVC) libc time functions may return data one hour off if TZ is not set and automatic DST adjustment is enabled. This made curl_getdate() return wrong value, and it also concerned internal cookie expirations etc. --- lib/parsedate.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 52529848d..ae9e232a9 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -236,9 +236,20 @@ static time_t Curl_parsedate(const char *date) struct tm tm; enum assume dignext = DATE_MDAY; const char *indate = date; /* save the original pointer */ - int part = 0; /* max 6 parts */ +#ifdef WIN32 + /* + * On Windows, we need an odd work-around for the case when no TZ variable + * is set. If it isn't set and "automatic DST adjustment" is enabled, the + * time functions below will return values one hour off! As reported and + * investigated in bug report #1230118. + */ + const char *env = getenv("TZ"); + if(!env) + putenv("TZ=GMT"); +#endif + while(*date && (part < 6)) { bool found=FALSE; -- cgit v1.2.1 From 6c157a404b3b0d2e6659fde92f498c7c5608ac61 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 9 Aug 2005 21:59:31 +0000 Subject: Christopher R. Palmer fixed the offsets used for date parsings when the time zone name of a daylight savings time was used. For example, PDT vs PDS. This flaw was introduced with the new date parser (11 sep 2004 - 7.12.2). Fortunately, no web server or cookie string etc should be using such time zone names thus limiting the effect of this bug. --- lib/parsedate.c | 87 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 44 insertions(+), 43 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index ae9e232a9..caf38a2ca 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -102,50 +102,51 @@ struct tzinfo { /* Here's a bunch of frequently used time zone names. These were supported by the old getdate parser. */ +#define tDAYZONE -60 /* offset for daylight savings time */ static const struct tzinfo tz[]= { - {"GMT", 0}, /* Greenwich Mean */ - {"UTC", 0}, /* Universal (Coordinated) */ - {"WET", 0}, /* Western European */ - {"BST", 0}, /* British Summer */ - {"WAT", 60}, /* West Africa */ - {"AST", 240}, /* Atlantic Standard */ - {"ADT", 240}, /* Atlantic Daylight */ - {"EST", 300}, /* Eastern Standard */ - {"EDT", 300}, /* Eastern Daylight */ - {"CST", 360}, /* Central Standard */ - {"CDT", 360}, /* Central Daylight */ - {"MST", 420}, /* Mountain Standard */ - {"MDT", 420}, /* Mountain Daylight */ - {"PST", 480}, /* Pacific Standard */ - {"PDT", 480}, /* Pacific Daylight */ - {"YST", 540}, /* Yukon Standard */ - {"YDT", 540}, /* Yukon Daylight */ - {"HST", 600}, /* Hawaii Standard */ - {"HDT", 600}, /* Hawaii Daylight */ - {"CAT", 600}, /* Central Alaska */ - {"AHST", 600}, /* Alaska-Hawaii Standard */ - {"NT", 660}, /* Nome */ - {"IDLW", 720}, /* International Date Line West */ - {"CET", -60}, /* Central European */ - {"MET", -60}, /* Middle European */ - {"MEWT", -60}, /* Middle European Winter */ - {"MEST", -120}, /* Middle European Summer */ - {"CEST", -120}, /* Central European Summer */ - {"MESZ", -60}, /* Middle European Summer */ - {"FWT", -60}, /* French Winter */ - {"FST", -60}, /* French Summer */ - {"EET", -120}, /* Eastern Europe, USSR Zone 1 */ - {"WAST", -420}, /* West Australian Standard */ - {"WADT", -420}, /* West Australian Daylight */ - {"CCT", -480}, /* China Coast, USSR Zone 7 */ - {"JST", -540}, /* Japan Standard, USSR Zone 8 */ - {"EAST", -600}, /* Eastern Australian Standard */ - {"EADT", -600}, /* Eastern Australian Daylight */ - {"GST", -600}, /* Guam Standard, USSR Zone 9 */ - {"NZT", -720}, /* New Zealand */ - {"NZST", -720}, /* New Zealand Standard */ - {"NZDT", -720}, /* New Zealand Daylight */ - {"IDLE", -720}, /* International Date Line East */ + {"GMT", 0}, /* Greenwich Mean */ + {"UTC", 0}, /* Universal (Coordinated) */ + {"WET", 0}, /* Western European */ + {"BST", 0 tDAYZONE}, /* British Summer */ + {"WAT", 60}, /* West Africa */ + {"AST", 240}, /* Atlantic Standard */ + {"ADT", 240 tDAYZONE}, /* Atlantic Daylight */ + {"EST", 300}, /* Eastern Standard */ + {"EDT", 300 tDAYZONE}, /* Eastern Daylight */ + {"CST", 360}, /* Central Standard */ + {"CDT", 360 tDAYZONE}, /* Central Daylight */ + {"MST", 420}, /* Mountain Standard */ + {"MDT", 420 tDAYZONE}, /* Mountain Daylight */ + {"PST", 480}, /* Pacific Standard */ + {"PDT", 480 tDAYZONE}, /* Pacific Daylight */ + {"YST", 540}, /* Yukon Standard */ + {"YDT", 540 tDAYZONE}, /* Yukon Daylight */ + {"HST", 600}, /* Hawaii Standard */ + {"HDT", 600 tDAYZONE}, /* Hawaii Daylight */ + {"CAT", 600}, /* Central Alaska */ + {"AHST", 600}, /* Alaska-Hawaii Standard */ + {"NT", 660}, /* Nome */ + {"IDLW", 720}, /* International Date Line West */ + {"CET", -60}, /* Central European */ + {"MET", -60}, /* Middle European */ + {"MEWT", -60}, /* Middle European Winter */ + {"MEST", -120 tDAYZONE}, /* Middle European Summer */ + {"CEST", -120 tDAYZONE}, /* Central European Summer */ + {"MESZ", -60 tDAYZONE}, /* Middle European Summer */ + {"FWT", -60}, /* French Winter */ + {"FST", -60 tDAYZONE}, /* French Summer */ + {"EET", -120}, /* Eastern Europe, USSR Zone 1 */ + {"WAST", -420}, /* West Australian Standard */ + {"WADT", -420 tDAYZONE}, /* West Australian Daylight */ + {"CCT", -480}, /* China Coast, USSR Zone 7 */ + {"JST", -540}, /* Japan Standard, USSR Zone 8 */ + {"EAST", -600}, /* Eastern Australian Standard */ + {"EADT", -600 tDAYZONE}, /* Eastern Australian Daylight */ + {"GST", -600}, /* Guam Standard, USSR Zone 9 */ + {"NZT", -720}, /* New Zealand */ + {"NZST", -720}, /* New Zealand Standard */ + {"NZDT", -720 tDAYZONE}, /* New Zealand Daylight */ + {"IDLE", -720}, /* International Date Line East */ }; /* returns: -- cgit v1.2.1 From db83a0ebbc37dece413b3c8c89cfd2856cd932f6 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 4 Oct 2005 18:15:33 +0000 Subject: Michael Wallner reported that the date parser had wrong offset stored for the MEST and CEST time zones. --- lib/parsedate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index caf38a2ca..52684825f 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -130,8 +130,8 @@ static const struct tzinfo tz[]= { {"CET", -60}, /* Central European */ {"MET", -60}, /* Middle European */ {"MEWT", -60}, /* Middle European Winter */ - {"MEST", -120 tDAYZONE}, /* Middle European Summer */ - {"CEST", -120 tDAYZONE}, /* Central European Summer */ + {"MEST", -60 tDAYZONE}, /* Middle European Summer */ + {"CEST", -60 tDAYZONE}, /* Central European Summer */ {"MESZ", -60 tDAYZONE}, /* Middle European Summer */ {"FWT", -60}, /* French Winter */ {"FST", -60 tDAYZONE}, /* French Summer */ -- cgit v1.2.1 From b11dec5dd5a4e727be964448b9c5d14cd0ace974 Mon Sep 17 00:00:00 2001 From: Marty Kuhrt Date: Fri, 30 Dec 2005 00:07:25 +0000 Subject: putting back into dist --- lib/parsedate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 52684825f..864231b0e 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -391,7 +391,7 @@ static time_t Curl_parsedate(const char *date) t = mktime(&tm); /* time zone adjust */ - if(-1 != t) { + if(-1 != (int)t) { struct tm *gmt; long delta; time_t t2; -- cgit v1.2.1 From 0040a60559a3bdc9aaf295727cd07a37f0362e70 Mon Sep 17 00:00:00 2001 From: Marty Kuhrt Date: Fri, 30 Dec 2005 00:35:21 +0000 Subject: fix questionable compare --- lib/parsedate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 864231b0e..37b4ddfe3 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -390,7 +390,7 @@ static time_t Curl_parsedate(const char *date) */ t = mktime(&tm); - /* time zone adjust */ + /* time zone adjust (cast t to int to compare to negative one) */ if(-1 != (int)t) { struct tm *gmt; long delta; -- cgit v1.2.1 From 44d84ac1646cf04ccc2c1a736f3c9d1644ccacec Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 17 Oct 2006 21:32:56 +0000 Subject: Avoid typecasting a signed char to an int when using is*() functions, as that could very well cause a negate number get passed in and thus cause reading outside of the array usually used for this purpose. We avoid this by using the uppercase macro versions introduced just now that does some extra crazy typecasts to avoid byte codes > 127 to cause negative int values. --- lib/parsedate.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 37b4ddfe3..0bb6d0c5a 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2005, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2006, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -213,7 +213,7 @@ static int checktz(char *check) static void skip(const char **date) { /* skip everything that aren't letters or digits */ - while(**date && !isalnum((int)**date)) + while(**date && !ISALNUM(**date)) (*date)++; } @@ -256,7 +256,7 @@ static time_t Curl_parsedate(const char *date) skip(&date); - if(isalpha((int)*date)) { + if(ISALPHA(*date)) { /* a name coming up */ char buf[32]=""; size_t len; @@ -286,7 +286,7 @@ static time_t Curl_parsedate(const char *date) date += len; } - else if(isdigit((int)*date)) { + else if(ISDIGIT(*date)) { /* a digit */ int val; char *end; -- cgit v1.2.1 From 17ae28e0feb08da02d785a69d08116d877df5ca9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 5 Dec 2006 14:57:43 +0000 Subject: Martin Skinner brought back bug report #1230118 to haunt us once again. (http://curl.haxx.se/bug/view.cgi?id=1230118) curl_getdate() did not work properly for all input dates on Windows. It was mostly seen on some TZ time zones using DST. Luckily, Martin also provided a fix. --- lib/parsedate.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 0bb6d0c5a..ef91585e5 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -239,18 +239,6 @@ static time_t Curl_parsedate(const char *date) const char *indate = date; /* save the original pointer */ int part = 0; /* max 6 parts */ -#ifdef WIN32 - /* - * On Windows, we need an odd work-around for the case when no TZ variable - * is set. If it isn't set and "automatic DST adjustment" is enabled, the - * time functions below will return values one hour off! As reported and - * investigated in bug report #1230118. - */ - const char *env = getenv("TZ"); - if(!env) - putenv("TZ=GMT"); -#endif - while(*date && (part < 6)) { bool found=FALSE; @@ -400,13 +388,22 @@ static time_t Curl_parsedate(const char *date) /* 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 */ -#endif if(!gmt) return -1; /* illegal date/time */ - - t2 = mktime(gmt); + 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. */ -- cgit v1.2.1 From caf880be181a9a4f3b03cff8c21b5bdba75b67b0 Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Tue, 6 Nov 2007 16:20:04 +0000 Subject: Constified from arguments. --- lib/parsedate.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index ef91585e5..5dd6c6ef7 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -154,7 +154,7 @@ static const struct tzinfo tz[]= { 0 monday - 6 sunday */ -static int checkday(char *check, size_t len) +static int checkday(const char *check, size_t len) { int i; const char * const *what; @@ -173,7 +173,7 @@ static int checkday(char *check, size_t len) return found?i:-1; } -static int checkmonth(char *check) +static int checkmonth(const char *check) { int i; const char * const *what; @@ -193,7 +193,7 @@ static int checkmonth(char *check) /* return the time zone offset between GMT and the input one, in number of seconds or -1 if the timezone wasn't found/legal */ -static int checktz(char *check) +static int checktz(const char *check) { unsigned int i; const struct tzinfo *what; -- cgit v1.2.1 From cbd1a77ec24e397d05f20c6de106625676343c9d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 7 Nov 2007 09:21:35 +0000 Subject: if () => if() while () => while() and some other minor re-indentings --- lib/parsedate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 5dd6c6ef7..af2d4c265 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2006, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -325,7 +325,7 @@ static time_t Curl_parsedate(const char *date) yearnum = val; found = TRUE; if(yearnum < 1900) { - if (yearnum > 70) + if(yearnum > 70) yearnum += 1900; else yearnum += 2000; -- cgit v1.2.1 From 662bee71930fc30ef3fe43077bf696def44c5c7b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 8 Dec 2007 22:50:55 +0000 Subject: All static functions that were previously name Curl_* something no longer use that prefix as we use that prefix only for library-wide internal global symbols. --- lib/parsedate.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index af2d4c265..0f0a18629 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -84,7 +84,7 @@ #include -static time_t Curl_parsedate(const char *date); +static time_t parsedate(const char *date); const char * const Curl_wkday[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; @@ -223,7 +223,7 @@ enum assume { DATE_TIME }; -static time_t Curl_parsedate(const char *date) +static time_t parsedate(const char *date) { time_t t = 0; int wdaynum=-1; /* day of the week number, 0-6 (mon-sun) */ @@ -421,5 +421,5 @@ static time_t Curl_parsedate(const char *date) time_t curl_getdate(const char *p, const time_t *now) { (void)now; - return Curl_parsedate(p); + return parsedate(p); } -- cgit v1.2.1 From 423309541a1952ab0b340361d0a752d289d9653f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 6 Jan 2008 10:50:57 +0000 Subject: Jeff Johnson filed bug report #1863171 (http://curl.haxx.se/bug/view.cgi?id=1863171) where he pointed out that libcurl's date parser didn't accept a +1300 time zone which actually is used fairly often (like New Zealand's Dailight Savings Time), so I modified the parser to now accept up to and including -1400 to +1400. --- lib/parsedate.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 0f0a18629..78cc96fe2 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -289,11 +289,17 @@ static time_t parsedate(const char *date) if((tzoff == -1) && ((end - date) == 4) && - (val < 1300) && + (val <= 1400) && (indate< date) && ((date[-1] == '+' || date[-1] == '-'))) { - /* four digits and a value less than 1300 and it is preceeded with - a plus or minus. This is a time zone indication. */ + /* four digits and a value less than or equal to 1400 (to take into + account all sorts of funny time zone diffs) and it is preceeded + with a plus or minus. This is a time zone indication. 1400 is + picked since +1300 is frequently used and +1400 is mentioned as + an edge number in the document "ISO C 200X Proposal: Timezone + Functions" at http://david.tribble.com/text/c0xtimezone.html If + anyone has a more authoritative source for the exact maximum time + zone offsets, please speak up! */ found = TRUE; tzoff = (val/100 * 60 + val%100)*60; -- cgit v1.2.1 From 90a6a59a2f27124917ee6931f66594a636a4c591 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Sun, 22 Jun 2008 06:57:00 +0000 Subject: Stopped using ranges in scanf character sequences (e.g. %[a-z]) since that is not ANSI C, just a common extension. This caused problems on at least Open Watcom C. --- lib/parsedate.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 78cc96fe2..d1d8d5837 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -84,8 +84,6 @@ #include -static time_t parsedate(const char *date); - const char * const Curl_wkday[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; static const char * const weekday[] = @@ -248,7 +246,7 @@ static time_t parsedate(const char *date) /* a name coming up */ char buf[32]=""; size_t len; - sscanf(date, "%31[A-Za-z]", buf); + sscanf(date, "%31[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]", buf); len = strlen(buf); if(wdaynum == -1) { -- cgit v1.2.1 From f7ef60c13f948ba41dcf76db3dbaaf29657ac4e2 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 18 Sep 2008 19:17:28 +0000 Subject: fix compiler warning: external definition with no prior declaration --- lib/parsedate.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index d1d8d5837..64bb2cc41 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -83,6 +83,7 @@ #endif #include +#include "parsedate.h" const char * const Curl_wkday[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; -- cgit v1.2.1 From d369a2b7755d763490575fc18de748def0b3ba77 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 23 Sep 2008 11:00:01 +0000 Subject: - 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. --- lib/parsedate.c | 72 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 32 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 64bb2cc41..d1d1fdc82 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -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 */ -- cgit v1.2.1 From 6d24719167c85165a91a387c4c9af38fa93587e2 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Mon, 29 Sep 2008 23:22:41 +0000 Subject: Made the month days table static const --- lib/parsedate.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index d1d1fdc82..d30286ef5 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -222,10 +222,14 @@ enum assume { DATE_TIME }; -/* struct tm to time since epoch in GMT time zone */ +/* struct tm to time since epoch in GMT time zone. + * This is similar to the standard mktime function but for GMT only, and + * doesn't suffer from the various bugs and portability problems that + * some systems' implementations have. + */ static time_t my_timegm(struct tm * tm) { - int month_days_cumulative [12] = + static const int month_days_cumulative [12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; int month, year, leap_days; -- cgit v1.2.1 From ba9963b8fa22707dbf49e4fa253208467b2cb732 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 9 Oct 2008 21:57:51 +0000 Subject: I replaced the use of 'struct tm' with a private clone of that struct simply because the struct is declared on the stack and not all members are used so we could just as well make struct with only struct members we actually need. --- lib/parsedate.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index d30286ef5..fc6f9216f 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -222,12 +222,23 @@ enum assume { DATE_TIME }; +/* this is a clone of 'struct tm' but with all fields we don't need or use + cut out */ +struct my_tm { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; +}; + /* struct tm to time since epoch in GMT time zone. * This is similar to the standard mktime function but for GMT only, and * doesn't suffer from the various bugs and portability problems that * some systems' implementations have. */ -static time_t my_timegm(struct tm * tm) +static time_t my_timegm(struct my_tm *tm) { static const int month_days_cumulative [12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; @@ -269,7 +280,7 @@ static time_t parsedate(const char *date) int secnum=-1; int yearnum=-1; int tzoff=-1; - struct tm tm; + struct my_tm tm; enum assume dignext = DATE_MDAY; const char *indate = date; /* save the original pointer */ int part = 0; /* max 6 parts */ @@ -407,9 +418,6 @@ static time_t parsedate(const char *date) tm.tm_mday = mdaynum; tm.tm_mon = monnum; tm.tm_year = yearnum - 1900; - tm.tm_wday = 0; - tm.tm_yday = 0; - tm.tm_isdst = 0; /* my_timegm() returns a time_t. time_t is often 32 bits, even on many architectures that feature 64 bit 'long'. -- cgit v1.2.1 From a579d6706436615845f57692921e0891fb6e3719 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 15 Oct 2008 21:43:48 +0000 Subject: - Pascal Terjan filed bug #2154627 (http://curl.haxx.se/bug/view.cgi?id=2154627) which pointed out that libcurl uses strcasecmp() in multiple places where it causes failures when the Turkish locale is used. This is because 'i' and 'I' isn't the same letter so strcasecmp() on those letters are different in Turkish than in English (or just about all other languages). I thus introduced a totally new internal function in libcurl (called Curl_ascii_equal) for doing case insentive comparisons for english-(ascii?) style strings that thus will make "file" and "FILE" match even if the Turkish locale is selected. --- lib/parsedate.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index fc6f9216f..11dc55e64 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -83,6 +83,7 @@ #endif #include +#include "strequal.h" #include "parsedate.h" const char * const Curl_wkday[] = @@ -163,7 +164,7 @@ static int checkday(const char *check, size_t len) else what = &Curl_wkday[0]; for(i=0; i<7; i++) { - if(curl_strequal(check, what[0])) { + if(Curl_ascii_equal(check, what[0])) { found=TRUE; break; } @@ -180,7 +181,7 @@ static int checkmonth(const char *check) what = &Curl_month[0]; for(i=0; i<12; i++) { - if(curl_strequal(check, what[0])) { + if(Curl_ascii_equal(check, what[0])) { found=TRUE; break; } @@ -200,7 +201,7 @@ static int checktz(const char *check) what = tz; for(i=0; i< sizeof(tz)/sizeof(tz[0]); i++) { - if(curl_strequal(check, what->name)) { + if(Curl_ascii_equal(check, what->name)) { found=TRUE; break; } -- cgit v1.2.1 From 9d16b4081ed011c11f9876ae2685076e92113593 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 16 Oct 2008 08:23:48 +0000 Subject: Renamed Curl_ascii_equal to Curl_raw_equal and bugfixed the my_toupper function used in strequal.c so now all test cases run fine for me again. --- lib/parsedate.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 11dc55e64..ef2ee658b 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -164,7 +164,7 @@ static int checkday(const char *check, size_t len) else what = &Curl_wkday[0]; for(i=0; i<7; i++) { - if(Curl_ascii_equal(check, what[0])) { + if(Curl_raw_equal(check, what[0])) { found=TRUE; break; } @@ -181,7 +181,7 @@ static int checkmonth(const char *check) what = &Curl_month[0]; for(i=0; i<12; i++) { - if(Curl_ascii_equal(check, what[0])) { + if(Curl_raw_equal(check, what[0])) { found=TRUE; break; } @@ -201,7 +201,7 @@ static int checktz(const char *check) what = tz; for(i=0; i< sizeof(tz)/sizeof(tz[0]); i++) { - if(Curl_ascii_equal(check, what->name)) { + if(Curl_raw_equal(check, what->name)) { found=TRUE; break; } -- cgit v1.2.1 From 7fc4e8af0a2778f6c017a9a95d64a0c211ea1f55 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Wed, 22 Oct 2008 05:46:29 +0000 Subject: Changed some arrays of char* to arrays of char[] to reduce data size and run-time relocations. --- lib/parsedate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index ef2ee658b..786ab7ff4 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -96,7 +96,7 @@ const char * const Curl_month[]= "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; struct tzinfo { - const char *name; + char name[5]; int offset; /* +/- in minutes */ }; -- cgit v1.2.1 From b701ea36a723b2d7700e23ae53e2c3145dfe7bda Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 23 Oct 2008 11:49:19 +0000 Subject: moved the Curl_raw_ functions into the new lib/rawstr.c file for easier curlx_ inclusion by the curl tool without colliding with the curl_strequal functions. --- lib/parsedate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 786ab7ff4..843368cf7 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -83,7 +83,7 @@ #endif #include -#include "strequal.h" +#include "rawstr.h" #include "parsedate.h" const char * const Curl_wkday[] = -- cgit v1.2.1 From 777168cb778b6626ec9a2325e85acc3e17b5cde9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 3 Sep 2009 08:13:32 +0000 Subject: provide and export Curl_parsedate() as a library-wide internal function for a better API to date parsing than the external API is --- lib/parsedate.c | 48 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 843368cf7..badf71114 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -270,7 +270,18 @@ static time_t my_timegm(struct my_tm *tm) + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec; } -static time_t parsedate(const char *date) +/* + * Curl_parsedate() + * + * Returns: + * + * PARSEDATE_OK - a fine conversion + * PARSEDATE_FAIL - failed to convert + * PARSEDATE_LATER - time overflow at the far end of time_t + * PARSEDATE_SOONER - time underflow at the low end of time_t + */ + +int Curl_parsedate(const char *date, time_t *output) { time_t t = 0; int wdaynum=-1; /* day of the week number, 0-6 (mon-sun) */ @@ -318,7 +329,7 @@ static time_t parsedate(const char *date) } if(!found) - return -1; /* bad string */ + return PARSEDATE_FAIL; /* bad string */ date += len; } @@ -389,7 +400,7 @@ static time_t parsedate(const char *date) } if(!found) - return -1; + return PARSEDATE_FAIL; date = end; } @@ -405,14 +416,21 @@ static time_t parsedate(const char *date) (-1 == monnum) || (-1 == yearnum)) /* lacks vital info, fail */ - return -1; + return PARSEDATE_FAIL; #if SIZEOF_TIME_T < 5 /* 32 bit time_t can only hold dates to the beginning of 2038 */ - if(yearnum > 2037) - return 0x7fffffff; + if(yearnum > 2037) { + *output = 0x7fffffff; + return PARSEDATE_LATER; + } #endif + if(yearnum < 1970) { + *output = 0; + return PARSEDATE_SOONER; + } + tm.tm_sec = secnum; tm.tm_min = minnum; tm.tm_hour = hournum; @@ -441,11 +459,23 @@ static time_t parsedate(const char *date) t += delta; } - return t; + *output = t; + + return PARSEDATE_OK; } time_t curl_getdate(const char *p, const time_t *now) { - (void)now; - return parsedate(p); + time_t parsed; + int rc = Curl_parsedate(p, &parsed); + (void)now; /* legacy argument from the past that we ignore */ + + switch(rc) { + case PARSEDATE_OK: + case PARSEDATE_LATER: + case PARSEDATE_SOONER: + return parsed; + } + /* everything else is fail */ + return -1; } -- cgit v1.2.1 From 183c9ce1cfde10c860dc5cb1a3cb25a56038625f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 3 Sep 2009 08:30:28 +0000 Subject: fix copyright year --- lib/parsedate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index badf71114..2b704b52e 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms -- cgit v1.2.1 From 6f4a5a46125d48d8fb9c6f8e112ca9c376829577 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 18 Oct 2009 21:56:19 +0000 Subject: - Ray Dassen provided a patch in Debian's bug tracker (bug number #551461) that now makes curl_getdate(3) actually handles RFC 822 formatted dates that use the "single letter military timezones". http://www.rfc-ref.org/RFC-TEXTS/822/chapter5.html has the details. --- lib/parsedate.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 2b704b52e..b846501c1 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -147,6 +147,36 @@ static const struct tzinfo tz[]= { {"NZST", -720}, /* New Zealand Standard */ {"NZDT", -720 tDAYZONE}, /* New Zealand Daylight */ {"IDLE", -720}, /* International Date Line East */ + /* Next up: Military timezone names. RFC822 allowed these, but (as noted in + RFC 1123) had their signs wrong. Here we use the correct signs to match + actual military usage. + */ + {"A", +1 * 60}, /* Alpha */ + {"B", +2 * 60}, /* Bravo */ + {"C", +3 * 60}, /* Charlie */ + {"D", +4 * 60}, /* Delta */ + {"E", +5 * 60}, /* Echo */ + {"F", +6 * 60}, /* Foxtrot */ + {"G", +7 * 60}, /* Golf */ + {"H", +8 * 60}, /* Hotel */ + {"I", +9 * 60}, /* India */ + /* "J", Juliet is not used as a timezone, to indicate the observer's local time */ + {"K", +10 * 60}, /* Kilo */ + {"L", +11 * 60}, /* Lima */ + {"M", +12 * 60}, /* Mike */ + {"N", -1 * 60}, /* November */ + {"O", -2 * 60}, /* Oscar */ + {"P", -3 * 60}, /* Papa */ + {"Q", -4 * 60}, /* Quebec */ + {"R", -5 * 60}, /* Romeo */ + {"S", -6 * 60}, /* Sierra */ + {"T", -7 * 60}, /* Tango */ + {"U", -8 * 60}, /* Uniform */ + {"V", -9 * 60}, /* Victor */ + {"W", -10 * 60}, /* Whiskey */ + {"X", -11 * 60}, /* X-ray */ + {"Y", -12 * 60}, /* Yankee */ + {"Z", 0}, /* Zulu, zero meridian, a.k.a. UTC */ }; /* returns: -- cgit v1.2.1 From 2309b4e330b96bc2e1f8e36b6184015e59544037 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 24 Mar 2010 11:02:54 +0100 Subject: remove the CVSish $Id$ lines --- lib/parsedate.c | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index b846501c1..8e26f1c7e 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -18,7 +18,6 @@ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * - * $Id$ ***************************************************************************/ /* A brief summary of the date string formats this parser groks: -- cgit v1.2.1 From b7848e4a7272e5319cf5794ec59ecaa955642e1c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 17 Apr 2010 18:57:39 +0200 Subject: parsedate: Value stored to 'found' is never read --- lib/parsedate.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 8e26f1c7e..26f7d84ce 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -370,7 +370,6 @@ int Curl_parsedate(const char *date, time_t *output) (3 == sscanf(date, "%02d:%02d:%02d", &hournum, &minnum, &secnum))) { /* time stamp! */ date += 8; - found = TRUE; } else { val = (int)strtol(date, &end, 10); -- cgit v1.2.1 From 4d58f97f604bfef5b2cb7538f9bbc925c141622f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 27 Sep 2010 16:54:02 +0200 Subject: parsedate: allow time specified without seconds The date format in RFC822 allows that the seconds part of HH:MM:SS is left out, but this function didn't allow it. This change also includes a modified test case that makes sure that this now works. Reported by: Matt Ford Bug: http://curl.haxx.se/bug/view.cgi?id=3076529 --- lib/parsedate.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 26f7d84ce..5d8af2692 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -371,6 +371,12 @@ int Curl_parsedate(const char *date, time_t *output) /* time stamp! */ date += 8; } + else if((secnum == -1) && + (2 == sscanf(date, "%02d:%02d", &hournum, &minnum))) { + /* time stamp without seconds */ + date += 5; + secnum = 0; + } else { val = (int)strtol(date, &end, 10); -- cgit v1.2.1 From 7e3f0bffe5d930489db80e1d65c27fe44a51f6f4 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 1 Dec 2010 23:33:43 +0100 Subject: fix compiler warning: conversion may lose significant bits --- lib/parsedate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 5d8af2692..3e003db31 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -83,6 +83,7 @@ #include #include "rawstr.h" +#include "warnless.h" #include "parsedate.h" const char * const Curl_wkday[] = @@ -378,7 +379,7 @@ int Curl_parsedate(const char *date, time_t *output) secnum = 0; } else { - val = (int)strtol(date, &end, 10); + val = curlx_sltosi(strtol(date, &end, 10)); if((tzoff == -1) && ((end - date) == 4) && -- cgit v1.2.1 From 54d9f060b4b0a8fb5fa006813e4db1ca5c1a07e8 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 7 Feb 2011 15:00:48 +0100 Subject: Curl_gmtime: added a portable gmtime Instead of polluting many places with #ifdefs, we create a single place for this function, and also check return code properly so that a NULL pointer returned won't cause problems. --- lib/parsedate.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 3e003db31..ea1f36e73 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -514,3 +514,20 @@ time_t curl_getdate(const char *p, const time_t *now) /* everything else is fail */ return -1; } + +CURLcode Curl_gmtime(time_t intime, struct tm *store) +{ + const struct tm *tm; +#ifdef HAVE_GMTIME_R + /* thread-safe version */ + tm = (struct tm *)(gmtime_r)(&intime, store); +#else + tm = (gmtime)(&intime); + if(tm) + *store = *tm; /* copy the pointed struct to the local copy */ +#endif + + if(!tm) + return CURLE_BAD_FUNCTION_ARGUMENT; + return CURLE_OK; +} -- cgit v1.2.1 From 0696260122f1ebdf43bcc926b03bfd58bff318e3 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 7 Feb 2011 15:09:24 +0100 Subject: Curl_gmtime: avoid future mistakes Document Curl_gmtime() and define away the old functions so that they won't be used internally again by mistake. --- lib/parsedate.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index ea1f36e73..1d7f035f2 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -515,6 +515,15 @@ time_t curl_getdate(const char *p, const time_t *now) return -1; } +/* + * Curl_gmtime() is a gmtime() replacement for portability. Do not use the + * gmtime_r() or gmtime() functions anywhere else but here. + * + * To make sure no such function calls slip in, we define them to cause build + * errors, which is why we use the name within parentheses in this function. + * + */ + CURLcode Curl_gmtime(time_t intime, struct tm *store) { const struct tm *tm; -- cgit v1.2.1 From f19ace8d33e468969d3329e6bb17d6c032147e91 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 14 Feb 2011 13:42:01 +0100 Subject: gmtime: remove define It turns out some systems rely on the gmtime or gmtime_r to be defined already in the system headers and thus my "precaution" redefining of them only caused trouble. They are now removed. --- lib/parsedate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 1d7f035f2..1e9381c7d 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -529,9 +529,9 @@ CURLcode Curl_gmtime(time_t intime, struct tm *store) const struct tm *tm; #ifdef HAVE_GMTIME_R /* thread-safe version */ - tm = (struct tm *)(gmtime_r)(&intime, store); + tm = (struct tm *)gmtime_r(&intime, store); #else - tm = (gmtime)(&intime); + tm = gmtime(&intime); if(tm) *store = *tm; /* copy the pointed struct to the local copy */ #endif -- cgit v1.2.1 From 1702a2c08d3a0ed5945f34e6cd38436611f65164 Mon Sep 17 00:00:00 2001 From: Fabian Keil Date: Tue, 19 Apr 2011 15:54:13 +0200 Subject: Fix a couple of spelling errors in lib/ Found with codespell. --- lib/parsedate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 1e9381c7d..298481701 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -387,7 +387,7 @@ int Curl_parsedate(const char *date, time_t *output) (indate< date) && ((date[-1] == '+' || date[-1] == '-'))) { /* four digits and a value less than or equal to 1400 (to take into - account all sorts of funny time zone diffs) and it is preceeded + account all sorts of funny time zone diffs) and it is preceded with a plus or minus. This is a time zone indication. 1400 is picked since +1300 is frequently used and +1400 is mentioned as an edge number in the document "ISO C 200X Proposal: Timezone -- cgit v1.2.1 From b903186fa0189ff241d756d25d07fdfe9885ae49 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 20 Apr 2011 15:17:42 +0200 Subject: source cleanup: unify look, style and indent levels By the use of a the new lib/checksrc.pl script that checks that our basic source style rules are followed. --- lib/parsedate.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 298481701..60a584530 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -160,7 +160,8 @@ static const struct tzinfo tz[]= { {"G", +7 * 60}, /* Golf */ {"H", +8 * 60}, /* Hotel */ {"I", +9 * 60}, /* India */ - /* "J", Juliet is not used as a timezone, to indicate the observer's local time */ + /* "J", Juliet is not used as a timezone, to indicate the observer's local + time */ {"K", +10 * 60}, /* Kilo */ {"L", +11 * 60}, /* Lima */ {"M", +12 * 60}, /* Mike */ @@ -282,11 +283,11 @@ static time_t my_timegm(struct my_tm *tm) year = tm->tm_year + 1900; month = tm->tm_mon; - if (month < 0) { + if(month < 0) { year += (11 - month) / 12; month = 11 - (11 - month) % 12; } - else if (month >= 12) { + else if(month >= 12) { year -= month / 12; month = month % 12; } -- cgit v1.2.1 From a6f14e17b747893295bd6805abcaeb3e9b3217e0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 3 Jun 2011 19:31:32 +0200 Subject: parsedate: turn private and static I removed the prefix as well accordingly. --- lib/parsedate.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 60a584530..6865f8e40 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -100,6 +100,24 @@ struct tzinfo { int offset; /* +/- in minutes */ }; +/* + * parsedate() + * + * Returns: + * + * PARSEDATE_OK - a fine conversion + * PARSEDATE_FAIL - failed to convert + * PARSEDATE_LATER - time overflow at the far end of time_t + * PARSEDATE_SOONER - time underflow at the low end of time_t + */ + +static int parsedate(const char *date, time_t *output); + +#define PARSEDATE_OK 0 +#define PARSEDATE_FAIL -1 +#define PARSEDATE_LATER 1 +#define PARSEDATE_SOONER 2 + /* Here's a bunch of frequently used time zone names. These were supported by the old getdate parser. */ #define tDAYZONE -60 /* offset for daylight savings time */ @@ -302,7 +320,7 @@ static time_t my_timegm(struct my_tm *tm) } /* - * Curl_parsedate() + * parsedate() * * Returns: * @@ -312,7 +330,7 @@ static time_t my_timegm(struct my_tm *tm) * PARSEDATE_SOONER - time underflow at the low end of time_t */ -int Curl_parsedate(const char *date, time_t *output) +static int parsedate(const char *date, time_t *output) { time_t t = 0; int wdaynum=-1; /* day of the week number, 0-6 (mon-sun) */ @@ -503,7 +521,7 @@ int Curl_parsedate(const char *date, time_t *output) time_t curl_getdate(const char *p, const time_t *now) { time_t parsed; - int rc = Curl_parsedate(p, &parsed); + int rc = parsedate(p, &parsed); (void)now; /* legacy argument from the past that we ignore */ switch(rc) { -- cgit v1.2.1 From 57d51be60c0bb299a30ae5b4c66d9a7113e7586b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 21 Jun 2011 23:18:05 +0200 Subject: parsedate: detect more invalid dates better --- lib/parsedate.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 6865f8e40..62f1a4181 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -485,6 +485,10 @@ static int parsedate(const char *date, time_t *output) return PARSEDATE_SOONER; } + if((mdaynum > 31) || (monnum > 11) || + (hournum > 23) || (minnum > 59) || (secnum > 60)) + return PARSEDATE_FAIL; /* clearly an illegal date */ + tm.tm_sec = secnum; tm.tm_min = minnum; tm.tm_hour = hournum; -- cgit v1.2.1 From f1586cb4775681810afd8e6626e7842d459f3b85 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 26 Jul 2011 17:23:27 +0200 Subject: stdio.h, stdlib.h, string.h, stdarg.h and ctype.h inclusion done in setup_once.h --- lib/parsedate.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index 62f1a4181..ec60e78e7 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -72,14 +72,8 @@ 20040911 +0200 */ -#include "setup.h" -#include -#include -#include -#ifdef HAVE_STDLIB_H -#include /* for strtol() */ -#endif +#include "setup.h" #include #include "rawstr.h" -- cgit v1.2.1 From e8a32438c24f2e67944666ff22dbbba829ccaf2a Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 22 Mar 2012 15:53:03 +0100 Subject: parsedate.c: fix a numeric overflow --- lib/parsedate.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'lib/parsedate.c') diff --git a/lib/parsedate.c b/lib/parsedate.c index ec60e78e7..b6079bc8f 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -75,6 +75,10 @@ #include "setup.h" +#ifdef HAVE_LIMITS_H +#include +#endif + #include #include "rawstr.h" #include "warnless.h" @@ -392,7 +396,24 @@ static int parsedate(const char *date, time_t *output) secnum = 0; } else { - val = curlx_sltosi(strtol(date, &end, 10)); + long lval; + int error; + int old_errno; + + old_errno = ERRNO; + SET_ERRNO(0); + lval = strtol(date, &end, 10); + error = ERRNO; + if(error != old_errno) + SET_ERRNO(old_errno); + + if(error) + return PARSEDATE_FAIL; + + if((lval > (long)INT_MAX) || (lval < (long)INT_MIN)) + return PARSEDATE_FAIL; + + val = curlx_sltosi(lval); if((tzoff == -1) && ((end - date) == 4) && -- cgit v1.2.1