⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_muc_room.erl

📁 ejabberd-0.7.5 分布式Jabber服务器
💻 ERL
📖 第 1 页 / 共 5 页
字号:
%%%----------------------------------------------------------------------%%% File    : mod_muc_room.erl%%% Author  : Alexey Shchepin <alexey@sevcom.net>%%% Purpose : MUC room stuff%%% Created : 19 Mar 2003 by Alexey Shchepin <alexey@sevcom.net>%%% Id      : $Id: mod_muc_room.erl,v 1.31 2004/10/08 20:40:28 aleksey Exp $%%%-----------------------------------------------------------------------module(mod_muc_room).-author('alexey@sevcom.net').-vsn('$Revision: 1.31 $ ').-behaviour(gen_fsm).%% External exports-export([start/5,	 start/4,	 route/4]).%% gen_fsm callbacks-export([init/1,	 normal_state/2,	 handle_event/3,	 handle_sync_event/4,	 handle_info/3,	 terminate/3,	 code_change/4]).-include("ejabberd.hrl").-include("jlib.hrl").-define(SETS, gb_sets).-define(DICT, dict).-record(lqueue, {queue, len, max}).-record(config, {title = "",		 allow_change_subj = true,		 allow_query_users = true,		 allow_private_messages = true,		 public = true,		 public_list = true,		 persistent = false,		 moderated = false, % TODO		 members_by_default = true,		 members_only = false,		 allow_user_invites = false,		 password_protected = false,		 password = "",		 anonymous = true,		 logging = false % TODO		}).-record(user, {jid,	       nick,	       role,	       last_presence}).-record(state, {room,		host,		access,		jid,		config = #config{},		users = ?DICT:new(),		affiliations = ?DICT:new(),		history = lqueue_new(20),		subject = "",		subject_author = "",		just_created = false}).%-define(DBGFSM, true).-ifdef(DBGFSM).-define(FSMOPTS, [{debug, [trace]}]).-else.-define(FSMOPTS, []).-endif.%%%----------------------------------------------------------------------%%% API%%%----------------------------------------------------------------------start(Host, Access, Room, Creator, Nick) ->    gen_fsm:start(?MODULE, [Host, Access, Room, Creator, Nick], ?FSMOPTS).start(Host, Access, Room, Opts) ->    gen_fsm:start(?MODULE, [Host, Access, Room, Opts], ?FSMOPTS).%%%----------------------------------------------------------------------%%% Callback functions from gen_fsm%%%----------------------------------------------------------------------%%----------------------------------------------------------------------%% Func: init/1%% Returns: {ok, StateName, StateData}          |%%          {ok, StateName, StateData, Timeout} |%%          ignore                              |%%          {stop, StopReason}                   %%----------------------------------------------------------------------init([Host, Access, Room, Creator, Nick]) ->    State = set_affiliation(Creator, owner,			    #state{host = Host,				   access = Access,				   room = Room,				   jid = jlib:make_jid(Room, Host, ""),				   just_created = true}),    {ok, normal_state, State};init([Host, Access, Room, Opts]) ->    State = set_opts(Opts, #state{host = Host,				  access = Access,				  room = Room,				  jid = jlib:make_jid(Room, Host, "")}),    {ok, normal_state, State}.%%----------------------------------------------------------------------%% Func: StateName/2%% Returns: {next_state, NextStateName, NextStateData}          |%%          {next_state, NextStateName, NextStateData, Timeout} |%%          {stop, Reason, NewStateData}                         %%----------------------------------------------------------------------normal_state({route, From, "",	      {xmlelement, "message", Attrs, Els} = Packet},	     StateData) ->    Lang = xml:get_attr_s("xml:lang", Attrs),    case is_user_online(From, StateData) of	true ->	    case xml:get_attr_s("type", Attrs) of		"groupchat" ->		    {ok, #user{nick = FromNick, role = Role}} =			?DICT:find(jlib:jid_tolower(From),				   StateData#state.users),		    if			(Role == moderator) or (Role == participant) ->			    {NewStateData1, IsAllowed} =				case check_subject(Packet) of				    false ->					{StateData, true};				    Subject ->					case can_change_subject(Role,								StateData) of					    true ->						NSD =						    StateData#state{						      subject = Subject,						      subject_author =						      FromNick},						case (NSD#state.config)#config.persistent of						    true ->							mod_muc:store_room(							  NSD#state.room,							  make_opts(NSD));						    _ ->							ok						end,						{NSD, true};					    _ ->						{StateData, false}					end				end,			    case IsAllowed of				true ->				    lists:foreach(				      fun({_LJID, Info}) ->					      ejabberd_router:route(						jlib:jid_replace_resource(						  StateData#state.jid,						  FromNick),						Info#user.jid,						Packet)				      end,				      ?DICT:to_list(StateData#state.users)),				    NewStateData2 =					add_message_to_history(FromNick,							       Packet,							       NewStateData1),				    {next_state, normal_state, NewStateData2};				_ ->				    ErrText = 					case (StateData#state.config)#config.allow_change_subj of					    true ->						"Only moderators and participants "						"are allowed to change subject in this room";					    _ ->						"Only moderators "						"are allowed to change subject in this room"					end,				    Err = jlib:make_error_reply(					    Packet, ?ERRT_FORBIDDEN(Lang, ErrText)),				    ejabberd_router:route(				      StateData#state.jid,				      From, Err),			    {next_state, normal_state, StateData}			    end;			true ->			    ErrText = "Visitors are not allowed to send messages to all occupants",			    Err = jlib:make_error_reply(				    Packet, ?ERRT_FORBIDDEN(Lang, ErrText)),			    ejabberd_router:route(			      StateData#state.jid,			      From, Err),			    {next_state, normal_state, StateData}		    end;		"error" ->		    case is_user_online(From, StateData) of			true ->			    NewState =				add_user_presence_un(				  From,				  {xmlelement, "presence",				   [{"type", "unavailable"}], []},			      StateData),			    send_new_presence(From, NewState),			    {next_state, normal_state,			     remove_online_user(From, NewState)};			_ ->			    {next_state, normal_state, StateData}		    end;		"chat" ->		    ErrText = "It is not allowed to send private messages to the conference",		    Err = jlib:make_error_reply(			    Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),		    ejabberd_router:route(		      StateData#state.jid,		      From, Err),		    {next_state, normal_state, StateData};		Type when (Type == "") or (Type == "normal") ->		    case check_invitation(From, Els, StateData) of			error ->			    ErrText = "It is not allowed to send normal messages to the conference",			    Err = jlib:make_error_reply(				    Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),			    ejabberd_router:route(			      StateData#state.jid,			      From, Err),			    {next_state, normal_state, StateData};			IJID ->			    Config = StateData#state.config,			    case Config#config.members_only of				true ->				    case get_affiliation(IJID, StateData) of					none ->					    NSD = set_affiliation(						    IJID,						    member,						    StateData),					    {next_state, normal_state, NSD};					_ ->					    {next_state, normal_state,					     StateData}				    end;				false ->				    {next_state, normal_state, StateData}			    end		    end;		_ ->		    ErrText = "Improper message type",		    Err = jlib:make_error_reply(			    Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),		    ejabberd_router:route(		      StateData#state.jid,		      From, Err),		    {next_state, normal_state, StateData}	    end;	_ ->	    case xml:get_attr_s("type", Attrs) of		"error" ->		    ok;		_ ->		    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(StateData#state.jid, From, Err)	    end,	    {next_state, normal_state, StateData}    end;normal_state({route, From, "",	      {xmlelement, "iq", _Attrs, _Els} = Packet},	     StateData) ->    case jlib:iq_query_info(Packet) of	#iq{type = Type, xmlns = XMLNS, lang = Lang, sub_el = SubEl} = IQ when	      (XMLNS == ?NS_MUC_ADMIN) or	      (XMLNS == ?NS_MUC_OWNER) or	      (XMLNS == ?NS_DISCO_INFO) or	      (XMLNS == ?NS_DISCO_ITEMS) ->	    Res1 = case XMLNS of		       ?NS_MUC_ADMIN ->			   process_iq_admin(From, Type, Lang, SubEl, StateData);		       ?NS_MUC_OWNER ->			   process_iq_owner(From, Type, Lang, SubEl, StateData);		       ?NS_DISCO_INFO ->			   process_iq_disco_info(From, Type, Lang, StateData);		       ?NS_DISCO_ITEMS ->			   process_iq_disco_items(From, Type, Lang, StateData)		   end,	    {IQRes, NewStateData} =		case Res1 of		    {result, Res, SD} ->			{IQ#iq{type = result,			       sub_el = [{xmlelement, "query",					  [{"xmlns", XMLNS}],					  Res					 }]},			 SD};		    {error, Error} ->			{IQ#iq{type = error,			       sub_el = [SubEl, Error]},			 StateData}		end,	    ejabberd_router:route(StateData#state.jid,				  From,				  jlib:iq_to_xml(IQRes)),	    case NewStateData of		stop ->		    {stop, normal, StateData};		_ ->		    {next_state, normal_state, NewStateData}	    end;	reply ->	    {next_state, normal_state, StateData};	_ ->	    Err = jlib:make_error_reply(		    Packet, ?ERR_FEATURE_NOT_IMPLEMENTED),	    ejabberd_router:route(StateData#state.jid, From, Err),	    {next_state, normal_state, StateData}    end;normal_state({route, From, Nick,	      {xmlelement, "presence", Attrs, _Els} = Packet},	     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 ->			NewState =			    add_user_presence_un(From, Packet, StateData),			send_new_presence(From, NewState),			remove_online_user(From, NewState);		    _ ->			StateData		end;	    "error" ->		case is_user_online(From, StateData) of		    true ->			NewState =			    add_user_presence_un(			      From,			      {xmlelement, "presence",			       [{"type", "unavailable"}], []},			      StateData),			send_new_presence(From, NewState),			remove_online_user(From, NewState);		    _ ->			StateData		end;	    "" ->		case is_user_online(From, StateData) of		    true ->			case is_nick_change(From, Nick, StateData) of			    true ->				case {is_nick_exists(Nick, StateData),				      mod_muc:can_use_nick(From, Nick)} of				    {true, _} ->					Lang = xml:get_attr_s("xml:lang", Attrs),					ErrText = "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 = "Nickname is registered by another person",					Err = jlib:make_error_reply(						Packet,						?ERRT_CONFLICT(Lang, ErrText)),					ejabberd_router:route(					  % TODO: s/Nick/""/					  jlib:jid_replace_resource(					    StateData#state.jid,					    Nick),					  From, Err),					StateData;				    _ ->					change_nick(From, Nick, StateData)				end;			    _ ->				NewState =				    add_user_presence(From, Packet, StateData),				send_new_presence(From, NewState),				NewState			end;		    _ ->			add_new_user(From, Nick, Packet, StateData)		end;	    _ ->		StateData	end,    %io:format("STATE1: ~p~n", [?DICT:to_list(StateData#state.users)]),    %io:format("STATE2: ~p~n", [?DICT:to_list(StateData1#state.users)]),    case (not (StateData1#state.config)#config.persistent) andalso	(?DICT:to_list(StateData1#state.users) == []) of	true ->	    {stop, normal, StateData1};	_ ->	    {next_state, normal_state, StateData1}    end;normal_state({route, From, ToNick,	      {xmlelement, "message", Attrs, _Els} = Packet},	     StateData) ->    Type = xml:get_attr_s("type", Attrs),    Lang = xml:get_attr_s("xml:lang", Attrs),    case Type of	"error" ->	    case is_user_online(From, StateData) of		true ->		    NewState =			add_user_presence_un(			  From,			  {xmlelement, "presence",			   [{"type", "unavailable"}], []},			  StateData),		    send_new_presence(From, NewState),		    {next_state, normal_state,		     remove_online_user(From, NewState)};		_ ->		    {next_state, normal_state, StateData}	    end;	_ ->	    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(				    Packet, ?ERRT_BAD_REQUEST(Lang, ErrText)),			    ejabberd_router:route(				jlib:jid_replace_resource(				    StateData#state.jid,				    ToNick),				From, Err);			_ ->			    case find_jid_by_nick(ToNick, StateData) of				false ->				    ErrText = "Recipient is not in the conference room",				    Err = jlib:make_error_reply(					    Packet, ?ERRT_ITEM_NOT_FOUND(Lang, ErrText)),

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -