zotonic/zotonic — Issue #302: z_utils:percent_encode
Author: dmitriid
Created: 2012-03-09 14:11:43+00:00
State: open

Also see http://groups.google.com/group/erlang-programming/msg/5f69c5a153f40eb7

In order to work with Twitter, for example, you need to percent encode parameters, which is *not* the same as z_utils:url_encode. url_encode converts spaces to +, whereas percent_ecnode converts them to %20.

The post referenced above provides a way to encode stuff, but it still is incorrect (even though it claims to be correct :) )

Here's the updated version. It also handles characters that are outside of ASCII range

-define(is_uppercase_alpha(C), C >= $A, C =< $Z).
-define(is_lowercase_alpha(C), C >= $a, C =< $z).
-define(is_alpha(C), ?is_uppercase_alpha(C); ?is_lowercase_alpha(C)).
-define(is_digit(C), C >= $0, C =< $9).
-define(is_alphanumeric(C), ?is_alpha(C); ?is_digit(C)).
-define(is_unreserved(C), ?is_alphanumeric(C); C =:= $-; C =:= $_; C =:= $.; C =:= $~).

percent_encode(Chars) ->
percent_encode(Chars, []).

percent_encode([], Encoded) ->
lists:flatten(lists:reverse(Encoded));
percent_encode([C|Etc], Encoded) when ?is_unreserved(C) ->
percent_encode(Etc, [C|Encoded]);
percent_encode([C|Etc], Encoded) ->
Value = [io_lib:format("%~s", [z_utils:encode([Char], 16)])
|| Char <- binary_to_list(unicode:characters_to_binary([C]))],
percent_encode(Etc, [lists:flatten(Value)|Encoded]).

It would be a nee addition to z_utils module