mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-20 16:15:59 +01:00
Link MUC subscription to bare JID
This commit is contained in:
parent
1edca899ff
commit
3803a8de3c
@ -77,11 +77,15 @@
|
||||
jid :: jid(),
|
||||
nick :: binary(),
|
||||
role :: role(),
|
||||
is_subscriber = false :: boolean(),
|
||||
subscriptions = [] :: [binary()],
|
||||
%%is_subscriber = false :: boolean(),
|
||||
%%subscriptions = [] :: [binary()],
|
||||
last_presence :: xmlel()
|
||||
}).
|
||||
|
||||
-record(subscriber, {jid :: jid(),
|
||||
nick = <<>> :: binary(),
|
||||
nodes = [] :: [binary()]}).
|
||||
|
||||
-record(activity,
|
||||
{
|
||||
message_time = 0 :: integer(),
|
||||
@ -101,6 +105,7 @@
|
||||
jid = #jid{} :: jid(),
|
||||
config = #config{} :: config(),
|
||||
users = (?DICT):new() :: ?TDICT,
|
||||
subscribers = (?DICT):new() :: ?TDICT,
|
||||
last_voice_request_time = treap:empty() :: treap:treap(),
|
||||
robots = (?DICT):new() :: ?TDICT,
|
||||
nicks = (?DICT):new() :: ?TDICT,
|
||||
|
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user