Skip to content

Commit

Permalink
Optimised URL encoding. Removed dependency on inets by implementing b…
Browse files Browse the repository at this point in the history
…ase64 encoding/decoding in ibrowse itself.
  • Loading branch information
chandrusf committed Apr 20, 2007
1 parent abd23b3 commit 898bf65
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 8 deletions.
7 changes: 7 additions & 0 deletions lib/ibrowse/README
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ Comments to : Chandrashekhar.Mullaparthi@t-mobile.co.uk

CONTRIBUTIONS & CHANGE HISTORY
==============================
20-04-2007 - Geoff Cant sent a patch to remove URL encoding for digits in
ibrowse_lib:url_encode/1.
ibrowse had a dependency on the inets application because the
ibrowse_http_client.erl invoked httpd_util:encode_base64/1. This
dependency is now removed and the encode_base64/1 has been
implemented in ibrowse_lib.erl

06-03-2007 - Eric Merritt sent a patch to support WebDAV requests.

12-01-2007 - Derek Upham sent in a bug fix. The reset_state function was not
Expand Down
12 changes: 12 additions & 0 deletions lib/ibrowse/doc/ibrowse_lib.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ <h2><a name="index">Function Index</a></h2>
<table width="100%" border="1"><tr><td valign="top"><a href="#dec2hex-2">dec2hex/2</a></td><td>dec2hex taken from gtk.erl in std dist
M = integer() -- number of hex digits required
N = integer() -- the number to represent as hex.</td></tr>
<tr><td valign="top"><a href="#decode_base64-1">decode_base64/1</a></td><td>Implements the base64 decoding algorithm.</td></tr>
<tr><td valign="top"><a href="#decode_rfc822_date-1">decode_rfc822_date/1</a></td><td/></tr>
<tr><td valign="top"><a href="#drv_ue-1">drv_ue/1</a></td><td/></tr>
<tr><td valign="top"><a href="#drv_ue-2">drv_ue/2</a></td><td/></tr>
<tr><td valign="top"><a href="#encode_base64-1">encode_base64/1</a></td><td>Implements the base64 encoding algorithm.</td></tr>
<tr><td valign="top"><a href="#status_code-1">status_code/1</a></td><td>Given a status code, returns an atom describing the status code.</td></tr>
<tr><td valign="top"><a href="#url_encode-1">url_encode/1</a></td><td>URL-encodes a string based on RFC 1738.</td></tr>
</table>
Expand All @@ -30,6 +32,11 @@ <h3><a name="dec2hex-2">dec2hex/2</a></h3>
M = integer() -- number of hex digits required
N = integer() -- the number to represent as hex</p>

<h3><a name="decode_base64-1">decode_base64/1</a></h3>
<p><tt>decode_base64(List::In) -&gt; Out | <a href="#type-exit">exit({error, invalid_input})</a></tt>
<ul><li><tt>In = string() | binary()</tt></li><li><tt>Out = string() | binary()</tt></li></ul></p>
<p>Implements the base64 decoding algorithm. The output data type matches in the input data type.</p>

<h3><a name="decode_rfc822_date-1">decode_rfc822_date/1</a></h3>
<tt>decode_rfc822_date(String) -&gt; term()
</tt>
Expand All @@ -42,6 +49,11 @@ <h3><a name="drv_ue-2">drv_ue/2</a></h3>
<tt>drv_ue(Str, Port) -&gt; term()
</tt>

<h3><a name="encode_base64-1">encode_base64/1</a></h3>
<p><tt>encode_base64(List::In) -&gt; Out</tt>
<ul><li><tt>In = string() | binary()</tt></li><li><tt>Out = string() | binary()</tt></li></ul></p>
<p>Implements the base64 encoding algorithm. The output data type matches in the input data type.</p>

<h3><a name="status_code-1">status_code/1</a></h3>
<p><tt>status_code(StatusCode::<a href="#type-status_code">status_code()</a>) -&gt; StatusDescription</tt>
<ul><li><tt><a name="type-status_code">status_code()</a> = string() | integer()</tt></li><li><tt>StatusDescription = atom()</tt></li></ul></p>
Expand Down
3 changes: 2 additions & 1 deletion lib/ibrowse/src/ibrowse_http_client.erl
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,8 @@ cons_headers(Headers) ->
cons_headers([], Acc) ->
encode_headers(Acc);
cons_headers([{basic_auth, {U,P}} | T], Acc) ->
cons_headers(T, [{"Authorization", ["Basic ", httpd_util:encode_base64(U++":"++P)]} | Acc]);
cons_headers(T, [{"Authorization",
["Basic ", ibrowse_lib:encode_base64(U++":"++P)]} | Acc]);
cons_headers([{cookie, Cookie} | T], Acc) ->
cons_headers(T, [{"Cookie", Cookie} | Acc]);
cons_headers([{content_length, L} | T], Acc) ->
Expand Down
95 changes: 89 additions & 6 deletions lib/ibrowse/src/ibrowse_lib.erl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
status_code/1,
dec2hex/2,
drv_ue/1,
drv_ue/2]).
drv_ue/2,
encode_base64/1,
decode_base64/1
]).

drv_ue(Str) ->
[{port, Port}| _] = ets:lookup(ibrowse_table, port),
Expand All @@ -36,6 +39,8 @@ drv_ue(Str, Port) ->
url_encode(Str) when list(Str) ->
url_encode_char(lists:reverse(Str), []).

