Skip to content

Commit

Permalink
Better handling of parse errors in HttpTime
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
pulkomandy committed Jun 6, 2014
1 parent 6ac7ba8 commit fed9b96
Showing 1 changed file with 34 additions and 39 deletions.
73 changes: 34 additions & 39 deletions src/kits/network/libnetapi/HttpTime.cpp
Expand Up @@ -13,11 +13,12 @@
#include <cstdio>


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;

Expand Down Expand Up @@ -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);
Expand All @@ -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;
}

0 comments on commit fed9b96

Please sign in to comment.