]> granicus.if.org Git - ejabberd/commitdiff
Make common tests working again
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>
Tue, 13 Sep 2016 09:30:05 +0000 (12:30 +0300)
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>
Tue, 13 Sep 2016 09:30:05 +0000 (12:30 +0300)
24 files changed:
include/xmpp_codec.hrl
src/ejabberd_c2s.erl
src/mod_announce.erl
src/mod_blocking.erl
src/mod_client_state.erl
src/mod_mam.erl
src/mod_mam_mnesia.erl
src/mod_mix.erl
src/mod_muc.erl
src/mod_offline.erl
src/mod_privacy.erl
src/mod_pubsub.erl
src/mod_register.erl
src/mod_roster.erl
src/mod_vcard.erl
src/mod_vcard_ldap.erl
src/mod_vcard_xupdate.erl
src/node_flat.erl
src/xmpp_codec.erl
src/xmpp_util.erl
test/ejabberd_SUITE.erl
test/ejabberd_SUITE_data/ejabberd.yml
test/suite.erl
tools/xmpp_codec.spec

index 635fcf3cb460dd64abf1dd2649354822071cd6cb..845861948431322f067aeec544c68e712ace22a4 100644 (file)
                   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()}).
index e658536ab637c1e552f5eaf9f5199179688c1997..186f7e9a5906fe190f72d0c7846305dd4185fa65 100644 (file)
@@ -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
index d9209f418e93df14142036faf32948f0c9b7d45a..8d2fbebff483b2b1b1087cd875f011dc5de7f963 100644 (file)
@@ -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.
 
index 55e3ca1516caf7a9af250ed149cb7accffb21ccc..b3bbff96eaabb5b168b206b15c966be9cab0026b 100644 (file)
@@ -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 <block/> and <unblock/> 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()].
index f72f334f30ed9cc18d5bb29359ab8018654fdc94..7f0658eff8459f4edda813cbf884098b0c1d16b9 100644 (file)
@@ -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).
 
index 2529b7389ed637cfae9da78c947ae6b7b7cf4278..ea267c1c06fe31bec7e562eddf4ac7c870af861b 100644 (file)
@@ -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).
 
index cbe7c336c6d8bfcb2342e2abfe474b96f26b9eb3..ecaa4d0537bae954b6bb5334229625cb99cada56 100644 (file)
@@ -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,
index f39408210e718a3bdedcfd6ebac4a74d2b97e351..7ca09f4db71aadef2ae49d1e7609f0eeb0eb120a 100644 (file)
@@ -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}].
index 3eca79fec359d1b0114607ff4e6aa4b16f8637de..66604394b911a5848c06a976d40419a521f62492 100644 (file)
@@ -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,
index 509406aa47ae82ca526bc1e48a0957a761960623..a2bcec894a32164aff4484d6a85a59cefecb6172 100644 (file)
@@ -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}.
index 3be3f2d3b5d66581267e73719d00733024e685c7..2f318deec4437c3012769baf1ba59935e2b2bf4b 100644 (file)
@@ -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 <list/> 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: "
                    "<list/>, <active/> or <default/>">>,
            {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}.
index b470d83d94431b9ff76cbf77ccf55defa4dba1b0..f7e1a98348d3fc5be0f7aba46fd2c72e8b390d17 100644 (file)
@@ -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);
index 334af451478944e1a754a76e2d7790b637dabf41..44a64539ea3491932f58b80d7417cc1db697b2f3 100644 (file)
@@ -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">>,
index 2a41907a42f3fa9ceb9444a2e2f1be182fd63971..feebd3945ded3c57e604fe49be9fd575ff6860b4 100644 (file)
@@ -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(<<"">>, <<"">>, <<"">>),
index 1f6edb46094744eaf60d8627895fac03c810f072..8333d32cfa2ebd17229ae1df32aa2de7e179ed87 100644 (file)
@@ -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,
index 191676224e30681d0dbe19de03f542ada51576a2..d8efe30f5c4fcd6d0585e0e84dbff290f4c42ee9 100644 (file)
@@ -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}]};
index 5cc87056ec0fec212bd587a3f7349c0e1d09997d..27688e8fbdaa2a081db7378b4e9b72052c231f20 100644 (file)
@@ -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.
 
index 2ec9afe54cf93592545fcd24600dc879ac1ab8d1..e80aaad347ef35501def557a1e292f3bba510e16 100644 (file)
@@ -707,7 +707,7 @@ del_state(Nidx, Key) ->
 %% relational database), or they can even decide not to persist any items.</p>
 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),
index 8653d591c5c920cb73d8c29ce4ac36dc19523de9..00ee53aaf8ec179bf6d7ef06478f829ce74e749e 100644 (file)
@@ -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,
+                    [{<<"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, Stable,
+                    [{<<"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) ->
index 20231fffa15e917bc8ee3af961b38a0dd41c3ba6..43178e86f699e9c320775283d6a149b31f5ea72f 100644 (file)
@@ -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)],
index d3e7ec668fca764ae71188451cb555b5d2512249..fbaee781f5696703a728ba4ce3147394c384b411 100644 (file)
@@ -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 <presence/> 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},
index aca547d998db7a8a0e9948d284a365d2877c256b..b2a0cd5accc7ff940acae19369b702b9c608cd35 100644 (file)
@@ -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
index c5593c4cf63a0d561f075ddb42c37d3d4618454f..d89a49ef8098004ad4d335adc6fce5dea0ecc42d 100644 (file)
@@ -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.
index 265bd6de94d5b584e6a839ee4801c283dc200376..aa18899c9782b74c0302155a34648876c401cf2c 100644 (file)
 
 -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, []}},