diff --git a/headers/os/net/NetworkCookie.h b/headers/os/net/NetworkCookie.h index 168c9b10e4..dc9b78d9c1 100644 --- a/headers/os/net/NetworkCookie.h +++ b/headers/os/net/NetworkCookie.h @@ -17,109 +17,96 @@ class BNetworkCookie : public BArchivable { public: BNetworkCookie(const char* name, const char* value); - BNetworkCookie(const BNetworkCookie& other); BNetworkCookie(const BString& cookieString); BNetworkCookie(const BString& cookieString, const BUrl& url); BNetworkCookie(BMessage* archive); BNetworkCookie(); virtual ~BNetworkCookie(); - - // Parse a "SetCookie" string, or "name=value" - - BNetworkCookie& ParseCookieStringFromUrl(const BString& string, + + // Parse a "SetCookie" string + + BNetworkCookie& ParseCookieStringFromUrl(const BString& string, const BUrl& url); BNetworkCookie& ParseCookieString(const BString& cookieString); - + // Modify the cookie fields - BNetworkCookie& SetComment(const BString& comment); - BNetworkCookie& SetCommentUrl(const BString& commentUrl); - BNetworkCookie& SetDiscard(bool discard); + BNetworkCookie& SetName(const BString& name); + BNetworkCookie& SetValue(const BString& value); BNetworkCookie& SetDomain(const BString& domain); + BNetworkCookie& SetPath(const BString& path); BNetworkCookie& SetMaxAge(int32 maxAge); BNetworkCookie& SetExpirationDate(time_t expireDate); BNetworkCookie& SetExpirationDate(BDateTime& expireDate); - BNetworkCookie& SetPath(const BString& path); BNetworkCookie& SetSecure(bool secure); - BNetworkCookie& SetVersion(int8 version); - BNetworkCookie& SetName(const BString& name); - BNetworkCookie& SetValue(const BString& value); - + BNetworkCookie& SetHttpOnly(bool httpOnly); + // Access the cookie fields - const BString& CommentUrl() const; - const BString& Comment() const; - bool Discard() const; - const BString& Domain() const; - int32 MaxAge() const; - time_t ExpirationDate() const; - const BString& ExpirationString() const; - const BString& Path() const; - bool Secure() const; - int8 Version() const; const BString& Name() const; const BString& Value() const; + const BString& Domain() const; + const BString& Path() const; + time_t ExpirationDate() const; + const BString& ExpirationString() const; + bool Secure() const; + bool HttpOnly() const; const BString& RawCookie(bool full) const; + + bool IsHostOnly() const; bool IsSessionCookie() const; - bool IsValid(bool strict = false) const; + bool IsValid() const; bool IsValidForUrl(const BUrl& url) const; bool IsValidForDomain(const BString& domain) const; bool IsValidForPath(const BString& path) const; - + // Test if cookie fields are defined - bool HasCommentUrl() const; - bool HasComment() const; - bool HasDiscard() const; - bool HasDomain() const; - bool HasMaxAge() const; - bool HasExpirationDate() const; - bool HasPath() const; - bool HasVersion() const; bool HasName() const; bool HasValue() const; - + bool HasDomain() const; + bool HasPath() const; + bool HasExpirationDate() const; + // Test if cookie could be deleted bool ShouldDeleteAtExit() const; bool ShouldDeleteNow() const; - + // BArchivable members virtual status_t Archive(BMessage* into, bool deep = true) const; static BArchivable* Instantiate(BMessage* archive); - + // Overloaded operators - BNetworkCookie& operator=(const BNetworkCookie& other); BNetworkCookie& operator=(const char* string); bool operator==(const BNetworkCookie& other); bool operator!=(const BNetworkCookie& other); private: void _Reset(); - void _ExtractNameValuePair( - const BString& cookieString, int16* index, - bool parseField = false); - + int32 _ExtractNameValuePair(const BString& string, + BString& name, BString& value, + int32 index); + int32 _ExtractAttributeValuePair( + const BString& string, BString& name, + BString& value, int32 index); + BString _DefaultPathForUrl(const BUrl& url); + private: mutable BString fRawCookie; mutable bool fRawCookieValid; mutable BString fRawFullCookie; mutable bool fRawFullCookieValid; - - BString fComment; - BString fCommentUrl; - bool fDiscard; - BString fDomain; - BDateTime fExpiration; mutable BString fExpirationString; mutable bool fExpirationStringValid; - BString fPath; - bool fSecure; - int8 fVersion; + BString fName; BString fValue; - - bool fHasDiscard; - bool fHasExpirationDate; + BString fDomain; + BString fPath; + BDateTime fExpiration; + bool fSecure; + bool fHttpOnly; + + bool fHostOnly; bool fSessionCookie; - bool fHasVersion; }; #endif // _B_NETWORK_COOKIE_H_ diff --git a/headers/os/net/NetworkCookieJar.h b/headers/os/net/NetworkCookieJar.h index 31cd196a5b..9c3e775f7d 100644 --- a/headers/os/net/NetworkCookieJar.h +++ b/headers/os/net/NetworkCookieJar.h @@ -1,5 +1,5 @@ /* - * Copyright 2010 Haiku Inc. All rights reserved. + * Copyright 2010-2013 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. */ #ifndef _B_NETWORK_COOKIE_JAR_H_ @@ -24,7 +24,7 @@ public: class UrlIterator; struct PrivateIterator; struct PrivateHashMap; - + public: BNetworkCookieJar(); BNetworkCookieJar( @@ -34,16 +34,15 @@ public: BNetworkCookieJar(BMessage* archive); virtual ~BNetworkCookieJar(); - bool AddCookie(const BNetworkCookie& cookie); - bool AddCookie(BNetworkCookie* cookie); - bool AddCookies( - const BNetworkCookieList& cookies); + status_t AddCookie(const BNetworkCookie& cookie); + status_t AddCookie(BNetworkCookie* cookie); + status_t AddCookies(const BNetworkCookieList& cookies); uint32 DeleteOutdatedCookies(); uint32 PurgeForExit(); // BArchivable members - virtual status_t Archive(BMessage* into, + virtual status_t Archive(BMessage* into, bool deep = true) const; static BArchivable* Instantiate(BMessage* archive); @@ -54,20 +53,20 @@ public: virtual status_t Flatten(void* buffer, ssize_t size) const; virtual bool AllowsTypeCode(type_code code) const; - virtual status_t Unflatten(type_code code, + virtual status_t Unflatten(type_code code, const void* buffer, ssize_t size); // Iterators Iterator GetIterator() const; UrlIterator GetUrlIterator(const BUrl& url) const; - + private: void _DoFlatten() const; - + private: friend class Iterator; friend class UrlIterator; - + PrivateHashMap* fCookieHashMap; mutable BString fFlattened; }; @@ -117,7 +116,7 @@ private: UrlIterator(const BNetworkCookieJar* map, const BUrl& url); - bool _SupDomain(); + bool _SuperDomain(); void _FindNext(); void _FindDomain(); bool _FindPath(); @@ -131,10 +130,10 @@ private: BNetworkCookieList* fLastList; BNetworkCookie* fElement; BNetworkCookie* fLastElement; - + int32 fIndex; int32 fLastIndex; - + BUrl fUrl; }; diff --git a/src/apps/terminal/AppearPrefView.cpp b/src/apps/terminal/AppearPrefView.cpp index 3c3d23bc78..fa58dae14e 100644 --- a/src/apps/terminal/AppearPrefView.cpp +++ b/src/apps/terminal/AppearPrefView.cpp @@ -73,12 +73,12 @@ AppearancePrefView::AppearancePrefView(const char* name, fTerminalMessenger(messenger) { const char* kColorTable[] = { - B_TRANSLATE("Text"), - B_TRANSLATE("Background"), - B_TRANSLATE("Cursor"), - B_TRANSLATE("Text under cursor"), - B_TRANSLATE("Selected text"), - B_TRANSLATE("Selected background"), + B_TRANSLATE_MARK("Text"), + B_TRANSLATE_MARK("Background"), + B_TRANSLATE_MARK("Cursor"), + B_TRANSLATE_MARK("Text under cursor"), + B_TRANSLATE_MARK("Selected text"), + B_TRANSLATE_MARK("Selected background"), NULL }; @@ -272,11 +272,14 @@ AppearancePrefView::MessageReceived(BMessage* msg) case MSG_COLOR_CHANGED: { - rgb_color oldColor = PrefHandler::Default()->getRGB( - fColorField->Menu()->FindMarked()->Label()); + const BMessage* itemMessage + = fColorField->Menu()->FindMarked()->Message(); + const char* label = NULL; + if (itemMessage->FindString("label", &label) != B_OK) + break; + rgb_color oldColor = PrefHandler::Default()->getRGB(label); if (oldColor != fColorControl->ValueAsColor()) { - PrefHandler::Default()->setRGB( - fColorField->Menu()->FindMarked()->Label(), + PrefHandler::Default()->setRGB(label, fColorControl->ValueAsColor()); modified = true; } @@ -300,9 +303,12 @@ AppearancePrefView::MessageReceived(BMessage* msg) } case MSG_COLOR_FIELD_CHANGED: - fColorControl->SetValue(PrefHandler::Default()->getRGB( - fColorField->Menu()->FindMarked()->Label())); + { + const char* label = NULL; + if (msg->FindString("label", &label) == B_OK) + fColorControl->SetValue(PrefHandler::Default()->getRGB(label)); break; + } case MSG_BLINK_CURSOR_CHANGED: if (PrefHandler::Default()->getBool(PREF_BLINK_CURSOR) @@ -514,23 +520,21 @@ AppearancePrefView::_MakeMenu(uint32 msg, const char** items, { BPopUpMenu* menu = new BPopUpMenu(""); - int32 i = 0; while (*items) { if (strcmp((*items), "") == 0) menu->AddSeparatorItem(); else { BMessage* message = new BMessage(msg); - menu->AddItem(new BMenuItem((*items), message)); + message->AddString("label", *items); + BMenuItem* item = new BMenuItem(B_TRANSLATE(*items), message); + menu->AddItem(item); + if (strcmp(*items, defaultItemName) == 0) + item->SetMarked(true); } items++; - i++; } - BMenuItem* defaultItem = menu->FindItem(defaultItemName); - if (defaultItem) - defaultItem->SetMarked(true); - return menu; } diff --git a/src/kits/network/libnetapi/NetworkCookie.cpp b/src/kits/network/libnetapi/NetworkCookie.cpp index 16fad675fa..25b5e5c36d 100644 --- a/src/kits/network/libnetapi/NetworkCookie.cpp +++ b/src/kits/network/libnetapi/NetworkCookie.cpp @@ -1,68 +1,44 @@ /* - * Copyright 2010 Haiku Inc. All rights reserved. + * Copyright 2010-2013 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Christophe Huriaux, c.huriaux@gmail.com + * Hamish Morrison, hamishm53@gmail.com */ -#include -#include #include +#include +#include +#include + +#include #include #include -#include -#define PRINT(x) printf x; - using BPrivate::BHttpTime; -static const char* kArchivedCookieComment = "be:cookie.comment"; -static const char* kArchivedCookieCommentUrl = "be:cookie.commenturl"; -static const char* kArchivedCookieDiscard = "be:cookie.discard"; -static const char* kArchivedCookieDomain = "be:cookie.domain"; -static const char* kArchivedCookieExpirationDate = "be:cookie.expiredate"; -static const char* kArchivedCookiePath = "be:cookie.path"; -static const char* kArchivedCookieSecure = "be:cookie.secure"; -static const char* kArchivedCookieVersion = "be:cookie.version"; -static const char* kArchivedCookieName = "be:cookie.name"; -static const char* kArchivedCookieValue = "be:cookie.value"; +static const char* kArchivedCookieName = "be:cookie.name"; +static const char* kArchivedCookieValue = "be:cookie.value"; +static const char* kArchivedCookieDomain = "be:cookie.domain"; +static const char* kArchivedCookiePath = "be:cookie.path"; +static const char* kArchivedCookieExpirationDate = "be:cookie.expirationdate"; +static const char* kArchivedCookieSecure = "be:cookie.secure"; +static const char* kArchivedCookieHttpOnly = "be:cookie.httponly"; +static const char* kArchivedCookieHostOnly = "be:cookie.hostonly"; BNetworkCookie::BNetworkCookie(const char* name, const char* value) - : - fDiscard(false), - fExpiration(BDateTime::CurrentDateTime(B_GMT_TIME)), - fVersion(0), - fName(name), - fValue(value), - fSessionCookie(true) { _Reset(); -} - - -BNetworkCookie::BNetworkCookie(const BNetworkCookie& other) - : - BArchivable(), - fDiscard(false), - fExpiration(BDateTime::CurrentDateTime(B_GMT_TIME)), - fVersion(0), - fSessionCookie(true) -{ - _Reset(); - *this = other; + fName = name; + fValue = value; } BNetworkCookie::BNetworkCookie(const BString& cookieString) - : - fDiscard(false), - fExpiration(BDateTime::CurrentDateTime(B_GMT_TIME)), - fVersion(0), - fSessionCookie(true) { _Reset(); ParseCookieString(cookieString); @@ -71,11 +47,6 @@ BNetworkCookie::BNetworkCookie(const BString& cookieString) BNetworkCookie::BNetworkCookie(const BString& cookieString, const BUrl& url) - : - fDiscard(false), - fExpiration(BDateTime::CurrentDateTime(B_GMT_TIME)), - fVersion(0), - fSessionCookie(true) { _Reset(); ParseCookieStringFromUrl(cookieString, url); @@ -83,29 +54,18 @@ BNetworkCookie::BNetworkCookie(const BString& cookieString, BNetworkCookie::BNetworkCookie(BMessage* archive) - : - fDiscard(false), - fExpiration(BDateTime::CurrentDateTime(B_GMT_TIME)), - fVersion(0), - fSessionCookie(true) { _Reset(); - + archive->FindString(kArchivedCookieName, &fName); archive->FindString(kArchivedCookieValue, &fValue); - - archive->FindString(kArchivedCookieComment, &fComment); - archive->FindString(kArchivedCookieCommentUrl, &fCommentUrl); + archive->FindString(kArchivedCookieDomain, &fDomain); archive->FindString(kArchivedCookiePath, &fPath); archive->FindBool(kArchivedCookieSecure, &fSecure); - - if (archive->FindBool(kArchivedCookieDiscard, &fDiscard) == B_OK) - fHasDiscard = true; - - if (archive->FindInt8(kArchivedCookieVersion, &fVersion) == B_OK) - fHasVersion = true; - + archive->FindBool(kArchivedCookieHttpOnly, &fHttpOnly); + archive->FindBool(kArchivedCookieHostOnly, &fHostOnly); + int32 expiration; if (archive->FindInt32(kArchivedCookieExpirationDate, &expiration) == B_OK) { @@ -115,12 +75,6 @@ BNetworkCookie::BNetworkCookie(BMessage* archive) BNetworkCookie::BNetworkCookie() - : - fDiscard(false), - fExpiration(BDateTime::CurrentDateTime(B_GMT_TIME)), - fPath("/"), - fVersion(0), - fSessionCookie(true) { _Reset(); } @@ -138,21 +92,75 @@ BNetworkCookie& BNetworkCookie::ParseCookieStringFromUrl(const BString& string, const BUrl& url) { - BString cookieString(string); - int16 index = 0; - _Reset(); - - // Default values from url - SetDomain(url.Host()); - SetPath(url.Path()); - - _ExtractNameValuePair(cookieString, &index); - while (index < cookieString.Length()) - _ExtractNameValuePair(cookieString, &index, true); - - return *this; + BString name; + BString value; + int32 index = 0; + + // Parse the name and value of the cookie + index = _ExtractNameValuePair(string, name, value, index); + if (index == -1) { + // The set-cookie-string is not valid + return *this; + } + + SetName(name); + SetValue(value); + + // Parse the remaining cookie attributes. + while (index < string.Length()) { + ASSERT(string[index] == ';'); + index++; + + index = _ExtractAttributeValuePair(string, name, value, index); + + if (name.ICompare("secure") == 0) + SetSecure(true); + else if (name.ICompare("httponly") == 0) + SetHttpOnly(true); + + // The following attributes require a value. + if (value.IsEmpty()) + continue; + + if (name.ICompare("max-age") == 0) { + // Validate the max-age value. + char* end = NULL; + long maxAge = strtol(value.String(), &end, 10); + if (*end == '\0') + SetMaxAge((int)maxAge); + } else if (name.ICompare("expires") == 0) { + BHttpTime date(value); + SetExpirationDate(date.Parse()); + } else if (name.ICompare("domain") == 0) { + SetDomain(value); + } else if (name.ICompare("path") == 0) { + SetPath(value); + } + } + + // If no domain was specified, we set a host-only domain from the URL. + if (!HasDomain()) { + SetDomain(url.Host()); + fHostOnly = true; + } else { + // Otherwise the setting URL must domain-match the domain it set. + if (!IsValidForDomain(url.Host())) { + // Invalidate the cookie. + _Reset(); + return *this; + } + // We should also reject cookies with domains that match public + // suffixes. + } + + // If no path was specified or the path is invalid, we compute the default + // path from the URL. + if (!HasPath() || Path()[0] != '/') + SetPath(_DefaultPathForUrl(url)); + + return *this; } @@ -169,28 +177,30 @@ BNetworkCookie::ParseCookieString(const BString& string) BNetworkCookie& -BNetworkCookie::SetComment(const BString& comment) +BNetworkCookie::SetName(const BString& name) { - fComment = comment; + fName = name; fRawFullCookieValid = false; + fRawCookieValid = false; return *this; } BNetworkCookie& -BNetworkCookie::SetCommentUrl(const BString& commentUrl) +BNetworkCookie::SetValue(const BString& value) { - fCommentUrl = commentUrl; + fValue = value; fRawFullCookieValid = false; + fRawCookieValid = false; return *this; } BNetworkCookie& -BNetworkCookie::SetDiscard(bool discard) +BNetworkCookie::SetPath(const BString& path) { - fDiscard = discard; - fHasDiscard = true; + // TODO: canonicalize the path + fPath = path; fRawFullCookieValid = false; return *this; } @@ -199,12 +209,10 @@ BNetworkCookie::SetDiscard(bool discard) BNetworkCookie& BNetworkCookie::SetDomain(const BString& domain) { + // TODO: canonicalize the domain fDomain = domain; - - // We always use pre-dotted domains for tail matching - if (fDomain.ByteAt(0) != '.') - fDomain.Prepend("."); - + fHostOnly = false; + fRawFullCookieValid = false; return *this; } @@ -236,24 +244,13 @@ BNetworkCookie::SetExpirationDate(BDateTime& expireDate) fSessionCookie = true; fExpirationStringValid = false; fRawFullCookieValid = false; - fHasExpirationDate = false; } else { fExpiration = expireDate; fSessionCookie = false; fExpirationStringValid = false; fRawFullCookieValid = false; - fHasExpirationDate = true; } - - return *this; -} - -BNetworkCookie& -BNetworkCookie::SetPath(const BString& path) -{ - fPath = path; - fRawFullCookieValid = false; return *this; } @@ -268,31 +265,10 @@ BNetworkCookie::SetSecure(bool secure) BNetworkCookie& -BNetworkCookie::SetVersion(int8 version) +BNetworkCookie::SetHttpOnly(bool httpOnly) { - fVersion = version; - fHasVersion = true; - fRawCookieValid = false; - return *this; -} - - -BNetworkCookie& -BNetworkCookie::SetName(const BString& name) -{ - fName = name; + fHttpOnly = httpOnly; fRawFullCookieValid = false; - fRawCookieValid = false; - return *this; -} - - -BNetworkCookie& -BNetworkCookie::SetValue(const BString& value) -{ - fValue = value; - fRawFullCookieValid = false; - fRawCookieValid = false; return *this; } @@ -300,83 +276,6 @@ BNetworkCookie::SetValue(const BString& value) // #pragma mark Cookie fields access -const BString& -BNetworkCookie::Comment() const -{ - return fComment; -} - - -const BString& -BNetworkCookie::CommentUrl() const -{ - return fCommentUrl; -} - - -bool -BNetworkCookie::Discard() const -{ - return fDiscard; -} - - -const BString& -BNetworkCookie::Domain() const -{ - return fDomain; -} - - -int32 -BNetworkCookie::MaxAge() const -{ - return fExpiration.Time_t() - BDateTime::CurrentDateTime(B_GMT_TIME).Time_t(); -} - - -time_t -BNetworkCookie::ExpirationDate() const -{ - return fExpiration.Time_t(); -} - - -const BString& -BNetworkCookie::ExpirationString() const -{ - BHttpTime date(ExpirationDate()); - - if (!fExpirationStringValid) { - fExpirationString = date.ToString(BPrivate::B_HTTP_TIME_FORMAT_COOKIE); - fExpirationStringValid = true; - } - - return fExpirationString; -} - - -const BString& -BNetworkCookie::Path() const -{ - return fPath; -} - - -bool -BNetworkCookie::Secure() const -{ - return fSecure; -} - - -int8 -BNetworkCookie::Version() const -{ - return fVersion; -} - - const BString& BNetworkCookie::Name() const { @@ -391,47 +290,96 @@ BNetworkCookie::Value() const } +const BString& +BNetworkCookie::Domain() const +{ + return fDomain; +} + + +const BString& +BNetworkCookie::Path() const +{ + return fPath; +} + + +time_t +BNetworkCookie::ExpirationDate() const +{ + return fExpiration.Time_t(); +} + + +const BString& +BNetworkCookie::ExpirationString() const +{ + BHttpTime date(ExpirationDate()); + + if (!fExpirationStringValid) { + fExpirationString = date.ToString(BPrivate::B_HTTP_TIME_FORMAT_COOKIE); + fExpirationStringValid = true; + } + + return fExpirationString; +} + + +bool +BNetworkCookie::Secure() const +{ + return fSecure; +} + + +bool +BNetworkCookie::HttpOnly() const +{ + return fHttpOnly; +} + + const BString& BNetworkCookie::RawCookie(bool full) const { if (full && !fRawFullCookieValid) { fRawFullCookie.Truncate(0); fRawFullCookieValid = true; - + fRawFullCookie << fName << "=" << fValue; - - if (HasCommentUrl()) - fRawFullCookie << "; Comment-Url=" << fCommentUrl; - if (HasComment()) - fRawFullCookie << "; Comment=" << fComment; - if (HasDiscard()) - fRawFullCookie << "; Discard=" << (fDiscard?"true":"false"); + if (HasDomain()) fRawFullCookie << "; Domain=" << fDomain; if (HasExpirationDate()) - fRawFullCookie << "; Max-Age=" << MaxAge(); -// fRawFullCookie << "; Expires=" << ExpirationString(); + fRawFullCookie << "; Expires=" << ExpirationString(); if (HasPath()) fRawFullCookie << "; Path=" << fPath; - if (Secure() && fSecure) - fRawFullCookie << "; Secure=" << (fSecure?"true":"false"); - if (HasVersion()) - fRawFullCookie << ", Version=" << fVersion; - + if (Secure()) + fRawFullCookie << "; Secure"; + if (HttpOnly()) + fRawFullCookie << "; HttpOnly"; + } else if (!full && !fRawCookieValid) { fRawCookie.Truncate(0); fRawCookieValid = true; - + fRawCookie << fName << "=" << fValue; } - return full?fRawFullCookie:fRawCookie; + return full ? fRawFullCookie : fRawCookie; } // #pragma mark Cookie test +bool +BNetworkCookie::IsHostOnly() const +{ + return fHostOnly; +} + + bool BNetworkCookie::IsSessionCookie() const { @@ -440,39 +388,72 @@ BNetworkCookie::IsSessionCookie() const bool -BNetworkCookie::IsValid(bool strict) const +BNetworkCookie::IsValid() const { - return HasName() && HasValue() && (!strict || HasVersion()); + return HasName() && HasDomain() && HasPath(); } bool BNetworkCookie::IsValidForUrl(const BUrl& url) const { - BString urlHost = url.Host(); - BString urlPath = url.Path(); - - return IsValidForDomain(urlHost) && IsValidForPath(urlPath); + if (Secure() && url.Protocol() != "https") + return false; + + return IsValidForDomain(url.Host()) && IsValidForPath(url.Path()); } bool BNetworkCookie::IsValidForDomain(const BString& domain) const { - if (fDomain.Length() > domain.Length()) + // TODO: canonicalize both domains + const BString& cookieDomain = Domain(); + + int32 difference = domain.Length() - cookieDomain.Length(); + // If the cookie domain is longer than the domain string it cannot + // be valid. + if (difference < 0) return false; - - return domain.FindLast(fDomain) == (domain.Length() - fDomain.Length()); + + // If the cookie is host-only the domains must match exactly. + if (IsHostOnly()) + return domain == cookieDomain; + + // Otherwise, the domains must match exactly, or the cookie domain + // must be a suffix with the preceeding character being a dot. + const char* suffix = domain.String() + difference; + if (strcmp(suffix, cookieDomain.String()) == 0) { + if (difference == 0) + return true; + else if (domain[difference - 1] == '.') + return true; + } + + return false; } bool BNetworkCookie::IsValidForPath(const BString& path) const { - if (fPath.Length() > path.Length()) + const BString& cookiePath = Path(); + if (path.Length() < cookiePath.Length()) return false; - - return path.FindFirst(fPath) == 0; + + // The cookie path must be a prefix of the path string + if (path.Compare(cookiePath, cookiePath.Length()) != 0) + return false; + + // The paths match if they are identical, or if the last + // character of the prefix is a slash, or if the character + // after the prefix is a slash. + if (path.Length() == cookiePath.Length() + || cookiePath[cookiePath.Length() - 1] == '/' + || path[cookiePath.Length()] == '/') + return true; + + return false; } @@ -480,23 +461,16 @@ BNetworkCookie::IsValidForPath(const BString& path) const bool -BNetworkCookie::HasCommentUrl() const +BNetworkCookie::HasName() const { - return fCommentUrl.Length() > 0; + return fName.Length() > 0; } bool -BNetworkCookie::HasComment() const +BNetworkCookie::HasValue() const { - return fComment.Length() > 0; -} - - -bool -BNetworkCookie::HasDiscard() const -{ - return fHasDiscard; + return fValue.Length() > 0; } @@ -514,31 +488,10 @@ BNetworkCookie::HasPath() const } -bool -BNetworkCookie::HasVersion() const -{ - return fHasVersion; -} - - -bool -BNetworkCookie::HasName() const -{ - return fName.Length() > 0; -} - - -bool -BNetworkCookie::HasValue() const -{ - return fValue.Length() > 0; -} - - bool BNetworkCookie::HasExpirationDate() const { - return fHasExpirationDate; + return !IsSessionCookie(); } @@ -548,18 +501,16 @@ BNetworkCookie::HasExpirationDate() const bool BNetworkCookie::ShouldDeleteAtExit() const { - return (HasDiscard() && Discard()) - || (!IsSessionCookie() && ShouldDeleteNow()) - || IsSessionCookie(); + return IsSessionCookie() || ShouldDeleteNow(); } bool BNetworkCookie::ShouldDeleteNow() const { - if (!IsSessionCookie() && HasExpirationDate()) + if (HasExpirationDate()) return (BDateTime::CurrentDateTime(B_GMT_TIME) > fExpiration); - + return false; } @@ -574,62 +525,50 @@ BNetworkCookie::Archive(BMessage* into, bool deep) const if (error != B_OK) return error; - + error = into->AddString(kArchivedCookieName, fName); if (error != B_OK) return error; - + error = into->AddString(kArchivedCookieValue, fValue); if (error != B_OK) return error; - - + + // We add optional fields only if they're defined - if (HasComment()) { - error = into->AddString(kArchivedCookieComment, fComment); - if (error != B_OK) - return error; - } - - if (HasCommentUrl()) { - error = into->AddString(kArchivedCookieCommentUrl, fCommentUrl); - if (error != B_OK) - return error; - } - - if (HasDiscard()) { - error = into->AddBool(kArchivedCookieDiscard, fDiscard); - if (error != B_OK) - return error; - } - if (HasDomain()) { error = into->AddString(kArchivedCookieDomain, fDomain); if (error != B_OK) return error; } - - if (fHasExpirationDate) { - error = into->AddInt32(kArchivedCookieExpirationDate, + + if (HasExpirationDate()) { + error = into->AddInt32(kArchivedCookieExpirationDate, fExpiration.Time_t()); if (error != B_OK) return error; } - + if (HasPath()) { error = into->AddString(kArchivedCookiePath, fPath); if (error != B_OK) return error; } - + if (Secure()) { error = into->AddBool(kArchivedCookieSecure, fSecure); if (error != B_OK) return error; } - - if (HasVersion()) { - error = into->AddInt8(kArchivedCookieVersion, fVersion); + + if (HttpOnly()) { + error = into->AddBool(kArchivedCookieHttpOnly, fHttpOnly); + if (error != B_OK) + return error; + } + + if (IsHostOnly()) { + error = into->AddBool(kArchivedCookieHostOnly, true); if (error != B_OK) return error; } @@ -652,37 +591,6 @@ BNetworkCookie::Instantiate(BMessage* archive) // #pragma mark Overloaded operators -BNetworkCookie& -BNetworkCookie::operator=(const BNetworkCookie& other) -{ - // Should we prefer to discard the cache ? - fRawCookie = other.fRawCookie; - fRawCookieValid = other.fRawCookieValid; - fRawFullCookie = other.fRawFullCookie; - fRawFullCookieValid = other.fRawFullCookieValid; - fExpirationString = other.fExpirationString; - fExpirationStringValid = other.fExpirationStringValid; - - fComment = other.fComment; - fCommentUrl = other.fCommentUrl; - fDiscard = other.fDiscard; - fDomain = other.fDomain; - fExpiration = other.fExpiration; - fPath = other.fPath; - fSecure = other.fSecure; - fVersion = other.fVersion; - fName = other.fName; - fValue = other.fValue; - - fHasDiscard = other.fHasDiscard; - fHasExpirationDate = other.fHasExpirationDate; - fSessionCookie = other.fSessionCookie; - fHasVersion = other.fHasVersion; - - return *this; -} - - BNetworkCookie& BNetworkCookie::operator=(const char* string) { @@ -708,106 +616,133 @@ BNetworkCookie::operator!=(const BNetworkCookie& other) void BNetworkCookie::_Reset() { - fComment.Truncate(0); - fCommentUrl.Truncate(0); - fDomain.Truncate(0); - fPath.Truncate(0); fName.Truncate(0); fValue.Truncate(0); - fDiscard = false; - fSecure = false; - fVersion = 0; - fExpiration = 0; + fDomain.Truncate(0); + fPath.Truncate(0); + fExpiration = BDateTime(); + fSecure = false; + fHttpOnly = false; - fHasDiscard = false; - fHasExpirationDate = false; - fSessionCookie = true; - fHasVersion = false; - - fRawCookieValid = false; - fRawFullCookieValid = false; - fExpirationStringValid = false; + fSessionCookie = true; + fHostOnly = true; + + fRawCookieValid = false; + fRawFullCookieValid = false; + fExpirationStringValid = false; } -void -BNetworkCookie::_ExtractNameValuePair(const BString& cookieString, - int16* index, bool parseField) +int32 +skip_whitespace_forward(const BString& string, int32 index) { - // Skip whitespaces - while (cookieString.ByteAt(*index) == ' ' - && *index < cookieString.Length()) - (*index)++; - - if (*index >= cookieString.Length()) - return; - - - // Look for a name=value pair - int16 firstSemiColon = cookieString.FindFirst(";", *index); - int16 firstEqual = cookieString.FindFirst("=", *index); - - BString name; - BString value; - - if (firstSemiColon == -1) { - if (firstEqual != -1) { - cookieString.CopyInto(name, *index, firstEqual - *index); - cookieString.CopyInto(value, firstEqual + 1, - cookieString.Length() - firstEqual - 1); - } else - cookieString.CopyInto(value, *index, - cookieString.Length() - *index); - - *index = cookieString.Length() + 1; - } else { - if (firstEqual != -1 && firstEqual < firstSemiColon) { - cookieString.CopyInto(name, *index, firstEqual - *index); - cookieString.CopyInto(value, firstEqual + 1, - firstSemiColon - firstEqual - 1); - } else - cookieString.CopyInto(value, *index, firstSemiColon - *index); - - *index = firstSemiColon + 1; - } - - // Cookie name/value pair - if (!parseField) { - SetName(name); - SetValue(value); - return; - } - - name.ToLower(); - name.Trim(); - value.Trim(); - - // Cookie comment - if (name == "comment") - SetComment(value); - // Cookie comment URL - else if (name == "comment-url") - SetCommentUrl(value); - // Cookie discard flag - else if (name == "discard") - SetDiscard(value.Length() == 0 || value.ToLower() == "true"); - // Cookie max-age - else if (name == "maxage") - SetMaxAge(atoi(value.String())); - // Cookie expiration date - else if (name == "expires") { - BHttpTime date(value); - SetExpirationDate(date.Parse()); - // Cookie valid domain - } else if (name == "domain") - SetDomain(value); - // Cookie valid path - else if (name == "path") - SetPath(value); - // Cookie secure flag - else if (name == "secure") - SetSecure(value.Length() == 0 || value.ToLower() == "true"); - // Cookie version - else if (name == "version") - SetVersion(atoi(value.String())); + while (index < string.Length() && (string[index] == ' ' + || string[index] == '\t')) + index++; + return index; +} + + +int32 +skip_whitespace_backward(const BString& string, int32 index) +{ + while (index >= 0 && (string[index] == ' ' || string[index] == '\t')) + index--; + return index; +} + + +int32 +BNetworkCookie::_ExtractNameValuePair(const BString& cookieString, + BString& name, BString& value, int32 index) +{ + // Find our name-value-pair and the delimiter. + int32 firstEquals = cookieString.FindFirst('=', index); + int32 nameValueEnd = cookieString.FindFirst(';', index); + + // If the set-cookie-string lacks a semicolon, the name-value-pair + // is the whole string. + if (nameValueEnd == -1) + nameValueEnd = cookieString.Length(); + + // If the name-value-pair lacks an equals, the parse should fail. + if (firstEquals == -1 || firstEquals > nameValueEnd) + return -1; + + int32 first = skip_whitespace_forward(cookieString, index); + int32 last = skip_whitespace_backward(cookieString, firstEquals - 1); + + // If we lack a name, fail to parse. + if (first > last) + return -1; + + cookieString.CopyInto(name, first, last - first + 1); + + first = skip_whitespace_forward(cookieString, firstEquals + 1); + last = skip_whitespace_backward(cookieString, nameValueEnd - 1); + if (first <= last) + cookieString.CopyInto(value, first, last - first + 1); + else + value.SetTo(""); + + return nameValueEnd; +} + + +int32 +BNetworkCookie::_ExtractAttributeValuePair(const BString& cookieString, + BString& attribute, BString& value, int32 index) +{ + // Find the end of our cookie-av. + int32 cookieAVEnd = cookieString.FindFirst(';', index); + + // If the unparsed-attributes lacks a semicolon, then the cookie-av is the + // whole string. + if (cookieAVEnd == -1) + cookieAVEnd = cookieString.Length(); + + int32 attributeNameEnd = cookieString.FindFirst('=', index); + // If the cookie-av has no equals, the attribute-name is the entire + // cookie-av and the attribute-value is empty. + if (attributeNameEnd == -1 || attributeNameEnd > cookieAVEnd) + attributeNameEnd = cookieAVEnd; + + int32 first = skip_whitespace_forward(cookieString, index); + int32 last = skip_whitespace_backward(cookieString, attributeNameEnd - 1); + + if (first <= last) + cookieString.CopyInto(attribute, first, last - first + 1); + else + attribute.SetTo(""); + + if (attributeNameEnd == cookieAVEnd) { + value.SetTo(""); + return cookieAVEnd; + } + + first = skip_whitespace_forward(cookieString, attributeNameEnd + 1); + last = skip_whitespace_backward(cookieString, cookieAVEnd - 1); + if (first <= last) + cookieString.CopyInto(value, first, last - first + 1); + else + value.SetTo(""); + + return cookieAVEnd; +} + + +BString +BNetworkCookie::_DefaultPathForUrl(const BUrl& url) +{ + const BString& path = url.Path(); + if (path.IsEmpty() || path.ByteAt(0) != '/') + return ""; + + int32 index = path.FindLast('/'); + if (index == 0) + return ""; + + BString newPath = path; + newPath.Truncate(index); + return newPath; } diff --git a/src/kits/network/libnetapi/NetworkCookieJar.cpp b/src/kits/network/libnetapi/NetworkCookieJar.cpp index eef91d110b..cfe3efdb6a 100644 --- a/src/kits/network/libnetapi/NetworkCookieJar.cpp +++ b/src/kits/network/libnetapi/NetworkCookieJar.cpp @@ -1,63 +1,68 @@ /* - * Copyright 2010 Haiku Inc. All rights reserved. + * Copyright 2010-2013 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Christophe Huriaux, c.huriaux@gmail.com + * Hamish Morrison, hamishm53@gmail.com */ -#include - #include #include #include #include #include + +#include + #include "NetworkCookieJarPrivate.h" -const char* kArchivedCookieMessageName = "be:cookie"; + +const char* kArchivedCookieMessageName = "be:cookie"; BNetworkCookieJar::BNetworkCookieJar() - : - fCookieHashMap(new PrivateHashMap) + : + fCookieHashMap(new PrivateHashMap()) { } BNetworkCookieJar::BNetworkCookieJar(const BNetworkCookieJar&) - : - BArchivable(), - fCookieHashMap(new PrivateHashMap) + : + fCookieHashMap(new PrivateHashMap()) { // TODO } BNetworkCookieJar::BNetworkCookieJar(const BNetworkCookieList& otherList) - : - fCookieHashMap(new PrivateHashMap) + : + fCookieHashMap(new PrivateHashMap()) { AddCookies(otherList); } BNetworkCookieJar::BNetworkCookieJar(BMessage* archive) - : - fCookieHashMap(new PrivateHashMap) + : + fCookieHashMap(new PrivateHashMap()) { BMessage extractedCookie; - - for (int32 i = 0; - archive->FindMessage(kArchivedCookieMessageName, i, &extractedCookie) - == B_OK; - i++) { - BNetworkCookie* heapCookie + + for (int32 i = 0; archive->FindMessage(kArchivedCookieMessageName, i, + &extractedCookie) == B_OK; i++) { + BNetworkCookie* heapCookie = new(std::nothrow) BNetworkCookie(&extractedCookie); - - if (heapCookie == NULL || !AddCookie(heapCookie)) + + if (heapCookie == NULL) break; + + if (!AddCookie(heapCookie)) { + delete heapCookie; + continue; + } } } @@ -65,8 +70,8 @@ BNetworkCookieJar::BNetworkCookieJar(BMessage* archive) BNetworkCookieJar::~BNetworkCookieJar() { BNetworkCookie* cookiePtr; - - for (Iterator it(GetIterator()); (cookiePtr = it.Next()); ) + + for (Iterator it = GetIterator(); (cookiePtr = it.Next()) != NULL;) delete it.Remove(); } @@ -74,64 +79,72 @@ BNetworkCookieJar::~BNetworkCookieJar() // #pragma mark Add cookie to cookie jar -bool +status_t BNetworkCookieJar::AddCookie(const BNetworkCookie& cookie) { BNetworkCookie* heapCookie = new(std::nothrow) BNetworkCookie(cookie); - - if (!AddCookie(heapCookie)) { + if (heapCookie == NULL) + return B_NO_MEMORY; + + status_t result = AddCookie(heapCookie); + if (result != B_OK) { delete heapCookie; - return false; + return result; } - - return true; + + return B_OK; } -bool +status_t BNetworkCookieJar::AddCookie(BNetworkCookie* cookie) { - if (cookie != NULL) { - HashString key(cookie->Domain()); - - if (!fCookieHashMap->fHashMap.ContainsKey(key)) - fCookieHashMap->fHashMap.Put(key, new BList); - - BNetworkCookieList* list = fCookieHashMap->fHashMap.Get(key); - - for (int32 i = 0; i < list->CountItems(); i++) { - BNetworkCookie* c - = reinterpret_cast(list->ItemAt(i)); - - if (c->Name() == cookie->Name()) { - list->RemoveItem(i); - break; - } - } - - // Discard the cookie if it's to be deleted - if (!cookie->ShouldDeleteNow()) - list->AddItem(cookie); + if (cookie == NULL) + return B_BAD_VALUE; + + HashString key(cookie->Domain()); + + BNetworkCookieList* list = fCookieHashMap->fHashMap.Get(key); + if (list == NULL) { + list = new(std::nothrow) BNetworkCookieList(); + if (list == NULL || fCookieHashMap->fHashMap.Put(key, list) != B_OK) + return B_NO_MEMORY; } - - return true; + + for (int32 i = 0; i < list->CountItems(); i++) { + BNetworkCookie* c + = reinterpret_cast(list->ItemAt(i)); + + if (c->Name() == cookie->Name() && c->Path() == cookie->Path()) { + list->RemoveItem(i); + break; + } + } + + if (cookie->ShouldDeleteNow()) + delete cookie; + else + list->AddItem(cookie); + + return B_OK; } -bool +status_t BNetworkCookieJar::AddCookies(const BNetworkCookieList& cookies) { for (int32 i = 0; i < cookies.CountItems(); i++) { - BNetworkCookie* cookiePtr + BNetworkCookie* cookiePtr = reinterpret_cast(cookies.ItemAt(i)); - + // Using AddCookie by reference in order to avoid multiple // cookie jar share the same cookie pointers - if (!AddCookie(*cookiePtr)) - return false; + status_t result = AddCookie(*cookiePtr); + if (result != B_OK) + return result; } - - return true; + + return B_OK; } @@ -143,8 +156,8 @@ BNetworkCookieJar::DeleteOutdatedCookies() { int32 deleteCount = 0; BNetworkCookie* cookiePtr; - - for (Iterator it(GetIterator()); (cookiePtr = it.Next()); ) { + + for (Iterator it = GetIterator(); (cookiePtr = it.Next()) != NULL;) { if (cookiePtr->ShouldDeleteNow()) { delete it.Remove(); deleteCount++; @@ -160,8 +173,8 @@ BNetworkCookieJar::PurgeForExit() { int32 deleteCount = 0; BNetworkCookie* cookiePtr; - - for (Iterator it(GetIterator()); (cookiePtr = it.Next()); ) { + + for (Iterator it = GetIterator(); (cookiePtr = it.Next()) != NULL;) { if (cookiePtr->ShouldDeleteAtExit()) { delete it.Remove(); deleteCount++; @@ -182,10 +195,10 @@ BNetworkCookieJar::Archive(BMessage* into, bool deep) const if (error == B_OK) { BNetworkCookie* cookiePtr; - - for (Iterator it(GetIterator()); (cookiePtr = it.Next()); ) { + + for (Iterator it = GetIterator(); (cookiePtr = it.Next()) != NULL;) { BMessage subArchive; - + error = cookiePtr->Archive(&subArchive, deep); if (error != B_OK) return error; @@ -205,7 +218,7 @@ BNetworkCookieJar::Instantiate(BMessage* archive) { if (archive->HasMessage(kArchivedCookieMessageName)) return new(std::nothrow) BNetworkCookieJar(archive); - + return NULL; } @@ -242,11 +255,11 @@ BNetworkCookieJar::Flatten(void* buffer, ssize_t size) const { if (FlattenedSize() > size) return B_ERROR; - - fFlattened.CopyInto(reinterpret_cast(buffer), 0, + + fFlattened.CopyInto(reinterpret_cast(buffer), 0, fFlattened.Length()); reinterpret_cast(buffer)[fFlattened.Length()] = 0; - + return B_OK; } @@ -262,13 +275,13 @@ BNetworkCookieJar::AllowsTypeCode(type_code) const status_t BNetworkCookieJar::Unflatten(type_code, const void* buffer, ssize_t size) { - BString flattenedCookies; + BString flattenedCookies; flattenedCookies.SetTo(reinterpret_cast(buffer), size); - - while (flattenedCookies.Length() > 0) { + + while (flattenedCookies.Length() > 0) { BNetworkCookie tempCookie; BString tempCookieLine; - + int32 endOfLine = flattenedCookies.FindFirst('\n', 0); if (endOfLine == -1) tempCookieLine = flattenedCookies; @@ -276,11 +289,11 @@ BNetworkCookieJar::Unflatten(type_code, const void* buffer, ssize_t size) flattenedCookies.MoveInto(tempCookieLine, 0, endOfLine); flattenedCookies.Remove(0, 1); } - + if (tempCookieLine.Length() != 0 && tempCookieLine[0] != '#') { for (int32 field = 0; field < 7; field++) { BString tempString; - + int32 endOfField = tempCookieLine.FindFirst('\t', 0); if (endOfField == -1) tempString = tempCookieLine; @@ -288,42 +301,42 @@ BNetworkCookieJar::Unflatten(type_code, const void* buffer, ssize_t size) tempCookieLine.MoveInto(tempString, 0, endOfField); tempCookieLine.Remove(0, 1); } - + switch (field) { case 0: tempCookie.SetDomain(tempString); break; - + case 1: // TODO: Useless field ATM break; - + case 2: tempCookie.SetPath(tempString); break; - + case 3: tempCookie.SetSecure(tempString == "TRUE"); break; - + case 4: tempCookie.SetExpirationDate(atoi(tempString)); break; - + case 5: tempCookie.SetName(tempString); break; - + case 6: tempCookie.SetValue(tempString); break; } // switch } // for loop - + AddCookie(tempCookie); } - } - + } + return B_OK; } @@ -346,7 +359,7 @@ BNetworkCookieJar::GetUrlIterator(const BUrl& url) const copy.SetPath("/"); return BNetworkCookieJar::UrlIterator(this, copy); } - + return BNetworkCookieJar::UrlIterator(this, url); } @@ -357,10 +370,10 @@ BNetworkCookieJar::_DoFlatten() const fFlattened.Truncate(0); BNetworkCookie* cookiePtr; - for (Iterator it(GetIterator()); (cookiePtr = it.Next()); ) { - fFlattened << cookiePtr->Domain() << '\t' << "TRUE" << '\t' - << cookiePtr->Path() << '\t' - << (cookiePtr->Secure()?"TRUE":"FALSE") << '\t' + for (Iterator it = GetIterator(); (cookiePtr = it.Next()) != NULL;) { + fFlattened << cookiePtr->Domain() << '\t' << "TRUE" << '\t' + << cookiePtr->Path() << '\t' + << (cookiePtr->Secure()?"TRUE":"FALSE") << '\t' << (int32)cookiePtr->ExpirationDate() << '\t' << cookiePtr->Name() << '\t' << cookiePtr->Value() << '\n'; } @@ -395,7 +408,7 @@ BNetworkCookieJar::Iterator::Iterator(const BNetworkCookieJar* cookieJar) { fIterator = new(std::nothrow) PrivateIterator( fCookieJar->fCookieHashMap->fHashMap.GetIterator()); - + // Locate first cookie _FindNext(); } @@ -419,7 +432,7 @@ BNetworkCookieJar::Iterator::Next() { if (!fElement) return NULL; - + BNetworkCookie* result = fElement; _FindNext(); return result; @@ -431,18 +444,18 @@ BNetworkCookieJar::Iterator::NextDomain() { if (!fElement) return NULL; - + BNetworkCookie* result = fElement; - + if (!fIterator->fCookieMapIterator.HasNext()) { fElement = NULL; return NULL; } - - fList = *(fIterator->fCookieMapIterator.NextValue()); + + fList = *fIterator->fCookieMapIterator.NextValue(); fIndex = 0; fElement = reinterpret_cast(fList->ItemAt(fIndex)); - + return result; } @@ -452,7 +465,7 @@ BNetworkCookieJar::Iterator::Remove() { if (!fLastElement) return NULL; - + BNetworkCookie* result = fLastElement; if (fIndex == 0) { @@ -463,10 +476,10 @@ BNetworkCookieJar::Iterator::Remove() else fLastList->RemoveItem(fLastList->CountItems() - 1); } else { - fList->RemoveItem(fIndex-1); fIndex--; + fList->RemoveItem(fIndex); } - + fLastElement = NULL; return result; } @@ -476,12 +489,18 @@ BNetworkCookieJar::Iterator& BNetworkCookieJar::Iterator::operator=(const BNetworkCookieJar::Iterator& other) { fCookieJar = other.fCookieJar; - fIterator = other.fIterator; fLastList = other.fLastList; fList = other.fList; fElement = other.fElement; fLastElement = other.fLastElement; fIndex = other.fIndex; + + fIterator = new(std::nothrow) PrivateIterator(*other.fIterator); + if (fIterator == NULL) { + // Make the iterator unusable. + fElement = NULL; + fLastElement = NULL; + } return *this; } @@ -490,18 +509,18 @@ void BNetworkCookieJar::Iterator::_FindNext() { fLastElement = fElement; - + fIndex++; if (fList && fIndex < fList->CountItems()) { fElement = reinterpret_cast(fList->ItemAt(fIndex)); return; } - + if (!fIterator->fCookieMapIterator.HasNext()) { fElement = NULL; return; } - + fLastList = fList; fList = *(fIterator->fCookieMapIterator.NextValue()); fIndex = 0; @@ -529,25 +548,22 @@ BNetworkCookieJar::UrlIterator::UrlIterator(const BNetworkCookieJar* cookieJar, fLastElement(NULL), fIndex(0), fLastIndex(0), - fUrl(const_cast(url)) + fUrl(url) { - BString domain(url.Host()); + BString domain = url.Host(); if (!domain.Length()) return; - if (domain[0] != '.') - domain.Prepend("."); - - // Prepending another dot since _FindNext is going to - // call _SupDomain() - domain.Prepend("."); - fIterator = new(std::nothrow) PrivateIterator( fCookieJar->fCookieHashMap->fHashMap.GetIterator()); - fIterator->fKey.SetTo(domain, domain.Length()); - _FindNext(); + if (fIterator != NULL) { + // Prepending a dot since _FindNext is going to call _SupDomain() + domain.Prepend("."); + fIterator->fKey.SetTo(domain, domain.Length()); + _FindNext(); + } } @@ -569,7 +585,7 @@ BNetworkCookieJar::UrlIterator::Next() { if (!fElement) return NULL; - + BNetworkCookie* result = fElement; _FindNext(); return result; @@ -581,15 +597,15 @@ BNetworkCookieJar::UrlIterator::Remove() { if (!fLastElement) return NULL; - + BNetworkCookie* result = fLastElement; fLastList->RemoveItem(fLastIndex); if (fLastList->CountItems() == 0) { - HashString lastKey(fLastElement->Domain(), + HashString lastKey(fLastElement->Domain(), fLastElement->Domain().Length()); - + delete fCookieJar->fCookieHashMap->fHashMap.Remove(lastKey); } @@ -609,23 +625,28 @@ BNetworkCookieJar::UrlIterator::operator=( fLastElement = other.fLastElement; fIndex = other.fIndex; fLastIndex = other.fLastIndex; - fUrl = other.fUrl; - fIterator = other.fIterator; + + fIterator = new(std::nothrow) PrivateIterator(*other.fIterator); + if (fIterator == NULL) { + // Make the iterator unusable. + fElement = NULL; + fLastElement = NULL; + } + return *this; } bool -BNetworkCookieJar::UrlIterator::_SupDomain() +BNetworkCookieJar::UrlIterator::_SuperDomain() { - BString domain(fIterator->fKey.GetString()); - int32 nextDot = domain.FindFirst('.', 1); - - if (nextDot == -1) + const char* domain = fIterator->fKey.GetString(); + const char* nextDot = strchr(domain, '.'); + + if (nextDot == NULL) return false; - - domain.Remove(0, nextDot); - fIterator->fKey.SetTo(domain.String(), domain.Length()); + + fIterator->fKey.SetTo(nextDot + 1); return true; } @@ -635,19 +656,16 @@ BNetworkCookieJar::UrlIterator::_FindNext() { fLastIndex = fIndex; fLastElement = fElement; - - if (_FindPath()) - return; - fLastList = fList; - do { - if (!_SupDomain()) { + + while (!_FindPath()) { + if (!_SuperDomain()) { fElement = NULL; return; } - + _FindDomain(); - } while (!_FindPath()); + } } @@ -655,10 +673,10 @@ void BNetworkCookieJar::UrlIterator::_FindDomain() { fList = fCookieJar->fCookieHashMap->fHashMap.Get(fIterator->fKey); - + if (fList == NULL) fElement = NULL; - + fIndex = -1; } @@ -667,17 +685,14 @@ bool BNetworkCookieJar::UrlIterator::_FindPath() { fIndex++; - if (fList && fIndex < fList->CountItems()) { - do { - fElement - = reinterpret_cast(fList->ItemAt(fIndex)); - - if (fElement->IsValidForPath(fUrl.Path())) - return true; - - fIndex++; - } while (fList && fIndex < fList->CountItems()); + while (fList && fIndex < fList->CountItems()) { + fElement = reinterpret_cast(fList->ItemAt(fIndex)); + + if (fElement->IsValidForPath(fUrl.Path())) + return true; + + fIndex++; } - + return false; } diff --git a/src/kits/tracker/Commands.h b/src/kits/tracker/Commands.h index a98d6147e7..869270be48 100644 --- a/src/kits/tracker/Commands.h +++ b/src/kits/tracker/Commands.h @@ -140,7 +140,7 @@ const uint32 kUpdateVolumeSpaceBar = 'UpSB'; const uint32 kShowVolumeSpaceBar = 'ShSB'; const uint32 kSpaceBarColorChanged = 'SBcc'; -const uint32 kMoveFilesToTrashChanged = 'STdm'; +const uint32 kDontMoveFilesToTrashChanged = 'STdm'; const uint32 kAskBeforeDeleteFileChanged = 'STad'; } // namespace BPrivate diff --git a/src/kits/tracker/ContainerWindow.cpp b/src/kits/tracker/ContainerWindow.cpp index bf3a7e58e1..35f12a9be0 100644 --- a/src/kits/tracker/ContainerWindow.cpp +++ b/src/kits/tracker/ContainerWindow.cpp @@ -604,7 +604,7 @@ BContainerWindow::BContainerWindow(LockingList* list, app->StartWatching(this, kWindowsShowFullPathChanged); app->StartWatching(this, kSingleWindowBrowseChanged); app->StartWatching(this, kShowNavigatorChanged); - app->StartWatching(this, kMoveFilesToTrashChanged); + app->StartWatching(this, kDontMoveFilesToTrashChanged); app->Unlock(); } @@ -625,7 +625,7 @@ BContainerWindow::~BContainerWindow() app->StopWatching(this, kWindowsShowFullPathChanged); app->StopWatching(this, kSingleWindowBrowseChanged); app->StopWatching(this, kShowNavigatorChanged); - app->StopWatching(this, kMoveFilesToTrashChanged); + app->StopWatching(this, kDontMoveFilesToTrashChanged); app->Unlock(); } @@ -1687,10 +1687,10 @@ BContainerWindow::MessageReceived(BMessage* message) settings.SingleWindowBrowse()); break; - case kMoveFilesToTrashChanged: + case kDontMoveFilesToTrashChanged: { bool dontMoveToTrash - = settings.MoveFilesToTrash(); + = settings.DontMoveFilesToTrash(); BMenuItem* item = fFileContextMenu->FindItem(kMoveToTrash); @@ -1934,8 +1934,8 @@ BContainerWindow::AddFileMenu(BMenu* menu) menu->AddItem(new BMenuItem(B_TRANSLATE("Duplicate"), new BMessage(kDuplicateSelection), 'D')); - menu->AddItem(new BMenuItem(TrackerSettings().MoveFilesToTrash() - ? B_TRANSLATE("Move to Trash") : B_TRANSLATE("Delete"), + menu->AddItem(new BMenuItem(TrackerSettings().DontMoveFilesToTrash() + ? B_TRANSLATE("Delete") : B_TRANSLATE("Move to Trash"), new BMessage(kMoveToTrash), 'T')); menu->AddSeparatorItem(); @@ -2758,8 +2758,8 @@ BContainerWindow::AddFileContextMenus(BMenu* menu) } if (!IsTrash() && !InTrash()) { - menu->AddItem(new BMenuItem(TrackerSettings().MoveFilesToTrash() - ? B_TRANSLATE("Move to Trash") : B_TRANSLATE("Delete"), + menu->AddItem(new BMenuItem(TrackerSettings().DontMoveFilesToTrash() + ? B_TRANSLATE("Delete") : B_TRANSLATE("Move to Trash"), new BMessage(kMoveToTrash), 'T')); // add separator for copy to/move to items (navigation items) diff --git a/src/kits/tracker/FSUtils.cpp b/src/kits/tracker/FSUtils.cpp index f001b29e0b..8a75bbc1e8 100644 --- a/src/kits/tracker/FSUtils.cpp +++ b/src/kits/tracker/FSUtils.cpp @@ -2842,9 +2842,9 @@ status_t _DeleteTask(BObjectList* list, bool confirm) { if (confirm) { - bool MoveToTrash = TrackerSettings().MoveFilesToTrash(); + bool dontMoveToTrash = TrackerSettings().DontMoveFilesToTrash(); - if (MoveToTrash) { + if (!dontMoveToTrash) { BAlert* alert = new BAlert("", B_TRANSLATE_NOCOLLECT(kDeleteConfirmationStr), B_TRANSLATE("Cancel"), B_TRANSLATE("Move to Trash"), diff --git a/src/kits/tracker/FilePanelPriv.cpp b/src/kits/tracker/FilePanelPriv.cpp index 64cb1326ed..70d8cc3432 100644 --- a/src/kits/tracker/FilePanelPriv.cpp +++ b/src/kits/tracker/FilePanelPriv.cpp @@ -885,9 +885,9 @@ TFilePanel::AddFileContextMenus(BMenu* menu) new BMessage(kGetInfo), 'I')); menu->AddItem(new BMenuItem(B_TRANSLATE("Edit name"), new BMessage(kEditItem), 'E')); - menu->AddItem(new BMenuItem(TrackerSettings().MoveFilesToTrash() - ? B_TRANSLATE("Move to Trash") - : B_TRANSLATE("Delete"), + menu->AddItem(new BMenuItem(TrackerSettings().DontMoveFilesToTrash() + ? B_TRANSLATE("Delete") + : B_TRANSLATE("Move to Trash"), new BMessage(kMoveToTrash), 'T')); menu->AddSeparatorItem(); menu->AddItem(new BMenuItem(B_TRANSLATE("Cut"), diff --git a/src/kits/tracker/PoseView.cpp b/src/kits/tracker/PoseView.cpp index 87ea8b3bf4..cda2c0ee9a 100644 --- a/src/kits/tracker/PoseView.cpp +++ b/src/kits/tracker/PoseView.cpp @@ -2323,7 +2323,7 @@ BPoseView::MessageReceived(BMessage* message) { TrackerSettings settings; - if ((modifiers() & B_SHIFT_KEY) != 0 || !settings.MoveFilesToTrash()) + if ((modifiers() & B_SHIFT_KEY) != 0 || settings.DontMoveFilesToTrash()) DeleteSelection(true, settings.AskBeforeDeleteFile()); else MoveSelectionToTrash(); @@ -6461,7 +6461,7 @@ BPoseView::KeyDown(const char* bytes, int32 count) } else { TrackerSettings settings; - if ((modifiers() & B_SHIFT_KEY) != 0 || !settings.MoveFilesToTrash()) + if ((modifiers() & B_SHIFT_KEY) != 0 || settings.DontMoveFilesToTrash()) DeleteSelection(true, settings.AskBeforeDeleteFile()); else MoveSelectionToTrash(); diff --git a/src/kits/tracker/PoseViewScripting.cpp b/src/kits/tracker/PoseViewScripting.cpp index 94089a3e48..cb9d299acb 100644 --- a/src/kits/tracker/PoseViewScripting.cpp +++ b/src/kits/tracker/PoseViewScripting.cpp @@ -491,7 +491,7 @@ BPoseView::DeleteProperty(BMessage* _SCRIPTING_ONLY(specifier), if (error == B_OK) { TrackerSettings settings; - if (settings.MoveFilesToTrash()) { + if (!settings.DontMoveFilesToTrash()) { // move the list we build into trash, don't make the // trashing task select the next item MoveListToTrash(entryList, false, false); diff --git a/src/kits/tracker/SettingsViews.cpp b/src/kits/tracker/SettingsViews.cpp index d44d767792..3e645d433e 100644 --- a/src/kits/tracker/SettingsViews.cpp +++ b/src/kits/tracker/SettingsViews.cpp @@ -947,151 +947,3 @@ SpaceBarSettingsView::IsRevertable() const || fFreeSpaceColor != settings.FreeSpaceColor() || fWarningSpaceColor != settings.WarningSpaceColor(); } - - -// #pragma mark - - - -TrashSettingsView::TrashSettingsView() - : - SettingsView("TrashSettingsView") -{ - fMoveFilesToTrashCheckBox = new BCheckBox("", - B_TRANSLATE("Move deleted files to Trash first"), - new BMessage(kMoveFilesToTrashChanged)); - - fAskBeforeDeleteFileCheckBox = new BCheckBox("", - B_TRANSLATE("Ask before deleting for good"), - new BMessage(kAskBeforeDeleteFileChanged)); - - const float spacing = be_control_look->DefaultItemSpacing(); - - BGroupLayout* layout = GroupLayout(); - layout->SetOrientation(B_VERTICAL); - layout->SetSpacing(0); - BGroupLayoutBuilder(layout) - .Add(fMoveFilesToTrashCheckBox) - .Add(fAskBeforeDeleteFileCheckBox) - .AddGlue() - .SetInsets(spacing, spacing, spacing, spacing); - -} - - -void -TrashSettingsView::AttachedToWindow() -{ - fMoveFilesToTrashCheckBox->SetTarget(this); - fAskBeforeDeleteFileCheckBox->SetTarget(this); -} - - -void -TrashSettingsView::MessageReceived(BMessage* message) -{ - TTracker* tracker = dynamic_cast(be_app); - if (!tracker) - return; - TrackerSettings settings; - - switch (message->what) { - case kMoveFilesToTrashChanged: - settings.SetMoveFilesToTrash( - fMoveFilesToTrashCheckBox->Value() == 1); - - tracker->SendNotices(kMoveFilesToTrashChanged); - Window()->PostMessage(kSettingsContentsModified); - break; - - case kAskBeforeDeleteFileChanged: - settings.SetAskBeforeDeleteFile( - fAskBeforeDeleteFileCheckBox->Value() == 1); - - tracker->SendNotices(kAskBeforeDeleteFileChanged); - Window()->PostMessage(kSettingsContentsModified); - break; - - default: - _inherited::MessageReceived(message); - break; - } -} - - -void -TrashSettingsView::SetDefaults() -{ - TrackerSettings settings; - - settings.SetMoveFilesToTrash(true); - settings.SetAskBeforeDeleteFile(true); - - ShowCurrentSettings(); - _SendNotices(); -} - - -bool -TrashSettingsView::IsDefaultable() const -{ - TrackerSettings settings; - - return settings.MoveFilesToTrash() != true - || settings.AskBeforeDeleteFile() != true; -} - - -void -TrashSettingsView::Revert() -{ - TrackerSettings settings; - - settings.SetMoveFilesToTrash(fMoveFilesToTrash); - settings.SetAskBeforeDeleteFile(fAskBeforeDeleteFile); - - ShowCurrentSettings(); - _SendNotices(); -} - - -void -TrashSettingsView::_SendNotices() -{ - TTracker* tracker = dynamic_cast(be_app); - if (!tracker) - return; - - tracker->SendNotices(kMoveFilesToTrashChanged); - tracker->SendNotices(kAskBeforeDeleteFileChanged); -} - - -void -TrashSettingsView::ShowCurrentSettings() -{ - TrackerSettings settings; - - fMoveFilesToTrashCheckBox->SetValue(settings.MoveFilesToTrash()); - fAskBeforeDeleteFileCheckBox->SetValue(settings.AskBeforeDeleteFile()); -} - - -void -TrashSettingsView::RecordRevertSettings() -{ - TrackerSettings settings; - - fMoveFilesToTrash = settings.MoveFilesToTrash(); - fAskBeforeDeleteFile = settings.AskBeforeDeleteFile(); -} - - -bool -TrashSettingsView::IsRevertable() const -{ - return fMoveFilesToTrash - != (fMoveFilesToTrashCheckBox->Value() > 0) - || fAskBeforeDeleteFile - != (fAskBeforeDeleteFileCheckBox->Value() > 0); -} - diff --git a/src/kits/tracker/SettingsViews.h b/src/kits/tracker/SettingsViews.h index f6c21beb44..68ce03484f 100644 --- a/src/kits/tracker/SettingsViews.h +++ b/src/kits/tracker/SettingsViews.h @@ -163,33 +163,6 @@ class SpaceBarSettingsView : public SettingsView { typedef SettingsView _inherited; }; - -class TrashSettingsView : public SettingsView { - public: - TrashSettingsView(); - - virtual void MessageReceived(BMessage* message); - virtual void AttachedToWindow(); - - virtual void SetDefaults(); - virtual bool IsDefaultable() const; - virtual void Revert(); - virtual void ShowCurrentSettings(); - virtual void RecordRevertSettings(); - virtual bool IsRevertable() const; - - private: - void _SendNotices(); - - BCheckBox* fMoveFilesToTrashCheckBox; - BCheckBox* fAskBeforeDeleteFileCheckBox; - - bool fMoveFilesToTrash; - bool fAskBeforeDeleteFile; - - typedef SettingsView _inherited; -}; - } // namespace BPrivate using namespace BPrivate; diff --git a/src/kits/tracker/TrackerSettings.cpp b/src/kits/tracker/TrackerSettings.cpp index 5ee3ed202c..7eebfa4e21 100644 --- a/src/kits/tracker/TrackerSettings.cpp +++ b/src/kits/tracker/TrackerSettings.cpp @@ -82,7 +82,7 @@ class TTrackerState : public Settings { HexScalarValueSetting* fFreeSpaceColor; HexScalarValueSetting* fWarningSpaceColor; - BooleanValueSetting* fMoveFilesToTrash; + BooleanValueSetting* fDontMoveFilesToTrash; BooleanValueSetting* fAskBeforeDeleteFile; Benaphore fInitLock; @@ -202,8 +202,8 @@ TTrackerState::LoadSettingsIfNeeded() Add(fWarningSpaceColor = new HexScalarValueSetting("WarningSpaceColor", 0xc0cb0000, "", "")); - Add(fMoveFilesToTrash - = new BooleanValueSetting("MoveFilesToTrash", true)); + Add(fDontMoveFilesToTrash + = new BooleanValueSetting("DontMoveFilesToTrash", false)); Add(fAskBeforeDeleteFile = new BooleanValueSetting("AskBeforeDeleteFile", true)); @@ -509,16 +509,16 @@ TrackerSettings::SetRecentFoldersCount(int32 count) bool -TrackerSettings::MoveFilesToTrash() +TrackerSettings::DontMoveFilesToTrash() { - return gTrackerState.fMoveFilesToTrash->Value(); + return gTrackerState.fDontMoveFilesToTrash->Value(); } void -TrackerSettings::SetMoveFilesToTrash(bool enabled) +TrackerSettings::SetDontMoveFilesToTrash(bool enabled) { - gTrackerState.fMoveFilesToTrash->SetValue(enabled); + gTrackerState.fDontMoveFilesToTrash->SetValue(enabled); } diff --git a/src/kits/tracker/TrackerSettings.h b/src/kits/tracker/TrackerSettings.h index da762ebb7b..78f2f335e5 100644 --- a/src/kits/tracker/TrackerSettings.h +++ b/src/kits/tracker/TrackerSettings.h @@ -118,8 +118,8 @@ class TrackerSettings { bool ClockIs24Hr(); void SetClockTo24Hr(bool); - bool MoveFilesToTrash(); - void SetMoveFilesToTrash(bool); + bool DontMoveFilesToTrash(); + void SetDontMoveFilesToTrash(bool); bool AskBeforeDeleteFile(); void SetAskBeforeDeleteFile(bool); diff --git a/src/kits/tracker/TrackerSettingsWindow.cpp b/src/kits/tracker/TrackerSettingsWindow.cpp index 66267a60d3..754ae65bc3 100644 --- a/src/kits/tracker/TrackerSettingsWindow.cpp +++ b/src/kits/tracker/TrackerSettingsWindow.cpp @@ -114,8 +114,6 @@ TrackerSettingsWindow::TrackerSettingsWindow() new DesktopSettingsView())); fSettingsTypeListView->AddItem(new SettingsItem(B_TRANSLATE("Windows"), new WindowsSettingsView())); - fSettingsTypeListView->AddItem(new SettingsItem(B_TRANSLATE("Trash"), - new TrashSettingsView())); fSettingsTypeListView->AddItem(new SettingsItem( B_TRANSLATE("Volume icons"), new SpaceBarSettingsView())); diff --git a/src/tests/kits/net/cookie/cookie_test.cpp b/src/tests/kits/net/cookie/cookie_test.cpp index ded674ce34..8a4417eb09 100644 --- a/src/tests/kits/net/cookie/cookie_test.cpp +++ b/src/tests/kits/net/cookie/cookie_test.cpp @@ -20,58 +20,81 @@ using std::cout; using std::endl; -typedef struct -{ +typedef struct { const char* cookieString; - + const char* url; struct { + bool valid; const char* name; const char* value; const char* domain; const char* path; bool secure; - bool discard; + bool httponly; bool session; - int32 maxAge; + BDateTime expire; } expected; } ExplodeTest; -const ExplodeTest kTestExplode[] = - // Cookie string - // Name Value Domain Path Secure Discard Session maxAge - // -------- --------- --------- --------- ------ ------- -------- ------- + +ExplodeTest kTestExplode[] = + // Cookie string URL + // ------------- ------------- + // Valid Name Value Domain Path Secure HttpOnly Session Expiration + // --------- -------- --------- ----------------- --------- -------- -------- ------- ---------- { - { "name=value", - { "name", "value", "", "", false, false, true, 0 } }, - { "name=value;secure=true", - { "name", "value", "", "", true, false, true, 0 } }, - { "name=value;secure=false;maxage=5", - { "name", "value", "", "", false, false, false, 5 } }, - { "name=value;discard=true", - { "name", "value", "", "", false, true, true, 0 } }, + // Normal cookies + { "name=value", "http://www.example.com/path/path", + { true, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } }, + { "name=value; domain=example.com; path=/; secure", "http://www.example.com/path/path", + { true, "name", "value", "example.com", "/" , true, false, true, BDateTime() } }, + { "name=value; httponly; secure", "http://www.example.com/path/path", + { true, "name", "value", "www.example.com", "/path", true, true, true, BDateTime() } }, + { "name=value; expires=Wed, 20 Feb 2013 20:00:00 UTC", "http://www.example.com/path/path", + { true, "name", "value", "www.example.com", "/path", false, false, false, + BDateTime(BDate(2012, 2, 20), BTime(20, 0, 0, 0)) } }, + // Valid cookie with bad form + { "name= ; domain =example.com ;path=/; secure = yup ; blahblah ;)", "http://www.example.com/path/path", + { true, "name", "", "example.com", "/" , true, false, true, BDateTime() } }, + // Invalid path, default path should be used instead + { "name=value; path=invalid", "http://www.example.com/path/path", + { true, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } }, + // Setting for other subdomain (invalid) + { "name=value; domain=subdomain.example.com", "http://www.example.com/path/path", + { false, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } }, + // Various invalid cookies + { "name", "http://www.example.com/path/path", + { false, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } }, + { "; domain=example.com", "http://www.example.com/path/path", + { false, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } } }; void explodeImplodeTest() { - uint8 testIndex; + uint32 testIndex; BNetworkCookie cookie; for (testIndex = 0; testIndex < (sizeof(kTestExplode) / sizeof(ExplodeTest)); testIndex++) { - cookie.ParseCookieString(kTestExplode[testIndex].cookieString); + BUrl url(kTestExplode[testIndex].url); + cookie.ParseCookieStringFromUrl(kTestExplode[testIndex].cookieString, url); - ASSERT(testIndex, BString(kTestExplode[testIndex].expected.name) == BString(cookie.Name())); - ASSERT(testIndex, BString(kTestExplode[testIndex].expected.value) == BString(cookie.Value())); - ASSERT(testIndex, BString(kTestExplode[testIndex].expected.domain) == BString(cookie.Domain())); - ASSERT(testIndex, BString(kTestExplode[testIndex].expected.path) == BString(cookie.Path())); - ASSERT(testIndex, kTestExplode[testIndex].expected.secure == cookie.Secure()); - ASSERT(testIndex, kTestExplode[testIndex].expected.discard == cookie.Discard()); - ASSERT(testIndex, kTestExplode[testIndex].expected.session == cookie.IsSessionCookie()); + ASSERT(testIndex, kTestExplode[testIndex].expected.valid == cookie.IsValid()); - if (!cookie.IsSessionCookie()) - ASSERT(testIndex, kTestExplode[testIndex].expected.maxAge == cookie.MaxAge()); + if (kTestExplode[testIndex].expected.valid) { + ASSERT(testIndex, BString(kTestExplode[testIndex].expected.name) == cookie.Name()); + ASSERT(testIndex, BString(kTestExplode[testIndex].expected.value) == cookie.Value()); + ASSERT(testIndex, BString(kTestExplode[testIndex].expected.domain) == cookie.Domain()); + ASSERT(testIndex, BString(kTestExplode[testIndex].expected.path) == cookie.Path()); + ASSERT(testIndex, kTestExplode[testIndex].expected.secure == cookie.Secure()); + ASSERT(testIndex, kTestExplode[testIndex].expected.httponly == cookie.HttpOnly()); + ASSERT(testIndex, kTestExplode[testIndex].expected.session == cookie.IsSessionCookie()); + + if (!cookie.IsSessionCookie()) + ASSERT(testIndex, kTestExplode[testIndex].expected.expire.Time_t() == cookie.ExpirationDate()); + } } } @@ -79,27 +102,27 @@ void explodeImplodeTest() void stressTest(int32 domainNumber, int32 totalCookies, char** flat, ssize_t* size) { char **domains = new char*[domainNumber]; - + cout << "Creating random domains" << endl; srand(time(NULL)); for (int32 i = 0; i < domainNumber; i++) { int16 charNum = (rand() % 16) + 1; - + domains[i] = new char[charNum + 5]; - + // Random domain - for (int32 c = 0; c < charNum; c++) + for (int32 c = 0; c < charNum; c++) domains[i][c] = (rand() % 26) + 'a'; - + domains[i][charNum] = '.'; - + // Random tld - for (int32 c = 0; c < 3; c++) + for (int32 c = 0; c < 3; c++) domains[i][charNum+1+c] = (rand() % 26) + 'a'; - + domains[i][charNum+4] = 0; } - + BNetworkCookieJar j; BStopWatch* watch = new BStopWatch("Cookie insertion"); for (int32 i = 0; i < totalCookies; i++) { @@ -107,21 +130,21 @@ void stressTest(int32 domainNumber, int32 totalCookies, char** flat, ssize_t* si int16 domain = (rand() % domainNumber); BString name("Foo"); name << i; - + c.SetName(name); c.SetValue("Bar"); c.SetDomain(domains[domain]); c.SetPath("/"); - + j.AddCookie(c); } delete watch; - + BNetworkCookie* c; int16 domain = (rand() % domainNumber); BString host("http://"); host << domains[domain] << "/"; - + watch = new BStopWatch("Cookie filtering"); BUrl url(host); int32 count = 0; @@ -131,17 +154,17 @@ void stressTest(int32 domainNumber, int32 totalCookies, char** flat, ssize_t* si } delete watch; cout << "Count for " << host << ": " << count << endl; - - + + cout << "Flat view of cookie jar is " << j.FlattenedSize() << " bytes large." << endl; *flat = new char[j.FlattenedSize()]; *size = j.FlattenedSize(); - + if (j.Flatten(*flat, j.FlattenedSize()) == B_OK) cout << "Flatten() success!" << endl; else cout << "Flatten() error!" << endl; - + delete[] domains; } @@ -152,22 +175,22 @@ main(int, char**) cout << "Running explodeImplodeTest:" << endl; explodeImplodeTest(); cout << endl << endl; - + cout << "Running stressTest:" << endl; char* flatJar; ssize_t size; stressTest(10000, 40000, &flatJar, &size); - + BNetworkCookieJar j; j.Unflatten(B_ANY_TYPE, flatJar, size); - + int32 count = 0; BNetworkCookie* c; for (BNetworkCookieJar::Iterator it(j.GetIterator()); (c = it.Next()); ) count++; cout << "Count : " << count << endl; - + delete[] flatJar; - + return EXIT_SUCCESS; }