summaryrefslogtreecommitdiff
path: root/src/mod_muc_room.erl
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2016-09-07 10:33:37 +0300
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2016-09-07 10:33:37 +0300
commit3803a8de3c2ad70ef967bb6d7a47f20fcf82f859 (patch)
tree86b929bb501a81fd357008256b98b86fc9de050c /src/mod_muc_room.erl
parentAdd SQL support for microblogging node plugin (diff)
Link MUC subscription to bare JID
Diffstat (limited to 'src/mod_muc_room.erl')
-rw-r--r--src/mod_muc_room.erl337
1 files changed, 141 insertions, 196 deletions
diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl
index f86b990d..11cc1d5f 100644
--- a/src/mod_muc_room.erl
+++ b/src/mod_muc_room.erl
@@ -678,7 +678,7 @@ handle_event({service_message, Msg}, _StateName,
children = [{xmlcdata, Msg}]}]},
send_wrapped_multiple(
StateData#state.jid,
- StateData#state.users,
+ get_users_and_subscribers(StateData),
MessagePkt,
?NS_MUCSUB_NODES_MESSAGES,
StateData),
@@ -750,12 +750,8 @@ handle_sync_event({process_item_change, Item, UJID}, _From, StateName, StateData
NSD = process_item_change(Item, StateData, UJID),
{reply, {ok, NSD}, StateName, NSD};
handle_sync_event(get_subscribers, _From, StateName, StateData) ->
- JIDs = dict:fold(
- fun(_, #user{is_subscriber = true, jid = J}, Acc) ->
- [J|Acc];
- (_, _, Acc) ->
- Acc
- end, [], StateData#state.users),
+ JIDs = lists:map(fun jid:make/1,
+ ?DICT:fetch_keys(StateData#state.subscribers)),
{reply, {ok, JIDs}, StateName, StateData};
handle_sync_event({muc_subscribe, From, Nick, Nodes}, _From,
StateName, StateData) ->
@@ -936,7 +932,7 @@ terminate(Reason, _StateName, StateData) ->
end,
tab_remove_online_user(LJID, StateData)
end,
- [], StateData#state.users),
+ [], get_users_and_subscribers(StateData)),
add_to_log(room_existence, stopped, StateData),
mod_muc:room_destroyed(StateData#state.host, StateData#state.room, self(),
StateData#state.server_host),
@@ -953,11 +949,12 @@ process_groupchat_message(From,
#xmlel{name = <<"message">>, attrs = Attrs} = Packet,
StateData) ->
Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs),
- case is_user_online(From, StateData) orelse
+ IsSubscriber = is_subscriber(From, StateData),
+ case is_user_online(From, StateData) orelse IsSubscriber orelse
is_user_allowed_message_nonparticipant(From, StateData)
of
true ->
- {FromNick, Role, IsSubscriber} = get_participant_data(From, StateData),
+ {FromNick, Role} = get_participant_data(From, StateData),
if (Role == moderator) or (Role == participant) or IsSubscriber or
((StateData#state.config)#config.moderated == false) ->
Subject = check_subject(Packet),
@@ -1000,7 +997,7 @@ process_groupchat_message(From,
end,
send_wrapped_multiple(
jid:replace_resource(StateData#state.jid, FromNick),
- StateData#state.users,
+ get_users_and_subscribers(StateData),
NewPacket, Node, NewStateData1),
NewStateData2 = case has_body_or_subject(NewPacket) of
true ->
@@ -1068,9 +1065,9 @@ get_participant_data(From, StateData) ->
case (?DICT):find(jid:tolower(From),
StateData#state.users)
of
- {ok, #user{nick = FromNick, role = Role, is_subscriber = IsSubscriber}} ->
- {FromNick, Role, IsSubscriber};
- error -> {<<"">>, moderator, false}
+ {ok, #user{nick = FromNick, role = Role}} ->
+ {FromNick, Role};
+ error -> {<<"">>, moderator}
end.
process_presence(From, Nick,
@@ -1078,7 +1075,6 @@ process_presence(From, Nick,
StateData) ->
Type0 = fxml:get_attr_s(<<"type">>, Attrs0),
IsOnline = is_user_online(From, StateData),
- IsSubscriber = is_subscriber(From, StateData),
if Type0 == <<"">>;
IsOnline and ((Type0 == <<"unavailable">>) or (Type0 == <<"error">>)) ->
case ejabberd_hooks:run_fold(muc_filter_presence,
@@ -1115,7 +1111,7 @@ process_presence(From, Nick,
Status_el ->
fxml:get_tag_cdata(Status_el)
end,
- remove_online_user(From, NewState, IsSubscriber, Reason);
+ remove_online_user(From, NewState, Reason);
<<"error">> ->
ErrorText = <<"It is not allowed to send error messages to the"
" room. The participant (~s) has sent an error "
@@ -1172,27 +1168,15 @@ process_presence(From, Nick,
From, Err),
StateData;
_ ->
- case is_initial_presence(From, StateData) of
- true ->
- subscriber_becomes_available(
- From, Nick, Packet, StateData);
- false ->
- change_nick(From, Nick, StateData)
- end
+ change_nick(From, Nick, StateData)
end;
_NotNickChange ->
- case is_initial_presence(From, StateData) of
- true ->
- subscriber_becomes_available(
- From, Nick, Packet, StateData);
- false ->
- Stanza = maybe_strip_status_from_presence(
- From, Packet, StateData),
- NewState = add_user_presence(From, Stanza,
- StateData),
- send_new_presence(From, NewState, StateData),
- NewState
- end
+ Stanza = maybe_strip_status_from_presence(
+ From, Packet, StateData),
+ NewState = add_user_presence(From, Stanza,
+ StateData),
+ send_new_presence(From, NewState, StateData),
+ NewState
end
end
end,
@@ -1210,22 +1194,10 @@ maybe_strip_status_from_presence(From, Packet, StateData) ->
_Allowed -> Packet
end.
-subscriber_becomes_available(From, Nick, Packet, StateData) ->
- Stanza = maybe_strip_status_from_presence(From, Packet, StateData),
- State1 = add_user_presence(From, Stanza, StateData),
- Aff = get_affiliation(From, State1),
- Role = get_default_role(Aff, State1),
- State2 = set_role(From, Role, State1),
- State3 = set_nick(From, Nick, State2),
- tab_add_online_user(From, StateData),
- send_existing_presences(From, State3),
- send_initial_presence(From, State3, StateData),
- State3.
-
close_room_if_temporary_and_empty(StateData1) ->
case not (StateData1#state.config)#config.persistent
- andalso (?DICT):to_list(StateData1#state.users) == []
- of
+ andalso (?DICT):size(StateData1#state.users) == 0
+ andalso (?DICT):size(StateData1#state.subscribers) == 0 of
true ->
?INFO_MSG("Destroyed MUC room ~s because it's temporary "
"and empty",
@@ -1235,18 +1207,39 @@ close_room_if_temporary_and_empty(StateData1) ->
_ -> {next_state, normal_state, StateData1}
end.
+get_users_and_subscribers(StateData) ->
+ OnlineSubscribers = ?DICT:fold(
+ fun(LJID, _, Acc) ->
+ LBareJID = jid:remove_resource(LJID),
+ case is_subscriber(LBareJID, StateData) of
+ true ->
+ ?SETS:add_element(LBareJID, Acc);
+ false ->
+ Acc
+ end
+ end, ?SETS:new(), StateData#state.users),
+ ?DICT:fold(
+ fun(LBareJID, #subscriber{nick = Nick}, Acc) ->
+ case ?SETS:is_element(LBareJID, OnlineSubscribers) of
+ false ->
+ ?DICT:store(LBareJID,
+ #user{jid = jid:make(LBareJID),
+ nick = Nick,
+ role = none,
+ last_presence = undefined},
+ Acc);
+ true ->
+ Acc
+ end
+ end, StateData#state.users, StateData#state.subscribers).
+
is_user_online(JID, StateData) ->
LJID = jid:tolower(JID),
(?DICT):is_key(LJID, StateData#state.users).
is_subscriber(JID, StateData) ->
- LJID = jid:tolower(JID),
- case (?DICT):find(LJID, StateData#state.users) of
- {ok, #user{is_subscriber = IsSubscriber}} ->
- IsSubscriber;
- _ ->
- false
- end.
+ LJID = jid:tolower(jid:remove_resource(JID)),
+ (?DICT):is_key(LJID, StateData#state.subscribers).
%% Check if the user is occupant of the room, or at least is an admin or owner.
is_occupant_or_admin(JID, StateData) ->
@@ -1423,7 +1416,6 @@ make_reason(Packet, From, StateData, Reason1) ->
iolist_to_binary(io_lib:format(Reason1, [FromNick, Condition])).
expulse_participant(Packet, From, StateData, Reason1) ->
- IsSubscriber = is_subscriber(From, StateData),
Reason2 = make_reason(Packet, From, StateData, Reason1),
NewState = add_user_presence_un(From,
#xmlel{name = <<"presence">>,
@@ -1438,7 +1430,7 @@ expulse_participant(Packet, From, StateData, Reason1) ->
Reason2}]}]},
StateData),
send_new_presence(From, NewState, StateData),
- remove_online_user(From, NewState, IsSubscriber).
+ remove_online_user(From, NewState).
set_affiliation(JID, Affiliation, StateData) ->
set_affiliation(JID, Affiliation, StateData, <<"">>).
@@ -1718,8 +1710,7 @@ prepare_room_queue(StateData) ->
{empty, _} -> StateData
end.
-update_online_user(JID, #user{nick = Nick, subscriptions = Nodes,
- is_subscriber = IsSubscriber} = User, StateData) ->
+update_online_user(JID, #user{nick = Nick} = User, StateData) ->
LJID = jid:tolower(JID),
Nicks1 = case (?DICT):find(LJID, StateData#state.users) of
{ok, #user{nick = OldNick}} ->
@@ -1738,9 +1729,7 @@ update_online_user(JID, #user{nick = Nick, subscriptions = Nodes,
[LJID], Nicks1),
Users = (?DICT):update(LJID,
fun(U) ->
- U#user{nick = Nick,
- subscriptions = Nodes,
- is_subscriber = IsSubscriber}
+ U#user{nick = Nick}
end, User, StateData#state.users),
NewStateData = StateData#state{users = Users, nicks = Nicks},
case {?DICT:find(LJID, StateData#state.users),
@@ -1752,32 +1741,26 @@ update_online_user(JID, #user{nick = Nick, subscriptions = Nodes,
end,
NewStateData.
-add_online_user(JID, Nick, Role, IsSubscriber, Nodes, StateData) ->
- User = #user{jid = JID, nick = Nick, role = Role,
- is_subscriber = IsSubscriber, subscriptions = Nodes},
- StateData1 = update_online_user(JID, User, StateData),
- if IsSubscriber ->
- store_room(StateData1);
- true ->
- ok
- end,
- StateData1.
+set_subscriber(JID, Nick, Nodes, StateData) ->
+ BareJID = jid:remove_resource(JID),
+ Subscribers = ?DICT:store(jid:tolower(BareJID),
+ #subscriber{jid = BareJID,
+ nick = Nick,
+ nodes = Nodes},
+ StateData#state.subscribers),
+ NewStateData = StateData#state{subscribers = Subscribers},
+ store_room(NewStateData),
+ NewStateData.
-remove_online_user(JID, StateData, IsSubscriber) ->
- remove_online_user(JID, StateData, IsSubscriber, <<"">>).
+add_online_user(JID, Nick, Role, StateData) ->
+ tab_add_online_user(JID, StateData),
+ User = #user{jid = JID, nick = Nick, role = Role},
+ update_online_user(JID, User, StateData).
-remove_online_user(JID, StateData, _IsSubscriber = true, _Reason) ->
- LJID = jid:tolower(JID),
- Users = case (?DICT):find(LJID, StateData#state.users) of
- {ok, U} ->
- (?DICT):store(LJID, U#user{last_presence = undefined},
- StateData#state.users);
- error ->
- StateData#state.users
- end,
- tab_remove_online_user(JID, StateData),
- StateData#state{users = Users};
-remove_online_user(JID, StateData, _IsSubscriber, Reason) ->
+remove_online_user(JID, StateData) ->
+ remove_online_user(JID, StateData, <<"">>).
+
+remove_online_user(JID, StateData, Reason) ->
LJID = jid:tolower(JID),
{ok, #user{nick = Nick}} = (?DICT):find(LJID,
StateData#state.users),
@@ -2032,9 +2015,7 @@ add_new_user(From, Nick,
NewState = add_user_presence(
From, Packet,
add_online_user(From, Nick, Role,
- IsSubscribeRequest,
- Nodes, StateData)),
- tab_add_online_user(From, NewState),
+ StateData)),
send_existing_presences(From, NewState),
send_initial_presence(From, NewState, StateData),
Shift = count_stanza_shift(Nick, Els, NewState),
@@ -2044,9 +2025,7 @@ add_new_user(From, Nick,
end,
NewState;
true ->
- add_online_user(From, Nick, none,
- IsSubscribeRequest,
- Nodes, StateData)
+ set_subscriber(From, Nick, Nodes, StateData)
end,
ResultState =
case NewStateData#state.just_created of
@@ -2286,15 +2265,6 @@ presence_broadcast_allowed(JID, StateData) ->
Role = get_role(JID, StateData),
lists:member(Role, (StateData#state.config)#config.presence_broadcast).
-is_initial_presence(From, StateData) ->
- LJID = jid:tolower(From),
- case (?DICT):find(LJID, StateData#state.users) of
- {ok, #user{last_presence = Pres}} when Pres /= undefined ->
- false;
- _ ->
- true
- end.
-
send_initial_presence(NJID, StateData, OldStateData) ->
send_new_presence1(NJID, <<"">>, true, StateData, OldStateData).
@@ -2388,7 +2358,7 @@ send_new_presence1(NJID, Reason, IsInitialPresence, StateData, OldStateData) ->
true ->
[{LNJID, UserInfo}];
false ->
- (?DICT):to_list(StateData#state.users)
+ (?DICT):to_list(get_users_and_subscribers(StateData))
end,
lists:foreach(
fun({LUJID, Info}) ->
@@ -2444,7 +2414,7 @@ send_new_presence1(NJID, Reason, IsInitialPresence, StateData, OldStateData) ->
send_wrapped(jid:replace_resource(StateData#state.jid, Nick),
Info#user.jid, Packet, Node1, StateData),
Type = fxml:get_tag_attr_s(<<"type">>, Packet),
- IsSubscriber = Info#user.is_subscriber,
+ IsSubscriber = is_subscriber(Info#user.jid, StateData),
IsOccupant = Info#user.last_presence /= undefined,
if (IsSubscriber and not IsOccupant) and
(IsInitialPresence or (Type == <<"unavailable">>)) ->
@@ -2668,19 +2638,20 @@ send_nick_changing(JID, OldNick, StateData,
(_) ->
ok
end,
- (?DICT):to_list(StateData#state.users)).
+ ?DICT:to_list(get_users_and_subscribers(StateData))).
maybe_send_affiliation(JID, Affiliation, StateData) ->
LJID = jid:tolower(JID),
+ Users = get_users_and_subscribers(StateData),
IsOccupant = case LJID of
{LUser, LServer, <<"">>} ->
not (?DICT):is_empty(
(?DICT):filter(fun({U, S, _}, _) ->
U == LUser andalso
S == LServer
- end, StateData#state.users));
+ end, Users));
{_LUser, _LServer, _LResource} ->
- (?DICT):is_key(LJID, StateData#state.users)
+ (?DICT):is_key(LJID, Users)
end,
case IsOccupant of
true ->
@@ -2701,19 +2672,19 @@ send_affiliation(LJID, Affiliation, StateData) ->
children =
[#xmlel{name = <<"item">>,
attrs = ItemAttrs}]}]},
+ Users = get_users_and_subscribers(StateData),
Recipients = case (StateData#state.config)#config.anonymous of
true ->
(?DICT):filter(fun(_, #user{role = moderator}) ->
true;
(_, _) ->
false
- end, StateData#state.users);
+ end, Users);
false ->
- StateData#state.users
+ Users
end,
- send_multiple(StateData#state.jid,
- StateData#state.server_host,
- Recipients, Message).
+ send_wrapped_multiple(StateData#state.jid, Recipients, Message,
+ ?NS_MUCSUB_NODES_AFFILIATIONS, StateData).
status_els(IsInitialPresence, JID, #user{jid = JID}, StateData) ->
Status = case IsInitialPresence of
@@ -3420,7 +3391,7 @@ send_kickban_presence1(MJID, UJID, Reason, Code, Affiliation,
StateData#state.jid, Nick),
send_wrapped(RoomJIDNick, Info#user.jid, Packet,
?NS_MUCSUB_NODES_AFFILIATIONS, StateData),
- IsSubscriber = Info#user.is_subscriber,
+ IsSubscriber = is_subscriber(Info#user.jid, StateData),
IsOccupant = Info#user.last_presence /= undefined,
if (IsSubscriber and not IsOccupant) ->
send_wrapped(RoomJIDNick, Info#user.jid, Packet,
@@ -3429,7 +3400,7 @@ send_kickban_presence1(MJID, UJID, Reason, Code, Affiliation,
ok
end
end,
- (?DICT):to_list(StateData#state.users)).
+ (?DICT):to_list(get_users_and_subscribers(StateData))).
get_actor_nick(<<"">>, _StateData) ->
<<"">>;
@@ -4259,7 +4230,7 @@ send_config_change_info(New, #state{config = Old} = StateData) ->
attrs = [{<<"xmlns">>, ?NS_MUC_USER}],
children = StatusEls}]},
send_wrapped_multiple(StateData#state.jid,
- StateData#state.users,
+ get_users_and_subscribers(StateData),
Message,
?NS_MUCSUB_NODES_CONFIG,
StateData).
@@ -4275,7 +4246,7 @@ remove_nonmembers(StateData) ->
_ -> SD
end
end,
- StateData, (?DICT):to_list(StateData#state.users)).
+ StateData, (?DICT):to_list(get_users_and_subscribers(StateData))).
set_opts([], StateData) -> StateData;
set_opts([{Opt, Val} | Opts], StateData) ->
@@ -4396,14 +4367,17 @@ set_opts([{Opt, Val} | Opts], StateData) ->
StateData#state{config =
(StateData#state.config)#config{allow_subscription = Val}};
subscribers ->
- lists:foldl(
- fun({JID, Nick, Nodes}, State) ->
- User = #user{jid = JID, nick = Nick,
- subscriptions = Nodes,
- is_subscriber = true,
- role = none},
- update_online_user(JID, User, State)
- end, StateData, Val);
+ Subscribers = lists:foldl(
+ fun({JID, Nick, Nodes}, Acc) ->
+ BareJID = jid:remove_resource(JID),
+ ?DICT:store(
+ jid:tolower(BareJID),
+ #subscriber{jid = BareJID,
+ nick = Nick,
+ nodes = Nodes},
+ Acc)
+ end, ?DICT:new(), Val),
+ StateData#state{subscribers = Subscribers};
affiliations ->
StateData#state{affiliations = (?DICT):from_list(Val)};
subject -> StateData#state{subject = Val};
@@ -4418,12 +4392,11 @@ set_opts([{Opt, Val} | Opts], StateData) ->
make_opts(StateData) ->
Config = StateData#state.config,
Subscribers = (?DICT):fold(
- fun(_LJID, #user{is_subscriber = true} = User, Acc) ->
- [{User#user.jid, User#user.nick,
- User#user.subscriptions}|Acc];
- (_, _, Acc) ->
- Acc
- end, [], StateData#state.users),
+ fun(_LJID, Sub, Acc) ->
+ [{Sub#subscriber.jid,
+ Sub#subscriber.nick,
+ Sub#subscriber.nodes}|Acc]
+ end, [], StateData#state.subscribers),
[?MAKE_CONFIG_OPT(title), ?MAKE_CONFIG_OPT(description),
?MAKE_CONFIG_OPT(allow_change_subj),
?MAKE_CONFIG_OPT(allow_query_users),
@@ -4479,7 +4452,7 @@ destroy_room(DEl, StateData) ->
Info#user.jid, Packet,
?NS_MUCSUB_NODES_CONFIG, StateData)
end,
- (?DICT):to_list(StateData#state.users)),
+ (?DICT):to_list(get_users_and_subscribers(StateData))),
case (StateData#state.config)#config.persistent of
true ->
mod_muc:forget_room(StateData#state.server_host,
@@ -4639,9 +4612,9 @@ process_iq_mucsub(From, Packet,
Err = ?ERRT_BAD_REQUEST(Lang, <<"Missing 'nick' attribute">>),
{error, Err};
Nick when Config#config.allow_subscription ->
- LJID = jid:tolower(From),
- case (?DICT):find(LJID, StateData#state.users) of
- {ok, #user{role = Role, nick = Nick1}} when Nick1 /= Nick ->
+ LBareJID = jid:tolower(jid:remove_resource(From)),
+ case (?DICT):find(LBareJID, StateData#state.subscribers) of
+ {ok, #subscriber{nick = Nick1}} when Nick1 /= Nick ->
Nodes = get_subscription_nodes(Packet),
case {nick_collision(From, Nick, StateData),
mod_muc:can_use_nick(StateData#state.server_host,
@@ -4654,14 +4627,12 @@ process_iq_mucsub(From, Packet,
ErrText = <<"That nickname is registered by another person">>,
{error, ?ERRT_CONFLICT(Lang, ErrText)};
_ ->
- NewStateData = add_online_user(
- From, Nick, Role, true, Nodes, StateData),
+ NewStateData = set_subscriber(From, Nick, Nodes, StateData),
{result, subscription_nodes_to_events(Nodes), NewStateData}
end;
- {ok, #user{role = Role}} ->
+ {ok, #subscriber{}} ->
Nodes = get_subscription_nodes(Packet),
- NewStateData = add_online_user(
- From, Nick, Role, true, Nodes, StateData),
+ NewStateData = set_subscriber(From, Nick, Nodes, StateData),
{result, subscription_nodes_to_events(Nodes), NewStateData};
error ->
add_new_user(From, Nick, Packet, StateData)
@@ -4674,27 +4645,11 @@ process_iq_mucsub(From, _Packet,
#iq{type = set,
sub_el = #xmlel{name = <<"unsubscribe">>}},
StateData) ->
- LJID = jid:tolower(From),
- case ?DICT:find(LJID, StateData#state.users) of
- {ok, #user{is_subscriber = true} = User} ->
- NewStateData = remove_subscription(From, User, StateData),
- store_room(NewStateData),
- {result, [], NewStateData};
- error when From#jid.lresource == <<"">> ->
- {LUser, LServer, _} = LJID,
- NewStateData =
- dict:fold(
- fun({U, S, _}, #user{jid = J, is_subscriber = true} = User,
- AccState) when U == LUser, S == LServer ->
- remove_subscription(J, User, AccState);
- (_, _, AccState) ->
- AccState
- end, StateData, StateData#state.users),
- store_room(NewStateData),
- {result, [], NewStateData};
- _ ->
- {result, [], StateData}
- end;
+ LBareJID = jid:tolower(jid:remove_resource(From)),
+ Subscribers = ?DICT:erase(LBareJID, StateData#state.subscribers),
+ NewStateData = StateData#state{subscribers = Subscribers},
+ store_room(NewStateData),
+ {result, [], NewStateData};
process_iq_mucsub(From, _Packet,
#iq{type = get, lang = Lang,
sub_el = #xmlel{name = <<"subscriptions">>}},
@@ -4703,13 +4658,11 @@ process_iq_mucsub(From, _Packet,
FRole = get_role(From, StateData),
if FRole == moderator; FAffiliation == owner; FAffiliation == admin ->
Subs = dict:fold(
- fun(_, #user{is_subscriber = true, jid = J}, Acc) ->
- SJID = jid:to_string(jid:remove_resource(J)),
+ fun(_, #subscriber{jid = J}, Acc) ->
+ SJID = jid:to_string(J),
[#xmlel{name = <<"subscription">>,
- attrs = [{<<"jid">>, SJID}]}|Acc];
- (_, _, Acc) ->
- Acc
- end, [], StateData#state.users),
+ attrs = [{<<"jid">>, SJID}]}|Acc]
+ end, [], StateData#state.subscribers),
{result, Subs, StateData};
true ->
Txt = <<"Moderator privileges required">>,
@@ -4719,25 +4672,9 @@ process_iq_mucsub(_From, _Packet, #iq{lang = Lang}, _StateData) ->
Txt = <<"Unrecognized subscription command">>,
{error, ?ERRT_BAD_REQUEST(Lang, Txt)}.
-remove_subscription(JID, #user{is_subscriber = true} = User, StateData) ->
- case User#user.last_presence of
- undefined ->
- remove_online_user(JID, StateData, false);
- _ ->
- LJID = jid:tolower(JID),
- Users = ?DICT:store(LJID, User#user{is_subscriber = false},
- StateData#state.users),
- StateData#state{users = Users}
- end;
-remove_subscription(_JID, #user{}, StateData) ->
- StateData.
-
remove_subscriptions(StateData) ->
if not (StateData#state.config)#config.allow_subscription ->
- dict:fold(
- fun(_LJID, User, State) ->
- remove_subscription(User#user.jid, User, State)
- end, StateData, StateData#state.users);
+ StateData#state{subscribers = ?DICT:new()};
true ->
StateData
end.
@@ -5198,18 +5135,26 @@ store_room(StateData) ->
send_wrapped(From, To, Packet, Node, State) ->
LTo = jid:tolower(To),
- case ?DICT:find(LTo, State#state.users) of
- {ok, #user{is_subscriber = true,
- subscriptions = Nodes,
- last_presence = undefined}} ->
- case lists:member(Node, Nodes) of
- true ->
- NewPacket = wrap(From, To, Packet, Node),
- ejabberd_router:route(State#state.jid, To, NewPacket);
- false ->
+ LBareTo = jid:tolower(jid:remove_resource(To)),
+ IsOffline = case ?DICT:find(LTo, State#state.users) of
+ {ok, #user{last_presence = undefined}} -> true;
+ error -> true;
+ _ -> false
+ end,
+ if IsOffline ->
+ case ?DICT:find(LBareTo, State#state.subscribers) of
+ {ok, #subscriber{nodes = Nodes, jid = JID}} ->
+ case lists:member(Node, Nodes) of
+ true ->
+ NewPacket = wrap(From, JID, Packet, Node),
+ ejabberd_router:route(State#state.jid, JID, NewPacket);
+ false ->
+ ok
+ end;
+ _ ->
ok
end;
- _ ->
+ true ->
ejabberd_router:route(From, To, Packet)
end.
@@ -5230,9 +5175,9 @@ wrap(From, To, Packet, Node) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Multicast
-send_multiple(From, Server, Users, Packet) ->
- JIDs = [ User#user.jid || {_, User} <- ?DICT:to_list(Users)],
- ejabberd_router_multicast:route_multicast(From, Server, JIDs, Packet).
+%% send_multiple(From, Server, Users, Packet) ->
+%% JIDs = [ User#user.jid || {_, User} <- ?DICT:to_list(Users)],
+%% ejabberd_router_multicast:route_multicast(From, Server, JIDs, Packet).
send_wrapped_multiple(From, Users, Packet, Node, State) ->
lists:foreach(