mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-26 17:38:45 +01:00
Rewrite mod_http_upload to use XML generator
This commit is contained in:
parent
d2d3b961eb
commit
792e6a7c1c
@ -91,6 +91,12 @@
|
||||
since :: any()}).
|
||||
-type muc_history() :: #muc_history{}.
|
||||
|
||||
-record(thumbnail, {uri :: binary(),
|
||||
'media-type' = <<>> :: binary(),
|
||||
width :: non_neg_integer(),
|
||||
height :: non_neg_integer()}).
|
||||
-type thumbnail() :: #thumbnail{}.
|
||||
|
||||
-record(pubsub_affiliation, {node :: binary(),
|
||||
type :: 'member' | 'none' | 'outcast' | 'owner' | 'publish-only' | 'publisher'}).
|
||||
-type pubsub_affiliation() :: #pubsub_affiliation{}.
|
||||
@ -387,6 +393,11 @@
|
||||
items = [] :: [#pubsub_item{}]}).
|
||||
-type pubsub_retract() :: #pubsub_retract{}.
|
||||
|
||||
-record(upload_slot, {get :: binary(),
|
||||
put :: binary(),
|
||||
xmlns :: binary()}).
|
||||
-type upload_slot() :: #upload_slot{}.
|
||||
|
||||
-record(mix_participant, {jid :: any(),
|
||||
nick :: binary()}).
|
||||
-type mix_participant() :: #mix_participant{}.
|
||||
@ -405,6 +416,12 @@
|
||||
-record(block_list, {items = [] :: [any()]}).
|
||||
-type block_list() :: #block_list{}.
|
||||
|
||||
-record(upload_request, {filename :: binary(),
|
||||
size :: non_neg_integer(),
|
||||
'content-type' = <<>> :: binary(),
|
||||
xmlns :: binary()}).
|
||||
-type upload_request() :: #upload_request{}.
|
||||
|
||||
-record(xdata_option, {label :: binary(),
|
||||
value :: binary()}).
|
||||
-type xdata_option() :: #xdata_option{}.
|
||||
@ -837,15 +854,16 @@
|
||||
version() |
|
||||
pubsub_affiliation() |
|
||||
mam_fin() |
|
||||
sm_a() |
|
||||
bob_data() |
|
||||
media() |
|
||||
sm_a() |
|
||||
carbons_sent() |
|
||||
mam_archived() |
|
||||
p1_rebind() |
|
||||
sasl_abort() |
|
||||
carbons_received() |
|
||||
pubsub_retract() |
|
||||
upload_slot() |
|
||||
mix_participant() |
|
||||
compressed() |
|
||||
block_list() |
|
||||
@ -887,6 +905,7 @@
|
||||
feature_csi() |
|
||||
privacy_query() |
|
||||
delay() |
|
||||
thumbnail() |
|
||||
vcard_tel() |
|
||||
vcard_geo() |
|
||||
vcard_photo() |
|
||||
@ -932,6 +951,7 @@
|
||||
mam_result() |
|
||||
rsm_first() |
|
||||
stat() |
|
||||
upload_request() |
|
||||
xdata_field() |
|
||||
adhoc_command() |
|
||||
sm_failed() |
|
||||
|
@ -92,7 +92,7 @@
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("ejabberd_http.hrl").
|
||||
-include("jlib.hrl").
|
||||
-include("xmpp.hrl").
|
||||
-include("logger.hrl").
|
||||
|
||||
-record(state,
|
||||
@ -360,9 +360,8 @@ handle_cast(Request, State) ->
|
||||
|
||||
-spec handle_info(timeout | _, state()) -> {noreply, state()}.
|
||||
|
||||
handle_info({route, From, To, #xmlel{name = <<"iq">>} = Stanza}, State) ->
|
||||
Request = jlib:iq_query_info(Stanza),
|
||||
{Reply, NewState} = case process_iq(From, Request, State) of
|
||||
handle_info({route, From, To, #iq{} = IQ}, State) ->
|
||||
{Reply, NewState} = case process_iq(From, IQ, State) of
|
||||
R when is_record(R, iq) ->
|
||||
{R, State};
|
||||
{R, S} ->
|
||||
@ -371,7 +370,7 @@ handle_info({route, From, To, #xmlel{name = <<"iq">>} = Stanza}, State) ->
|
||||
{none, State}
|
||||
end,
|
||||
if Reply /= none ->
|
||||
ejabberd_router:route(To, From, jlib:iq_to_xml(Reply));
|
||||
ejabberd_router:route(To, From, Reply);
|
||||
true ->
|
||||
ok
|
||||
end,
|
||||
@ -531,89 +530,48 @@ expand_host(Subject, Host) ->
|
||||
|
||||
%% XMPP request handling.
|
||||
|
||||
-spec process_iq(jid(), iq_request() | reply | invalid, state())
|
||||
-> {iq_reply(), state()} | iq_reply() | not_request.
|
||||
-spec process_iq(jid(), iq(), state()) -> {iq(), state()} | iq() | not_request.
|
||||
|
||||
process_iq(_From,
|
||||
#iq{type = get, xmlns = ?NS_DISCO_INFO, lang = Lang} = IQ,
|
||||
#iq{type = get, lang = Lang, sub_els = [#disco_info{}]} = IQ,
|
||||
#state{server_host = ServerHost, name = Name}) ->
|
||||
AddInfo = ejabberd_hooks:run_fold(disco_info, ServerHost, [],
|
||||
[ServerHost, ?MODULE, <<"">>, <<"">>]),
|
||||
IQ#iq{type = result,
|
||||
sub_el = [#xmlel{name = <<"query">>,
|
||||
attrs = [{<<"xmlns">>, ?NS_DISCO_INFO}],
|
||||
children = iq_disco_info(ServerHost, Lang, Name)
|
||||
++ AddInfo}]};
|
||||
process_iq(From,
|
||||
#iq{type = get, xmlns = XMLNS, lang = Lang, sub_el = SubEl} = IQ,
|
||||
#state{server_host = ServerHost, access = Access} = State)
|
||||
when XMLNS == ?NS_HTTP_UPLOAD;
|
||||
XMLNS == ?NS_HTTP_UPLOAD_OLD ->
|
||||
xmpp:make_iq_result(IQ, iq_disco_info(ServerHost, Lang, Name, AddInfo));
|
||||
process_iq(From, #iq{type = get, lang = Lang,
|
||||
sub_els = [#upload_request{filename = File,
|
||||
size = Size,
|
||||
'content-type' = CType,
|
||||
xmlns = XMLNS}]} = IQ,
|
||||
#state{server_host = ServerHost, access = Access} = State) ->
|
||||
case acl:match_rule(ServerHost, Access, From) of
|
||||
allow ->
|
||||
case parse_request(SubEl, Lang) of
|
||||
{ok, File, Size, ContentType} ->
|
||||
case create_slot(State, From, File, Size, ContentType,
|
||||
Lang) of
|
||||
{ok, Slot} ->
|
||||
{ok, Timer} = timer:send_after(?SLOT_TIMEOUT,
|
||||
{slot_timed_out,
|
||||
Slot}),
|
||||
NewState = add_slot(Slot, Size, Timer, State),
|
||||
SlotEl = slot_el(Slot, State, XMLNS),
|
||||
{IQ#iq{type = result, sub_el = [SlotEl]}, NewState};
|
||||
{ok, PutURL, GetURL} ->
|
||||
SlotEl = slot_el(PutURL, GetURL, XMLNS),
|
||||
IQ#iq{type = result, sub_el = [SlotEl]};
|
||||
{error, Error} ->
|
||||
IQ#iq{type = error, sub_el = [SubEl, Error]}
|
||||
end;
|
||||
ContentType = yield_content_type(CType),
|
||||
case create_slot(State, From, File, Size, ContentType, Lang) of
|
||||
{ok, Slot} ->
|
||||
{ok, Timer} = timer:send_after(?SLOT_TIMEOUT,
|
||||
{slot_timed_out,
|
||||
Slot}),
|
||||
NewState = add_slot(Slot, Size, Timer, State),
|
||||
Slot = mk_slot(Slot, State, XMLNS),
|
||||
{xmpp:make_iq_result(IQ, Slot), NewState};
|
||||
{ok, PutURL, GetURL} ->
|
||||
Slot = mk_slot(PutURL, GetURL, XMLNS),
|
||||
xmpp:make_iq_result(IQ, Slot);
|
||||
{error, Error} ->
|
||||
?DEBUG("Cannot parse request from ~s",
|
||||
[jid:to_string(From)]),
|
||||
IQ#iq{type = error, sub_el = [SubEl, Error]}
|
||||
xmpp:make_error(IQ, Error)
|
||||
end;
|
||||
deny ->
|
||||
?DEBUG("Denying HTTP upload slot request from ~s",
|
||||
[jid:to_string(From)]),
|
||||
Txt = <<"Denied by ACL">>,
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERRT_FORBIDDEN(Lang, Txt)]}
|
||||
xmpp:make_error(IQ, xmpp:err_forbidden(Txt, Lang))
|
||||
end;
|
||||
process_iq(_From, #iq{sub_el = SubEl} = IQ, _State) ->
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
|
||||
process_iq(_From, reply, _State) ->
|
||||
not_request;
|
||||
process_iq(_From, invalid, _State) ->
|
||||
process_iq(_From, #iq{type = T} = IQ, _State) when T == get; T == set ->
|
||||
xmpp:make_error(IQ, xmpp:err_not_allowed());
|
||||
process_iq(_From, #iq{}, _State) ->
|
||||
not_request.
|
||||
|
||||
-spec parse_request(xmlel(), binary())
|
||||
-> {ok, binary(), pos_integer(), binary()} | {error, xmlel()}.
|
||||
|
||||
parse_request(#xmlel{name = <<"request">>, attrs = Attrs} = Request, Lang) ->
|
||||
case fxml:get_attr(<<"xmlns">>, Attrs) of
|
||||
{value, XMLNS} when XMLNS == ?NS_HTTP_UPLOAD;
|
||||
XMLNS == ?NS_HTTP_UPLOAD_OLD ->
|
||||
case {fxml:get_subtag_cdata(Request, <<"filename">>),
|
||||
fxml:get_subtag_cdata(Request, <<"size">>),
|
||||
fxml:get_subtag_cdata(Request, <<"content-type">>)} of
|
||||
{File, SizeStr, ContentType} when byte_size(File) > 0 ->
|
||||
case catch jlib:binary_to_integer(SizeStr) of
|
||||
Size when is_integer(Size), Size > 0 ->
|
||||
{ok, File, Size, yield_content_type(ContentType)};
|
||||
_ ->
|
||||
Text = <<"Please specify file size.">>,
|
||||
{error, ?ERRT_BAD_REQUEST(Lang, Text)}
|
||||
end;
|
||||
_ ->
|
||||
Text = <<"Please specify file name.">>,
|
||||
{error, ?ERRT_BAD_REQUEST(Lang, Text)}
|
||||
end;
|
||||
_ ->
|
||||
Text = <<"No or invalid XML namespace">>,
|
||||
{error, ?ERRT_BAD_REQUEST(Lang, Text)}
|
||||
end;
|
||||
parse_request(_El, _Lang) -> {error, ?ERR_BAD_REQUEST}.
|
||||
|
||||
-spec create_slot(state(), jid(), binary(), pos_integer(), binary(), binary())
|
||||
-> {ok, slot()} | {ok, binary(), binary()} | {error, xmlel()}.
|
||||
|
||||
@ -624,7 +582,7 @@ create_slot(#state{service_url = undefined, max_size = MaxSize},
|
||||
" Bytes.">>,
|
||||
?INFO_MSG("Rejecting file ~s from ~s (too large: ~B bytes)",
|
||||
[File, jid:to_string(JID), Size]),
|
||||
{error, ?ERRT_NOT_ACCEPTABLE(Lang, Text)};
|
||||
{error, xmpp:err_not_acceptable(Text, Lang)};
|
||||
create_slot(#state{service_url = undefined,
|
||||
jid_in_url = JIDinURL,
|
||||
secret_length = SecretLength,
|
||||
@ -642,8 +600,8 @@ create_slot(#state{service_url = undefined,
|
||||
[jid:to_string(JID), File]),
|
||||
{ok, [UserStr, RandStr, FileStr]};
|
||||
deny ->
|
||||
{error, ?ERR_SERVICE_UNAVAILABLE};
|
||||
#xmlel{} = Error ->
|
||||
{error, xmpp:err_service_unavailable()};
|
||||
#error{} = Error ->
|
||||
{error, Error}
|
||||
end;
|
||||
create_slot(#state{service_url = ServiceURL},
|
||||
@ -669,28 +627,28 @@ create_slot(#state{service_url = ServiceURL},
|
||||
?ERROR_MSG("Can't parse data received for ~s from <~s>: ~p",
|
||||
[jid:to_string(JID), ServiceURL, Lines]),
|
||||
Txt = <<"Failed to parse HTTP response">>,
|
||||
{error, ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)}
|
||||
{error, xmpp:err_service_unavailable(Txt, Lang)}
|
||||
end;
|
||||
{ok, {402, _Body}} ->
|
||||
?INFO_MSG("Got status code 402 for ~s from <~s>",
|
||||
[jid:to_string(JID), ServiceURL]),
|
||||
{error, ?ERR_RESOURCE_CONSTRAINT};
|
||||
{error, xmpp:err_resource_constraint()};
|
||||
{ok, {403, _Body}} ->
|
||||
?INFO_MSG("Got status code 403 for ~s from <~s>",
|
||||
[jid:to_string(JID), ServiceURL]),
|
||||
{error, ?ERR_NOT_ALLOWED};
|
||||
{error, xmpp:err_not_allowed()};
|
||||
{ok, {413, _Body}} ->
|
||||
?INFO_MSG("Got status code 413 for ~s from <~s>",
|
||||
[jid:to_string(JID), ServiceURL]),
|
||||
{error, ?ERR_NOT_ACCEPTABLE};
|
||||
{error, xmpp:err_not_acceptable()};
|
||||
{ok, {Code, _Body}} ->
|
||||
?ERROR_MSG("Got unexpected status code for ~s from <~s>: ~B",
|
||||
[jid:to_string(JID), ServiceURL, Code]),
|
||||
{error, ?ERR_SERVICE_UNAVAILABLE};
|
||||
{error, xmpp:err_service_unavailable()};
|
||||
{error, Reason} ->
|
||||
?ERROR_MSG("Error requesting upload slot for ~s from <~s>: ~p",
|
||||
[jid:to_string(JID), ServiceURL, Reason]),
|
||||
{error, ?ERR_SERVICE_UNAVAILABLE}
|
||||
{error, xmpp:err_service_unavailable()}
|
||||
end.
|
||||
|
||||
-spec add_slot(slot(), pos_integer(), timer:tref(), state()) -> state().
|
||||
@ -710,19 +668,12 @@ del_slot(Slot, #state{slots = Slots} = State) ->
|
||||
NewSlots = maps:remove(Slot, Slots),
|
||||
State#state{slots = NewSlots}.
|
||||
|
||||
-spec slot_el(slot() | binary(), state() | binary(), binary()) -> xmlel().
|
||||
-spec mk_slot(slot() | binary(), state() | binary(), binary()) -> xmlel().
|
||||
|
||||
slot_el(Slot, #state{put_url = PutPrefix, get_url = GetPrefix}, XMLNS) ->
|
||||
mk_slot(Slot, #state{put_url = PutPrefix, get_url = GetPrefix}, XMLNS) ->
|
||||
PutURL = str:join([PutPrefix | Slot], <<$/>>),
|
||||
GetURL = str:join([GetPrefix | Slot], <<$/>>),
|
||||
slot_el(PutURL, GetURL, XMLNS);
|
||||
slot_el(PutURL, GetURL, XMLNS) ->
|
||||
#xmlel{name = <<"slot">>,
|
||||
attrs = [{<<"xmlns">>, XMLNS}],
|
||||
children = [#xmlel{name = <<"put">>,
|
||||
children = [{xmlcdata, PutURL}]},
|
||||
#xmlel{name = <<"get">>,
|
||||
children = [{xmlcdata, GetURL}]}]}.
|
||||
#upload_slot{get = GetURL, put = PutURL, xmlns = XMLNS}.
|
||||
|
||||
-spec make_user_string(jid(), sha1 | node) -> binary().
|
||||
|
||||
@ -762,44 +713,30 @@ map_int_to_char(N) when N =< 61 -> N + 61. % Lower-case character.
|
||||
yield_content_type(<<"">>) -> ?DEFAULT_CONTENT_TYPE;
|
||||
yield_content_type(Type) -> Type.
|
||||
|
||||
-spec iq_disco_info(binary(), binary(), binary()) -> [xmlel()].
|
||||
-spec iq_disco_info(binary(), binary(), binary(), [xdata()]) -> [xmlel()].
|
||||
|
||||
iq_disco_info(Host, Lang, Name) ->
|
||||
iq_disco_info(Host, Lang, Name, AddInfo) ->
|
||||
Form = case gen_mod:get_module_opt(Host, ?MODULE, max_size,
|
||||
fun(I) when is_integer(I), I > 0 -> I;
|
||||
(infinity) -> infinity
|
||||
end,
|
||||
104857600) of
|
||||
infinity ->
|
||||
[];
|
||||
AddInfo;
|
||||
MaxSize ->
|
||||
MaxSizeStr = jlib:integer_to_binary(MaxSize),
|
||||
Fields = [#xmlel{name = <<"field">>,
|
||||
attrs = [{<<"type">>, <<"hidden">>},
|
||||
{<<"var">>, <<"FORM_TYPE">>}],
|
||||
children = [#xmlel{name = <<"value">>,
|
||||
children =
|
||||
[{xmlcdata,
|
||||
?NS_HTTP_UPLOAD}]}]},
|
||||
#xmlel{name = <<"field">>,
|
||||
attrs = [{<<"var">>, <<"max-file-size">>}],
|
||||
children = [#xmlel{name = <<"value">>,
|
||||
children =
|
||||
[{xmlcdata,
|
||||
MaxSizeStr}]}]}],
|
||||
[#xmlel{name = <<"x">>,
|
||||
attrs = [{<<"xmlns">>, ?NS_XDATA},
|
||||
{<<"type">>, <<"result">>}],
|
||||
children = Fields}]
|
||||
Fields = [#xdata_field{type = hidden,
|
||||
var = <<"FORM_TYPE">>,
|
||||
values = [?NS_HTTP_UPLOAD]},
|
||||
#xdata_field{var = <<"max-file-size">>,
|
||||
values = [MaxSizeStr]}],
|
||||
[#xdata{type = result, fields = Fields}|AddInfo]
|
||||
end,
|
||||
[#xmlel{name = <<"identity">>,
|
||||
attrs = [{<<"category">>, <<"store">>},
|
||||
{<<"type">>, <<"file">>},
|
||||
{<<"name">>, translate:translate(Lang, Name)}]},
|
||||
#xmlel{name = <<"feature">>,
|
||||
attrs = [{<<"var">>, ?NS_HTTP_UPLOAD}]},
|
||||
#xmlel{name = <<"feature">>,
|
||||
attrs = [{<<"var">>, ?NS_HTTP_UPLOAD_OLD}]} | Form].
|
||||
#disco_info{identities = [#identity{category = <<"store">>,
|
||||
type = <<"file">>,
|
||||
name = translate:translate(Lang, Name)}],
|
||||
features = [?NS_HTTP_UPLOAD, ?NS_HTTP_UPLOAD_OLD],
|
||||
xdata = Form}.
|
||||
|
||||
%% HTTP request handling.
|
||||
|
||||
@ -984,20 +921,14 @@ convert(Path, #media_info{type = T, width = W, height = H}) ->
|
||||
|
||||
thumb_el(Path, URI) ->
|
||||
ContentType = guess_content_type(Path),
|
||||
case identify(Path) of
|
||||
{ok, #media_info{height = H, width = W}} ->
|
||||
#xmlel{name = <<"thumbnail">>,
|
||||
attrs = [{<<"xmlns">>, ?NS_THUMBS_1},
|
||||
{<<"media-type">>, ContentType},
|
||||
{<<"uri">>, URI},
|
||||
{<<"height">>, jlib:integer_to_binary(H)},
|
||||
{<<"width">>, jlib:integer_to_binary(W)}]};
|
||||
pass ->
|
||||
#xmlel{name = <<"thumbnail">>,
|
||||
attrs = [{<<"xmlns">>, ?NS_THUMBS_1},
|
||||
{<<"uri">>, URI},
|
||||
{<<"media-type">>, ContentType}]}
|
||||
end.
|
||||
xmpp:encode(
|
||||
case identify(Path) of
|
||||
{ok, #media_info{height = H, width = W}} ->
|
||||
#thumbnail{'media-type' = ContentType, uri = URI,
|
||||
height = H, width = W};
|
||||
pass ->
|
||||
#thumbnail{uri = URI, 'media-type' = ContentType}
|
||||
end).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Remove user.
|
||||
|
@ -53,7 +53,7 @@
|
||||
%% ejabberd_hooks callback.
|
||||
-export([handle_slot_request/5]).
|
||||
|
||||
-include("jlib.hrl").
|
||||
-include("jid.hrl").
|
||||
-include("logger.hrl").
|
||||
-include_lib("kernel/include/file.hrl").
|
||||
|
||||
|
@ -15,6 +15,56 @@ decode(_el) -> decode(_el, []).
|
||||
decode({xmlel, _name, _attrs, _} = _el, Opts) ->
|
||||
IgnoreEls = proplists:get_bool(ignore_els, Opts),
|
||||
case {_name, get_attr(<<"xmlns">>, _attrs)} of
|
||||
{<<"thumbnail">>, <<"urn:xmpp:thumbs:1">>} ->
|
||||
decode_thumbnail(<<"urn:xmpp:thumbs:1">>, IgnoreEls,
|
||||
_el);
|
||||
{<<"slot">>, <<"urn:xmpp:http:upload">>} ->
|
||||
decode_upload_slot(<<"urn:xmpp:http:upload">>,
|
||||
IgnoreEls, _el);
|
||||
{<<"slot">>,
|
||||
<<"eu:siacs:conversations:http:upload">>} ->
|
||||
decode_upload_slot(<<"eu:siacs:conversations:http:upload">>,
|
||||
IgnoreEls, _el);
|
||||
{<<"put">>, <<"urn:xmpp:http:upload">>} ->
|
||||
decode_upload_put(<<"urn:xmpp:http:upload">>, IgnoreEls,
|
||||
_el);
|
||||
{<<"put">>, <<"eu:siacs:conversations:http:upload">>} ->
|
||||
decode_upload_put(<<"eu:siacs:conversations:http:upload">>,
|
||||
IgnoreEls, _el);
|
||||
{<<"get">>, <<"urn:xmpp:http:upload">>} ->
|
||||
decode_upload_get(<<"urn:xmpp:http:upload">>, IgnoreEls,
|
||||
_el);
|
||||
{<<"get">>, <<"eu:siacs:conversations:http:upload">>} ->
|
||||
decode_upload_get(<<"eu:siacs:conversations:http:upload">>,
|
||||
IgnoreEls, _el);
|
||||
{<<"request">>, <<"urn:xmpp:http:upload">>} ->
|
||||
decode_upload_request(<<"urn:xmpp:http:upload">>,
|
||||
IgnoreEls, _el);
|
||||
{<<"request">>,
|
||||
<<"eu:siacs:conversations:http:upload">>} ->
|
||||
decode_upload_request(<<"eu:siacs:conversations:http:upload">>,
|
||||
IgnoreEls, _el);
|
||||
{<<"content-type">>, <<"urn:xmpp:http:upload">>} ->
|
||||
decode_upload_content_type(<<"urn:xmpp:http:upload">>,
|
||||
IgnoreEls, _el);
|
||||
{<<"content-type">>,
|
||||
<<"eu:siacs:conversations:http:upload">>} ->
|
||||
decode_upload_content_type(<<"eu:siacs:conversations:http:upload">>,
|
||||
IgnoreEls, _el);
|
||||
{<<"size">>, <<"urn:xmpp:http:upload">>} ->
|
||||
decode_upload_size(<<"urn:xmpp:http:upload">>,
|
||||
IgnoreEls, _el);
|
||||
{<<"size">>,
|
||||
<<"eu:siacs:conversations:http:upload">>} ->
|
||||
decode_upload_size(<<"eu:siacs:conversations:http:upload">>,
|
||||
IgnoreEls, _el);
|
||||
{<<"filename">>, <<"urn:xmpp:http:upload">>} ->
|
||||
decode_upload_filename(<<"urn:xmpp:http:upload">>,
|
||||
IgnoreEls, _el);
|
||||
{<<"filename">>,
|
||||
<<"eu:siacs:conversations:http:upload">>} ->
|
||||
decode_upload_filename(<<"eu:siacs:conversations:http:upload">>,
|
||||
IgnoreEls, _el);
|
||||
{<<"address">>, <<"urn:xmpp:sic:0">>} ->
|
||||
decode_sic(<<"urn:xmpp:sic:0">>, IgnoreEls, _el);
|
||||
{<<"address">>, <<"urn:xmpp:sic:1">>} ->
|
||||
@ -1319,6 +1369,34 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) ->
|
||||
|
||||
is_known_tag({xmlel, _name, _attrs, _} = _el) ->
|
||||
case {_name, get_attr(<<"xmlns">>, _attrs)} of
|
||||
{<<"thumbnail">>, <<"urn:xmpp:thumbs:1">>} -> true;
|
||||
{<<"slot">>, <<"urn:xmpp:http:upload">>} -> true;
|
||||
{<<"slot">>,
|
||||
<<"eu:siacs:conversations:http:upload">>} ->
|
||||
true;
|
||||
{<<"put">>, <<"urn:xmpp:http:upload">>} -> true;
|
||||
{<<"put">>, <<"eu:siacs:conversations:http:upload">>} ->
|
||||
true;
|
||||
{<<"get">>, <<"urn:xmpp:http:upload">>} -> true;
|
||||
{<<"get">>, <<"eu:siacs:conversations:http:upload">>} ->
|
||||
true;
|
||||
{<<"request">>, <<"urn:xmpp:http:upload">>} -> true;
|
||||
{<<"request">>,
|
||||
<<"eu:siacs:conversations:http:upload">>} ->
|
||||
true;
|
||||
{<<"content-type">>, <<"urn:xmpp:http:upload">>} ->
|
||||
true;
|
||||
{<<"content-type">>,
|
||||
<<"eu:siacs:conversations:http:upload">>} ->
|
||||
true;
|
||||
{<<"size">>, <<"urn:xmpp:http:upload">>} -> true;
|
||||
{<<"size">>,
|
||||
<<"eu:siacs:conversations:http:upload">>} ->
|
||||
true;
|
||||
{<<"filename">>, <<"urn:xmpp:http:upload">>} -> true;
|
||||
{<<"filename">>,
|
||||
<<"eu:siacs:conversations:http:upload">>} ->
|
||||
true;
|
||||
{<<"address">>, <<"urn:xmpp:sic:0">>} -> true;
|
||||
{<<"address">>, <<"urn:xmpp:sic:1">>} -> true;
|
||||
{<<"port">>, <<"urn:xmpp:sic:1">>} -> true;
|
||||
@ -2626,7 +2704,14 @@ encode({media, _, _, _} = Media) ->
|
||||
encode({oob_x, _, _, _} = X) ->
|
||||
encode_oob_x(X, [{<<"xmlns">>, <<"jabber:x:oob">>}]);
|
||||
encode({sic, _, _, _} = Address) ->
|
||||
encode_sic(Address, []).
|
||||
encode_sic(Address, []);
|
||||
encode({upload_request, _, _, _, _} = Request) ->
|
||||
encode_upload_request(Request, []);
|
||||
encode({upload_slot, _, _, _} = Slot) ->
|
||||
encode_upload_slot(Slot, []);
|
||||
encode({thumbnail, _, _, _, _} = Thumbnail) ->
|
||||
encode_thumbnail(Thumbnail,
|
||||
[{<<"xmlns">>, <<"urn:xmpp:thumbs:1">>}]).
|
||||
|
||||
get_name({last, _, _}) -> <<"query">>;
|
||||
get_name({version, _, _, _}) -> <<"query">>;
|
||||
@ -2820,7 +2905,10 @@ get_name({xcaptcha, _}) -> <<"captcha">>;
|
||||
get_name({media_uri, _, _}) -> <<"uri">>;
|
||||
get_name({media, _, _, _}) -> <<"media">>;
|
||||
get_name({oob_x, _, _, _}) -> <<"x">>;
|
||||
get_name({sic, _, _, _}) -> <<"address">>.
|
||||
get_name({sic, _, _, _}) -> <<"address">>;
|
||||
get_name({upload_request, _, _, _, _}) -> <<"request">>;
|
||||
get_name({upload_slot, _, _, _}) -> <<"slot">>;
|
||||
get_name({thumbnail, _, _, _, _}) -> <<"thumbnail">>.
|
||||
|
||||
get_ns({last, _, _}) -> <<"jabber:iq:last">>;
|
||||
get_ns({version, _, _, _}) -> <<"jabber:iq:version">>;
|
||||
@ -3089,7 +3177,11 @@ get_ns({media_uri, _, _}) ->
|
||||
get_ns({media, _, _, _}) ->
|
||||
<<"urn:xmpp:media-element">>;
|
||||
get_ns({oob_x, _, _, _}) -> <<"jabber:x:oob">>;
|
||||
get_ns({sic, _, _, Xmlns}) -> Xmlns.
|
||||
get_ns({sic, _, _, Xmlns}) -> Xmlns;
|
||||
get_ns({upload_request, _, _, _, Xmlns}) -> Xmlns;
|
||||
get_ns({upload_slot, _, _, Xmlns}) -> Xmlns;
|
||||
get_ns({thumbnail, _, _, _, _}) ->
|
||||
<<"urn:xmpp:thumbs:1">>.
|
||||
|
||||
dec_int(Val) -> dec_int(Val, infinity, infinity).
|
||||
|
||||
@ -3339,6 +3431,10 @@ pp(media_uri, 2) -> [type, uri];
|
||||
pp(media, 3) -> [height, width, uri];
|
||||
pp(oob_x, 3) -> [url, desc, sid];
|
||||
pp(sic, 3) -> [ip, port, xmlns];
|
||||
pp(upload_request, 4) ->
|
||||
[filename, size, 'content-type', xmlns];
|
||||
pp(upload_slot, 3) -> [get, put, xmlns];
|
||||
pp(thumbnail, 4) -> [uri, 'media-type', width, height];
|
||||
pp(_, _) -> no.
|
||||
|
||||
enc_ip({0, 0, 0, 0, 0, 65535, A, B}) ->
|
||||
@ -3394,6 +3490,533 @@ dec_tzo(Val) ->
|
||||
M = jlib:binary_to_integer(M1),
|
||||
if H >= -12, H =< 12, M >= 0, M < 60 -> {H, M} end.
|
||||
|
||||
decode_thumbnail(__TopXMLNS, __IgnoreEls,
|
||||
{xmlel, <<"thumbnail">>, _attrs, _els}) ->
|
||||
{Uri, Media_type, Width, Height} =
|
||||
decode_thumbnail_attrs(__TopXMLNS, _attrs, undefined,
|
||||
undefined, undefined, undefined),
|
||||
{thumbnail, Uri, Media_type, Width, Height}.
|
||||
|
||||
decode_thumbnail_attrs(__TopXMLNS,
|
||||
[{<<"uri">>, _val} | _attrs], _Uri, Media_type, Width,
|
||||
Height) ->
|
||||
decode_thumbnail_attrs(__TopXMLNS, _attrs, _val,
|
||||
Media_type, Width, Height);
|
||||
decode_thumbnail_attrs(__TopXMLNS,
|
||||
[{<<"media-type">>, _val} | _attrs], Uri, _Media_type,
|
||||
Width, Height) ->
|
||||
decode_thumbnail_attrs(__TopXMLNS, _attrs, Uri, _val,
|
||||
Width, Height);
|
||||
decode_thumbnail_attrs(__TopXMLNS,
|
||||
[{<<"width">>, _val} | _attrs], Uri, Media_type, _Width,
|
||||
Height) ->
|
||||
decode_thumbnail_attrs(__TopXMLNS, _attrs, Uri,
|
||||
Media_type, _val, Height);
|
||||
decode_thumbnail_attrs(__TopXMLNS,
|
||||
[{<<"height">>, _val} | _attrs], Uri, Media_type, Width,
|
||||
_Height) ->
|
||||
decode_thumbnail_attrs(__TopXMLNS, _attrs, Uri,
|
||||
Media_type, Width, _val);
|
||||
decode_thumbnail_attrs(__TopXMLNS, [_ | _attrs], Uri,
|
||||
Media_type, Width, Height) ->
|
||||
decode_thumbnail_attrs(__TopXMLNS, _attrs, Uri,
|
||||
Media_type, Width, Height);
|
||||
decode_thumbnail_attrs(__TopXMLNS, [], Uri, Media_type,
|
||||
Width, Height) ->
|
||||
{decode_thumbnail_attr_uri(__TopXMLNS, Uri),
|
||||
'decode_thumbnail_attr_media-type'(__TopXMLNS,
|
||||
Media_type),
|
||||
decode_thumbnail_attr_width(__TopXMLNS, Width),
|
||||
decode_thumbnail_attr_height(__TopXMLNS, Height)}.
|
||||
|
||||
encode_thumbnail({thumbnail, Uri, Media_type, Width,
|
||||
Height},
|
||||
_xmlns_attrs) ->
|
||||
_els = [],
|
||||
_attrs = encode_thumbnail_attr_height(Height,
|
||||
encode_thumbnail_attr_width(Width,
|
||||
'encode_thumbnail_attr_media-type'(Media_type,
|
||||
encode_thumbnail_attr_uri(Uri,
|
||||
_xmlns_attrs)))),
|
||||
{xmlel, <<"thumbnail">>, _attrs, _els}.
|
||||
|
||||
decode_thumbnail_attr_uri(__TopXMLNS, undefined) ->
|
||||
erlang:error({xmpp_codec,
|
||||
{missing_attr, <<"uri">>, <<"thumbnail">>,
|
||||
__TopXMLNS}});
|
||||
decode_thumbnail_attr_uri(__TopXMLNS, _val) -> _val.
|
||||
|
||||
encode_thumbnail_attr_uri(_val, _acc) ->
|
||||
[{<<"uri">>, _val} | _acc].
|
||||
|
||||
'decode_thumbnail_attr_media-type'(__TopXMLNS,
|
||||
undefined) ->
|
||||
<<>>;
|
||||
'decode_thumbnail_attr_media-type'(__TopXMLNS, _val) ->
|
||||
_val.
|
||||
|
||||
'encode_thumbnail_attr_media-type'(<<>>, _acc) -> _acc;
|
||||
'encode_thumbnail_attr_media-type'(_val, _acc) ->
|
||||
[{<<"media-type">>, _val} | _acc].
|
||||
|
||||
decode_thumbnail_attr_width(__TopXMLNS, undefined) ->
|
||||
undefined;
|
||||
decode_thumbnail_attr_width(__TopXMLNS, _val) ->
|
||||
case catch dec_int(_val, 0, infinity) of
|
||||
{'EXIT', _} ->
|
||||
erlang:error({xmpp_codec,
|
||||
{bad_attr_value, <<"width">>, <<"thumbnail">>,
|
||||
__TopXMLNS}});
|
||||
_res -> _res
|
||||
end.
|
||||
|
||||
encode_thumbnail_attr_width(undefined, _acc) -> _acc;
|
||||
encode_thumbnail_attr_width(_val, _acc) ->
|
||||
[{<<"width">>, enc_int(_val)} | _acc].
|
||||
|
||||
decode_thumbnail_attr_height(__TopXMLNS, undefined) ->
|
||||
undefined;
|
||||
decode_thumbnail_attr_height(__TopXMLNS, _val) ->
|
||||
case catch dec_int(_val, 0, infinity) of
|
||||
{'EXIT', _} ->
|
||||
erlang:error({xmpp_codec,
|
||||
{bad_attr_value, <<"height">>, <<"thumbnail">>,
|
||||
__TopXMLNS}});
|
||||
_res -> _res
|
||||
end.
|
||||
|
||||
encode_thumbnail_attr_height(undefined, _acc) -> _acc;
|
||||
encode_thumbnail_attr_height(_val, _acc) ->
|
||||
[{<<"height">>, enc_int(_val)} | _acc].
|
||||
|
||||
decode_upload_slot(__TopXMLNS, __IgnoreEls,
|
||||
{xmlel, <<"slot">>, _attrs, _els}) ->
|
||||
{Put, Get} = decode_upload_slot_els(__TopXMLNS,
|
||||
__IgnoreEls, _els, undefined,
|
||||
undefined),
|
||||
Xmlns = decode_upload_slot_attrs(__TopXMLNS, _attrs,
|
||||
undefined),
|
||||
{upload_slot, Get, Put, Xmlns}.
|
||||
|
||||
decode_upload_slot_els(__TopXMLNS, __IgnoreEls, [], Put,
|
||||
Get) ->
|
||||
{Put, Get};
|
||||
decode_upload_slot_els(__TopXMLNS, __IgnoreEls,
|
||||
[{xmlel, <<"get">>, _attrs, _} = _el | _els], Put,
|
||||
Get) ->
|
||||
case get_attr(<<"xmlns">>, _attrs) of
|
||||
<<"">>
|
||||
when __TopXMLNS ==
|
||||
<<"eu:siacs:conversations:http:upload">>;
|
||||
__TopXMLNS == <<"urn:xmpp:http:upload">> ->
|
||||
decode_upload_slot_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Put,
|
||||
decode_upload_get(__TopXMLNS, __IgnoreEls,
|
||||
_el));
|
||||
<<"urn:xmpp:http:upload">> ->
|
||||
decode_upload_slot_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Put,
|
||||
decode_upload_get(<<"urn:xmpp:http:upload">>,
|
||||
__IgnoreEls, _el));
|
||||
<<"eu:siacs:conversations:http:upload">> ->
|
||||
decode_upload_slot_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Put,
|
||||
decode_upload_get(<<"eu:siacs:conversations:http:upload">>,
|
||||
__IgnoreEls, _el));
|
||||
_ ->
|
||||
decode_upload_slot_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Put, Get)
|
||||
end;
|
||||
decode_upload_slot_els(__TopXMLNS, __IgnoreEls,
|
||||
[{xmlel, <<"put">>, _attrs, _} = _el | _els], Put,
|
||||
Get) ->
|
||||
case get_attr(<<"xmlns">>, _attrs) of
|
||||
<<"">>
|
||||
when __TopXMLNS ==
|
||||
<<"eu:siacs:conversations:http:upload">>;
|
||||
__TopXMLNS == <<"urn:xmpp:http:upload">> ->
|
||||
decode_upload_slot_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
decode_upload_put(__TopXMLNS, __IgnoreEls,
|
||||
_el),
|
||||
Get);
|
||||
<<"urn:xmpp:http:upload">> ->
|
||||
decode_upload_slot_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
decode_upload_put(<<"urn:xmpp:http:upload">>,
|
||||
__IgnoreEls, _el),
|
||||
Get);
|
||||
<<"eu:siacs:conversations:http:upload">> ->
|
||||
decode_upload_slot_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
decode_upload_put(<<"eu:siacs:conversations:http:upload">>,
|
||||
__IgnoreEls, _el),
|
||||
Get);
|
||||
_ ->
|
||||
decode_upload_slot_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Put, Get)
|
||||
end;
|
||||
decode_upload_slot_els(__TopXMLNS, __IgnoreEls,
|
||||
[_ | _els], Put, Get) ->
|
||||
decode_upload_slot_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Put, Get).
|
||||
|
||||
decode_upload_slot_attrs(__TopXMLNS,
|
||||
[{<<"xmlns">>, _val} | _attrs], _Xmlns) ->
|
||||
decode_upload_slot_attrs(__TopXMLNS, _attrs, _val);
|
||||
decode_upload_slot_attrs(__TopXMLNS, [_ | _attrs],
|
||||
Xmlns) ->
|
||||
decode_upload_slot_attrs(__TopXMLNS, _attrs, Xmlns);
|
||||
decode_upload_slot_attrs(__TopXMLNS, [], Xmlns) ->
|
||||
decode_upload_slot_attr_xmlns(__TopXMLNS, Xmlns).
|
||||
|
||||
encode_upload_slot({upload_slot, Get, Put, Xmlns},
|
||||
_xmlns_attrs) ->
|
||||
_els = lists:reverse('encode_upload_slot_$put'(Put,
|
||||
'encode_upload_slot_$get'(Get,
|
||||
[]))),
|
||||
_attrs = encode_upload_slot_attr_xmlns(Xmlns,
|
||||
_xmlns_attrs),
|
||||
{xmlel, <<"slot">>, _attrs, _els}.
|
||||
|
||||
'encode_upload_slot_$put'(undefined, _acc) -> _acc;
|
||||
'encode_upload_slot_$put'(Put, _acc) ->
|
||||
[encode_upload_put(Put, []) | _acc].
|
||||
|
||||
'encode_upload_slot_$get'(undefined, _acc) -> _acc;
|
||||
'encode_upload_slot_$get'(Get, _acc) ->
|
||||
[encode_upload_get(Get, []) | _acc].
|
||||
|
||||
decode_upload_slot_attr_xmlns(__TopXMLNS, undefined) ->
|
||||
undefined;
|
||||
decode_upload_slot_attr_xmlns(__TopXMLNS, _val) -> _val.
|
||||
|
||||
encode_upload_slot_attr_xmlns(undefined, _acc) -> _acc;
|
||||
encode_upload_slot_attr_xmlns(_val, _acc) ->
|
||||
[{<<"xmlns">>, _val} | _acc].
|
||||
|
||||
decode_upload_put(__TopXMLNS, __IgnoreEls,
|
||||
{xmlel, <<"put">>, _attrs, _els}) ->
|
||||
Cdata = decode_upload_put_els(__TopXMLNS, __IgnoreEls,
|
||||
_els, <<>>),
|
||||
Cdata.
|
||||
|
||||
decode_upload_put_els(__TopXMLNS, __IgnoreEls, [],
|
||||
Cdata) ->
|
||||
decode_upload_put_cdata(__TopXMLNS, Cdata);
|
||||
decode_upload_put_els(__TopXMLNS, __IgnoreEls,
|
||||
[{xmlcdata, _data} | _els], Cdata) ->
|
||||
decode_upload_put_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
<<Cdata/binary, _data/binary>>);
|
||||
decode_upload_put_els(__TopXMLNS, __IgnoreEls,
|
||||
[_ | _els], Cdata) ->
|
||||
decode_upload_put_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Cdata).
|
||||
|
||||
encode_upload_put(Cdata, _xmlns_attrs) ->
|
||||
_els = encode_upload_put_cdata(Cdata, []),
|
||||
_attrs = _xmlns_attrs,
|
||||
{xmlel, <<"put">>, _attrs, _els}.
|
||||
|
||||
decode_upload_put_cdata(__TopXMLNS, <<>>) ->
|
||||
erlang:error({xmpp_codec,
|
||||
{missing_cdata, <<>>, <<"put">>, __TopXMLNS}});
|
||||
decode_upload_put_cdata(__TopXMLNS, _val) -> _val.
|
||||
|
||||
encode_upload_put_cdata(_val, _acc) ->
|
||||
[{xmlcdata, _val} | _acc].
|
||||
|
||||
decode_upload_get(__TopXMLNS, __IgnoreEls,
|
||||
{xmlel, <<"get">>, _attrs, _els}) ->
|
||||
Cdata = decode_upload_get_els(__TopXMLNS, __IgnoreEls,
|
||||
_els, <<>>),
|
||||
Cdata.
|
||||
|
||||
decode_upload_get_els(__TopXMLNS, __IgnoreEls, [],
|
||||
Cdata) ->
|
||||
decode_upload_get_cdata(__TopXMLNS, Cdata);
|
||||
decode_upload_get_els(__TopXMLNS, __IgnoreEls,
|
||||
[{xmlcdata, _data} | _els], Cdata) ->
|
||||
decode_upload_get_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
<<Cdata/binary, _data/binary>>);
|
||||
decode_upload_get_els(__TopXMLNS, __IgnoreEls,
|
||||
[_ | _els], Cdata) ->
|
||||
decode_upload_get_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Cdata).
|
||||
|
||||
encode_upload_get(Cdata, _xmlns_attrs) ->
|
||||
_els = encode_upload_get_cdata(Cdata, []),
|
||||
_attrs = _xmlns_attrs,
|
||||
{xmlel, <<"get">>, _attrs, _els}.
|
||||
|
||||
decode_upload_get_cdata(__TopXMLNS, <<>>) ->
|
||||
erlang:error({xmpp_codec,
|
||||
{missing_cdata, <<>>, <<"get">>, __TopXMLNS}});
|
||||
decode_upload_get_cdata(__TopXMLNS, _val) -> _val.
|
||||
|
||||
encode_upload_get_cdata(_val, _acc) ->
|
||||
[{xmlcdata, _val} | _acc].
|
||||
|
||||
decode_upload_request(__TopXMLNS, __IgnoreEls,
|
||||
{xmlel, <<"request">>, _attrs, _els}) ->
|
||||
{Content_type, Size, Filename} =
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
<<>>, error, error),
|
||||
Xmlns = decode_upload_request_attrs(__TopXMLNS, _attrs,
|
||||
undefined),
|
||||
{upload_request, Filename, Size, Content_type, Xmlns}.
|
||||
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls, [],
|
||||
Content_type, Size, Filename) ->
|
||||
{Content_type,
|
||||
case Size of
|
||||
error ->
|
||||
erlang:error({xmpp_codec,
|
||||
{missing_tag, <<"size">>, __TopXMLNS}});
|
||||
{value, Size1} -> Size1
|
||||
end,
|
||||
case Filename of
|
||||
error ->
|
||||
erlang:error({xmpp_codec,
|
||||
{missing_tag, <<"filename">>, __TopXMLNS}});
|
||||
{value, Filename1} -> Filename1
|
||||
end};
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls,
|
||||
[{xmlel, <<"filename">>, _attrs, _} = _el | _els],
|
||||
Content_type, Size, Filename) ->
|
||||
case get_attr(<<"xmlns">>, _attrs) of
|
||||
<<"">>
|
||||
when __TopXMLNS ==
|
||||
<<"eu:siacs:conversations:http:upload">>;
|
||||
__TopXMLNS == <<"urn:xmpp:http:upload">> ->
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Content_type, Size,
|
||||
{value,
|
||||
decode_upload_filename(__TopXMLNS,
|
||||
__IgnoreEls, _el)});
|
||||
<<"urn:xmpp:http:upload">> ->
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Content_type, Size,
|
||||
{value,
|
||||
decode_upload_filename(<<"urn:xmpp:http:upload">>,
|
||||
__IgnoreEls, _el)});
|
||||
<<"eu:siacs:conversations:http:upload">> ->
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Content_type, Size,
|
||||
{value,
|
||||
decode_upload_filename(<<"eu:siacs:conversations:http:upload">>,
|
||||
__IgnoreEls, _el)});
|
||||
_ ->
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Content_type, Size, Filename)
|
||||
end;
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls,
|
||||
[{xmlel, <<"size">>, _attrs, _} = _el | _els],
|
||||
Content_type, Size, Filename) ->
|
||||
case get_attr(<<"xmlns">>, _attrs) of
|
||||
<<"">>
|
||||
when __TopXMLNS ==
|
||||
<<"eu:siacs:conversations:http:upload">>;
|
||||
__TopXMLNS == <<"urn:xmpp:http:upload">> ->
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Content_type,
|
||||
{value,
|
||||
decode_upload_size(__TopXMLNS, __IgnoreEls,
|
||||
_el)},
|
||||
Filename);
|
||||
<<"urn:xmpp:http:upload">> ->
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Content_type,
|
||||
{value,
|
||||
decode_upload_size(<<"urn:xmpp:http:upload">>,
|
||||
__IgnoreEls, _el)},
|
||||
Filename);
|
||||
<<"eu:siacs:conversations:http:upload">> ->
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Content_type,
|
||||
{value,
|
||||
decode_upload_size(<<"eu:siacs:conversations:http:upload">>,
|
||||
__IgnoreEls, _el)},
|
||||
Filename);
|
||||
_ ->
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Content_type, Size, Filename)
|
||||
end;
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls,
|
||||
[{xmlel, <<"content-type">>, _attrs, _} = _el | _els],
|
||||
Content_type, Size, Filename) ->
|
||||
case get_attr(<<"xmlns">>, _attrs) of
|
||||
<<"">>
|
||||
when __TopXMLNS ==
|
||||
<<"eu:siacs:conversations:http:upload">>;
|
||||
__TopXMLNS == <<"urn:xmpp:http:upload">> ->
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
decode_upload_content_type(__TopXMLNS,
|
||||
__IgnoreEls,
|
||||
_el),
|
||||
Size, Filename);
|
||||
<<"urn:xmpp:http:upload">> ->
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
decode_upload_content_type(<<"urn:xmpp:http:upload">>,
|
||||
__IgnoreEls,
|
||||
_el),
|
||||
Size, Filename);
|
||||
<<"eu:siacs:conversations:http:upload">> ->
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
decode_upload_content_type(<<"eu:siacs:conversations:http:upload">>,
|
||||
__IgnoreEls,
|
||||
_el),
|
||||
Size, Filename);
|
||||
_ ->
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Content_type, Size, Filename)
|
||||
end;
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls,
|
||||
[_ | _els], Content_type, Size, Filename) ->
|
||||
decode_upload_request_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Content_type, Size, Filename).
|
||||
|
||||
decode_upload_request_attrs(__TopXMLNS,
|
||||
[{<<"xmlns">>, _val} | _attrs], _Xmlns) ->
|
||||
decode_upload_request_attrs(__TopXMLNS, _attrs, _val);
|
||||
decode_upload_request_attrs(__TopXMLNS, [_ | _attrs],
|
||||
Xmlns) ->
|
||||
decode_upload_request_attrs(__TopXMLNS, _attrs, Xmlns);
|
||||
decode_upload_request_attrs(__TopXMLNS, [], Xmlns) ->
|
||||
decode_upload_request_attr_xmlns(__TopXMLNS, Xmlns).
|
||||
|
||||
encode_upload_request({upload_request, Filename, Size,
|
||||
Content_type, Xmlns},
|
||||
_xmlns_attrs) ->
|
||||
_els =
|
||||
lists:reverse('encode_upload_request_$content-type'(Content_type,
|
||||
'encode_upload_request_$size'(Size,
|
||||
'encode_upload_request_$filename'(Filename,
|
||||
[])))),
|
||||
_attrs = encode_upload_request_attr_xmlns(Xmlns,
|
||||
_xmlns_attrs),
|
||||
{xmlel, <<"request">>, _attrs, _els}.
|
||||
|
||||
'encode_upload_request_$content-type'(<<>>, _acc) ->
|
||||
_acc;
|
||||
'encode_upload_request_$content-type'(Content_type,
|
||||
_acc) ->
|
||||
[encode_upload_content_type(Content_type, []) | _acc].
|
||||
|
||||
'encode_upload_request_$size'(Size, _acc) ->
|
||||
[encode_upload_size(Size, []) | _acc].
|
||||
|
||||
'encode_upload_request_$filename'(Filename, _acc) ->
|
||||
[encode_upload_filename(Filename, []) | _acc].
|
||||
|
||||
decode_upload_request_attr_xmlns(__TopXMLNS,
|
||||
undefined) ->
|
||||
undefined;
|
||||
decode_upload_request_attr_xmlns(__TopXMLNS, _val) ->
|
||||
_val.
|
||||
|
||||
encode_upload_request_attr_xmlns(undefined, _acc) ->
|
||||
_acc;
|
||||
encode_upload_request_attr_xmlns(_val, _acc) ->
|
||||
[{<<"xmlns">>, _val} | _acc].
|
||||
|
||||
decode_upload_content_type(__TopXMLNS, __IgnoreEls,
|
||||
{xmlel, <<"content-type">>, _attrs, _els}) ->
|
||||
Cdata = decode_upload_content_type_els(__TopXMLNS,
|
||||
__IgnoreEls, _els, <<>>),
|
||||
Cdata.
|
||||
|
||||
decode_upload_content_type_els(__TopXMLNS, __IgnoreEls,
|
||||
[], Cdata) ->
|
||||
decode_upload_content_type_cdata(__TopXMLNS, Cdata);
|
||||
decode_upload_content_type_els(__TopXMLNS, __IgnoreEls,
|
||||
[{xmlcdata, _data} | _els], Cdata) ->
|
||||
decode_upload_content_type_els(__TopXMLNS, __IgnoreEls,
|
||||
_els, <<Cdata/binary, _data/binary>>);
|
||||
decode_upload_content_type_els(__TopXMLNS, __IgnoreEls,
|
||||
[_ | _els], Cdata) ->
|
||||
decode_upload_content_type_els(__TopXMLNS, __IgnoreEls,
|
||||
_els, Cdata).
|
||||
|
||||
encode_upload_content_type(Cdata, _xmlns_attrs) ->
|
||||
_els = encode_upload_content_type_cdata(Cdata, []),
|
||||
_attrs = _xmlns_attrs,
|
||||
{xmlel, <<"content-type">>, _attrs, _els}.
|
||||
|
||||
decode_upload_content_type_cdata(__TopXMLNS, <<>>) ->
|
||||
<<>>;
|
||||
decode_upload_content_type_cdata(__TopXMLNS, _val) ->
|
||||
_val.
|
||||
|
||||
encode_upload_content_type_cdata(<<>>, _acc) -> _acc;
|
||||
encode_upload_content_type_cdata(_val, _acc) ->
|
||||
[{xmlcdata, _val} | _acc].
|
||||
|
||||
decode_upload_size(__TopXMLNS, __IgnoreEls,
|
||||
{xmlel, <<"size">>, _attrs, _els}) ->
|
||||
Cdata = decode_upload_size_els(__TopXMLNS, __IgnoreEls,
|
||||
_els, <<>>),
|
||||
Cdata.
|
||||
|
||||
decode_upload_size_els(__TopXMLNS, __IgnoreEls, [],
|
||||
Cdata) ->
|
||||
decode_upload_size_cdata(__TopXMLNS, Cdata);
|
||||
decode_upload_size_els(__TopXMLNS, __IgnoreEls,
|
||||
[{xmlcdata, _data} | _els], Cdata) ->
|
||||
decode_upload_size_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
<<Cdata/binary, _data/binary>>);
|
||||
decode_upload_size_els(__TopXMLNS, __IgnoreEls,
|
||||
[_ | _els], Cdata) ->
|
||||
decode_upload_size_els(__TopXMLNS, __IgnoreEls, _els,
|
||||
Cdata).
|
||||
|
||||
encode_upload_size(Cdata, _xmlns_attrs) ->
|
||||
_els = encode_upload_size_cdata(Cdata, []),
|
||||
_attrs = _xmlns_attrs,
|
||||
{xmlel, <<"size">>, _attrs, _els}.
|
||||
|
||||
decode_upload_size_cdata(__TopXMLNS, <<>>) ->
|
||||
erlang:error({xmpp_codec,
|
||||
{missing_cdata, <<>>, <<"size">>, __TopXMLNS}});
|
||||
decode_upload_size_cdata(__TopXMLNS, _val) ->
|
||||
case catch dec_int(_val, 0, infinity) of
|
||||
{'EXIT', _} ->
|
||||
erlang:error({xmpp_codec,
|
||||
{bad_cdata_value, <<>>, <<"size">>, __TopXMLNS}});
|
||||
_res -> _res
|
||||
end.
|
||||
|
||||
encode_upload_size_cdata(_val, _acc) ->
|
||||
[{xmlcdata, enc_int(_val)} | _acc].
|
||||
|
||||
decode_upload_filename(__TopXMLNS, __IgnoreEls,
|
||||
{xmlel, <<"filename">>, _attrs, _els}) ->
|
||||
Cdata = decode_upload_filename_els(__TopXMLNS,
|
||||
__IgnoreEls, _els, <<>>),
|
||||
Cdata.
|
||||
|
||||
decode_upload_filename_els(__TopXMLNS, __IgnoreEls, [],
|
||||
Cdata) ->
|
||||
decode_upload_filename_cdata(__TopXMLNS, Cdata);
|
||||
decode_upload_filename_els(__TopXMLNS, __IgnoreEls,
|
||||
[{xmlcdata, _data} | _els], Cdata) ->
|
||||
decode_upload_filename_els(__TopXMLNS, __IgnoreEls,
|
||||
_els, <<Cdata/binary, _data/binary>>);
|
||||
decode_upload_filename_els(__TopXMLNS, __IgnoreEls,
|
||||
[_ | _els], Cdata) ->
|
||||
decode_upload_filename_els(__TopXMLNS, __IgnoreEls,
|
||||
_els, Cdata).
|
||||
|
||||
encode_upload_filename(Cdata, _xmlns_attrs) ->
|
||||
_els = encode_upload_filename_cdata(Cdata, []),
|
||||
_attrs = _xmlns_attrs,
|
||||
{xmlel, <<"filename">>, _attrs, _els}.
|
||||
|
||||
decode_upload_filename_cdata(__TopXMLNS, <<>>) ->
|
||||
erlang:error({xmpp_codec,
|
||||
{missing_cdata, <<>>, <<"filename">>, __TopXMLNS}});
|
||||
decode_upload_filename_cdata(__TopXMLNS, _val) -> _val.
|
||||
|
||||
encode_upload_filename_cdata(_val, _acc) ->
|
||||
[{xmlcdata, _val} | _acc].
|
||||
|
||||
decode_sic(__TopXMLNS, __IgnoreEls,
|
||||
{xmlel, <<"address">>, _attrs, _els}) ->
|
||||
{Ip, Port} = decode_sic_els(__TopXMLNS, __IgnoreEls,
|
||||
|
@ -3021,6 +3021,78 @@
|
||||
refs = [#ref{name = sic_ip, min = 0, max = 1, label = '$ip'},
|
||||
#ref{name = sip_port, min = 0, max = 1, label = '$port'}]}).
|
||||
|
||||
-xml(upload_filename,
|
||||
#elem{name = <<"filename">>,
|
||||
xmlns = [<<"urn:xmpp:http:upload">>,
|
||||
<<"eu:siacs:conversations:http:upload">>],
|
||||
result = '$cdata',
|
||||
cdata = #cdata{required = true}}).
|
||||
|
||||
-xml(upload_size,
|
||||
#elem{name = <<"size">>,
|
||||
xmlns = [<<"urn:xmpp:http:upload">>,
|
||||
<<"eu:siacs:conversations:http:upload">>],
|
||||
result = '$cdata',
|
||||
cdata = #cdata{required = true,
|
||||
dec = {dec_int, [0, infinity]},
|
||||
enc = {enc_int, []}}}).
|
||||
|
||||
-xml(upload_content_type,
|
||||
#elem{name = <<"content-type">>,
|
||||
xmlns = [<<"urn:xmpp:http:upload">>,
|
||||
<<"eu:siacs:conversations:http:upload">>],
|
||||
result = '$cdata',
|
||||
cdata = #cdata{default = <<"">>}}).
|
||||
|
||||
-xml(upload_request,
|
||||
#elem{name = <<"request">>,
|
||||
xmlns = [<<"urn:xmpp:http:upload">>,
|
||||
<<"eu:siacs:conversations:http:upload">>],
|
||||
result = {upload_request, '$filename', '$size',
|
||||
'$content-type', '$xmlns'},
|
||||
attrs = [#attr{name = <<"xmlns">>}],
|
||||
refs = [#ref{name = upload_filename, label = '$filename',
|
||||
min = 1, max = 1},
|
||||
#ref{name = upload_size, label = '$size', min = 1, max = 1},
|
||||
#ref{name = upload_content_type, label = '$content-type',
|
||||
min = 0, max = 1, default = <<"">>}]}).
|
||||
|
||||
-xml(upload_get,
|
||||
#elem{name = <<"get">>,
|
||||
xmlns = [<<"urn:xmpp:http:upload">>,
|
||||
<<"eu:siacs:conversations:http:upload">>],
|
||||
result = '$cdata',
|
||||
cdata = #cdata{required = true}}).
|
||||
|
||||
-xml(upload_put,
|
||||
#elem{name = <<"put">>,
|
||||
xmlns = [<<"urn:xmpp:http:upload">>,
|
||||
<<"eu:siacs:conversations:http:upload">>],
|
||||
result = '$cdata',
|
||||
cdata = #cdata{required = true}}).
|
||||
|
||||
-xml(upload_slot,
|
||||
#elem{name = <<"slot">>,
|
||||
xmlns = [<<"urn:xmpp:http:upload">>,
|
||||
<<"eu:siacs:conversations:http:upload">>],
|
||||
result = {upload_slot, '$get', '$put', '$xmlns'},
|
||||
attrs = [#attr{name = <<"xmlns">>}],
|
||||
refs = [#ref{name = upload_get, min = 0, max = 1, label = '$get'},
|
||||
#ref{name = upload_put, min = 0, max = 1, label = '$put'}]}).
|
||||
|
||||
-xml(thumbnail,
|
||||
#elem{name = <<"thumbnail">>,
|
||||
xmlns = <<"urn:xmpp:thumbs:1">>,
|
||||
result = {thumbnail, '$uri', '$media-type', '$width', '$height'},
|
||||
attrs = [#attr{name = <<"uri">>, required = true},
|
||||
#attr{name = <<"media-type">>, default = <<"">>},
|
||||
#attr{name = <<"width">>,
|
||||
dec = {dec_int, [0, infinity]},
|
||||
enc = {enc_int, []}},
|
||||
#attr{name = <<"height">>,
|
||||
dec = {dec_int, [0, infinity]},
|
||||
enc = {enc_int, []}}]}).
|
||||
|
||||
dec_tzo(Val) ->
|
||||
[H1, M1] = str:tokens(Val, <<":">>),
|
||||
H = jlib:binary_to_integer(H1),
|
||||
|
Loading…
Reference in New Issue
Block a user