25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-24 17:29:28 +01:00

Make common tests working again

This commit is contained in:
Evgeniy Khramtsov 2016-09-13 12:30:05 +03:00
parent c29a48695d
commit e987b88848
24 changed files with 410 additions and 411 deletions

View File

@ -564,7 +564,8 @@
max :: non_neg_integer()}). max :: non_neg_integer()}).
-type rsm_set() :: #rsm_set{}. -type rsm_set() :: #rsm_set{}.
-record(mam_fin, {id = <<>> :: binary(), -record(mam_fin, {xmlns = <<>> :: binary(),
id = <<>> :: binary(),
rsm :: #rsm_set{}, rsm :: #rsm_set{},
stable :: boolean(), stable :: boolean(),
complete :: boolean()}). complete :: boolean()}).

View File

@ -2663,7 +2663,7 @@ make_resume_id(StateData) ->
add_resent_delay_info(_State, #iq{} = El, _Time) -> add_resent_delay_info(_State, #iq{} = El, _Time) ->
El; El;
add_resent_delay_info(#state{server = From}, El, Time) -> 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 %%% XEP-0352

View File

@ -130,34 +130,37 @@ stop(Host) ->
{wait, Proc}. {wait, Proc}.
%% Announcing via messages to a custom resource %% 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) -> announce(From, #jid{luser = <<>>} = To, #message{} = Packet) ->
Proc = gen_mod:get_module_proc(To#jid.lserver, ?PROCNAME), Proc = gen_mod:get_module_proc(To#jid.lserver, ?PROCNAME),
case To#jid.lresource of Res = case To#jid.lresource of
<<"announce/all">> -> <<"announce/all">> ->
Proc ! {announce_all, From, To, Packet}; Proc ! {announce_all, From, To, Packet};
<<"announce/all-hosts/all">> -> <<"announce/all-hosts/all">> ->
Proc ! {announce_all_hosts_all, From, To, Packet}; Proc ! {announce_all_hosts_all, From, To, Packet};
<<"announce/online">> -> <<"announce/online">> ->
Proc ! {announce_online, From, To, Packet}; Proc ! {announce_online, From, To, Packet};
<<"announce/all-hosts/online">> -> <<"announce/all-hosts/online">> ->
Proc ! {announce_all_hosts_online, From, To, Packet}; Proc ! {announce_all_hosts_online, From, To, Packet};
<<"announce/motd">> -> <<"announce/motd">> ->
Proc ! {announce_motd, From, To, Packet}; Proc ! {announce_motd, From, To, Packet};
<<"announce/all-hosts/motd">> -> <<"announce/all-hosts/motd">> ->
Proc ! {announce_all_hosts_motd, From, To, Packet}; Proc ! {announce_all_hosts_motd, From, To, Packet};
<<"announce/motd/update">> -> <<"announce/motd/update">> ->
Proc ! {announce_motd_update, From, To, Packet}; Proc ! {announce_motd_update, From, To, Packet};
<<"announce/all-hosts/motd/update">> -> <<"announce/all-hosts/motd/update">> ->
Proc ! {announce_all_hosts_motd_update, From, To, Packet}; Proc ! {announce_all_hosts_motd_update, From, To, Packet};
<<"announce/motd/delete">> -> <<"announce/motd/delete">> ->
Proc ! {announce_motd_delete, From, To, Packet}; Proc ! {announce_motd_delete, From, To, Packet};
<<"announce/all-hosts/motd/delete">> -> <<"announce/all-hosts/motd/delete">> ->
Proc ! {announce_all_hosts_motd_delete, From, To, Packet}; Proc ! {announce_all_hosts_motd_delete, From, To, Packet};
_ -> _ ->
ok ok
end, end,
ok; case Res of
ok -> ok;
_ -> stop
end;
announce(_From, _To, _Packet) -> announce(_From, _To, _Packet) ->
ok. ok.

View File

@ -74,39 +74,37 @@ process_iq(IQ) ->
-spec process_iq_get({error, stanza_error()} | {result, xmpp_element() | undefined}, -spec process_iq_get({error, stanza_error()} | {result, xmpp_element() | undefined},
iq(), userlist()) -> iq(), userlist()) ->
{error, stanza_error()} | {result, block_list()}. {error, stanza_error()} |
{result, xmpp_element() | undefined}.
process_iq_get(_, #iq{lang = Lang, from = From, process_iq_get(_, #iq{lang = Lang, from = From,
sub_els = [#block_list{}]}, _) -> sub_els = [#block_list{}]}, _) ->
#jid{luser = LUser, lserver = LServer} = From, #jid{luser = LUser, lserver = LServer} = From,
{stop, process_blocklist_get(LUser, LServer, Lang)}; process_blocklist_get(LUser, LServer, Lang);
process_iq_get(Acc, _, _) -> Acc. process_iq_get(Acc, _, _) -> Acc.
-spec process_iq_set({error, stanza_error()} | -spec process_iq_set({error, stanza_error()} |
{result, xmpp_element() | undefined} | {result, xmpp_element() | undefined} |
{result, xmpp_element() | undefined, userlist()}, {result, xmpp_element() | undefined, userlist()},
iq()) -> {error, stanza_error()} | iq()) -> {error, stanza_error()} |
{result, undefined} | {result, xmpp_element() | undefined} |
{result, undefined, userlist()}. {result, xmpp_element() | undefined, userlist()}.
process_iq_set(_, #iq{from = From, lang = Lang, sub_els = [SubEl]}) -> process_iq_set(Acc, #iq{from = From, lang = Lang, sub_els = [SubEl]}) ->
#jid{luser = LUser, lserver = LServer} = From, #jid{luser = LUser, lserver = LServer} = From,
Res = case SubEl of case SubEl of
#block{items = []} -> #block{items = []} ->
Txt = <<"No items found in this query">>, Txt = <<"No items found in this query">>,
{error, xmpp:err_bad_request(Txt, Lang)}; {error, xmpp:err_bad_request(Txt, Lang)};
#block{items = Items} -> #block{items = Items} ->
JIDs = [jid:tolower(Item) || Item <- Items], JIDs = [jid:tolower(Item) || Item <- Items],
process_blocklist_block(LUser, LServer, JIDs, Lang); process_blocklist_block(LUser, LServer, JIDs, Lang);
#unblock{items = []} -> #unblock{items = []} ->
process_blocklist_unblock_all(LUser, LServer, Lang); process_blocklist_unblock_all(LUser, LServer, Lang);
#unblock{items = Items} -> #unblock{items = Items} ->
JIDs = [jid:tolower(Item) || Item <- Items], JIDs = [jid:tolower(Item) || Item <- Items],
process_blocklist_unblock(LUser, LServer, JIDs, Lang); process_blocklist_unblock(LUser, LServer, JIDs, Lang);
_ -> _ ->
Txt = <<"Only <block/> and <unblock/> are allowed " Acc
"in this request">>, end;
{error, xmpp:err_bad_request(Txt, Lang)}
end,
{stop, Res};
process_iq_set(Acc, _) -> Acc. process_iq_set(Acc, _) -> Acc.
-spec list_to_blocklist_jids([listitem()], [ljid()]) -> [ljid()]. -spec list_to_blocklist_jids([listitem()], [ljid()]) -> [ljid()].

View File

@ -277,7 +277,7 @@ get_queue(C2SState) ->
get_stanzas(Queue, Host) -> get_stanzas(Queue, Host) ->
lists:map(fun({_Key, Time, Stanza}) -> 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">>) <<"Client Inactive">>)
end, Queue). end, Queue).

View File

@ -834,6 +834,10 @@ msg_to_el(#archive_msg{timestamp = TS, packet = Pkt1, nick = Nick, peer = Peer},
#forwarded{sub_els = [Pkt2], #forwarded{sub_els = [Pkt2],
delay = #delay{stamp = TS, from = jid:make(LServer)}}. 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, maybe_update_from_to(#message{sub_els = Els} = Pkt, JidRequestor, JidArchive,
Peer, {groupchat, Role, Peer, {groupchat, Role,
#state{config = #config{anonymous = Anon}}}, #state{config = #config{anonymous = Anon}}},
@ -908,7 +912,8 @@ send(Msgs, Count, IsComplete,
Result = if NS == ?NS_MAM_TMP -> Result = if NS == ?NS_MAM_TMP ->
#mam_query{xmlns = NS, id = QID, rsm = RSMOut}; #mam_query{xmlns = NS, id = QID, rsm = RSMOut};
true -> true ->
#mam_fin{id = QID, rsm = RSMOut, complete = IsComplete} #mam_fin{xmlns = NS, id = QID, rsm = RSMOut,
complete = IsComplete}
end, end,
if NS == ?NS_MAM_TMP; NS == ?NS_MAM_1 -> if NS == ?NS_MAM_TMP; NS == ?NS_MAM_1 ->
lists:foreach( lists:foreach(
@ -950,6 +955,8 @@ limit_max(#rsm_set{max = Max} = RSM, _NS) when Max > ?MAX_PAGE_SIZE ->
limit_max(RSM, _NS) -> limit_max(RSM, _NS) ->
RSM. RSM.
match_interval(Now, Start, undefined) ->
Now >= Start;
match_interval(Now, Start, End) -> match_interval(Now, Start, End) ->
(Now >= Start) and (Now =< End). (Now >= Start) and (Now =< End).

View File

@ -134,7 +134,10 @@ select(_LServer, JidRequestor,
#jid{luser = LUser, lserver = LServer} = JidArchive, #jid{luser = LUser, lserver = LServer} = JidArchive,
#mam_query{start = Start, 'end' = End, #mam_query{start = Start, 'end' = End,
with = With, rsm = RSM}, MsgType) -> 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), Msgs = mnesia:dirty_select(archive_msg, MS),
SortedMsgs = lists:keysort(#archive_msg.timestamp, Msgs), SortedMsgs = lists:keysort(#archive_msg.timestamp, Msgs),
{FilteredMsgs, IsComplete} = filter_by_rsm(SortedMsgs, RSM), {FilteredMsgs, IsComplete} = filter_by_rsm(SortedMsgs, RSM),
@ -155,6 +158,9 @@ select(_LServer, JidRequestor,
now_to_usec({MSec, Sec, USec}) -> now_to_usec({MSec, Sec, USec}) ->
(MSec*1000000 + Sec)*1000000 + 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) -> make_matchspec(LUser, LServer, Start, End, {_, _, <<>>} = With) ->
ets:fun2ms( ets:fun2ms(
fun(#archive_msg{timestamp = TS, fun(#archive_msg{timestamp = TS,

View File

@ -209,19 +209,18 @@ do_route(_State, _From, _To, _Packet) ->
subscribe_nodes(From, To, Nodes) -> subscribe_nodes(From, To, Nodes) ->
LTo = jid:tolower(jid:remove_resource(To)), LTo = jid:tolower(jid:remove_resource(To)),
LFrom = jid:tolower(jid:remove_resource(From)), LFrom = jid:tolower(jid:remove_resource(From)),
From_s = jid:to_string(LFrom),
lists:foldl( lists:foldl(
fun(_Node, {error, _} = Err) -> fun(_Node, {error, _} = Err) ->
Err; Err;
(Node, {result, _}) -> (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 -> {error, _} = Err ->
case is_item_not_found(Err) of case is_item_not_found(Err) of
true -> true ->
case mod_pubsub:create_node( case mod_pubsub:create_node(
LTo, To#jid.lserver, Node, LFrom, <<"mix">>) of LTo, To#jid.lserver, Node, LFrom, <<"mix">>) of
{result, _} -> {result, _} ->
mod_pubsub:subscribe_node(LTo, Node, From, From_s, []); mod_pubsub:subscribe_node(LTo, Node, From, From, []);
Error -> Error ->
Error Error
end; end;
@ -235,13 +234,12 @@ subscribe_nodes(From, To, Nodes) ->
unsubscribe_nodes(From, To, Nodes) -> unsubscribe_nodes(From, To, Nodes) ->
LTo = jid:tolower(jid:remove_resource(To)), LTo = jid:tolower(jid:remove_resource(To)),
LFrom = jid:tolower(jid:remove_resource(From)), BareFrom = jid:remove_resource(From),
From_s = jid:to_string(LFrom),
lists:foldl( lists:foldl(
fun(_Node, {error, _} = Err) -> fun(_Node, {error, _} = Err) ->
Err; Err;
(Node, {result, _} = Result) -> (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 -> {error, _} = Err ->
case is_not_subscribed(Err) of case is_not_subscribed(Err) of
true -> Result; true -> Result;
@ -297,19 +295,16 @@ delete_item(From, To, Node, ItemID) ->
end end
end. end.
is_item_not_found({error, ErrEl}) -> -spec is_item_not_found({error, stanza_error()}) -> boolean().
case fxml:get_subtag_with_xmlns( is_item_not_found({error, #stanza_error{reason = 'item-not-found'}}) -> true;
ErrEl, <<"item-not-found">>, ?NS_STANZAS) of is_item_not_found({error, _}) -> false.
#xmlel{} -> true;
_ -> false
end.
is_not_subscribed({error, ErrEl}) -> -spec is_not_subscribed({error, stanza_error()}) -> boolean().
case fxml:get_subtag_with_xmlns( is_not_subscribed({error, #stanza_error{sub_els = Els}}) ->
ErrEl, <<"not-subscribed">>, ?NS_PUBSUB_ERRORS) of %% TODO: make xmpp:get_els function working for any XMPP element
#xmlel{} -> true; %% with sub_els field
_ -> false xmpp:has_subtag(#message{sub_els = Els},
end. #ps_error{type = 'not-subscribed'}).
depends(_Host, _Opts) -> depends(_Host, _Opts) ->
[{mod_pubsub, hard}]. [{mod_pubsub, hard}].

View File

@ -668,17 +668,17 @@ get_nick(ServerHost, Host, From) ->
Mod:get_nick(LServer, Host, From). Mod:get_nick(LServer, Host, From).
iq_get_register_info(ServerHost, Host, From, Lang) -> iq_get_register_info(ServerHost, Host, From, Lang) ->
{Nick, Registered} = case get_nick(ServerHost, Host, From) of {Nick, NickVals, Registered} = case get_nick(ServerHost, Host, From) of
error -> {<<"">>, false}; error -> {<<"">>, [], false};
N -> {N, true} N -> {N, [N], true}
end, end,
Title = <<(translate:translate( Title = <<(translate:translate(
Lang, <<"Nickname Registration at ">>))/binary, Host/binary>>, Lang, <<"Nickname Registration at ">>))/binary, Host/binary>>,
Inst = translate:translate(Lang, <<"Enter nickname you want to register">>), Inst = translate:translate(Lang, <<"Enter nickname you want to register">>),
Field = #xdata_field{type = 'text-single', Field = #xdata_field{type = 'text-single',
label = translate:translate(Lang, <<"Nickname">>), label = translate:translate(Lang, <<"Nickname">>),
var = <<"nick">>, var = <<"nick">>,
values = [Nick]}, values = NickVals},
X = #xdata{type = form, title = Title, X = #xdata{type = form, title = Title,
instructions = [Inst], fields = [Field]}, instructions = [Inst], fields = [Field]},
#register{nick = Nick, #register{nick = Nick,

View File

@ -616,7 +616,7 @@ offline_msg_to_route(LServer, #offline_msg{} = R) ->
undefined -> undefined ->
Pkt; Pkt;
TS -> TS ->
xmpp_util:add_delay_info(Pkt, LServer, TS, xmpp_util:add_delay_info(Pkt, jid:make(LServer), TS,
<<"Offline Storage">>) <<"Offline Storage">>)
end, end,
{route, R#offline_msg.from, R#offline_msg.to, Pkt1}. {route, R#offline_msg.from, R#offline_msg.to, Pkt1}.

View File

@ -101,7 +101,8 @@ process_iq(IQ) ->
xmpp:make_error(IQ, xmpp:err_not_allowed()). xmpp:make_error(IQ, xmpp:err_not_allowed()).
-spec process_iq_get({error, stanza_error()} | {result, xmpp_element() | undefined}, -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, process_iq_get(_, #iq{from = From, lang = Lang,
sub_els = [#privacy_query{lists = Lists}]}, sub_els = [#privacy_query{lists = Lists}]},
#userlist{name = Active}) -> #userlist{name = Active}) ->
@ -114,7 +115,9 @@ process_iq_get(_, #iq{from = From, lang = Lang,
_ -> _ ->
Txt = <<"Too many <list/> elements">>, Txt = <<"Too many <list/> elements">>,
{error, xmpp:err_bad_request(Txt, Lang)} {error, xmpp:err_bad_request(Txt, Lang)}
end. end;
process_iq_get(Acc, _, _) ->
Acc.
-spec process_lists_get(binary(), binary(), binary(), binary()) -> -spec process_lists_get(binary(), binary(), binary(), binary()) ->
{error, stanza_error()} | {result, privacy_query()}. {error, stanza_error()} | {result, privacy_query()}.
@ -218,7 +221,8 @@ decode_value(Type, Value) ->
{result, xmpp_element() | undefined} | {result, xmpp_element() | undefined} |
{result, xmpp_element() | undefined, userlist()}, {result, xmpp_element() | undefined, userlist()},
iq()) -> {error, stanza_error()} | iq()) -> {error, stanza_error()} |
{result, undefined, userlist()}. {result, xmpp_element() | undefined} |
{result, xmpp_element() | undefined, userlist()}.
process_iq_set(_, #iq{from = From, lang = Lang, process_iq_set(_, #iq{from = From, lang = Lang,
sub_els = [#privacy_query{default = Default, sub_els = [#privacy_query{default = Default,
active = Active, active = Active,
@ -236,7 +240,9 @@ process_iq_set(_, #iq{from = From, lang = Lang,
Txt = <<"There should be exactly one element in this query: " Txt = <<"There should be exactly one element in this query: "
"<list/>, <active/> or <default/>">>, "<list/>, <active/> or <default/>">>,
{error, xmpp:err_bad_request(Txt, Lang)} {error, xmpp:err_bad_request(Txt, Lang)}
end. end;
process_iq_set(Acc, _) ->
Acc.
-spec process_default_set(binary(), binary(), none | binary(), -spec process_default_set(binary(), binary(), none | binary(),
binary()) -> {error, stanza_error()} | {result, undefined}. binary()) -> {error, stanza_error()} | {result, undefined}.

View File

@ -69,9 +69,7 @@
tree_action/3, node_action/4, node_call/4]). tree_action/3, node_action/4, node_call/4]).
%% general helpers for plugins %% general helpers for plugins
-export([subscription_to_string/1, affiliation_to_string/1, -export([extended_error/2, service_jid/1,
string_to_subscription/1, string_to_affiliation/1,
extended_error/2, service_jid/1,
tree/1, tree/2, plugin/2, plugins/1, config/3, tree/1, tree/2, plugin/2, plugins/1, config/3,
host/1, serverhost/1]). host/1, serverhost/1]).
@ -2170,7 +2168,7 @@ get_items(Host, Node, From, SubId, SMaxItems, ItemIds, RSM) ->
get_items(Host, Node) -> get_items(Host, Node) ->
Action = fun (#pubsub_node{type = Type, id = Nidx}) -> 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, end,
case transaction(Host, Node, Action, sync_dirty) of case transaction(Host, Node, Action, sync_dirty) of
{result, {_, {Items, _}}} -> Items; {result, {_, {Items, _}}} -> Items;
@ -2187,7 +2185,7 @@ get_item(Host, Node, ItemId) ->
end. end.
get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) -> 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}; {result, {Items, _RSM}} -> {result, Items};
Error -> Error Error -> Error
end. end.
@ -2203,7 +2201,7 @@ get_last_item(Host, Type, Nidx, LJID) ->
LastItem -> LastItem LastItem -> LastItem
end. end.
get_last_item(Host, Type, Nidx, LJID, mnesia) -> 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; {result, {[LastItem|_], _}} -> LastItem;
_ -> undefined _ -> undefined
end; 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) ->
get_last_items(Host, Type, Nidx, LJID, Number, gen_mod:db_type(serverhost(Host), ?MODULE)). get_last_items(Host, Type, Nidx, LJID, Number, gen_mod:db_type(serverhost(Host), ?MODULE)).
get_last_items(Host, Type, Nidx, LJID, Number, mnesia) -> 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); {result, {Items, _}} -> lists:sublist(Items, Number);
_ -> [] _ -> []
end; 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, AllowedGroups) ->
get_roster_info(OwnerUser, OwnerServer, jid:tolower(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(). -spec service_jid(jid() | ljid() | binary()) -> jid().
service_jid(#jid{} = Jid) -> Jid; service_jid(#jid{} = Jid) -> Jid;
service_jid({U, S, R}) -> jid:make(U, S, R); service_jid({U, S, R}) -> jid:make(U, S, R);

View File

@ -146,12 +146,10 @@ process_iq(#iq{type = set, lang = Lang, to = To, from = From,
end; end;
true -> true ->
case From of case From of
#jid{user = User, lserver = Server, resource = Resource} -> #jid{luser = LUser, lserver = Server} ->
ResIQ = xmpp:make_iq_result(IQ), ResIQ = xmpp:make_iq_result(IQ),
ejabberd_router:route(jid:make(User, Server, Resource), ejabberd_router:route(From, From, ResIQ),
jid:make(User, Server, Resource), ejabberd_auth:remove_user(LUser, Server),
ResIQ),
ejabberd_auth:remove_user(User, Server),
ignore; ignore;
_ -> _ ->
Txt = <<"The query is only allowed from local users">>, Txt = <<"The query is only allowed from local users">>,

View File

@ -308,13 +308,13 @@ encode_item(Item) ->
end, end,
groups = Item#roster.groups}. 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), R#roster{jid = jid:tolower(Item#roster_item.jid),
name = Item#roster_item.name, name = Item#roster_item.name,
subscription = case Item#roster_item.subscription of subscription = case Item#roster_item.subscription of
remove -> remove; remove -> remove;
Sub when Managed -> Sub; Sub when Managed -> Sub;
_ -> undefined _ -> R#roster.subscription
end, end,
groups = Item#roster_item.groups}. groups = Item#roster_item.groups}.
@ -334,45 +334,48 @@ try_process_iq_set(#iq{from = From, lang = Lang} = IQ) ->
end. end.
process_iq_set(#iq{from = From, to = To, id = Id, 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), 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, #jid{user = User, luser = LUser, lserver = LServer} = From,
LJID = jid:tolower(JID1),
F = fun () -> F = fun () ->
Item = get_roster_by_jid_t(LUser, LServer, LJID), lists:map(
Item2 = decode_item(QueryItem, Item, Managed), fun(#roster_item{jid = JID1} = QueryItem) ->
Item3 = ejabberd_hooks:run_fold(roster_process_item, LJID = jid:tolower(JID1),
LServer, Item2, Item = get_roster_by_jid_t(LUser, LServer, LJID),
[LServer]), Item2 = decode_item(QueryItem, Item, Managed),
case Item3#roster.subscription of Item3 = ejabberd_hooks:run_fold(roster_process_item,
remove -> del_roster_t(LUser, LServer, LJID); LServer, Item2,
_ -> update_roster_t(LUser, LServer, LJID, Item3) [LServer]),
end, case Item3#roster.subscription of
send_itemset_to_managers(From, Item3, Managed), remove -> del_roster_t(LUser, LServer, LJID);
case roster_version_on_db(LServer) of _ -> update_roster_t(LUser, LServer, LJID, Item3)
true -> write_roster_version_t(LUser, LServer); end,
false -> ok case roster_version_on_db(LServer) of
end, true -> write_roster_version_t(LUser, LServer);
{Item, Item3} false -> ok
end,
{Item, Item3}
end, QueryItems)
end, end,
case transaction(LServer, F) of case transaction(LServer, F) of
{atomic, {OldItem, Item}} -> {atomic, ItemPairs} ->
push_item(User, LServer, To, Item), lists:foreach(
case Item#roster.subscription of fun({OldItem, Item}) ->
remove -> send_itemset_to_managers(From, Item, Managed),
send_unsubscribing_presence(From, OldItem), ok; push_item(User, LServer, To, Item),
_ -> ok case Item#roster.subscription of
end; remove ->
send_unsubscribing_presence(From, OldItem);
_ ->
ok
end
end, ItemPairs),
xmpp:make_iq_result(IQ);
E -> E ->
?DEBUG("ROSTER: roster item set error: ~p~n", [E]), ok ?ERROR_MSG("roster set failed:~nIQ = ~s~nError = ~p",
end; [xmpp:pp(IQ), E]),
process_item_set(_From, _To, _, _Managed) -> ok. xmpp:make_error(IQ, xmpp:err_internal_server_error())
end.
push_item(User, Server, From, Item) -> push_item(User, Server, From, Item) ->
ejabberd_sm:route(jid:make(<<"">>, <<"">>, <<"">>), ejabberd_sm:route(jid:make(<<"">>, <<"">>, <<"">>),

View File

@ -137,7 +137,7 @@ stop(Host) ->
?NS_VCARD), ?NS_VCARD),
ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE,
get_sm_features, 50), get_sm_features, 50),
Mod = gen_mod:db_type(Host, ?MODULE), Mod = gen_mod:db_mod(Host, ?MODULE),
Mod:stop(Host), Mod:stop(Host),
Proc = gen_mod:get_module_proc(Host, ?PROCNAME), Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
Proc ! stop, Proc ! stop,

View File

@ -248,10 +248,10 @@ ldap_attribute_to_vcard({Attr, Value}, V) ->
<<"tel">> -> V#vcard_temp{tel = [#vcard_tel{number = Value}|Ts]}; <<"tel">> -> V#vcard_temp{tel = [#vcard_tel{number = Value}|Ts]};
<<"email">> -> V#vcard_temp{email = [#vcard_email{userid = Value}|Es]}; <<"email">> -> V#vcard_temp{email = [#vcard_email{userid = Value}|Es]};
<<"photo">> -> V#vcard_temp{photo = #vcard_photo{binval = Value}}; <<"photo">> -> V#vcard_temp{photo = #vcard_photo{binval = Value}};
<<"family">> -> V#vcard_temp{n = N#vcard_name{family = V}}; <<"family">> -> V#vcard_temp{n = N#vcard_name{family = Value}};
<<"given">> -> V#vcard_temp{n = N#vcard_name{given = V}}; <<"given">> -> V#vcard_temp{n = N#vcard_name{given = Value}};
<<"middle">> -> V#vcard_temp{n = N#vcard_name{middle = V}}; <<"middle">> -> V#vcard_temp{n = N#vcard_name{middle = Value}};
<<"orgname">> -> V#vcard_temp{org = O#vcard_org{name = V}}; <<"orgname">> -> V#vcard_temp{org = O#vcard_org{name = Value}};
<<"orgunit">> -> V#vcard_temp{org = O#vcard_org{units = [Value]}}; <<"orgunit">> -> V#vcard_temp{org = O#vcard_org{units = [Value]}};
<<"locality">> -> V#vcard_temp{adr = [A#vcard_adr{locality = Value}]}; <<"locality">> -> V#vcard_temp{adr = [A#vcard_adr{locality = Value}]};
<<"street">> -> V#vcard_temp{adr = [A#vcard_adr{street = Value}]}; <<"street">> -> V#vcard_temp{adr = [A#vcard_adr{street = Value}]};

View File

@ -52,7 +52,7 @@ depends(_Host, _Opts) ->
%% Hooks %% Hooks
%%==================================================================== %%====================================================================
-spec update_presence(presence(), binary(), binary()) -> presence(). -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); presence_with_xupdate(Packet, User, Host);
update_presence(Packet, _User, _Host) -> Packet. update_presence(Packet, _User, _Host) -> Packet.

View File

@ -707,7 +707,7 @@ del_state(Nidx, Key) ->
%% relational database), or they can even decide not to persist any items.</p> %% relational database), or they can even decide not to persist any items.</p>
get_items(Nidx, _From, _RSM) -> get_items(Nidx, _From, _RSM) ->
Items = mnesia:match_object(#pubsub_item{itemid = {'_', Nidx}, _ = '_'}), 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) -> get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, RSM) ->
SubKey = jid:tolower(JID), SubKey = jid:tolower(JID),

View File

@ -286,6 +286,8 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) ->
_el); _el);
{<<"fin">>, <<"urn:xmpp:mam:0">>} -> {<<"fin">>, <<"urn:xmpp:mam:0">>} ->
decode_mam_fin(<<"urn:xmpp:mam:0">>, IgnoreEls, _el); 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">>} -> {<<"prefs">>, <<"urn:xmpp:mam:0">>} ->
decode_mam_prefs(<<"urn:xmpp:mam:0">>, IgnoreEls, _el); decode_mam_prefs(<<"urn:xmpp:mam:0">>, IgnoreEls, _el);
{<<"prefs">>, <<"urn:xmpp:mam:1">>} -> {<<"prefs">>, <<"urn:xmpp:mam:1">>} ->
@ -1688,6 +1690,7 @@ is_known_tag({xmlel, _name, _attrs, _} = _el) ->
{<<"disable">>, <<"urn:xmpp:carbons:2">>} -> true; {<<"disable">>, <<"urn:xmpp:carbons:2">>} -> true;
{<<"forwarded">>, <<"urn:xmpp:forward:0">>} -> true; {<<"forwarded">>, <<"urn:xmpp:forward:0">>} -> true;
{<<"fin">>, <<"urn:xmpp:mam:0">>} -> true; {<<"fin">>, <<"urn:xmpp:mam:0">>} -> true;
{<<"fin">>, <<"urn:xmpp:mam:1">>} -> true;
{<<"prefs">>, <<"urn:xmpp:mam:0">>} -> true; {<<"prefs">>, <<"urn:xmpp:mam:0">>} -> true;
{<<"prefs">>, <<"urn:xmpp:mam:1">>} -> true; {<<"prefs">>, <<"urn:xmpp:mam:1">>} -> true;
{<<"prefs">>, <<"urn:xmpp:mam:tmp">>} -> true; {<<"prefs">>, <<"urn:xmpp:mam:tmp">>} -> true;
@ -2978,9 +2981,8 @@ encode({mam_result, _, _, _, _} = Result) ->
encode_mam_result(Result, []); encode_mam_result(Result, []);
encode({mam_prefs, _, _, _, _} = Prefs) -> encode({mam_prefs, _, _, _, _} = Prefs) ->
encode_mam_prefs(Prefs, []); encode_mam_prefs(Prefs, []);
encode({mam_fin, _, _, _, _} = Fin) -> encode({mam_fin, _, _, _, _, _} = Fin) ->
encode_mam_fin(Fin, encode_mam_fin(Fin, []);
[{<<"xmlns">>, <<"urn:xmpp:mam:0">>}]);
encode({forwarded, _, _} = Forwarded) -> encode({forwarded, _, _} = Forwarded) ->
encode_forwarded(Forwarded, encode_forwarded(Forwarded,
[{<<"xmlns">>, <<"urn:xmpp:forward:0">>}]); [{<<"xmlns">>, <<"urn:xmpp:forward:0">>}]);
@ -3196,7 +3198,7 @@ get_name({iq, _, _, _, _, _, _}) -> <<"iq">>;
get_name({last, _, _}) -> <<"query">>; get_name({last, _, _}) -> <<"query">>;
get_name({legacy_auth, _, _, _, _}) -> <<"query">>; get_name({legacy_auth, _, _, _, _}) -> <<"query">>;
get_name({mam_archived, _, _}) -> <<"archived">>; get_name({mam_archived, _, _}) -> <<"archived">>;
get_name({mam_fin, _, _, _, _}) -> <<"fin">>; get_name({mam_fin, _, _, _, _, _}) -> <<"fin">>;
get_name({mam_prefs, _, _, _, _}) -> <<"prefs">>; get_name({mam_prefs, _, _, _, _}) -> <<"prefs">>;
get_name({mam_query, _, _, _, _, _, _, _, _}) -> get_name({mam_query, _, _, _, _, _, _, _, _}) ->
<<"query">>; <<"query">>;
@ -3466,7 +3468,7 @@ get_ns({last, _, _}) -> <<"jabber:iq:last">>;
get_ns({legacy_auth, _, _, _, _}) -> get_ns({legacy_auth, _, _, _, _}) ->
<<"jabber:iq:auth">>; <<"jabber:iq:auth">>;
get_ns({mam_archived, _, _}) -> <<"urn:xmpp:mam:tmp">>; 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_prefs, Xmlns, _, _, _}) -> Xmlns;
get_ns({mam_query, Xmlns, _, _, _, _, _, _, _}) -> get_ns({mam_query, Xmlns, _, _, _, _, _, _, _}) ->
Xmlns; Xmlns;
@ -3898,7 +3900,7 @@ pp(mam_query, 8) ->
pp(mam_archived, 2) -> [by, id]; pp(mam_archived, 2) -> [by, id];
pp(mam_result, 4) -> [xmlns, queryid, id, sub_els]; pp(mam_result, 4) -> [xmlns, queryid, id, sub_els];
pp(mam_prefs, 4) -> [xmlns, default, always, never]; 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(forwarded, 2) -> [delay, sub_els];
pp(carbons_disable, 0) -> []; pp(carbons_disable, 0) -> [];
pp(carbons_enable, 0) -> []; pp(carbons_enable, 0) -> [];
@ -8600,10 +8602,10 @@ decode_mam_fin(__TopXMLNS, __IgnoreEls,
{xmlel, <<"fin">>, _attrs, _els}) -> {xmlel, <<"fin">>, _attrs, _els}) ->
Rsm = decode_mam_fin_els(__TopXMLNS, __IgnoreEls, _els, Rsm = decode_mam_fin_els(__TopXMLNS, __IgnoreEls, _els,
undefined), undefined),
{Id, Stable, Complete} = {Id, Xmlns, Stable, Complete} =
decode_mam_fin_attrs(__TopXMLNS, _attrs, undefined, decode_mam_fin_attrs(__TopXMLNS, _attrs, undefined,
undefined, undefined), undefined, undefined, undefined),
{mam_fin, Id, Rsm, Stable, Complete}. {mam_fin, Xmlns, Id, Rsm, Stable, Complete}.
decode_mam_fin_els(__TopXMLNS, __IgnoreEls, [], Rsm) -> decode_mam_fin_els(__TopXMLNS, __IgnoreEls, [], Rsm) ->
Rsm; Rsm;
@ -8622,37 +8624,45 @@ decode_mam_fin_els(__TopXMLNS, __IgnoreEls, [_ | _els],
decode_mam_fin_els(__TopXMLNS, __IgnoreEls, _els, Rsm). decode_mam_fin_els(__TopXMLNS, __IgnoreEls, _els, Rsm).
decode_mam_fin_attrs(__TopXMLNS, decode_mam_fin_attrs(__TopXMLNS,
[{<<"queryid">>, _val} | _attrs], _Id, Stable, [{<<"queryid">>, _val} | _attrs], _Id, Xmlns, Stable,
Complete) -> Complete) ->
decode_mam_fin_attrs(__TopXMLNS, _attrs, _val, Stable, decode_mam_fin_attrs(__TopXMLNS, _attrs, _val, Xmlns,
Complete); Stable, Complete);
decode_mam_fin_attrs(__TopXMLNS, decode_mam_fin_attrs(__TopXMLNS,
[{<<"stable">>, _val} | _attrs], Id, _Stable, [{<<"xmlns">>, _val} | _attrs], Id, _Xmlns, Stable,
Complete) -> Complete) ->
decode_mam_fin_attrs(__TopXMLNS, _attrs, Id, _val, decode_mam_fin_attrs(__TopXMLNS, _attrs, Id, _val,
Complete); Stable, Complete);
decode_mam_fin_attrs(__TopXMLNS, 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) -> _Complete) ->
decode_mam_fin_attrs(__TopXMLNS, _attrs, Id, Stable, decode_mam_fin_attrs(__TopXMLNS, _attrs, Id, Xmlns,
_val); Stable, _val);
decode_mam_fin_attrs(__TopXMLNS, [_ | _attrs], Id, decode_mam_fin_attrs(__TopXMLNS, [_ | _attrs], Id,
Stable, Complete) -> Xmlns, Stable, Complete) ->
decode_mam_fin_attrs(__TopXMLNS, _attrs, Id, Stable, decode_mam_fin_attrs(__TopXMLNS, _attrs, Id, Xmlns,
Complete); Stable, Complete);
decode_mam_fin_attrs(__TopXMLNS, [], Id, Stable, decode_mam_fin_attrs(__TopXMLNS, [], Id, Xmlns, Stable,
Complete) -> Complete) ->
{decode_mam_fin_attr_queryid(__TopXMLNS, Id), {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_stable(__TopXMLNS, Stable),
decode_mam_fin_attr_complete(__TopXMLNS, Complete)}. 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) -> _xmlns_attrs) ->
_els = lists:reverse('encode_mam_fin_$rsm'(Rsm, [])), _els = lists:reverse('encode_mam_fin_$rsm'(Rsm, [])),
_attrs = encode_mam_fin_attr_complete(Complete, _attrs = encode_mam_fin_attr_complete(Complete,
encode_mam_fin_attr_stable(Stable, encode_mam_fin_attr_stable(Stable,
encode_mam_fin_attr_queryid(Id, encode_mam_fin_attr_xmlns(Xmlns,
_xmlns_attrs))), encode_mam_fin_attr_queryid(Id,
_xmlns_attrs)))),
{xmlel, <<"fin">>, _attrs, _els}. {xmlel, <<"fin">>, _attrs, _els}.
'encode_mam_fin_$rsm'(undefined, _acc) -> _acc; '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) -> encode_mam_fin_attr_queryid(_val, _acc) ->
[{<<"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) -> decode_mam_fin_attr_stable(__TopXMLNS, undefined) ->
undefined; undefined;
decode_mam_fin_attr_stable(__TopXMLNS, _val) -> decode_mam_fin_attr_stable(__TopXMLNS, _val) ->

View File

@ -68,7 +68,7 @@ unwrap_carbon(Stanza) -> Stanza.
-spec is_standalone_chat_state(stanza()) -> boolean(). -spec is_standalone_chat_state(stanza()) -> boolean().
is_standalone_chat_state(Stanza) -> is_standalone_chat_state(Stanza) ->
case unwrap_carbon(Stanza) of case unwrap_carbon(Stanza) of
#message{sub_els = Els} -> #message{body = [], subject = [], sub_els = Els} ->
IgnoreNS = [?NS_CHATSTATES, ?NS_DELAY], IgnoreNS = [?NS_CHATSTATES, ?NS_DELAY],
Stripped = [El || El <- Els, Stripped = [El || El <- Els,
not lists:member(xmpp:get_ns(El), IgnoreNS)], not lists:member(xmpp:get_ns(El), IgnoreNS)],

View File

@ -25,7 +25,7 @@
-include("suite.hrl"). -include("suite.hrl").
suite() -> suite() ->
[{timetrap, {seconds,120}}]. [{timetrap, {seconds,10}}].
init_per_suite(Config) -> init_per_suite(Config) ->
NewConfig = init_config(Config), NewConfig = init_config(Config),
@ -432,8 +432,8 @@ test_register(Config) ->
register(Config) -> register(Config) ->
#iq{type = result, #iq{type = result,
sub_els = [#register{username = none, sub_els = [#register{username = <<>>,
password = none}]} = password = <<>>}]} =
send_recv(Config, #iq{type = get, to = server_jid(Config), send_recv(Config, #iq{type = get, to = server_jid(Config),
sub_els = [#register{}]}), sub_els = [#register{}]}),
#iq{type = result, sub_els = []} = #iq{type = result, sub_els = []} =
@ -492,31 +492,31 @@ test_open_session(Config) ->
disconnect(open_session(Config)). disconnect(open_session(Config)).
roster_get(Config) -> roster_get(Config) ->
#iq{type = result, sub_els = [#roster{items = []}]} = #iq{type = result, sub_els = [#roster_query{items = []}]} =
send_recv(Config, #iq{type = get, sub_els = [#roster{}]}), send_recv(Config, #iq{type = get, sub_els = [#roster_query{}]}),
disconnect(Config). disconnect(Config).
roster_ver(Config) -> roster_ver(Config) ->
%% Get initial "ver" %% 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, send_recv(Config, #iq{type = get,
sub_els = [#roster{ver = <<"">>}]}), sub_els = [#roster_query{ver = <<"">>}]}),
%% Should receive empty IQ-result %% Should receive empty IQ-result
#iq{type = result, sub_els = []} = #iq{type = result, sub_els = []} =
send_recv(Config, #iq{type = get, send_recv(Config, #iq{type = get,
sub_els = [#roster{ver = Ver1}]}), sub_els = [#roster_query{ver = Ver1}]}),
%% Attempting to subscribe to server's JID %% Attempting to subscribe to server's JID
send(Config, #presence{type = subscribe, to = server_jid(Config)}), send(Config, #presence{type = subscribe, to = server_jid(Config)}),
%% Receive a single roster push with the new "ver" %% 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 %% 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, 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. %% Now requesting roster with the newest "ver". Should receive empty IQ.
#iq{type = result, sub_els = []} = #iq{type = result, sub_els = []} =
send_recv(Config, #iq{type = get, send_recv(Config, #iq{type = get,
sub_els = [#roster{ver = Ver2}]}), sub_els = [#roster_query{ver = Ver2}]}),
disconnect(Config). disconnect(Config).
presence(Config) -> presence(Config) ->
@ -539,7 +539,7 @@ presence_broadcast(Config) ->
lang = <<"en">>, lang = <<"en">>,
name = <<"ejabberd_ct">>}], name = <<"ejabberd_ct">>}],
node = Node, features = [Feature]}, 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]}), send(Config, #presence{sub_els = [Caps]}),
JID = my_jid(Config), JID = my_jid(Config),
%% We receive: %% We receive:
@ -559,10 +559,7 @@ presence_broadcast(Config) ->
lists:foldl( lists:foldl(
fun(Time, []) -> fun(Time, []) ->
timer:sleep(Time), timer:sleep(Time),
mod_caps:get_features( mod_caps:get_features(Server, Caps);
Server,
mod_caps:read_caps(
[xmpp_codec:encode(Caps)]));
(_, Acc) -> (_, Acc) ->
Acc Acc
end, [], [0, 100, 200, 2000, 5000, 10000]), end, [], [0, 100, 200, 2000, 5000, 10000]),
@ -692,12 +689,12 @@ last(Config) ->
privacy(Config) -> privacy(Config) ->
true = is_feature_advertised(Config, ?NS_PRIVACY), true = is_feature_advertised(Config, ?NS_PRIVACY),
#iq{type = result, sub_els = [#privacy{}]} = #iq{type = result, sub_els = [#privacy_query{}]} =
send_recv(Config, #iq{type = get, sub_els = [#privacy{}]}), send_recv(Config, #iq{type = get, sub_els = [#privacy_query{}]}),
JID = <<"tybalt@example.com">>, JID = <<"tybalt@example.com">>,
I1 = send(Config, I1 = send(Config,
#iq{type = set, #iq{type = set,
sub_els = [#privacy{ sub_els = [#privacy_query{
lists = [#privacy_list{ lists = [#privacy_list{
name = <<"public">>, name = <<"public">>,
items = items =
@ -705,41 +702,41 @@ privacy(Config) ->
type = jid, type = jid,
order = 3, order = 3,
action = deny, action = deny,
kinds = ['presence-in'], presence_in = true,
value = JID}]}]}]}), value = JID}]}]}]}),
{Push1, _} = {Push1, _} =
?recv2( ?recv2(
#iq{type = set, #iq{type = set,
sub_els = [#privacy{ sub_els = [#privacy_query{
lists = [#privacy_list{ lists = [#privacy_list{
name = <<"public">>}]}]}, name = <<"public">>}]}]},
#iq{type = result, id = I1, sub_els = []}), #iq{type = result, id = I1, sub_els = []}),
send(Config, make_iq_result(Push1)), send(Config, make_iq_result(Push1)),
#iq{type = result, sub_els = []} = #iq{type = result, sub_els = []} =
send_recv(Config, #iq{type = set, send_recv(Config, #iq{type = set,
sub_els = [#privacy{active = <<"public">>}]}), sub_els = [#privacy_query{active = <<"public">>}]}),
#iq{type = result, sub_els = []} = #iq{type = result, sub_els = []} =
send_recv(Config, #iq{type = set, send_recv(Config, #iq{type = set,
sub_els = [#privacy{default = <<"public">>}]}), sub_els = [#privacy_query{default = <<"public">>}]}),
#iq{type = result, #iq{type = result,
sub_els = [#privacy{default = <<"public">>, sub_els = [#privacy_query{default = <<"public">>,
active = <<"public">>, active = <<"public">>,
lists = [#privacy_list{name = <<"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 = []} = #iq{type = result, sub_els = []} =
send_recv(Config, 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 = []} = #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, I2 = send(Config, #iq{type = set,
sub_els = [#privacy{ sub_els = [#privacy_query{
lists = lists =
[#privacy_list{ [#privacy_list{
name = <<"public">>}]}]}), name = <<"public">>}]}]}),
{Push2, _} = {Push2, _} =
?recv2( ?recv2(
#iq{type = set, #iq{type = set,
sub_els = [#privacy{ sub_els = [#privacy_query{
lists = [#privacy_list{ lists = [#privacy_list{
name = <<"public">>}]}]}, name = <<"public">>}]}]},
#iq{type = result, id = I2, sub_els = []}), #iq{type = result, id = I2, sub_els = []}),
@ -756,7 +753,7 @@ blocking(Config) ->
{Push1, Push2, _} = {Push1, Push2, _} =
?recv3( ?recv3(
#iq{type = set, #iq{type = set,
sub_els = [#privacy{lists = [#privacy_list{}]}]}, sub_els = [#privacy_query{lists = [#privacy_list{}]}]},
#iq{type = set, #iq{type = set,
sub_els = [#block{items = [JID]}]}, sub_els = [#block{items = [JID]}]},
#iq{type = result, id = I1, sub_els = []}), #iq{type = result, id = I1, sub_els = []}),
@ -767,7 +764,7 @@ blocking(Config) ->
{Push3, Push4, _} = {Push3, Push4, _} =
?recv3( ?recv3(
#iq{type = set, #iq{type = set,
sub_els = [#privacy{lists = [#privacy_list{}]}]}, sub_els = [#privacy_query{lists = [#privacy_list{}]}]},
#iq{type = set, #iq{type = set,
sub_els = [#unblock{items = [JID]}]}, sub_els = [#unblock{items = [JID]}]},
#iq{type = result, id = I2, sub_els = []}), #iq{type = result, id = I2, sub_els = []}),
@ -778,7 +775,7 @@ blocking(Config) ->
vcard(Config) -> vcard(Config) ->
true = is_feature_advertised(Config, ?NS_VCARD), true = is_feature_advertised(Config, ?NS_VCARD),
VCard = VCard =
#vcard{fn = <<"Peter Saint-Andre">>, #vcard_temp{fn = <<"Peter Saint-Andre">>,
n = #vcard_name{family = <<"Saint-Andre">>, n = #vcard_name{family = <<"Saint-Andre">>,
given = <<"Peter">>}, given = <<"Peter">>},
nickname = <<"stpeter">>, nickname = <<"stpeter">>,
@ -811,21 +808,21 @@ vcard(Config) ->
send_recv(Config, #iq{type = set, sub_els = [VCard]}), send_recv(Config, #iq{type = set, sub_els = [VCard]}),
%% TODO: check if VCard == VCard1. %% TODO: check if VCard == VCard1.
#iq{type = result, sub_els = [_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). disconnect(Config).
vcard_get(Config) -> vcard_get(Config) ->
true = is_feature_advertised(Config, ?NS_VCARD), true = is_feature_advertised(Config, ?NS_VCARD),
%% TODO: check if VCard corresponds to LDIF data from ejabberd.ldif %% TODO: check if VCard corresponds to LDIF data from ejabberd.ldif
#iq{type = result, sub_els = [_VCard]} = #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). disconnect(Config).
ldap_shared_roster_get(Config) -> ldap_shared_roster_get(Config) ->
Item = #roster_item{jid = jid:from_string(<<"user2@ldap.localhost">>), name = <<"Test User 2">>, Item = #roster_item{jid = jid:from_string(<<"user2@ldap.localhost">>), name = <<"Test User 2">>,
groups = [<<"group1">>], subscription = both}, groups = [<<"group1">>], subscription = both},
#iq{type = result, sub_els = [#roster{items = [Item]}]} = #iq{type = result, sub_els = [#roster_query{items = [Item]}]} =
send_recv(Config, #iq{type = get, sub_els = [#roster{}]}), send_recv(Config, #iq{type = get, sub_els = [#roster_query{}]}),
disconnect(Config). disconnect(Config).
vcard_xupdate_master(Config) -> vcard_xupdate_master(Config) ->
@ -835,17 +832,17 @@ vcard_xupdate_master(Config) ->
Peer = ?config(slave, Config), Peer = ?config(slave, Config),
wait_for_slave(Config), wait_for_slave(Config),
send(Config, #presence{}), send(Config, #presence{}),
?recv2(#presence{from = MyJID, type = undefined}, ?recv2(#presence{from = MyJID, type = available},
#presence{from = Peer, type = undefined}), #presence{from = Peer, type = available}),
VCard = #vcard{photo = #vcard_photo{type = <<"image/png">>, binval = Img}}, VCard = #vcard_temp{photo = #vcard_photo{type = <<"image/png">>, binval = Img}},
I1 = send(Config, #iq{type = set, sub_els = [VCard]}), I1 = send(Config, #iq{type = set, sub_els = [VCard]}),
?recv2(#iq{type = result, sub_els = [], id = I1}, ?recv2(#iq{type = result, sub_els = [], id = I1},
#presence{from = MyJID, type = undefined, #presence{from = MyJID, type = available,
sub_els = [#vcard_xupdate{photo = ImgHash}]}), sub_els = [#vcard_xupdate{hash = ImgHash}]}),
I2 = send(Config, #iq{type = set, sub_els = [#vcard{}]}), I2 = send(Config, #iq{type = set, sub_els = [#vcard_temp{}]}),
?recv3(#iq{type = result, sub_els = [], id = I2}, ?recv3(#iq{type = result, sub_els = [], id = I2},
#presence{from = MyJID, type = undefined, #presence{from = MyJID, type = available,
sub_els = [#vcard_xupdate{photo = undefined}]}, sub_els = [#vcard_xupdate{hash = undefined}]},
#presence{from = Peer, type = unavailable}), #presence{from = Peer, type = unavailable}),
disconnect(Config). disconnect(Config).
@ -855,24 +852,24 @@ vcard_xupdate_slave(Config) ->
MyJID = my_jid(Config), MyJID = my_jid(Config),
Peer = ?config(master, Config), Peer = ?config(master, Config),
send(Config, #presence{}), send(Config, #presence{}),
?recv1(#presence{from = MyJID, type = undefined}), ?recv1(#presence{from = MyJID, type = available}),
wait_for_master(Config), wait_for_master(Config),
?recv1(#presence{from = Peer, type = undefined}), ?recv1(#presence{from = Peer, type = available}),
?recv1(#presence{from = Peer, type = undefined, ?recv1(#presence{from = Peer, type = available,
sub_els = [#vcard_xupdate{photo = ImgHash}]}), sub_els = [#vcard_xupdate{hash = ImgHash}]}),
?recv1(#presence{from = Peer, type = undefined, ?recv1(#presence{from = Peer, type = available,
sub_els = [#vcard_xupdate{photo = undefined}]}), sub_els = [#vcard_xupdate{hash = undefined}]}),
disconnect(Config). disconnect(Config).
stats(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{}], send_recv(Config, #iq{type = get, sub_els = [#stats{}],
to = server_jid(Config)}), to = server_jid(Config)}),
lists:foreach( lists:foreach(
fun(#stat{} = Stat) -> fun(#stat{} = Stat) ->
#iq{type = result, sub_els = [_|_]} = #iq{type = result, sub_els = [_|_]} =
send_recv(Config, #iq{type = get, send_recv(Config, #iq{type = get,
sub_els = [#stats{stat = [Stat]}], sub_els = [#stats{list = [Stat]}],
to = server_jid(Config)}) to = server_jid(Config)})
end, Stats), end, Stats),
disconnect(Config). disconnect(Config).
@ -883,68 +880,68 @@ pubsub(Config) ->
%% Publish <presence/> element within node "presence" %% Publish <presence/> element within node "presence"
ItemID = randoms:get_string(), ItemID = randoms:get_string(),
Node = <<"presence!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>, Node = <<"presence!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>,
Item = #pubsub_item{id = ItemID, Item = #ps_item{id = ItemID,
xml_els = [xmpp_codec:encode(#presence{})]}, xml_els = [xmpp_codec:encode(#presence{})]},
#iq{type = result, #iq{type = result,
sub_els = [#pubsub{publish = #pubsub_publish{ sub_els = [#pubsub{publish = #ps_publish{
node = Node, node = Node,
items = [#pubsub_item{id = ItemID}]}}]} = items = [#ps_item{id = ItemID}]}}]} =
send_recv(Config, send_recv(Config,
#iq{type = set, to = pubsub_jid(Config), #iq{type = set, to = pubsub_jid(Config),
sub_els = [#pubsub{publish = #pubsub_publish{ sub_els = [#pubsub{publish = #ps_publish{
node = Node, node = Node,
items = [Item]}}]}), items = [Item]}}]}),
%% Subscribe to node "presence" %% Subscribe to node "presence"
I1 = send(Config, I1 = send(Config,
#iq{type = set, to = pubsub_jid(Config), #iq{type = set, to = pubsub_jid(Config),
sub_els = [#pubsub{subscribe = #pubsub_subscribe{ sub_els = [#pubsub{subscribe = #ps_subscribe{
node = Node, node = Node,
jid = my_jid(Config)}}]}), jid = my_jid(Config)}}]}),
?recv2( ?recv2(
#message{sub_els = [#pubsub_event{}, #delay{}]}, #message{sub_els = [#ps_event{}, #delay{}]},
#iq{type = result, id = I1}), #iq{type = result, id = I1}),
%% Get subscriptions %% Get subscriptions
true = lists:member(?PUBSUB("retrieve-subscriptions"), Features), true = lists:member(?PUBSUB("retrieve-subscriptions"), Features),
#iq{type = result, #iq{type = result,
sub_els = sub_els =
[#pubsub{subscriptions = [#pubsub{subscriptions =
{none, [#pubsub_subscription{node = Node}]}}]} = {<<>>, [#ps_subscription{node = Node}]}}]} =
send_recv(Config, #iq{type = get, to = pubsub_jid(Config), send_recv(Config, #iq{type = get, to = pubsub_jid(Config),
sub_els = [#pubsub{subscriptions = {none, []}}]}), sub_els = [#pubsub{subscriptions = {<<>>, []}}]}),
%% Get affiliations %% Get affiliations
true = lists:member(?PUBSUB("retrieve-affiliations"), Features), true = lists:member(?PUBSUB("retrieve-affiliations"), Features),
#iq{type = result, #iq{type = result,
sub_els = [#pubsub{ sub_els = [#pubsub{
affiliations = affiliations =
[#pubsub_affiliation{node = Node, type = owner}]}]} = {<<>>, [#ps_affiliation{node = Node, type = owner}]}}]} =
send_recv(Config, #iq{type = get, to = pubsub_jid(Config), send_recv(Config, #iq{type = get, to = pubsub_jid(Config),
sub_els = [#pubsub{affiliations = []}]}), sub_els = [#pubsub{affiliations = {<<>>, []}}]}),
%% Fetching published items from node "presence" %% Fetching published items from node "presence"
#iq{type = result, #iq{type = result,
sub_els = [#pubsub{items = #pubsub_items{ sub_els = [#pubsub{items = #ps_items{
node = Node, node = Node,
items = [Item]}}]} = items = [Item]}}]} =
send_recv(Config, send_recv(Config,
#iq{type = get, to = pubsub_jid(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 %% Deleting the item from the node
true = lists:member(?PUBSUB("delete-items"), Features), true = lists:member(?PUBSUB("delete-items"), Features),
I2 = send(Config, I2 = send(Config,
#iq{type = set, to = pubsub_jid(Config), #iq{type = set, to = pubsub_jid(Config),
sub_els = [#pubsub{retract = #pubsub_retract{ sub_els = [#pubsub{retract = #ps_retract{
node = Node, node = Node,
items = [#pubsub_item{id = ItemID}]}}]}), items = [#ps_item{id = ItemID}]}}]}),
?recv2( ?recv2(
#iq{type = result, id = I2, sub_els = []}, #iq{type = result, id = I2, sub_els = []},
#message{sub_els = [#pubsub_event{ #message{sub_els = [#ps_event{
items = [#pubsub_event_items{ items = #ps_items{
node = Node, node = Node,
retract = [ItemID]}]}]}), retract = ItemID}}]}),
%% Unsubscribe from node "presence" %% Unsubscribe from node "presence"
#iq{type = result, sub_els = []} = #iq{type = result, sub_els = []} =
send_recv(Config, send_recv(Config,
#iq{type = set, to = pubsub_jid(Config), #iq{type = set, to = pubsub_jid(Config),
sub_els = [#pubsub{unsubscribe = #pubsub_unsubscribe{ sub_els = [#pubsub{unsubscribe = #ps_unsubscribe{
node = Node, node = Node,
jid = my_jid(Config)}}]}), jid = my_jid(Config)}}]}),
disconnect(Config). disconnect(Config).
@ -974,12 +971,12 @@ mix_master(Config) ->
I0 = send(Config, #iq{type = set, to = Room, I0 = send(Config, #iq{type = set, to = Room,
sub_els = [#mix_join{subscribe = Nodes}]}), sub_els = [#mix_join{subscribe = Nodes}]}),
{_, #message{sub_els = {_, #message{sub_els =
[#pubsub_event{ [#ps_event{
items = [#pubsub_event_items{ items = #ps_items{
node = ?NS_MIX_NODES_PARTICIPANTS, node = ?NS_MIX_NODES_PARTICIPANTS,
items = [#pubsub_event_item{ items = [#ps_item{
id = ParticipantID, id = ParticipantID,
xml_els = [PXML]}]}]}]}} = xml_els = [PXML]}]}}]}} =
?recv2(#iq{type = result, id = I0, ?recv2(#iq{type = result, id = I0,
sub_els = [#mix_join{subscribe = Nodes, jid = MyBareJID}]}, sub_els = [#mix_join{subscribe = Nodes, jid = MyBareJID}]},
#message{from = Room}), #message{from = Room}),
@ -992,42 +989,42 @@ mix_master(Config) ->
#iq{type = set, to = Room, #iq{type = set, to = Room,
sub_els = sub_els =
[#pubsub{ [#pubsub{
publish = #pubsub_publish{ publish = #ps_publish{
node = ?NS_MIX_NODES_PRESENCE, node = ?NS_MIX_NODES_PRESENCE,
items = [#pubsub_item{ items = [#ps_item{
id = PresenceID, id = PresenceID,
xml_els = [Presence]}]}}]}), xml_els = [Presence]}]}}]}),
?recv2(#iq{type = result, id = I1, ?recv2(#iq{type = result, id = I1,
sub_els = sub_els =
[#pubsub{ [#pubsub{
publish = #pubsub_publish{ publish = #ps_publish{
node = ?NS_MIX_NODES_PRESENCE, node = ?NS_MIX_NODES_PRESENCE,
items = [#pubsub_item{id = PresenceID}]}}]}, items = [#ps_item{id = PresenceID}]}}]},
#message{from = Room, #message{from = Room,
sub_els = sub_els =
[#pubsub_event{ [#ps_event{
items = [#pubsub_event_items{ items = #ps_items{
node = ?NS_MIX_NODES_PRESENCE, node = ?NS_MIX_NODES_PRESENCE,
items = [#pubsub_event_item{ items = [#ps_item{
id = PresenceID, id = PresenceID,
xml_els = [Presence]}]}]}]}), xml_els = [Presence]}]}}]}),
%% Coming offline %% Coming offline
send(Config, #presence{type = unavailable, to = Room}), send(Config, #presence{type = unavailable, to = Room}),
%% Receiving presence retract event %% Receiving presence retract event
#message{from = Room, #message{from = Room,
sub_els = [#pubsub_event{ sub_els = [#ps_event{
items = [#pubsub_event_items{ items = #ps_items{
node = ?NS_MIX_NODES_PRESENCE, node = ?NS_MIX_NODES_PRESENCE,
retract = [PresenceID]}]}]} = recv(), retract = PresenceID}}]} = recv(),
%% Leaving %% Leaving
I2 = send(Config, #iq{type = set, to = Room, sub_els = [#mix_leave{}]}), I2 = send(Config, #iq{type = set, to = Room, sub_els = [#mix_leave{}]}),
?recv2(#iq{type = result, id = I2, sub_els = []}, ?recv2(#iq{type = result, id = I2, sub_els = []},
#message{from = Room, #message{from = Room,
sub_els = sub_els =
[#pubsub_event{ [#ps_event{
items = [#pubsub_event_items{ items = #ps_items{
node = ?NS_MIX_NODES_PARTICIPANTS, node = ?NS_MIX_NODES_PARTICIPANTS,
retract = [ParticipantID]}]}]}), retract = ParticipantID}}]}),
disconnect(Config). disconnect(Config).
mix_slave(Config) -> mix_slave(Config) ->
@ -1041,45 +1038,45 @@ roster_subscribe_master(Config) ->
LPeer = jid:remove_resource(Peer), LPeer = jid:remove_resource(Peer),
send(Config, #presence{type = subscribe, to = LPeer}), send(Config, #presence{type = subscribe, to = LPeer}),
Push1 = ?recv1(#iq{type = set, Push1 = ?recv1(#iq{type = set,
sub_els = [#roster{items = [#roster_item{ sub_els = [#roster_query{items = [#roster_item{
ask = subscribe, ask = subscribe,
subscription = none, subscription = none,
jid = LPeer}]}]}), jid = LPeer}]}]}),
send(Config, make_iq_result(Push1)), send(Config, make_iq_result(Push1)),
{Push2, _} = ?recv2( {Push2, _} = ?recv2(
#iq{type = set, #iq{type = set,
sub_els = [#roster{items = [#roster_item{ sub_els = [#roster_query{items = [#roster_item{
subscription = to, subscription = to,
jid = LPeer}]}]}, jid = LPeer}]}]},
#presence{type = subscribed, from = LPeer}), #presence{type = subscribed, from = LPeer}),
send(Config, make_iq_result(Push2)), 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? %% BUG: ejabberd sends previous push again. Is it ok?
Push3 = ?recv1(#iq{type = set, Push3 = ?recv1(#iq{type = set,
sub_els = [#roster{items = [#roster_item{ sub_els = [#roster_query{items = [#roster_item{
subscription = to, subscription = to,
jid = LPeer}]}]}), jid = LPeer}]}]}),
send(Config, make_iq_result(Push3)), send(Config, make_iq_result(Push3)),
?recv1(#presence{type = subscribe, from = LPeer}), ?recv1(#presence{type = subscribe, from = LPeer}),
send(Config, #presence{type = subscribed, to = LPeer}), send(Config, #presence{type = subscribed, to = LPeer}),
Push4 = ?recv1(#iq{type = set, Push4 = ?recv1(#iq{type = set,
sub_els = [#roster{items = [#roster_item{ sub_els = [#roster_query{items = [#roster_item{
subscription = both, subscription = both,
jid = LPeer}]}]}), jid = LPeer}]}]}),
send(Config, make_iq_result(Push4)), send(Config, make_iq_result(Push4)),
%% Move into a group %% Move into a group
Groups = [<<"A">>, <<"B">>], Groups = [<<"A">>, <<"B">>],
Item = #roster_item{jid = LPeer, groups = Groups}, 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( {Push5, _} = ?recv2(
#iq{type = set, #iq{type = set,
sub_els = sub_els =
[#roster{items = [#roster_item{ [#roster_query{items = [#roster_item{
jid = LPeer, jid = LPeer,
subscription = both}]}]}, subscription = both}]}]},
#iq{type = result, id = I1, sub_els = []}), #iq{type = result, id = I1, sub_els = []}),
send(Config, make_iq_result(Push5)), 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), Groups = lists:sort(G1),
wait_for_slave(Config), wait_for_slave(Config),
?recv1(#presence{type = unavailable, from = Peer}), ?recv1(#presence{type = unavailable, from = Peer}),
@ -1094,25 +1091,25 @@ roster_subscribe_slave(Config) ->
?recv1(#presence{type = subscribe, from = LPeer}), ?recv1(#presence{type = subscribe, from = LPeer}),
send(Config, #presence{type = subscribed, to = LPeer}), send(Config, #presence{type = subscribed, to = LPeer}),
Push1 = ?recv1(#iq{type = set, Push1 = ?recv1(#iq{type = set,
sub_els = [#roster{items = [#roster_item{ sub_els = [#roster_query{items = [#roster_item{
subscription = from, subscription = from,
jid = LPeer}]}]}), jid = LPeer}]}]}),
send(Config, make_iq_result(Push1)), send(Config, make_iq_result(Push1)),
send(Config, #presence{type = subscribe, to = LPeer}), send(Config, #presence{type = subscribe, to = LPeer}),
Push2 = ?recv1(#iq{type = set, Push2 = ?recv1(#iq{type = set,
sub_els = [#roster{items = [#roster_item{ sub_els = [#roster_query{items = [#roster_item{
ask = subscribe, ask = subscribe,
subscription = from, subscription = from,
jid = LPeer}]}]}), jid = LPeer}]}]}),
send(Config, make_iq_result(Push2)), send(Config, make_iq_result(Push2)),
{Push3, _} = ?recv2( {Push3, _} = ?recv2(
#iq{type = set, #iq{type = set,
sub_els = [#roster{items = [#roster_item{ sub_els = [#roster_query{items = [#roster_item{
subscription = both, subscription = both,
jid = LPeer}]}]}, jid = LPeer}]}]},
#presence{type = subscribed, from = LPeer}), #presence{type = subscribed, from = LPeer}),
send(Config, make_iq_result(Push3)), send(Config, make_iq_result(Push3)),
?recv1(#presence{type = undefined, from = Peer}), ?recv1(#presence{type = available, from = Peer}),
wait_for_master(Config), wait_for_master(Config),
disconnect(Config). disconnect(Config).
@ -1123,8 +1120,8 @@ roster_remove_master(Config) ->
Groups = [<<"A">>, <<"B">>], Groups = [<<"A">>, <<"B">>],
wait_for_slave(Config), wait_for_slave(Config),
send(Config, #presence{}), send(Config, #presence{}),
?recv2(#presence{from = MyJID, type = undefined}, ?recv2(#presence{from = MyJID, type = available},
#presence{from = Peer, type = undefined}), #presence{from = Peer, type = available}),
%% The peer removed us from its roster. %% The peer removed us from its roster.
{Push1, Push2, _, _, _} = {Push1, Push2, _, _, _} =
?recv5( ?recv5(
@ -1132,12 +1129,12 @@ roster_remove_master(Config) ->
%% to send transient roster push with subscription = 'to'. %% to send transient roster push with subscription = 'to'.
#iq{type = set, #iq{type = set,
sub_els = sub_els =
[#roster{items = [#roster_item{ [#roster_query{items = [#roster_item{
jid = LPeer, jid = LPeer,
subscription = to}]}]}, subscription = to}]}]},
#iq{type = set, #iq{type = set,
sub_els = sub_els =
[#roster{items = [#roster_item{ [#roster_query{items = [#roster_item{
jid = LPeer, jid = LPeer,
subscription = none}]}]}, subscription = none}]}]},
#presence{type = unsubscribe, from = LPeer}, #presence{type = unsubscribe, from = LPeer},
@ -1145,8 +1142,8 @@ roster_remove_master(Config) ->
#presence{type = unavailable, from = Peer}), #presence{type = unavailable, from = Peer}),
send(Config, make_iq_result(Push1)), send(Config, make_iq_result(Push1)),
send(Config, make_iq_result(Push2)), send(Config, make_iq_result(Push2)),
#iq{sub_els = [#roster{items = [#roster_item{groups = G1}]}]} = Push1, #iq{sub_els = [#roster_query{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 = G2}]}]} = Push2,
Groups = lists:sort(G1), Groups = lists:sort(G2), Groups = lists:sort(G1), Groups = lists:sort(G2),
disconnect(Config). disconnect(Config).
@ -1155,16 +1152,16 @@ roster_remove_slave(Config) ->
Peer = ?config(master, Config), Peer = ?config(master, Config),
LPeer = jid:remove_resource(Peer), LPeer = jid:remove_resource(Peer),
send(Config, #presence{}), send(Config, #presence{}),
?recv1(#presence{from = MyJID, type = undefined}), ?recv1(#presence{from = MyJID, type = available}),
wait_for_master(Config), wait_for_master(Config),
?recv1(#presence{from = Peer, type = undefined}), ?recv1(#presence{from = Peer, type = available}),
%% Remove the peer from roster. %% Remove the peer from roster.
Item = #roster_item{jid = LPeer, subscription = remove}, 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( {Push, _, _} = ?recv3(
#iq{type = set, #iq{type = set,
sub_els = sub_els =
[#roster{items = [#roster_item{ [#roster_query{items = [#roster_item{
jid = LPeer, jid = LPeer,
subscription = remove}]}]}, subscription = remove}]}]},
#iq{type = result, id = I, sub_els = []}, #iq{type = result, id = I, sub_els = []},
@ -1178,7 +1175,7 @@ proxy65_master(Config) ->
Peer = ?config(slave, Config), Peer = ?config(slave, Config),
wait_for_slave(Config), wait_for_slave(Config),
send(Config, #presence{}), send(Config, #presence{}),
?recv1(#presence{from = MyJID, type = undefined}), ?recv1(#presence{from = MyJID, type = available}),
true = is_feature_advertised(Config, ?NS_BYTESTREAMS, Proxy), true = is_feature_advertised(Config, ?NS_BYTESTREAMS, Proxy),
#iq{type = result, sub_els = [#bytestreams{hosts = [StreamHost]}]} = #iq{type = result, sub_els = [#bytestreams{hosts = [StreamHost]}]} =
send_recv( send_recv(
@ -1201,7 +1198,7 @@ proxy65_slave(Config) ->
MyJID = my_jid(Config), MyJID = my_jid(Config),
Peer = ?config(master, Config), Peer = ?config(master, Config),
send(Config, #presence{}), send(Config, #presence{}),
?recv1(#presence{from = MyJID, type = undefined}), ?recv1(#presence{from = MyJID, type = available}),
wait_for_master(Config), wait_for_master(Config),
{StreamHost, SID, Data} = get_event(Config), {StreamHost, SID, Data} = get_event(Config),
Socks5 = socks5_connect(StreamHost, {SID, Peer, MyJID}), Socks5 = socks5_connect(StreamHost, {SID, Peer, MyJID}),
@ -1228,6 +1225,7 @@ retrieve_messages_from_room_via_mam(Config, Range) ->
Room = muc_room_jid(Config), Room = muc_room_jid(Config),
MyNickJID = jid:replace_resource(Room, MyNick), MyNickJID = jid:replace_resource(Room, MyNick),
QID = randoms:get_string(), QID = randoms:get_string(),
Count = length(Range),
I = send(Config, #iq{type = set, to = Room, I = send(Config, #iq{type = set, to = Room,
sub_els = [#mam_query{xmlns = ?NS_MAM_1, id = QID}]}), sub_els = [#mam_query{xmlns = ?NS_MAM_1, id = QID}]}),
lists:foreach( lists:foreach(
@ -1247,7 +1245,11 @@ retrieve_messages_from_room_via_mam(Config, Range) ->
type = groupchat, type = groupchat,
body = [Text]}]}]}]}) body = [Text]}]}]}]})
end, Range), 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) -> muc_mam_master(Config) ->
MyJID = my_jid(Config), MyJID = my_jid(Config),
@ -1318,14 +1320,12 @@ muc_master(Config) ->
%% 4. The room subject %% 4. The room subject
%% 5. Live messages, presence updates, new user joins, etc. %% 5. Live messages, presence updates, new user joins, etc.
%% As this is the newly created room, we receive only the 2nd stanza. %% As this is the newly created room, we receive only the 2nd stanza.
?recv1(#presence{ #muc_user{
from = MyNickJID, status_codes = Codes,
sub_els = [#vcard_xupdate{}, items = [#muc_item{role = moderator,
#muc_user{ jid = MyJID,
status_codes = Codes, affiliation = owner}]} =
items = [#muc_item{role = moderator, xmpp:get_subtag(?recv1(#presence{from = MyNickJID}), #muc_user{}),
jid = MyJID,
affiliation = owner}]}]}),
%% 110 -> Inform user that presence refers to itself %% 110 -> Inform user that presence refers to itself
%% 201 -> Inform user that a new room has been created %% 201 -> Inform user that a new room has been created
[110, 201] = lists:sort(Codes), [110, 201] = lists:sort(Codes),
@ -1389,13 +1389,11 @@ muc_master(Config) ->
[#muc_user{ [#muc_user{
invites = invites =
[#muc_invite{to = PeerJID}]}]}), [#muc_invite{to = PeerJID}]}]}),
%% Peer is joining #muc_user{
?recv1(#presence{from = PeerNickJID, items = [#muc_item{role = visitor,
sub_els = [#vcard_xupdate{}, jid = PeerJID,
#muc_user{ affiliation = none}]} =
items = [#muc_item{role = visitor, xmpp:get_subtag(?recv1(#presence{from = PeerNickJID}), #muc_user{}),
jid = PeerJID,
affiliation = none}]}]}),
%% Receiving a voice request %% Receiving a voice request
?recv1(#message{from = Room, ?recv1(#message{from = Room,
sub_els = [#xdata{type = form, sub_els = [#xdata{type = form,
@ -1424,12 +1422,10 @@ muc_master(Config) ->
sub_els = [#xdata{type = submit, sub_els = [#xdata{type = submit,
fields = ReplyVoiceReqFs}]}), fields = ReplyVoiceReqFs}]}),
%% Peer is becoming a participant %% Peer is becoming a participant
?recv1(#presence{from = PeerNickJID, #muc_user{items = [#muc_item{role = participant,
sub_els = [#vcard_xupdate{}, jid = PeerJID,
#muc_user{ affiliation = none}]} =
items = [#muc_item{role = participant, xmpp:get_subtag(?recv1(#presence{from = PeerNickJID}), #muc_user{}),
jid = PeerJID,
affiliation = none}]}]}),
%% Receive private message from the peer %% Receive private message from the peer
?recv1(#message{from = PeerNickJID, body = [#text{data = Subject}]}), ?recv1(#message{from = PeerNickJID, body = [#text{data = Subject}]}),
%% Granting membership to the peer and localhost server %% Granting membership to the peer and localhost server
@ -1443,19 +1439,16 @@ muc_master(Config) ->
jid = PeerBareJID, jid = PeerBareJID,
affiliation = member}]}]}), affiliation = member}]}]}),
%% Peer became a member %% Peer became a member
?recv1(#presence{from = PeerNickJID, #muc_user{items = [#muc_item{affiliation = member,
sub_els = [#vcard_xupdate{}, jid = PeerJID,
#muc_user{ role = participant}]} =
items = [#muc_item{affiliation = member, xmpp:get_subtag(?recv1(#presence{from = PeerNickJID}), #muc_user{}),
jid = PeerJID,
role = participant}]}]}),
?recv1(#message{from = Room, ?recv1(#message{from = Room,
sub_els = [#muc_user{ sub_els = [#muc_user{
items = [#muc_item{affiliation = member, items = [#muc_item{affiliation = member,
jid = Localhost, jid = Localhost,
role = none}]}]}), 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 %% Receive groupchat message from the peer
?recv1(#message{type = groupchat, from = PeerNickJID, ?recv1(#message{type = groupchat, from = PeerNickJID,
body = [#text{data = Subject}]}), body = [#text{data = Subject}]}),
@ -1483,22 +1476,20 @@ muc_master(Config) ->
items = [#muc_item{affiliation = member, items = [#muc_item{affiliation = member,
jid = PeerJID, jid = PeerJID,
role = none}]}]}), 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 %% Destroying the room
I3 = send(Config, I3 = send(Config,
#iq{type = set, to = Room, #iq{type = set, to = Room,
sub_els = [#muc_owner{ sub_els = [#muc_owner{
destroy = #muc_owner_destroy{ destroy = #muc_destroy{
reason = Subject}}]}), reason = Subject}}]}),
%% Kicked off %% Kicked off
?recv1(#presence{from = MyNickJID, type = unavailable, ?recv1(#presence{from = MyNickJID, type = unavailable,
sub_els = [#muc_user{items = [#muc_item{role = none, sub_els = [#muc_user{items = [#muc_item{role = none,
affiliation = none}], affiliation = none}],
destroy = #muc_user_destroy{ destroy = #muc_destroy{
reason = Subject}}]}), 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). disconnect(Config).
muc_slave(Config) -> muc_slave(Config) ->
@ -1514,10 +1505,9 @@ muc_slave(Config) ->
Subject = ?config(room_subject, Config), Subject = ?config(room_subject, Config),
Localhost = jid:make(<<"">>, <<"localhost">>, <<"">>), Localhost = jid:make(<<"">>, <<"localhost">>, <<"">>),
%% Receive an invite from the peer %% Receive an invite from the peer
?recv1(#message{from = Room, type = normal, #muc_user{invites = [#muc_invite{from = PeerJID}]} =
sub_els = xmpp:get_subtag(?recv1(#message{from = Room, type = normal}),
[#muc_user{invites = #muc_user{}),
[#muc_invite{from = PeerJID}]}]}),
%% But before joining we discover the MUC service first %% But before joining we discover the MUC service first
%% to check if the room is in the disco list %% to check if the room is in the disco list
#iq{type = result, #iq{type = result,
@ -1533,21 +1523,16 @@ muc_slave(Config) ->
%% Now joining %% Now joining
send(Config, #presence{to = MyNickJID, sub_els = [#muc{}]}), send(Config, #presence{to = MyNickJID, sub_els = [#muc{}]}),
%% First presence is from the participant, i.e. from the peer %% First presence is from the participant, i.e. from the peer
?recv1(#presence{ #muc_user{
from = PeerNickJID, status_codes = [],
sub_els = [#vcard_xupdate{}, items = [#muc_item{role = moderator,
#muc_user{ affiliation = owner}]} =
status_codes = [], xmpp:get_subtag(?recv1(#presence{from = PeerNickJID}), #muc_user{}),
items = [#muc_item{role = moderator,
affiliation = owner}]}]}),
%% The next is the self-presence (code 110 means it) %% The next is the self-presence (code 110 means it)
?recv1(#presence{ #muc_user{status_codes = [110],
from = MyNickJID, items = [#muc_item{role = visitor,
sub_els = [#vcard_xupdate{}, affiliation = none}]} =
#muc_user{ xmpp:get_subtag(?recv1(#presence{from = MyNickJID}), #muc_user{}),
status_codes = [110],
items = [#muc_item{role = visitor,
affiliation = none}]}]}),
%% Receive the room subject %% Receive the room subject
?recv1(#message{from = PeerNickJID, type = groupchat, ?recv1(#message{from = PeerNickJID, type = groupchat,
body = [#text{data = Subject}], body = [#text{data = Subject}],
@ -1574,20 +1559,16 @@ muc_slave(Config) ->
values = [<<"participant">>]}]}, values = [<<"participant">>]}]},
send(Config, #message{to = Room, sub_els = [VoiceReq]}), send(Config, #message{to = Room, sub_els = [VoiceReq]}),
%% Becoming a participant %% Becoming a participant
?recv1(#presence{from = MyNickJID, #muc_user{items = [#muc_item{role = participant,
sub_els = [#vcard_xupdate{}, affiliation = none}]} =
#muc_user{ xmpp:get_subtag(?recv1(#presence{from = MyNickJID}), #muc_user{}),
items = [#muc_item{role = participant,
affiliation = none}]}]}),
%% Sending private message to the peer %% Sending private message to the peer
send(Config, #message{to = PeerNickJID, send(Config, #message{to = PeerNickJID,
body = [#text{data = Subject}]}), body = [#text{data = Subject}]}),
%% Becoming a member %% Becoming a member
?recv1(#presence{from = MyNickJID, #muc_user{items = [#muc_item{role = participant,
sub_els = [#vcard_xupdate{}, affiliation = member}]} =
#muc_user{ xmpp:get_subtag(?recv1(#presence{from = MyNickJID}), #muc_user{}),
items = [#muc_item{role = participant,
affiliation = member}]}]}),
%% Sending groupchat message %% Sending groupchat message
send(Config, #message{to = Room, type = groupchat, send(Config, #message{to = Room, type = groupchat,
body = [#text{data = Subject}]}), body = [#text{data = Subject}]}),
@ -1624,7 +1605,7 @@ muc_register_nick(Config, MUC, PrevNick, Nick) ->
X = #xdata{type = submit, X = #xdata{type = submit,
fields = [#xdata_field{var = <<"nick">>, values = [Nick]}]}, fields = [#xdata_field{var = <<"nick">>, values = [Nick]}]},
%% Submitting form %% Submitting form
#iq{type = result, sub_els = [_|_]} = #iq{type = result, sub_els = []} =
send_recv(Config, #iq{type = set, to = MUC, send_recv(Config, #iq{type = set, to = MUC,
sub_els = [#register{xdata = X}]}), sub_els = [#register{xdata = X}]}),
%% Check if the nick was registered %% Check if the nick was registered
@ -1643,7 +1624,7 @@ muc_register_master(Config) ->
%% Register nick "master1" %% Register nick "master1"
muc_register_nick(Config, MUC, <<"">>, <<"master1">>), muc_register_nick(Config, MUC, <<"">>, <<"master1">>),
%% Unregister nick "master1" via jabber:register %% Unregister nick "master1" via jabber:register
#iq{type = result, sub_els = [_|_]} = #iq{type = result, sub_els = []} =
send_recv(Config, #iq{type = set, to = MUC, send_recv(Config, #iq{type = set, to = MUC,
sub_els = [#register{remove = true}]}), sub_els = [#register{remove = true}]}),
%% Register nick "master2" %% Register nick "master2"
@ -1690,6 +1671,7 @@ announce_slave(Config) ->
flex_offline_master(Config) -> flex_offline_master(Config) ->
Peer = ?config(slave, Config), Peer = ?config(slave, Config),
ct:log("hooks = ~p", [ets:tab2list(hooks)]),
LPeer = jid:remove_resource(Peer), LPeer = jid:remove_resource(Peer),
lists:foreach( lists:foreach(
fun(I) -> fun(I) ->
@ -2026,8 +2008,11 @@ mam_slave(Config, NS) ->
lists:foreach( lists:foreach(
fun(N) -> fun(N) ->
Text = #text{data = integer_to_binary(N)}, Text = #text{data = integer_to_binary(N)},
?recv1(#message{from = Peer, body = [Text], Msg = ?recv1(#message{from = Peer, body = [Text]}),
sub_els = [#mam_archived{by = ServerJID}]}) #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)), end, lists:seq(1, 5)),
#iq{type = result, sub_els = [#mam_prefs{xmlns = NS, default = never}]} = #iq{type = result, sub_els = [#mam_prefs{xmlns = NS, default = never}]} =
send_recv(Config, #iq{type = set, send_recv(Config, #iq{type = set,
@ -2241,7 +2226,7 @@ mam_query_rsm(Config, NS) ->
#iq{type = Type, #iq{type = Type,
sub_els = [#mam_query{xmlns = NS, sub_els = [#mam_query{xmlns = NS,
rsm = #rsm_set{max = 2, rsm = #rsm_set{max = 2,
before = none}}]}), before = <<"">>}}]}),
maybe_recv_iq_result(NS, I5), maybe_recv_iq_result(NS, I5),
lists:foreach( lists:foreach(
fun(N) -> fun(N) ->
@ -2278,25 +2263,25 @@ client_state_master(Config) ->
PepOne = #message{ PepOne = #message{
to = Peer, to = Peer,
sub_els = sub_els =
[#pubsub_event{ [#ps_event{
items = items =
[#pubsub_event_items{ #ps_items{
node = <<"foo-1">>, node = <<"foo-1">>,
items = items =
[#pubsub_event_item{ [#ps_item{
id = <<"pep-1">>, id = <<"pep-1">>,
xml_els = [PepPayload]}]}]}]}, xml_els = [PepPayload]}]}}]},
PepTwo = #message{ PepTwo = #message{
to = Peer, to = Peer,
sub_els = sub_els =
[#pubsub_event{ [#ps_event{
items = items =
[#pubsub_event_items{ #ps_items{
node = <<"foo-2">>, node = <<"foo-2">>,
items = items =
[#pubsub_event_item{ [#ps_item{
id = <<"pep-2">>, id = <<"pep-2">>,
xml_els = [PepPayload]}]}]}]}, xml_els = [PepPayload]}]}}]},
%% Wait for the slave to become inactive. %% Wait for the slave to become inactive.
wait_for_slave(Config), wait_for_slave(Config),
%% Should be queued (but see below): %% Should be queued (but see below):
@ -2330,24 +2315,24 @@ client_state_slave(Config) ->
#message{ #message{
from = Peer, from = Peer,
sub_els = sub_els =
[#pubsub_event{ [#ps_event{
items = items =
[#pubsub_event_items{ #ps_items{
node = <<"foo-1">>, node = <<"foo-1">>,
items = items =
[#pubsub_event_item{ [#ps_item{
id = <<"pep-1">>}]}]}, id = <<"pep-1">>}]}},
#delay{}]} = recv(), #delay{}]} = recv(),
#message{ #message{
from = Peer, from = Peer,
sub_els = sub_els =
[#pubsub_event{ [#ps_event{
items = items =
[#pubsub_event_items{ #ps_items{
node = <<"foo-2">>, node = <<"foo-2">>,
items = items =
[#pubsub_event_item{ [#ps_item{
id = <<"pep-2">>}]}]}, id = <<"pep-2">>}]}},
#delay{}]} = recv(), #delay{}]} = recv(),
?recv1(#message{from = Peer, thread = <<"1">>, ?recv1(#message{from = Peer, thread = <<"1">>,
sub_els = [#chatstate{type = composing}, sub_els = [#chatstate{type = composing},

View File

@ -337,7 +337,8 @@ Welcome to this XMPP server."
ldap_base: "ou=users,dc=localhost" ldap_base: "ou=users,dc=localhost"
auth_method: ldap auth_method: ldap
modules: modules:
mod_vcard_ldap: [] mod_vcard:
db_type: ldap
mod_roster: [] # mod_roster is required by mod_shared_roster mod_roster: [] # mod_roster is required by mod_shared_roster
mod_shared_roster_ldap: mod_shared_roster_ldap:
ldap_auth_check: off ldap_auth_check: off

View File

@ -199,7 +199,7 @@ bind(Config) ->
open_session(Config) -> open_session(Config) ->
#iq{type = result, sub_els = []} = #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. Config.
auth_SASL(Mech, Config) -> auth_SASL(Mech, Config) ->
@ -252,10 +252,15 @@ match_failure(Received, Matches) ->
recv() -> recv() ->
receive receive
{'$gen_event', {xmlstreamelement, El}} -> {'$gen_event', {xmlstreamelement, El}} ->
Pkt = xmpp_codec:decode(fix_ns(El)), try
ct:pal("recv: ~p ->~n~s", [El, xmpp_codec:pp(Pkt)]), Pkt = xmpp:decode(El),
Pkt; ct:pal("recv: ~p ->~n~s", [El, xmpp_codec:pp(Pkt)]),
{'$gen_event', Event} -> Pkt
catch _:{xmpp_codec, Why} ->
ct:fail("recv failed: ~p->~n~s",
[El, xmpp:format_error(Why)])
end;
{'$gen_event', Event} ->
Event Event
end. end.
@ -404,9 +409,9 @@ mix_room_jid(Config) ->
jid:make(<<"test">>, <<"mix.", Server/binary>>, <<>>). jid:make(<<"test">>, <<"mix.", Server/binary>>, <<>>).
id() -> id() ->
id(undefined). id(<<>>).
id(undefined) -> id(<<>>) ->
randoms:get_string(); randoms:get_string();
id(ID) -> id(ID) ->
ID. ID.

View File

@ -2653,9 +2653,10 @@
-xml(mam_fin, -xml(mam_fin,
#elem{name = <<"fin">>, #elem{name = <<"fin">>,
xmlns = <<"urn:xmpp:mam:0">>, xmlns = [<<"urn:xmpp:mam:0">>, <<"urn:xmpp:mam:1">>],
result = {mam_fin, '$id', '$rsm', '$stable', '$complete'}, result = {mam_fin, '$xmlns', '$id', '$rsm', '$stable', '$complete'},
attrs = [#attr{name = <<"queryid">>, label = '$id'}, attrs = [#attr{name = <<"queryid">>, label = '$id'},
#attr{name = <<"xmlns">>},
#attr{name = <<"stable">>, label = '$stable', #attr{name = <<"stable">>, label = '$stable',
dec = {dec_bool, []}, dec = {dec_bool, []},
enc = {enc_bool, []}}, enc = {enc_bool, []}},