diff options
Diffstat (limited to 'lib/parsedate.c')
-rw-r--r-- | lib/parsedate.c | 94 |
1 files changed, 79 insertions, 15 deletions
diff --git a/lib/parsedate.c b/lib/parsedate.c index 3e003db31..1ddd0080a 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -72,13 +72,11 @@ 20040911 +0200 */ -#include "setup.h" -#include <stdio.h> -#include <ctype.h> -#include <string.h> -#ifdef HAVE_STDLIB_H -#include <stdlib.h> /* for strtol() */ +#include "curl_setup.h" + +#ifdef HAVE_LIMITS_H +#include <limits.h> #endif #include <curl/curl.h> @@ -100,6 +98,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 */ @@ -160,7 +176,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 +299,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; } @@ -301,7 +318,7 @@ static time_t my_timegm(struct my_tm *tm) } /* - * Curl_parsedate() + * parsedate() * * Returns: * @@ -311,7 +328,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) */ @@ -379,7 +396,24 @@ int Curl_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) && @@ -387,7 +421,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 @@ -466,6 +500,10 @@ int Curl_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; @@ -502,7 +540,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) { @@ -514,3 +552,29 @@ time_t curl_getdate(const char *p, const time_t *now) /* everything else is fail */ 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; +#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; +} |