diff --git a/ChangeLog b/ChangeLog index 90db5e13..3569e075 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2008-11-05 Tatsuhiro Tsujikawa + + Handle date before epoch. + To create *bad* Time object, call Time::null(). + * src/CookieParser.cc + * src/FtpConnection.cc + * src/FtpConnection.h + * src/FtpNegotiationCommand.cc + * src/RequestGroup.cc + * src/TimeA2.cc + * src/TimeA2.h + * test/CookieParserTest.cc + * test/FtpConnectionTest.cc + * test/TimeTest.cc + 2008-11-04 Tatsuhiro Tsujikawa Added support for following envrionment variables: http_proxy, diff --git a/src/CookieParser.cc b/src/CookieParser.cc index d009ad38..0f49f6e5 100644 --- a/src/CookieParser.cc +++ b/src/CookieParser.cc @@ -33,14 +33,17 @@ */ /* copyright --> */ #include "CookieParser.h" -#include "Util.h" -#include "A2STR.h" -#include "TimeA2.h" + #include + #include #include #include +#include "Util.h" +#include "A2STR.h" +#include "TimeA2.h" + namespace aria2 { const std::string CookieParser::C_SECURE("secure"); @@ -76,20 +79,17 @@ Cookie CookieParser::parse(const std::string& cookieStr, const std::string& defa Util::split(nv, *itr, '='); values[nv.first] = nv.second; } - time_t expiry = -1; + time_t expiry = 0; if(values.find(C_EXPIRES) != values.end()) { - expiry = Time::parseHTTPDate(values[C_EXPIRES]).getTime(); - } - if(expiry == -1) { - return Cookie(nameValue.first, nameValue.second, - values[C_PATH], values[C_DOMAIN], - values.find(C_SECURE) != values.end()); - } else { - return Cookie(nameValue.first, nameValue.second, - expiry, - values[C_PATH], values[C_DOMAIN], - values.find(C_SECURE) != values.end()); + Time expiryTime = Time::parseHTTPDate(values[C_EXPIRES]); + if(expiryTime.good()) { + expiry = expiryTime.getTime(); + } } + return Cookie(nameValue.first, nameValue.second, + expiry, + values[C_PATH], values[C_DOMAIN], + values.find(C_SECURE) != values.end()); } diff --git a/src/FtpConnection.cc b/src/FtpConnection.cc index 916c3dfa..60f24db3 100644 --- a/src/FtpConnection.cc +++ b/src/FtpConnection.cc @@ -369,7 +369,7 @@ unsigned int FtpConnection::receiveMdtmResponse(Time& time) if(strlen(buf) == 14) { time = Time::parse(buf, "%Y%m%d%H%M%S"); } else { - time.setTimeInSec(-1); + time = Time::null(); } } return response.first; diff --git a/src/FtpConnection.h b/src/FtpConnection.h index 17eeb52e..bc8395ec 100644 --- a/src/FtpConnection.h +++ b/src/FtpConnection.h @@ -105,7 +105,7 @@ public: // time-val and store it in time. // If a code other than 213 is returned, time is not touched. // Expect MDTM reply is YYYYMMDDhhmmss in GMT. If status is 213 but returned - // date cannot be parsed, then executes time.setTimeInSec(-1). + // date cannot be parsed, then assign Time::null() to given time. // If reply is not received yet, returns 0. unsigned int receiveMdtmResponse(Time& time); unsigned int receivePasvResponse(std::pair& dest); diff --git a/src/FtpNegotiationCommand.cc b/src/FtpNegotiationCommand.cc index 39f84c67..e2c48936 100644 --- a/src/FtpNegotiationCommand.cc +++ b/src/FtpNegotiationCommand.cc @@ -283,7 +283,7 @@ bool FtpNegotiationCommand::sendMdtm() bool FtpNegotiationCommand::recvMdtm() { - Time lastModifiedTime(-1); + Time lastModifiedTime = Time::null(); unsigned int status = ftp->receiveMdtmResponse(lastModifiedTime); if(status == 0) { return false; diff --git a/src/RequestGroup.cc b/src/RequestGroup.cc index df2cfca7..4db4f21a 100644 --- a/src/RequestGroup.cc +++ b/src/RequestGroup.cc @@ -123,7 +123,7 @@ RequestGroup::RequestGroup(const Option* option, _forceHaltRequested(false), _singleHostMultiConnectionEnabled(true), _uriSelector(new InOrderURISelector()), - _lastModifiedTime(-1), + _lastModifiedTime(Time::null()), _fileNotFoundCount(0), _option(option), _logger(LogFactory::getInstance()) diff --git a/src/TimeA2.cc b/src/TimeA2.cc index cf83cf07..8ffddc80 100644 --- a/src/TimeA2.cc +++ b/src/TimeA2.cc @@ -42,19 +42,24 @@ namespace aria2 { -Time::Time() { +Time::Time():_good(true) +{ reset(); } -Time::Time(const Time& time) { +Time::Time(const Time& time) +{ tv = time.tv; + _good = time._good; } -Time::Time(time_t sec) { +Time::Time(time_t sec):_good(true) +{ setTimeInSec(sec); } -Time::Time(const struct timeval& tv) { +Time::Time(const struct timeval& tv):_good(true) +{ this->tv = tv; } @@ -64,6 +69,7 @@ Time& Time::operator=(const Time& time) { if(this != &time) { tv = time.tv; + _good = time._good; } return *this; } @@ -152,7 +158,12 @@ void Time::setTimeInSec(time_t sec) { bool Time::good() const { - return tv.tv_sec >= 0; + return _good; +} + +bool Time::bad() const +{ + return !_good; } Time Time::parse(const std::string& datetime, const std::string& format) @@ -161,7 +172,7 @@ Time Time::parse(const std::string& datetime, const std::string& format) memset(&tm, 0, sizeof(tm)); char* r = strptime(datetime.c_str(), format.c_str(), &tm); if(r != datetime.c_str()+datetime.size()) { - return Time(-1); + return Time::null(); } time_t thetime = timegm(&tm); if(thetime == -1) { @@ -190,9 +201,9 @@ Time Time::parseRFC850Ext(const std::string& datetime) Time Time::parseHTTPDate(const std::string& datetime) { Time (*funcs[])(const std::string&) = { + &parseRFC850, &parseRFC1123, &parseRFC850Ext, - &parseRFC850, }; for(Time (**funcsp)(const std::string&) = &funcs[0]; funcsp != &funcs[arrayLength(funcs)]; ++funcsp) { @@ -201,7 +212,14 @@ Time Time::parseHTTPDate(const std::string& datetime) return t; } } - return Time(-1); + return Time::null(); +} + +Time Time::null() +{ + Time t(0); + t._good = false; + return t; } } // namespace aria2 diff --git a/src/TimeA2.h b/src/TimeA2.h index f2e27591..7b9c5478 100644 --- a/src/TimeA2.h +++ b/src/TimeA2.h @@ -49,6 +49,8 @@ class Time { private: struct timeval tv; + bool _good; + struct timeval getCurrentTime() const; public: // The time value is initialized so that it represents the time at which @@ -95,6 +97,9 @@ public: bool good() const; + // Returns !good() + bool bad() const; + // Currently timezone is assumed as GMT. static Time parse(const std::string& datetime, const std::string& format); @@ -111,6 +116,8 @@ public: // Try parseRFC1123, parseRFC850Ex, parseRFC850 in that order and returns // the first "good" Time object returned by these functions. static Time parseHTTPDate(const std::string& datetime); + + static Time null(); }; } // namespace aria2 diff --git a/test/CookieParserTest.cc b/test/CookieParserTest.cc index 2f39f1fa..44c51383 100644 --- a/test/CookieParserTest.cc +++ b/test/CookieParserTest.cc @@ -52,10 +52,11 @@ void CookieParserTest::testParse() c = CookieParser().parse(str3); CPPUNIT_ASSERT(!c.good()); - std::string str4 = "UID=300; expires=Wed, 01-Jan-1890 00:00:00 GMT;"; + std::string str4 = "UID=300; expires=Wed, 01-Jan-1890 00:00:00 GMT"; c = CookieParser().parse(str4, "localhost", "/"); CPPUNIT_ASSERT(c.good()); - CPPUNIT_ASSERT(c.isSessionCookie()); + CPPUNIT_ASSERT(!c.isSessionCookie()); + CPPUNIT_ASSERT_EQUAL((time_t)-2524521600, c.getExpiry()); std::string str5 = "k=v; expires=Sun, 10-Jun-07 11:00:00 GMT"; c = CookieParser().parse(str5); diff --git a/test/FtpConnectionTest.cc b/test/FtpConnectionTest.cc index 2a4e4812..6fb9699b 100644 --- a/test/FtpConnectionTest.cc +++ b/test/FtpConnectionTest.cc @@ -149,14 +149,14 @@ void FtpConnectionTest::testReceiveMdtmResponse() Time t; _serverSocket->writeData("213 20080908\r\n"); CPPUNIT_ASSERT_EQUAL((unsigned int)213, _ftp->receiveMdtmResponse(t)); - CPPUNIT_ASSERT_EQUAL((time_t)-1, t.getTime()); + CPPUNIT_ASSERT(t.bad()); } { // invalid month: 19 Time t; _serverSocket->writeData("213 20081908124312\r\n"); CPPUNIT_ASSERT_EQUAL((unsigned int)213, _ftp->receiveMdtmResponse(t)); - CPPUNIT_ASSERT_EQUAL((time_t)-1, t.getTime()); + CPPUNIT_ASSERT(t.bad()); } { Time t; diff --git a/test/TimeTest.cc b/test/TimeTest.cc index 4b55e239..b51e7ce5 100644 --- a/test/TimeTest.cc +++ b/test/TimeTest.cc @@ -64,9 +64,8 @@ void TimeTest::testParseHTTPDate() CPPUNIT_ASSERT_EQUAL((time_t)1220714793, Time::parseHTTPDate ("Sat, 06-Sep-08 15:26:33 GMT").getTime()); - CPPUNIT_ASSERT_EQUAL((time_t)-1, - Time::parseHTTPDate - ("Sat, 2008-09-06 15:26:33 GMT").getTime()); + CPPUNIT_ASSERT(Time::parseHTTPDate + ("Sat, 2008-09-06 15:26:33 GMT").bad()); } void TimeTest::testOperatorLess()