url_encode_char([X | T], Acc) when X >= $0, X =< $9 ->
url_encode_char(T, [X | Acc]);
url_encode_char([X | T], Acc) when X >= $a, X =< $z ->
url_encode_char(T, [X | Acc]);
url_encode_char([X | T], Acc) when X >= $A, X =< $Z ->
Expand Down Expand Up @@ -93,8 +98,8 @@ month_int("Nov") -> 11;
month_int("Dec") -> 12.

%% @doc Given a status code, returns an atom describing the status code.
%% @spec status_code(StatusCode) -> StatusDescription
%% StatusCode = string() | integer()
%% @spec status_code(StatusCode::status_code()) -> StatusDescription
%% status_code() = string() | integer()
%% StatusDescription = atom()
status_code(100) -> continue;
status_code(101) -> switching_protocols;
Expand Down Expand Up @@ -147,11 +152,89 @@ status_code(X) when is_list(X) -> status_code(list_to_integer(X));
status_code(_) -> unknown_status_code.

%% @doc dec2hex taken from gtk.erl in std dist
%% @spec dec2hex(M, N) -> string()
%% M = integer() - number of hex digits required
%% N = integer() - the number to represent as hex
%% M = integer() -- number of hex digits required
%% N = integer() -- the number to represent as hex
%% @spec dec2hex(M::integer(), N::integer()) -> string()
dec2hex(M,N) -> dec2hex(M,N,[]).

dec2hex(0,_N,Ack) -> Ack;
dec2hex(M,N,Ack) -> dec2hex(M-1,N bsr 4,[d2h(N band 15)|Ack]).

%% @doc Implements the base64 encoding algorithm. The output data type matches in the input data type.
%% @spec encode_base64(In) -> Out
%% In = string() | binary()
%% Out = string() | binary()
encode_base64(List) when list(List) ->
encode_base64_1(list_to_binary(List));
encode_base64(Bin) when binary(Bin) ->
List = encode_base64_1(Bin),
list_to_binary(List).

encode_base64_1(<<A:6, B:6, C:6, D:6, Rest/binary>>) ->
[int_to_b64(A), int_to_b64(B),
int_to_b64(C), int_to_b64(D) | encode_base64_1(Rest)];
encode_base64_1(<<A:6, B:6, C:4>>) ->
[int_to_b64(A), int_to_b64(B), int_to_b64(C bsl 2), $=];
encode_base64_1(<<A:6, B:2>>) ->
[int_to_b64(A), int_to_b64(B bsl 4), $=, $=];
encode_base64_1(<<>>) ->
[].

%% @doc Implements the base64 decoding algorithm. The output data type matches in the input data type.
%% @spec decode_base64(In) -> Out | exit({error, invalid_input})
%% In = string() | binary()
%% Out = string() | binary()
decode_base64(List) when list(List) ->
decode_base64_1(List, []);
decode_base64(Bin) when binary(Bin) ->
List = decode_base64_1(binary_to_list(Bin), []),
list_to_binary(List).

decode_base64_1([H | T], Acc) when ((H == $\t) or
(H == 32) or
(H == $\r) or
(H == $\n)) ->
decode_base64_1(T, Acc);

decode_base64_1([$=, $=], Acc) ->
lists:reverse(Acc);
decode_base64_1([$=, _ | _], _Acc) ->
exit({error, invalid_input});

decode_base64_1([A1, B1, $=, $=], Acc) ->
A = b64_to_int(A1),
B = b64_to_int(B1),
Oct1 = (A bsl 2) bor (B bsr 4),
decode_base64_1([], [Oct1 | Acc]);
decode_base64_1([A1, B1, C1, $=], Acc) ->
A = b64_to_int(A1),
B = b64_to_int(B1),
C = b64_to_int(C1),
Oct1 = (A bsl 2) bor (B bsr 4),
Oct2 = ((B band 16#f) bsl 6) bor (C bsr 2),
decode_base64_1([], [Oct2, Oct1 | Acc]);
decode_base64_1([A1, B1, C1, D1 | T], Acc) ->
A = b64_to_int(A1),
B = b64_to_int(B1),
C = b64_to_int(C1),
D = b64_to_int(D1),
Oct1 = (A bsl 2) bor (B bsr 4),
Oct2 = ((B band 16#f) bsl 4) bor (C bsr 2),
Oct3 = ((C band 2#11) bsl 6) bor D,
decode_base64_1(T, [Oct3, Oct2, Oct1 | Acc]);
decode_base64_1([], Acc) ->
lists:reverse(Acc).

%% Taken from httpd_util.erl
int_to_b64(X) when X >= 0, X =< 25 -> X + $A;
int_to_b64(X) when X >= 26, X =< 51 -> X - 26 + $a;
int_to_b64(X) when X >= 52, X =< 61 -> X - 52 + $0;
int_to_b64(62) -> $+;
int_to_b64(63) -> $/.

%% Taken from httpd_util.erl
b64_to_int(X) when X >= $A, X =< $Z -> X - $A;
b64_to_int(X) when X >= $a, X =< $z -> X - $a + 26;
b64_to_int(X) when X >= $0, X =< $9 -> X - $0 + 52;
b64_to_int($+) -> 62;
b64_to_int($/) -> 63.
2 changes: 1 addition & 1 deletion lib/ibrowse/vsn.mk
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
IBROWSE_VSN = 1.2.5
IBROWSE_VSN = 1.2.6

0 comments on commit 898bf65

Please sign in to comment.