diff --git a/include/xmpp_codec.hrl b/include/xmpp_codec.hrl index 635fcf3cb..845861948 100644 --- a/include/xmpp_codec.hrl +++ b/include/xmpp_codec.hrl @@ -564,7 +564,8 @@ max :: non_neg_integer()}). -type rsm_set() :: #rsm_set{}. --record(mam_fin, {id = <<>> :: binary(), +-record(mam_fin, {xmlns = <<>> :: binary(), + id = <<>> :: binary(), rsm :: #rsm_set{}, stable :: boolean(), complete :: boolean()}). diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index e658536ab..186f7e9a5 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -2663,7 +2663,7 @@ make_resume_id(StateData) -> add_resent_delay_info(_State, #iq{} = El, _Time) -> El; add_resent_delay_info(#state{server = From}, El, Time) -> - xmpp_util:add_delay_info(El, From, Time, <<"Resent">>). + xmpp_util:add_delay_info(El, jid:make(From), Time, <<"Resent">>). %%%---------------------------------------------------------------------- %%% XEP-0352 diff --git a/src/mod_announce.erl b/src/mod_announce.erl index d9209f418..8d2fbebff 100644 --- a/src/mod_announce.erl +++ b/src/mod_announce.erl @@ -130,34 +130,37 @@ stop(Host) -> {wait, Proc}. %% Announcing via messages to a custom resource --spec announce(jid(), jid(), stanza()) -> ok. +-spec announce(jid(), jid(), stanza()) -> ok | stop. announce(From, #jid{luser = <<>>} = To, #message{} = Packet) -> Proc = gen_mod:get_module_proc(To#jid.lserver, ?PROCNAME), - case To#jid.lresource of - <<"announce/all">> -> - Proc ! {announce_all, From, To, Packet}; - <<"announce/all-hosts/all">> -> - Proc ! {announce_all_hosts_all, From, To, Packet}; - <<"announce/online">> -> - Proc ! {announce_online, From, To, Packet}; - <<"announce/all-hosts/online">> -> - Proc ! {announce_all_hosts_online, From, To, Packet}; - <<"announce/motd">> -> - Proc ! {announce_motd, From, To, Packet}; - <<"announce/all-hosts/motd">> -> - Proc ! {announce_all_hosts_motd, From, To, Packet}; - <<"announce/motd/update">> -> - Proc ! {announce_motd_update, From, To, Packet}; - <<"announce/all-hosts/motd/update">> -> - Proc ! {announce_all_hosts_motd_update, From, To, Packet}; - <<"announce/motd/delete">> -> - Proc ! {announce_motd_delete, From, To, Packet}; - <<"announce/all-hosts/motd/delete">> -> - Proc ! {announce_all_hosts_motd_delete, From, To, Packet}; - _ -> - ok - end, - ok; + Res = case To#jid.lresource of + <<"announce/all">> -> + Proc ! {announce_all, From, To, Packet}; + <<"announce/all-hosts/all">> -> + Proc ! {announce_all_hosts_all, From, To, Packet}; + <<"announce/online">> -> + Proc ! {announce_online, From, To, Packet}; + <<"announce/all-hosts/online">> -> + Proc ! {announce_all_hosts_online, From, To, Packet}; + <<"announce/motd">> -> + Proc ! {announce_motd, From, To, Packet}; + <<"announce/all-hosts/motd">> -> + Proc ! {announce_all_hosts_motd, From, To, Packet}; + <<"announce/motd/update">> -> + Proc ! {announce_motd_update, From, To, Packet}; + <<"announce/all-hosts/motd/update">> -> + Proc ! {announce_all_hosts_motd_update, From, To, Packet}; + <<"announce/motd/delete">> -> + Proc ! {announce_motd_delete, From, To, Packet}; + <<"announce/all-hosts/motd/delete">> -> + Proc ! {announce_all_hosts_motd_delete, From, To, Packet}; + _ -> + ok + end, + case Res of + ok -> ok; + _ -> stop + end; announce(_From, _To, _Packet) -> ok. diff --git a/src/mod_blocking.erl b/src/mod_blocking.erl index 55e3ca151..b3bbff96e 100644 --- a/src/mod_blocking.erl +++ b/src/mod_blocking.erl @@ -74,39 +74,37 @@ process_iq(IQ) -> -spec process_iq_get({error, stanza_error()} | {result, xmpp_element() | undefined}, iq(), userlist()) -> - {error, stanza_error()} | {result, block_list()}. + {error, stanza_error()} | + {result, xmpp_element() | undefined}. process_iq_get(_, #iq{lang = Lang, from = From, sub_els = [#block_list{}]}, _) -> #jid{luser = LUser, lserver = LServer} = From, - {stop, process_blocklist_get(LUser, LServer, Lang)}; + process_blocklist_get(LUser, LServer, Lang); process_iq_get(Acc, _, _) -> Acc. -spec process_iq_set({error, stanza_error()} | {result, xmpp_element() | undefined} | {result, xmpp_element() | undefined, userlist()}, iq()) -> {error, stanza_error()} | - {result, undefined} | - {result, undefined, userlist()}. -process_iq_set(_, #iq{from = From, lang = Lang, sub_els = [SubEl]}) -> + {result, xmpp_element() | undefined} | + {result, xmpp_element() | undefined, userlist()}. +process_iq_set(Acc, #iq{from = From, lang = Lang, sub_els = [SubEl]}) -> #jid{luser = LUser, lserver = LServer} = From, - Res = case SubEl of - #block{items = []} -> - Txt = <<"No items found in this query">>, - {error, xmpp:err_bad_request(Txt, Lang)}; - #block{items = Items} -> - JIDs = [jid:tolower(Item) || Item <- Items], - process_blocklist_block(LUser, LServer, JIDs, Lang); - #unblock{items = []} -> - process_blocklist_unblock_all(LUser, LServer, Lang); - #unblock{items = Items} -> - JIDs = [jid:tolower(Item) || Item <- Items], - process_blocklist_unblock(LUser, LServer, JIDs, Lang); - _ -> - Txt = <<"Only and are allowed " - "in this request">>, - {error, xmpp:err_bad_request(Txt, Lang)} - end, - {stop, Res}; + case SubEl of + #block{items = []} -> + Txt = <<"No items found in this query">>, + {error, xmpp:err_bad_request(Txt, Lang)}; + #block{items = Items} -> + JIDs = [jid:tolower(Item) || Item <- Items], + process_blocklist_block(LUser, LServer, JIDs, Lang); + #unblock{items = []} -> + process_blocklist_unblock_all(LUser, LServer, Lang); + #unblock{items = Items} -> + JIDs = [jid:tolower(Item) || Item <- Items], + process_blocklist_unblock(LUser, LServer, JIDs, Lang); + _ -> + Acc + end; process_iq_set(Acc, _) -> Acc. -spec list_to_blocklist_jids([listitem()], [ljid()]) -> [ljid()]. diff --git a/src/mod_client_state.erl b/src/mod_client_state.erl index f72f334f3..7f0658eff 100644 --- a/src/mod_client_state.erl +++ b/src/mod_client_state.erl @@ -277,7 +277,7 @@ get_queue(C2SState) -> get_stanzas(Queue, Host) -> lists:map(fun({_Key, Time, Stanza}) -> - xmpp_util:add_delay_info(Stanza, Host, Time, + xmpp_util:add_delay_info(Stanza, jid:make(Host), Time, <<"Client Inactive">>) end, Queue). diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 2529b7389..ea267c1c0 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -834,6 +834,10 @@ msg_to_el(#archive_msg{timestamp = TS, packet = Pkt1, nick = Nick, peer = Peer}, #forwarded{sub_els = [Pkt2], delay = #delay{stamp = TS, from = jid:make(LServer)}}. +maybe_update_from_to(#xmlel{} = El, JidRequestor, JidArchive, Peer, + {groupchat, _, _} = MsgType, Nick) -> + Pkt = xmpp:decode(El, [ignore_els]), + maybe_update_from_to(Pkt, JidRequestor, JidArchive, Peer, MsgType, Nick); maybe_update_from_to(#message{sub_els = Els} = Pkt, JidRequestor, JidArchive, Peer, {groupchat, Role, #state{config = #config{anonymous = Anon}}}, @@ -908,7 +912,8 @@ send(Msgs, Count, IsComplete, Result = if NS == ?NS_MAM_TMP -> #mam_query{xmlns = NS, id = QID, rsm = RSMOut}; true -> - #mam_fin{id = QID, rsm = RSMOut, complete = IsComplete} + #mam_fin{xmlns = NS, id = QID, rsm = RSMOut, + complete = IsComplete} end, if NS == ?NS_MAM_TMP; NS == ?NS_MAM_1 -> lists:foreach( @@ -950,6 +955,8 @@ limit_max(#rsm_set{max = Max} = RSM, _NS) when Max > ?MAX_PAGE_SIZE -> limit_max(RSM, _NS) -> RSM. +match_interval(Now, Start, undefined) -> + Now >= Start; match_interval(Now, Start, End) -> (Now >= Start) and (Now =< End). diff --git a/src/mod_mam_mnesia.erl b/src/mod_mam_mnesia.erl index cbe7c336c..ecaa4d053 100644 --- a/src/mod_mam_mnesia.erl +++ b/src/mod_mam_mnesia.erl @@ -134,7 +134,10 @@ select(_LServer, JidRequestor, #jid{luser = LUser, lserver = LServer} = JidArchive, #mam_query{start = Start, 'end' = End, with = With, rsm = RSM}, MsgType) -> - MS = make_matchspec(LUser, LServer, Start, End, With), + LWith = if With /= undefined -> jid:tolower(With); + true -> undefined + end, + MS = make_matchspec(LUser, LServer, Start, End, LWith), Msgs = mnesia:dirty_select(archive_msg, MS), SortedMsgs = lists:keysort(#archive_msg.timestamp, Msgs), {FilteredMsgs, IsComplete} = filter_by_rsm(SortedMsgs, RSM), @@ -155,6 +158,9 @@ select(_LServer, JidRequestor, now_to_usec({MSec, Sec, USec}) -> (MSec*1000000 + Sec)*1000000 + USec. +make_matchspec(LUser, LServer, Start, undefined, With) -> + %% List is always greater than a tuple + make_matchspec(LUser, LServer, Start, [], With); make_matchspec(LUser, LServer, Start, End, {_, _, <<>>} = With) -> ets:fun2ms( fun(#archive_msg{timestamp = TS, diff --git a/src/mod_mix.erl b/src/mod_mix.erl index f39408210..7ca09f4db 100644 --- a/src/mod_mix.erl +++ b/src/mod_mix.erl @@ -209,19 +209,18 @@ do_route(_State, _From, _To, _Packet) -> subscribe_nodes(From, To, Nodes) -> LTo = jid:tolower(jid:remove_resource(To)), LFrom = jid:tolower(jid:remove_resource(From)), - From_s = jid:to_string(LFrom), lists:foldl( fun(_Node, {error, _} = Err) -> Err; (Node, {result, _}) -> - case mod_pubsub:subscribe_node(LTo, Node, From, From_s, []) of + case mod_pubsub:subscribe_node(LTo, Node, From, From, []) of {error, _} = Err -> case is_item_not_found(Err) of true -> case mod_pubsub:create_node( LTo, To#jid.lserver, Node, LFrom, <<"mix">>) of {result, _} -> - mod_pubsub:subscribe_node(LTo, Node, From, From_s, []); + mod_pubsub:subscribe_node(LTo, Node, From, From, []); Error -> Error end; @@ -235,13 +234,12 @@ subscribe_nodes(From, To, Nodes) -> unsubscribe_nodes(From, To, Nodes) -> LTo = jid:tolower(jid:remove_resource(To)), - LFrom = jid:tolower(jid:remove_resource(From)), - From_s = jid:to_string(LFrom), + BareFrom = jid:remove_resource(From), lists:foldl( fun(_Node, {error, _} = Err) -> Err; (Node, {result, _} = Result) -> - case mod_pubsub:unsubscribe_node(LTo, Node, From, From_s, <<"">>) of + case mod_pubsub:unsubscribe_node(LTo, Node, From, BareFrom, <<"">>) of {error, _} = Err -> case is_not_subscribed(Err) of true -> Result; @@ -297,19 +295,16 @@ delete_item(From, To, Node, ItemID) -> end end. -is_item_not_found({error, ErrEl}) -> - case fxml:get_subtag_with_xmlns( - ErrEl, <<"item-not-found">>, ?NS_STANZAS) of - #xmlel{} -> true; - _ -> false - end. +-spec is_item_not_found({error, stanza_error()}) -> boolean(). +is_item_not_found({error, #stanza_error{reason = 'item-not-found'}}) -> true; +is_item_not_found({error, _}) -> false. -is_not_subscribed({error, ErrEl}) -> - case fxml:get_subtag_with_xmlns( - ErrEl, <<"not-subscribed">>, ?NS_PUBSUB_ERRORS) of - #xmlel{} -> true; - _ -> false - end. +-spec is_not_subscribed({error, stanza_error()}) -> boolean(). +is_not_subscribed({error, #stanza_error{sub_els = Els}}) -> + %% TODO: make xmpp:get_els function working for any XMPP element + %% with sub_els field + xmpp:has_subtag(#message{sub_els = Els}, + #ps_error{type = 'not-subscribed'}). depends(_Host, _Opts) -> [{mod_pubsub, hard}]. diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 3eca79fec..66604394b 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -668,17 +668,17 @@ get_nick(ServerHost, Host, From) -> Mod:get_nick(LServer, Host, From). iq_get_register_info(ServerHost, Host, From, Lang) -> - {Nick, Registered} = case get_nick(ServerHost, Host, From) of - error -> {<<"">>, false}; - N -> {N, true} - end, + {Nick, NickVals, Registered} = case get_nick(ServerHost, Host, From) of + error -> {<<"">>, [], false}; + N -> {N, [N], true} + end, Title = <<(translate:translate( Lang, <<"Nickname Registration at ">>))/binary, Host/binary>>, Inst = translate:translate(Lang, <<"Enter nickname you want to register">>), Field = #xdata_field{type = 'text-single', label = translate:translate(Lang, <<"Nickname">>), var = <<"nick">>, - values = [Nick]}, + values = NickVals}, X = #xdata{type = form, title = Title, instructions = [Inst], fields = [Field]}, #register{nick = Nick, diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 509406aa4..a2bcec894 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -616,7 +616,7 @@ offline_msg_to_route(LServer, #offline_msg{} = R) -> undefined -> Pkt; TS -> - xmpp_util:add_delay_info(Pkt, LServer, TS, + xmpp_util:add_delay_info(Pkt, jid:make(LServer), TS, <<"Offline Storage">>) end, {route, R#offline_msg.from, R#offline_msg.to, Pkt1}. diff --git a/src/mod_privacy.erl b/src/mod_privacy.erl index 3be3f2d3b..2f318deec 100644 --- a/src/mod_privacy.erl +++ b/src/mod_privacy.erl @@ -101,7 +101,8 @@ process_iq(IQ) -> xmpp:make_error(IQ, xmpp:err_not_allowed()). -spec process_iq_get({error, stanza_error()} | {result, xmpp_element() | undefined}, - iq(), userlist()) -> {error, stanza_error()} | {result, privacy_query()}. + iq(), userlist()) -> {error, stanza_error()} | + {result, xmpp_element() | undefined}. process_iq_get(_, #iq{from = From, lang = Lang, sub_els = [#privacy_query{lists = Lists}]}, #userlist{name = Active}) -> @@ -114,7 +115,9 @@ process_iq_get(_, #iq{from = From, lang = Lang, _ -> Txt = <<"Too many elements">>, {error, xmpp:err_bad_request(Txt, Lang)} - end. + end; +process_iq_get(Acc, _, _) -> + Acc. -spec process_lists_get(binary(), binary(), binary(), binary()) -> {error, stanza_error()} | {result, privacy_query()}. @@ -218,7 +221,8 @@ decode_value(Type, Value) -> {result, xmpp_element() | undefined} | {result, xmpp_element() | undefined, userlist()}, iq()) -> {error, stanza_error()} | - {result, undefined, userlist()}. + {result, xmpp_element() | undefined} | + {result, xmpp_element() | undefined, userlist()}. process_iq_set(_, #iq{from = From, lang = Lang, sub_els = [#privacy_query{default = Default, active = Active, @@ -236,7 +240,9 @@ process_iq_set(_, #iq{from = From, lang = Lang, Txt = <<"There should be exactly one element in this query: " ", or ">>, {error, xmpp:err_bad_request(Txt, Lang)} - end. + end; +process_iq_set(Acc, _) -> + Acc. -spec process_default_set(binary(), binary(), none | binary(), binary()) -> {error, stanza_error()} | {result, undefined}. diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index b470d83d9..f7e1a9834 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -69,9 +69,7 @@ tree_action/3, node_action/4, node_call/4]). %% general helpers for plugins --export([subscription_to_string/1, affiliation_to_string/1, - string_to_subscription/1, string_to_affiliation/1, - extended_error/2, service_jid/1, +-export([extended_error/2, service_jid/1, tree/1, tree/2, plugin/2, plugins/1, config/3, host/1, serverhost/1]). @@ -2170,7 +2168,7 @@ get_items(Host, Node, From, SubId, SMaxItems, ItemIds, RSM) -> get_items(Host, Node) -> Action = fun (#pubsub_node{type = Type, id = Nidx}) -> - node_call(Host, Type, get_items, [Nidx, service_jid(Host), none]) + node_call(Host, Type, get_items, [Nidx, service_jid(Host), undefined]) end, case transaction(Host, Node, Action, sync_dirty) of {result, {_, {Items, _}}} -> Items; @@ -2187,7 +2185,7 @@ get_item(Host, Node, ItemId) -> end. get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) -> - case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners, none) of + case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners, undefined) of {result, {Items, _RSM}} -> {result, Items}; Error -> Error end. @@ -2203,7 +2201,7 @@ get_last_item(Host, Type, Nidx, LJID) -> LastItem -> LastItem end. get_last_item(Host, Type, Nidx, LJID, mnesia) -> - case node_action(Host, Type, get_items, [Nidx, LJID, none]) of + case node_action(Host, Type, get_items, [Nidx, LJID, undefined]) of {result, {[LastItem|_], _}} -> LastItem; _ -> undefined end; @@ -2218,7 +2216,7 @@ get_last_item(_Host, _Type, _Nidx, _LJID, _) -> get_last_items(Host, Type, Nidx, LJID, Number) -> get_last_items(Host, Type, Nidx, LJID, Number, gen_mod:db_type(serverhost(Host), ?MODULE)). get_last_items(Host, Type, Nidx, LJID, Number, mnesia) -> - case node_action(Host, Type, get_items, [Nidx, LJID, none]) of + case node_action(Host, Type, get_items, [Nidx, LJID, undefined]) of {result, {Items, _}} -> lists:sublist(Items, Number); _ -> [] end; @@ -2714,32 +2712,6 @@ get_roster_info(OwnerUser, OwnerServer, {SubscriberUser, SubscriberServer, _}, A get_roster_info(OwnerUser, OwnerServer, JID, AllowedGroups) -> get_roster_info(OwnerUser, OwnerServer, jid:tolower(JID), AllowedGroups). -string_to_affiliation(<<"owner">>) -> owner; -string_to_affiliation(<<"publisher">>) -> publisher; -string_to_affiliation(<<"publish-only">>) -> publish_only; -string_to_affiliation(<<"member">>) -> member; -string_to_affiliation(<<"outcast">>) -> outcast; -string_to_affiliation(<<"none">>) -> none; -string_to_affiliation(_) -> false. - -string_to_subscription(<<"subscribed">>) -> subscribed; -string_to_subscription(<<"pending">>) -> pending; -string_to_subscription(<<"unconfigured">>) -> unconfigured; -string_to_subscription(<<"none">>) -> none; -string_to_subscription(_) -> false. - -affiliation_to_string(owner) -> <<"owner">>; -affiliation_to_string(publisher) -> <<"publisher">>; -affiliation_to_string(publish_only) -> <<"publish-only">>; -affiliation_to_string(member) -> <<"member">>; -affiliation_to_string(outcast) -> <<"outcast">>; -affiliation_to_string(_) -> <<"none">>. - -subscription_to_string(subscribed) -> <<"subscribed">>; -subscription_to_string(pending) -> <<"pending">>; -subscription_to_string(unconfigured) -> <<"unconfigured">>; -subscription_to_string(_) -> <<"none">>. - -spec service_jid(jid() | ljid() | binary()) -> jid(). service_jid(#jid{} = Jid) -> Jid; service_jid({U, S, R}) -> jid:make(U, S, R); diff --git a/src/mod_register.erl b/src/mod_register.erl index 334af4514..44a64539e 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -146,12 +146,10 @@ process_iq(#iq{type = set, lang = Lang, to = To, from = From, end; true -> case From of - #jid{user = User, lserver = Server, resource = Resource} -> + #jid{luser = LUser, lserver = Server} -> ResIQ = xmpp:make_iq_result(IQ), - ejabberd_router:route(jid:make(User, Server, Resource), - jid:make(User, Server, Resource), - ResIQ), - ejabberd_auth:remove_user(User, Server), + ejabberd_router:route(From, From, ResIQ), + ejabberd_auth:remove_user(LUser, Server), ignore; _ -> Txt = <<"The query is only allowed from local users">>, diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 2a41907a4..feebd3945 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -308,13 +308,13 @@ encode_item(Item) -> end, groups = Item#roster.groups}. -decode_item(#roster_item{} = Item, R, Managed) -> +decode_item(Item, R, Managed) -> R#roster{jid = jid:tolower(Item#roster_item.jid), name = Item#roster_item.name, subscription = case Item#roster_item.subscription of remove -> remove; Sub when Managed -> Sub; - _ -> undefined + _ -> R#roster.subscription end, groups = Item#roster_item.groups}. @@ -334,45 +334,48 @@ try_process_iq_set(#iq{from = From, lang = Lang} = IQ) -> end. process_iq_set(#iq{from = From, to = To, id = Id, - sub_els = [#roster_query{items = Items}]} = IQ) -> + sub_els = [#roster_query{items = QueryItems}]} = IQ) -> Managed = is_managed_from_id(Id), - lists:foreach(fun (Item) -> process_item_set(From, To, Item, Managed) - end, - Items), - xmpp:make_iq_result(IQ). - -process_item_set(From, To, #roster_item{jid = JID1} = QueryItem, Managed) -> #jid{user = User, luser = LUser, lserver = LServer} = From, - LJID = jid:tolower(JID1), F = fun () -> - Item = get_roster_by_jid_t(LUser, LServer, LJID), - Item2 = decode_item(QueryItem, Item, Managed), - Item3 = ejabberd_hooks:run_fold(roster_process_item, - LServer, Item2, - [LServer]), - case Item3#roster.subscription of - remove -> del_roster_t(LUser, LServer, LJID); - _ -> update_roster_t(LUser, LServer, LJID, Item3) - end, - send_itemset_to_managers(From, Item3, Managed), - case roster_version_on_db(LServer) of - true -> write_roster_version_t(LUser, LServer); - false -> ok - end, - {Item, Item3} + lists:map( + fun(#roster_item{jid = JID1} = QueryItem) -> + LJID = jid:tolower(JID1), + Item = get_roster_by_jid_t(LUser, LServer, LJID), + Item2 = decode_item(QueryItem, Item, Managed), + Item3 = ejabberd_hooks:run_fold(roster_process_item, + LServer, Item2, + [LServer]), + case Item3#roster.subscription of + remove -> del_roster_t(LUser, LServer, LJID); + _ -> update_roster_t(LUser, LServer, LJID, Item3) + end, + case roster_version_on_db(LServer) of + true -> write_roster_version_t(LUser, LServer); + false -> ok + end, + {Item, Item3} + end, QueryItems) end, case transaction(LServer, F) of - {atomic, {OldItem, Item}} -> - push_item(User, LServer, To, Item), - case Item#roster.subscription of - remove -> - send_unsubscribing_presence(From, OldItem), ok; - _ -> ok - end; + {atomic, ItemPairs} -> + lists:foreach( + fun({OldItem, Item}) -> + send_itemset_to_managers(From, Item, Managed), + push_item(User, LServer, To, Item), + case Item#roster.subscription of + remove -> + send_unsubscribing_presence(From, OldItem); + _ -> + ok + end + end, ItemPairs), + xmpp:make_iq_result(IQ); E -> - ?DEBUG("ROSTER: roster item set error: ~p~n", [E]), ok - end; -process_item_set(_From, _To, _, _Managed) -> ok. + ?ERROR_MSG("roster set failed:~nIQ = ~s~nError = ~p", + [xmpp:pp(IQ), E]), + xmpp:make_error(IQ, xmpp:err_internal_server_error()) + end. push_item(User, Server, From, Item) -> ejabberd_sm:route(jid:make(<<"">>, <<"">>, <<"">>), diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index 1f6edb460..8333d32cf 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -137,7 +137,7 @@ stop(Host) -> ?NS_VCARD), ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 50), - Mod = gen_mod:db_type(Host, ?MODULE), + Mod = gen_mod:db_mod(Host, ?MODULE), Mod:stop(Host), Proc = gen_mod:get_module_proc(Host, ?PROCNAME), Proc ! stop, diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl index 191676224..d8efe30f5 100644 --- a/src/mod_vcard_ldap.erl +++ b/src/mod_vcard_ldap.erl @@ -248,10 +248,10 @@ ldap_attribute_to_vcard({Attr, Value}, V) -> <<"tel">> -> V#vcard_temp{tel = [#vcard_tel{number = Value}|Ts]}; <<"email">> -> V#vcard_temp{email = [#vcard_email{userid = Value}|Es]}; <<"photo">> -> V#vcard_temp{photo = #vcard_photo{binval = Value}}; - <<"family">> -> V#vcard_temp{n = N#vcard_name{family = V}}; - <<"given">> -> V#vcard_temp{n = N#vcard_name{given = V}}; - <<"middle">> -> V#vcard_temp{n = N#vcard_name{middle = V}}; - <<"orgname">> -> V#vcard_temp{org = O#vcard_org{name = V}}; + <<"family">> -> V#vcard_temp{n = N#vcard_name{family = Value}}; + <<"given">> -> V#vcard_temp{n = N#vcard_name{given = Value}}; + <<"middle">> -> V#vcard_temp{n = N#vcard_name{middle = Value}}; + <<"orgname">> -> V#vcard_temp{org = O#vcard_org{name = Value}}; <<"orgunit">> -> V#vcard_temp{org = O#vcard_org{units = [Value]}}; <<"locality">> -> V#vcard_temp{adr = [A#vcard_adr{locality = Value}]}; <<"street">> -> V#vcard_temp{adr = [A#vcard_adr{street = Value}]}; diff --git a/src/mod_vcard_xupdate.erl b/src/mod_vcard_xupdate.erl index 5cc87056e..27688e8fb 100644 --- a/src/mod_vcard_xupdate.erl +++ b/src/mod_vcard_xupdate.erl @@ -52,7 +52,7 @@ depends(_Host, _Opts) -> %% Hooks %%==================================================================== -spec update_presence(presence(), binary(), binary()) -> presence(). -update_presence(#presence{type = undefined} = Packet, User, Host) -> +update_presence(#presence{type = available} = Packet, User, Host) -> presence_with_xupdate(Packet, User, Host); update_presence(Packet, _User, _Host) -> Packet. diff --git a/src/node_flat.erl b/src/node_flat.erl index 2ec9afe54..e80aaad34 100644 --- a/src/node_flat.erl +++ b/src/node_flat.erl @@ -707,7 +707,7 @@ del_state(Nidx, Key) -> %% relational database), or they can even decide not to persist any items.

