diff options
| author | Holger Weiss <holger@zedat.fu-berlin.de> | 2015-08-04 20:13:00 +0200 | 
|---|---|---|
| committer | Holger Weiss <holger@zedat.fu-berlin.de> | 2015-08-04 20:13:00 +0200 | 
| commit | 3d4e8ffac69f7c08b9c44d6c842898574d5c06f8 (patch) | |
| tree | 19d611db926f84f581e7d6fbc3562476131edce7 | |
| parent | Add split_jid/1 (diff) | |
New hook: muc_filter_presence
Add a hook that allows for modifying or dropping presence stanzas sent
to MUC rooms.
| -rw-r--r-- | src/mod_muc_room.erl | 228 | 
1 files changed, 118 insertions, 110 deletions
| diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index df06bce4f..495852d5a 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -1035,117 +1035,125 @@ get_participant_data(From, StateData) ->      end.  process_presence(From, Nick, -		 #xmlel{name = <<"presence">>, attrs = Attrs} = Packet, +		 #xmlel{name = <<"presence">>, attrs = Attrs0} = Packet0,  		 StateData) -> -    Type = xml:get_attr_s(<<"type">>, Attrs), -    Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), -    StateData1 = case Type of -		   <<"unavailable">> -> -		       case is_user_online(From, StateData) of -			 true -> -			     NewPacket = case -					   {(StateData#state.config)#config.allow_visitor_status, -					    is_visitor(From, StateData)} -					     of -					   {false, true} -> -					       strip_status(Packet); -					   _ -> Packet -					 end, -			     NewState = add_user_presence_un(From, NewPacket, -							     StateData), -			     case (?DICT):find(Nick, StateData#state.nicks) of -			       {ok, [_, _ | _]} -> ok; -			       _ -> send_new_presence(From, NewState) -			     end, -			     Reason = case xml:get_subtag(NewPacket, -							  <<"status">>) -					  of -					false -> <<"">>; -					Status_el -> -					    xml:get_tag_cdata(Status_el) -				      end, -			     remove_online_user(From, NewState, Reason); -			 _ -> StateData -		       end; -		   <<"error">> -> -		       case is_user_online(From, StateData) of -			 true -> -			     ErrorText = -				 <<"This participant is kicked from the " -				   "room because he sent an error presence">>, -			     expulse_participant(Packet, From, StateData, -						 translate:translate(Lang, -								     ErrorText)); -			 _ -> StateData -		       end; -		   <<"">> -> -		       case is_user_online(From, StateData) of -			 true -> -			     case is_nick_change(From, Nick, StateData) of -			       true -> -				   case {nick_collision(From, Nick, StateData), -					 mod_muc:can_use_nick(StateData#state.server_host, -							      StateData#state.host, -							      From, Nick), -					 {(StateData#state.config)#config.allow_visitor_nickchange, -					  is_visitor(From, StateData)}} -				       of -				     {_, _, {false, true}} -> -					 ErrText = -					     <<"Visitors are not allowed to change their " -					       "nicknames in this room">>, -					 Err = jlib:make_error_reply(Packet, -								     ?ERRT_NOT_ALLOWED(Lang, -										       ErrText)), -					 ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, -										Nick), -						      From, Err), -					 StateData; -				     {true, _, _} -> -					 Lang = xml:get_attr_s(<<"xml:lang">>, -							       Attrs), -					 ErrText = -					     <<"That nickname is already in use by another " -					       "occupant">>, -					 Err = jlib:make_error_reply(Packet, -								     ?ERRT_CONFLICT(Lang, -										    ErrText)), -					 ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, -										Nick), % TODO: s/Nick/""/ -						      From, Err), -					 StateData; -				     {_, false, _} -> -					 ErrText = -					     <<"That nickname is registered by another " -					       "person">>, -					 Err = jlib:make_error_reply(Packet, -								     ?ERRT_CONFLICT(Lang, -										    ErrText)), -					 ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, -										Nick), -						      From, Err), -					 StateData; -				     _ -> change_nick(From, Nick, StateData) -				   end; -			       _NotNickChange -> -				   Stanza = case -					      {(StateData#state.config)#config.allow_visitor_status, -					       is_visitor(From, StateData)} -						of -					      {false, true} -> -						  strip_status(Packet); -					      _Allowed -> Packet -					    end, -				   NewState = add_user_presence(From, Stanza, -								StateData), -				   send_new_presence(From, NewState), -				   NewState -			     end; -			 _ -> add_new_user(From, Nick, Packet, StateData) -		       end; -		   _ -> StateData -		 end, -    close_room_if_temporary_and_empty(StateData1). +    Type0 = xml:get_attr_s(<<"type">>, Attrs0), +    IsOnline = is_user_online(From, StateData), +    if Type0 == <<"">>; +       IsOnline and ((Type0 == <<"unavailable">>) or (Type0 == <<"error">>)) -> +	   case ejabberd_hooks:run_fold(muc_filter_presence, +					StateData#state.server_host, +					Packet0, +					[StateData, +					 StateData#state.jid, +					 From, Nick]) of +	     drop -> +		 {next_state, normal_state, StateData}; +	     #xmlel{attrs = Attrs} = Packet -> +		 Type = xml:get_attr_s(<<"xml:lang">>, Attrs), +		 Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), +		 StateData1 = case Type of +				<<"unavailable">> -> +				    NewPacket = case +						  {(StateData#state.config)#config.allow_visitor_status, +						   is_visitor(From, StateData)} +						    of +						  {false, true} -> +						      strip_status(Packet); +						  _ -> Packet +						end, +				    NewState = add_user_presence_un(From, NewPacket, +								    StateData), +				    case (?DICT):find(Nick, StateData#state.nicks) of +				      {ok, [_, _ | _]} -> ok; +				      _ -> send_new_presence(From, NewState) +				    end, +				    Reason = case xml:get_subtag(NewPacket, +								 <<"status">>) +						 of +					       false -> <<"">>; +					       Status_el -> +						   xml:get_tag_cdata(Status_el) +					     end, +				    remove_online_user(From, NewState, Reason); +				<<"error">> -> +				    ErrorText = +					<<"This participant is kicked from the " +					  "room because he sent an error presence">>, +				    expulse_participant(Packet, From, StateData, +							translate:translate(Lang, +									    ErrorText)); +				<<"">> -> +				    if not IsOnline -> +					   add_new_user(From, Nick, Packet, StateData); +				       true -> +					   case is_nick_change(From, Nick, StateData) of +					     true -> +						 case {nick_collision(From, Nick, StateData), +						       mod_muc:can_use_nick(StateData#state.server_host, +									    StateData#state.host, +									    From, Nick), +						       {(StateData#state.config)#config.allow_visitor_nickchange, +							is_visitor(From, StateData)}} +						     of +						   {_, _, {false, true}} -> +						       ErrText = +							   <<"Visitors are not allowed to change their " +							     "nicknames in this room">>, +						       Err = jlib:make_error_reply(Packet, +										   ?ERRT_NOT_ALLOWED(Lang, +												     ErrText)), +						       ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, +											      Nick), +								    From, Err), +						       StateData; +						   {true, _, _} -> +						       Lang = xml:get_attr_s(<<"xml:lang">>, +									     Attrs), +						       ErrText = +							   <<"That nickname is already in use by another " +							     "occupant">>, +						       Err = jlib:make_error_reply(Packet, +										   ?ERRT_CONFLICT(Lang, +												  ErrText)), +						       ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, +											      Nick), % TODO: s/Nick/""/ +								    From, Err), +						       StateData; +						   {_, false, _} -> +						       ErrText = +							   <<"That nickname is registered by another " +							     "person">>, +						       Err = jlib:make_error_reply(Packet, +										   ?ERRT_CONFLICT(Lang, +												  ErrText)), +						       ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, +											      Nick), +								   From, Err), +						       StateData; +						   _ -> change_nick(From, Nick, StateData) +						 end; +					     _NotNickChange -> +						 Stanza = case +							    {(StateData#state.config)#config.allow_visitor_status, +							     is_visitor(From, StateData)} +							      of +							    {false, true} -> +								strip_status(Packet); +							    _Allowed -> Packet +							  end, +						 NewState = add_user_presence(From, Stanza, +									      StateData), +						 send_new_presence(From, NewState), +						 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) ->      case not (StateData1#state.config)#config.persistent | 
