* src/mod_muc/mod_muc_room.erl: MUC kicks a participant if sends a

private message with type=error (EJAB-496)

SVN Revision: 1163
This commit is contained in:
Badlop 2008-01-29 14:49:08 +00:00
parent fbe26a9186
commit b29e6ef07f
2 changed files with 116 additions and 44 deletions

View File

@ -1,3 +1,8 @@
2008-01-29 Badlop <badlop@process-one.net>
* src/mod_muc/mod_muc_room.erl: MUC kicks a participant if sends a
private message with type=error (EJAB-496)
2008-01-25 Badlop <badlop@process-one.net> 2008-01-25 Badlop <badlop@process-one.net>
* doc/introduction.tex: Updated list of languages * doc/introduction.tex: Updated list of languages

View File

@ -298,7 +298,10 @@ normal_state({route, From, "",
add_user_presence_un( add_user_presence_un(
From, From,
{xmlelement, "presence", {xmlelement, "presence",
[{"type", "unavailable"}], []}, [{"type", "unavailable"}],
[{xmlelement, "status", [],
[{xmlcdata,
"This participant sent a bad error message to the room."}]}]},
StateData), StateData),
send_new_presence(From, NewState), send_new_presence(From, NewState),
{next_state, normal_state, {next_state, normal_state,
@ -465,57 +468,75 @@ normal_state({route, From, Nick,
end; end;
normal_state({route, From, ToNick, normal_state({route, From, ToNick,
{xmlelement, "message", Attrs, _Els} = Packet}, {xmlelement, "message", Attrs, _} = Packet},
StateData) -> StateData) ->
Type = xml:get_attr_s("type", Attrs), Type = xml:get_attr_s("type", Attrs),
Lang = xml:get_attr_s("xml:lang", Attrs), Lang = xml:get_attr_s("xml:lang", Attrs),
case (StateData#state.config)#config.allow_private_messages case decide_fate_message(Type, Packet, From, StateData) of
andalso is_user_online(From, StateData) of {expulse_sender, Reason} ->
true -> ?INFO_MSG(Reason, []),
case Type of Status_text = "This participant sent a bad error message to another participant.",
"groupchat" -> NewState =
ErrText = "It is not allowed to send private " add_user_presence_un(
"messages of type \"groupchat\"", From,
Err = jlib:make_error_reply( {xmlelement, "presence",
Packet, ?ERRT_BAD_REQUEST(Lang, ErrText)), [{"type", "unavailable"}],
ejabberd_router:route( [{xmlelement, "status", [], [{xmlcdata, Status_text}]}]},
jlib:jid_replace_resource( StateData),
StateData#state.jid, send_new_presence(From, NewState),
ToNick), {next_state, normal_state,
From, Err); remove_online_user(From, NewState)};
_ -> forget_message ->
case find_jid_by_nick(ToNick, StateData) of {next_state, normal_state, StateData};
false -> continue_delivery ->
ErrText = "Recipient is not in the conference room", case (StateData#state.config)#config.allow_private_messages
andalso is_user_online(From, StateData) of
true ->
case Type of
"groupchat" ->
ErrText = "It is not allowed to send private "
"messages of type \"groupchat\"",
Err = jlib:make_error_reply( Err = jlib:make_error_reply(
Packet, ?ERRT_ITEM_NOT_FOUND(Lang, ErrText)), Packet, ?ERRT_BAD_REQUEST(Lang, ErrText)),
ejabberd_router:route( ejabberd_router:route(
jlib:jid_replace_resource( jlib:jid_replace_resource(
StateData#state.jid, StateData#state.jid,
ToNick), ToNick),
From, Err); From, Err);
ToJID -> _ ->
{ok, #user{nick = FromNick}} = case find_jid_by_nick(ToNick, StateData) of
?DICT:find(jlib:jid_tolower(From), false ->
StateData#state.users), ErrText = "Recipient is not in the conference room",
ejabberd_router:route( Err = jlib:make_error_reply(
jlib:jid_replace_resource( Packet, ?ERRT_ITEM_NOT_FOUND(Lang, ErrText)),
StateData#state.jid, ejabberd_router:route(
FromNick), jlib:jid_replace_resource(
ToJID, Packet) StateData#state.jid,
end ToNick),
end; From, Err);
_ -> ToJID ->
ErrText = "Only occupants are allowed to send messages to the conference", {ok, #user{nick = FromNick}} =
Err = jlib:make_error_reply( ?DICT:find(jlib:jid_tolower(From),
Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)), StateData#state.users),
ejabberd_router:route( ejabberd_router:route(
jlib:jid_replace_resource( jlib:jid_replace_resource(
StateData#state.jid, StateData#state.jid,
ToNick), FromNick),
From, Err) ToJID, Packet)
end, end
{next_state, normal_state, StateData}; end;
_ ->
ErrText = "Only occupants are allowed to send messages to the conference",
Err = jlib:make_error_reply(
Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
ejabberd_router:route(
jlib:jid_replace_resource(
StateData#state.jid,
ToNick),
From, Err)
end,
{next_state, normal_state, StateData}
end;
normal_state({route, From, ToNick, normal_state({route, From, ToNick,
{xmlelement, "iq", Attrs, _Els} = Packet}, {xmlelement, "iq", Attrs, _Els} = Packet},
@ -885,7 +906,9 @@ process_presence(From, Nick, {xmlelement, "presence", Attrs, _Els} = Packet,
add_user_presence_un( add_user_presence_un(
From, From,
{xmlelement, "presence", {xmlelement, "presence",
[{"type", "unavailable"}], []}, [{"type", "unavailable"}],
[{xmlelement, "status", [],
[{xmlcdata, "This participant sent a bad error presence."}]}]},
StateData), StateData),
send_new_presence(From, NewState), send_new_presence(From, NewState),
remove_online_user(From, NewState); remove_online_user(From, NewState);
@ -987,6 +1010,50 @@ list_to_affiliation(Affiliation) ->
"none" -> none "none" -> none
end. end.
%% Decide the fate of the message and its sender
%% Returns: continue_delivery | forget_message | {expulse_sender, Reason}
decide_fate_message("error", Packet, From, StateData) ->
case catch check_error_kick(Packet) of
%% If this is an error stanza and its condition matches a criteria
true ->
%% If the sender of the message is online
case is_user_online(From, StateData) of
true ->
Reason = io_lib:format("This participant is considered a ghost and is expulsed: ~s",
[jlib:jid_to_string(From)]),
{expulse_sender, Reason};
false ->
forget_message
end;
false ->
continue_delivery;
{'EXIT', Error} ->
Reason = io_lib:format(
"This participant sent a problematic packet and is expulsed: ~s~nPacket: ~p~nError: ~p",
[jlib:jid_to_string(From), Packet, Error]),
{expulse_sender, Reason}
end;
decide_fate_message(_, _, _, _) ->
continue_delivery.
%% Check if the elements of this error stanza indicate
%% that the sender is a dead participant.
%% If so, return true to kick the participant.
check_error_kick(Packet) ->
{xmlelement, _, _, EEls} = xml:get_subtag(Packet, "error"),
[{xmlelement, Name, _, _}] = xml:remove_cdata(EEls),
case Name of
"gone" -> true;
"internal-server-error" -> true;
"item-not-found" -> true;
"jid-malformed" -> true;
"recipient-unavailable" -> true;
"redirect" -> true;
"remote-server-not-found" -> true;
"remote-server-timeout" -> true;
"service-unavailable" -> true;
_ -> false
end.
set_affiliation(JID, Affiliation, StateData) -> set_affiliation(JID, Affiliation, StateData) ->