From 1bdc1185c67c3845969996ad1b3824be9b4afa8d Mon Sep 17 00:00:00 2001 From: Filipe David Manana Date: Sat, 10 Jul 2010 23:47:04 +0100 Subject: [PATCH] Use Erlang's OTP base64 module (available since R12B02) and avoid duplicated base64 encoding/decoding code in ibrowse_lib.erl and ibrowse_http_client.erl. OTP's base64 module is also more efficient (C implementation): 1> Data = crypto:rand_bytes(4096). <<205,174,13,169,97,159,110,161,71,43,226,153,42,101,243, 83,11,96,23,161,253,251,129,240,163,216,58,175,190,...>> 2> 2> timer:tc(ibrowse_lib, encode_base64, [Data]). {2920, <<"za4NqWGfbqFHK+KZKmXzUwtgF6H9+4Hwo9g6r77h2EF1/Xk1oKOIOmnAkgtv41LPXg37fp2dlr45C8qCA9/8zrcc9F5zr2JT0eVPTrh5aahl"...>>} 3> timer:tc(ibrowse_lib, encode_base64, [Data]). {1221, <<"za4NqWGfbqFHK+KZKmXzUwtgF6H9+4Hwo9g6r77h2EF1/Xk1oKOIOmnAkgtv41LPXg37fp2dlr45C8qCA9/8zrcc9F5zr2JT0eVPTrh5aahl"...>>} 4> timer:tc(ibrowse_lib, encode_base64, [Data]). {1436, <<"za4NqWGfbqFHK+KZKmXzUwtgF6H9+4Hwo9g6r77h2EF1/Xk1oKOIOmnAkgtv41LPXg37fp2dlr45C8qCA9/8zrcc9F5zr2JT0eVPTrh5aahl"...>>} 5> timer:tc(ibrowse_lib, encode_base64, [Data]). {1195, <<"za4NqWGfbqFHK+KZKmXzUwtgF6H9+4Hwo9g6r77h2EF1/Xk1oKOIOmnAkgtv41LPXg37fp2dlr45C8qCA9/8zrcc9F5zr2JT0eVPTrh5aahl"...>>} 6> 6> timer:tc(base64, encode, [Data]). {1846, <<"za4NqWGfbqFHK+KZKmXzUwtgF6H9+4Hwo9g6r77h2EF1/Xk1oKOIOmnAkgtv41LPXg37fp2dlr45C8qCA9/8zrcc9F5zr2JT0eVPTrh5aahl"...>>} 7> timer:tc(base64, encode, [Data]). {743, <<"za4NqWGfbqFHK+KZKmXzUwtgF6H9+4Hwo9g6r77h2EF1/Xk1oKOIOmnAkgtv41LPXg37fp2dlr45C8qCA9/8zrcc9F5zr2JT0eVPTrh5aahl"...>>} 8> timer:tc(base64, encode, [Data]). {737, <<"za4NqWGfbqFHK+KZKmXzUwtgF6H9+4Hwo9g6r77h2EF1/Xk1oKOIOmnAkgtv41LPXg37fp2dlr45C8qCA9/8zrcc9F5zr2JT0eVPTrh5aahl"...>>} 9> timer:tc(base64, encode, [Data]). {656, <<"za4NqWGfbqFHK+KZKmXzUwtgF6H9+4Hwo9g6r77h2EF1/Xk1oKOIOmnAkgtv41LPXg37fp2dlr45C8qCA9/8zrcc9F5zr2JT0eVPTrh5aahl"...>>} --- src/ibrowse_http_client.erl | 22 +----------- src/ibrowse_lib.erl | 69 +++---------------------------------- 2 files changed, 5 insertions(+), 86 deletions(-) diff --git a/src/ibrowse_http_client.erl b/src/ibrowse_http_client.erl index 1a1539c..1633e5b 100644 --- a/src/ibrowse_http_client.erl +++ b/src/ibrowse_http_client.erl @@ -765,27 +765,7 @@ add_proxy_auth_headers(#state{proxy_auth_digest = Auth_digest}, Headers) -> http_auth_digest([], []) -> []; http_auth_digest(Username, Password) -> - encode_base64(Username ++ [$: | Password]). - -encode_base64([]) -> - []; -encode_base64([A]) -> - [e(A bsr 2), e((A band 3) bsl 4), $=, $=]; -encode_base64([A,B]) -> - [e(A bsr 2), e(((A band 3) bsl 4) bor (B bsr 4)), e((B band 15) bsl 2), $=]; -encode_base64([A,B,C|Ls]) -> - encode_base64_do(A,B,C, Ls). -encode_base64_do(A,B,C, Rest) -> - BB = (A bsl 16) bor (B bsl 8) bor C, - [e(BB bsr 18), e((BB bsr 12) band 63), - e((BB bsr 6) band 63), e(BB band 63)|encode_base64(Rest)]. - -e(X) when X >= 0, X < 26 -> X+65; -e(X) when X>25, X<52 -> X+71; -e(X) when X>51, X<62 -> X-4; -e(62) -> $+; -e(63) -> $/; -e(X) -> exit({bad_encode_base64_token, X}). + ibrowse_lib:encode_base64(Username ++ [$: | Password]). make_request(Method, Headers, AbsPath, RelPath, Body, Options, #state{use_proxy = UseProxy}) -> diff --git a/src/ibrowse_lib.erl b/src/ibrowse_lib.erl index 9dc71cd..fbb9c34 100644 --- a/src/ibrowse_lib.erl +++ b/src/ibrowse_lib.erl @@ -177,79 +177,18 @@ dec2hex(M,N,Ack) -> dec2hex(M-1,N bsr 4,[d2h(N band 15)|Ack]). %% In = string() | binary() %% Out = string() | binary() encode_base64(List) when is_list(List) -> - encode_base64_1(list_to_binary(List)); + binary_to_list(base64:encode(List)); encode_base64(Bin) when is_binary(Bin) -> - List = encode_base64_1(Bin), - list_to_binary(List). - -encode_base64_1(<>) -> - [int_to_b64(A), int_to_b64(B), - int_to_b64(C), int_to_b64(D) | encode_base64_1(Rest)]; -encode_base64_1(<>) -> - [int_to_b64(A), int_to_b64(B), int_to_b64(C bsl 2), $=]; -encode_base64_1(<>) -> - [int_to_b64(A), int_to_b64(B bsl 4), $=, $=]; -encode_base64_1(<<>>) -> - []. + base64:encode(Bin). %% @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 is_list(List) -> - decode_base64_1(List, []); + binary_to_list(base64:decode(List)); decode_base64(Bin) when is_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. + base64:decode(Bin). get_value(Tag, TVL, DefVal) -> case lists:keysearch(Tag, 1, TVL) of