Merge pull request #213 from mochi/lego12239-master
fix cookie value parsing (follow up)
diff --git a/CHANGES.md b/CHANGES.md
index 45464d0..e4f10d7 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,8 @@
+Version 2.20.0 released 2019-XX-XX
+
+* Fix parsing of certain unquoted cookie values
+ https://github.com/mochi/mochiweb/pull/212
+
Version 2.19.0 released 2019-01-17
* Fix warning in 21.2.3 and crash on incompatible releases
diff --git a/src/mochiweb.app.src b/src/mochiweb.app.src
index 70c7165..6486fcb 100644
--- a/src/mochiweb.app.src
+++ b/src/mochiweb.app.src
@@ -1,7 +1,7 @@
%% This is generated from src/mochiweb.app.src
{application, mochiweb,
[{description, "MochiMedia Web Server"},
- {vsn, "2.19.0"},
+ {vsn, "2.20.0"},
{modules, []},
{registered, []},
{env, []},
diff --git a/src/mochiweb_cookies.erl b/src/mochiweb_cookies.erl
index 013dbe0..c7b0fcf 100644
--- a/src/mochiweb_cookies.erl
+++ b/src/mochiweb_cookies.erl
@@ -39,6 +39,19 @@
C =:= $[ orelse C =:= $] orelse C =:= $? orelse C =:= $= orelse
C =:= ${ orelse C =:= $})).
+%% RFC 6265 cookie value allowed characters
+%% cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
+%% ; US-ASCII characters excluding CTLs,
+%% ; whitespace DQUOTE, comma, semicolon,
+%% ; and backslash
+-define(IS_COOKIE_OCTET(C),
+ (C =:= 16#21
+ orelse (C >= 16#23 andalso C =< 16#2B)
+ orelse (C >= 16#2D andalso C =< 16#3A)
+ orelse (C >= 16#3C andalso C =< 16#5B)
+ orelse (C >= 16#5D andalso C =< 16#7E)
+ )).
+
%% @type proplist() = [{Key::string(), Value::string()}].
%% @type header() = {Name::string(), Value::string()}.
%% @type int_seconds() = integer().
@@ -208,11 +221,15 @@
[?QUOTE | _] ->
read_quoted(Value1);
_ ->
- read_token(Value1)
+ read_value_(Value1)
end;
read_value(String) ->
{"", String}.
+read_value_(String) ->
+ F = fun (C) -> ?IS_COOKIE_OCTET(C) end,
+ lists:splitwith(F, String).
+
read_quoted([?QUOTE | String]) ->
read_quoted(String, []).
@@ -302,6 +319,12 @@
?assertEqual(
[{"foo", "bar"}, {"baz", "wibble"}],
parse_cookie("foo=bar , baz=wibble ")),
+ ?assertEqual(
+ [{"foo", "base64=="}, {"bar", "base64="}],
+ parse_cookie("foo=\"base64==\";bar=\"base64=\"")),
+ ?assertEqual(
+ [{"foo", "base64=="}, {"bar", "base64="}],
+ parse_cookie("foo=base64==;bar=base64=")),
ok.
domain_test() ->