Mercurial > dillo_port1.3
changeset 1608:5f8f8ce7a913
use tm when parsing date string
author | corvid <corvid@lavabit.com> |
---|---|
date | Wed, 10 Mar 2010 02:01:49 +0000 |
parents | 7dc68ea220cb |
children | afbbdad5f64a |
files | dpi/cookies.c |
diffstat | 1 files changed, 62 insertions(+), 58 deletions(-) [+] |
line wrap: on
line diff
--- a/dpi/cookies.c Wed Mar 10 00:28:04 2010 +0000 +++ b/dpi/cookies.c Wed Mar 10 02:01:49 2010 +0000 @@ -417,21 +417,20 @@ } /* - * Take a months name and return a number between 1-12. - * E.g. 'April' -> 4 + * Take a month's name and return a number between 0-11. + * E.g. 'April' -> 3 */ static int Cookies_get_month(const char *month_name) { static const char *const months[] = - { "", - "Jan", "Feb", "Mar", + { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; int i; - for (i = 1; i <= 12; i++) { + for (i = 0; i < 12; i++) { if (!dStrncasecmp(months[i], month_name, 3)) return i; } @@ -439,8 +438,7 @@ } /* - * Return a local timestamp from a GMT date string - * Accept: RFC-1123 | RFC-850 | ANSI asctime | Old Netscape format. + * Accept: RFC-1123 | RFC-850 | ANSI asctime | Old Netscape format date string. * * Wdy, DD-Mon-YY HH:MM:SS GMT * Wdy, DD-Mon-YYYY HH:MM:SS GMT @@ -452,7 +450,7 @@ * Let's add: * Mon Jan 11 08:00:00 2010 GMT * - * (return 0 on malformed date string syntax) + * Return a pointer to a struct tm, or NULL on error. * * NOTE that the draft spec wants user agents to be more flexible in what * they accept. For now, let's hack in special cases when they're encountered. @@ -460,71 +458,76 @@ * abandon that (or at best decrease that -- see section 5.1.1) until there * is known to be good reason. */ -static time_t Cookies_create_timestamp(const char *expires) +static struct tm *Cookies_parse_date(const char *date) { - time_t ret; - int day, month, year, hour, minutes, seconds; - char *cp; - const char *const E_msg = - "Expire date is malformed!\n" - " (should be RFC-1123 | RFC-850 | ANSI asctime)\n" - " Discarding cookie: "; + struct tm *tm; + char *cp = strchr(date, ','); - cp = strchr(expires, ','); - if (!cp && strlen(expires)>20 && expires[13] == ':' && expires[16] == ':') { + if (!cp && strlen(date)>20 && date[13] == ':' && date[16] == ':') { /* Looks like ANSI asctime format... */ - cp = (char *)expires; - day = strtol(cp + 8, NULL, 10); /* day */ - month = Cookies_get_month(cp + 4); /* month */ - year = strtol(cp + 20, NULL, 10); /* year */ - hour = strtol(cp + 11, NULL, 10); /* hour */ - minutes = strtol(cp + 14, NULL, 10); /* minutes */ - seconds = strtol(cp + 17, NULL, 10); /* seconds */ + tm = dNew0(struct tm, 1); - } else if (cp && (cp - expires == 3 || cp - expires > 5) && + cp = (char *)date; + tm->tm_mon = Cookies_get_month(cp + 4); + tm->tm_mday = strtol(cp + 8, NULL, 10); + tm->tm_hour = strtol(cp + 11, NULL, 10); + tm->tm_min = strtol(cp + 14, NULL, 10); + tm->tm_sec = strtol(cp + 17, NULL, 10); + tm->tm_year = strtol(cp + 20, NULL, 10) - 1900; + + } else if (cp && (cp - date == 3 || cp - date > 5) && (strlen(cp) == 24 || strlen(cp) == 26)) { /* RFC-1123 | RFC-850 format | Old Netscape format */ - day = strtol(cp + 2, NULL, 10); - month = Cookies_get_month(cp + 5); - year = strtol(cp + 9, &cp, 10); - /* TODO: tricky, because two digits for year IS ambiguous! */ - year += (year < 70) ? 2000 : ((year < 100) ? 1900 : 0); - hour = strtol(cp + 1, NULL, 10); - minutes = strtol(cp + 4, NULL, 10); - seconds = strtol(cp + 7, NULL, 10); + tm = dNew0(struct tm, 1); + + tm->tm_mday = strtol(cp + 2, NULL, 10); + tm->tm_mon = Cookies_get_month(cp + 5); + tm->tm_year = strtol(cp + 9, &cp, 10); + /* tm_year is the number of years since 1900 */ + if (tm->tm_year < 70) + tm->tm_year += 100; + else if (tm->tm_year > 100) + tm->tm_year -= 1900; + tm->tm_hour = strtol(cp + 1, NULL, 10); + tm->tm_min = strtol(cp + 4, NULL, 10); + tm->tm_sec = strtol(cp + 7, NULL, 10); } else { - MSG("%s%s\n", E_msg, expires); - return (time_t) 0; + tm = NULL; + MSG("In date \"%s\", format not understood.\n", date); } - /* Error checks --this may be overkill */ - if (!(day > 0 && day < 32 && month > 0 && month < 13 && year >= 1970 && - hour >= 0 && hour < 24 && minutes >= 0 && minutes < 60 && - seconds >= 0 && seconds < 60)) { - MSG("%s%s\n", E_msg, expires); - return (time_t) 0; + /* Error checks. This may be overkill. */ + if (tm && + !(tm->tm_mday > 0 && tm->tm_mday < 32 && tm->tm_mon >= 0 && + tm->tm_mon < 12 && tm->tm_year >= 70 && tm->tm_hour >= 0 && + tm->tm_hour < 24 && tm->tm_min >= 0 && tm->tm_min < 60 && + tm->tm_sec >= 0 && tm->tm_sec < 60)) { + MSG("Date \"%s\" values not in range.\n", date); + dFree(tm); + tm = NULL; } - /* Calculate local timestamp. - * [stolen from Lynx... (http://lynx.browser.org)] */ - month -= 3; - if (month < 0) { - month += 12; - year--; - } + return tm; +} - day += (year - 1968) * 1461 / 4; - day += ((((month * 153) + 2) / 5) - 672); - ret = (time_t)((day * 60 * 60 * 24) + - (hour * 60 * 60) + - (minutes * 60) + - seconds); +static time_t Cookies_create_timestamp(const char *date) +{ + time_t ret = 0; + struct tm *tm = Cookies_parse_date(date); - /* handle overflow */ - if (year >= 1970 && ret < 0) - ret = DILLO_TIME_MAX; + if (tm) { + ret = mktime(tm); + if (ret == (time_t) -1) { + ret = 0; + if (tm->tm_year >= 138) { + /* Make the guess that it simply couldn't be represented */ + ret = cookies_future_time; + } + } + dFree(tm); + } return ret; } @@ -676,6 +679,7 @@ value++; } exptime = Cookies_create_timestamp(value); + MSG("expires attr \"%s\" represented as %s", value, ctime(&exptime)); if (exptime && server_date) { time_t server_time = Cookies_create_timestamp(server_date);