Commit 64527a5d authored by battre@chromium.org's avatar battre@chromium.org

Add a mutable version of CookieMonster::ParsedCookie

This CL implements CookieMonster::MutableParsedCookie which is derived from CookieMonster::ParsedCookie. This allows parsing a cookie and modifying it afterwards.

BUG=112155
TEST=no


Review URL: https://chromiumcodereview.appspot.com/10697035

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@149622 0039d316-1c4b-4281-b951-d872f2087c98
parent 4f05741a
This diff is collapsed.
......@@ -27,8 +27,9 @@ class NET_EXPORT ParsedCookie {
ParsedCookie(const std::string& cookie_line);
~ParsedCookie();
// You should not call any other methods on the class if !IsValid
bool IsValid() const { return is_valid_; }
// You should not call any other methods except for SetName/SetValue on the
// class if !IsValid.
bool IsValid() const;
const std::string& Name() const { return pairs_[0].first; }
const std::string& Token() const { return Name(); }
......@@ -55,8 +56,24 @@ class NET_EXPORT ParsedCookie {
// "BLAH=hah; path=/; domain=.google.com"
size_t NumberOfAttributes() const { return pairs_.size() - 1; }
// For debugging only!
std::string DebugString() const;
// These functions set the respective properties of the cookie. If the
// parameters are empty, the respective properties are cleared.
// The functions return false in case an error occurred.
// The cookie needs to be assigned a name/value before setting the other
// attributes.
bool SetName(const std::string& name);
bool SetValue(const std::string& value);
bool SetPath(const std::string& path);
bool SetDomain(const std::string& domain);
bool SetMACKey(const std::string& mac_key);
bool SetMACAlgorithm(const std::string& mac_algorithm);
bool SetExpires(const std::string& expires);
bool SetMaxAge(const std::string& maxage);
bool SetIsSecure(bool is_secure);
bool SetIsHttpOnly(bool is_http_only);
// Returns the cookie description as it appears in a HTML response header.
std::string ToCookieLine() const;
// Returns an iterator pointing to the first terminator character found in
// the given string.
......@@ -87,15 +104,32 @@ class NET_EXPORT ParsedCookie {
static std::string ParseValueString(const std::string& value);
private:
static const char kTerminator[];
static const int kTerminatorLen;
static const char kWhitespace[];
static const char kValueSeparator[];
static const char kTokenSeparator[];
void ParseTokenValuePairs(const std::string& cookie_line);
void SetupAttributes();
// Sets a key/value pair for a cookie. |index| has to point to one of the
// |*_index_| fields in ParsedCookie and is updated to the position where
// the key/value pair is set in |pairs_|. Accordingly, |key| has to correspond
// to the token matching |index|. If |value| contains invalid characters, the
// cookie parameter is not changed and the function returns false.
// If |value| is empty/false the key/value pair is removed.
bool SetString(size_t* index,
const std::string& key,
const std::string& value);
bool SetBool(size_t* index,
const std::string& key,
bool value);
// Helper function for SetString and SetBool handling the case that the
// key/value pair shall not be removed.
bool SetAttributePair(size_t* index,
const std::string& key,
const std::string& value);
// Removes the key/value pair from a cookie that is identified by |index|.
// |index| refers to a position in |pairs_|.
void ClearAttributePair(size_t index);
PairList pairs_;
bool is_valid_;
// These will default to 0, but that should never be valid since the
......
......@@ -275,4 +275,142 @@ TEST(ParsedCookieTest, ParseTokensAndValues) {
ParsedCookie::ParseValueString("A=B=C;D=E"));
}
TEST(ParsedCookieTest, SerializeCookieLine) {
const char input[] = "ANCUUID=zohNumRKgI0oxyhSsV3Z7D ; "
"expires=Sun, 18-Apr-2027 21:06:29 GMT ; "
"path=/ ; ";
const char output[] = "ANCUUID=zohNumRKgI0oxyhSsV3Z7D; "
"expires=Sun, 18-Apr-2027 21:06:29 GMT; "
"path=/";
ParsedCookie pc(input);
EXPECT_EQ(output, pc.ToCookieLine());
}
TEST(ParsedCookieTest, SetNameAndValue) {
ParsedCookie empty("");
EXPECT_FALSE(empty.IsValid());
EXPECT_FALSE(empty.SetDomain("foobar.com"));
EXPECT_TRUE(empty.SetName("name"));
EXPECT_TRUE(empty.SetValue("value"));
EXPECT_EQ("name=value", empty.ToCookieLine());
EXPECT_TRUE(empty.IsValid());
// We don't test
// ParsedCookie invalid("@foo=bar");
// EXPECT_FALSE(invalid.IsValid());
// here because we are slightly more tolerant to invalid cookie names and
// values that are set by webservers. We only enforce a correct name and
// value if set via SetName() and SetValue().
ParsedCookie pc("name=value");
EXPECT_TRUE(pc.IsValid());
// Set invalid name / value.
EXPECT_FALSE(pc.SetName("@foobar"));
EXPECT_EQ("name=value", pc.ToCookieLine());
EXPECT_TRUE(pc.IsValid());
EXPECT_FALSE(pc.SetName(""));
EXPECT_EQ("name=value", pc.ToCookieLine());
EXPECT_TRUE(pc.IsValid());
EXPECT_FALSE(pc.SetValue("foo bar"));
EXPECT_EQ("name=value", pc.ToCookieLine());
EXPECT_TRUE(pc.IsValid());
EXPECT_FALSE(pc.SetValue("\"foobar"));
EXPECT_EQ("name=value", pc.ToCookieLine());
EXPECT_TRUE(pc.IsValid());
// Set valid name / value
EXPECT_TRUE(pc.SetName("test"));
EXPECT_EQ("test=value", pc.ToCookieLine());
EXPECT_TRUE(pc.IsValid());
EXPECT_TRUE(pc.SetValue("\"foobar\""));
EXPECT_EQ("test=\"foobar\"", pc.ToCookieLine());
EXPECT_TRUE(pc.IsValid());
EXPECT_TRUE(pc.SetValue(""));
EXPECT_EQ("test=", pc.ToCookieLine());
EXPECT_TRUE(pc.IsValid());
}
TEST(ParsedCookieTest, SetAttributes) {
ParsedCookie pc("name=value");
EXPECT_TRUE(pc.IsValid());
// Clear an unset attribute.
EXPECT_TRUE(pc.SetDomain(""));
EXPECT_FALSE(pc.HasDomain());
EXPECT_EQ("name=value", pc.ToCookieLine());
EXPECT_TRUE(pc.IsValid());
// Set a string containing an invalid character
EXPECT_FALSE(pc.SetDomain("foo;bar"));
EXPECT_FALSE(pc.HasDomain());
EXPECT_EQ("name=value", pc.ToCookieLine());
EXPECT_TRUE(pc.IsValid());
// Set all other attributes and check that they are appended in order.
EXPECT_TRUE(pc.SetDomain("domain.com"));
EXPECT_TRUE(pc.SetPath("/"));
EXPECT_TRUE(pc.SetMACKey("mackey"));
EXPECT_TRUE(pc.SetMACAlgorithm("\"macalgorithm\""));
EXPECT_TRUE(pc.SetExpires("Sun, 18-Apr-2027 21:06:29 GMT"));
EXPECT_TRUE(pc.SetMaxAge("12345"));
EXPECT_TRUE(pc.SetIsSecure(true));
EXPECT_TRUE(pc.SetIsHttpOnly(true));
EXPECT_EQ("name=value; domain=domain.com; path=/; mac-key=mackey; "
"mac-algorithm=\"macalgorithm\"; "
"expires=Sun, 18-Apr-2027 21:06:29 GMT; max-age=12345; secure; "
"httponly",
pc.ToCookieLine());
EXPECT_TRUE(pc.HasDomain());
EXPECT_TRUE(pc.HasPath());
EXPECT_TRUE(pc.HasMACKey());
EXPECT_TRUE(pc.HasMACAlgorithm());
EXPECT_TRUE(pc.HasExpires());
EXPECT_TRUE(pc.HasMaxAge());
EXPECT_TRUE(pc.IsSecure());
EXPECT_TRUE(pc.IsHttpOnly());
// Clear one attribute from the middle.
EXPECT_TRUE(pc.SetMACAlgorithm(""));
EXPECT_TRUE(pc.HasDomain());
EXPECT_TRUE(pc.HasPath());
EXPECT_TRUE(pc.HasMACKey());
EXPECT_FALSE(pc.HasMACAlgorithm());
EXPECT_TRUE(pc.HasExpires());
EXPECT_TRUE(pc.HasMaxAge());
EXPECT_TRUE(pc.IsSecure());
EXPECT_TRUE(pc.IsHttpOnly());
EXPECT_EQ("name=value; domain=domain.com; path=/; mac-key=mackey; "
"expires=Sun, 18-Apr-2027 21:06:29 GMT; max-age=12345; secure; "
"httponly",
pc.ToCookieLine());
// Clear the rest and change the name and value.
EXPECT_TRUE(pc.SetDomain(""));
EXPECT_TRUE(pc.SetPath(""));
EXPECT_TRUE(pc.SetMACKey(""));
EXPECT_TRUE(pc.SetMACAlgorithm(""));
EXPECT_TRUE(pc.SetExpires(""));
EXPECT_TRUE(pc.SetMaxAge(""));
EXPECT_TRUE(pc.SetIsSecure(false));
EXPECT_TRUE(pc.SetIsHttpOnly(false));
EXPECT_TRUE(pc.SetName("name2"));
EXPECT_TRUE(pc.SetValue("value2"));
EXPECT_FALSE(pc.HasDomain());
EXPECT_FALSE(pc.HasPath());
EXPECT_FALSE(pc.HasMACKey());
EXPECT_FALSE(pc.HasMACAlgorithm());
EXPECT_FALSE(pc.HasExpires());
EXPECT_FALSE(pc.HasMaxAge());
EXPECT_FALSE(pc.IsSecure());
EXPECT_FALSE(pc.IsHttpOnly());
EXPECT_EQ("name2=value2", pc.ToCookieLine());
}
} // namespace net
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment