New hook: muc_filter_presence

Add a hook that allows for modifying or dropping presence stanzas sent
to MUC rooms.
This commit is contained in:
Holger Weiss 2015-08-04 20:13:00 +02:00
parent e3b7d43b76
commit 3d4e8ffac6
1 changed files with 118 additions and 110 deletions

View File

@ -1035,117 +1035,125 @@ get_participant_data(From, StateData) ->
end. end.
process_presence(From, Nick, process_presence(From, Nick,
#xmlel{name = <<"presence">>, attrs = Attrs} = Packet, #xmlel{name = <<"presence">>, attrs = Attrs0} = Packet0,
StateData) -> StateData) ->
Type = xml:get_attr_s(<<"type">>, Attrs), Type0 = xml:get_attr_s(<<"type">>, Attrs0),
Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), IsOnline = is_user_online(From, StateData),
StateData1 = case Type of if Type0 == <<"">>;
<<"unavailable">> -> IsOnline and ((Type0 == <<"unavailable">>) or (Type0 == <<"error">>)) ->
case is_user_online(From, StateData) of case ejabberd_hooks:run_fold(muc_filter_presence,
true -> StateData#state.server_host,
NewPacket = case Packet0,
{(StateData#state.config)#config.allow_visitor_status, [StateData,
is_visitor(From, StateData)} StateData#state.jid,
of From, Nick]) of
{false, true} -> drop ->
strip_status(Packet); {next_state, normal_state, StateData};
_ -> Packet #xmlel{attrs = Attrs} = Packet ->
end, Type = xml:get_attr_s(<<"xml:lang">>, Attrs),
NewState = add_user_presence_un(From, NewPacket, Lang = xml:get_attr_s(<<"xml:lang">>, Attrs),
StateData), StateData1 = case Type of
case (?DICT):find(Nick, StateData#state.nicks) of <<"unavailable">> ->
{ok, [_, _ | _]} -> ok; NewPacket = case
_ -> send_new_presence(From, NewState) {(StateData#state.config)#config.allow_visitor_status,
end, is_visitor(From, StateData)}
Reason = case xml:get_subtag(NewPacket, of
<<"status">>) {false, true} ->
of strip_status(Packet);
false -> <<"">>; _ -> Packet
Status_el -> end,
xml:get_tag_cdata(Status_el) NewState = add_user_presence_un(From, NewPacket,
end, StateData),
remove_online_user(From, NewState, Reason); case (?DICT):find(Nick, StateData#state.nicks) of
_ -> StateData {ok, [_, _ | _]} -> ok;
end; _ -> send_new_presence(From, NewState)
<<"error">> -> end,
case is_user_online(From, StateData) of Reason = case xml:get_subtag(NewPacket,
true -> <<"status">>)
ErrorText = of
<<"This participant is kicked from the " false -> <<"">>;
"room because he sent an error presence">>, Status_el ->
expulse_participant(Packet, From, StateData, xml:get_tag_cdata(Status_el)
translate:translate(Lang, end,
ErrorText)); remove_online_user(From, NewState, Reason);
_ -> StateData <<"error">> ->
end; ErrorText =
<<"">> -> <<"This participant is kicked from the "
case is_user_online(From, StateData) of "room because he sent an error presence">>,
true -> expulse_participant(Packet, From, StateData,
case is_nick_change(From, Nick, StateData) of translate:translate(Lang,
true -> ErrorText));
case {nick_collision(From, Nick, StateData), <<"">> ->
mod_muc:can_use_nick(StateData#state.server_host, if not IsOnline ->
StateData#state.host, add_new_user(From, Nick, Packet, StateData);
From, Nick), true ->
{(StateData#state.config)#config.allow_visitor_nickchange, case is_nick_change(From, Nick, StateData) of
is_visitor(From, StateData)}} true ->
of case {nick_collision(From, Nick, StateData),
{_, _, {false, true}} -> mod_muc:can_use_nick(StateData#state.server_host,
ErrText = StateData#state.host,
<<"Visitors are not allowed to change their " From, Nick),
"nicknames in this room">>, {(StateData#state.config)#config.allow_visitor_nickchange,
Err = jlib:make_error_reply(Packet, is_visitor(From, StateData)}}
?ERRT_NOT_ALLOWED(Lang, of
ErrText)), {_, _, {false, true}} ->
ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, ErrText =
Nick), <<"Visitors are not allowed to change their "
From, Err), "nicknames in this room">>,
StateData; Err = jlib:make_error_reply(Packet,
{true, _, _} -> ?ERRT_NOT_ALLOWED(Lang,
Lang = xml:get_attr_s(<<"xml:lang">>, ErrText)),
Attrs), ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid,
ErrText = Nick),
<<"That nickname is already in use by another " From, Err),
"occupant">>, StateData;
Err = jlib:make_error_reply(Packet, {true, _, _} ->
?ERRT_CONFLICT(Lang, Lang = xml:get_attr_s(<<"xml:lang">>,
ErrText)), Attrs),
ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, ErrText =
Nick), % TODO: s/Nick/""/ <<"That nickname is already in use by another "
From, Err), "occupant">>,
StateData; Err = jlib:make_error_reply(Packet,
{_, false, _} -> ?ERRT_CONFLICT(Lang,
ErrText = ErrText)),
<<"That nickname is registered by another " ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid,
"person">>, Nick), % TODO: s/Nick/""/
Err = jlib:make_error_reply(Packet, From, Err),
?ERRT_CONFLICT(Lang, StateData;
ErrText)), {_, false, _} ->
ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, ErrText =
Nick), <<"That nickname is registered by another "
From, Err), "person">>,
StateData; Err = jlib:make_error_reply(Packet,
_ -> change_nick(From, Nick, StateData) ?ERRT_CONFLICT(Lang,
end; ErrText)),
_NotNickChange -> ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid,
Stanza = case Nick),
{(StateData#state.config)#config.allow_visitor_status, From, Err),
is_visitor(From, StateData)} StateData;
of _ -> change_nick(From, Nick, StateData)
{false, true} -> end;
strip_status(Packet); _NotNickChange ->
_Allowed -> Packet Stanza = case
end, {(StateData#state.config)#config.allow_visitor_status,
NewState = add_user_presence(From, Stanza, is_visitor(From, StateData)}
StateData), of
send_new_presence(From, NewState), {false, true} ->
NewState strip_status(Packet);
end; _Allowed -> Packet
_ -> add_new_user(From, Nick, Packet, StateData) end,
end; NewState = add_user_presence(From, Stanza,
_ -> StateData StateData),
end, send_new_presence(From, NewState),
close_room_if_temporary_and_empty(StateData1). NewState
end
end
end,
close_room_if_temporary_and_empty(StateData1)
end;
true ->
{next_state, normal_state, StateData}
end.
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