From 8858ca240fe42e3fcd0b9c3b1a2388b432301a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Thu, 20 Dec 2012 14:19:39 +0100 Subject: Fix parsing of the Cookie header This should be equivalent to what we do in Set-Cookie. Real-world testing is needed to confirm it works as intended. --- src/cowboy_http.erl | 64 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 10 deletions(-) (limited to 'src/cowboy_http.erl') diff --git a/src/cowboy_http.erl b/src/cowboy_http.erl index 4754649..aa94016 100644 --- a/src/cowboy_http.erl +++ b/src/cowboy_http.erl @@ -121,7 +121,7 @@ cookie_list(Data, Acc) -> fun (<<>>) -> Acc; (<< $,, Rest/binary >>) -> cookie_list(Rest, Acc); (<< $;, Rest/binary >>) -> cookie_list(Rest, Acc); - (Rest) -> param(Rest, + (Rest) -> cookie(Rest, fun (Rest2, << $$, _/bits >>, _) -> cookie_list(Rest2, Acc); (Rest2, Name, Value) -> @@ -129,6 +129,50 @@ cookie_list(Data, Acc) -> end) end). +-spec cookie(binary(), fun()) -> any(). +cookie(Data, Fun) -> + whitespace(Data, + fun (Rest) -> + cookie_name(Rest, + fun (_Rest2, <<>>) -> {error, badarg}; + (<< $=, Rest2/binary >>, Name) -> + cookie_value(Rest2, + fun (Rest3, Value) -> + Fun(Rest3, Name, Value) + end); + (_Rest2, _Attr) -> {error, badarg} + end) + end). + +-spec cookie_name(binary(), fun()) -> any(). +cookie_name(Data, Fun) -> + cookie_name(Data, Fun, <<>>). + +-spec cookie_name(binary(), fun(), binary()) -> any(). +cookie_name(<<>>, Fun, Acc) -> + Fun(<<>>, Acc); +cookie_name(Data = << C, _Rest/binary >>, Fun, Acc) + when C =:= $=; C =:= $,; C =:= $;; C =:= $\s; C =:= $\t; + C =:= $\r; C =:= $\n; C =:= $\013; C =:= $\014 -> + Fun(Data, Acc); +cookie_name(<< C, Rest/binary >>, Fun, Acc) -> + C2 = cowboy_bstr:char_to_lower(C), + cookie_name(Rest, Fun, << Acc/binary, C2 >>). + +-spec cookie_value(binary(), fun()) -> any(). +cookie_value(Data, Fun) -> + cookie_value(Data, Fun, <<>>). + +-spec cookie_value(binary(), fun(), binary()) -> any(). +cookie_value(<<>>, Fun, Acc) -> + Fun(<<>>, Acc); +cookie_value(Data = << C, _Rest/binary >>, Fun, Acc) + when C =:= $,; C =:= $;; C =:= $\s; C =:= $\t; + C =:= $\r; C =:= $\n; C =:= $\013; C =:= $\014 -> + Fun(Data, Acc); +cookie_value(<< C, Rest/binary >>, Fun, Acc) -> + cookie_value(Rest, Fun, << Acc/binary, C >>). + %% @doc Parse a content type. -spec content_type(binary()) -> any(). content_type(Data) -> @@ -1016,24 +1060,24 @@ cookie_list_test_() -> {<<"name">>, <<"value">>}, {<<"name2">>, <<"value2">>} ]}, - {<<"$Version=\"1\"; Customer=\"WILE_E_COYOTE\"; $Path=\"/acme\"">>, [ + {<<"$Version=1; Customer=WILE_E_COYOTE; $Path=/acme">>, [ {<<"customer">>, <<"WILE_E_COYOTE">>} ]}, - {<<"$Version=\"1\"; Customer=\"WILE_E_COYOTE\"; $Path=\"/acme\"; " - "Part_Number=\"Rocket_Launcher_0001\"; $Path=\"/acme\"; " - "Shipping=\"FedEx\"; $Path=\"/acme\"">>, [ + {<<"$Version=1; Customer=WILE_E_COYOTE; $Path=/acme; " + "Part_Number=Rocket_Launcher_0001; $Path=/acme; " + "Shipping=FedEx; $Path=/acme">>, [ {<<"customer">>, <<"WILE_E_COYOTE">>}, {<<"part_number">>, <<"Rocket_Launcher_0001">>}, {<<"shipping">>, <<"FedEx">>} ]}, %% Potential edge cases (initially from Mochiweb). - {<<"foo=\"\\x\"">>, [{<<"foo">>, <<"x">>}]}, + {<<"foo=\\x">>, [{<<"foo">>, <<"\\x">>}]}, {<<"=">>, {error, badarg}}, {<<" foo ; bar ">>, {error, badarg}}, - {<<"foo=;bar=">>, {error, badarg}}, - {<<"foo=\"\\\";\";bar ">>, {error, badarg}}, - {<<"foo=\"\\\";\";bar=good ">>, - [{<<"foo">>, <<"\";">>}, {<<"bar">>, <<"good">>}]}, + {<<"foo=;bar=">>, [{<<"foo">>, <<>>}, {<<"bar">>, <<>>}]}, + {<<"foo=\\\";;bar ">>, {error, badarg}}, + {<<"foo=\\\";;bar=good ">>, + [{<<"foo">>, <<"\\\"">>}, {<<"bar">>, <<"good">>}]}, {<<"foo=\"\\\";bar">>, {error, badarg}}, {<<"">>, {error, badarg}}, {<<"foo=bar , baz=wibble ">>, -- cgit v1.2.3