NetworkCookie: set the default path according to RFC 6265

This commit is contained in:
Hamish Morrison
2013-02-09 16:02:15 +00:00
parent 2e7b5f9e18
commit 05f42aaba4
2 changed files with 89 additions and 68 deletions
+14 -13
View File
@@ -24,13 +24,13 @@ public:
BNetworkCookie(BMessage* archive); BNetworkCookie(BMessage* archive);
BNetworkCookie(); BNetworkCookie();
virtual ~BNetworkCookie(); virtual ~BNetworkCookie();
// Parse a "SetCookie" string, or "name=value" // Parse a "SetCookie" string, or "name=value"
BNetworkCookie& ParseCookieStringFromUrl(const BString& string, BNetworkCookie& ParseCookieStringFromUrl(const BString& string,
const BUrl& url); const BUrl& url);
BNetworkCookie& ParseCookieString(const BString& cookieString); BNetworkCookie& ParseCookieString(const BString& cookieString);
// Modify the cookie fields // Modify the cookie fields
BNetworkCookie& SetComment(const BString& comment); BNetworkCookie& SetComment(const BString& comment);
BNetworkCookie& SetCommentUrl(const BString& commentUrl); BNetworkCookie& SetCommentUrl(const BString& commentUrl);
@@ -44,7 +44,7 @@ public:
BNetworkCookie& SetVersion(int8 version); BNetworkCookie& SetVersion(int8 version);
BNetworkCookie& SetName(const BString& name); BNetworkCookie& SetName(const BString& name);
BNetworkCookie& SetValue(const BString& value); BNetworkCookie& SetValue(const BString& value);
// Access the cookie fields // Access the cookie fields
const BString& CommentUrl() const; const BString& CommentUrl() const;
const BString& Comment() const; const BString& Comment() const;
@@ -64,7 +64,7 @@ public:
bool IsValidForUrl(const BUrl& url) const; bool IsValidForUrl(const BUrl& url) const;
bool IsValidForDomain(const BString& domain) const; bool IsValidForDomain(const BString& domain) const;
bool IsValidForPath(const BString& path) const; bool IsValidForPath(const BString& path) const;
// Test if cookie fields are defined // Test if cookie fields are defined
bool HasCommentUrl() const; bool HasCommentUrl() const;
bool HasComment() const; bool HasComment() const;
@@ -76,16 +76,16 @@ public:
bool HasVersion() const; bool HasVersion() const;
bool HasName() const; bool HasName() const;
bool HasValue() const; bool HasValue() const;
// Test if cookie could be deleted // Test if cookie could be deleted
bool ShouldDeleteAtExit() const; bool ShouldDeleteAtExit() const;
bool ShouldDeleteNow() const; bool ShouldDeleteNow() const;
// BArchivable members // BArchivable members
virtual status_t Archive(BMessage* into, virtual status_t Archive(BMessage* into,
bool deep = true) const; bool deep = true) const;
static BArchivable* Instantiate(BMessage* archive); static BArchivable* Instantiate(BMessage* archive);
// Overloaded operators // Overloaded operators
BNetworkCookie& operator=(const BNetworkCookie& other); BNetworkCookie& operator=(const BNetworkCookie& other);
BNetworkCookie& operator=(const char* string); BNetworkCookie& operator=(const char* string);
@@ -94,15 +94,16 @@ public:
private: private:
void _Reset(); void _Reset();
void _ExtractNameValuePair( void _ExtractNameValuePair(
const BString& cookieString, int16* index, const BString& cookieString, int16* index,
bool parseField = false); bool parseField = false);
void _SetDefaultPathForUrl(const BUrl& url);
private: private:
mutable BString fRawCookie; mutable BString fRawCookie;
mutable bool fRawCookieValid; mutable bool fRawCookieValid;
mutable BString fRawFullCookie; mutable BString fRawFullCookie;
mutable bool fRawFullCookieValid; mutable bool fRawFullCookieValid;
BString fComment; BString fComment;
BString fCommentUrl; BString fCommentUrl;
bool fDiscard; bool fDiscard;
@@ -115,7 +116,7 @@ private:
int8 fVersion; int8 fVersion;
BString fName; BString fName;
BString fValue; BString fValue;
bool fHasDiscard; bool fHasDiscard;
bool fHasExpirationDate; bool fHasExpirationDate;
bool fSessionCookie; bool fSessionCookie;
+75 -55
View File
@@ -32,7 +32,7 @@ static const char* kArchivedCookieValue = "be:cookie.value";
BNetworkCookie::BNetworkCookie(const char* name, const char* value) BNetworkCookie::BNetworkCookie(const char* name, const char* value)
: :
fDiscard(false), fDiscard(false),
fExpiration(BDateTime::CurrentDateTime(B_GMT_TIME)), fExpiration(BDateTime::CurrentDateTime(B_GMT_TIME)),
fVersion(0), fVersion(0),
@@ -45,7 +45,7 @@ BNetworkCookie::BNetworkCookie(const char* name, const char* value)
BNetworkCookie::BNetworkCookie(const BNetworkCookie& other) BNetworkCookie::BNetworkCookie(const BNetworkCookie& other)
: :
BArchivable(), BArchivable(),
fDiscard(false), fDiscard(false),
fExpiration(BDateTime::CurrentDateTime(B_GMT_TIME)), fExpiration(BDateTime::CurrentDateTime(B_GMT_TIME)),
@@ -58,7 +58,7 @@ BNetworkCookie::BNetworkCookie(const BNetworkCookie& other)
BNetworkCookie::BNetworkCookie(const BString& cookieString) BNetworkCookie::BNetworkCookie(const BString& cookieString)
: :
fDiscard(false), fDiscard(false),
fExpiration(BDateTime::CurrentDateTime(B_GMT_TIME)), fExpiration(BDateTime::CurrentDateTime(B_GMT_TIME)),
fVersion(0), fVersion(0),
@@ -71,7 +71,7 @@ BNetworkCookie::BNetworkCookie(const BString& cookieString)
BNetworkCookie::BNetworkCookie(const BString& cookieString, BNetworkCookie::BNetworkCookie(const BString& cookieString,
const BUrl& url) const BUrl& url)
: :
fDiscard(false), fDiscard(false),
fExpiration(BDateTime::CurrentDateTime(B_GMT_TIME)), fExpiration(BDateTime::CurrentDateTime(B_GMT_TIME)),
fVersion(0), fVersion(0),
@@ -83,29 +83,29 @@ BNetworkCookie::BNetworkCookie(const BString& cookieString,
BNetworkCookie::BNetworkCookie(BMessage* archive) BNetworkCookie::BNetworkCookie(BMessage* archive)
: :
fDiscard(false), fDiscard(false),
fExpiration(BDateTime::CurrentDateTime(B_GMT_TIME)), fExpiration(BDateTime::CurrentDateTime(B_GMT_TIME)),
fVersion(0), fVersion(0),
fSessionCookie(true) fSessionCookie(true)
{ {
_Reset(); _Reset();
archive->FindString(kArchivedCookieName, &fName); archive->FindString(kArchivedCookieName, &fName);
archive->FindString(kArchivedCookieValue, &fValue); archive->FindString(kArchivedCookieValue, &fValue);
archive->FindString(kArchivedCookieComment, &fComment); archive->FindString(kArchivedCookieComment, &fComment);
archive->FindString(kArchivedCookieCommentUrl, &fCommentUrl); archive->FindString(kArchivedCookieCommentUrl, &fCommentUrl);
archive->FindString(kArchivedCookieDomain, &fDomain); archive->FindString(kArchivedCookieDomain, &fDomain);
archive->FindString(kArchivedCookiePath, &fPath); archive->FindString(kArchivedCookiePath, &fPath);
archive->FindBool(kArchivedCookieSecure, &fSecure); archive->FindBool(kArchivedCookieSecure, &fSecure);
if (archive->FindBool(kArchivedCookieDiscard, &fDiscard) == B_OK) if (archive->FindBool(kArchivedCookieDiscard, &fDiscard) == B_OK)
fHasDiscard = true; fHasDiscard = true;
if (archive->FindInt8(kArchivedCookieVersion, &fVersion) == B_OK) if (archive->FindInt8(kArchivedCookieVersion, &fVersion) == B_OK)
fHasVersion = true; fHasVersion = true;
int32 expiration; int32 expiration;
if (archive->FindInt32(kArchivedCookieExpirationDate, &expiration) if (archive->FindInt32(kArchivedCookieExpirationDate, &expiration)
== B_OK) { == B_OK) {
@@ -115,7 +115,7 @@ BNetworkCookie::BNetworkCookie(BMessage* archive)
BNetworkCookie::BNetworkCookie() BNetworkCookie::BNetworkCookie()
: :
fDiscard(false), fDiscard(false),
fExpiration(BDateTime::CurrentDateTime(B_GMT_TIME)), fExpiration(BDateTime::CurrentDateTime(B_GMT_TIME)),
fPath("/"), fPath("/"),
@@ -140,19 +140,19 @@ BNetworkCookie::ParseCookieStringFromUrl(const BString& string,
{ {
BString cookieString(string); BString cookieString(string);
int16 index = 0; int16 index = 0;
_Reset(); _Reset();
// Default values from url // Default values from url
SetDomain(url.Host()); SetDomain(url.Host());
SetPath(url.Path()); _SetDefaultPathForUrl(url);
_ExtractNameValuePair(cookieString, &index); _ExtractNameValuePair(cookieString, &index);
while (index < cookieString.Length()) while (index < cookieString.Length())
_ExtractNameValuePair(cookieString, &index, true); _ExtractNameValuePair(cookieString, &index, true);
return *this; return *this;
} }
@@ -200,11 +200,11 @@ BNetworkCookie&
BNetworkCookie::SetDomain(const BString& domain) BNetworkCookie::SetDomain(const BString& domain)
{ {
fDomain = domain; fDomain = domain;
// We always use pre-dotted domains for tail matching // We always use pre-dotted domains for tail matching
if (fDomain.ByteAt(0) != '.') if (fDomain.ByteAt(0) != '.')
fDomain.Prepend("."); fDomain.Prepend(".");
fRawFullCookieValid = false; fRawFullCookieValid = false;
return *this; return *this;
} }
@@ -244,7 +244,7 @@ BNetworkCookie::SetExpirationDate(BDateTime& expireDate)
fRawFullCookieValid = false; fRawFullCookieValid = false;
fHasExpirationDate = true; fHasExpirationDate = true;
} }
return *this; return *this;
} }
@@ -346,12 +346,12 @@ const BString&
BNetworkCookie::ExpirationString() const BNetworkCookie::ExpirationString() const
{ {
BHttpTime date(ExpirationDate()); BHttpTime date(ExpirationDate());
if (!fExpirationStringValid) { if (!fExpirationStringValid) {
fExpirationString = date.ToString(BPrivate::B_HTTP_TIME_FORMAT_COOKIE); fExpirationString = date.ToString(BPrivate::B_HTTP_TIME_FORMAT_COOKIE);
fExpirationStringValid = true; fExpirationStringValid = true;
} }
return fExpirationString; return fExpirationString;
} }
@@ -397,9 +397,9 @@ BNetworkCookie::RawCookie(bool full) const
if (full && !fRawFullCookieValid) { if (full && !fRawFullCookieValid) {
fRawFullCookie.Truncate(0); fRawFullCookie.Truncate(0);
fRawFullCookieValid = true; fRawFullCookieValid = true;
fRawFullCookie << fName << "=" << fValue; fRawFullCookie << fName << "=" << fValue;
if (HasCommentUrl()) if (HasCommentUrl())
fRawFullCookie << "; Comment-Url=" << fCommentUrl; fRawFullCookie << "; Comment-Url=" << fCommentUrl;
if (HasComment()) if (HasComment())
@@ -417,11 +417,11 @@ BNetworkCookie::RawCookie(bool full) const
fRawFullCookie << "; Secure=" << (fSecure?"true":"false"); fRawFullCookie << "; Secure=" << (fSecure?"true":"false");
if (HasVersion()) if (HasVersion())
fRawFullCookie << ", Version=" << fVersion; fRawFullCookie << ", Version=" << fVersion;
} else if (!full && !fRawCookieValid) { } else if (!full && !fRawCookieValid) {
fRawCookie.Truncate(0); fRawCookie.Truncate(0);
fRawCookieValid = true; fRawCookieValid = true;
fRawCookie << fName << "=" << fValue; fRawCookie << fName << "=" << fValue;
} }
@@ -451,7 +451,7 @@ BNetworkCookie::IsValidForUrl(const BUrl& url) const
{ {
BString urlHost = url.Host(); BString urlHost = url.Host();
BString urlPath = url.Path(); BString urlPath = url.Path();
return IsValidForDomain(urlHost) && IsValidForPath(urlPath); return IsValidForDomain(urlHost) && IsValidForPath(urlPath);
} }
@@ -461,7 +461,7 @@ BNetworkCookie::IsValidForDomain(const BString& domain) const
{ {
if (fDomain.Length() > domain.Length()) if (fDomain.Length() > domain.Length())
return false; return false;
return domain.FindLast(fDomain) == (domain.Length() - fDomain.Length()); return domain.FindLast(fDomain) == (domain.Length() - fDomain.Length());
} }
@@ -471,7 +471,7 @@ BNetworkCookie::IsValidForPath(const BString& path) const
{ {
if (fPath.Length() > path.Length()) if (fPath.Length() > path.Length())
return false; return false;
return path.FindFirst(fPath) == 0; return path.FindFirst(fPath) == 0;
} }
@@ -559,7 +559,7 @@ BNetworkCookie::ShouldDeleteNow() const
{ {
if (!IsSessionCookie() && HasExpirationDate()) if (!IsSessionCookie() && HasExpirationDate())
return (BDateTime::CurrentDateTime(B_GMT_TIME) > fExpiration); return (BDateTime::CurrentDateTime(B_GMT_TIME) > fExpiration);
return false; return false;
} }
@@ -574,60 +574,60 @@ BNetworkCookie::Archive(BMessage* into, bool deep) const
if (error != B_OK) if (error != B_OK)
return error; return error;
error = into->AddString(kArchivedCookieName, fName); error = into->AddString(kArchivedCookieName, fName);
if (error != B_OK) if (error != B_OK)
return error; return error;
error = into->AddString(kArchivedCookieValue, fValue); error = into->AddString(kArchivedCookieValue, fValue);
if (error != B_OK) if (error != B_OK)
return error; return error;
// We add optional fields only if they're defined // We add optional fields only if they're defined
if (HasComment()) { if (HasComment()) {
error = into->AddString(kArchivedCookieComment, fComment); error = into->AddString(kArchivedCookieComment, fComment);
if (error != B_OK) if (error != B_OK)
return error; return error;
} }
if (HasCommentUrl()) { if (HasCommentUrl()) {
error = into->AddString(kArchivedCookieCommentUrl, fCommentUrl); error = into->AddString(kArchivedCookieCommentUrl, fCommentUrl);
if (error != B_OK) if (error != B_OK)
return error; return error;
} }
if (HasDiscard()) { if (HasDiscard()) {
error = into->AddBool(kArchivedCookieDiscard, fDiscard); error = into->AddBool(kArchivedCookieDiscard, fDiscard);
if (error != B_OK) if (error != B_OK)
return error; return error;
} }
if (HasDomain()) { if (HasDomain()) {
error = into->AddString(kArchivedCookieDomain, fDomain); error = into->AddString(kArchivedCookieDomain, fDomain);
if (error != B_OK) if (error != B_OK)
return error; return error;
} }
if (fHasExpirationDate) { if (fHasExpirationDate) {
error = into->AddInt32(kArchivedCookieExpirationDate, error = into->AddInt32(kArchivedCookieExpirationDate,
fExpiration.Time_t()); fExpiration.Time_t());
if (error != B_OK) if (error != B_OK)
return error; return error;
} }
if (HasPath()) { if (HasPath()) {
error = into->AddString(kArchivedCookiePath, fPath); error = into->AddString(kArchivedCookiePath, fPath);
if (error != B_OK) if (error != B_OK)
return error; return error;
} }
if (Secure()) { if (Secure()) {
error = into->AddBool(kArchivedCookieSecure, fSecure); error = into->AddBool(kArchivedCookieSecure, fSecure);
if (error != B_OK) if (error != B_OK)
return error; return error;
} }
if (HasVersion()) { if (HasVersion()) {
error = into->AddInt8(kArchivedCookieVersion, fVersion); error = into->AddInt8(kArchivedCookieVersion, fVersion);
if (error != B_OK) if (error != B_OK)
@@ -652,7 +652,7 @@ BNetworkCookie::Instantiate(BMessage* archive)
// #pragma mark Overloaded operators // #pragma mark Overloaded operators
BNetworkCookie& BNetworkCookie&
BNetworkCookie::operator=(const BNetworkCookie& other) BNetworkCookie::operator=(const BNetworkCookie& other)
{ {
// Should we prefer to discard the cache ? // Should we prefer to discard the cache ?
@@ -662,7 +662,7 @@ BNetworkCookie::operator=(const BNetworkCookie& other)
fRawFullCookieValid = other.fRawFullCookieValid; fRawFullCookieValid = other.fRawFullCookieValid;
fExpirationString = other.fExpirationString; fExpirationString = other.fExpirationString;
fExpirationStringValid = other.fExpirationStringValid; fExpirationStringValid = other.fExpirationStringValid;
fComment = other.fComment; fComment = other.fComment;
fCommentUrl = other.fCommentUrl; fCommentUrl = other.fCommentUrl;
fDiscard = other.fDiscard; fDiscard = other.fDiscard;
@@ -673,12 +673,12 @@ BNetworkCookie::operator=(const BNetworkCookie& other)
fVersion = other.fVersion; fVersion = other.fVersion;
fName = other.fName; fName = other.fName;
fValue = other.fValue; fValue = other.fValue;
fHasDiscard = other.fHasDiscard; fHasDiscard = other.fHasDiscard;
fHasExpirationDate = other.fHasExpirationDate; fHasExpirationDate = other.fHasExpirationDate;
fSessionCookie = other.fSessionCookie; fSessionCookie = other.fSessionCookie;
fHasVersion = other.fHasVersion; fHasVersion = other.fHasVersion;
return *this; return *this;
} }
@@ -723,7 +723,7 @@ BNetworkCookie::_Reset()
fHasExpirationDate = false; fHasExpirationDate = false;
fSessionCookie = true; fSessionCookie = true;
fHasVersion = false; fHasVersion = false;
fRawCookieValid = false; fRawCookieValid = false;
fRawFullCookieValid = false; fRawFullCookieValid = false;
fExpirationStringValid = false; fExpirationStringValid = false;
@@ -731,32 +731,32 @@ BNetworkCookie::_Reset()
void void
BNetworkCookie::_ExtractNameValuePair(const BString& cookieString, BNetworkCookie::_ExtractNameValuePair(const BString& cookieString,
int16* index, bool parseField) int16* index, bool parseField)
{ {
// Skip whitespaces // Skip whitespaces
while (cookieString.ByteAt(*index) == ' ' while (cookieString.ByteAt(*index) == ' '
&& *index < cookieString.Length()) && *index < cookieString.Length())
(*index)++; (*index)++;
if (*index >= cookieString.Length()) if (*index >= cookieString.Length())
return; return;
// Look for a name=value pair // Look for a name=value pair
int16 firstSemiColon = cookieString.FindFirst(";", *index); int16 firstSemiColon = cookieString.FindFirst(";", *index);
int16 firstEqual = cookieString.FindFirst("=", *index); int16 firstEqual = cookieString.FindFirst("=", *index);
BString name; BString name;
BString value; BString value;
if (firstSemiColon == -1) { if (firstSemiColon == -1) {
if (firstEqual != -1) { if (firstEqual != -1) {
cookieString.CopyInto(name, *index, firstEqual - *index); cookieString.CopyInto(name, *index, firstEqual - *index);
cookieString.CopyInto(value, firstEqual + 1, cookieString.CopyInto(value, firstEqual + 1,
cookieString.Length() - firstEqual - 1); cookieString.Length() - firstEqual - 1);
} else } else
cookieString.CopyInto(value, *index, cookieString.CopyInto(value, *index,
cookieString.Length() - *index); cookieString.Length() - *index);
*index = cookieString.Length() + 1; *index = cookieString.Length() + 1;
@@ -799,7 +799,7 @@ BNetworkCookie::_ExtractNameValuePair(const BString& cookieString,
BHttpTime date(value); BHttpTime date(value);
SetExpirationDate(date.Parse()); SetExpirationDate(date.Parse());
// Cookie valid domain // Cookie valid domain
} else if (name == "domain") } else if (name == "domain")
SetDomain(value); SetDomain(value);
// Cookie valid path // Cookie valid path
else if (name == "path") else if (name == "path")
@@ -811,3 +811,23 @@ BNetworkCookie::_ExtractNameValuePair(const BString& cookieString,
else if (name == "version") else if (name == "version")
SetVersion(atoi(value.String())); SetVersion(atoi(value.String()));
} }
void
BNetworkCookie::_SetDefaultPathForUrl(const BUrl& url)
{
const BString& path = url.Path();
if (path.IsEmpty() || path.ByteAt(0) != '/') {
SetPath("/");
return;
}
int32 index = path.FindLast('/');
if (index == 0) {
SetPath("/");
return;
}
BString newPath = path;
SetPath(newPath.Truncate(index));
}