From 52c9cec5c6715139cf06a99be9779e2f677bceae Mon Sep 17 00:00:00 2001 From: Adam Kocoloski Date: Fri, 5 Mar 2010 15:27:40 +0000 Subject: use OTP base64 lib. Patch by Filipe Manana. Closes COUCHDB-681 git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@919449 13f79535-47bb-0310-9956-ffa450edef68 --- src/couchdb/couch_doc.erl | 38 +++++++---- src/couchdb/couch_httpd_auth.erl | 2 +- src/couchdb/couch_httpd_external.erl | 2 +- src/couchdb/couch_util.erl | 122 ++++------------------------------- 4 files changed, 39 insertions(+), 125 deletions(-) (limited to 'src/couchdb') diff --git a/src/couchdb/couch_doc.erl b/src/couchdb/couch_doc.erl index efb0f6a5..f5c47bf7 100644 --- a/src/couchdb/couch_doc.erl +++ b/src/couchdb/couch_doc.erl @@ -98,12 +98,11 @@ to_json_attachments(Atts, RevPosIncludeAfter, DataToFollow) -> true -> AttData = case Att#att.comp of true -> - zlib:gunzip(att_to_iolist(Att)); + zlib:gunzip(att_to_bin(Att)); _ -> - att_to_iolist(Att) + att_to_bin(Att) end, - [{<<"data">>, - couch_util:encodeBase64(AttData)}] + [{<<"data">>, base64:encode(AttData)}] end; true -> [{<<"length">>, DiskLen}, {<<"stub">>, true}] @@ -206,7 +205,7 @@ transfer_fields([{<<"_attachments">>, {JsonBins}} | Rest], Doc) -> att_len=Len, disk_len=Len, revpos=RevPos}; _ -> Value = proplists:get_value(<<"data">>, BinProps), - Bin = couch_util:decodeBase64(Value), + Bin = base64:decode(Value), LenBin = size(Bin), #att{name=Name, data=Bin, type=Type, att_len=LenBin, disk_len=LenBin, revpos=RevPos} @@ -291,16 +290,27 @@ att_foldl(#att{data=DataFun,att_len=Len}, Fun, Acc) when is_function(DataFun) -> att_foldl_unzip(#att{data={Fd,Sp},md5=Md5}, Fun, Acc) -> couch_stream:foldl_unzip(Fd, Sp, Md5, Fun, Acc). -att_to_iolist(#att{data=Bin}) when is_binary(Bin) -> +att_to_bin(#att{data=Bin}) when is_binary(Bin) -> Bin; -att_to_iolist(#att{data=Iolist}) when is_list(Iolist) -> - Iolist; -att_to_iolist(#att{data={_Fd,_Sp}}=Att) -> - lists:reverse(att_foldl(Att, - fun(Bin,Acc) -> [Bin|Acc] end, [])); -att_to_iolist(#att{data=DataFun, att_len=Len}) when is_function(DataFun)-> - lists:reverse(fold_streamed_data(DataFun, Len, - fun(Data, Acc) -> [Data | Acc] end, [])). +att_to_bin(#att{data=Iolist}) when is_list(Iolist) -> + iolist_to_binary(Iolist); +att_to_bin(#att{data={_Fd,_Sp}}=Att) -> + iolist_to_binary( + lists:reverse(att_foldl( + Att, + fun(Bin,Acc) -> [Bin|Acc] end, + [] + )) + ); +att_to_bin(#att{data=DataFun, att_len=Len}) when is_function(DataFun)-> + iolist_to_binary( + lists:reverse(fold_streamed_data( + DataFun, + Len, + fun(Data, Acc) -> [Data | Acc] end, + [] + )) + ). get_validate_doc_fun(#doc{body={Props}}=DDoc) -> case proplists:get_value(<<"validate_doc_update">>, Props) of diff --git a/src/couchdb/couch_httpd_auth.erl b/src/couchdb/couch_httpd_auth.erl index a1e8f11e..c4683af4 100644 --- a/src/couchdb/couch_httpd_auth.erl +++ b/src/couchdb/couch_httpd_auth.erl @@ -48,7 +48,7 @@ basic_name_pw(Req) -> AuthorizationHeader = header_value(Req, "Authorization"), case AuthorizationHeader of "Basic " ++ Base64Value -> - case string:tokens(?b2l(couch_util:decodeBase64(Base64Value)),":") of + case string:tokens(?b2l(base64:decode(Base64Value)),":") of ["_", "_"] -> % special name and pass to be logged out nil; diff --git a/src/couchdb/couch_httpd_external.erl b/src/couchdb/couch_httpd_external.erl index efbe87b8..fb099350 100644 --- a/src/couchdb/couch_httpd_external.erl +++ b/src/couchdb/couch_httpd_external.erl @@ -124,7 +124,7 @@ parse_external_response({Response}) -> Args#extern_resp_args{data=Value, ctype="text/html; charset=utf-8"}; {<<"base64">>, Value} -> Args#extern_resp_args{ - data=couch_util:decodeBase64(Value), + data=base64:decode(Value), ctype="application/binary" }; {<<"headers">>, {Headers}} -> diff --git a/src/couchdb/couch_util.erl b/src/couchdb/couch_util.erl index ca36a6db..b7e237c1 100644 --- a/src/couchdb/couch_util.erl +++ b/src/couchdb/couch_util.erl @@ -16,8 +16,8 @@ -export([should_flush/0, should_flush/1, to_existing_atom/1]). -export([rand32/0, implode/2, collate/2, collate/3]). -export([abs_pathname/1,abs_pathname/2, trim/1, ascii_lower/1]). --export([encodeBase64/1, decodeBase64/1, encodeBase64Url/1, decodeBase64Url/1, - to_hex/1,parse_term/1, dict_find/3]). +-export([encodeBase64Url/1, decodeBase64Url/1]). +-export([to_hex/1, parse_term/1, dict_find/3]). -export([file_read_size/1, get_nested_json_value/2, json_user_ctx/1]). -export([to_binary/1, to_integer/1, to_list/1, url_encode/1]). -export([json_encode/1, json_decode/1]). @@ -232,114 +232,18 @@ should_flush(MemThreshHold) -> ProcMem2+BinMem2 > MemThreshHold; true -> false end. +encodeBase64Url(Url) -> + Url1 = iolist_to_binary(re:replace(base64:encode(Url), "=+$", "")), + Url2 = iolist_to_binary(re:replace(Url1, "/", "_", [global])), + iolist_to_binary(re:replace(Url2, "\\+", "-", [global])). -%%% Purpose : Base 64 encoding and decoding. -%%% Copied from ssl_base_64 to avoid using the -%%% erlang ssl library - --define(st(X,A), ((X-A+256) div 256)). - -%% A PEM encoding consists of characters A-Z, a-z, 0-9, +, / and -%% =. Each character encodes a 6 bits value from 0 to 63 (A = 0, / = -%% 63); = is a padding character. -%% - -%% -%% encode64(Bytes|Binary) -> binary -%% -%% Take 3 bytes a time (3 x 8 = 24 bits), and make 4 characters out of -%% them (4 x 6 = 24 bits). -%% -encodeBase64(Bs) when is_list(Bs) -> - encodeBase64(iolist_to_binary(Bs), <<>>); -encodeBase64(Bs) -> - encodeBase64(Bs, <<>>). - -encodeBase64(<>, Acc) -> - <> = B, - encodeBase64(Bs, <>); -encodeBase64(<>, Acc) -> - <> = <>, - <>; -encodeBase64(<>, Acc) -> - <> = <>, - <>; -encodeBase64(<<>>, Acc) -> - Acc. - -encodeBase64Url(Bs) when is_list(Bs) -> - encodeBase64Url(list_to_binary(Bs), <<>>); -encodeBase64Url(Bs) -> - encodeBase64Url(Bs, <<>>). - -encodeBase64Url(<>, Acc) -> - <> = B, - encodeBase64Url(Bs, <>); -encodeBase64Url(<>, Acc) -> - <> = <>, - <>; -encodeBase64Url(<>, Acc) -> - <> = <>, - <>; -encodeBase64Url(<<>>, Acc) -> - Acc. - -%% -%% decodeBase64(BinaryChars) -> Binary -%% -decodeBase64(Cs) when is_list(Cs) -> - decodeBase64(list_to_binary(Cs)); -decodeBase64(Cs) -> - decode1(Cs, <<>>). - -decode1(<>, Acc) -> - <> = <<(dec(C1)):6, (dec(C2)):6, 0:12>>, - <>; -decode1(<>, Acc) -> - <> = <<(dec(C1)):6, (dec(C2)):6, (dec(C3)):6, (dec(0)):6>>, - <>; -decode1(<>, Acc) -> - Bin = <>, - decode1(Cs, Bin); -decode1(<<>>, Acc) -> - Acc. - -decodeBase64Url(Cs) when is_list(Cs) -> - decodeBase64Url(list_to_binary(Cs)); -decodeBase64Url(Cs) -> - decode1Url(Cs, <<>>). - -decode1Url(<>, Acc) -> - <> = <<(decUrl(C1)):6, (decUrl(C2)):6, 0:12>>, - <>; -decode1Url(<>, Acc) -> - <> = <<(decUrl(C1)):6, (decUrl(C2)):6, (decUrl(C3)):6, (decUrl(0)):6>>, - <>; -decode1Url(<>, Acc) -> - Bin = <>, - decode1Url(Cs, Bin); -decode1Url(<<>>, Acc) -> - Acc. - -%% enc/1 and dec/1 -%% -%% Mapping: 0-25 -> A-Z, 26-51 -> a-z, 52-61 -> 0-9, 62 -> +, 63 -> / -%% -enc(C) -> - 65 + C + 6*?st(C,26) - 75*?st(C,52) -15*?st(C,62) + 3*?st(C,63). - -dec(C) -> - 62*?st(C,43) + ?st(C,47) + (C-59)*?st(C,48) - 69*?st(C,65) - 6*?st(C,97). - -%% encUrl/1 and decUrl/1 -%% -%% Mapping: 0-25 -> A-Z, 26-51 -> a-z, 52-61 -> 0-9, 62 -> -, 63 -> _ -%% -encUrl(C) -> - 65 + C + 6*?st(C,26) - 75*?st(C,52) -13*?st(C,62) + 49*?st(C,63). - -decUrl(C) -> - 62*?st(C,45) + (C-58)*?st(C,48) - 69*?st(C,65) + 33*?st(C,95) - 39*?st(C,97). +decodeBase64Url(Url64) -> + Url1 = re:replace(iolist_to_binary(Url64), "-", "+", [global]), + Url2 = iolist_to_binary( + re:replace(iolist_to_binary(Url1), "_", "/", [global]) + ), + Padding = ?l2b(lists:duplicate((4 - size(Url2) rem 4) rem 4, $=)), + base64:decode(<>). dict_find(Key, Dict, DefaultValue) -> case dict:find(Key, Dict) of -- cgit v1.2.3