From c747efbd7533c3b4dd7caa267070c36608c4c0d2 Mon Sep 17 00:00:00 2001 From: Magnus Klaar Date: Mon, 5 Dec 2011 01:08:38 +0100 Subject: replace quoted:from_url with cowboy_http:urldecode This change makes the dependency on quoted optional by adding a minimal urldecode function to cowboy. A protocol option for setting the urldecoding function has been added to the cowboy_http_protocol module. The default value for this option is set to be equivalent to the default settings for quoted. {fun cowboy_http:urldecode/2, crash} A note has been added in the README to document how to use quoted instead of this function. A field to store this option value has been added to the state record in the cowboy_http_protocol module and the http_req record in include/http.hrl Functions that previously used quoted:from_url/1 has been updated to require an equivalent function in addition to the previously required arguments. This change removes a C compiler from the build requirements of cowboy. It also removes the requirement to cross compile the code if the target arch/OS is different from the arch/OS used to build it. --- src/cowboy_http.erl | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) (limited to 'src/cowboy_http.erl') 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(<>, <>, OnError); + true -> + urldecode(Rest, <>, OnError) + end; +urldecode(<<$%, Rest/binary>>, Acc, OnError) -> + case OnError of skip -> ok; crash -> erlang:error(badarg) end, + urldecode(Rest, <>, OnError); +urldecode(<<$+, Rest/binary>>, Acc, OnError) -> + urldecode(Rest, <>, OnError); +urldecode(<>, Acc, OnError) -> + urldecode(Rest, <>, 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. -- cgit v1.2.3