diff --git a/include/xmpp_codec.hrl b/include/xmpp_codec.hrl index 981f7f4c2..03421d98d 100644 --- a/include/xmpp_codec.hrl +++ b/include/xmpp_codec.hrl @@ -181,7 +181,7 @@ -type starttls_proceed() :: #starttls_proceed{}. -record(forwarded, {delay :: #delay{}, - sub_els = [] :: [xmpp_element() | fxml:xmlel()]}). + xml_els = [] :: [fxml:xmlel()]}). -type forwarded() :: #forwarded{}. -record(privilege, {perms = [] :: [#privilege_perm{}], diff --git a/specs/xmpp_codec.spec b/specs/xmpp_codec.spec index bcab7a6e5..0aa124ec8 100644 --- a/specs/xmpp_codec.spec +++ b/specs/xmpp_codec.spec @@ -2679,7 +2679,7 @@ -xml(forwarded, #elem{name = <<"forwarded">>, xmlns = <<"urn:xmpp:forward:0">>, - result = {forwarded, '$delay', '$_els'}, + result = {forwarded, '$delay', '$_xmls'}, refs = [#ref{name = delay, min = 0, max = 1, label = '$delay'}]}). diff --git a/src/mod_carboncopy.erl b/src/mod_carboncopy.erl index 023e8dc6f..7d8ca5332 100644 --- a/src/mod_carboncopy.erl +++ b/src/mod_carboncopy.erl @@ -198,7 +198,7 @@ send_copies(JID, To, Packet, Direction)-> -spec build_forward_packet(jid(), message(), jid(), jid(), direction()) -> message(). build_forward_packet(JID, #message{type = T} = Msg, Sender, Dest, Direction) -> - Forwarded = #forwarded{sub_els = [complete_packet(JID, Msg, Direction)]}, + Forwarded = #forwarded{xml_els = [xmpp:encode(complete_packet(JID, Msg, Direction))]}, Carbon = case Direction of sent -> #carbons_sent{forwarded = Forwarded}; received -> #carbons_received{forwarded = Forwarded} diff --git a/src/mod_delegation.erl b/src/mod_delegation.erl index 7fec01dcb..ad57bad44 100644 --- a/src/mod_delegation.erl +++ b/src/mod_delegation.erl @@ -217,7 +217,8 @@ process_iq(#iq{to = To, lang = Lang, sub_els = [SubEl]} = IQ, Type) -> Delegations = get_delegations(LServer), case dict:find({NS, Type}, Delegations) of {ok, {Host, _}} -> - Delegation = #delegation{forwarded = #forwarded{sub_els = [IQ]}}, + Delegation = #delegation{ + forwarded = #forwarded{xml_els = [xmpp:encode(IQ)]}}, NewFrom = jid:make(LServer), NewTo = jid:make(Host), ejabberd_local:route_iq( @@ -236,14 +237,15 @@ process_iq(#iq{to = To, lang = Lang, sub_els = [SubEl]} = IQ, Type) -> -spec process_iq_result(iq(), iq()) -> ok. process_iq_result(#iq{from = From, to = To, id = ID, lang = Lang} = IQ, #iq{type = result} = ResIQ) -> - case xmpp:get_subtag(ResIQ, #delegation{}) of - #delegation{ - forwarded = #forwarded{ - sub_els = [#iq{from = To, to = From, - type = Type, id = ID} = Reply]}} - when Type == error; Type == result -> - ejabberd_router:route(From, To, Reply); - _ -> + try + #delegation{forwarded = #forwarded{xml_els = [SubEl]}} = + xmpp:get_subtag(ResIQ, #delegation{}), + case xmpp:decode(SubEl, ?NS_CLIENT, [ignore_els]) of + #iq{from = To, to = From, type = Type, id = ID} = Reply + when Type == error; Type == result -> + ejabberd_router:route(From, To, Reply) + end + catch _:_ -> ?ERROR_MSG("got iq-result with invalid delegated " "payload:~n~s", [xmpp:pp(ResIQ)]), Txt = <<"External component failure">>, diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 8c5422f07..f9ef104bd 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -794,7 +794,7 @@ msg_to_el(#archive_msg{timestamp = TS, packet = Pkt1, nick = Nick, peer = Peer}, MsgType, JidRequestor, #jid{lserver = LServer} = JidArchive) -> Pkt2 = maybe_update_from_to(Pkt1, JidRequestor, JidArchive, Peer, MsgType, Nick), - #forwarded{sub_els = [Pkt2], + #forwarded{xml_els = [xmpp:encode(Pkt2)], delay = #delay{stamp = TS, from = jid:make(LServer)}}. maybe_update_from_to(#xmlel{} = El, JidRequestor, JidArchive, Peer, diff --git a/src/mod_privilege.erl b/src/mod_privilege.erl index 50212b7ae..936c237bd 100644 --- a/src/mod_privilege.erl +++ b/src/mod_privilege.erl @@ -257,25 +257,33 @@ get_permissions(ServerHost) -> end. forward_message(From, To, Msg) -> - Host = From#jid.lserver, ServerHost = To#jid.lserver, + Lang = xmpp:get_lang(Msg), case xmpp:get_subtag(Msg, #privilege{}) of - #privilege{forwarded = #forwarded{sub_els = [#message{} = SubEl]}} -> - case SubEl#message.from of - #jid{lresource = <<"">>, lserver = ServerHost} -> - ejabberd_router:route( - xmpp:get_from(SubEl), xmpp:get_to(SubEl), SubEl); + #privilege{forwarded = #forwarded{xml_els = [SubEl]}} -> + try xmpp:decode(SubEl, ?NS_CLIENT, [ignore_els]) of + #message{} = NewMsg -> + case NewMsg#message.from of + #jid{lresource = <<"">>, lserver = ServerHost} -> + ejabberd_router:route( + xmpp:get_from(NewMsg), xmpp:get_to(NewMsg), NewMsg); + _ -> + Lang = xmpp:get_lang(Msg), + Txt = <<"Invalid 'from' attribute in forwarded message">>, + Err = xmpp:err_forbidden(Txt, Lang), + ejabberd_router:route_error(To, From, Msg, Err) + end; _ -> - Lang = xmpp:get_lang(Msg), - Txt = <<"Invalid 'from' attribute">>, - Err = xmpp:err_forbidden(Txt, Lang), + Txt = <<"Message not found in forwarded payload">>, + Err = xmpp:err_bad_request(Txt, Lang), + ejabberd_router:route_error(To, From, Msg, Err) + catch _:{xmpp_codec, Why} -> + Txt = xmpp:format_error(Why), + Err = xmpp:err_bad_request(Txt, Lang), ejabberd_router:route_error(To, From, Msg, Err) end; _ -> - ?ERROR_MSG("got invalid forwarded payload from external " - "component '~s':~n~s", [Host, xmpp:pp(Msg)]), - Lang = xmpp:get_lang(Msg), - Txt = <<"Invalid forwarded payload">>, + Txt = <<"Invalid element">>, Err = xmpp:err_bad_request(Txt, Lang), ejabberd_router:route_error(To, From, Msg, Err) end. diff --git a/src/xmpp_codec.erl b/src/xmpp_codec.erl index 2931baaa4..6089f79fc 100644 --- a/src/xmpp_codec.erl +++ b/src/xmpp_codec.erl @@ -6639,7 +6639,7 @@ pp(mam_archived, 2) -> [by, id]; pp(mam_result, 4) -> [xmlns, queryid, id, sub_els]; pp(mam_prefs, 4) -> [xmlns, default, always, never]; pp(mam_fin, 5) -> [xmlns, id, rsm, stable, complete]; -pp(forwarded, 2) -> [delay, sub_els]; +pp(forwarded, 2) -> [delay, xml_els]; pp(carbons_disable, 0) -> []; pp(carbons_enable, 0) -> []; pp(carbons_private, 0) -> []; @@ -11966,53 +11966,41 @@ encode_carbons_disable({carbons_disable}, __TopXMLNS) -> decode_forwarded(__TopXMLNS, __IgnoreEls, {xmlel, <<"forwarded">>, _attrs, _els}) -> - {Delay, __Els} = decode_forwarded_els(__TopXMLNS, - __IgnoreEls, _els, undefined, []), - {forwarded, Delay, __Els}. + {Delay, __Xmls} = decode_forwarded_els(__TopXMLNS, + __IgnoreEls, _els, undefined, []), + {forwarded, Delay, __Xmls}. decode_forwarded_els(__TopXMLNS, __IgnoreEls, [], Delay, - __Els) -> - {Delay, lists:reverse(__Els)}; + __Xmls) -> + {Delay, lists:reverse(__Xmls)}; decode_forwarded_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"delay">>, _attrs, _} = _el | _els], Delay, - __Els) -> + __Xmls) -> case get_attr(<<"xmlns">>, _attrs) of <<"urn:xmpp:delay">> -> decode_forwarded_els(__TopXMLNS, __IgnoreEls, _els, decode_delay(<<"urn:xmpp:delay">>, __IgnoreEls, _el), - __Els); + __Xmls); _ -> decode_forwarded_els(__TopXMLNS, __IgnoreEls, _els, - Delay, __Els) + Delay, __Xmls) end; decode_forwarded_els(__TopXMLNS, __IgnoreEls, - [{xmlel, _, _, _} = _el | _els], Delay, __Els) -> - if __IgnoreEls -> - decode_forwarded_els(__TopXMLNS, __IgnoreEls, _els, - Delay, [_el | __Els]); - true -> - case is_known_tag(_el, __TopXMLNS) of - true -> - decode_forwarded_els(__TopXMLNS, __IgnoreEls, _els, - Delay, - [decode(_el, __TopXMLNS, []) | __Els]); - false -> - decode_forwarded_els(__TopXMLNS, __IgnoreEls, _els, - Delay, __Els) - end - end; -decode_forwarded_els(__TopXMLNS, __IgnoreEls, - [_ | _els], Delay, __Els) -> + [{xmlel, _, _, _} = _el | _els], Delay, __Xmls) -> decode_forwarded_els(__TopXMLNS, __IgnoreEls, _els, - Delay, __Els). + Delay, [_el | __Xmls]); +decode_forwarded_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Delay, __Xmls) -> + decode_forwarded_els(__TopXMLNS, __IgnoreEls, _els, + Delay, __Xmls). -encode_forwarded({forwarded, Delay, __Els}, +encode_forwarded({forwarded, Delay, __Xmls}, __TopXMLNS) -> __NewTopXMLNS = choose_top_xmlns(<<"urn:xmpp:forward:0">>, [], __TopXMLNS), - _els = [encode(_el, __NewTopXMLNS) || _el <- __Els] ++ + _els = __Xmls ++ lists:reverse('encode_forwarded_$delay'(Delay, __NewTopXMLNS, [])), _attrs = enc_xmlns_attrs(__NewTopXMLNS, __TopXMLNS), diff --git a/src/xmpp_util.erl b/src/xmpp_util.erl index a07dae78b..57440b50e 100644 --- a/src/xmpp_util.erl +++ b/src/xmpp_util.erl @@ -42,16 +42,20 @@ add_delay_info(Stz, From, Time, Desc) -> -spec unwrap_carbon(stanza()) -> xmpp_element(). unwrap_carbon(#message{} = Msg) -> - case xmpp:get_subtag(Msg, #carbons_sent{}) of - #carbons_sent{forwarded = #forwarded{sub_els = [El]}} -> - El; - _ -> - case xmpp:get_subtag(Msg, #carbons_received{}) of - #carbons_received{forwarded = #forwarded{sub_els = [El]}} -> - El; - _ -> - Msg - end + try + case xmpp:get_subtag(Msg, #carbons_sent{}) of + #carbons_sent{forwarded = #forwarded{xml_els = [El]}} -> + xmpp:decode(El, ?NS_CLIENT, [ignore_els]); + _ -> + case xmpp:get_subtag(Msg, #carbons_received{}) of + #carbons_received{forwarded = #forwarded{xml_els = [El]}} -> + xmpp:decode(El, ?NS_CLIENT, [ignore_els]); + _ -> + Msg + end + end + catch _:{xmpp_codec, _} -> + Msg end; unwrap_carbon(Stanza) -> Stanza.