get_items(Nidx, _From, _RSM) -> Items = mnesia:match_object(#pubsub_item{itemid = {'_', Nidx}, _ = '_'}), - {result, {lists:reverse(lists:keysort(#pubsub_item.modification, Items)), none}}. + {result, {lists:reverse(lists:keysort(#pubsub_item.modification, Items)), undefined}}. get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, RSM) -> SubKey = jid:tolower(JID), diff --git a/src/xmpp_codec.erl b/src/xmpp_codec.erl index 8653d591c..00ee53aaf 100644 --- a/src/xmpp_codec.erl +++ b/src/xmpp_codec.erl @@ -286,6 +286,8 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) -> _el); {<<"fin">>, <<"urn:xmpp:mam:0">>} -> decode_mam_fin(<<"urn:xmpp:mam:0">>, IgnoreEls, _el); + {<<"fin">>, <<"urn:xmpp:mam:1">>} -> + decode_mam_fin(<<"urn:xmpp:mam:1">>, IgnoreEls, _el); {<<"prefs">>, <<"urn:xmpp:mam:0">>} -> decode_mam_prefs(<<"urn:xmpp:mam:0">>, IgnoreEls, _el); {<<"prefs">>, <<"urn:xmpp:mam:1">>} -> @@ -1688,6 +1690,7 @@ is_known_tag({xmlel, _name, _attrs, _} = _el) -> {<<"disable">>, <<"urn:xmpp:carbons:2">>} -> true; {<<"forwarded">>, <<"urn:xmpp:forward:0">>} -> true; {<<"fin">>, <<"urn:xmpp:mam:0">>} -> true; + {<<"fin">>, <<"urn:xmpp:mam:1">>} -> true; {<<"prefs">>, <<"urn:xmpp:mam:0">>} -> true; {<<"prefs">>, <<"urn:xmpp:mam:1">>} -> true; {<<"prefs">>, <<"urn:xmpp:mam:tmp">>} -> true; @@ -2978,9 +2981,8 @@ encode({mam_result, _, _, _, _} = Result) -> encode_mam_result(Result, []); encode({mam_prefs, _, _, _, _} = Prefs) -> encode_mam_prefs(Prefs, []); -encode({mam_fin, _, _, _, _} = Fin) -> - encode_mam_fin(Fin, - [{<<"xmlns">>, <<"urn:xmpp:mam:0">>}]); +encode({mam_fin, _, _, _, _, _} = Fin) -> + encode_mam_fin(Fin, []); encode({forwarded, _, _} = Forwarded) -> encode_forwarded(Forwarded, [{<<"xmlns">>, <<"urn:xmpp:forward:0">>}]); @@ -3196,7 +3198,7 @@ get_name({iq, _, _, _, _, _, _}) -> <<"iq">>; get_name({last, _, _}) -> <<"query">>; get_name({legacy_auth, _, _, _, _}) -> <<"query">>; get_name({mam_archived, _, _}) -> <<"archived">>; -get_name({mam_fin, _, _, _, _}) -> <<"fin">>; +get_name({mam_fin, _, _, _, _, _}) -> <<"fin">>; get_name({mam_prefs, _, _, _, _}) -> <<"prefs">>; get_name({mam_query, _, _, _, _, _, _, _, _}) -> <<"query">>; @@ -3466,7 +3468,7 @@ get_ns({last, _, _}) -> <<"jabber:iq:last">>; get_ns({legacy_auth, _, _, _, _}) -> <<"jabber:iq:auth">>; get_ns({mam_archived, _, _}) -> <<"urn:xmpp:mam:tmp">>; -get_ns({mam_fin, _, _, _, _}) -> <<"urn:xmpp:mam:0">>; +get_ns({mam_fin, Xmlns, _, _, _, _}) -> Xmlns; get_ns({mam_prefs, Xmlns, _, _, _}) -> Xmlns; get_ns({mam_query, Xmlns, _, _, _, _, _, _, _}) -> Xmlns; @@ -3898,7 +3900,7 @@ pp(mam_query, 8) -> 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, 4) -> [id, rsm, stable, complete]; +pp(mam_fin, 5) -> [xmlns, id, rsm, stable, complete]; pp(forwarded, 2) -> [delay, sub_els]; pp(carbons_disable, 0) -> []; pp(carbons_enable, 0) -> []; @@ -8600,10 +8602,10 @@ decode_mam_fin(__TopXMLNS, __IgnoreEls, {xmlel, <<"fin">>, _attrs, _els}) -> Rsm = decode_mam_fin_els(__TopXMLNS, __IgnoreEls, _els, undefined), - {Id, Stable, Complete} = + {Id, Xmlns, Stable, Complete} = decode_mam_fin_attrs(__TopXMLNS, _attrs, undefined, - undefined, undefined), - {mam_fin, Id, Rsm, Stable, Complete}. + undefined, undefined, undefined), + {mam_fin, Xmlns, Id, Rsm, Stable, Complete}. decode_mam_fin_els(__TopXMLNS, __IgnoreEls, [], Rsm) -> Rsm; @@ -8622,37 +8624,45 @@ decode_mam_fin_els(__TopXMLNS, __IgnoreEls, [_ | _els], decode_mam_fin_els(__TopXMLNS, __IgnoreEls, _els, Rsm). decode_mam_fin_attrs(__TopXMLNS, - [{<<"queryid">>, _val} | _attrs], _Id, Stable, + [{<<"queryid">>, _val} | _attrs], _Id, Xmlns, Stable, Complete) -> - decode_mam_fin_attrs(__TopXMLNS, _attrs, _val, Stable, - Complete); + decode_mam_fin_attrs(__TopXMLNS, _attrs, _val, Xmlns, + Stable, Complete); decode_mam_fin_attrs(__TopXMLNS, - [{<<"stable">>, _val} | _attrs], Id, _Stable, + [{<<"xmlns">>, _val} | _attrs], Id, _Xmlns, Stable, Complete) -> decode_mam_fin_attrs(__TopXMLNS, _attrs, Id, _val, - Complete); + Stable, Complete); decode_mam_fin_attrs(__TopXMLNS, - [{<<"complete">>, _val} | _attrs], Id, Stable, + [{<<"stable">>, _val} | _attrs], Id, Xmlns, _Stable, + Complete) -> + decode_mam_fin_attrs(__TopXMLNS, _attrs, Id, Xmlns, + _val, Complete); +decode_mam_fin_attrs(__TopXMLNS, + [{<<"complete">>, _val} | _attrs], Id, Xmlns, Stable, _Complete) -> - decode_mam_fin_attrs(__TopXMLNS, _attrs, Id, Stable, - _val); + decode_mam_fin_attrs(__TopXMLNS, _attrs, Id, Xmlns, + Stable, _val); decode_mam_fin_attrs(__TopXMLNS, [_ | _attrs], Id, - Stable, Complete) -> - decode_mam_fin_attrs(__TopXMLNS, _attrs, Id, Stable, - Complete); -decode_mam_fin_attrs(__TopXMLNS, [], Id, Stable, + Xmlns, Stable, Complete) -> + decode_mam_fin_attrs(__TopXMLNS, _attrs, Id, Xmlns, + Stable, Complete); +decode_mam_fin_attrs(__TopXMLNS, [], Id, Xmlns, Stable, Complete) -> {decode_mam_fin_attr_queryid(__TopXMLNS, Id), + decode_mam_fin_attr_xmlns(__TopXMLNS, Xmlns), decode_mam_fin_attr_stable(__TopXMLNS, Stable), decode_mam_fin_attr_complete(__TopXMLNS, Complete)}. -encode_mam_fin({mam_fin, Id, Rsm, Stable, Complete}, +encode_mam_fin({mam_fin, Xmlns, Id, Rsm, Stable, + Complete}, _xmlns_attrs) -> _els = lists:reverse('encode_mam_fin_$rsm'(Rsm, [])), _attrs = encode_mam_fin_attr_complete(Complete, encode_mam_fin_attr_stable(Stable, - encode_mam_fin_attr_queryid(Id, - _xmlns_attrs))), + encode_mam_fin_attr_xmlns(Xmlns, + encode_mam_fin_attr_queryid(Id, + _xmlns_attrs)))), {xmlel, <<"fin">>, _attrs, _els}. 'encode_mam_fin_$rsm'(undefined, _acc) -> _acc; @@ -8669,6 +8679,14 @@ encode_mam_fin_attr_queryid(<<>>, _acc) -> _acc; encode_mam_fin_attr_queryid(_val, _acc) -> [{<<"queryid">>, _val} | _acc]. +decode_mam_fin_attr_xmlns(__TopXMLNS, undefined) -> + <<>>; +decode_mam_fin_attr_xmlns(__TopXMLNS, _val) -> _val. + +encode_mam_fin_attr_xmlns(<<>>, _acc) -> _acc; +encode_mam_fin_attr_xmlns(_val, _acc) -> + [{<<"xmlns">>, _val} | _acc]. + decode_mam_fin_attr_stable(__TopXMLNS, undefined) -> undefined; decode_mam_fin_attr_stable(__TopXMLNS, _val) -> diff --git a/src/xmpp_util.erl b/src/xmpp_util.erl index 20231fffa..43178e86f 100644 --- a/src/xmpp_util.erl +++ b/src/xmpp_util.erl @@ -68,7 +68,7 @@ unwrap_carbon(Stanza) -> Stanza. -spec is_standalone_chat_state(stanza()) -> boolean(). is_standalone_chat_state(Stanza) -> case unwrap_carbon(Stanza) of - #message{sub_els = Els} -> + #message{body = [], subject = [], sub_els = Els} -> IgnoreNS = [?NS_CHATSTATES, ?NS_DELAY], Stripped = [El || El <- Els, not lists:member(xmpp:get_ns(El), IgnoreNS)], diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index d3e7ec668..fbaee781f 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -25,7 +25,7 @@ -include("suite.hrl"). suite() -> - [{timetrap, {seconds,120}}]. + [{timetrap, {seconds,10}}]. init_per_suite(Config) -> NewConfig = init_config(Config), @@ -432,8 +432,8 @@ test_register(Config) -> register(Config) -> #iq{type = result, - sub_els = [#register{username = none, - password = none}]} = + sub_els = [#register{username = <<>>, + password = <<>>}]} = send_recv(Config, #iq{type = get, to = server_jid(Config), sub_els = [#register{}]}), #iq{type = result, sub_els = []} = @@ -492,31 +492,31 @@ test_open_session(Config) -> disconnect(open_session(Config)). roster_get(Config) -> - #iq{type = result, sub_els = [#roster{items = []}]} = - send_recv(Config, #iq{type = get, sub_els = [#roster{}]}), + #iq{type = result, sub_els = [#roster_query{items = []}]} = + send_recv(Config, #iq{type = get, sub_els = [#roster_query{}]}), disconnect(Config). roster_ver(Config) -> %% Get initial "ver" - #iq{type = result, sub_els = [#roster{ver = Ver1, items = []}]} = + #iq{type = result, sub_els = [#roster_query{ver = Ver1, items = []}]} = send_recv(Config, #iq{type = get, - sub_els = [#roster{ver = <<"">>}]}), + sub_els = [#roster_query{ver = <<"">>}]}), %% Should receive empty IQ-result #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = get, - sub_els = [#roster{ver = Ver1}]}), + sub_els = [#roster_query{ver = Ver1}]}), %% Attempting to subscribe to server's JID send(Config, #presence{type = subscribe, to = server_jid(Config)}), %% Receive a single roster push with the new "ver" - ?recv1(#iq{type = set, sub_els = [#roster{ver = Ver2}]}), + ?recv1(#iq{type = set, sub_els = [#roster_query{ver = Ver2}]}), %% Requesting roster with the previous "ver". Should receive Ver2 again - #iq{type = result, sub_els = [#roster{ver = Ver2}]} = + #iq{type = result, sub_els = [#roster_query{ver = Ver2}]} = send_recv(Config, #iq{type = get, - sub_els = [#roster{ver = Ver1}]}), + sub_els = [#roster_query{ver = Ver1}]}), %% Now requesting roster with the newest "ver". Should receive empty IQ. #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = get, - sub_els = [#roster{ver = Ver2}]}), + sub_els = [#roster_query{ver = Ver2}]}), disconnect(Config). presence(Config) -> @@ -539,7 +539,7 @@ presence_broadcast(Config) -> lang = <<"en">>, name = <<"ejabberd_ct">>}], node = Node, features = [Feature]}, - Caps = #caps{hash = <<"sha-1">>, node = ?EJABBERD_CT_URI, ver = Ver}, + Caps = #caps{hash = <<"sha-1">>, node = ?EJABBERD_CT_URI, version = B64Ver}, send(Config, #presence{sub_els = [Caps]}), JID = my_jid(Config), %% We receive: @@ -559,10 +559,7 @@ presence_broadcast(Config) -> lists:foldl( fun(Time, []) -> timer:sleep(Time), - mod_caps:get_features( - Server, - mod_caps:read_caps( - [xmpp_codec:encode(Caps)])); + mod_caps:get_features(Server, Caps); (_, Acc) -> Acc end, [], [0, 100, 200, 2000, 5000, 10000]), @@ -692,12 +689,12 @@ last(Config) -> privacy(Config) -> true = is_feature_advertised(Config, ?NS_PRIVACY), - #iq{type = result, sub_els = [#privacy{}]} = - send_recv(Config, #iq{type = get, sub_els = [#privacy{}]}), + #iq{type = result, sub_els = [#privacy_query{}]} = + send_recv(Config, #iq{type = get, sub_els = [#privacy_query{}]}), JID = <<"tybalt@example.com">>, I1 = send(Config, #iq{type = set, - sub_els = [#privacy{ + sub_els = [#privacy_query{ lists = [#privacy_list{ name = <<"public">>, items = @@ -705,41 +702,41 @@ privacy(Config) -> type = jid, order = 3, action = deny, - kinds = ['presence-in'], + presence_in = true, value = JID}]}]}]}), {Push1, _} = ?recv2( #iq{type = set, - sub_els = [#privacy{ + sub_els = [#privacy_query{ lists = [#privacy_list{ name = <<"public">>}]}]}, #iq{type = result, id = I1, sub_els = []}), send(Config, make_iq_result(Push1)), #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = set, - sub_els = [#privacy{active = <<"public">>}]}), + sub_els = [#privacy_query{active = <<"public">>}]}), #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = set, - sub_els = [#privacy{default = <<"public">>}]}), + sub_els = [#privacy_query{default = <<"public">>}]}), #iq{type = result, - sub_els = [#privacy{default = <<"public">>, + sub_els = [#privacy_query{default = <<"public">>, active = <<"public">>, lists = [#privacy_list{name = <<"public">>}]}]} = - send_recv(Config, #iq{type = get, sub_els = [#privacy{}]}), + send_recv(Config, #iq{type = get, sub_els = [#privacy_query{}]}), #iq{type = result, sub_els = []} = send_recv(Config, - #iq{type = set, sub_els = [#privacy{default = none}]}), + #iq{type = set, sub_els = [#privacy_query{default = none}]}), #iq{type = result, sub_els = []} = - send_recv(Config, #iq{type = set, sub_els = [#privacy{active = none}]}), + send_recv(Config, #iq{type = set, sub_els = [#privacy_query{active = none}]}), I2 = send(Config, #iq{type = set, - sub_els = [#privacy{ + sub_els = [#privacy_query{ lists = [#privacy_list{ name = <<"public">>}]}]}), {Push2, _} = ?recv2( #iq{type = set, - sub_els = [#privacy{ + sub_els = [#privacy_query{ lists = [#privacy_list{ name = <<"public">>}]}]}, #iq{type = result, id = I2, sub_els = []}), @@ -756,7 +753,7 @@ blocking(Config) -> {Push1, Push2, _} = ?recv3( #iq{type = set, - sub_els = [#privacy{lists = [#privacy_list{}]}]}, + sub_els = [#privacy_query{lists = [#privacy_list{}]}]}, #iq{type = set, sub_els = [#block{items = [JID]}]}, #iq{type = result, id = I1, sub_els = []}), @@ -767,7 +764,7 @@ blocking(Config) -> {Push3, Push4, _} = ?recv3( #iq{type = set, - sub_els = [#privacy{lists = [#privacy_list{}]}]}, + sub_els = [#privacy_query{lists = [#privacy_list{}]}]}, #iq{type = set, sub_els = [#unblock{items = [JID]}]}, #iq{type = result, id = I2, sub_els = []}), @@ -778,7 +775,7 @@ blocking(Config) -> vcard(Config) -> true = is_feature_advertised(Config, ?NS_VCARD), VCard = - #vcard{fn = <<"Peter Saint-Andre">>, + #vcard_temp{fn = <<"Peter Saint-Andre">>, n = #vcard_name{family = <<"Saint-Andre">>, given = <<"Peter">>}, nickname = <<"stpeter">>, @@ -811,21 +808,21 @@ vcard(Config) -> send_recv(Config, #iq{type = set, sub_els = [VCard]}), %% TODO: check if VCard == VCard1. #iq{type = result, sub_els = [_VCard1]} = - send_recv(Config, #iq{type = get, sub_els = [#vcard{}]}), + send_recv(Config, #iq{type = get, sub_els = [#vcard_temp{}]}), disconnect(Config). vcard_get(Config) -> true = is_feature_advertised(Config, ?NS_VCARD), %% TODO: check if VCard corresponds to LDIF data from ejabberd.ldif #iq{type = result, sub_els = [_VCard]} = - send_recv(Config, #iq{type = get, sub_els = [#vcard{}]}), + send_recv(Config, #iq{type = get, sub_els = [#vcard_temp{}]}), disconnect(Config). ldap_shared_roster_get(Config) -> Item = #roster_item{jid = jid:from_string(<<"user2@ldap.localhost">>), name = <<"Test User 2">>, groups = [<<"group1">>], subscription = both}, - #iq{type = result, sub_els = [#roster{items = [Item]}]} = - send_recv(Config, #iq{type = get, sub_els = [#roster{}]}), + #iq{type = result, sub_els = [#roster_query{items = [Item]}]} = + send_recv(Config, #iq{type = get, sub_els = [#roster_query{}]}), disconnect(Config). vcard_xupdate_master(Config) -> @@ -835,17 +832,17 @@ vcard_xupdate_master(Config) -> Peer = ?config(slave, Config), wait_for_slave(Config), send(Config, #presence{}), - ?recv2(#presence{from = MyJID, type = undefined}, - #presence{from = Peer, type = undefined}), - VCard = #vcard{photo = #vcard_photo{type = <<"image/png">>, binval = Img}}, + ?recv2(#presence{from = MyJID, type = available}, + #presence{from = Peer, type = available}), + VCard = #vcard_temp{photo = #vcard_photo{type = <<"image/png">>, binval = Img}}, I1 = send(Config, #iq{type = set, sub_els = [VCard]}), ?recv2(#iq{type = result, sub_els = [], id = I1}, - #presence{from = MyJID, type = undefined, - sub_els = [#vcard_xupdate{photo = ImgHash}]}), - I2 = send(Config, #iq{type = set, sub_els = [#vcard{}]}), + #presence{from = MyJID, type = available, + sub_els = [#vcard_xupdate{hash = ImgHash}]}), + I2 = send(Config, #iq{type = set, sub_els = [#vcard_temp{}]}), ?recv3(#iq{type = result, sub_els = [], id = I2}, - #presence{from = MyJID, type = undefined, - sub_els = [#vcard_xupdate{photo = undefined}]}, + #presence{from = MyJID, type = available, + sub_els = [#vcard_xupdate{hash = undefined}]}, #presence{from = Peer, type = unavailable}), disconnect(Config). @@ -855,24 +852,24 @@ vcard_xupdate_slave(Config) -> MyJID = my_jid(Config), Peer = ?config(master, Config), send(Config, #presence{}), - ?recv1(#presence{from = MyJID, type = undefined}), + ?recv1(#presence{from = MyJID, type = available}), wait_for_master(Config), - ?recv1(#presence{from = Peer, type = undefined}), - ?recv1(#presence{from = Peer, type = undefined, - sub_els = [#vcard_xupdate{photo = ImgHash}]}), - ?recv1(#presence{from = Peer, type = undefined, - sub_els = [#vcard_xupdate{photo = undefined}]}), + ?recv1(#presence{from = Peer, type = available}), + ?recv1(#presence{from = Peer, type = available, + sub_els = [#vcard_xupdate{hash = ImgHash}]}), + ?recv1(#presence{from = Peer, type = available, + sub_els = [#vcard_xupdate{hash = undefined}]}), disconnect(Config). stats(Config) -> - #iq{type = result, sub_els = [#stats{stat = Stats}]} = + #iq{type = result, sub_els = [#stats{list = Stats}]} = send_recv(Config, #iq{type = get, sub_els = [#stats{}], to = server_jid(Config)}), lists:foreach( fun(#stat{} = Stat) -> #iq{type = result, sub_els = [_|_]} = send_recv(Config, #iq{type = get, - sub_els = [#stats{stat = [Stat]}], + sub_els = [#stats{list = [Stat]}], to = server_jid(Config)}) end, Stats), disconnect(Config). @@ -883,68 +880,68 @@ pubsub(Config) -> %% Publish element within node "presence" ItemID = randoms:get_string(), Node = <<"presence!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>, - Item = #pubsub_item{id = ItemID, + Item = #ps_item{id = ItemID, xml_els = [xmpp_codec:encode(#presence{})]}, #iq{type = result, - sub_els = [#pubsub{publish = #pubsub_publish{ + sub_els = [#pubsub{publish = #ps_publish{ node = Node, - items = [#pubsub_item{id = ItemID}]}}]} = + items = [#ps_item{id = ItemID}]}}]} = send_recv(Config, #iq{type = set, to = pubsub_jid(Config), - sub_els = [#pubsub{publish = #pubsub_publish{ + sub_els = [#pubsub{publish = #ps_publish{ node = Node, items = [Item]}}]}), %% Subscribe to node "presence" I1 = send(Config, #iq{type = set, to = pubsub_jid(Config), - sub_els = [#pubsub{subscribe = #pubsub_subscribe{ + sub_els = [#pubsub{subscribe = #ps_subscribe{ node = Node, jid = my_jid(Config)}}]}), ?recv2( - #message{sub_els = [#pubsub_event{}, #delay{}]}, + #message{sub_els = [#ps_event{}, #delay{}]}, #iq{type = result, id = I1}), %% Get subscriptions true = lists:member(?PUBSUB("retrieve-subscriptions"), Features), #iq{type = result, sub_els = [#pubsub{subscriptions = - {none, [#pubsub_subscription{node = Node}]}}]} = + {<<>>, [#ps_subscription{node = Node}]}}]} = send_recv(Config, #iq{type = get, to = pubsub_jid(Config), - sub_els = [#pubsub{subscriptions = {none, []}}]}), + sub_els = [#pubsub{subscriptions = {<<>>, []}}]}), %% Get affiliations true = lists:member(?PUBSUB("retrieve-affiliations"), Features), #iq{type = result, sub_els = [#pubsub{ affiliations = - [#pubsub_affiliation{node = Node, type = owner}]}]} = + {<<>>, [#ps_affiliation{node = Node, type = owner}]}}]} = send_recv(Config, #iq{type = get, to = pubsub_jid(Config), - sub_els = [#pubsub{affiliations = []}]}), + sub_els = [#pubsub{affiliations = {<<>>, []}}]}), %% Fetching published items from node "presence" #iq{type = result, - sub_els = [#pubsub{items = #pubsub_items{ + sub_els = [#pubsub{items = #ps_items{ node = Node, items = [Item]}}]} = send_recv(Config, #iq{type = get, to = pubsub_jid(Config), - sub_els = [#pubsub{items = #pubsub_items{node = Node}}]}), + sub_els = [#pubsub{items = #ps_items{node = Node}}]}), %% Deleting the item from the node true = lists:member(?PUBSUB("delete-items"), Features), I2 = send(Config, #iq{type = set, to = pubsub_jid(Config), - sub_els = [#pubsub{retract = #pubsub_retract{ + sub_els = [#pubsub{retract = #ps_retract{ node = Node, - items = [#pubsub_item{id = ItemID}]}}]}), + items = [#ps_item{id = ItemID}]}}]}), ?recv2( #iq{type = result, id = I2, sub_els = []}, - #message{sub_els = [#pubsub_event{ - items = [#pubsub_event_items{ - node = Node, - retract = [ItemID]}]}]}), + #message{sub_els = [#ps_event{ + items = #ps_items{ + node = Node, + retract = ItemID}}]}), %% Unsubscribe from node "presence" #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = set, to = pubsub_jid(Config), - sub_els = [#pubsub{unsubscribe = #pubsub_unsubscribe{ + sub_els = [#pubsub{unsubscribe = #ps_unsubscribe{ node = Node, jid = my_jid(Config)}}]}), disconnect(Config). @@ -974,12 +971,12 @@ mix_master(Config) -> I0 = send(Config, #iq{type = set, to = Room, sub_els = [#mix_join{subscribe = Nodes}]}), {_, #message{sub_els = - [#pubsub_event{ - items = [#pubsub_event_items{ - node = ?NS_MIX_NODES_PARTICIPANTS, - items = [#pubsub_event_item{ - id = ParticipantID, - xml_els = [PXML]}]}]}]}} = + [#ps_event{ + items = #ps_items{ + node = ?NS_MIX_NODES_PARTICIPANTS, + items = [#ps_item{ + id = ParticipantID, + xml_els = [PXML]}]}}]}} = ?recv2(#iq{type = result, id = I0, sub_els = [#mix_join{subscribe = Nodes, jid = MyBareJID}]}, #message{from = Room}), @@ -992,42 +989,42 @@ mix_master(Config) -> #iq{type = set, to = Room, sub_els = [#pubsub{ - publish = #pubsub_publish{ + publish = #ps_publish{ node = ?NS_MIX_NODES_PRESENCE, - items = [#pubsub_item{ + items = [#ps_item{ id = PresenceID, xml_els = [Presence]}]}}]}), ?recv2(#iq{type = result, id = I1, sub_els = [#pubsub{ - publish = #pubsub_publish{ + publish = #ps_publish{ node = ?NS_MIX_NODES_PRESENCE, - items = [#pubsub_item{id = PresenceID}]}}]}, + items = [#ps_item{id = PresenceID}]}}]}, #message{from = Room, sub_els = - [#pubsub_event{ - items = [#pubsub_event_items{ - node = ?NS_MIX_NODES_PRESENCE, - items = [#pubsub_event_item{ + [#ps_event{ + items = #ps_items{ + node = ?NS_MIX_NODES_PRESENCE, + items = [#ps_item{ id = PresenceID, - xml_els = [Presence]}]}]}]}), + xml_els = [Presence]}]}}]}), %% Coming offline send(Config, #presence{type = unavailable, to = Room}), %% Receiving presence retract event #message{from = Room, - sub_els = [#pubsub_event{ - items = [#pubsub_event_items{ - node = ?NS_MIX_NODES_PRESENCE, - retract = [PresenceID]}]}]} = recv(), + sub_els = [#ps_event{ + items = #ps_items{ + node = ?NS_MIX_NODES_PRESENCE, + retract = PresenceID}}]} = recv(), %% Leaving I2 = send(Config, #iq{type = set, to = Room, sub_els = [#mix_leave{}]}), ?recv2(#iq{type = result, id = I2, sub_els = []}, #message{from = Room, sub_els = - [#pubsub_event{ - items = [#pubsub_event_items{ - node = ?NS_MIX_NODES_PARTICIPANTS, - retract = [ParticipantID]}]}]}), + [#ps_event{ + items = #ps_items{ + node = ?NS_MIX_NODES_PARTICIPANTS, + retract = ParticipantID}}]}), disconnect(Config). mix_slave(Config) -> @@ -1041,45 +1038,45 @@ roster_subscribe_master(Config) -> LPeer = jid:remove_resource(Peer), send(Config, #presence{type = subscribe, to = LPeer}), Push1 = ?recv1(#iq{type = set, - sub_els = [#roster{items = [#roster_item{ + sub_els = [#roster_query{items = [#roster_item{ ask = subscribe, subscription = none, jid = LPeer}]}]}), send(Config, make_iq_result(Push1)), {Push2, _} = ?recv2( #iq{type = set, - sub_els = [#roster{items = [#roster_item{ + sub_els = [#roster_query{items = [#roster_item{ subscription = to, jid = LPeer}]}]}, #presence{type = subscribed, from = LPeer}), send(Config, make_iq_result(Push2)), - ?recv1(#presence{type = undefined, from = Peer}), + ?recv1(#presence{type = available, from = Peer}), %% BUG: ejabberd sends previous push again. Is it ok? Push3 = ?recv1(#iq{type = set, - sub_els = [#roster{items = [#roster_item{ + sub_els = [#roster_query{items = [#roster_item{ subscription = to, jid = LPeer}]}]}), send(Config, make_iq_result(Push3)), ?recv1(#presence{type = subscribe, from = LPeer}), send(Config, #presence{type = subscribed, to = LPeer}), Push4 = ?recv1(#iq{type = set, - sub_els = [#roster{items = [#roster_item{ + sub_els = [#roster_query{items = [#roster_item{ subscription = both, jid = LPeer}]}]}), send(Config, make_iq_result(Push4)), %% Move into a group Groups = [<<"A">>, <<"B">>], Item = #roster_item{jid = LPeer, groups = Groups}, - I1 = send(Config, #iq{type = set, sub_els = [#roster{items = [Item]}]}), + I1 = send(Config, #iq{type = set, sub_els = [#roster_query{items = [Item]}]}), {Push5, _} = ?recv2( #iq{type = set, sub_els = - [#roster{items = [#roster_item{ + [#roster_query{items = [#roster_item{ jid = LPeer, subscription = both}]}]}, #iq{type = result, id = I1, sub_els = []}), send(Config, make_iq_result(Push5)), - #iq{sub_els = [#roster{items = [#roster_item{groups = G1}]}]} = Push5, + #iq{sub_els = [#roster_query{items = [#roster_item{groups = G1}]}]} = Push5, Groups = lists:sort(G1), wait_for_slave(Config), ?recv1(#presence{type = unavailable, from = Peer}), @@ -1094,25 +1091,25 @@ roster_subscribe_slave(Config) -> ?recv1(#presence{type = subscribe, from = LPeer}), send(Config, #presence{type = subscribed, to = LPeer}), Push1 = ?recv1(#iq{type = set, - sub_els = [#roster{items = [#roster_item{ + sub_els = [#roster_query{items = [#roster_item{ subscription = from, jid = LPeer}]}]}), send(Config, make_iq_result(Push1)), send(Config, #presence{type = subscribe, to = LPeer}), Push2 = ?recv1(#iq{type = set, - sub_els = [#roster{items = [#roster_item{ + sub_els = [#roster_query{items = [#roster_item{ ask = subscribe, subscription = from, jid = LPeer}]}]}), send(Config, make_iq_result(Push2)), {Push3, _} = ?recv2( #iq{type = set, - sub_els = [#roster{items = [#roster_item{ + sub_els = [#roster_query{items = [#roster_item{ subscription = both, jid = LPeer}]}]}, #presence{type = subscribed, from = LPeer}), send(Config, make_iq_result(Push3)), - ?recv1(#presence{type = undefined, from = Peer}), + ?recv1(#presence{type = available, from = Peer}), wait_for_master(Config), disconnect(Config). @@ -1123,8 +1120,8 @@ roster_remove_master(Config) -> Groups = [<<"A">>, <<"B">>], wait_for_slave(Config), send(Config, #presence{}), - ?recv2(#presence{from = MyJID, type = undefined}, - #presence{from = Peer, type = undefined}), + ?recv2(#presence{from = MyJID, type = available}, + #presence{from = Peer, type = available}), %% The peer removed us from its roster. {Push1, Push2, _, _, _} = ?recv5( @@ -1132,12 +1129,12 @@ roster_remove_master(Config) -> %% to send transient roster push with subscription = 'to'. #iq{type = set, sub_els = - [#roster{items = [#roster_item{ + [#roster_query{items = [#roster_item{ jid = LPeer, subscription = to}]}]}, #iq{type = set, sub_els = - [#roster{items = [#roster_item{ + [#roster_query{items = [#roster_item{ jid = LPeer, subscription = none}]}]}, #presence{type = unsubscribe, from = LPeer}, @@ -1145,8 +1142,8 @@ roster_remove_master(Config) -> #presence{type = unavailable, from = Peer}), send(Config, make_iq_result(Push1)), send(Config, make_iq_result(Push2)), - #iq{sub_els = [#roster{items = [#roster_item{groups = G1}]}]} = Push1, - #iq{sub_els = [#roster{items = [#roster_item{groups = G2}]}]} = Push2, + #iq{sub_els = [#roster_query{items = [#roster_item{groups = G1}]}]} = Push1, + #iq{sub_els = [#roster_query{items = [#roster_item{groups = G2}]}]} = Push2, Groups = lists:sort(G1), Groups = lists:sort(G2), disconnect(Config). @@ -1155,16 +1152,16 @@ roster_remove_slave(Config) -> Peer = ?config(master, Config), LPeer = jid:remove_resource(Peer), send(Config, #presence{}), - ?recv1(#presence{from = MyJID, type = undefined}), + ?recv1(#presence{from = MyJID, type = available}), wait_for_master(Config), - ?recv1(#presence{from = Peer, type = undefined}), + ?recv1(#presence{from = Peer, type = available}), %% Remove the peer from roster. Item = #roster_item{jid = LPeer, subscription = remove}, - I = send(Config, #iq{type = set, sub_els = [#roster{items = [Item]}]}), + I = send(Config, #iq{type = set, sub_els = [#roster_query{items = [Item]}]}), {Push, _, _} = ?recv3( #iq{type = set, sub_els = - [#roster{items = [#roster_item{ + [#roster_query{items = [#roster_item{ jid = LPeer, subscription = remove}]}]}, #iq{type = result, id = I, sub_els = []}, @@ -1178,7 +1175,7 @@ proxy65_master(Config) -> Peer = ?config(slave, Config), wait_for_slave(Config), send(Config, #presence{}), - ?recv1(#presence{from = MyJID, type = undefined}), + ?recv1(#presence{from = MyJID, type = available}), true = is_feature_advertised(Config, ?NS_BYTESTREAMS, Proxy), #iq{type = result, sub_els = [#bytestreams{hosts = [StreamHost]}]} = send_recv( @@ -1201,7 +1198,7 @@ proxy65_slave(Config) -> MyJID = my_jid(Config), Peer = ?config(master, Config), send(Config, #presence{}), - ?recv1(#presence{from = MyJID, type = undefined}), + ?recv1(#presence{from = MyJID, type = available}), wait_for_master(Config), {StreamHost, SID, Data} = get_event(Config), Socks5 = socks5_connect(StreamHost, {SID, Peer, MyJID}), @@ -1228,6 +1225,7 @@ retrieve_messages_from_room_via_mam(Config, Range) -> Room = muc_room_jid(Config), MyNickJID = jid:replace_resource(Room, MyNick), QID = randoms:get_string(), + Count = length(Range), I = send(Config, #iq{type = set, to = Room, sub_els = [#mam_query{xmlns = ?NS_MAM_1, id = QID}]}), lists:foreach( @@ -1247,7 +1245,11 @@ retrieve_messages_from_room_via_mam(Config, Range) -> type = groupchat, body = [Text]}]}]}]}) end, Range), - ?recv1(#iq{from = Room, id = I, type = result, sub_els = []}). + ?recv1(#iq{from = Room, id = I, type = result, + sub_els = [#mam_fin{xmlns = ?NS_MAM_1, + id = QID, + rsm = #rsm_set{count = Count}, + complete = true}]}). muc_mam_master(Config) -> MyJID = my_jid(Config), @@ -1318,14 +1320,12 @@ muc_master(Config) -> %% 4. The room subject %% 5. Live messages, presence updates, new user joins, etc. %% As this is the newly created room, we receive only the 2nd stanza. - ?recv1(#presence{ - from = MyNickJID, - sub_els = [#vcard_xupdate{}, - #muc_user{ - status_codes = Codes, - items = [#muc_item{role = moderator, - jid = MyJID, - affiliation = owner}]}]}), + #muc_user{ + status_codes = Codes, + items = [#muc_item{role = moderator, + jid = MyJID, + affiliation = owner}]} = + xmpp:get_subtag(?recv1(#presence{from = MyNickJID}), #muc_user{}), %% 110 -> Inform user that presence refers to itself %% 201 -> Inform user that a new room has been created [110, 201] = lists:sort(Codes), @@ -1389,13 +1389,11 @@ muc_master(Config) -> [#muc_user{ invites = [#muc_invite{to = PeerJID}]}]}), - %% Peer is joining - ?recv1(#presence{from = PeerNickJID, - sub_els = [#vcard_xupdate{}, - #muc_user{ - items = [#muc_item{role = visitor, - jid = PeerJID, - affiliation = none}]}]}), + #muc_user{ + items = [#muc_item{role = visitor, + jid = PeerJID, + affiliation = none}]} = + xmpp:get_subtag(?recv1(#presence{from = PeerNickJID}), #muc_user{}), %% Receiving a voice request ?recv1(#message{from = Room, sub_els = [#xdata{type = form, @@ -1424,12 +1422,10 @@ muc_master(Config) -> sub_els = [#xdata{type = submit, fields = ReplyVoiceReqFs}]}), %% Peer is becoming a participant - ?recv1(#presence{from = PeerNickJID, - sub_els = [#vcard_xupdate{}, - #muc_user{ - items = [#muc_item{role = participant, - jid = PeerJID, - affiliation = none}]}]}), + #muc_user{items = [#muc_item{role = participant, + jid = PeerJID, + affiliation = none}]} = + xmpp:get_subtag(?recv1(#presence{from = PeerNickJID}), #muc_user{}), %% Receive private message from the peer ?recv1(#message{from = PeerNickJID, body = [#text{data = Subject}]}), %% Granting membership to the peer and localhost server @@ -1443,19 +1439,16 @@ muc_master(Config) -> jid = PeerBareJID, affiliation = member}]}]}), %% Peer became a member - ?recv1(#presence{from = PeerNickJID, - sub_els = [#vcard_xupdate{}, - #muc_user{ - items = [#muc_item{affiliation = member, - jid = PeerJID, - role = participant}]}]}), + #muc_user{items = [#muc_item{affiliation = member, + jid = PeerJID, + role = participant}]} = + xmpp:get_subtag(?recv1(#presence{from = PeerNickJID}), #muc_user{}), ?recv1(#message{from = Room, sub_els = [#muc_user{ items = [#muc_item{affiliation = member, jid = Localhost, role = none}]}]}), - %% BUG: We should not receive any sub_els! - ?recv1(#iq{type = result, id = I1, sub_els = [_|_]}), + ?recv1(#iq{type = result, id = I1, sub_els = []}), %% Receive groupchat message from the peer ?recv1(#message{type = groupchat, from = PeerNickJID, body = [#text{data = Subject}]}), @@ -1483,22 +1476,20 @@ muc_master(Config) -> items = [#muc_item{affiliation = member, jid = PeerJID, role = none}]}]}), - %% BUG: We should not receive any sub_els! - ?recv1(#iq{type = result, id = I2, sub_els = [_|_]}), + ?recv1(#iq{type = result, id = I2, sub_els = []}), %% Destroying the room I3 = send(Config, #iq{type = set, to = Room, sub_els = [#muc_owner{ - destroy = #muc_owner_destroy{ + destroy = #muc_destroy{ reason = Subject}}]}), %% Kicked off ?recv1(#presence{from = MyNickJID, type = unavailable, sub_els = [#muc_user{items = [#muc_item{role = none, affiliation = none}], - destroy = #muc_user_destroy{ + destroy = #muc_destroy{ reason = Subject}}]}), - %% BUG: We should not receive any sub_els! - ?recv1(#iq{type = result, id = I3, sub_els = [_|_]}), + ?recv1(#iq{type = result, id = I3, sub_els = []}), disconnect(Config). muc_slave(Config) -> @@ -1514,10 +1505,9 @@ muc_slave(Config) -> Subject = ?config(room_subject, Config), Localhost = jid:make(<<"">>, <<"localhost">>, <<"">>), %% Receive an invite from the peer - ?recv1(#message{from = Room, type = normal, - sub_els = - [#muc_user{invites = - [#muc_invite{from = PeerJID}]}]}), + #muc_user{invites = [#muc_invite{from = PeerJID}]} = + xmpp:get_subtag(?recv1(#message{from = Room, type = normal}), + #muc_user{}), %% But before joining we discover the MUC service first %% to check if the room is in the disco list #iq{type = result, @@ -1533,21 +1523,16 @@ muc_slave(Config) -> %% Now joining send(Config, #presence{to = MyNickJID, sub_els = [#muc{}]}), %% First presence is from the participant, i.e. from the peer - ?recv1(#presence{ - from = PeerNickJID, - sub_els = [#vcard_xupdate{}, - #muc_user{ - status_codes = [], - items = [#muc_item{role = moderator, - affiliation = owner}]}]}), + #muc_user{ + status_codes = [], + items = [#muc_item{role = moderator, + affiliation = owner}]} = + xmpp:get_subtag(?recv1(#presence{from = PeerNickJID}), #muc_user{}), %% The next is the self-presence (code 110 means it) - ?recv1(#presence{ - from = MyNickJID, - sub_els = [#vcard_xupdate{}, - #muc_user{ - status_codes = [110], - items = [#muc_item{role = visitor, - affiliation = none}]}]}), + #muc_user{status_codes = [110], + items = [#muc_item{role = visitor, + affiliation = none}]} = + xmpp:get_subtag(?recv1(#presence{from = MyNickJID}), #muc_user{}), %% Receive the room subject ?recv1(#message{from = PeerNickJID, type = groupchat, body = [#text{data = Subject}], @@ -1574,20 +1559,16 @@ muc_slave(Config) -> values = [<<"participant">>]}]}, send(Config, #message{to = Room, sub_els = [VoiceReq]}), %% Becoming a participant - ?recv1(#presence{from = MyNickJID, - sub_els = [#vcard_xupdate{}, - #muc_user{ - items = [#muc_item{role = participant, - affiliation = none}]}]}), + #muc_user{items = [#muc_item{role = participant, + affiliation = none}]} = + xmpp:get_subtag(?recv1(#presence{from = MyNickJID}), #muc_user{}), %% Sending private message to the peer send(Config, #message{to = PeerNickJID, body = [#text{data = Subject}]}), %% Becoming a member - ?recv1(#presence{from = MyNickJID, - sub_els = [#vcard_xupdate{}, - #muc_user{ - items = [#muc_item{role = participant, - affiliation = member}]}]}), + #muc_user{items = [#muc_item{role = participant, + affiliation = member}]} = + xmpp:get_subtag(?recv1(#presence{from = MyNickJID}), #muc_user{}), %% Sending groupchat message send(Config, #message{to = Room, type = groupchat, body = [#text{data = Subject}]}), @@ -1624,7 +1605,7 @@ muc_register_nick(Config, MUC, PrevNick, Nick) -> X = #xdata{type = submit, fields = [#xdata_field{var = <<"nick">>, values = [Nick]}]}, %% Submitting form - #iq{type = result, sub_els = [_|_]} = + #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = set, to = MUC, sub_els = [#register{xdata = X}]}), %% Check if the nick was registered @@ -1643,7 +1624,7 @@ muc_register_master(Config) -> %% Register nick "master1" muc_register_nick(Config, MUC, <<"">>, <<"master1">>), %% Unregister nick "master1" via jabber:register - #iq{type = result, sub_els = [_|_]} = + #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = set, to = MUC, sub_els = [#register{remove = true}]}), %% Register nick "master2" @@ -1690,6 +1671,7 @@ announce_slave(Config) -> flex_offline_master(Config) -> Peer = ?config(slave, Config), + ct:log("hooks = ~p", [ets:tab2list(hooks)]), LPeer = jid:remove_resource(Peer), lists:foreach( fun(I) -> @@ -2026,8 +2008,11 @@ mam_slave(Config, NS) -> lists:foreach( fun(N) -> Text = #text{data = integer_to_binary(N)}, - ?recv1(#message{from = Peer, body = [Text], - sub_els = [#mam_archived{by = ServerJID}]}) + Msg = ?recv1(#message{from = Peer, body = [Text]}), + #mam_archived{by = ServerJID} = + xmpp:get_subtag(Msg, #mam_archived{}), + #stanza_id{by = ServerJID} = + xmpp:get_subtag(Msg, #stanza_id{}) end, lists:seq(1, 5)), #iq{type = result, sub_els = [#mam_prefs{xmlns = NS, default = never}]} = send_recv(Config, #iq{type = set, @@ -2241,7 +2226,7 @@ mam_query_rsm(Config, NS) -> #iq{type = Type, sub_els = [#mam_query{xmlns = NS, rsm = #rsm_set{max = 2, - before = none}}]}), + before = <<"">>}}]}), maybe_recv_iq_result(NS, I5), lists:foreach( fun(N) -> @@ -2278,25 +2263,25 @@ client_state_master(Config) -> PepOne = #message{ to = Peer, sub_els = - [#pubsub_event{ + [#ps_event{ items = - [#pubsub_event_items{ - node = <<"foo-1">>, - items = - [#pubsub_event_item{ - id = <<"pep-1">>, - xml_els = [PepPayload]}]}]}]}, + #ps_items{ + node = <<"foo-1">>, + items = + [#ps_item{ + id = <<"pep-1">>, + xml_els = [PepPayload]}]}}]}, PepTwo = #message{ to = Peer, sub_els = - [#pubsub_event{ + [#ps_event{ items = - [#pubsub_event_items{ - node = <<"foo-2">>, - items = - [#pubsub_event_item{ - id = <<"pep-2">>, - xml_els = [PepPayload]}]}]}]}, + #ps_items{ + node = <<"foo-2">>, + items = + [#ps_item{ + id = <<"pep-2">>, + xml_els = [PepPayload]}]}}]}, %% Wait for the slave to become inactive. wait_for_slave(Config), %% Should be queued (but see below): @@ -2330,24 +2315,24 @@ client_state_slave(Config) -> #message{ from = Peer, sub_els = - [#pubsub_event{ + [#ps_event{ items = - [#pubsub_event_items{ - node = <<"foo-1">>, - items = - [#pubsub_event_item{ - id = <<"pep-1">>}]}]}, + #ps_items{ + node = <<"foo-1">>, + items = + [#ps_item{ + id = <<"pep-1">>}]}}, #delay{}]} = recv(), #message{ from = Peer, sub_els = - [#pubsub_event{ + [#ps_event{ items = - [#pubsub_event_items{ - node = <<"foo-2">>, - items = - [#pubsub_event_item{ - id = <<"pep-2">>}]}]}, + #ps_items{ + node = <<"foo-2">>, + items = + [#ps_item{ + id = <<"pep-2">>}]}}, #delay{}]} = recv(), ?recv1(#message{from = Peer, thread = <<"1">>, sub_els = [#chatstate{type = composing}, diff --git a/test/ejabberd_SUITE_data/ejabberd.yml b/test/ejabberd_SUITE_data/ejabberd.yml index aca547d99..b2a0cd5ac 100644 --- a/test/ejabberd_SUITE_data/ejabberd.yml +++ b/test/ejabberd_SUITE_data/ejabberd.yml @@ -337,7 +337,8 @@ Welcome to this XMPP server." ldap_base: "ou=users,dc=localhost" auth_method: ldap modules: - mod_vcard_ldap: [] + mod_vcard: + db_type: ldap mod_roster: [] # mod_roster is required by mod_shared_roster mod_shared_roster_ldap: ldap_auth_check: off diff --git a/test/suite.erl b/test/suite.erl index c5593c4cf..d89a49ef8 100644 --- a/test/suite.erl +++ b/test/suite.erl @@ -199,7 +199,7 @@ bind(Config) -> open_session(Config) -> #iq{type = result, sub_els = []} = - send_recv(Config, #iq{type = set, sub_els = [#session{}]}), + send_recv(Config, #iq{type = set, sub_els = [#xmpp_session{}]}), Config. auth_SASL(Mech, Config) -> @@ -252,10 +252,15 @@ match_failure(Received, Matches) -> recv() -> receive {'$gen_event', {xmlstreamelement, El}} -> - Pkt = xmpp_codec:decode(fix_ns(El)), - ct:pal("recv: ~p ->~n~s", [El, xmpp_codec:pp(Pkt)]), - Pkt; - {'$gen_event', Event} -> + try + Pkt = xmpp:decode(El), + ct:pal("recv: ~p ->~n~s", [El, xmpp_codec:pp(Pkt)]), + Pkt + catch _:{xmpp_codec, Why} -> + ct:fail("recv failed: ~p->~n~s", + [El, xmpp:format_error(Why)]) + end; + {'$gen_event', Event} -> Event end. @@ -404,9 +409,9 @@ mix_room_jid(Config) -> jid:make(<<"test">>, <<"mix.", Server/binary>>, <<>>). id() -> - id(undefined). + id(<<>>). -id(undefined) -> +id(<<>>) -> randoms:get_string(); id(ID) -> ID. diff --git a/tools/xmpp_codec.spec b/tools/xmpp_codec.spec index 265bd6de9..aa18899c9 100644 --- a/tools/xmpp_codec.spec +++ b/tools/xmpp_codec.spec @@ -2653,9 +2653,10 @@ -xml(mam_fin, #elem{name = <<"fin">>, - xmlns = <<"urn:xmpp:mam:0">>, - result = {mam_fin, '$id', '$rsm', '$stable', '$complete'}, + xmlns = [<<"urn:xmpp:mam:0">>, <<"urn:xmpp:mam:1">>], + result = {mam_fin, '$xmlns', '$id', '$rsm', '$stable', '$complete'}, attrs = [#attr{name = <<"queryid">>, label = '$id'}, + #attr{name = <<"xmlns">>}, #attr{name = <<"stable">>, label = '$stable', dec = {dec_bool, []}, enc = {enc_bool, []}},