aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/stdlib/src/uri_string.erl91
-rw-r--r--lib/stdlib/test/uri_string_SUITE.erl18
2 files changed, 59 insertions, 50 deletions
diff --git a/lib/stdlib/src/uri_string.erl b/lib/stdlib/src/uri_string.erl
index 2bf7ceaff1..09bf4aef1d 100644
--- a/lib/stdlib/src/uri_string.erl
+++ b/lib/stdlib/src/uri_string.erl
@@ -423,18 +423,21 @@ compose_query([], _Options, IsList, Acc) ->
QueryString :: uri_string(),
QueryList :: [{string(), string()}]
| {error, atom(), list() | binary()}.
+dissect_query(<<>>) ->
+ [];
dissect_query([]) ->
[];
-dissect_query(QueryString) when is_binary(QueryString) ->
- L = convert_list(QueryString, utf8),
- try dissect_query_key(L, [], [], []) of
+dissect_query(QueryString) when is_list(QueryString) ->
+ try
+ B = convert_binary(QueryString, utf8, utf8),
+ dissect_query_key(B, true, [], <<>>, <<>>)
+ of
Result -> Result
catch
throw:{error, Atom, RestData} -> {error, Atom, RestData}
end;
dissect_query(QueryString) ->
- L = flatten_list(QueryString, utf8),
- try dissect_query_key(L, [], [], []) of
+ try dissect_query_key(QueryString, false, [], <<>>, <<>>) of
Result -> Result
catch
throw:{error, Atom, RestData} -> {error, Atom, RestData}
@@ -1706,7 +1709,6 @@ flatten_list(Arg, _, _) ->
throw({error, badarg, Arg}).
-
percent_encode_segment(Segment) ->
percent_encode_binary(Segment, <<>>).
@@ -1790,50 +1792,48 @@ is_unsafe(_) -> false.
%%-------------------------------------------------------------------------
%% Helper functions for dissect_query
%%-------------------------------------------------------------------------
-dissect_query_key([$=|T], Acc, Key, Value) ->
- dissect_query_value(T, Acc, Key, Value);
-dissect_query_key([H|T], Acc, Key, Value) ->
- dissect_query_key(T, Acc, [H|Key], Value);
-dissect_query_key(L, _, _, _) ->
- throw({error, missing_value, L}).
-
-
-dissect_query_value([$&|_] = L, Acc, Key, Value) ->
- K = form_urldecode(lists:reverse(Key)),
- V = form_urldecode(lists:reverse(Value)),
- dissect_query_separator_amp(L, [{K,V}|Acc], [], []);
-dissect_query_value([$;|_] = L, Acc, Key, Value) ->
- K = form_urldecode(lists:reverse(Key)),
- V = form_urldecode(lists:reverse(Value)),
- dissect_query_separator_semicolon(L, [{K,V}|Acc], [], []);
-dissect_query_value([H|T], Acc, Key, Value) ->
- dissect_query_value(T, Acc, Key, [H|Value]);
-dissect_query_value([], Acc, Key, Value) ->
- K = form_urldecode(lists:reverse(Key)),
- V = form_urldecode(lists:reverse(Value)),
+dissect_query_key(<<$=,T/binary>>, IsList, Acc, Key, Value) ->
+ dissect_query_value(T, IsList, Acc, Key, Value);
+dissect_query_key(<<H,T/binary>>, IsList, Acc, Key, Value) ->
+ dissect_query_key(T, IsList, Acc, <<Key/binary,H>>, Value);
+dissect_query_key(B, _, _, _, _) ->
+ throw({error, missing_value, B}).
+
+
+dissect_query_value(<<$&,_/binary>> = B, IsList, Acc, Key, Value) ->
+ K = form_urldecode(IsList, Key),
+ V = form_urldecode(IsList, Value),
+ dissect_query_separator_amp(B, IsList, [{K,V}|Acc], <<>>, <<>>);
+dissect_query_value(<<$;,_/binary>> = B, IsList, Acc, Key, Value) ->
+ K = form_urldecode(IsList, Key),
+ V = form_urldecode(IsList, Value),
+ dissect_query_separator_semicolon(B, IsList, [{K,V}|Acc], <<>>, <<>>);
+dissect_query_value(<<H,T/binary>>, IsList, Acc, Key, Value) ->
+ dissect_query_value(T, IsList, Acc, Key, <<Value/binary,H>>);
+dissect_query_value(<<>>, IsList, Acc, Key, Value) ->
+ K = form_urldecode(IsList, Key),
+ V = form_urldecode(IsList, Value),
lists:reverse([{K,V}|Acc]).
-dissect_query_separator_amp("&amp;" ++ T, Acc, Key, Value) ->
- dissect_query_key(T, Acc, Key, Value);
-dissect_query_separator_amp("&" ++ T, Acc, Key, Value) ->
- dissect_query_key(T, Acc, Key, Value);
-dissect_query_separator_amp(L, _, _, _) ->
- throw({error, invalid_separator, L}).
+dissect_query_separator_amp(<<"&amp;",T/binary>>, IsList, Acc, Key, Value) ->
+ dissect_query_key(T, IsList, Acc, Key, Value);
+dissect_query_separator_amp(<<$&,T/binary>>, IsList, Acc, Key, Value) ->
+ dissect_query_key(T, IsList, Acc, Key, Value).
-dissect_query_separator_semicolon([$;|T], Acc, Key, Value) ->
- dissect_query_key(T, Acc, Key, Value).
+dissect_query_separator_semicolon(<<$;,T/binary>>, IsList, Acc, Key, Value) ->
+ dissect_query_key(T, IsList, Acc, Key, Value).
%% Form-urldecode input based on RFC 1866 [8.2.1]
-form_urldecode(Cs) ->
- B = convert_binary(Cs, utf8, utf8),
+form_urldecode(true, B) ->
Result = form_urldecode(B, <<>>),
- convert_list(Result, utf8).
-%%
+ convert_list(Result, utf8);
+form_urldecode(false, B) ->
+ form_urldecode(B, <<>>);
form_urldecode(<<>>, Acc) ->
- convert_list(Acc, utf8);
+ Acc;
form_urldecode(<<$+,T/binary>>, Acc) ->
form_urldecode(T, <<Acc/binary,$ >>);
form_urldecode(<<$%,C0,C1,T/binary>>, Acc) ->
@@ -1843,13 +1843,14 @@ form_urldecode(<<$%,C0,C1,T/binary>>, Acc) ->
form_urldecode(T, <<Acc/binary, V>>);
false ->
L = convert_list(<<$%,C0,C1,T/binary>>, utf8),
- throw({error, urldecode, L})
+ throw({error, invalid_percent_encoding, L})
end;
-form_urldecode(<<H,T/binary>>, Acc) ->
+form_urldecode(<<H/utf8,T/binary>>, Acc) ->
case is_url_char(H) of
true ->
form_urldecode(T, <<Acc/binary,H>>);
false ->
- L = convert_list(<<H,T/binary>>, utf8),
- throw({error, urldecode, L})
- end.
+ throw({error, invalid_character, [H]})
+ end;
+form_urldecode(<<H,_/binary>>, _Acc) ->
+ throw({error, invalid_character, [H]}).
diff --git a/lib/stdlib/test/uri_string_SUITE.erl b/lib/stdlib/test/uri_string_SUITE.erl
index c230f7c631..2fc4e1a092 100644
--- a/lib/stdlib/test/uri_string_SUITE.erl
+++ b/lib/stdlib/test/uri_string_SUITE.erl
@@ -846,13 +846,21 @@ dissect_query(_Config) ->
[{"foo","1"}, {"bar", "2"}] = uri_string:dissect_query("foo=1&bar=2"),
[{"foo","1"}, {"bar", "2"}] = uri_string:dissect_query("foo=1;bar=2"),
[{"foo","1"}, {"bar", "222"}] = uri_string:dissect_query([<<"foo=1;bar=2">>,"22"]),
- [{"foo","ö"}, {"bar", "2"}] = uri_string:dissect_query("foo=%C3%B6&amp;bar=2").
+ [{"foo","ö"}, {"bar", "2"}] = uri_string:dissect_query("foo=%C3%B6&amp;bar=2"),
+ [{<<"foo">>,<<"ö"/utf8>>}, {<<"bar">>, <<"2">>}] =
+ uri_string:dissect_query(<<"foo=%C3%B6&amp;bar=2">>),
+ [{"foo bar","1"},{"ö","2"}] =
+ uri_string:dissect_query([<<"foo+bar=1&amp;">>,<<"%C3%B6=2">>]).
dissect_query_negative(_Config) ->
- {error,urldecode,";bar"} =
+ {error,invalid_character,";"} =
uri_string:dissect_query("foo=1&ap;bar=2"),
- {error,urldecode,"&amp;bar"} =
+ {error,invalid_character,"&"} =
uri_string:dissect_query("foo1&amp;bar=2"),
- {error,urldecode,"%XX%B6"} = uri_string:dissect_query("foo=%XX%B6&amp;bar=2"),
+ {error,invalid_percent_encoding,"%XX%B6"} = uri_string:dissect_query("foo=%XX%B6&amp;bar=2"),
{error,invalid_input,<<153,182>>} =
- uri_string:dissect_query("foo=%99%B6&amp;bar=2").
+ uri_string:dissect_query("foo=%99%B6&amp;bar=2"),
+ {error,invalid_character,"ö"} = uri_string:dissect_query("föo+bar=1&amp;%C3%B6=2"),
+ {error,invalid_character,"ö"} = uri_string:dissect_query(<<"föo+bar=1&amp;%C3%B6=2">>),
+ {error,invalid_input,<<"ö">>} =
+ uri_string:dissect_query([<<"foo+bar=1&amp;">>,<<"%C3%B6=2ö">>]).