diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cowboy_router.erl | 25 |
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. |