aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/cowboy_router.erl25
1 files changed, 23 insertions, 2 deletions
diff --git a/src/cowboy_router.erl b/src/cowboy_router.erl
index f07b307..f2f8fb4 100644
--- a/src/cowboy_router.erl
+++ b/src/cowboy_router.erl
@@ -322,9 +322,9 @@ split_path(Path, Acc) ->
try
case binary:match(Path, <<"/">>) of
nomatch when Path =:= <<>> ->
- lists:reverse([cow_qs:urldecode(S) || S <- Acc]);
+ remove_dot_segments(lists:reverse([cow_uri:urldecode(S) || S <- Acc]), []);
nomatch ->
- lists:reverse([cow_qs:urldecode(S) || S <- [Path|Acc]]);
+ remove_dot_segments(lists:reverse([cow_uri:urldecode(S) || S <- [Path|Acc]]), []);
{Pos, _} ->
<< Segment:Pos/binary, _:8, Rest/bits >> = Path,
split_path(Rest, [Segment|Acc])
@@ -334,6 +334,27 @@ split_path(Path, Acc) ->
badrequest
end.
+remove_dot_segments([], Acc) ->
+ lists:reverse(Acc);
+remove_dot_segments([<<".">>|Segments], Acc) ->
+ remove_dot_segments(Segments, Acc);
+remove_dot_segments([<<"..">>|Segments], Acc=[]) ->
+ remove_dot_segments(Segments, Acc);
+remove_dot_segments([<<"..">>|Segments], [_|Acc]) ->
+ remove_dot_segments(Segments, Acc);
+remove_dot_segments([S|Segments], Acc) ->
+ remove_dot_segments(Segments, [S|Acc]).
+
+-ifdef(TEST).
+remove_dot_segments_test_() ->
+ Tests = [
+ {[<<"a">>, <<"b">>, <<"c">>, <<".">>, <<"..">>, <<"..">>, <<"g">>], [<<"a">>, <<"g">>]},
+ {[<<"mid">>, <<"content=5">>, <<"..">>, <<"6">>], [<<"mid">>, <<"6">>]},
+ {[<<"..">>, <<"a">>], [<<"a">>]}
+ ],
+ [fun() -> R = remove_dot_segments(S, []) end || {S, R} <- Tests].
+-endif.
+
-spec list_match(tokens(), dispatch_match(), bindings())
-> {true, bindings(), undefined | tokens()} | false.
%% Atom '...' matches any trailing path, stop right now.