From 77d0b8b27364cff0d44e54f797eb96c1934f3c55 Mon Sep 17 00:00:00 2001 From: Nelson Vides Date: Wed, 8 Jan 2025 07:52:31 +0100 Subject: [PATCH] Upgrade exml to 4.0.0 --- rebar.config | 6 +- rebar.lock | 6 +- src/escalus_bosh.erl | 67 +++++------ src/escalus_component.erl | 9 +- src/escalus_event.erl | 10 +- src/escalus_pred.erl | 28 ++--- src/escalus_pubsub_stanza.erl | 102 ++++++++-------- src/escalus_session.erl | 4 +- src/escalus_stanza.erl | 219 ++++++++++++++++------------------ test/escalus_stanza_SUITE.erl | 8 +- 10 files changed, 226 insertions(+), 233 deletions(-) diff --git a/rebar.config b/rebar.config index 3ecc3463..9b7dedef 100644 --- a/rebar.config +++ b/rebar.config @@ -6,7 +6,7 @@ {require_min_otp_vsn, "26"}. {deps, [ - {exml, "3.4.1", {pkg, hexml}}, + {exml, "4.0.0", {pkg, hexml}}, {meck, "1.0.0"}, {bbmustache, "1.12.2"}, {uuid, "2.0.7", {pkg, uuid_erl}}, @@ -16,6 +16,10 @@ {fast_scram, "0.6.1"} ]}. +{dialyzer, [ + {warnings, [unknown]}, + {plt_extra_apps, [common_test, exml, uuid, worker_pool, fast_scram]}]}. + %% To override the plugin as installed by worker_pool {project_plugins, [rebar3_hex, {rebar3_codecov, "0.6.0"}]}. diff --git a/rebar.lock b/rebar.lock index 71899364..f52ca898 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.2.0", [{<<"bbmustache">>,{pkg,<<"bbmustache">>,<<"1.12.2">>},0}, {<<"cowlib">>,{pkg,<<"cowlib">>,<<"2.13.0">>},1}, - {<<"exml">>,{pkg,<<"hexml">>,<<"3.4.1">>},0}, + {<<"exml">>,{pkg,<<"hexml">>,<<"4.0.0">>},0}, {<<"fast_pbkdf2">>,{pkg,<<"fast_pbkdf2">>,<<"1.0.6">>},1}, {<<"fast_scram">>,{pkg,<<"fast_scram">>,<<"0.6.1">>},0}, {<<"fast_tls">>,{pkg,<<"fast_tls">>,<<"1.1.21">>},0}, @@ -15,7 +15,7 @@ {pkg_hash,[ {<<"bbmustache">>, <<"0CABDCE0DB9FE6D3318131174B9F2B351328A4C0AFBEB3E6E99BB0E02E9B621D">>}, {<<"cowlib">>, <<"DB8F7505D8332D98EF50A3EF34B34C1AFDDEC7506E4EE4DD4A3A266285D282CA">>}, - {<<"exml">>, <<"9581FE6512D9772C61BBE611CD4A8E5BB90B4D4481275325EC520F7A931A9393">>}, + {<<"exml">>, <<"54C1AAD5BD290EC31C19CE4A5D449C7E3236107AA2D3610FC04FC963DC8EAF13">>}, {<<"fast_pbkdf2">>, <<"199BCEC73A1A246941E9465D3DC41052953B638128841ED24B29ED03CF70AF27">>}, {<<"fast_scram">>, <<"BEEADB03D774640F0671681759CE53B2FF33CB58C86FD9BF2A793E2FC1ED0F5D">>}, {<<"fast_tls">>, <<"65D7D547A09EEFB37A1C0D04D8601FAC4F3E6E2C1EDE859A7787081670F9648D">>}, @@ -28,7 +28,7 @@ {pkg_hash_ext,[ {<<"bbmustache">>, <<"688B33A4D5CC2D51F575ADF0B3683FC40A38314A2F150906EDCFC77F5B577B3B">>}, {<<"cowlib">>, <<"E1E1284DC3FC030A64B1AD0D8382AE7E99DA46C3246B815318A4B848873800A4">>}, - {<<"exml">>, <<"D8E7894E2544402B4986EEB2443C15B51B14F686266F091DBF2777D1D99A2FA2">>}, + {<<"exml">>, <<"08CC97527C708D57A03F467049AC260B5951BD67906AA154BE56B5D8BDD3238C">>}, {<<"fast_pbkdf2">>, <<"35EEC22629AAA739915843C7B7DE0D84657D1ECE972D8BBC86368747E9C14012">>}, {<<"fast_scram">>, <<"FE0650A309FDF97C75E1EA812CCFB40EB464ECAFD3783E83AA17C7F572EDAB0B">>}, {<<"fast_tls">>, <<"131542913937025E48CD80AA81F00359686D5501B75621E72026A87B5229505B">>}, diff --git a/src/escalus_bosh.erl b/src/escalus_bosh.erl index 8767c564..f7eb8295 100644 --- a/src/escalus_bosh.erl +++ b/src/escalus_bosh.erl @@ -169,49 +169,48 @@ session_creation_body(Rid, To) -> exml:element(). session_creation_body(Wait, Version, Lang, Rid, To, nil) -> empty_body(Rid, nil, - [{<<"content">>, <<"text/xml; charset=utf-8">>}, - {<<"xmlns:xmpp">>, ?NS_BOSH}, - {<<"xmpp:version">>, Version}, - {<<"ver">>, <<"1.6">>}, - {<<"hold">>, <<"1">>}, - {<<"wait">>, list_to_binary(integer_to_list(Wait))}, - {<<"xml:lang">>, Lang}, - {<<"to">>, To}]); + #{<<"content">> => <<"text/xml; charset=utf-8">>, + <<"xmlns:xmpp">> => ?NS_BOSH, + <<"xmpp:version">> => Version, + <<"ver">> => <<"1.6">>, + <<"hold">> => <<"1">>, + <<"wait">> => list_to_binary(integer_to_list(Wait)), + <<"xml:lang">> => Lang, + <<"to">> => To}); session_creation_body(_Wait, _Version, Lang, Rid, To, Sid) -> empty_body(Rid, Sid, - [{<<"xmlns:xmpp">>, ?NS_BOSH}, - {<<"xml:lang">>, Lang}, - {<<"to">>, To}, - {<<"xmpp:restart">>, <<"true">>}]). + #{<<"xmlns:xmpp">> => ?NS_BOSH, + <<"xml:lang">> => Lang, + <<"to">> => To, + <<"xmpp:restart">> => <<"true">>}). -spec session_termination_body(Rid :: integer(), Sid :: binary() | nil) -> exml:element(). session_termination_body(Rid, Sid) -> - Body = empty_body(Rid, Sid, [{<<"type">>, <<"terminate">>}]), + Body = empty_body(Rid, Sid, #{<<"type">> => <<"terminate">>}), Body#xmlel{children = [escalus_stanza:presence(<<"unavailable">>)]}. -spec empty_body(Rid :: integer(), Sid :: binary()) -> exml:element(). empty_body(Rid, Sid) -> - empty_body(Rid, Sid, []). + empty_body(Rid, Sid, #{}). --spec empty_body(Rid :: integer(), Sid :: binary() | nil, ExtraAttrs :: [exml:attr()]) -> +-spec empty_body(Rid :: integer(), Sid :: binary() | nil, ExtraAttrs :: exml:attrs()) -> exml:element(). empty_body(Rid, Sid, ExtraAttrs) -> #xmlel{name = <<"body">>, - attrs = common_attrs(Rid, Sid) ++ ExtraAttrs}. + attrs = maps:merge(common_attrs(Rid, Sid), ExtraAttrs)}. pause_body(Rid, Sid, Seconds) -> Empty = empty_body(Rid, Sid), - Pause = {<<"pause">>, integer_to_binary(Seconds)}, - Empty#xmlel{attrs = Empty#xmlel.attrs ++ [Pause]}. + Empty#xmlel{attrs = maps:put(<<"pause">>, integer_to_binary(Seconds), Empty#xmlel.attrs)}. common_attrs(Rid) -> - [{<<"rid">>, pack_rid(Rid)}, - {<<"xmlns">>, ?NS_HTTP_BIND}]. + #{<<"rid">> => pack_rid(Rid), + <<"xmlns">> => ?NS_HTTP_BIND}. common_attrs(Rid, nil) -> common_attrs(Rid); common_attrs(Rid, Sid) -> - common_attrs(Rid) ++ [{<<"sid">>, Sid}]. + maps:put(<<"sid">>, Sid, common_attrs(Rid)). pack_rid(Rid) -> integer_to_binary(Rid). @@ -576,27 +575,27 @@ handle_recv(#state{replies = [{#xmlel{name = <<"body">>, attrs = Attrs} = Body, wrap_elem(#xmlstreamstart{attrs = Attrs}, #state{rid = Rid, sid = Sid, wait = Wait}) -> - Version = proplists:get_value(<<"version">>, Attrs, <<"1.0">>), - Lang = proplists:get_value(<<"xml:lang">>, Attrs, <<"en">>), - To = proplists:get_value(<<"to">>, Attrs, <<"localhost">>), + Version = maps:get(<<"version">>, Attrs, <<"1.0">>), + Lang = maps:get(<<"xml:lang">>, Attrs, <<"en">>), + To = maps:get(<<"to">>, Attrs, <<"localhost">>), session_creation_body(Wait, Version, Lang, Rid, To, Sid); wrap_elem(#xmlstreamend{}, #state{sid=Sid, rid=Rid}) -> session_termination_body(Rid, Sid); wrap_elem(Element, #state{sid = Sid, rid=Rid}) -> (empty_body(Rid, Sid))#xmlel{children = [Element]}. -unwrap_elem(#xmlel{name = <<"body">>, children = Body, attrs=Attrs}) -> +unwrap_elem(#xmlel{name = <<"body">>, children = Body, attrs = Attrs}) -> Type = detect_type(Attrs), case Type of {streamstart, Ver} -> - Server = proplists:get_value(<<"from">>, Attrs), - StreamStart = #xmlstreamstart{name = <<"stream:stream">>, attrs=[ - {<<"from">>, Server}, - {<<"version">>, Ver}, - {<<"xml:lang">>, <<"en">>}, - {<<"xmlns">>, <<"jabber:client">>}, - {<<"xmlns:stream">>, - <<"http://etherx.jabber.org/streams">>}]}, + Server = maps:get(<<"from">>, Attrs), + NewAttrs = #{<<"from">> => Server, + <<"version">> => Ver, + <<"xml:lang">> => <<"en">>, + <<"xmlns">> => <<"jabber:client">>, + <<"xmlns:stream">> => <<"http://etherx.jabber.org/streams">>}, + StreamStart = #xmlstreamstart{name = <<"stream:stream">>, + attrs = NewAttrs}, [StreamStart]; streamend -> [escalus_stanza:stream_end()]; @@ -604,7 +603,7 @@ unwrap_elem(#xmlel{name = <<"body">>, children = Body, attrs=Attrs}) -> end ++ Body. detect_type(Attrs) -> - Get = fun(A) -> proplists:get_value(A, Attrs) end, + Get = fun(A) -> maps:get(A, Attrs, undefined) end, case {Get(<<"type">>), Get(<<"xmpp:version">>)} of {<<"terminate">>, _} -> streamend; {_, undefined} -> normal; diff --git a/src/escalus_component.erl b/src/escalus_component.erl index 9ee44781..37b11330 100644 --- a/src/escalus_component.erl +++ b/src/escalus_component.erl @@ -180,7 +180,7 @@ component_start_stream(Conn = #client{props = Props}, []) -> StreamStartRep = escalus_connection:get_stanza(Conn, wait_for_stream), #xmlstreamstart{attrs = Attrs} = StreamStartRep, - Id = proplists:get_value(<<"id">>, Attrs), + Id = maps:get(<<"id">>, Attrs, undefined), {Conn#client{props = [{sid, Id} | Props]}, []}. @@ -205,10 +205,9 @@ component_handshake(Conn = #client{props = Props}, []) -> %% Stanzas %%-------------------------------------------------------------------- component_stream_start(Component) -> - Attrs = [{<<"to">>, Component}, - {<<"xmlns">>, <<"jabber:component:accept">>}, - {<<"xmlns:stream">>, - <<"http://etherx.jabber.org/streams">>}], + Attrs = #{<<"to">> => Component, + <<"xmlns">> => <<"jabber:component:accept">>, + <<"xmlns:stream">> => <<"http://etherx.jabber.org/streams">>}, #xmlstreamstart{name = <<"stream:stream">>, attrs = Attrs}. component_handshake_el(SID, Password) -> diff --git a/src/escalus_event.erl b/src/escalus_event.erl index ac87c691..4cf2e61d 100644 --- a/src/escalus_event.erl +++ b/src/escalus_event.erl @@ -165,13 +165,13 @@ build_elem_event(BaseTime, {story, Type, Time}) -> build_story_event_elem(Type, BaseTime, Time). build_story_event_elem(Type, BaseTime, Time) -> - #xmlel{name = list_to_binary(atom_to_list(Type)), - attrs = [{<<"offset">>, time_offset_binary(BaseTime, Time)}]}. + #xmlel{name = atom_to_binary(Type), + attrs = #{<<"offset">> => time_offset_binary(BaseTime, Time)}}. build_stanza_event_elem(Type, JID, BaseTime, Time, Elem) -> - #xmlel{name = list_to_binary(atom_to_list(Type)), - attrs = [{<<"jid">>, jid_to_binary(JID)}, - {<<"offset">>, time_offset_binary(BaseTime, Time)}], + #xmlel{name = atom_to_binary(Type), + attrs = #{<<"jid">> => jid_to_binary(JID), + <<"offset">> => time_offset_binary(BaseTime, Time)}, children = [Elem || Elem =/= undefined]}. manager(Config) -> diff --git a/src/escalus_pred.erl b/src/escalus_pred.erl index 1105a569..74ac4126 100644 --- a/src/escalus_pred.erl +++ b/src/escalus_pred.erl @@ -199,12 +199,12 @@ is_chat_message(Msg, Stanza) -> -spec is_chat_message_from_to(binary(), binary(), binary(), exml:element()) -> boolean(). -is_chat_message_from_to(From, To, Msg, #xmlel{attrs=Attrs} = Stanza) -> +is_chat_message_from_to(From, To, Msg, #xmlel{attrs = Attrs} = Stanza) -> is_chat_message(Msg, Stanza) andalso - bin(From) == proplists:get_value(<<"from">>, Attrs) + bin(From) == maps:get(<<"from">>, Attrs, undefined) andalso - bin(To) == proplists:get_value(<<"to">>, Attrs). + bin(To) == maps:get(<<"to">>, Attrs, undefined). -spec is_groupchat_message(exml:element()) -> boolean(). is_groupchat_message(Stanza) -> @@ -257,24 +257,24 @@ has_type(Type, Stanza) -> -spec is_0184_request(exml:element()) -> boolean(). is_0184_request(#xmlel{children = Els}) -> #xmlel{ name = <<"request">>, - attrs = [{<<"xmlns">>, <<"urn:xmpp:receipts">>}], + attrs = #{<<"xmlns">> => <<"urn:xmpp:receipts">>}, children = [] } =:= lists:keyfind(<<"request">>, 2, Els). -spec is_0184_receipt(exml:element(), exml:element()) -> boolean(). -is_0184_receipt(#xmlel{ attrs = ReqAttrs } = Request, Receipt) -> - {_, ReqTo} = lists:keyfind(<<"to">>, 1, ReqAttrs), +is_0184_receipt(#xmlel{attrs = ReqAttrs} = Request, Receipt) -> + ReqTo = maps:get(<<"to">>, ReqAttrs), is_0184_receipt(Request, ReqTo, Receipt). -spec is_0184_receipt(exml:element(), binary(), exml:element()) -> boolean(). -is_0184_receipt(#xmlel{ attrs = ReqAttrs } = _Request, +is_0184_receipt(#xmlel{attrs = ReqAttrs} = _Request, ProperResFrom, - #xmlel{ attrs = ResAttrs, - children = [#xmlel{ name = <<"received">>, - attrs = SubAttrs}]} = _Receipt) -> - {_, ResFrom} = lists:keyfind(<<"from">>, 1, ResAttrs), - {_, ReqID} = lists:keyfind(<<"id">>, 1, ReqAttrs), - {_, ResID} = lists:keyfind(<<"id">>, 1, SubAttrs), - {_, ResXmlns} = lists:keyfind(<<"xmlns">>, 1, SubAttrs), + #xmlel{attrs = ResAttrs, + children = [#xmlel{name = <<"received">>, + attrs = SubAttrs}]} = _Receipt) -> + ResFrom = maps:get(<<"from">>, ResAttrs), + ReqID = maps:get(<<"id">>, ReqAttrs), + ResID = maps:get(<<"id">>, SubAttrs), + ResXmlns = maps:get(<<"xmlns">>, SubAttrs), binary:longest_common_prefix([ProperResFrom, ResFrom]) == byte_size(ProperResFrom) andalso ReqID == ResID diff --git a/src/escalus_pubsub_stanza.erl b/src/escalus_pubsub_stanza.erl index c92aad94..bd8bbe8c 100644 --- a/src/escalus_pubsub_stanza.erl +++ b/src/escalus_pubsub_stanza.erl @@ -59,10 +59,10 @@ -spec discover_nodes(escalus_utils:jid_spec(), binary(), binary() | pubsub_node_id()) -> exml:element(). discover_nodes(User, Id, {NodeAddr, NodeName}) -> - QueryElement = escalus_stanza:query_el(?NS_DISCO_ITEMS, [{<<"node">>, NodeName}], []), + QueryElement = escalus_stanza:query_el(?NS_DISCO_ITEMS, #{<<"node">> => NodeName}, []), iq(<<"get">>, User, Id, NodeAddr, [QueryElement]); discover_nodes(User, Id, NodeAddr) -> - QueryElement = escalus_stanza:query_el(?NS_DISCO_ITEMS, [], []), + QueryElement = escalus_stanza:query_el(?NS_DISCO_ITEMS, #{}, []), iq(<<"get">>, User, Id, NodeAddr, [QueryElement]). %% ---------------- create & delete ---------------- @@ -86,8 +86,8 @@ delete_node(User, Id, {NodeAddr, NodeName}) -> -spec get_configuration(escalus_utils:jid_spec(), binary(), pubsub_node_id()) -> exml:element(). get_configuration(User, Id, {NodeAddr, NodeName}) -> - Elements = [#xmlel{ name = <<"configure">>, - attrs = [{<<"node">>, NodeName}] }], + Elements = [#xmlel{name = <<"configure">>, + attrs = #{<<"node">> => NodeName}}], pubsub_owner_iq(<<"get">>, User, Id, NodeAddr, Elements). -spec set_configuration(escalus_utils:jid_spec(), binary(), @@ -107,20 +107,20 @@ get_default_configuration(User, Id, NodeAddr) -> -spec get_affiliations(escalus_utils:jid_spec(), binary(), pubsub_node_id()) -> exml:element(). get_affiliations(User, Id, {NodeAddr, NodeName}) -> - Elements = [#xmlel{ name = <<"affiliations">>, - attrs = [{<<"node">>, NodeName}] }], + Elements = [#xmlel{name = <<"affiliations">>, + attrs = #{<<"node">> => NodeName}}], pubsub_owner_iq(<<"get">>, User, Id, NodeAddr, Elements). -spec set_affiliations(escalus_utils:jid_spec(), binary(), pubsub_node_id(), [{escalus_utils:jid_spec(), binary()}]) -> exml:element(). set_affiliations(User, Id, {NodeAddr, NodeName}, AffChange) -> - AffList = [ #xmlel{ name = <<"affiliation">>, - attrs = [{<<"jid">>, escalus_utils:get_short_jid(U)}, - {<<"affiliation">>, A}] } + AffList = [ #xmlel{name = <<"affiliation">>, + attrs = #{<<"jid">> => escalus_utils:get_short_jid(U), + <<"affiliation">> => A}} || {U, A} <- AffChange ], - Affiliations = #xmlel{ name = <<"affiliations">>, attrs = [{<<"node">>, NodeName}], - children = AffList }, + Affiliations = #xmlel{name = <<"affiliations">>, attrs = #{<<"node">> => NodeName}, + children = AffList}, pubsub_owner_iq(<<"set">>, User, Id, NodeAddr, [Affiliations]). %% ---------------- subscriptions ---------------- @@ -146,7 +146,7 @@ submit_subscription_response(User, Id, {NodeAddr, _NodeName}, Form) -> Fields = [ encode_form_field(F) || F <- Form ], XEl = escalus_stanza:x_data_form(<<"submit">>, Fields), Msg = #xmlel{ name = <<"message">>, - attrs = [{<<"to">>, NodeAddr}, {<<"id">>, Id}], + attrs = #{<<"to">> => NodeAddr, <<"id">> => Id}, children = [XEl] }, escalus_stanza:from(Msg, escalus_utils:get_jid(User)). @@ -320,31 +320,31 @@ optional_form(FormName, NodeName, Type, Fields) -> %% Elements create_node_element(NodeName) -> - #xmlel{name = <<"create">>, attrs = [{<<"node">>, NodeName}]}. + #xmlel{name = <<"create">>, attrs = #{<<"node">> => NodeName}}. pubsub_element(Children, NS) -> #xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, NS}], + attrs = #{<<"xmlns">> => NS}, children = Children}. delete_element(NodeName) -> #xmlel{name = <<"delete">>, - attrs = [{<<"node">>, NodeName}]}. + attrs = #{<<"node">> => NodeName}}. subscribe_element(NodeName, User) -> #xmlel{name = <<"subscribe">>, - attrs = [{<<"node">>, NodeName}, - {<<"jid">>, escalus_utils:get_jid(User)}]}. + attrs = #{<<"node">> => NodeName, + <<"jid">> => escalus_utils:get_jid(User)}}. unsubscribe_element(NodeName, User) -> #xmlel{name = <<"unsubscribe">>, - attrs = [{<<"node">>, NodeName}, - {<<"jid">>, escalus_utils:get_jid(User)}]}. + attrs = #{<<"node">> => NodeName, + <<"jid">> => escalus_utils:get_jid(User)}}. publish_element(NodeName, Item) -> #xmlel{name = <<"publish">>, - attrs = [{<<"node">>, NodeName}], - children = skip_undefined([Item])}. + attrs = #{<<"node">> => NodeName}, + children = maybe_children([Item])}. publish_options_element(Fields) -> #xmlel{name = <<"publish-options">>, @@ -358,63 +358,63 @@ x_data_fields(Fields) -> form_type_field() -> [#xmlel{name = <<"field">>, - attrs = [{<<"var">>, <<"FORM_TYPE">>}, {<<"type">>, <<"hidden">>}], + attrs = #{<<"var">> => <<"FORM_TYPE">>, <<"type">> => <<"hidden">>}, children = [#xmlel{name = <<"value">>, - children = [{xmlcdata, ?NS_PUBSUB_PUBLISH_OPTIONS}]}]}]. + children = [#xmlcdata{content = ?NS_PUBSUB_PUBLISH_OPTIONS}]}]}]. items_element(NodeName) -> #xmlel{name = <<"items">>, - attrs = [{<<"node">>, NodeName}]}. + attrs = #{<<"node">> => NodeName}}. items_element(NodeName, MaxItems) -> #xmlel{name = <<"items">>, - attrs = [{<<"node">>, NodeName}, - {<<"max_items">>, integer_to_binary(MaxItems)}]}. + attrs = #{<<"node">> => NodeName, + <<"max_items">> => integer_to_binary(MaxItems)}}. item_element(ContentElement) -> #xmlel{name = <<"item">>, - children = skip_undefined([ContentElement])}. + children = maybe_children([ContentElement])}. item_element(ItemId, ContentElement) -> #xmlel{name = <<"item">>, - attrs = [{<<"id">>, ItemId}], - children = skip_undefined([ContentElement])}. + attrs = #{<<"id">> => ItemId}, + children = maybe_children([ContentElement])}. retract_item(NodeName, ItemId) -> #xmlel{name = <<"retract">>, - attrs = [{<<"node">>, NodeName}], - children = [#xmlel{ name = <<"item">>, - attrs = [{<<"id">>, ItemId}] }]}. + attrs = #{<<"node">> => NodeName}, + children = [#xmlel{name = <<"item">>, + attrs = #{<<"id">> => ItemId} }]}. purge_element(NodeName) -> #xmlel{name = <<"purge">>, - attrs = [{<<"node">>, NodeName}]}. + attrs = #{<<"node">> => NodeName}}. subscriptions_element() -> #xmlel{name = <<"subscriptions">>}. subscriptions_element(NodeName, Children) -> #xmlel{name = <<"subscriptions">>, - attrs = [{<<"node">>, NodeName}], + attrs = #{<<"node">> => NodeName}, children = Children}. subscription_element(User, SubscriptionState) -> #xmlel{name = <<"subscription">>, - attrs = [{<<"jid">>, escalus_utils:get_jid(User)}, - {<<"subscription">>, SubscriptionState}]}. + attrs = #{<<"jid">> => escalus_utils:get_jid(User), + <<"subscription">> => SubscriptionState}}. subscription_options(NodeName, User) -> #xmlel{name = <<"options">>, - attrs = [{<<"node">>, NodeName}, - {<<"jid">>, escalus_utils:get_jid(User)}]}. + attrs = #{<<"node">> => NodeName, + <<"jid">> => escalus_utils:get_jid(User)}}. set_subscription_options_form(NodeName, User, Children) -> #xmlel{name = <<"options">>, - attrs = [{<<"node">>, NodeName}, - {<<"jid">>, escalus_utils:get_jid(User)}], + attrs = #{<<"node">> => NodeName, + <<"jid">> => escalus_utils:get_jid(User)}, children = [#xmlel{name = <<"x">>, - attrs = [{<<"xmlns">>, <<"jabber:x:data">>}, - {<<"type">>, <<"submit">>}], + attrs = #{<<"xmlns">> => <<"jabber:x:data">>, + <<"type">> => <<"submit">>}, children = Children}]}. default_element() -> @@ -422,18 +422,18 @@ default_element() -> form_element(FormName, NodeName, FieldElements) -> #xmlel{name = FormName, - attrs = skip_undefined([{<<"node">>, NodeName}]), + attrs = skip_undefined(#{<<"node">> => NodeName}), children = [#xmlel{name = <<"x">>, - attrs = [{<<"xmlns">>, <<"jabber:x:data">>}, - {<<"type">>, <<"submit">>}], + attrs = #{<<"xmlns">> => <<"jabber:x:data">>, + <<"type">> => <<"submit">>}, children = FieldElements} ]}. form_type_field_element(FormType) -> Content = << <<"http://jabber.org/protocol/pubsub#">>/binary, FormType/binary >>, #xmlel{name = <<"field">>, - attrs = [{<<"var">>, <<"FORM_TYPE">>}, - {<<"type">>, <<"hidden">>}], + attrs = #{<<"var">> => <<"FORM_TYPE">>, + <<"type">> => <<"hidden">>}, children = [#xmlel{name = <<"value">>, children = [#xmlcdata{content = Content}]}]}. @@ -447,12 +447,16 @@ encode_form_field({Var, _Type, Value}) -> encode_form_field(Var, Values) -> Children = [ #xmlel{name = <<"value">>, children = [#xmlcdata{content = Content}]} || Content <- Values ], - #xmlel{name = <<"field">>, attrs = [{<<"var">>, Var}], children = Children}. + #xmlel{name = <<"field">>, attrs = #{<<"var">> => Var}, children = Children}. %% Helpers -skip_undefined(L) -> +maybe_children(L) -> lists:filter(fun(undefined) -> false; ({_, undefined}) -> false; (_) -> true end, L). + + +skip_undefined(L) -> + maps:filter(fun(_, Val) -> undefined =/= Val end, L). diff --git a/src/escalus_session.erl b/src/escalus_session.erl index 90d52479..09a67286 100644 --- a/src/escalus_session.erl +++ b/src/escalus_session.erl @@ -334,11 +334,11 @@ get_sasl_mechanisms(Features) -> exml_query:paths(Features, [{element, <<"mechanisms">>}, {element, <<"mechanism">>}, cdata]). --spec get_server_caps(exml:element()) -> map(). +-spec get_server_caps(exml:element()) -> undefined | map(). get_server_caps(Features) -> case exml_query:subelement(Features, <<"c">>) of #xmlel{attrs = Attrs} -> - maps:from_list(Attrs); + Attrs; _ -> undefined end. diff --git a/src/escalus_stanza.erl b/src/escalus_stanza.erl index 0f9c53f0..ce6b358b 100644 --- a/src/escalus_stanza.erl +++ b/src/escalus_stanza.erl @@ -150,60 +150,59 @@ stream_start(Server, XMLNS) -> #xmlstreamstart{name = <<"stream:stream">>, - attrs = [{<<"to">>, Server}, - {<<"version">>, <<"1.0">>}, - {<<"xml:lang">>, <<"en">>}, - {<<"xmlns">>, XMLNS}, - {<<"xmlns:stream">>, - <<"http://etherx.jabber.org/streams">>}]}. + attrs = #{<<"to">> => Server, + <<"version">> => <<"1.0">>, + <<"xml:lang">> => <<"en">>, + <<"xmlns">> => XMLNS, + <<"xmlns:stream">> => <<"http://etherx.jabber.org/streams">>}}. stream_end() -> #xmlstreamend{name = <<"stream:stream">>}. ws_open(Server) -> - #xmlel{name= <<"open">>, attrs = [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-framing">>}, - {<<"to">>, Server}, - {<<"version">>,<<"1.0">>}]}. + #xmlel{name= <<"open">>, + attrs = #{<<"xmlns">> => <<"urn:ietf:params:xml:ns:xmpp-framing">>, + <<"to">> => Server, + <<"version">> => <<"1.0">>}}. ws_close()-> - #xmlel{name= <<"close">>, attrs = [ {<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-framing">>} ]}. + #xmlel{name= <<"close">>, + attrs = #{<<"xmlns">> => <<"urn:ietf:params:xml:ns:xmpp-framing">>}}. starttls() -> #xmlel{name = <<"starttls">>, - attrs = [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-tls">>}]}. + attrs = #{<<"xmlns">> => <<"urn:ietf:params:xml:ns:xmpp-tls">>}}. compress(Method) -> #xmlel{name = <<"compress">>, - attrs = [{<<"xmlns">>, <<"http://jabber.org/protocol/compress">>}], + attrs = #{<<"xmlns">> => <<"http://jabber.org/protocol/compress">>}, children = [#xmlel{name = <<"method">>, children = [#xmlcdata{content = Method}]}]}. -spec iq(binary(), [exml:element()]) -> exml:element(). iq(Type, Body) -> #xmlel{name = <<"iq">>, - attrs = [{<<"type">>, Type}, - {<<"id">>, id()}], + attrs = #{<<"type">> => Type, <<"id">> => id()}, children = Body}. iq(To, Type, Body) -> IQ = iq(Type, Body), - IQ#xmlel{attrs = [{<<"to">>, To} | IQ#xmlel.attrs]}. + IQ#xmlel{attrs = maps:put(<<"to">>, To, IQ#xmlel.attrs)}. %% slightly naughty, this isn't a stanza but it will go inside an query_el(NS, Children) -> - query_el(NS, [], Children). + query_el(NS, #{}, Children). query_el(NS, Attrs, Children) -> #xmlel{name = <<"query">>, - attrs = [{<<"xmlns">>, NS} | Attrs], + attrs = maps:put(<<"xmlns">>, NS, Attrs), children = Children}. %% http://xmpp.org/extensions/xep-0004.html %% slightly naughty - this isn't a stanza but can be a child of various stanza types x_data_form(Type, Children) -> #xmlel{name = <<"x">>, - attrs = [{<<"xmlns">>,?NS_DATA_FORMS}, - {<<"type">>, Type}], + attrs = #{<<"xmlns">> => ?NS_DATA_FORMS, <<"type">> => Type}, children = Children}. -spec bind(binary()) -> exml:element(). @@ -215,14 +214,14 @@ bind(Resource) -> end, iq(<<"set">>, [#xmlel{name = <<"bind">>, - attrs = [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-bind">>}], + attrs = #{<<"xmlns">> => <<"urn:ietf:params:xml:ns:xmpp-bind">>}, children = Children}]). -spec session() -> exml:element(). session() -> NS = <<"urn:ietf:params:xml:ns:xmpp-session">>, iq(<<"set">>, [#xmlel{name = <<"session">>, - attrs = [{<<"xmlns">>, NS}]}]). + attrs = #{<<"xmlns">> => NS}}]). to(Stanza, Recipient) when is_binary(Recipient) -> setattr(Stanza, <<"to">>, Recipient); @@ -238,7 +237,7 @@ set_id(Stanza, ID) -> setattr(Stanza, <<"id">>, ID). setattr(Stanza, Key, Val) -> - NewAttrs = lists:keystore(Key, 1, Stanza#xmlel.attrs, {Key, Val}), + NewAttrs = maps:put(Key, Val, Stanza#xmlel.attrs), Stanza#xmlel{attrs = NewAttrs}. tags(KVs) -> @@ -253,7 +252,7 @@ presence(<<"available">>, Children) -> #xmlel{name = <<"presence">>, children = Children}; presence(Type, Children) -> #xmlel{name = <<"presence">>, - attrs = [{<<"type">>, bin(Type)}], + attrs = #{<<"type">> => bin(Type)}, children = Children}. presence_direct(Recipient, Type) -> @@ -284,9 +283,9 @@ presence_show(Show) -> error_element(Type, Condition) -> #xmlel{name = <<"error">>, - attrs = [{<<"type">>, Type}], + attrs = #{<<"type">> => Type}, children = [#xmlel{name = Condition, - attrs = [{<<"xmlns">>, ?NS_STANZA_ERRORS}]}]}. + attrs = #{<<"xmlns">> => ?NS_STANZA_ERRORS}}]}. -spec message(From, Recipient, Type, Msg) -> exml:element() when From :: undefined | binary(), @@ -356,26 +355,22 @@ chat_without_carbon_to(Recipient, Msg) -> Stanza = #xmlel{children = Children} = chat_to(Recipient, Msg), Stanza#xmlel{children = Children ++ [#xmlel{name = <<"private">>, - attrs = [{<<"xmlns">>, ?NS_CARBONS_2}]}]}. + attrs = #{<<"xmlns">> => ?NS_CARBONS_2}}]}. -receipt_req(#xmlel{ name = <<"message">>, - attrs = Attrs, - children = Children } = Msg) -> +receipt_req(#xmlel{name = <<"message">>, attrs = Attrs, children = Children } = Msg) -> ReqStanza = receipt_req_elem(), - Msg2 = case lists:keysearch(<<"id">>, 1, Attrs) of - {value, _} -> + Msg2 = case maps:find(<<"id">>, Attrs) of + {ok, _} -> Msg; - _ -> - Msg#xmlel{ attrs = [{<<"id">>, id()} | Attrs] } + error -> + Msg#xmlel{attrs = maps:put(<<"id">>, id(), Attrs)} end, Msg2#xmlel{ children = [ReqStanza | Children] }. -receipt_conf(#xmlel{ attrs = Attrs, children = Children }) -> - {value, {_, ID}} = lists:keysearch(<<"id">>, 1, Attrs), - {value, {_, From}} = lists:keysearch(<<"from">>, 1, Attrs), - Type = case lists:keyfind(<<"type">>, 1, Attrs) of - false -> <<"chat">>; - {_, Type0} -> Type0 +receipt_conf(#xmlel{attrs = #{<<"id">> := ID, <<"from">> := From} = Attrs, children = Children}) -> + Type = case maps:find(<<"type">>, Attrs) of + error -> <<"chat">>; + {ok, Type0} -> Type0 end, To = case lists:keyfind(<<"received">>, #xmlel.name, Children) of #xmlel{ name = <<"received">> } -> @@ -392,21 +387,21 @@ receipt_conf(#xmlel{ attrs = Attrs, children = Children }) -> end end, #xmlel{ name = <<"message">>, - attrs = [{<<"to">>, To}, {<<"id">>, id()}, {<<"type">>, Type}], + attrs = #{<<"to">> => To, <<"id">> => id(), <<"type">> => Type}, children = [receipt_conf_elem(ID)] }. receipt_req_elem() -> #xmlel{ name = <<"request">>, - attrs = [{<<"xmlns">>, ?NS_RECEIPTS}], + attrs = #{<<"xmlns">> => ?NS_RECEIPTS}, children = [] }. receipt_conf_elem(ID) -> #xmlel{ name = <<"received">>, - attrs = [{<<"xmlns">>, ?NS_RECEIPTS}, {<<"id">>, ID}], + attrs = #{<<"xmlns">> => ?NS_RECEIPTS, <<"id">> => ID}, children = [] }. @@ -415,16 +410,16 @@ groupchat_to(Recipient, Msg) -> get_registration_fields() -> iq(<<"get">>, [#xmlel{name = <<"query">>, - attrs = [{<<"xmlns">>, <<"jabber:iq:register">>}]}]). + attrs = #{<<"xmlns">> => <<"jabber:iq:register">>}}]). register_account(Body) -> iq(<<"set">>, [#xmlel{name = <<"query">>, - attrs = [{<<"xmlns">>, <<"jabber:iq:register">>}], + attrs = #{<<"xmlns">> => <<"jabber:iq:register">>}, children = Body}]). remove_account() -> iq(<<"set">>, [#xmlel{name = <<"query">>, - attrs = [{<<"xmlns">>, <<"jabber:iq:register">>}], + attrs = #{<<"xmlns">> => <<"jabber:iq:register">>}, children = [#xmlel{name = <<"remove">>}]}]). iq_result(Request) -> @@ -433,14 +428,13 @@ iq_result(Request) -> iq_result(Request, Payload) -> ToAttr = case exml_query:attr(Request, <<"from">>) of undefined -> - []; + #{}; Jid -> - [{<<"to">>, Jid}] + #{<<"to">> => Jid} end, Id = exml_query:attr(Request, <<"id">>), - Attrs = ToAttr ++ [{<<"id">>, Id}, {<<"type">>, <<"result">>}], #xmlel{name = <<"iq">>, - attrs = Attrs, + attrs = ToAttr#{<<"id">> => Id, <<"type">> => <<"result">>}, children = Payload}. iq_get(NS, Payload) -> @@ -455,14 +449,14 @@ iq_set_nonquery(NS, Payload) -> iq_with_type(Type, NS, Payload) -> iq(Type, [#xmlel{name = <<"query">>, - attrs = [{<<"xmlns">>, NS}], + attrs = #{<<"xmlns">> => NS}, children = Payload}]). iq_with_type(Type, NS, Payload, nonquery) -> #xmlel{name = <<"iq">>, - attrs = [{<<"xmlns">>, NS}, - {<<"type">>, Type}, - {<<"id">>, id()}], + attrs = #{<<"xmlns">> => NS, + <<"type">> => Type, + <<"id">> => id()}, children = Payload}. roster_get() -> @@ -470,7 +464,7 @@ roster_get() -> roster_get(Ver) -> #xmlel{children = [Query]} = Stanza = iq_get(?NS_ROSTER, []), - NewQuery = Query#xmlel{attrs = [{<<"ver">>, Ver} | Query#xmlel.attrs]}, + NewQuery = Query#xmlel{attrs = maps:put(<<"ver">>, Ver, Query#xmlel.attrs)}, Stanza#xmlel{children = [NewQuery]}. roster_add_contacts(ItemSpecs) -> @@ -481,9 +475,8 @@ roster_add_contacts(ItemSpecs) -> %% whether to use bare or full jid. contact_item({User, Groups, Nick}) -> #xmlel{name = <<"item">>, - attrs = [%% XXX - {<<"jid">>, escalus_utils:get_short_jid(User)}, - {<<"name">>, bin(Nick)}], + attrs = #{<<"jid">> => escalus_utils:get_short_jid(User), + <<"name">> => bin(Nick)}, children = [#xmlel{name = <<"group">>, children = [#xmlcdata{content = bin(Group)}]} || Group <- Groups]}. @@ -495,16 +488,15 @@ roster_add_contact(User, Groups, Nick) -> roster_remove_contact(User) -> iq_set(?NS_ROSTER, [#xmlel{name = <<"item">>, - attrs = [%% XXX - {<<"jid">>, escalus_utils:get_short_jid(User)}, - {<<"subscription">>, <<"remove">>}]}]). + attrs = #{<<"jid">> => escalus_utils:get_short_jid(User), + <<"subscription">> => <<"remove">>}}]). private_set(Element) -> iq_set(?NS_PRIVATE, [Element]). private_get(NS, Name) -> Element = #xmlel{name = bin(Name), - attrs = [{<<"xmlns">>, bin(NS)}]}, + attrs = #{<<"xmlns">> => bin(NS)}}, iq_get(?NS_PRIVATE, [Element]). last_activity(User) -> @@ -515,23 +507,23 @@ privacy_get_all() -> privacy_get_lists(ListNames) -> iq_get(?NS_PRIVACY, [#xmlel{name = <<"list">>, - attrs = [{<<"name">>, bin(Name)}]} + attrs = #{<<"name">> => bin(Name)}} || Name <- ListNames]). privacy_set_list(PrivacyList) -> iq_set(?NS_PRIVACY, [PrivacyList]). privacy_activate(ListName) -> - privacy_set(<<"active">>, [{<<"name">>, bin(ListName)}]). + privacy_set(<<"active">>, #{<<"name">> => bin(ListName)}). privacy_deactivate()-> - privacy_set(<<"active">>, []). + privacy_set(<<"active">>, #{}). privacy_set_default(ListName) -> - privacy_set(<<"default">>, [{<<"name">>, bin(ListName)}]). + privacy_set(<<"default">>, #{<<"name">> => bin(ListName)}). privacy_no_default()-> - privacy_set(<<"default">>, []). + privacy_set(<<"default">>, #{}). privacy_set(What, Attrs) -> iq_set(?NS_PRIVACY, [#xmlel{name = What, attrs = Attrs}]). @@ -539,21 +531,21 @@ privacy_set(What, Attrs) -> %% Create empty list element with given name. privacy_list(Name, Items) -> #xmlel{name = <<"list">>, - attrs = [{<<"name">>, Name}], + attrs = #{<<"name">> => Name}, children = Items}. privacy_list_item(Order, Action, Content) -> #xmlel{name = <<"item">>, - attrs = [{<<"order">>, Order}, - {<<"action">>, Action}], + attrs = #{<<"order">> => Order, + <<"action">> => Action}, children = [#xmlel{name = C} || C <- Content]}. privacy_list_item(Order, Action, Type, Value, Content) -> #xmlel{name = <<"item">>, - attrs = [{<<"order">>, Order}, - {<<"type">>, Type}, - {<<"value">>, Value}, - {<<"action">>, Action}], + attrs = #{<<"order">> => Order, + <<"type">> => Type, + <<"value">> => Value, + <<"action">> => Action}, children = [#xmlel{name = C} || C <- Content]}. privacy_list_jid_item(Order, Action, Who, Contents) -> @@ -565,14 +557,14 @@ disco_info(JID) -> iq(JID, <<"get">>, [Query]). disco_info(JID, Node) -> - Query = query_el(?NS_DISCO_INFO, [{<<"node">>, Node}], []), + Query = query_el(?NS_DISCO_INFO, #{<<"node">> => Node}, []), iq(JID, <<"get">>, [Query]). disco_items(JID) -> ItemsQuery = query_el(?NS_DISCO_ITEMS, []), iq(JID, <<"get">>, [ItemsQuery]). disco_items(JID, Node) -> - ItemsQuery = query_el(?NS_DISCO_ITEMS, [{<<"node">>, Node}], []), + ItemsQuery = query_el(?NS_DISCO_ITEMS, #{<<"node">> => Node}, []), iq(JID, <<"get">>, [ItemsQuery]). search_fields([]) -> @@ -581,9 +573,9 @@ search_fields([null|Rest]) -> [#xmlel{name = <<"field">>} | search_fields(Rest)]; search_fields([{Key, Val}|Rest]) -> [#xmlel{name = <<"field">>, - attrs = [{<<"var">>, Key}], + attrs = #{<<"var">> => Key}, children = [#xmlel{name = <<"value">>, - children = [{xmlcdata, Val}]}]} + children = [#xmlcdata{content = Val}]}]} | search_fields(Rest)]. search_fields_iq(JID) -> @@ -611,18 +603,14 @@ vcard([{_,_}|_] = Tuples) -> vcard(tuples_to_fields(Tuples)); vcard(Body) -> #xmlel{name = <<"vCard">>, - attrs = [{<<"xmlns">>,<<"vcard-temp">>}], + attrs = #{<<"xmlns">> => <<"vcard-temp">>}, children = Body}. cdata_field(Name, Value) -> - #xmlel{name = Name, - attrs = [], - children = [{xmlcdata, Value}]}. + #xmlel{name = Name, children = [#xmlcdata{content = Value}]}. field(Name, Children) -> - #xmlel{name = Name, - attrs = [], - children = Children}. + #xmlel{name = Name, children = Children}. tuples_to_fields([]) -> []; @@ -637,14 +625,14 @@ adhoc_request(Node) -> adhoc_request(Node, Payload) -> iq(<<"set">>, [#xmlel{name = <<"command">>, - attrs = [{<<"xmlns">>, ?NS_ADHOC}, - {<<"node">>, Node}, - {<<"action">>, <<"execute">>}], + attrs = #{<<"xmlns">> => ?NS_ADHOC, + <<"node">> => Node, + <<"action">> => <<"execute">>}, children = Payload}]). ping_request(To) -> IQ = iq(<<"get">>, [#xmlel{name = <<"ping">>, - attrs = [{<<"xmlns">>, ?NS_PING}] + attrs = #{<<"xmlns">> => ?NS_PING} }]), to(IQ, To). @@ -661,8 +649,8 @@ auth(Mechanism) -> -spec auth(binary(), [#xmlcdata{}]) -> #xmlel{}. auth(Mechanism, Children) -> #xmlel{name = <<"auth">>, - attrs = [{<<"xmlns">>, ?NS_SASL}, - {<<"mechanism">>, Mechanism}], + attrs = #{<<"xmlns">> => ?NS_SASL, + <<"mechanism">> => Mechanism}, children = Children}. auth_response() -> @@ -670,33 +658,36 @@ auth_response() -> auth_response(Children) -> #xmlel{name = <<"response">>, - attrs = [{<<"xmlns">>, ?NS_SASL}], + attrs = #{<<"xmlns">> => ?NS_SASL}, children = Children}. enable_sm() -> #xmlel{name = <<"enable">>, - attrs = [{<<"xmlns">>, ?NS_STREAM_MGNT_3}]}. + attrs = #{<<"xmlns">> => ?NS_STREAM_MGNT_3}}. enable_sm(Opts) -> - #xmlel{name = <<"enable">>, - attrs = [{<<"xmlns">>, ?NS_STREAM_MGNT_3}] - ++ [{<<"resume">>, <<"true">>} - || true == proplists:is_defined(resume, Opts)]}. + case proplists:is_defined(resume, Opts) of + true -> + #xmlel{name = <<"enable">>, + attrs = #{<<"xmlns">> => ?NS_STREAM_MGNT_3, <<"resume">> => <<"true">>}}; + false -> + enable_sm() + end. sm_request() -> #xmlel{name = <<"r">>, - attrs = [{<<"xmlns">>, ?NS_STREAM_MGNT_3}]}. + attrs = #{<<"xmlns">> => ?NS_STREAM_MGNT_3}}. sm_ack(H) -> #xmlel{name = <<"a">>, - attrs = [{<<"xmlns">>, ?NS_STREAM_MGNT_3}, - {<<"h">>, integer_to_binary(H)}]}. + attrs = #{<<"xmlns">> => ?NS_STREAM_MGNT_3, + <<"h">> => integer_to_binary(H)}}. resume(SMID, PrevH) -> #xmlel{name = <<"resume">>, - attrs = [{<<"xmlns">>, ?NS_STREAM_MGNT_3}, - {<<"previd">>, SMID}, - {<<"h">>, integer_to_binary(PrevH)}]}. + attrs = #{<<"xmlns">> => ?NS_STREAM_MGNT_3, + <<"previd">> => SMID, + <<"h">> => integer_to_binary(PrevH)}}. %% XEP-0313 Mam @@ -713,9 +704,8 @@ field_el(Name, Type, Values) when is_list(Values) -> children = [#xmlcdata{content = E}]} end, Values), #xmlel{name = <<"field">>, - attrs = [{<<"type">>, Type}, - {<<"var">>, Name}], - children = Fields }; + attrs = #{<<"type">> => Type, <<"var">> => Name}, + children = Fields}; field_el(Name, Type, Value) -> field_el(Name, Type, [Value]). @@ -730,7 +720,7 @@ mam_archive_query(QueryId, Children) -> ChildEl = case length(DefChilds) > 1 of true -> [#xmlel{name = <<"x">>, - attrs = [{<<"xmlns">>, <<"jabberd:x:data">>}], + attrs = #{<<"xmlns">> => <<"jabberd:x:data">>}, children = DefChilds}]; false -> %% no need to create form element @@ -741,7 +731,7 @@ mam_archive_query(QueryId, Children) -> <<"set">>, [#xmlel{ name = <<"query">>, - attrs = [mam_ns_attr(), {<<"queryid">>, QueryId}], + attrs = #{<<"xmlns">> => ?NS_MAM, <<"queryid">> => QueryId}, children = ChildEl}]). @@ -786,7 +776,7 @@ defined(L) when is_list(L) -> [ El || El <- L, El /= undefined ]. rsm_after_or_before({Direction, AbstractID, MaxCount}) -> #xmlel{name = <<"set">>, - attrs = [{<<"xmlns">>, ?NS_RSM}], + attrs = #{<<"xmlns">> => ?NS_RSM}, children = defined([max(MaxCount), direction_el(Direction, AbstractID) ])}. direction_el('after', AbstractID) when is_binary(AbstractID) -> @@ -804,8 +794,6 @@ max(N) when is_integer(N) -> max(_) -> undefined. -mam_ns_attr() -> {<<"xmlns">>,?NS_MAM}. - %% XEP-0280 Carbons %% @@ -817,11 +805,11 @@ carbons_disable() -> disable_carbons_el() -> #xmlel{name = <<"disable">>, - attrs = [{<<"xmlns">>, ?NS_CARBONS_2}]}. + attrs = #{<<"xmlns">> => ?NS_CARBONS_2}}. enable_carbons_el() -> #xmlel{name = <<"enable">>, - attrs = [{<<"xmlns">>, ?NS_CARBONS_2}]}. + attrs = #{<<"xmlns">> => ?NS_CARBONS_2}}. %% XEP-0333 Chat Markers %% @@ -832,18 +820,17 @@ markable(Message = #xmlel{name = <<"message">>, children = Children}) -> -spec chat_marker(escalus_utils:jid_spec(), binary(), binary()) -> exml:element(). chat_marker(To, MarkerName, MessageId) -> #xmlel{name = <<"message">>, - attrs = [{<<"to">>, escalus_utils:get_jid(To)}], + attrs = #{<<"to">> => escalus_utils:get_jid(To)}, children = [marker_el(MarkerName, MessageId)]}. markable_el() -> - #xmlel{name = <<"markable">>, attrs = [{<<"xmlns">>, ?NS_CHAT_MARKERS}]}. + #xmlel{name = <<"markable">>, attrs = #{<<"xmlns">> => ?NS_CHAT_MARKERS}}. marker_el(MarkerName, MessageId) when MarkerName =:= <<"received">> orelse MarkerName =:= <<"displayed">> orelse MarkerName =:= <<"acknowledged">>, is_binary(MessageId) -> - #xmlel{name = MarkerName, attrs = [{<<"xmlns">>, ?NS_CHAT_MARKERS}, - {<<"id">>, MessageId}]}. + #xmlel{name = MarkerName, attrs = #{<<"xmlns">> => ?NS_CHAT_MARKERS, <<"id">> => MessageId}}. -spec id() -> binary(). id() -> diff --git a/test/escalus_stanza_SUITE.erl b/test/escalus_stanza_SUITE.erl index 90fbae6a..fb848d7a 100644 --- a/test/escalus_stanza_SUITE.erl +++ b/test/escalus_stanza_SUITE.erl @@ -28,14 +28,14 @@ nullary_snippet_to_xmlel(_) -> unary_snippet_to_xmlel(_) -> M = escalus_stanza, ?eq(#xmlel{name = <<"el">>, - attrs = [{<<"attr">>, <<"value">>}]}, + attrs = #{<<"attr">> => <<"value">>}}, M:from_template("", [{val, "value"}])). type_matrix_accepted(_) -> M = escalus_stanza, Example = #xmlel{name = <<"el">>, - attrs = [{<<"attr">>, <<"value">>}]}, + attrs = #{<<"attr">> => <<"value">>}}, ?eq(Example, M:from_template("", [{val, "value"}])), ?eq(Example, M:from_template(<<"">>, [{val, "value"}])), ?eq(Example, M:from_template(<<"">>, [{val, <<"value">>}])), @@ -52,13 +52,13 @@ attribute_as_argument(_) -> M = escalus_stanza, Attr = {<<"name">>, <<"value">>}, Example = #xmlel{name = <<"el">>, - attrs = [Attr]}, + attrs = #{<<"name">> => <<"value">>}}, ?eq(Example, M:from_template("", [{attr, Attr}])). numbers_as_arguments(_) -> M = escalus_stanza, Example = #xmlel{name = <<"el">>, - attrs = [{<<"int">>, <<"666">>}, {<<"pi">>, <<"3.14">>}]}, + attrs = #{<<"int">> => <<"666">>, <<"pi">> => <<"3.14">>}}, ?eq(Example, M:from_template("", [{int, 666}, {pi, math:pi()}])).