mirror of
https://github.com/processone/ejabberd.git
synced 2024-06-02 21:17:12 +02:00
Link MUC subscription to bare JID
This commit is contained in:
parent
1edca899ff
commit
3803a8de3c
|
@ -77,11 +77,15 @@
|
||||||
jid :: jid(),
|
jid :: jid(),
|
||||||
nick :: binary(),
|
nick :: binary(),
|
||||||
role :: role(),
|
role :: role(),
|
||||||
is_subscriber = false :: boolean(),
|
%%is_subscriber = false :: boolean(),
|
||||||
subscriptions = [] :: [binary()],
|
%%subscriptions = [] :: [binary()],
|
||||||
last_presence :: xmlel()
|
last_presence :: xmlel()
|
||||||
}).
|
}).
|
||||||
|
|
||||||
|
-record(subscriber, {jid :: jid(),
|
||||||
|
nick = <<>> :: binary(),
|
||||||
|
nodes = [] :: [binary()]}).
|
||||||
|
|
||||||
-record(activity,
|
-record(activity,
|
||||||
{
|
{
|
||||||
message_time = 0 :: integer(),
|
message_time = 0 :: integer(),
|
||||||
|
@ -101,6 +105,7 @@
|
||||||
jid = #jid{} :: jid(),
|
jid = #jid{} :: jid(),
|
||||||
config = #config{} :: config(),
|
config = #config{} :: config(),
|
||||||
users = (?DICT):new() :: ?TDICT,
|
users = (?DICT):new() :: ?TDICT,
|
||||||
|
subscribers = (?DICT):new() :: ?TDICT,
|
||||||
last_voice_request_time = treap:empty() :: treap:treap(),
|
last_voice_request_time = treap:empty() :: treap:treap(),
|
||||||
robots = (?DICT):new() :: ?TDICT,
|
robots = (?DICT):new() :: ?TDICT,
|
||||||
nicks = (?DICT):new() :: ?TDICT,
|
nicks = (?DICT):new() :: ?TDICT,
|
||||||
|
|
|
@ -678,7 +678,7 @@ handle_event({service_message, Msg}, _StateName,
|
||||||
children = [{xmlcdata, Msg}]}]},
|
children = [{xmlcdata, Msg}]}]},
|
||||||
send_wrapped_multiple(
|
send_wrapped_multiple(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
StateData#state.users,
|
get_users_and_subscribers(StateData),
|
||||||
MessagePkt,
|
MessagePkt,
|
||||||
?NS_MUCSUB_NODES_MESSAGES,
|
?NS_MUCSUB_NODES_MESSAGES,
|
||||||
StateData),
|
StateData),
|
||||||
|
@ -750,12 +750,8 @@ handle_sync_event({process_item_change, Item, UJID}, _From, StateName, StateData
|
||||||
NSD = process_item_change(Item, StateData, UJID),
|
NSD = process_item_change(Item, StateData, UJID),
|
||||||
{reply, {ok, NSD}, StateName, NSD};
|
{reply, {ok, NSD}, StateName, NSD};
|
||||||
handle_sync_event(get_subscribers, _From, StateName, StateData) ->
|
handle_sync_event(get_subscribers, _From, StateName, StateData) ->
|
||||||
JIDs = dict:fold(
|
JIDs = lists:map(fun jid:make/1,
|
||||||
fun(_, #user{is_subscriber = true, jid = J}, Acc) ->
|
?DICT:fetch_keys(StateData#state.subscribers)),
|
||||||
[J|Acc];
|
|
||||||
(_, _, Acc) ->
|
|
||||||
Acc
|
|
||||||
end, [], StateData#state.users),
|
|
||||||
{reply, {ok, JIDs}, StateName, StateData};
|
{reply, {ok, JIDs}, StateName, StateData};
|
||||||
handle_sync_event({muc_subscribe, From, Nick, Nodes}, _From,
|
handle_sync_event({muc_subscribe, From, Nick, Nodes}, _From,
|
||||||
StateName, StateData) ->
|
StateName, StateData) ->
|
||||||
|
@ -936,7 +932,7 @@ terminate(Reason, _StateName, StateData) ->
|
||||||
end,
|
end,
|
||||||
tab_remove_online_user(LJID, StateData)
|
tab_remove_online_user(LJID, StateData)
|
||||||
end,
|
end,
|
||||||
[], StateData#state.users),
|
[], get_users_and_subscribers(StateData)),
|
||||||
add_to_log(room_existence, stopped, StateData),
|
add_to_log(room_existence, stopped, StateData),
|
||||||
mod_muc:room_destroyed(StateData#state.host, StateData#state.room, self(),
|
mod_muc:room_destroyed(StateData#state.host, StateData#state.room, self(),
|
||||||
StateData#state.server_host),
|
StateData#state.server_host),
|
||||||
|
@ -953,11 +949,12 @@ process_groupchat_message(From,
|
||||||
#xmlel{name = <<"message">>, attrs = Attrs} = Packet,
|
#xmlel{name = <<"message">>, attrs = Attrs} = Packet,
|
||||||
StateData) ->
|
StateData) ->
|
||||||
Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs),
|
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)
|
is_user_allowed_message_nonparticipant(From, StateData)
|
||||||
of
|
of
|
||||||
true ->
|
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
|
if (Role == moderator) or (Role == participant) or IsSubscriber or
|
||||||
((StateData#state.config)#config.moderated == false) ->
|
((StateData#state.config)#config.moderated == false) ->
|
||||||
Subject = check_subject(Packet),
|
Subject = check_subject(Packet),
|
||||||
|
@ -1000,7 +997,7 @@ process_groupchat_message(From,
|
||||||
end,
|
end,
|
||||||
send_wrapped_multiple(
|
send_wrapped_multiple(
|
||||||
jid:replace_resource(StateData#state.jid, FromNick),
|
jid:replace_resource(StateData#state.jid, FromNick),
|
||||||
StateData#state.users,
|
get_users_and_subscribers(StateData),
|
||||||
NewPacket, Node, NewStateData1),
|
NewPacket, Node, NewStateData1),
|
||||||
NewStateData2 = case has_body_or_subject(NewPacket) of
|
NewStateData2 = case has_body_or_subject(NewPacket) of
|
||||||
true ->
|
true ->
|
||||||
|
@ -1068,9 +1065,9 @@ get_participant_data(From, StateData) ->
|
||||||
case (?DICT):find(jid:tolower(From),
|
case (?DICT):find(jid:tolower(From),
|
||||||
StateData#state.users)
|
StateData#state.users)
|
||||||
of
|
of
|
||||||
{ok, #user{nick = FromNick, role = Role, is_subscriber = IsSubscriber}} ->
|
{ok, #user{nick = FromNick, role = Role}} ->
|
||||||
{FromNick, Role, IsSubscriber};
|
{FromNick, Role};
|
||||||
error -> {<<"">>, moderator, false}
|
error -> {<<"">>, moderator}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
process_presence(From, Nick,
|
process_presence(From, Nick,
|
||||||
|
@ -1078,7 +1075,6 @@ process_presence(From, Nick,
|
||||||
StateData) ->
|
StateData) ->
|
||||||
Type0 = fxml:get_attr_s(<<"type">>, Attrs0),
|
Type0 = fxml:get_attr_s(<<"type">>, Attrs0),
|
||||||
IsOnline = is_user_online(From, StateData),
|
IsOnline = is_user_online(From, StateData),
|
||||||
IsSubscriber = is_subscriber(From, StateData),
|
|
||||||
if Type0 == <<"">>;
|
if Type0 == <<"">>;
|
||||||
IsOnline and ((Type0 == <<"unavailable">>) or (Type0 == <<"error">>)) ->
|
IsOnline and ((Type0 == <<"unavailable">>) or (Type0 == <<"error">>)) ->
|
||||||
case ejabberd_hooks:run_fold(muc_filter_presence,
|
case ejabberd_hooks:run_fold(muc_filter_presence,
|
||||||
|
@ -1115,7 +1111,7 @@ process_presence(From, Nick,
|
||||||
Status_el ->
|
Status_el ->
|
||||||
fxml:get_tag_cdata(Status_el)
|
fxml:get_tag_cdata(Status_el)
|
||||||
end,
|
end,
|
||||||
remove_online_user(From, NewState, IsSubscriber, Reason);
|
remove_online_user(From, NewState, Reason);
|
||||||
<<"error">> ->
|
<<"error">> ->
|
||||||
ErrorText = <<"It is not allowed to send error messages to the"
|
ErrorText = <<"It is not allowed to send error messages to the"
|
||||||
" room. The participant (~s) has sent an error "
|
" room. The participant (~s) has sent an error "
|
||||||
|
@ -1172,27 +1168,15 @@ process_presence(From, Nick,
|
||||||
From, Err),
|
From, Err),
|
||||||
StateData;
|
StateData;
|
||||||
_ ->
|
_ ->
|
||||||
case is_initial_presence(From, StateData) of
|
change_nick(From, Nick, StateData)
|
||||||
true ->
|
|
||||||
subscriber_becomes_available(
|
|
||||||
From, Nick, Packet, StateData);
|
|
||||||
false ->
|
|
||||||
change_nick(From, Nick, StateData)
|
|
||||||
end
|
|
||||||
end;
|
end;
|
||||||
_NotNickChange ->
|
_NotNickChange ->
|
||||||
case is_initial_presence(From, StateData) of
|
Stanza = maybe_strip_status_from_presence(
|
||||||
true ->
|
From, Packet, StateData),
|
||||||
subscriber_becomes_available(
|
NewState = add_user_presence(From, Stanza,
|
||||||
From, Nick, Packet, StateData);
|
StateData),
|
||||||
false ->
|
send_new_presence(From, NewState, StateData),
|
||||||
Stanza = maybe_strip_status_from_presence(
|
NewState
|
||||||
From, Packet, StateData),
|
|
||||||
NewState = add_user_presence(From, Stanza,
|
|
||||||
StateData),
|
|
||||||
send_new_presence(From, NewState, StateData),
|
|
||||||
NewState
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
@ -1210,22 +1194,10 @@ maybe_strip_status_from_presence(From, Packet, StateData) ->
|
||||||
_Allowed -> Packet
|
_Allowed -> Packet
|
||||||
end.
|
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) ->
|
close_room_if_temporary_and_empty(StateData1) ->
|
||||||
case not (StateData1#state.config)#config.persistent
|
case not (StateData1#state.config)#config.persistent
|
||||||
andalso (?DICT):to_list(StateData1#state.users) == []
|
andalso (?DICT):size(StateData1#state.users) == 0
|
||||||
of
|
andalso (?DICT):size(StateData1#state.subscribers) == 0 of
|
||||||
true ->
|
true ->
|
||||||
?INFO_MSG("Destroyed MUC room ~s because it's temporary "
|
?INFO_MSG("Destroyed MUC room ~s because it's temporary "
|
||||||
"and empty",
|
"and empty",
|
||||||
|
@ -1235,18 +1207,39 @@ close_room_if_temporary_and_empty(StateData1) ->
|
||||||
_ -> {next_state, normal_state, StateData1}
|
_ -> {next_state, normal_state, StateData1}
|
||||||
end.
|
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) ->
|
is_user_online(JID, StateData) ->
|
||||||
LJID = jid:tolower(JID),
|
LJID = jid:tolower(JID),
|
||||||
(?DICT):is_key(LJID, StateData#state.users).
|
(?DICT):is_key(LJID, StateData#state.users).
|
||||||
|
|
||||||
is_subscriber(JID, StateData) ->
|
is_subscriber(JID, StateData) ->
|
||||||
LJID = jid:tolower(JID),
|
LJID = jid:tolower(jid:remove_resource(JID)),
|
||||||
case (?DICT):find(LJID, StateData#state.users) of
|
(?DICT):is_key(LJID, StateData#state.subscribers).
|
||||||
{ok, #user{is_subscriber = IsSubscriber}} ->
|
|
||||||
IsSubscriber;
|
|
||||||
_ ->
|
|
||||||
false
|
|
||||||
end.
|
|
||||||
|
|
||||||
%% Check if the user is occupant of the room, or at least is an admin or owner.
|
%% Check if the user is occupant of the room, or at least is an admin or owner.
|
||||||
is_occupant_or_admin(JID, StateData) ->
|
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])).
|
iolist_to_binary(io_lib:format(Reason1, [FromNick, Condition])).
|
||||||
|
|
||||||
expulse_participant(Packet, From, StateData, Reason1) ->
|
expulse_participant(Packet, From, StateData, Reason1) ->
|
||||||
IsSubscriber = is_subscriber(From, StateData),
|
|
||||||
Reason2 = make_reason(Packet, From, StateData, Reason1),
|
Reason2 = make_reason(Packet, From, StateData, Reason1),
|
||||||
NewState = add_user_presence_un(From,
|
NewState = add_user_presence_un(From,
|
||||||
#xmlel{name = <<"presence">>,
|
#xmlel{name = <<"presence">>,
|
||||||
|
@ -1438,7 +1430,7 @@ expulse_participant(Packet, From, StateData, Reason1) ->
|
||||||
Reason2}]}]},
|
Reason2}]}]},
|
||||||
StateData),
|
StateData),
|
||||||
send_new_presence(From, NewState, 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) ->
|
||||||
set_affiliation(JID, Affiliation, StateData, <<"">>).
|
set_affiliation(JID, Affiliation, StateData, <<"">>).
|
||||||
|
@ -1718,8 +1710,7 @@ prepare_room_queue(StateData) ->
|
||||||
{empty, _} -> StateData
|
{empty, _} -> StateData
|
||||||
end.
|
end.
|
||||||
|
|
||||||
update_online_user(JID, #user{nick = Nick, subscriptions = Nodes,
|
update_online_user(JID, #user{nick = Nick} = User, StateData) ->
|
||||||
is_subscriber = IsSubscriber} = User, StateData) ->
|
|
||||||
LJID = jid:tolower(JID),
|
LJID = jid:tolower(JID),
|
||||||
Nicks1 = case (?DICT):find(LJID, StateData#state.users) of
|
Nicks1 = case (?DICT):find(LJID, StateData#state.users) of
|
||||||
{ok, #user{nick = OldNick}} ->
|
{ok, #user{nick = OldNick}} ->
|
||||||
|
@ -1738,9 +1729,7 @@ update_online_user(JID, #user{nick = Nick, subscriptions = Nodes,
|
||||||
[LJID], Nicks1),
|
[LJID], Nicks1),
|
||||||
Users = (?DICT):update(LJID,
|
Users = (?DICT):update(LJID,
|
||||||
fun(U) ->
|
fun(U) ->
|
||||||
U#user{nick = Nick,
|
U#user{nick = Nick}
|
||||||
subscriptions = Nodes,
|
|
||||||
is_subscriber = IsSubscriber}
|
|
||||||
end, User, StateData#state.users),
|
end, User, StateData#state.users),
|
||||||
NewStateData = StateData#state{users = Users, nicks = Nicks},
|
NewStateData = StateData#state{users = Users, nicks = Nicks},
|
||||||
case {?DICT:find(LJID, StateData#state.users),
|
case {?DICT:find(LJID, StateData#state.users),
|
||||||
|
@ -1752,32 +1741,26 @@ update_online_user(JID, #user{nick = Nick, subscriptions = Nodes,
|
||||||
end,
|
end,
|
||||||
NewStateData.
|
NewStateData.
|
||||||
|
|
||||||
add_online_user(JID, Nick, Role, IsSubscriber, Nodes, StateData) ->
|
set_subscriber(JID, Nick, Nodes, StateData) ->
|
||||||
User = #user{jid = JID, nick = Nick, role = Role,
|
BareJID = jid:remove_resource(JID),
|
||||||
is_subscriber = IsSubscriber, subscriptions = Nodes},
|
Subscribers = ?DICT:store(jid:tolower(BareJID),
|
||||||
StateData1 = update_online_user(JID, User, StateData),
|
#subscriber{jid = BareJID,
|
||||||
if IsSubscriber ->
|
nick = Nick,
|
||||||
store_room(StateData1);
|
nodes = Nodes},
|
||||||
true ->
|
StateData#state.subscribers),
|
||||||
ok
|
NewStateData = StateData#state{subscribers = Subscribers},
|
||||||
end,
|
store_room(NewStateData),
|
||||||
StateData1.
|
NewStateData.
|
||||||
|
|
||||||
remove_online_user(JID, StateData, IsSubscriber) ->
|
add_online_user(JID, Nick, Role, StateData) ->
|
||||||
remove_online_user(JID, StateData, IsSubscriber, <<"">>).
|
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) ->
|
remove_online_user(JID, StateData) ->
|
||||||
LJID = jid:tolower(JID),
|
remove_online_user(JID, StateData, <<"">>).
|
||||||
Users = case (?DICT):find(LJID, StateData#state.users) of
|
|
||||||
{ok, U} ->
|
remove_online_user(JID, StateData, Reason) ->
|
||||||
(?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) ->
|
|
||||||
LJID = jid:tolower(JID),
|
LJID = jid:tolower(JID),
|
||||||
{ok, #user{nick = Nick}} = (?DICT):find(LJID,
|
{ok, #user{nick = Nick}} = (?DICT):find(LJID,
|
||||||
StateData#state.users),
|
StateData#state.users),
|
||||||
|
@ -2032,9 +2015,7 @@ add_new_user(From, Nick,
|
||||||
NewState = add_user_presence(
|
NewState = add_user_presence(
|
||||||
From, Packet,
|
From, Packet,
|
||||||
add_online_user(From, Nick, Role,
|
add_online_user(From, Nick, Role,
|
||||||
IsSubscribeRequest,
|
StateData)),
|
||||||
Nodes, StateData)),
|
|
||||||
tab_add_online_user(From, NewState),
|
|
||||||
send_existing_presences(From, NewState),
|
send_existing_presences(From, NewState),
|
||||||
send_initial_presence(From, NewState, StateData),
|
send_initial_presence(From, NewState, StateData),
|
||||||
Shift = count_stanza_shift(Nick, Els, NewState),
|
Shift = count_stanza_shift(Nick, Els, NewState),
|
||||||
|
@ -2044,9 +2025,7 @@ add_new_user(From, Nick,
|
||||||
end,
|
end,
|
||||||
NewState;
|
NewState;
|
||||||
true ->
|
true ->
|
||||||
add_online_user(From, Nick, none,
|
set_subscriber(From, Nick, Nodes, StateData)
|
||||||
IsSubscribeRequest,
|
|
||||||
Nodes, StateData)
|
|
||||||
end,
|
end,
|
||||||
ResultState =
|
ResultState =
|
||||||
case NewStateData#state.just_created of
|
case NewStateData#state.just_created of
|
||||||
|
@ -2286,15 +2265,6 @@ presence_broadcast_allowed(JID, StateData) ->
|
||||||
Role = get_role(JID, StateData),
|
Role = get_role(JID, StateData),
|
||||||
lists:member(Role, (StateData#state.config)#config.presence_broadcast).
|
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_initial_presence(NJID, StateData, OldStateData) ->
|
||||||
send_new_presence1(NJID, <<"">>, true, StateData, OldStateData).
|
send_new_presence1(NJID, <<"">>, true, StateData, OldStateData).
|
||||||
|
|
||||||
|
@ -2388,7 +2358,7 @@ send_new_presence1(NJID, Reason, IsInitialPresence, StateData, OldStateData) ->
|
||||||
true ->
|
true ->
|
||||||
[{LNJID, UserInfo}];
|
[{LNJID, UserInfo}];
|
||||||
false ->
|
false ->
|
||||||
(?DICT):to_list(StateData#state.users)
|
(?DICT):to_list(get_users_and_subscribers(StateData))
|
||||||
end,
|
end,
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({LUJID, Info}) ->
|
fun({LUJID, Info}) ->
|
||||||
|
@ -2444,7 +2414,7 @@ send_new_presence1(NJID, Reason, IsInitialPresence, StateData, OldStateData) ->
|
||||||
send_wrapped(jid:replace_resource(StateData#state.jid, Nick),
|
send_wrapped(jid:replace_resource(StateData#state.jid, Nick),
|
||||||
Info#user.jid, Packet, Node1, StateData),
|
Info#user.jid, Packet, Node1, StateData),
|
||||||
Type = fxml:get_tag_attr_s(<<"type">>, Packet),
|
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,
|
IsOccupant = Info#user.last_presence /= undefined,
|
||||||
if (IsSubscriber and not IsOccupant) and
|
if (IsSubscriber and not IsOccupant) and
|
||||||
(IsInitialPresence or (Type == <<"unavailable">>)) ->
|
(IsInitialPresence or (Type == <<"unavailable">>)) ->
|
||||||
|
@ -2668,19 +2638,20 @@ send_nick_changing(JID, OldNick, StateData,
|
||||||
(_) ->
|
(_) ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
(?DICT):to_list(StateData#state.users)).
|
?DICT:to_list(get_users_and_subscribers(StateData))).
|
||||||
|
|
||||||
maybe_send_affiliation(JID, Affiliation, StateData) ->
|
maybe_send_affiliation(JID, Affiliation, StateData) ->
|
||||||
LJID = jid:tolower(JID),
|
LJID = jid:tolower(JID),
|
||||||
|
Users = get_users_and_subscribers(StateData),
|
||||||
IsOccupant = case LJID of
|
IsOccupant = case LJID of
|
||||||
{LUser, LServer, <<"">>} ->
|
{LUser, LServer, <<"">>} ->
|
||||||
not (?DICT):is_empty(
|
not (?DICT):is_empty(
|
||||||
(?DICT):filter(fun({U, S, _}, _) ->
|
(?DICT):filter(fun({U, S, _}, _) ->
|
||||||
U == LUser andalso
|
U == LUser andalso
|
||||||
S == LServer
|
S == LServer
|
||||||
end, StateData#state.users));
|
end, Users));
|
||||||
{_LUser, _LServer, _LResource} ->
|
{_LUser, _LServer, _LResource} ->
|
||||||
(?DICT):is_key(LJID, StateData#state.users)
|
(?DICT):is_key(LJID, Users)
|
||||||
end,
|
end,
|
||||||
case IsOccupant of
|
case IsOccupant of
|
||||||
true ->
|
true ->
|
||||||
|
@ -2701,19 +2672,19 @@ send_affiliation(LJID, Affiliation, StateData) ->
|
||||||
children =
|
children =
|
||||||
[#xmlel{name = <<"item">>,
|
[#xmlel{name = <<"item">>,
|
||||||
attrs = ItemAttrs}]}]},
|
attrs = ItemAttrs}]}]},
|
||||||
|
Users = get_users_and_subscribers(StateData),
|
||||||
Recipients = case (StateData#state.config)#config.anonymous of
|
Recipients = case (StateData#state.config)#config.anonymous of
|
||||||
true ->
|
true ->
|
||||||
(?DICT):filter(fun(_, #user{role = moderator}) ->
|
(?DICT):filter(fun(_, #user{role = moderator}) ->
|
||||||
true;
|
true;
|
||||||
(_, _) ->
|
(_, _) ->
|
||||||
false
|
false
|
||||||
end, StateData#state.users);
|
end, Users);
|
||||||
false ->
|
false ->
|
||||||
StateData#state.users
|
Users
|
||||||
end,
|
end,
|
||||||
send_multiple(StateData#state.jid,
|
send_wrapped_multiple(StateData#state.jid, Recipients, Message,
|
||||||
StateData#state.server_host,
|
?NS_MUCSUB_NODES_AFFILIATIONS, StateData).
|
||||||
Recipients, Message).
|
|
||||||
|
|
||||||
status_els(IsInitialPresence, JID, #user{jid = JID}, StateData) ->
|
status_els(IsInitialPresence, JID, #user{jid = JID}, StateData) ->
|
||||||
Status = case IsInitialPresence of
|
Status = case IsInitialPresence of
|
||||||
|
@ -3420,7 +3391,7 @@ send_kickban_presence1(MJID, UJID, Reason, Code, Affiliation,
|
||||||
StateData#state.jid, Nick),
|
StateData#state.jid, Nick),
|
||||||
send_wrapped(RoomJIDNick, Info#user.jid, Packet,
|
send_wrapped(RoomJIDNick, Info#user.jid, Packet,
|
||||||
?NS_MUCSUB_NODES_AFFILIATIONS, StateData),
|
?NS_MUCSUB_NODES_AFFILIATIONS, StateData),
|
||||||
IsSubscriber = Info#user.is_subscriber,
|
IsSubscriber = is_subscriber(Info#user.jid, StateData),
|
||||||
IsOccupant = Info#user.last_presence /= undefined,
|
IsOccupant = Info#user.last_presence /= undefined,
|
||||||
if (IsSubscriber and not IsOccupant) ->
|
if (IsSubscriber and not IsOccupant) ->
|
||||||
send_wrapped(RoomJIDNick, Info#user.jid, Packet,
|
send_wrapped(RoomJIDNick, Info#user.jid, Packet,
|
||||||
|
@ -3429,7 +3400,7 @@ send_kickban_presence1(MJID, UJID, Reason, Code, Affiliation,
|
||||||
ok
|
ok
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
(?DICT):to_list(StateData#state.users)).
|
(?DICT):to_list(get_users_and_subscribers(StateData))).
|
||||||
|
|
||||||
get_actor_nick(<<"">>, _StateData) ->
|
get_actor_nick(<<"">>, _StateData) ->
|
||||||
<<"">>;
|
<<"">>;
|
||||||
|
@ -4259,7 +4230,7 @@ send_config_change_info(New, #state{config = Old} = StateData) ->
|
||||||
attrs = [{<<"xmlns">>, ?NS_MUC_USER}],
|
attrs = [{<<"xmlns">>, ?NS_MUC_USER}],
|
||||||
children = StatusEls}]},
|
children = StatusEls}]},
|
||||||
send_wrapped_multiple(StateData#state.jid,
|
send_wrapped_multiple(StateData#state.jid,
|
||||||
StateData#state.users,
|
get_users_and_subscribers(StateData),
|
||||||
Message,
|
Message,
|
||||||
?NS_MUCSUB_NODES_CONFIG,
|
?NS_MUCSUB_NODES_CONFIG,
|
||||||
StateData).
|
StateData).
|
||||||
|
@ -4275,7 +4246,7 @@ remove_nonmembers(StateData) ->
|
||||||
_ -> SD
|
_ -> SD
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
StateData, (?DICT):to_list(StateData#state.users)).
|
StateData, (?DICT):to_list(get_users_and_subscribers(StateData))).
|
||||||
|
|
||||||
set_opts([], StateData) -> StateData;
|
set_opts([], StateData) -> StateData;
|
||||||
set_opts([{Opt, Val} | Opts], StateData) ->
|
set_opts([{Opt, Val} | Opts], StateData) ->
|
||||||
|
@ -4396,14 +4367,17 @@ set_opts([{Opt, Val} | Opts], StateData) ->
|
||||||
StateData#state{config =
|
StateData#state{config =
|
||||||
(StateData#state.config)#config{allow_subscription = Val}};
|
(StateData#state.config)#config{allow_subscription = Val}};
|
||||||
subscribers ->
|
subscribers ->
|
||||||
lists:foldl(
|
Subscribers = lists:foldl(
|
||||||
fun({JID, Nick, Nodes}, State) ->
|
fun({JID, Nick, Nodes}, Acc) ->
|
||||||
User = #user{jid = JID, nick = Nick,
|
BareJID = jid:remove_resource(JID),
|
||||||
subscriptions = Nodes,
|
?DICT:store(
|
||||||
is_subscriber = true,
|
jid:tolower(BareJID),
|
||||||
role = none},
|
#subscriber{jid = BareJID,
|
||||||
update_online_user(JID, User, State)
|
nick = Nick,
|
||||||
end, StateData, Val);
|
nodes = Nodes},
|
||||||
|
Acc)
|
||||||
|
end, ?DICT:new(), Val),
|
||||||
|
StateData#state{subscribers = Subscribers};
|
||||||
affiliations ->
|
affiliations ->
|
||||||
StateData#state{affiliations = (?DICT):from_list(Val)};
|
StateData#state{affiliations = (?DICT):from_list(Val)};
|
||||||
subject -> StateData#state{subject = Val};
|
subject -> StateData#state{subject = Val};
|
||||||
|
@ -4418,12 +4392,11 @@ set_opts([{Opt, Val} | Opts], StateData) ->
|
||||||
make_opts(StateData) ->
|
make_opts(StateData) ->
|
||||||
Config = StateData#state.config,
|
Config = StateData#state.config,
|
||||||
Subscribers = (?DICT):fold(
|
Subscribers = (?DICT):fold(
|
||||||
fun(_LJID, #user{is_subscriber = true} = User, Acc) ->
|
fun(_LJID, Sub, Acc) ->
|
||||||
[{User#user.jid, User#user.nick,
|
[{Sub#subscriber.jid,
|
||||||
User#user.subscriptions}|Acc];
|
Sub#subscriber.nick,
|
||||||
(_, _, Acc) ->
|
Sub#subscriber.nodes}|Acc]
|
||||||
Acc
|
end, [], StateData#state.subscribers),
|
||||||
end, [], StateData#state.users),
|
|
||||||
[?MAKE_CONFIG_OPT(title), ?MAKE_CONFIG_OPT(description),
|
[?MAKE_CONFIG_OPT(title), ?MAKE_CONFIG_OPT(description),
|
||||||
?MAKE_CONFIG_OPT(allow_change_subj),
|
?MAKE_CONFIG_OPT(allow_change_subj),
|
||||||
?MAKE_CONFIG_OPT(allow_query_users),
|
?MAKE_CONFIG_OPT(allow_query_users),
|
||||||
|
@ -4479,7 +4452,7 @@ destroy_room(DEl, StateData) ->
|
||||||
Info#user.jid, Packet,
|
Info#user.jid, Packet,
|
||||||
?NS_MUCSUB_NODES_CONFIG, StateData)
|
?NS_MUCSUB_NODES_CONFIG, StateData)
|
||||||
end,
|
end,
|
||||||
(?DICT):to_list(StateData#state.users)),
|
(?DICT):to_list(get_users_and_subscribers(StateData))),
|
||||||
case (StateData#state.config)#config.persistent of
|
case (StateData#state.config)#config.persistent of
|
||||||
true ->
|
true ->
|
||||||
mod_muc:forget_room(StateData#state.server_host,
|
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">>),
|
Err = ?ERRT_BAD_REQUEST(Lang, <<"Missing 'nick' attribute">>),
|
||||||
{error, Err};
|
{error, Err};
|
||||||
Nick when Config#config.allow_subscription ->
|
Nick when Config#config.allow_subscription ->
|
||||||
LJID = jid:tolower(From),
|
LBareJID = jid:tolower(jid:remove_resource(From)),
|
||||||
case (?DICT):find(LJID, StateData#state.users) of
|
case (?DICT):find(LBareJID, StateData#state.subscribers) of
|
||||||
{ok, #user{role = Role, nick = Nick1}} when Nick1 /= Nick ->
|
{ok, #subscriber{nick = Nick1}} when Nick1 /= Nick ->
|
||||||
Nodes = get_subscription_nodes(Packet),
|
Nodes = get_subscription_nodes(Packet),
|
||||||
case {nick_collision(From, Nick, StateData),
|
case {nick_collision(From, Nick, StateData),
|
||||||
mod_muc:can_use_nick(StateData#state.server_host,
|
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">>,
|
ErrText = <<"That nickname is registered by another person">>,
|
||||||
{error, ?ERRT_CONFLICT(Lang, ErrText)};
|
{error, ?ERRT_CONFLICT(Lang, ErrText)};
|
||||||
_ ->
|
_ ->
|
||||||
NewStateData = add_online_user(
|
NewStateData = set_subscriber(From, Nick, Nodes, StateData),
|
||||||
From, Nick, Role, true, Nodes, StateData),
|
|
||||||
{result, subscription_nodes_to_events(Nodes), NewStateData}
|
{result, subscription_nodes_to_events(Nodes), NewStateData}
|
||||||
end;
|
end;
|
||||||
{ok, #user{role = Role}} ->
|
{ok, #subscriber{}} ->
|
||||||
Nodes = get_subscription_nodes(Packet),
|
Nodes = get_subscription_nodes(Packet),
|
||||||
NewStateData = add_online_user(
|
NewStateData = set_subscriber(From, Nick, Nodes, StateData),
|
||||||
From, Nick, Role, true, Nodes, StateData),
|
|
||||||
{result, subscription_nodes_to_events(Nodes), NewStateData};
|
{result, subscription_nodes_to_events(Nodes), NewStateData};
|
||||||
error ->
|
error ->
|
||||||
add_new_user(From, Nick, Packet, StateData)
|
add_new_user(From, Nick, Packet, StateData)
|
||||||
|
@ -4674,27 +4645,11 @@ process_iq_mucsub(From, _Packet,
|
||||||
#iq{type = set,
|
#iq{type = set,
|
||||||
sub_el = #xmlel{name = <<"unsubscribe">>}},
|
sub_el = #xmlel{name = <<"unsubscribe">>}},
|
||||||
StateData) ->
|
StateData) ->
|
||||||
LJID = jid:tolower(From),
|
LBareJID = jid:tolower(jid:remove_resource(From)),
|
||||||
case ?DICT:find(LJID, StateData#state.users) of
|
Subscribers = ?DICT:erase(LBareJID, StateData#state.subscribers),
|
||||||
{ok, #user{is_subscriber = true} = User} ->
|
NewStateData = StateData#state{subscribers = Subscribers},
|
||||||
NewStateData = remove_subscription(From, User, StateData),
|
store_room(NewStateData),
|
||||||
store_room(NewStateData),
|
{result, [], 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;
|
|
||||||
process_iq_mucsub(From, _Packet,
|
process_iq_mucsub(From, _Packet,
|
||||||
#iq{type = get, lang = Lang,
|
#iq{type = get, lang = Lang,
|
||||||
sub_el = #xmlel{name = <<"subscriptions">>}},
|
sub_el = #xmlel{name = <<"subscriptions">>}},
|
||||||
|
@ -4703,13 +4658,11 @@ process_iq_mucsub(From, _Packet,
|
||||||
FRole = get_role(From, StateData),
|
FRole = get_role(From, StateData),
|
||||||
if FRole == moderator; FAffiliation == owner; FAffiliation == admin ->
|
if FRole == moderator; FAffiliation == owner; FAffiliation == admin ->
|
||||||
Subs = dict:fold(
|
Subs = dict:fold(
|
||||||
fun(_, #user{is_subscriber = true, jid = J}, Acc) ->
|
fun(_, #subscriber{jid = J}, Acc) ->
|
||||||
SJID = jid:to_string(jid:remove_resource(J)),
|
SJID = jid:to_string(J),
|
||||||
[#xmlel{name = <<"subscription">>,
|
[#xmlel{name = <<"subscription">>,
|
||||||
attrs = [{<<"jid">>, SJID}]}|Acc];
|
attrs = [{<<"jid">>, SJID}]}|Acc]
|
||||||
(_, _, Acc) ->
|
end, [], StateData#state.subscribers),
|
||||||
Acc
|
|
||||||
end, [], StateData#state.users),
|
|
||||||
{result, Subs, StateData};
|
{result, Subs, StateData};
|
||||||
true ->
|
true ->
|
||||||
Txt = <<"Moderator privileges required">>,
|
Txt = <<"Moderator privileges required">>,
|
||||||
|
@ -4719,25 +4672,9 @@ process_iq_mucsub(_From, _Packet, #iq{lang = Lang}, _StateData) ->
|
||||||
Txt = <<"Unrecognized subscription command">>,
|
Txt = <<"Unrecognized subscription command">>,
|
||||||
{error, ?ERRT_BAD_REQUEST(Lang, Txt)}.
|
{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) ->
|
remove_subscriptions(StateData) ->
|
||||||
if not (StateData#state.config)#config.allow_subscription ->
|
if not (StateData#state.config)#config.allow_subscription ->
|
||||||
dict:fold(
|
StateData#state{subscribers = ?DICT:new()};
|
||||||
fun(_LJID, User, State) ->
|
|
||||||
remove_subscription(User#user.jid, User, State)
|
|
||||||
end, StateData, StateData#state.users);
|
|
||||||
true ->
|
true ->
|
||||||
StateData
|
StateData
|
||||||
end.
|
end.
|
||||||
|
@ -5198,18 +5135,26 @@ store_room(StateData) ->
|
||||||
|
|
||||||
send_wrapped(From, To, Packet, Node, State) ->
|
send_wrapped(From, To, Packet, Node, State) ->
|
||||||
LTo = jid:tolower(To),
|
LTo = jid:tolower(To),
|
||||||
case ?DICT:find(LTo, State#state.users) of
|
LBareTo = jid:tolower(jid:remove_resource(To)),
|
||||||
{ok, #user{is_subscriber = true,
|
IsOffline = case ?DICT:find(LTo, State#state.users) of
|
||||||
subscriptions = Nodes,
|
{ok, #user{last_presence = undefined}} -> true;
|
||||||
last_presence = undefined}} ->
|
error -> true;
|
||||||
case lists:member(Node, Nodes) of
|
_ -> false
|
||||||
true ->
|
end,
|
||||||
NewPacket = wrap(From, To, Packet, Node),
|
if IsOffline ->
|
||||||
ejabberd_router:route(State#state.jid, To, NewPacket);
|
case ?DICT:find(LBareTo, State#state.subscribers) of
|
||||||
false ->
|
{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
|
ok
|
||||||
end;
|
end;
|
||||||
_ ->
|
true ->
|
||||||
ejabberd_router:route(From, To, Packet)
|
ejabberd_router:route(From, To, Packet)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -5230,9 +5175,9 @@ wrap(From, To, Packet, Node) ->
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
%% Multicast
|
%% Multicast
|
||||||
|
|
||||||
send_multiple(From, Server, Users, Packet) ->
|
%% send_multiple(From, Server, Users, Packet) ->
|
||||||
JIDs = [ User#user.jid || {_, User} <- ?DICT:to_list(Users)],
|
%% JIDs = [ User#user.jid || {_, User} <- ?DICT:to_list(Users)],
|
||||||
ejabberd_router_multicast:route_multicast(From, Server, JIDs, Packet).
|
%% ejabberd_router_multicast:route_multicast(From, Server, JIDs, Packet).
|
||||||
|
|
||||||
send_wrapped_multiple(From, Users, Packet, Node, State) ->
|
send_wrapped_multiple(From, Users, Packet, Node, State) ->
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
|
|
Loading…
Reference in New Issue
Block a user