summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Cookie.cc71
-rw-r--r--src/Cookie.h24
-rw-r--r--src/CookieStorage.cc456
-rw-r--r--src/CookieStorage.h219
-rw-r--r--src/HttpRequest.cc12
-rw-r--r--src/NsCookieParser.cc47
-rw-r--r--src/NsCookieParser.h4
-rw-r--r--src/Sqlite3CookieParser.cc36
-rw-r--r--src/Sqlite3CookieParser.h3
-rw-r--r--src/cookie_helper.cc48
-rw-r--r--src/cookie_helper.h6
11 files changed, 510 insertions, 416 deletions
diff --git a/src/Cookie.cc b/src/Cookie.cc
index 0628bc27..2c8b881e 100644
--- a/src/Cookie.cc
+++ b/src/Cookie.cc
@@ -43,23 +43,23 @@
namespace aria2 {
Cookie::Cookie
-(const std::string& name,
- const std::string& value,
+(std::string name,
+ std::string value,
time_t expiryTime,
bool persistent,
- const std::string& domain,
+ std::string domain,
bool hostOnly,
- const std::string& path,
+ std::string path,
bool secure,
bool httpOnly,
time_t creationTime):
- name_(name),
- value_(value),
+ name_(std::move(name)),
+ value_(std::move(value)),
expiryTime_(expiryTime),
persistent_(persistent),
- domain_(domain),
+ domain_(std::move(domain)),
hostOnly_(hostOnly),
- path_(path),
+ path_(std::move(path)),
secure_(secure),
httpOnly_(httpOnly),
creationTime_(creationTime),
@@ -74,40 +74,6 @@ Cookie::Cookie():
creationTime_(0),
lastAccessTime_(0) {}
-Cookie::Cookie(const Cookie& c)
- : name_(c.name_),
- value_(c.value_),
- expiryTime_(c.expiryTime_),
- persistent_(c.persistent_),
- domain_(c.domain_),
- hostOnly_(c.hostOnly_),
- path_(c.path_),
- secure_(c.secure_),
- httpOnly_(c.httpOnly_),
- creationTime_(c.creationTime_),
- lastAccessTime_(c.lastAccessTime_)
-{}
-
-Cookie::~Cookie() {}
-
-Cookie& Cookie::operator=(const Cookie& c)
-{
- if(this != &c) {
- name_ = c.name_;
- value_ = c.value_;
- expiryTime_ = c.expiryTime_;
- persistent_ = c.persistent_;
- domain_ = c.domain_;
- hostOnly_ = c.hostOnly_;
- path_ = c.path_;
- secure_ = c.secure_;
- httpOnly_ = c.httpOnly_;
- creationTime_ = c.creationTime_;
- lastAccessTime_ = c.lastAccessTime_;
- }
- return *this;
-}
-
std::string Cookie::toString() const
{
std::string s = name_;
@@ -138,6 +104,11 @@ bool Cookie::operator==(const Cookie& cookie) const
name_ == cookie.name_;
}
+bool Cookie::operator!=(const Cookie& cookie) const
+{
+ return !(*this == cookie);
+}
+
bool Cookie::isExpired(time_t base) const
{
return persistent_ && base > expiryTime_;
@@ -174,24 +145,24 @@ std::string Cookie::toNsCookieFormat() const
return ss.str();
}
-void Cookie::setName(const std::string& name)
+void Cookie::setName(std::string name)
{
- name_ = name;
+ name_ = std::move(name);
}
-void Cookie::setValue(const std::string& value)
+void Cookie::setValue(std::string value)
{
- value_ = value;
+ value_ = std::move(value);
}
-void Cookie::setDomain(const std::string& domain)
+void Cookie::setDomain(std::string domain)
{
- domain_ = domain;
+ domain_ = std::move(domain);
}
-void Cookie::setPath(const std::string& path)
+void Cookie::setPath(std::string path)
{
- path_ = path;
+ path_ = std::move(path);
}
} // namespace aria2
diff --git a/src/Cookie.h b/src/Cookie.h
index e571225d..d97ddaeb 100644
--- a/src/Cookie.h
+++ b/src/Cookie.h
@@ -63,23 +63,17 @@ public:
Cookie();
Cookie
- (const std::string& name,
- const std::string& value,
+ (std::string name,
+ std::string value,
time_t expiryTime,
bool persistent,
- const std::string& domain,
+ std::string domain,
bool hostOnly,
- const std::string& path,
+ std::string path,
bool secure,
bool httpOnly,
time_t creationTime);
- Cookie(const Cookie& c);
-
- ~Cookie();
-
- Cookie& operator=(const Cookie& c);
-
std::string toString() const;
bool match
@@ -88,6 +82,8 @@ public:
bool operator==(const Cookie& cookie) const;
+ bool operator!=(const Cookie& cookie) const;
+
bool isExpired(time_t base) const;
const std::string& getName() const
@@ -95,7 +91,7 @@ public:
return name_;
}
- void setName(const std::string& name);
+ void setName(std::string name);
template<typename InputIterator>
void setName(InputIterator first, InputIterator last)
@@ -108,7 +104,7 @@ public:
return value_;
}
- void setValue(const std::string& value);
+ void setValue(std::string value);
template<typename InputIterator>
void setValue(InputIterator first, InputIterator last)
@@ -141,7 +137,7 @@ public:
return domain_;
}
- void setDomain(const std::string& domain);
+ void setDomain(std::string domain);
template<typename InputIterator>
void setDomain(InputIterator first, InputIterator last)
@@ -164,7 +160,7 @@ public:
return path_;
}
- void setPath(const std::string& path);
+ void setPath(std::string path);
template<typename InputIterator>
void setPath(InputIterator first, InputIterator last)
diff --git a/src/CookieStorage.cc b/src/CookieStorage.cc
index e9353091..c21c4e6d 100644
--- a/src/CookieStorage.cc
+++ b/src/CookieStorage.cc
@@ -2,7 +2,7 @@
/*
* aria2 - The high speed download utility
*
- * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ * Copyright (C) 2013 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -56,131 +56,196 @@
namespace aria2 {
-CookieStorage::DomainEntry::DomainEntry(const std::string& domain)
- : key_(util::isNumericHost(domain)?domain:cookie::reverseDomainLevel(domain)),
- lastAccessTime_(0)
+DomainNode::DomainNode(std::string label, DomainNode* parent)
+ : label_{std::move(label)}, parent_{parent}, lastAccessTime_{0},
+ lruAccessTime_{0}, inLru_{false}
{}
-CookieStorage::DomainEntry::DomainEntry
-(const DomainEntry& c)
- : key_(c.key_),
- lastAccessTime_(c.lastAccessTime_),
- cookies_(c.cookies_)
-{}
-
-CookieStorage::DomainEntry::~DomainEntry() {}
-
-CookieStorage::DomainEntry& CookieStorage::DomainEntry::operator=
-(const DomainEntry& c)
-{
- if(this != &c) {
- key_ = c.key_;
- lastAccessTime_ = c.lastAccessTime_;
- cookies_ = c.cookies_;
- }
- return *this;
-}
-
-void CookieStorage::DomainEntry::swap(CookieStorage::DomainEntry& c)
-{
- using std::swap;
- swap(key_, c.key_);
- swap(lastAccessTime_, c.lastAccessTime_);
- swap(cookies_, c.cookies_);
-}
-
-void swap(CookieStorage::DomainEntry& a, CookieStorage::DomainEntry& b)
-{
- a.swap(b);
-}
-
-void CookieStorage::DomainEntry::findCookie
-(std::vector<Cookie>& out,
+void DomainNode::findCookie
+(std::vector<const Cookie*>& out,
const std::string& requestHost,
const std::string& requestPath,
time_t now, bool secure)
{
- for(std::deque<Cookie>::iterator i = cookies_.begin(),
- eoi = cookies_.end(); i != eoi; ++i) {
- if((*i).match(requestHost, requestPath, now, secure)) {
- (*i).setLastAccessTime(now);
- out.push_back(*i);
+ if(cookies_) {
+ for(auto& c : *cookies_) {
+ if(c->match(requestHost, requestPath, now, secure)) {
+ c->setLastAccessTime(now);
+ out.push_back(c.get());
+ }
}
}
}
-bool CookieStorage::DomainEntry::addCookie(const Cookie& cookie, time_t now)
+bool DomainNode::addCookie(std::unique_ptr<Cookie> cookie, time_t now)
{
using namespace std::placeholders;
setLastAccessTime(now);
- std::deque<Cookie>::iterator i =
- std::find(cookies_.begin(), cookies_.end(), cookie);
- if(i == cookies_.end()) {
- if(cookie.isExpired(now)) {
+ if(!cookies_) {
+ if(cookie->isExpired(now)) {
return false;
} else {
- if(cookies_.size() >= CookieStorage::MAX_COOKIE_PER_DOMAIN) {
- cookies_.erase
- (std::remove_if(cookies_.begin(), cookies_.end(),
+ cookies_ = make_unique<std::deque<std::unique_ptr<Cookie>>>();
+ cookies_->push_back(std::move(cookie));
+ return true;
+ }
+ }
+
+ auto i = std::find_if(std::begin(*cookies_), std::end(*cookies_),
+ [&](const std::unique_ptr<Cookie>& c)
+ {
+ return *c == *cookie;
+ });
+ if(i == std::end(*cookies_)) {
+ if(cookie->isExpired(now)) {
+ return false;
+ } else {
+ if(cookies_->size() >= CookieStorage::MAX_COOKIE_PER_DOMAIN) {
+ cookies_->erase
+ (std::remove_if(std::begin(*cookies_), std::end(*cookies_),
std::bind(&Cookie::isExpired, _1, now)),
- cookies_.end());
- if(cookies_.size() >= CookieStorage::MAX_COOKIE_PER_DOMAIN) {
- std::deque<Cookie>::iterator m = std::min_element
- (cookies_.begin(), cookies_.end(), LeastRecentAccess<Cookie>());
- *m = cookie;
+ std::end(*cookies_));
+ if(cookies_->size() >= CookieStorage::MAX_COOKIE_PER_DOMAIN) {
+ auto m = std::min_element(std::begin(*cookies_), std::end(*cookies_),
+ [](const std::unique_ptr<Cookie>& lhs,
+ const std::unique_ptr<Cookie>& rhs)
+ {
+ return lhs->getLastAccessTime() <
+ rhs->getLastAccessTime();
+ });
+ *m = std::move(cookie);
} else {
- cookies_.push_back(cookie);
+ cookies_->push_back(std::move(cookie));
}
} else {
- cookies_.push_back(cookie);
+ cookies_->push_back(std::move(cookie));
}
return true;
}
- } else if(cookie.isExpired(now)) {
- cookies_.erase(i);
+ } else if(cookie->isExpired(now)) {
+ cookies_->erase(i);
return false;
} else {
- *i = cookie;
+ *i = std::move(cookie);
return true;
}
}
-bool CookieStorage::DomainEntry::contains(const Cookie& cookie) const
+bool DomainNode::contains(const Cookie& cookie) const
{
- return std::find(cookies_.begin(), cookies_.end(), cookie) != cookies_.end();
+ if(cookies_) {
+ for(auto& i : *cookies_) {
+ if(*i == cookie) {
+ return true;
+ }
+ }
+ }
+ return false;
}
-bool CookieStorage::DomainEntry::writeCookie(BufferedFile& fp) const
+bool DomainNode::writeCookie(BufferedFile& fp) const
{
- for(std::deque<Cookie>::const_iterator i = cookies_.begin(),
- eoi = cookies_.end(); i != eoi; ++i) {
- std::string data = (*i).toNsCookieFormat();
- data += "\n";
- if(fp.write(data.data(), data.size()) != data.size()) {
- return false;
+ if(cookies_) {
+ for(const auto& c : *cookies_) {
+ std::string data = c->toNsCookieFormat();
+ data += "\n";
+ if(fp.write(data.data(), data.size()) != data.size()) {
+ return false;
+ }
}
}
return true;
}
-size_t CookieStorage::DomainEntry::countCookie() const
+size_t DomainNode::countCookie() const
+{
+ if(cookies_) {
+ return cookies_->size();
+ } else {
+ return 0;
+ }
+}
+
+void DomainNode::clearCookie()
+{
+ cookies_->clear();
+}
+
+void DomainNode::setLastAccessTime(time_t lastAccessTime)
{
- return cookies_.size();
+ lastAccessTime_ = lastAccessTime;
}
-bool CookieStorage::DomainEntry::operator==(const DomainEntry& de) const
+time_t DomainNode::getLastAccessTime() const
{
- return key_ == de.key_;
+ return lastAccessTime_;
}
-bool CookieStorage::DomainEntry::operator<(const DomainEntry& de) const
+void DomainNode::setLruAccessTime(time_t t)
{
- return key_ < de.key_;
+ lruAccessTime_ = t;
}
-CookieStorage::CookieStorage() {}
+time_t DomainNode::getLruAccessTime() const
+{
+ return lruAccessTime_;
+}
-CookieStorage::~CookieStorage() {}
+bool DomainNode::empty() const
+{
+ return !cookies_ || cookies_->empty();
+}
+
+bool DomainNode::hasNext() const
+{
+ return !next_.empty();
+}
+
+DomainNode* DomainNode::getParent() const
+{
+ return parent_;
+}
+
+void DomainNode::removeNode(DomainNode* node)
+{
+ next_.erase(node->getLabel());
+}
+
+DomainNode* DomainNode::findNext(const std::string& label) const
+{
+ auto i = next_.find(label);
+ if(i == std::end(next_)) {
+ return nullptr;
+ } else {
+ return (*i).second.get();
+ }
+}
+
+DomainNode* DomainNode::addNext(std::string label,
+ std::unique_ptr<DomainNode> node)
+{
+ auto& res = next_[std::move(label)] = std::move(node);
+ return res.get();
+}
+
+const std::string& DomainNode::getLabel() const
+{
+ return label_;
+}
+
+bool DomainNode::getInLru() const
+{
+ return inLru_;
+}
+
+void DomainNode::setInLru(bool f)
+{
+ inLru_ = f;
+}
+
+CookieStorage::CookieStorage()
+ : rootNode_{make_unique<DomainNode>("", nullptr)}
+{}
namespace {
// See CookieStorageTest::testDomainIsFull() in CookieStorageTest.cc
@@ -189,29 +254,86 @@ const size_t DOMAIN_EVICTION_TRIGGER = 2000;
const double DOMAIN_EVICTION_RATE = 0.1;
} // namespace
-bool CookieStorage::store(const Cookie& cookie, time_t now)
+namespace {
+std::vector<std::string> splitDomainLabel(const std::string& domain)
{
- if(domains_.size() >= DOMAIN_EVICTION_TRIGGER) {
- std::vector<std::shared_ptr<DomainEntry> > evictions(domains_.begin(),
- domains_.end());
- std::sort(evictions.begin(), evictions.end(),
- LeastRecentAccess<DomainEntry>());
- size_t delnum = (size_t)(evictions.size()*DOMAIN_EVICTION_RATE);
- domains_.clear();
- domains_.insert(evictions.begin()+delnum, evictions.end());
- }
- std::shared_ptr<DomainEntry> v(new DomainEntry(cookie.getDomain()));
- DomainEntrySet::iterator i = domains_.lower_bound(v);
- bool added = false;
- if(i != domains_.end() && *(*i) == *v) {
- added = (*i)->addCookie(cookie, now);
+ auto labels = std::vector<std::string>{};
+ if(util::isNumericHost(domain)) {
+ labels.push_back(domain);
} else {
- added = v->addCookie(cookie, now);
- if(added) {
- domains_.insert(i, v);
+ util::split(std::begin(domain), std::end(domain),
+ std::back_inserter(labels), '.');
+ }
+ return labels;
+}
+} // namespace
+
+
+size_t CookieStorage::getLruTrackerSize() const
+{
+ return lruTracker_.size();
+}
+
+void CookieStorage::evictNode(size_t delnum)
+{
+ for(; delnum > 0 && !lruTracker_.empty(); --delnum) {
+ auto node = (*lruTracker_.begin()).second;
+ lruTracker_.erase(lruTracker_.begin());
+ node->setInLru(false);
+ node->clearCookie();
+ while(node->empty() && !node->hasNext()) {
+ auto parent = node->getParent();
+ parent->removeNode(node);
+ if(!parent->empty() || parent->hasNext() ||
+ parent == rootNode_.get()) {
+ break;
+ }
+ node = parent;
+ if(node->getInLru()) {
+ lruTracker_.erase({node->getLruAccessTime(), node});
+ node->setInLru(false);
+ }
}
}
- return added;
+}
+
+const DomainNode* CookieStorage::getRootNode() const
+{
+ return rootNode_.get();
+}
+
+bool CookieStorage::store(std::unique_ptr<Cookie> cookie, time_t now)
+{
+ if(lruTracker_.size() >= DOMAIN_EVICTION_TRIGGER) {
+ auto delnum = size_t(lruTracker_.size()*DOMAIN_EVICTION_RATE);
+ evictNode(delnum);
+ }
+ auto labels = splitDomainLabel(cookie->getDomain());
+ auto node = rootNode_.get();
+ for(auto i = labels.rbegin(), eoi = labels.rend(); i != eoi; ++i) {
+ auto nextNode = node->findNext(*i);
+ if(nextNode) {
+ node = nextNode;
+ } else {
+ node = node->addNext(*i, make_unique<DomainNode>(*i, node));
+ }
+ }
+ bool ok = node->addCookie(std::move(cookie), now);
+ if(ok) {
+ updateLru(node, now);
+ }
+ return ok;
+}
+
+void CookieStorage::updateLru(DomainNode* node, time_t now)
+{
+ if(node->getInLru()) {
+ lruTracker_.erase({node->getLruAccessTime(), node});
+ } else {
+ node->setInLru(true);
+ }
+ node->setLruAccessTime(now);
+ lruTracker_.insert({node->getLruAccessTime(), node});
}
bool CookieStorage::parseAndStore
@@ -220,20 +342,17 @@ bool CookieStorage::parseAndStore
const std::string& defaultPath,
time_t now)
{
- Cookie cookie;
- if(cookie::parse(cookie, setCookieString, requestHost, defaultPath, now)) {
- return store(cookie, now);
- } else {
- return false;
- }
+ auto cookie = cookie::parse(setCookieString, requestHost, defaultPath, now);
+ return cookie && store(std::move(cookie), now);
}
+namespace {
struct CookiePathDivider {
- Cookie cookie_;
+ const Cookie* cookie_;
int pathDepth_;
- CookiePathDivider(const Cookie& cookie):cookie_(cookie), pathDepth_(0)
+ CookiePathDivider(const Cookie* cookie):cookie_(cookie), pathDepth_(0)
{
- const std::string& path = cookie_.getPath();
+ const std::string& path = cookie_->getPath();
if(!path.empty()) {
for(size_t i = 1, len = path.size(); i < len; ++i) {
if(path[i] == '/' && path[i-1] != '/') {
@@ -246,16 +365,17 @@ struct CookiePathDivider {
}
}
};
+} // namespace
namespace {
class CookiePathDividerConverter {
public:
- CookiePathDivider operator()(const Cookie& cookie) const
+ CookiePathDivider operator()(const Cookie* cookie) const
{
return CookiePathDivider(cookie);
}
- Cookie operator()(const CookiePathDivider& cookiePathDivider) const
+ const Cookie* operator()(const CookiePathDivider& cookiePathDivider) const
{
return cookiePathDivider.cookie_;
}
@@ -280,80 +400,69 @@ public:
// creation-times.
return lhs.pathDepth_ > rhs.pathDepth_ ||
(!(rhs.pathDepth_ > lhs.pathDepth_) &&
- lhs.cookie_.getCreationTime() < rhs.cookie_.getCreationTime());
+ lhs.cookie_->getCreationTime() < rhs.cookie_->getCreationTime());
}
};
} // namespace
-void CookieStorage::searchCookieByDomainSuffix
-(std::vector<Cookie>& out,
- const std::string& domain,
- const std::string& requestHost,
- const std::string& requestPath,
- time_t now, bool secure)
+namespace {
+DomainNode* findNode(const std::string& domain, DomainNode* node)
{
- std::shared_ptr<DomainEntry> v(new DomainEntry(domain));
- DomainEntrySet::iterator i = domains_.lower_bound(v);
- if(i != domains_.end() && *(*i) == *v) {
- (*i)->setLastAccessTime(now);
- (*i)->findCookie(out, requestHost, requestPath, now, secure);
+ auto labels = splitDomainLabel(domain);
+ for(auto i = labels.rbegin(), eoi = labels.rend(); i != eoi && node; ++i) {
+ node = node->findNext(*i);
}
+ return node;
}
+} // namespace
bool CookieStorage::contains(const Cookie& cookie) const
{
- std::shared_ptr<DomainEntry> v(new DomainEntry(cookie.getDomain()));
- DomainEntrySet::iterator i = domains_.find(v);
- if(i != domains_.end()) {
- return (*i)->contains(cookie);
- } else {
- return false;
- }
+ auto node = findNode(cookie.getDomain(), rootNode_.get());
+ return node && node->contains(cookie);
}
-std::vector<Cookie> CookieStorage::criteriaFind
+std::vector<const Cookie*> CookieStorage::criteriaFind
(const std::string& requestHost,
const std::string& requestPath,
time_t now,
bool secure)
{
- std::vector<Cookie> res;
+ auto res = std::vector<const Cookie*>{};
if(requestPath.empty()) {
return res;
}
- if(util::isNumericHost(requestHost)) {
- searchCookieByDomainSuffix
- (res, requestHost, requestHost, requestPath, now, secure);
- } else {
- std::vector<Scip> levels;
- util::splitIter(requestHost.begin(), requestHost.end(),
- std::back_inserter(levels), '.');
- std::string domain;
- for(std::vector<Scip>::const_reverse_iterator i =
- levels.rbegin(), eoi = levels.rend();
- i != eoi; ++i, domain.insert(domain.begin(), '.')) {
- domain.insert(domain.begin(), (*i).first, (*i).second);
- searchCookieByDomainSuffix
- (res, domain, requestHost, requestPath, now, secure);
+ auto labels = splitDomainLabel(requestHost);
+ auto node = rootNode_.get();
+ for(auto i = labels.rbegin(), eoi = labels.rend(); i != eoi; ++i) {
+ auto nextNode = node->findNext(*i);
+ if(nextNode) {
+ nextNode->setLastAccessTime(now);
+ if(nextNode->getInLru()) {
+ updateLru(nextNode, now);
+ }
+ nextNode->findCookie(res, requestHost, requestPath, now, secure);
+ node = nextNode;
+ } else {
+ break;
}
}
- std::vector<CookiePathDivider> divs;
- std::transform(res.begin(), res.end(), std::back_inserter(divs),
- CookiePathDividerConverter());
- std::sort(divs.begin(), divs.end(), OrderByPathDepthDesc());
- std::transform(divs.begin(), divs.end(), res.begin(),
- CookiePathDividerConverter());
+ auto divs = std::vector<CookiePathDivider>{};
+ std::transform(std::begin(res), std::end(res), std::back_inserter(divs),
+ CookiePathDividerConverter{});
+ std::sort(std::begin(divs), std::end(divs), OrderByPathDepthDesc{});
+ std::transform(std::begin(divs), std::end(divs), std::begin(res),
+ CookiePathDividerConverter{});
return res;
}
size_t CookieStorage::size() const
{
- size_t numCookie = 0;
- for(DomainEntrySet::iterator i = domains_.begin(), eoi = domains_.end();
- i != eoi; ++i) {
- numCookie += (*i)->countCookie();
+ size_t n = 0;
+ for(auto& p : lruTracker_) {
+ n += p.second->countCookie();
}
- return numCookie;
+ return n;
}
bool CookieStorage::load(const std::string& filename, time_t now)
@@ -361,7 +470,7 @@ bool CookieStorage::load(const std::string& filename, time_t now)
char header[16]; // "SQLite format 3" plus \0
size_t headlen;
{
- BufferedFile fp(filename.c_str(), BufferedFile::READ);
+ BufferedFile fp{filename.c_str(), BufferedFile::READ};
if(!fp) {
A2_LOG_ERROR(fmt("Failed to open cookie file %s", filename.c_str()));
return false;
@@ -371,25 +480,28 @@ bool CookieStorage::load(const std::string& filename, time_t now)
try {
if(headlen == 16 && memcmp(header, "SQLite format 3\0", 16) == 0) {
#ifdef HAVE_SQLITE3
- std::vector<Cookie> cookies;
try {
- Sqlite3MozCookieParser(filename).parse(cookies);
+ auto cookies = Sqlite3MozCookieParser(filename).parse();
+ storeCookies(std::make_move_iterator(std::begin(cookies)),
+ std::make_move_iterator(std::end(cookies)), now);
} catch(RecoverableException& e) {
A2_LOG_INFO_EX(EX_EXCEPTION_CAUGHT, e);
A2_LOG_INFO("This does not look like Firefox3 cookie file."
" Retrying, assuming it is Chromium cookie file.");
// Try chrome cookie format
- Sqlite3ChromiumCookieParser(filename).parse(cookies);
+ auto cookies = Sqlite3ChromiumCookieParser(filename).parse();
+ storeCookies(std::make_move_iterator(std::begin(cookies)),
+ std::make_move_iterator(std::end(cookies)), now);
}
- storeCookies(cookies.begin(), cookies.end(), now);
#else // !HAVE_SQLITE3
throw DL_ABORT_EX
("Cannot read SQLite3 database because SQLite3 support is disabled by"
" configuration.");
#endif // !HAVE_SQLITE3
} else {
- std::vector<Cookie> cookies = NsCookieParser().parse(filename, now);
- storeCookies(cookies.begin(), cookies.end(), now);
+ auto cookies = NsCookieParser().parse(filename, now);
+ storeCookies(std::make_move_iterator(std::begin(cookies)),
+ std::make_move_iterator(std::end(cookies)), now);
}
return true;
} catch(RecoverableException& e) {
@@ -400,17 +512,16 @@ bool CookieStorage::load(const std::string& filename, time_t now)
bool CookieStorage::saveNsFormat(const std::string& filename)
{
- std::string tempfilename = filename;
+ auto tempfilename = filename;
tempfilename += "__temp";
{
- BufferedFile fp(tempfilename.c_str(), BufferedFile::WRITE);
+ BufferedFile fp{tempfilename.c_str(), BufferedFile::WRITE};
if(!fp) {
A2_LOG_ERROR(fmt("Cannot create cookie file %s", filename.c_str()));
return false;
}
- for(DomainEntrySet::iterator i = domains_.begin(), eoi = domains_.end();
- i != eoi; ++i) {
- if(!(*i)->writeCookie(fp)) {
+ for(auto& p : lruTracker_) {
+ if(!p.second->writeCookie(fp)) {
A2_LOG_ERROR(fmt("Failed to save cookies to %s", filename.c_str()));
return false;
}
@@ -431,14 +542,3 @@ bool CookieStorage::saveNsFormat(const std::string& filename)
}
} // namespace aria2
-
-namespace std {
-template<>
-void swap<aria2::CookieStorage::DomainEntry>
-(aria2::CookieStorage::DomainEntry& a,
- aria2::CookieStorage::DomainEntry& b)
-{
- a.swap(b);
-}
-} // namespace std
-
diff --git a/src/CookieStorage.h b/src/CookieStorage.h
index 530e0d62..de3eaebc 100644
--- a/src/CookieStorage.h
+++ b/src/CookieStorage.h
@@ -2,7 +2,7 @@
/*
* aria2 - The high speed download utility
*
- * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ * Copyright (C) 2013 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -42,6 +42,7 @@
#include <vector>
#include <set>
#include <algorithm>
+#include <unordered_map>
#include "a2time.h"
#include "Cookie.h"
@@ -51,89 +52,97 @@ namespace aria2 {
class BufferedFile;
-class CookieStorage {
+// This object represents one domain label.
+class DomainNode {
public:
+ DomainNode(std::string label, DomainNode* parent);
+ // Stores the matching cookies in |out|. The |now| is used to update
+ // the last access time of this node.
+ void findCookie
+ (std::vector<const Cookie*>& out,
+ const std::string& requestHost,
+ const std::string& requestPath,
+ time_t now, bool secure);
+ // Returns the number of cookies this node has.
+ size_t countCookie() const;
+ // Add |cookie| using update time |now|. Returns true if the
+ // function succeeds.
+ bool addCookie(std::unique_ptr<Cookie> cookie, time_t now);
+ // Sets the last access time of this node.
+ void setLastAccessTime(time_t lastAccessTime);
+ // Returns the last access time of this node.
+ time_t getLastAccessTime() const;
+ // Sets the time |t| as a time used as key in LRU tracker.
+ void setLruAccessTime(time_t t);
+ time_t getLruAccessTime() const;
+
+ bool writeCookie(BufferedFile& fp) const;
+ // Returns true if this node contains the |cookie|.
+ bool contains(const Cookie& cookie) const;
+ // Returns true if this node contains no cookie.
+ bool empty() const;
+ // Returns true if this node has any next nodes.
+ bool hasNext() const;
+ // Returns the parent node. If this is the root node, returns
+ // nullptr.
+ DomainNode* getParent() const;
+ // Removes the child node |node|. Nothing happens if |node| is not a
+ // child of this node.
+ void removeNode(DomainNode* node);
+ // Returns the child node having label |label. Returns nullptr if
+ // there is no such node.
+ DomainNode* findNext(const std::string& label) const;
+ // Add the |node| as a child using label |label and returns the raw
+ // pointer of |node|.
+ DomainNode* addNext(std::string label, std::unique_ptr<DomainNode> node);
+ // Returns the |label|.
+ const std::string& getLabel() const;
+ // Deletes all cookies this node has.
+ void clearCookie();
+ // Returns value set by setInLru(). This is typically used to know
+ // this node is tracked by LRU tracker or not.
+ bool getInLru() const;
+ void setInLru(bool f);
- static const size_t MAX_COOKIE_PER_DOMAIN = 50;
-
- class DomainEntry {
- private:
- // This is reversed domain level string.
- // e.g. net.sourceforge.aria2
- // e.g. 192.168.0.1
- std::string key_;
-
- time_t lastAccessTime_;
-
- std::deque<Cookie> cookies_;
- public:
- DomainEntry(const std::string& domain);
- DomainEntry(const DomainEntry& c);
- ~DomainEntry();
-
- void swap(DomainEntry& c);
-
- DomainEntry& operator=(const DomainEntry& c);
-
- const std::string& getKey() const
- {
- return key_;
- }
-
- void findCookie
- (std::vector<Cookie>& out,
- const std::string& requestHost,
- const std::string& requestPath,
- time_t now, bool secure);
-
- size_t countCookie() const;
-
- bool addCookie(const Cookie& cookie, time_t now);
-
- void setLastAccessTime(time_t lastAccessTime)
- {
- lastAccessTime_ = lastAccessTime;
- }
-
- time_t getLastAccessTime() const
- {
- return lastAccessTime_;
- }
-
- bool writeCookie(BufferedFile& fp) const;
-
- bool contains(const Cookie& cookie) const;
-
- template<typename OutputIterator>
- OutputIterator dumpCookie(OutputIterator out) const
- {
- return std::copy(cookies_.begin(), cookies_.end(), out);
+ template<typename OutputIterator>
+ OutputIterator dumpCookie(OutputIterator out) const
+ {
+ if(cookies_) {
+ for(auto& c : *cookies_) {
+ out++ = c.get();
+ }
}
+ return out;
+ }
+private:
+ std::string label_;
+ DomainNode* parent_;
+ time_t lastAccessTime_;
+ time_t lruAccessTime_;
+ bool inLru_;
+ std::unique_ptr<std::deque<std::unique_ptr<Cookie>>> cookies_;
+ // domain label string to DomainNode
+ // e.g. net, sourceforge
+ // For numerical addresses, this is address itself.
+ // e.g. 192.168.0.1
+ std::unordered_map<std::string, std::unique_ptr<DomainNode>> next_;
+};
- bool operator==(const DomainEntry& de) const;
- bool operator<(const DomainEntry& de) const;
- };
+class CookieStorage {
+public:
+ static const size_t MAX_COOKIE_PER_DOMAIN = 50;
private:
- typedef std::set<std::shared_ptr<DomainEntry>,
- DerefLess<std::shared_ptr<DomainEntry> > > DomainEntrySet;
- DomainEntrySet domains_;
+ // typedef std::set<std::shared_ptr<DomainEntry>,
+ // DerefLess<std::shared_ptr<DomainEntry> > > DomainEntrySet;
+ // DomainEntrySet domains_;
- template<typename InputIterator>
- void storeCookies(InputIterator first, InputIterator last, time_t now)
- {
- for(; first != last; ++first) {
- store(*first, now);
- }
- }
public:
CookieStorage();
- ~CookieStorage();
-
// Returns true if cookie is stored or updated existing cookie.
// Returns false if cookie is expired. now is used as last access
// time.
- bool store(const Cookie& cookie, time_t now);
+ bool store(std::unique_ptr<Cookie> cookie, time_t now);
// Returns true if cookie is stored or updated existing cookie.
// Otherwise, returns false. now is used as creation time and last
@@ -146,9 +155,10 @@ public:
// Finds cookies matched with given criteria and returns them.
// Matched cookies' lastAccess_ property is updated.
- std::vector<Cookie> criteriaFind(const std::string& requestHost,
- const std::string& requestPath,
- time_t now, bool secure);
+ std::vector<const Cookie*>
+ criteriaFind(const std::string& requestHost,
+ const std::string& requestPath,
+ time_t now, bool secure);
// Loads Cookies from file denoted by filename. If compiled with
// libsqlite3, this method automatically detects the specified file
@@ -170,36 +180,51 @@ public:
// satisfies.
bool contains(const Cookie& cookie) const;
- // Searches Cookie using given domain, requestHost, requestPath,
- // current time and secure flag. The found Cookies are stored in
- // out.
- void searchCookieByDomainSuffix
- (std::vector<Cookie>& out,
- const std::string& domain,
- const std::string& requestHost,
- const std::string& requestPath,
- time_t now, bool secure);
-
template<typename OutputIterator>
OutputIterator dumpCookie(OutputIterator out) const
{
- for(DomainEntrySet::iterator i = domains_.begin(), eoi = domains_.end();
- i != eoi; ++i) {
- out = (*i)->dumpCookie(out);
+ for(auto& i : lruTracker_) {
+ out = i.second->dumpCookie(out);
}
return out;
}
-};
-void swap(CookieStorage::DomainEntry& a, CookieStorage::DomainEntry& b);
+ // Force eviction of delnum nodes. Exposed for unittest
+ void evictNode(size_t delnum);
+ // Returns size of LRU tracker. Exposed for unittest
+ size_t getLruTrackerSize() const;
+ // Returns root node. Exposed for unittest
+ const DomainNode* getRootNode() const;
+private:
+ template<typename InputIterator>
+ void storeCookies(InputIterator first, InputIterator last, time_t now)
+ {
+ for(; first != last; ++first) {
+ store(*first, now);
+ }
+ }
+
+ void updateLru(DomainNode* node, time_t now);
+
+ // rootNode_ is a root node of tree structure of reversed domain
+ // labels. rootNode_ always contans no cookie. It has the child
+ // nodes of the top level domain label (e.g., net, com and org). And
+ // those top level domain nodes have 2nd doman label (e.g.,
+ // sourcforge, github), and so on. The numeric host name are always
+ // stored as a child node of rootNode_. So the domain name of a
+ // paricular node is constructed as follows. First traverse the
+ // target node from root node. The concatenation of the visited
+ // node's label in the reverse order, delimited by ".", is the
+ std::unique_ptr<DomainNode> rootNode_;
+ // This object tracks the node which has cookies or it once had. The
+ // order is sorted by the least recent updated node first. This
+ // object does not track the node which has not contan cookie. For
+ // example, adding cookies in aria2.sourceforge.net, and no node
+ // labeled "sourceforge" is present, only node labelded "aria2" is
+ // tracked and node labeled "sourceforge" and "net" are not.
+ std::set<std::pair<time_t, DomainNode*>> lruTracker_;
+};
} // namespace aria2
-namespace std {
-template<>
-void swap<aria2::CookieStorage::DomainEntry>
-(aria2::CookieStorage::DomainEntry& a,
- aria2::CookieStorage::DomainEntry& b);
-} // namespace std
-
#endif // D_COOKIE_STORAGE_H
diff --git a/src/HttpRequest.cc b/src/HttpRequest.cc
index 3e7d1a4b..33469813 100644
--- a/src/HttpRequest.cc
+++ b/src/HttpRequest.cc
@@ -234,13 +234,11 @@ std::string HttpRequest::createRequest()
std::string cookiesValue;
std::string path = getDir();
path += getFile();
- std::vector<Cookie> cookies =
- cookieStorage_->criteriaFind(getHost(), path,
- Time().getTime(),
- getProtocol() == "https");
- for(std::vector<Cookie>::const_iterator itr = cookies.begin(),
- eoi = cookies.end(); itr != eoi; ++itr) {
- cookiesValue += (*itr).toString();
+ auto cookies = cookieStorage_->criteriaFind(getHost(), path,
+ Time().getTime(),
+ getProtocol() == "https");
+ for(auto c : cookies) {
+ cookiesValue += c->toString();
cookiesValue += ";";
}
if(!cookiesValue.empty()) {
diff --git a/src/NsCookieParser.cc b/src/NsCookieParser.cc
index 61672d18..e107a295 100644
--- a/src/NsCookieParser.cc
+++ b/src/NsCookieParser.cc
@@ -54,58 +54,59 @@ NsCookieParser::NsCookieParser() {}
NsCookieParser::~NsCookieParser() {}
namespace {
-bool parseNsCookie
-(Cookie& cookie, const std::string& cookieStr, time_t creationTime)
+std::unique_ptr<Cookie> parseNsCookie
+(const std::string& cookieStr, time_t creationTime)
{
std::vector<Scip> vs;
util::splitIter(cookieStr.begin(), cookieStr.end(), std::back_inserter(vs),
'\t', true);
if(vs.size() < 6) {
- return false;
+ return std::unique_ptr<Cookie>{};
}
vs[0].first = util::lstripIter(vs[0].first, vs[0].second, '.');
if(vs[5].first == vs[5].second || vs[0].first == vs[0].second ||
!cookie::goodPath(vs[2].first, vs[2].second)) {
- return false;
+ return std::unique_ptr<Cookie>{};
}
int64_t expiryTime;
if(!util::parseLLIntNoThrow(expiryTime,
std::string(vs[4].first, vs[4].second))) {
- return false;
+ return std::unique_ptr<Cookie>{};
}
if(std::numeric_limits<time_t>::max() < expiryTime) {
expiryTime = std::numeric_limits<time_t>::max();
} else if(std::numeric_limits<time_t>::min() > expiryTime) {
expiryTime = std::numeric_limits<time_t>::min();
}
- cookie.setName(vs[5].first, vs[5].second);
+ auto cookie = make_unique<Cookie>();
+ cookie->setName(vs[5].first, vs[5].second);
if(vs.size() >= 7) {
- cookie.setValue(vs[6].first, vs[6].second);
+ cookie->setValue(vs[6].first, vs[6].second);
} else {
- cookie.setValue(A2STR::NIL.begin(), A2STR::NIL.end());
+ cookie->setValue("");
}
- cookie.setExpiryTime(expiryTime == 0?
+ cookie->setExpiryTime(expiryTime == 0?
std::numeric_limits<time_t>::max():expiryTime);
- // aria2 treats expiryTime == 0 means session cookie.
- cookie.setPersistent(expiryTime != 0);
- cookie.setDomain(vs[0].first, vs[0].second);
- cookie.setHostOnly(util::isNumericHost(cookie.getDomain()) ||
+ // aria2 treats expiryTime == 0 means session cookie->
+ cookie->setPersistent(expiryTime != 0);
+ cookie->setDomain(vs[0].first, vs[0].second);
+ cookie->setHostOnly(util::isNumericHost(cookie->getDomain()) ||
!util::streq(vs[1].first, vs[1].second, "TRUE"));
- cookie.setPath(vs[2].first, vs[2].second);
- cookie.setSecure(util::streq(vs[3].first, vs[3].second, "TRUE"));
- cookie.setCreationTime(creationTime);
- return true;
+ cookie->setPath(vs[2].first, vs[2].second);
+ cookie->setSecure(util::streq(vs[3].first, vs[3].second, "TRUE"));
+ cookie->setCreationTime(creationTime);
+ return cookie;
}
} // namespace
-std::vector<Cookie> NsCookieParser::parse
+std::vector<std::unique_ptr<Cookie>> NsCookieParser::parse
(const std::string& filename, time_t creationTime)
{
- BufferedFile fp(filename.c_str(), BufferedFile::READ);
+ BufferedFile fp{filename.c_str(), BufferedFile::READ};
if(!fp) {
throw DL_ABORT_EX(fmt("Failed to open file %s", filename.c_str()));
}
- std::vector<Cookie> cookies;
+ std::vector<std::unique_ptr<Cookie>> cookies;
while(1) {
std::string line = fp.getLine();
if(line.empty()) {
@@ -120,9 +121,9 @@ std::vector<Cookie> NsCookieParser::parse
if(line[0] == '#') {
continue;
}
- Cookie c;
- if(parseNsCookie(c, line, creationTime)) {
- cookies.push_back(c);
+ auto c = parseNsCookie(line, creationTime);
+ if(c) {
+ cookies.push_back(std::move(c));
}
}
return cookies;
diff --git a/src/NsCookieParser.h b/src/NsCookieParser.h
index 5515692f..19668ed2 100644
--- a/src/NsCookieParser.h
+++ b/src/NsCookieParser.h
@@ -39,6 +39,7 @@
#include <string>
#include <vector>
+#include <memory>
namespace aria2 {
@@ -50,7 +51,8 @@ public:
~NsCookieParser();
- std::vector<Cookie> parse(const std::string& filename, time_t creationTime);
+ std::vector<std::unique_ptr<Cookie>> parse
+ (const std::string& filename, time_t creationTime);
};
} // namespace aria2
diff --git a/src/Sqlite3CookieParser.cc b/src/Sqlite3CookieParser.cc
index ed89aef7..08c2b836 100644
--- a/src/Sqlite3CookieParser.cc
+++ b/src/Sqlite3CookieParser.cc
@@ -102,8 +102,8 @@ int cookieRowMapper(void* data, int columns, char** values, char** names)
if(columns != 7 || !values[0] || !values[1] || !values[4]) {
return 0;
}
- std::vector<Cookie>& cookies =
- *reinterpret_cast<std::vector<Cookie>*>(data);
+ std::vector<std::unique_ptr<Cookie>>& cookies =
+ *reinterpret_cast<std::vector<std::unique_ptr<Cookie>>*>(data);
size_t val0len = strlen(values[0]);
std::string cookieDomain
(util::lstripIter(&values[0][0], &values[0][val0len], '.'),
@@ -122,29 +122,29 @@ int cookieRowMapper(void* data, int columns, char** values, char** names)
if(!values[6] || !parseTime(lastAccessTime, values[6])) {
return 0;
}
- Cookie c(cookieName,
- toString(values[5]), // value
- expiryTime,
- true, // persistent
- cookieDomain,
- util::isNumericHost(cookieDomain) ||
- (values[0] && values[0][0] != '.'), // hostOnly
- cookiePath,
- values[2] && strcmp(values[2], "1") == 0, //secure
- false,
- lastAccessTime // creation time. Set this later.
- );
- cookies.push_back(c);
+ cookies.push_back(make_unique<Cookie>
+ (std::move(cookieName),
+ toString(values[5]), // value
+ expiryTime,
+ true, // persistent
+ std::move(cookieDomain),
+ util::isNumericHost(cookieDomain) ||
+ (values[0] && values[0][0] != '.'), // hostOnly
+ std::move(cookiePath),
+ values[2] && strcmp(values[2], "1") == 0, //secure
+ false,
+ lastAccessTime // creation time. Set this later.
+ ));
return 0;
}
} // namespace
-void Sqlite3CookieParser::parse(std::vector<Cookie>& cookies)
+std::vector<std::unique_ptr<Cookie>> Sqlite3CookieParser::parse()
{
if(!db_) {
throw DL_ABORT_EX(fmt("SQLite3 database is not opened."));
}
- std::vector<Cookie> tcookies;
+ auto tcookies = std::vector<std::unique_ptr<Cookie>>{};
char* sqlite3ErrMsg = 0;
int ret = sqlite3_exec(db_, getQuery(), cookieRowMapper,
&tcookies, &sqlite3ErrMsg);
@@ -157,7 +157,7 @@ void Sqlite3CookieParser::parse(std::vector<Cookie>& cookies)
throw DL_ABORT_EX
(fmt("Failed to read SQLite3 database: %s", errMsg.c_str()));
}
- cookies.swap(tcookies);
+ return tcookies;
}
} // namespace aria2
diff --git a/src/Sqlite3CookieParser.h b/src/Sqlite3CookieParser.h
index 24b590df..b83a2175 100644
--- a/src/Sqlite3CookieParser.h
+++ b/src/Sqlite3CookieParser.h
@@ -39,6 +39,7 @@
#include <string>
#include <vector>
+#include <memory>
#include <sqlite3.h>
@@ -55,7 +56,7 @@ 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);
+ std::vector<std::unique_ptr<Cookie>> parse();
protected:
// Returns SQL select statement to get 1 record of cookie. The sql
// must return 6 columns in the following order: host, path,
diff --git a/src/cookie_helper.cc b/src/cookie_helper.cc
index bec1dba0..58a4c69c 100644
--- a/src/cookie_helper.cc
+++ b/src/cookie_helper.cc
@@ -216,9 +216,8 @@ bool parseDate
return time != -1;
}
-bool parse
-(Cookie& cookie,
- const std::string& cookieStr,
+std::unique_ptr<Cookie> parse
+(const std::string& cookieStr,
const std::string& requestHost,
const std::string& defaultPath,
time_t creationTime)
@@ -231,13 +230,13 @@ bool parse
std::string::const_iterator eq = cookieStr.begin();
for(; eq != nvEnd && *eq != '='; ++eq);
if(eq == nvEnd) {
- return false;
+ return std::unique_ptr<Cookie>{};
}
std::pair<std::string::const_iterator,
std::string::const_iterator> p =
util::stripIter(cookieStr.begin(), eq);
if(p.first == p.second) {
- return false;
+ return std::unique_ptr<Cookie>{};
}
Scip cookieName(p.first, p.second);
p = util::stripIter(eq+1, nvEnd);
@@ -276,18 +275,18 @@ bool parse
if(parseDate(expiryTime, attrp.first, attrp.second)) {
foundExpires = true;
} else {
- return false;
+ return std::unique_ptr<Cookie>{};
}
} else if(util::strieq(p.first, p.second, "max-age")) {
if(attrp.first == attrp.second ||
(!in(static_cast<unsigned char>(*attrp.first), 0x30u, 0x39u) &&
*attrp.first != '-')) {
- return false;
+ return std::unique_ptr<Cookie>{};
}
for(std::string::const_iterator s = attrp.first+1,
eos = attrp.second; s != eos; ++s) {
if(!in(static_cast<unsigned char>(*s), 0x30u, 0x39u)) {
- return false;
+ return std::unique_ptr<Cookie>{};
}
}
int64_t delta;
@@ -306,17 +305,17 @@ bool parse
}
}
} else {
- return false;
+ return std::unique_ptr<Cookie>{};
}
} else if(util::strieq(p.first, p.second, "domain")) {
if(attrp.first == attrp.second) {
- return false;
+ return std::unique_ptr<Cookie>{};
}
std::string::const_iterator noDot = attrp.first;
std::string::const_iterator end = attrp.second;
for(; noDot != end && *noDot == '.'; ++noDot);
if(noDot == end) {
- return false;
+ return std::unique_ptr<Cookie>{};
}
cookieDomain.assign(noDot, end);
} else if(util::strieq(p.first, p.second, "path")) {
@@ -349,26 +348,27 @@ bool parse
} else if(domainMatch(canonicalizedHost, cookieDomain)) {
hostOnly = util::isNumericHost(canonicalizedHost);
} else {
- return false;
+ return std::unique_ptr<Cookie>{};
}
if(cookiePath.empty()) {
cookiePath = defaultPath;
}
- cookie.setName(cookieName.first, cookieName.second);
- cookie.setValue(cookieValue.first, cookieValue.second);
- cookie.setExpiryTime(expiryTime);
- cookie.setPersistent(persistent);
- cookie.setDomain(cookieDomain);
- cookie.setHostOnly(hostOnly);
- cookie.setPath(cookiePath);
- cookie.setSecure(secure);
- cookie.setHttpOnly(httpOnly);
- cookie.setCreationTime(creationTime);
- cookie.setLastAccessTime(creationTime);
+ auto cookie = make_unique<Cookie>();
+ cookie->setName(cookieName.first, cookieName.second);
+ cookie->setValue(cookieValue.first, cookieValue.second);
+ cookie->setExpiryTime(expiryTime);
+ cookie->setPersistent(persistent);
+ cookie->setDomain(std::move(cookieDomain));
+ cookie->setHostOnly(hostOnly);
+ cookie->setPath(std::move(cookiePath));
+ cookie->setSecure(secure);
+ cookie->setHttpOnly(httpOnly);
+ cookie->setCreationTime(creationTime);
+ cookie->setLastAccessTime(creationTime);
- return true;
+ return cookie;
}
bool goodPath
diff --git a/src/cookie_helper.h b/src/cookie_helper.h
index 7e481f53..79264b09 100644
--- a/src/cookie_helper.h
+++ b/src/cookie_helper.h
@@ -38,6 +38,7 @@
#include "common.h"
#include <string>
+#include <memory>
#include "a2time.h"
@@ -52,9 +53,8 @@ bool parseDate
std::string::const_iterator first,
std::string::const_iterator last);
-bool parse
-(Cookie& cookie,
- const std::string& cookieStr,
+std::unique_ptr<Cookie> parse
+(const std::string& cookieStr,
const std::string& requestHost,
const std::string& defaultPath,
time_t creationTime);