Skip to content

Commit 04eba48

Browse files
authored
Merge pull request #234 from noahshaw11/add-unquote-path-for-separate-+-encoding
Add unquote_path/1 for separate + encoding
2 parents db54089 + c388368 commit 04eba48

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

src/mochiweb_util.erl

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
-module(mochiweb_util).
77
-author('[email protected]').
8-
-export([join/2, quote_plus/1, urlencode/1, parse_qs/1, unquote/1]).
8+
-export([join/2, quote_plus/1, urlencode/1, parse_qs/1, unquote/1, unquote_path/1]).
99
-export([path_split/1]).
1010
-export([urlsplit/1, urlsplit_path/1, urlunsplit/1, urlunsplit_path/1]).
1111
-export([guess_mime/1, parse_header/1]).
@@ -34,6 +34,8 @@ hexdigit(C) when C < 16 -> $A + (C - 10).
3434
unhexdigit(C) when C >= $0, C =< $9 -> C - $0;
3535
unhexdigit(C) when C >= $a, C =< $f -> C - $a + 10;
3636
unhexdigit(C) when C >= $A, C =< $F -> C - $A + 10.
37+
unhexdigit(Hi, Lo) ->
38+
unhexdigit(Lo) bor (unhexdigit(Hi) bsl 4).
3739

3840
%% @spec partition(String, Sep) -> {String, [], []} | {Prefix, Sep, Postfix}
3941
%% @doc Inspired by Python 2.5's str.partition:
@@ -256,10 +258,27 @@ qs_revdecode([], Acc) ->
256258
qs_revdecode([$+ | Rest], Acc) ->
257259
qs_revdecode(Rest, [$\s | Acc]);
258260
qs_revdecode([Lo, Hi, ?PERCENT | Rest], Acc) when ?IS_HEX(Lo), ?IS_HEX(Hi) ->
259-
qs_revdecode(Rest, [(unhexdigit(Lo) bor (unhexdigit(Hi) bsl 4)) | Acc]);
261+
qs_revdecode(Rest, [(unhexdigit(Hi, Lo)) | Acc]);
260262
qs_revdecode([C | Rest], Acc) ->
261263
qs_revdecode(Rest, [C | Acc]).
262264

265+
%% @spec unquote_path(string() | binary()) -> string()
266+
%% @doc Unquote a URL encoded string, does not encode + into space.
267+
unquote_path(Binary) when is_binary(Binary) ->
268+
unquote_path(binary_to_list(Binary));
269+
unquote_path(String) ->
270+
qs_revdecode_path(lists:reverse(String)).
271+
272+
qs_revdecode_path(S) ->
273+
qs_revdecode_path(S, []).
274+
275+
qs_revdecode_path([], Acc) ->
276+
Acc;
277+
qs_revdecode_path([Lo, Hi, ?PERCENT | Rest], Acc) when ?IS_HEX(Lo), ?IS_HEX(Hi) ->
278+
qs_revdecode_path(Rest, [(unhexdigit(Hi, Lo)) | Acc]);
279+
qs_revdecode_path([C | Rest], Acc) ->
280+
qs_revdecode_path(Rest, [C | Acc]).
281+
263282
%% @spec urlsplit(Url) -> {Scheme, Netloc, Path, Query, Fragment}
264283
%% @doc Return a 5-tuple, does not expand % escapes. Only supports HTTP style
265284
%% URLs.

test/mochiweb_util_tests.erl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
-module(mochiweb_util_tests).
2+
3+
-ifdef(TEST).
4+
5+
-include_lib("eunit/include/eunit.hrl").
6+
7+
unquote_test() ->
8+
Str = "/test/path/dwabble%20wibble+quux?qs=2",
9+
?assertEqual("/test/path/dwabble wibble quux?qs=2",
10+
mochiweb_util:unquote(Str)).
11+
12+
unquote_path_test() ->
13+
Str = "/test/path/dwabble%20wibble+quux?qs=2",
14+
?assertEqual("/test/path/dwabble wibble+quux?qs=2",
15+
mochiweb_util:unquote_path(Str)).
16+
17+
-endif.

0 commit comments

Comments
 (0)