forked from erlyaws/yaws
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
revert "remove support for SOAP DIME attachments"
This reverts commit 65bf36a.
- Loading branch information
Showing
5 changed files
with
278 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,6 +53,7 @@ MODULES=yaws \ | |
yaws_vdir \ | ||
yaws_multipart \ | ||
yaws_shaper \ | ||
yaws_dime \ | ||
$(BITSMODS) | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
%%%------------------------------------------------------------------- | ||
%%% File : dime.erl | ||
%%% @author Anders Nygren <anders.nygren@gmail.com> | ||
%%% @doc Encoding and decoding of DIME messages. | ||
%%% The Direct Internet Message Encapsulation (DIME) specification | ||
%%% defines a mechanism for packaging binary data with SOAP messages. | ||
%%% http://bgp.potaroo.net/ietf/all-ids/draft-nielsen-dime-02.txt | ||
%%% Layout of a DIME encoded message is like this | ||
%%%<pre> | ||
%%% 0 1 2 3 | ||
%%% 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | ||
%%% +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
%%% | |M|M|C| | | | | ||
%%% | VERSION |B|E|F| TYPE_T| RESRVD| OPTIONS_LENGTH | | ||
%%% +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
%%% | ID_LENGTH | TYPE_LENGTH | | ||
%%% +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
%%% | DATA_LENGTH | | ||
%%% +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
%%% | / | ||
%%% / OPTIONS + PADDING / | ||
%%% / | | ||
%%% +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
%%% | / | ||
%%% / ID + PADDING / | ||
%%% / | | ||
%%% +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
%%% | / | ||
%%% / TYPE + PADDING / | ||
%%% / | | ||
%%% +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
%%% | / | ||
%%% / DATA + PADDING / | ||
%%% / | | ||
%%% +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
%%%<pre> | ||
%%% @end | ||
%%% | ||
%%% Created : 7 Apr 2008 by Anders Nygren <> | ||
%%%------------------------------------------------------------------- | ||
-module(yaws_dime). | ||
|
||
%% API | ||
-export([encode/2, | ||
decode/1, | ||
pad_len/1]). | ||
|
||
|
||
-include_lib("kernel/include/file.hrl"). | ||
|
||
-define(VERSION1, 1). | ||
-define(T_UNCHANGED, 0). | ||
-define(T_MEDIA_TYPE, 1). | ||
-define(T_ABS_URI, 2). | ||
-define(T_UNKNOWN, 3). | ||
-define(T_NONE, 4). | ||
-define(SOAP_URI, "http://schemas.xmlsoap.org/soap/envelope"). | ||
%%==================================================================== | ||
%% API | ||
%%==================================================================== | ||
%%-------------------------------------------------------------------- | ||
%% @spec (Req, Attachments) ->binary() | ||
%% Description: | ||
%%-------------------------------------------------------------------- | ||
encode(Req, []) -> | ||
encode_part(1, 1, 0, ?T_ABS_URI, <<"">>, <<"">>, <<?SOAP_URI>>, Req); | ||
encode(Req, As) -> | ||
list_to_binary([encode_part(1, 0, 0, ?T_ABS_URI, <<"">>, <<"">>, <<?SOAP_URI>>, Req)| | ||
encode_attachments(As)]). | ||
|
||
encode_attachments([{attachment, Id, Type, File}]) -> | ||
[encode_part(0, 1, 0, ?T_ABS_URI, <<"">>, list_to_binary(Id), list_to_binary(Type), File)]; | ||
encode_attachments([{attachment, Id, Type, File} | As]) -> | ||
[encode_part(0, 0, 0, ?T_ABS_URI, <<"">>, list_to_binary(Id), list_to_binary(Type), File)| | ||
encode_attachments(As)]. | ||
|
||
encode_part(MB, ME, CF, TypeT, Opts, ID, Type, Data) -> | ||
Opts_len = size_of(Opts), | ||
Opts_pad = pad_len(Opts_len), | ||
Id_len = size_of(ID), | ||
Id_pad = pad_len(Id_len), | ||
Type_len = size_of(Type), | ||
Type_pad = pad_len(Type_len), | ||
Data_len = size_of(Data), | ||
Data_pad = pad_len(Data_len), | ||
Data1 = get_data(Data), | ||
<<?VERSION1:5, MB:1, ME:1, CF:1, TypeT:4, 0:4, | ||
Opts_len:1/big-integer-unit:16, | ||
Id_len:1/big-integer-unit:16, | ||
Type_len:1/big-integer-unit:16, | ||
Data_len:1/big-integer-unit:32, | ||
Opts:Opts_len/binary-unit:8, 0:Opts_pad/integer-unit:8, | ||
ID:Id_len/binary-unit:8, 0:Id_pad/integer-unit:8, | ||
Type:Type_len/binary-unit:8, 0:Type_pad/integer-unit:8, | ||
Data1:Data_len/binary-unit:8, 0:Data_pad/integer-unit:8>>. | ||
|
||
pad_len(Len) -> | ||
case Len rem 4 of | ||
0 -> | ||
0; | ||
N -> | ||
4-N | ||
end. | ||
|
||
size_of(X) when is_list(X) -> | ||
length(X); | ||
size_of(X) when is_binary(X)-> | ||
size(X); | ||
size_of({file, File}) -> | ||
{ok,R} = file:read_file_info(File), | ||
R#file_info.size. | ||
|
||
get_data({file, File}) -> | ||
{ok, Data} = file:read_file(File), | ||
Data; | ||
get_data(Data) when is_list(Data) -> | ||
list_to_binary(Data); | ||
|
||
get_data(Data) -> | ||
Data. | ||
%%-------------------------------------------------------------------- | ||
%% @spec (Msg::binary()) -> | ||
%% @doc Decode a DIME encoded message. | ||
%%-------------------------------------------------------------------- | ||
decode(Msg) -> | ||
decode_recs(Msg, [], []). | ||
|
||
decode_recs(<<>>, Acc, _Chunks) -> | ||
Acc; | ||
decode_recs(Msg, Acc, Chunks) -> | ||
case {decode_rec(Msg), Chunks} of | ||
%% A normal record | ||
{{_ME=0, _CF=0, Opts, ID, Type, Chunk, More}, []} -> | ||
decode_recs(More, [{Opts, ID, Type, Chunk}|Acc], []); | ||
|
||
%% The last chunk of a block, but not the last record | ||
{{_ME=0, _CF=0, Opts, ID, Type, Chunk, More}, Chunks} -> | ||
Cs = lists:reverse([{Opts, ID, Type, Chunk}|Chunks]), | ||
%% Only the first chunk has values for Opts, Id and Type | ||
{ROpts, RID, RType, _Chunk} = hd(Cs), | ||
Block = list_to_binary([Ch || {_Opts, _ID, _Type, Ch} <- Cs]), | ||
error_logger:info_report([?MODULE, decode_rec, merging, | ||
{id, ID},{type, Type}, | ||
{chunks, length(Cs)}]), | ||
decode_recs(More, [{ROpts, RID, RType, Block}|Acc], []); | ||
|
||
%% Last record, but not chunked | ||
{{_ME=1, _CF=0, Opts, ID, Type, Data, _More}, []} -> | ||
lists:reverse([{Opts, ID, Type, Data}|Acc]); | ||
|
||
%% Last record, and last chunk of block | ||
{{_ME=1, _CF=0, Opts, ID, Type, Chunk, _More}, Chunks} -> | ||
Cs = lists:reverse([{Opts, ID, Type, Chunk}|Chunks]), | ||
{ROpts, RID, RType, _Chunk} = hd(Cs), | ||
Block = list_to_binary([Ch || {_Opts, _ID, _Type, Ch} <- Cs]), | ||
error_logger:info_report([?MODULE, decode_rec, merging, | ||
{id, ID},{type, Type}, | ||
{chunks, length(Cs)}]), | ||
lists:reverse([{ROpts, RID, RType, Block}|Acc]); | ||
|
||
%% First or intermediate chunk, but not the last | ||
{{_ME=0, _CF=1, Opts, ID, Type, Data, More}, Chunks} -> | ||
decode_recs(More, Acc, [{Opts, ID, Type, Data}|Chunks]); | ||
|
||
%% Something wrong, ME=1 and CF=1 | ||
ErrorResult -> | ||
error_logger:error_report([?MODULE, decode_recs, | ||
{result, ErrorResult}]) | ||
end. | ||
|
||
decode_rec(<<?VERSION1:5, _MB:1, ME:1, CF:1, _Type_T:4, _Res:4, | ||
Opt_Len:1/big-integer-unit:16, | ||
ID_Len:1/big-integer-unit:16, | ||
Type_Len:1/big-integer-unit:16, | ||
Data_Len:1/big-integer-unit:32, | ||
Rest/binary>>=Block) -> | ||
error_logger:info_report([?MODULE, decode_rec, | ||
{version,1}, | ||
{mb,_MB},{me,ME},{cf,CF},{type_t,_Type_T}, | ||
{res,_Res},{opt_len,Opt_Len},{id_len,ID_Len}, | ||
{type_len,Type_Len},{date_len,Data_Len}, | ||
{total_rec_size,byte_size(Block)}]), | ||
Opt_pad = pad_len(Opt_Len), | ||
Id_pad = pad_len(ID_Len), | ||
Type_pad = pad_len(Type_Len), | ||
Data_pad = pad_len(Data_Len), | ||
Header = Opt_Len+Opt_pad+ID_Len+Id_pad+Type_Len+Type_pad, | ||
DataTot = Data_Len+Data_pad, | ||
case byte_size(Rest) of | ||
N when N >= Header+DataTot -> | ||
<<Opts:Opt_Len/binary-unit:8, _:Opt_pad/binary-unit:8, | ||
ID:ID_Len/binary-unit:8, _:Id_pad/binary-unit:8, | ||
Type:Type_Len/binary-unit:8, _:Type_pad/binary-unit:8, | ||
Data:Data_Len/binary-unit:8, _:Data_pad/binary-unit:8, | ||
More/binary >> = Rest, | ||
{ME, CF, Opts, ID, Type, Data, More}; | ||
N when N > Header-> | ||
<<Opts:Opt_Len/binary-unit:8, _:Opt_pad/binary-unit:8, | ||
ID:ID_Len/binary-unit:8, _:Id_pad/binary-unit:8, | ||
Type:Type_Len/binary-unit:8, _:Type_pad/binary-unit:8, | ||
Data/binary>> = Rest, | ||
error_logger:error_report([?MODULE, decode_rec, short_record, | ||
{need, Header+DataTot}, | ||
{has, N}]), | ||
{ME, CF, Opts, ID, Type, Data, <<>>}; | ||
N -> | ||
error_logger:error_report([?MODULE, decode_rec, short_record, | ||
{need, Header+DataTot}, | ||
{has, N}]), | ||
{error, not_enough_data} | ||
end; | ||
|
||
decode_rec(Bin) -> | ||
error_logger:error_report([?MODULE, decode_rec, short_record, | ||
no_header, | ||
{has, byte_size(Bin)}]), | ||
{error, no_header}. | ||
|
||
|
||
%%==================================================================== | ||
%% Internal functions | ||
%%==================================================================== |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters