diff --git a/ChangeLog b/ChangeLog index ef3e2119..f722cafa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2010-10-10 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net> + + Retrieve last access time from sqlite3 cookie database. + * src/CookieStorage.cc + * src/Sqlite3CookieParser.cc + * src/Sqlite3CookieParser.h + * src/Sqlite3CookieParserImpl.cc + * test/Sqlite3CookieParserTest.cc + * test/chromium_cookies.sqlite + * test/cookies.sqlite + 2010-10-10 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net> Remove expired cookies first when cookies_ is full. diff --git a/src/CookieStorage.cc b/src/CookieStorage.cc index b8b3bdb1..a4875267 100644 --- a/src/CookieStorage.cc +++ b/src/CookieStorage.cc @@ -308,7 +308,7 @@ bool CookieStorage::load(const std::string& filename, time_t now) #ifdef HAVE_SQLITE3 std::vector<Cookie> cookies; try { - Sqlite3MozCookieParser(filename).parse(cookies, now); + Sqlite3MozCookieParser(filename).parse(cookies); } catch(RecoverableException& e) { if(logger_->info()) { logger_->info(EX_EXCEPTION_CAUGHT, e); @@ -316,7 +316,7 @@ bool CookieStorage::load(const std::string& filename, time_t now) " Retrying, assuming it is Chromium cookie file."); } // Try chrome cookie format - Sqlite3ChromiumCookieParser(filename).parse(cookies, now); + Sqlite3ChromiumCookieParser(filename).parse(cookies); } storeCookies(cookies.begin(), cookies.end(), now); #else // !HAVE_SQLITE3 diff --git a/src/Sqlite3CookieParser.cc b/src/Sqlite3CookieParser.cc index 81525f8a..088ff99a 100644 --- a/src/Sqlite3CookieParser.cc +++ b/src/Sqlite3CookieParser.cc @@ -78,9 +78,23 @@ static std::string toString(const char* str) } } -static int cookieRowMapper(void* data, int rowIndex, +static bool parseTime(int64_t& time, const std::string& s) +{ + if(!util::parseLLIntNoThrow(time, s)) { + return false; + } + if(sizeof(time_t) == 4 && time > INT32_MAX) { + time = INT32_MAX; + } + return true; +} + +static int cookieRowMapper(void* data, int columns, char** values, char** names) { + if(columns != 7) { + return 0; + } std::vector<Cookie>& cookies = *reinterpret_cast<std::vector<Cookie>*>(data); std::string cookieDomain = cookie::removePrecedingDots(toString(values[0])); @@ -91,13 +105,13 @@ static int cookieRowMapper(void* data, int rowIndex, return 0; } int64_t expiryTime; - if(!util::parseLLIntNoThrow(expiryTime, toString(values[3]))) { + if(!parseTime(expiryTime, toString(values[3]))) { return 0; } - if(sizeof(time_t) == 4 && expiryTime > INT32_MAX) { - expiryTime = INT32_MAX; + int64_t lastAccessTime; + if(!parseTime(lastAccessTime, toString(values[6]))) { + return 0; } - // TODO get last access, creation date(chrome only) Cookie c(cookieName, toString(values[5]), // value expiryTime, @@ -107,14 +121,13 @@ static int cookieRowMapper(void* data, int rowIndex, cookiePath, strcmp(toString(values[2]).c_str(), "1") == 0, //secure false, - 0 // creation time. Set this later. + lastAccessTime // creation time. Set this later. ); cookies.push_back(c); return 0; } -void Sqlite3CookieParser::parse -(std::vector<Cookie>& cookies, time_t creationTime) +void Sqlite3CookieParser::parse(std::vector<Cookie>& cookies) { if(!db_) { throw DL_ABORT_EX(StringFormat("SQLite3 database is not opened.").str()); @@ -123,13 +136,6 @@ void Sqlite3CookieParser::parse char* sqlite3ErrMsg = 0; int ret = sqlite3_exec(db_, getQuery().c_str(), cookieRowMapper, &tcookies, &sqlite3ErrMsg); - // TODO If last access, creation date are retrieved from database, - // following for loop must be removed. - for(std::vector<Cookie>::iterator i = tcookies.begin(), eoi = tcookies.end(); - i != eoi; ++i) { - (*i).setCreationTime(creationTime); - (*i).setLastAccessTime(creationTime); - } std::string errMsg; if(sqlite3ErrMsg) { errMsg = sqlite3ErrMsg; diff --git a/src/Sqlite3CookieParser.h b/src/Sqlite3CookieParser.h index ecf55521..e8679294 100644 --- a/src/Sqlite3CookieParser.h +++ b/src/Sqlite3CookieParser.h @@ -55,12 +55,12 @@ public: // Loads cookies from sqlite3 database and stores them in cookies. // When loading is successful, cookies stored in cookies initially // are removed. Otherwise, the content of cookies is unchanged. - void parse(std::vector<Cookie>& cookies, time_t creationTime); + void parse(std::vector<Cookie>& cookies); protected: // Returns SQL select statement to get 1 record of cookie. The sql // must return 6 columns in the following order: host, path, // secure(1 for secure, 0 for not), expiry(utc, unix time), name, - // value + // value, last access time(utc, unix time) virtual const std::string& getQuery() const = 0; private: sqlite3* db_; diff --git a/src/Sqlite3CookieParserImpl.cc b/src/Sqlite3CookieParserImpl.cc index 9f9ebf56..07fb262c 100644 --- a/src/Sqlite3CookieParserImpl.cc +++ b/src/Sqlite3CookieParserImpl.cc @@ -44,7 +44,8 @@ Sqlite3MozCookieParser::~Sqlite3MozCookieParser() {} const std::string& Sqlite3MozCookieParser::getQuery() const { static const std::string sql = - "SELECT host, path, isSecure, expiry, name, value FROM moz_cookies"; + "SELECT host, path, isSecure, expiry, name, value, lastAccessed" + " FROM moz_cookies"; return sql; } @@ -56,7 +57,8 @@ Sqlite3ChromiumCookieParser::~Sqlite3ChromiumCookieParser() {} const std::string& Sqlite3ChromiumCookieParser::getQuery() const { static const std::string sql = - "SELECT host_key, path, secure, expires_utc, name, value FROM cookies"; + "SELECT host_key, path, secure, expires_utc, name, value, last_access_utc" + " FROM cookies"; return sql; } diff --git a/test/Sqlite3CookieParserTest.cc b/test/Sqlite3CookieParserTest.cc index e33d1b91..3a87e9ef 100644 --- a/test/Sqlite3CookieParserTest.cc +++ b/test/Sqlite3CookieParserTest.cc @@ -35,7 +35,7 @@ void Sqlite3CookieParserTest::testMozParse() { Sqlite3MozCookieParser parser("cookies.sqlite"); std::vector<Cookie> cookies; - parser.parse(cookies, 0); + parser.parse(cookies); CPPUNIT_ASSERT_EQUAL((size_t)3, cookies.size()); const Cookie& localhost = cookies[0]; @@ -47,6 +47,8 @@ void Sqlite3CookieParserTest::testMozParse() CPPUNIT_ASSERT(localhost.getHostOnly()); CPPUNIT_ASSERT_EQUAL(std::string("/"), localhost.getPath()); CPPUNIT_ASSERT(localhost.getSecure()); + CPPUNIT_ASSERT_EQUAL((time_t)3000, localhost.getLastAccessTime()); + CPPUNIT_ASSERT_EQUAL((time_t)3000, localhost.getCreationTime()); const Cookie& nullValue = cookies[1]; CPPUNIT_ASSERT_EQUAL(std::string("uid"), nullValue.getName()); @@ -79,7 +81,7 @@ void Sqlite3CookieParserTest::testMozParse_fileNotFound() Sqlite3MozCookieParser parser("fileNotFound"); try { std::vector<Cookie> cookies; - parser.parse(cookies, 0); + parser.parse(cookies); CPPUNIT_FAIL("exception must be thrown."); } catch(RecoverableException& e) { // SUCCESS @@ -93,7 +95,7 @@ void Sqlite3CookieParserTest::testMozParse_badfile() Sqlite3MozCookieParser parser("badcookies.sqlite"); try { std::vector<Cookie> cookies; - parser.parse(cookies, 0); + parser.parse(cookies); CPPUNIT_FAIL("exception must be thrown."); } catch(RecoverableException& e) { // SUCCESS @@ -104,7 +106,7 @@ void Sqlite3CookieParserTest::testChromumParse() { Sqlite3ChromiumCookieParser parser("chromium_cookies.sqlite"); std::vector<Cookie> cookies; - parser.parse(cookies, 0); + parser.parse(cookies); CPPUNIT_ASSERT_EQUAL((size_t)3, cookies.size()); const Cookie& sfnet = cookies[0]; @@ -130,7 +132,9 @@ void Sqlite3CookieParserTest::testChromumParse() const Cookie& localnet = cookies[2]; CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), localnet.getDomain()); - CPPUNIT_ASSERT(sfjp.getHostOnly()); + CPPUNIT_ASSERT(sfjp.getHostOnly()); + CPPUNIT_ASSERT_EQUAL((time_t)3000, localnet.getLastAccessTime()); + CPPUNIT_ASSERT_EQUAL((time_t)3000, localnet.getCreationTime()); } } // namespace aria2 diff --git a/test/chromium_cookies.sqlite b/test/chromium_cookies.sqlite index 6956987d..c3e98fc8 100644 Binary files a/test/chromium_cookies.sqlite and b/test/chromium_cookies.sqlite differ diff --git a/test/cookies.sqlite b/test/cookies.sqlite index 8a52a10c..e21fa95d 100644 Binary files a/test/cookies.sqlite and b/test/cookies.sqlite differ