From fed9b96e2633fb81f3e02a5c0182223947daeab7 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Fri, 6 Jun 2014 16:49:11 +0200 Subject: [PATCH] Better handling of parse errors in HttpTime strptime can return non-NULL values even if it only parsed part of the string. This was sometimes making us use the wrong format. Now we try all formats and checks how much of the string strptime managed to parse. We stop when it has parsed a big enough part of it. --- src/kits/network/libnetapi/HttpTime.cpp | 73 ++++++++++++------------- 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/src/kits/network/libnetapi/HttpTime.cpp b/src/kits/network/libnetapi/HttpTime.cpp index ada98514fd6..e5f933a63c4 100644 --- a/src/kits/network/libnetapi/HttpTime.cpp +++ b/src/kits/network/libnetapi/HttpTime.cpp @@ -13,11 +13,12 @@ #include -static const char* kRfc1123Format = "%a, %d %b %Y %H:%M:%S GMT"; -static const char* kCookieFormat = "%a, %d-%b-%Y %H:%M:%S GMT"; -static const char* kRfc1036Format = "%A, %d-%b-%y %H:%M:%S GMT"; -static const char* kAscTimeFormat = "%a %d %b %H:%M:%S %Y"; -static const uint16 kTimetToStringMaxLength = 128; +static const char* kDateFormats[] = { + "%a, %d %b %Y %H:%M:%S GMT", + "%a, %d-%b-%Y %H:%M:%S GMT", + "%A, %d-%b-%y %H:%M:%S GMT", + "%a %d %b %H:%M:%S %Y" +}; using namespace BPrivate; @@ -84,22 +85,25 @@ BHttpTime::Parse() expireTime.tm_wday = 0; expireTime.tm_yday = 0; expireTime.tm_isdst = 0; - - if (fDateString[3] == ',') { - if (strptime(fDateString.String(), kRfc1123Format, &expireTime) - == NULL) { - strptime(fDateString.String(), kCookieFormat, &expireTime); - fDateFormat = B_HTTP_TIME_FORMAT_COOKIE; - } else - fDateFormat = B_HTTP_TIME_FORMAT_RFC1123; - } else if (fDateString[3] == ' ') { - strptime(fDateString.String(), kRfc1036Format, &expireTime); - fDateFormat = B_HTTP_TIME_FORMAT_RFC1036; - } else { - strptime(fDateString.String(), kAscTimeFormat, &expireTime); - fDateFormat = B_HTTP_TIME_FORMAT_ASCTIME; + + fDateFormat = B_HTTP_TIME_FORMAT_PARSED; + unsigned int i; + for (i = 0; i < sizeof(kDateFormats) / sizeof(const char*); + i++) { + const char* result = strptime(fDateString.String(), kDateFormats[i], + &expireTime); + + // Make sure we parsed enough of the date string, not just a small + // part of it. + if (result != NULL && result > fDateString.String() + 24) { + fDateFormat = i; + break; + } } + if (fDateFormat == B_HTTP_TIME_FORMAT_PARSED) + return 0; + BTime time(expireTime.tm_hour, expireTime.tm_min, expireTime.tm_sec); BDate date(expireTime.tm_year + 1900, expireTime.tm_mon + 1, expireTime.tm_mday); @@ -123,27 +127,18 @@ BHttpTime::ToString(int8 format) expirationTm.tm_yday = 0; expirationTm.tm_isdst = 0; - char expirationString[kTimetToStringMaxLength + 1]; - size_t strLength; + if (format == B_HTTP_TIME_FORMAT_PARSED) + format = fDateFormat; + + if (format != B_HTTP_TIME_FORMAT_PARSED) { + static const uint16 kTimetToStringMaxLength = 128; + char expirationString[kTimetToStringMaxLength + 1]; + size_t strLength; - switch ((format == B_HTTP_TIME_FORMAT_PARSED)?fDateFormat:format) { - default: - case B_HTTP_TIME_FORMAT_RFC1123: - strLength = strftime(expirationString, kTimetToStringMaxLength, - kRfc1123Format, &expirationTm); - break; - - case B_HTTP_TIME_FORMAT_RFC1036: - strLength = strftime(expirationString, kTimetToStringMaxLength, - kRfc1036Format, &expirationTm); - break; - - case B_HTTP_TIME_FORMAT_ASCTIME: - strLength = strftime(expirationString, kTimetToStringMaxLength, - kAscTimeFormat, &expirationTm); - break; - } + strLength = strftime(expirationString, kTimetToStringMaxLength, + kDateFormats[format], &expirationTm); - expirationFinal.SetTo(expirationString, strLength); + expirationFinal.SetTo(expirationString, strLength); + } return expirationFinal; }