aboutsummaryrefslogtreecommitdiffstats
path: root/src/cowboy_http.erl
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2011-12-07 19:27:06 +0100
committerLoïc Hoguin <[email protected]>2011-12-07 19:27:06 +0100
commit7f46e5343625ba32b6e93e6a9a1ba76b4447b7a8 (patch)
tree187043c91714586beff865321c1e70ac000ecefc /src/cowboy_http.erl
parentce92ab1e633408b0d6b2d4bb4ba61d965208ef3c (diff)
parentc747efbd7533c3b4dd7caa267070c36608c4c0d2 (diff)
downloadcowboy-7f46e5343625ba32b6e93e6a9a1ba76b4447b7a8.tar.gz
cowboy-7f46e5343625ba32b6e93e6a9a1ba76b4447b7a8.tar.bz2
cowboy-7f46e5343625ba32b6e93e6a9a1ba76b4447b7a8.zip
Merge branch 'noquoted' of https://github.com/klaar/cowboy
Diffstat (limited to 'src/cowboy_http.erl')
-rw-r--r--src/cowboy_http.erl51
1 files changed, 50 insertions, 1 deletions
diff --git a/src/cowboy_http.erl b/src/cowboy_http.erl
index 4bb7c2c..fd0d142 100644
--- a/src/cowboy_http.erl
+++ b/src/cowboy_http.erl
@@ -23,7 +23,7 @@
digits/1, token/2, token_ci/2, quoted_string/2]).
%% Interpretation.
--export([connection_to_atom/1]).
+-export([connection_to_atom/1, urldecode/1, urldecode/2]).
-include("include/http.hrl").
-include_lib("eunit/include/eunit.hrl").
@@ -670,6 +670,46 @@ connection_to_atom([<<"close">>|_Tail]) ->
connection_to_atom([_Any|Tail]) ->
connection_to_atom(Tail).
+%% @doc Decode a URL encoded binary.
+%% @equiv urldecode(Bin, crash)
+-spec urldecode(binary()) -> binary().
+urldecode(Bin) when is_binary(Bin) ->
+ urldecode(Bin, <<>>, crash).
+
+%% @doc Decode a URL encoded binary.
+%% The second argument specifies how to handle percent characters that are not
+%% followed by two valid hex characters. Use `skip' to ignore such errors,
+%% if `crash' is used the function will fail with the reason `badarg'.
+-spec urldecode(binary(), crash | skip) -> binary().
+urldecode(Bin, OnError) when is_binary(Bin) ->
+ urldecode(Bin, <<>>, OnError).
+
+-spec urldecode(binary(), binary(), crash | skip) -> binary().
+urldecode(<<$%, H, L, Rest/binary>>, Acc, OnError) ->
+ G = unhex(H),
+ M = unhex(L),
+ if G =:= error; M =:= error ->
+ case OnError of skip -> ok; crash -> erlang:error(badarg) end,
+ urldecode(<<H, L, Rest/binary>>, <<Acc/binary, $%>>, OnError);
+ true ->
+ urldecode(Rest, <<Acc/binary, (G bsl 4 bor M)>>, OnError)
+ end;
+urldecode(<<$%, Rest/binary>>, Acc, OnError) ->
+ case OnError of skip -> ok; crash -> erlang:error(badarg) end,
+ urldecode(Rest, <<Acc/binary, $%>>, OnError);
+urldecode(<<$+, Rest/binary>>, Acc, OnError) ->
+ urldecode(Rest, <<Acc/binary, $ >>, OnError);
+urldecode(<<C, Rest/binary>>, Acc, OnError) ->
+ urldecode(Rest, <<Acc/binary, C>>, OnError);
+urldecode(<<>>, Acc, _OnError) ->
+ Acc.
+
+-spec unhex(byte()) -> byte() | error.
+unhex(C) when C >= $0, C =< $9 -> C - $0;
+unhex(C) when C >= $A, C =< $F -> C - $A + 10;
+unhex(C) when C >= $a, C =< $f -> C - $a + 10;
+unhex(_) -> error.
+
%% Tests.
-ifdef(TEST).
@@ -836,4 +876,13 @@ digits_test_() ->
],
[{V, fun() -> R = digits(V) end} || {V, R} <- Tests].
+urldecode_test_() ->
+ Tests = [
+ {<<" ">>, <<"%20">>},
+ {<<" ">>, <<"+">>},
+ {<<0>>, <<"%00">>},
+ {<<255>>, <<"%fF">>}
+ ],
+ [{I, ?_assertEqual(E, urldecode(I))} || {E, I} <- Tests].
+
-endif.