2003-03-23 21:08:44 +01:00
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
%%% File : mod_muc.erl
|
|
|
|
%%% Author : Alexey Shchepin <alexey@sevcom.net>
|
|
|
|
%%% Purpose : MUC support (JEP-0045)
|
|
|
|
%%% Created : 19 Mar 2003 by Alexey Shchepin <alexey@sevcom.net>
|
|
|
|
%%% Id : $Id$
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
|
|
|
|
-module(mod_muc).
|
|
|
|
-author('alexey@sevcom.net').
|
|
|
|
-vsn('$Revision$ ').
|
|
|
|
|
|
|
|
-behaviour(gen_mod).
|
|
|
|
|
|
|
|
-export([start/1,
|
2004-05-17 22:36:41 +02:00
|
|
|
init/2,
|
2003-03-23 21:08:44 +01:00
|
|
|
stop/0,
|
2003-03-25 22:03:35 +01:00
|
|
|
room_destroyed/1,
|
|
|
|
store_room/2,
|
|
|
|
restore_room/1,
|
2003-03-26 21:51:18 +01:00
|
|
|
forget_room/1,
|
2003-12-17 21:13:21 +01:00
|
|
|
process_iq_disco_items/4,
|
2003-04-17 21:47:43 +02:00
|
|
|
can_use_nick/2]).
|
2003-03-23 21:08:44 +01:00
|
|
|
|
|
|
|
-include("ejabberd.hrl").
|
|
|
|
-include("jlib.hrl").
|
|
|
|
|
|
|
|
|
|
|
|
-record(muc_room, {name, opts}).
|
|
|
|
-record(muc_online_room, {name, pid}).
|
2003-04-17 21:47:43 +02:00
|
|
|
-record(muc_registered, {user, nick}).
|
|
|
|
|
2003-03-23 21:08:44 +01:00
|
|
|
|
|
|
|
start(Opts) ->
|
|
|
|
mnesia:create_table(muc_room,
|
|
|
|
[{disc_copies, [node()]},
|
|
|
|
{attributes, record_info(fields, muc_room)}]),
|
2003-04-17 21:47:43 +02:00
|
|
|
mnesia:create_table(muc_registered,
|
|
|
|
[{disc_copies, [node()]},
|
|
|
|
{attributes, record_info(fields, muc_registered)}]),
|
|
|
|
mnesia:add_table_index(muc_registered, nick),
|
2003-03-23 21:08:44 +01:00
|
|
|
Host = gen_mod:get_opt(host, Opts, "conference." ++ ?MYNAME),
|
2004-05-17 22:36:41 +02:00
|
|
|
Access = gen_mod:get_opt(access, Opts, all),
|
|
|
|
AccessCreate = gen_mod:get_opt(access_create, Opts, all),
|
|
|
|
AccessAdmin = gen_mod:get_opt(access_admin, Opts, none),
|
|
|
|
register(ejabberd_mod_muc,
|
|
|
|
spawn(?MODULE, init, [Host, {Access, AccessCreate, AccessAdmin}])).
|
2003-03-23 21:08:44 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2004-05-17 22:36:41 +02:00
|
|
|
init(Host, Access) ->
|
2003-03-23 21:08:44 +01:00
|
|
|
catch ets:new(muc_online_room, [named_table,
|
|
|
|
public,
|
|
|
|
{keypos, #muc_online_room.name}]),
|
|
|
|
ejabberd_router:register_route(Host),
|
2004-05-17 22:36:41 +02:00
|
|
|
load_permanent_rooms(Host, Access),
|
|
|
|
loop(Host, Access).
|
2003-03-23 21:08:44 +01:00
|
|
|
|
2004-05-17 22:36:41 +02:00
|
|
|
loop(Host, Access) ->
|
2003-03-23 21:08:44 +01:00
|
|
|
receive
|
|
|
|
{route, From, To, Packet} ->
|
2004-05-17 22:36:41 +02:00
|
|
|
case catch do_route(Host, Access, From, To, Packet) of
|
2003-03-23 21:08:44 +01:00
|
|
|
{'EXIT', Reason} ->
|
|
|
|
?ERROR_MSG("~p", [Reason]);
|
|
|
|
_ ->
|
|
|
|
ok
|
|
|
|
end,
|
2004-05-17 22:36:41 +02:00
|
|
|
loop(Host, Access);
|
2003-03-23 21:08:44 +01:00
|
|
|
{room_destroyed, Room} ->
|
2003-06-30 14:24:35 +02:00
|
|
|
ets:delete(muc_online_room, Room),
|
2004-05-17 22:36:41 +02:00
|
|
|
loop(Host, Access);
|
2003-03-23 21:08:44 +01:00
|
|
|
stop ->
|
|
|
|
% TODO
|
|
|
|
ejabberd_router:unregister_global_route(Host),
|
|
|
|
ok;
|
|
|
|
_ ->
|
2004-05-17 22:36:41 +02:00
|
|
|
loop(Host, Access)
|
2003-03-23 21:08:44 +01:00
|
|
|
end.
|
|
|
|
|
|
|
|
|
2004-05-17 22:36:41 +02:00
|
|
|
do_route(Host, Access, From, To, Packet) ->
|
|
|
|
{AccessRoute, _AccessCreate, _AccessAdmin} = Access,
|
|
|
|
case acl:match_rule(AccessRoute, From) of
|
|
|
|
allow ->
|
|
|
|
do_route1(Host, Access, From, To, Packet);
|
|
|
|
_ ->
|
|
|
|
{xmlelement, _Name, Attrs, _Els} = Packet,
|
|
|
|
Lang = xml:get_attr_s("xml:lang", Attrs),
|
|
|
|
ErrText = "Access denied by service policy",
|
|
|
|
Err = jlib:make_error_reply(Packet,
|
|
|
|
?ERRT_FORBIDDEN(Lang, ErrText)),
|
|
|
|
ejabberd_router:route(To, From, Err)
|
|
|
|
end.
|
|
|
|
|
|
|
|
|
|
|
|
do_route1(Host, Access, From, To, Packet) ->
|
|
|
|
{_AccessRoute, AccessCreate, AccessAdmin} = Access,
|
2003-08-15 21:17:12 +02:00
|
|
|
{Room, _, Nick} = jlib:jid_tolower(To),
|
2004-05-17 22:36:41 +02:00
|
|
|
{xmlelement, Name, Attrs, _Els} = Packet,
|
2003-03-23 21:08:44 +01:00
|
|
|
case Room of
|
|
|
|
"" ->
|
|
|
|
case Nick of
|
|
|
|
"" ->
|
2003-05-18 18:41:15 +02:00
|
|
|
case Name of
|
|
|
|
"iq" ->
|
|
|
|
case jlib:iq_query_info(Packet) of
|
2003-12-17 21:13:21 +01:00
|
|
|
#iq{type = get, xmlns = ?NS_DISCO_INFO = XMLNS,
|
|
|
|
sub_el = SubEl} = IQ ->
|
|
|
|
Res = IQ#iq{type = result,
|
|
|
|
sub_el = [{xmlelement, "query",
|
|
|
|
[{"xmlns", XMLNS}],
|
|
|
|
iq_disco_info()}]},
|
2003-05-18 18:41:15 +02:00
|
|
|
ejabberd_router:route(To,
|
|
|
|
From,
|
|
|
|
jlib:iq_to_xml(Res));
|
2003-12-17 21:13:21 +01:00
|
|
|
#iq{type = get,
|
|
|
|
xmlns = ?NS_DISCO_ITEMS} = IQ ->
|
2003-05-18 18:41:15 +02:00
|
|
|
spawn(?MODULE,
|
|
|
|
process_iq_disco_items,
|
2003-12-17 21:13:21 +01:00
|
|
|
[Host, From, To, IQ]);
|
|
|
|
#iq{type = get,
|
|
|
|
xmlns = ?NS_REGISTER = XMLNS,
|
2004-02-26 23:00:04 +01:00
|
|
|
lang = Lang,
|
2003-12-17 21:13:21 +01:00
|
|
|
sub_el = SubEl} = IQ ->
|
|
|
|
Res = IQ#iq{type = result,
|
|
|
|
sub_el =
|
|
|
|
[{xmlelement, "query",
|
|
|
|
[{"xmlns", XMLNS}],
|
|
|
|
iq_get_register_info(
|
2004-02-26 23:00:04 +01:00
|
|
|
From, Host, Lang)}]},
|
2003-05-18 18:41:15 +02:00
|
|
|
ejabberd_router:route(To,
|
|
|
|
From,
|
|
|
|
jlib:iq_to_xml(Res));
|
2003-12-17 21:13:21 +01:00
|
|
|
#iq{type = set,
|
|
|
|
xmlns = ?NS_REGISTER = XMLNS,
|
2004-03-02 22:16:55 +01:00
|
|
|
lang = Lang,
|
2003-12-17 21:13:21 +01:00
|
|
|
sub_el = SubEl} = IQ ->
|
2004-03-02 22:16:55 +01:00
|
|
|
case process_iq_register_set(From, SubEl, Lang) of
|
2003-05-18 18:41:15 +02:00
|
|
|
{result, IQRes} ->
|
2003-12-17 21:13:21 +01:00
|
|
|
Res = IQ#iq{type = result,
|
|
|
|
sub_el =
|
|
|
|
[{xmlelement, "query",
|
|
|
|
[{"xmlns", XMLNS}],
|
|
|
|
IQRes}]},
|
2003-05-18 18:41:15 +02:00
|
|
|
ejabberd_router:route(
|
|
|
|
To, From, jlib:iq_to_xml(Res));
|
|
|
|
{error, Error} ->
|
|
|
|
Err = jlib:make_error_reply(
|
|
|
|
Packet, Error),
|
|
|
|
ejabberd_router:route(
|
|
|
|
To, From, Err)
|
|
|
|
end;
|
2003-12-17 21:13:21 +01:00
|
|
|
#iq{type = get,
|
|
|
|
xmlns = ?NS_VCARD = XMLNS,
|
2004-02-26 23:00:04 +01:00
|
|
|
lang = Lang,
|
2003-12-17 21:13:21 +01:00
|
|
|
sub_el = SubEl} = IQ ->
|
|
|
|
Res = IQ#iq{type = result,
|
|
|
|
sub_el =
|
2004-03-02 22:16:55 +01:00
|
|
|
[{xmlelement, "vCard",
|
2003-12-17 21:13:21 +01:00
|
|
|
[{"xmlns", XMLNS}],
|
|
|
|
iq_get_vcard(Lang)}]},
|
2003-05-18 18:41:15 +02:00
|
|
|
ejabberd_router:route(To,
|
|
|
|
From,
|
|
|
|
jlib:iq_to_xml(Res));
|
2003-12-17 21:13:21 +01:00
|
|
|
#iq{} ->
|
2003-04-17 21:47:43 +02:00
|
|
|
Err = jlib:make_error_reply(
|
2003-05-18 18:41:15 +02:00
|
|
|
Packet,
|
|
|
|
?ERR_FEATURE_NOT_IMPLEMENTED),
|
2003-12-17 21:13:21 +01:00
|
|
|
ejabberd_router:route(To, From, Err);
|
|
|
|
_ ->
|
|
|
|
ok
|
2003-04-17 21:47:43 +02:00
|
|
|
end;
|
2003-05-18 18:41:15 +02:00
|
|
|
"message" ->
|
|
|
|
case xml:get_attr_s("type", Attrs) of
|
|
|
|
"error" ->
|
|
|
|
ok;
|
|
|
|
_ ->
|
2004-05-17 22:36:41 +02:00
|
|
|
case acl:match_rule(AccessAdmin, From) of
|
2003-05-18 18:41:15 +02:00
|
|
|
allow ->
|
|
|
|
Msg = xml:get_path_s(
|
|
|
|
Packet,
|
|
|
|
[{elem, "body"}, cdata]),
|
|
|
|
broadcast_service_message(Msg);
|
|
|
|
_ ->
|
2004-03-02 22:16:55 +01:00
|
|
|
Lang = xml:get_attr_s("xml:lang", Attrs),
|
|
|
|
ErrText = "Only service administrators "
|
|
|
|
"are allowed to send service messages",
|
2003-05-18 18:41:15 +02:00
|
|
|
Err = jlib:make_error_reply(
|
|
|
|
Packet,
|
2004-03-02 22:16:55 +01:00
|
|
|
?ERRT_FORBIDDEN(Lang, ErrText)),
|
2003-05-18 18:41:15 +02:00
|
|
|
ejabberd_router:route(
|
|
|
|
To, From, Err)
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
"presence" ->
|
|
|
|
ok
|
|
|
|
end;
|
|
|
|
_ ->
|
|
|
|
case xml:get_attr_s("type", Attrs) of
|
|
|
|
"error" ->
|
|
|
|
ok;
|
|
|
|
"result" ->
|
|
|
|
ok;
|
2003-03-23 21:08:44 +01:00
|
|
|
_ ->
|
|
|
|
Err = jlib:make_error_reply(
|
2003-06-30 14:24:35 +02:00
|
|
|
Packet, ?ERR_ITEM_NOT_FOUND),
|
2003-03-23 21:08:44 +01:00
|
|
|
ejabberd_router:route(To, From, Err)
|
2003-05-18 18:41:15 +02:00
|
|
|
end
|
2003-03-23 21:08:44 +01:00
|
|
|
end;
|
|
|
|
_ ->
|
|
|
|
case ets:lookup(muc_online_room, Room) of
|
|
|
|
[] ->
|
|
|
|
Type = xml:get_attr_s("type", Attrs),
|
|
|
|
case {Name, Type} of
|
|
|
|
{"presence", ""} ->
|
2004-05-17 22:36:41 +02:00
|
|
|
case acl:match_rule(AccessCreate, From) of
|
|
|
|
allow ->
|
|
|
|
?DEBUG("MUC: open new room '~s'~n", [Room]),
|
|
|
|
{ok, Pid} = mod_muc_room:start(
|
|
|
|
Host, Access, Room, From, Nick),
|
|
|
|
ets:insert(
|
|
|
|
muc_online_room,
|
|
|
|
#muc_online_room{name = Room, pid = Pid}),
|
|
|
|
mod_muc_room:route(Pid, From, Nick, Packet),
|
|
|
|
ok;
|
|
|
|
_ ->
|
|
|
|
Lang = xml:get_attr_s("xml:lang", Attrs),
|
|
|
|
ErrText = "Room creation is denied by service policy",
|
|
|
|
Err = jlib:make_error_reply(
|
|
|
|
Packet, ?ERRT_FORBIDDEN(Lang, ErrText)),
|
|
|
|
ejabberd_router:route(To, From, Err)
|
|
|
|
end;
|
2003-03-23 21:08:44 +01:00
|
|
|
_ ->
|
2004-03-02 22:16:55 +01:00
|
|
|
Lang = xml:get_attr_s("xml:lang", Attrs),
|
|
|
|
ErrText = "Conference room does not exist",
|
2003-03-23 21:08:44 +01:00
|
|
|
Err = jlib:make_error_reply(
|
2004-03-02 22:16:55 +01:00
|
|
|
Packet, ?ERRT_ITEM_NOT_FOUND(Lang, ErrText)),
|
2003-03-23 21:08:44 +01:00
|
|
|
ejabberd_router:route(To, From, Err)
|
|
|
|
end;
|
|
|
|
[R] ->
|
|
|
|
Pid = R#muc_online_room.pid,
|
2003-09-26 20:55:01 +02:00
|
|
|
?DEBUG("MUC: send to process ~p~n", [Pid]),
|
2003-03-23 21:08:44 +01:00
|
|
|
mod_muc_room:route(Pid, From, Nick, Packet),
|
|
|
|
ok
|
|
|
|
end
|
|
|
|
end.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
room_destroyed(Room) ->
|
|
|
|
ejabberd_mod_muc ! {room_destroyed, Room},
|
|
|
|
ok.
|
|
|
|
|
|
|
|
stop() ->
|
|
|
|
ejabberd_mod_muc ! stop,
|
|
|
|
ok.
|
|
|
|
|
|
|
|
|
2003-03-25 22:03:35 +01:00
|
|
|
store_room(Name, Opts) ->
|
|
|
|
F = fun() ->
|
|
|
|
mnesia:write(#muc_room{name = Name,
|
|
|
|
opts = Opts})
|
|
|
|
end,
|
|
|
|
mnesia:transaction(F).
|
|
|
|
|
|
|
|
restore_room(Name) ->
|
|
|
|
case catch mnesia:dirty_read(muc_room, Name) of
|
|
|
|
[#muc_room{opts = Opts}] ->
|
|
|
|
Opts;
|
|
|
|
_ ->
|
|
|
|
error
|
|
|
|
end.
|
2003-03-23 21:08:44 +01:00
|
|
|
|
|
|
|
|
2003-03-25 22:03:35 +01:00
|
|
|
forget_room(Name) ->
|
|
|
|
F = fun() ->
|
|
|
|
mnesia:delete({muc_room, Name})
|
|
|
|
end,
|
|
|
|
mnesia:transaction(F).
|
2003-03-23 21:08:44 +01:00
|
|
|
|
|
|
|
|
2004-05-17 22:36:41 +02:00
|
|
|
load_permanent_rooms(Host, Access) ->
|
2003-03-25 22:03:35 +01:00
|
|
|
case catch mnesia:dirty_select(muc_room, [{'_', [], ['$_']}]) of
|
|
|
|
{'EXIT', Reason} ->
|
|
|
|
?ERROR_MSG("~p", [Reason]),
|
|
|
|
ok;
|
|
|
|
Rs ->
|
|
|
|
lists:foreach(fun(R) ->
|
|
|
|
Room = R#muc_room.name,
|
|
|
|
{ok, Pid} = mod_muc_room:start(
|
|
|
|
Host,
|
2004-05-17 22:36:41 +02:00
|
|
|
Access,
|
2003-03-25 22:03:35 +01:00
|
|
|
Room,
|
|
|
|
R#muc_room.opts),
|
|
|
|
ets:insert(
|
|
|
|
muc_online_room,
|
|
|
|
#muc_online_room{name = Room, pid = Pid})
|
|
|
|
end, Rs)
|
|
|
|
end.
|
|
|
|
|
2003-03-26 21:51:18 +01:00
|
|
|
|
|
|
|
iq_disco_info() ->
|
|
|
|
[{xmlelement, "identity",
|
|
|
|
[{"category", "conference"},
|
|
|
|
{"type", "text"},
|
|
|
|
{"name", "ejabberd/mod_muc"}], []},
|
2003-04-17 21:47:43 +02:00
|
|
|
{xmlelement, "feature", [{"var", ?NS_MUC}], []},
|
2003-05-09 21:32:59 +02:00
|
|
|
{xmlelement, "feature", [{"var", ?NS_REGISTER}], []},
|
|
|
|
{xmlelement, "feature", [{"var", ?NS_VCARD}], []}].
|
2003-03-26 21:51:18 +01:00
|
|
|
|
|
|
|
|
2004-03-08 21:20:15 +01:00
|
|
|
process_iq_disco_items(Host, From, To, #iq{lang = Lang} = IQ) ->
|
2003-12-17 21:13:21 +01:00
|
|
|
Res = IQ#iq{type = result,
|
|
|
|
sub_el = [{xmlelement, "query",
|
|
|
|
[{"xmlns", ?NS_DISCO_ITEMS}],
|
2004-03-08 21:20:15 +01:00
|
|
|
iq_disco_items(Host, From, Lang)}]},
|
2003-03-26 21:51:18 +01:00
|
|
|
ejabberd_router:route(To,
|
|
|
|
From,
|
|
|
|
jlib:iq_to_xml(Res)).
|
|
|
|
|
2004-03-08 21:20:15 +01:00
|
|
|
iq_disco_items(Host, From, Lang) ->
|
2003-03-26 21:51:18 +01:00
|
|
|
lists:zf(fun(#muc_online_room{name = Name, pid = Pid}) ->
|
|
|
|
case catch gen_fsm:sync_send_all_state_event(
|
2004-03-08 21:20:15 +01:00
|
|
|
Pid, {get_disco_item, From, Lang}, 100) of
|
2003-03-26 21:51:18 +01:00
|
|
|
{item, Desc} ->
|
|
|
|
{true,
|
|
|
|
{xmlelement, "item",
|
|
|
|
[{"jid", jlib:jid_to_string({Name, Host, ""})},
|
2003-03-27 15:06:17 +01:00
|
|
|
{"name", Desc}], []}};
|
|
|
|
_ ->
|
|
|
|
false
|
2003-03-26 21:51:18 +01:00
|
|
|
end
|
|
|
|
end, ets:tab2list(muc_online_room)).
|
|
|
|
|
|
|
|
|
2003-04-17 21:47:43 +02:00
|
|
|
-define(XFIELD(Type, Label, Var, Val),
|
|
|
|
{xmlelement, "field", [{"type", Type},
|
|
|
|
{"label", translate:translate(Lang, Label)},
|
|
|
|
{"var", Var}],
|
|
|
|
[{xmlelement, "value", [], [{xmlcdata, Val}]}]}).
|
|
|
|
|
2004-02-26 23:00:04 +01:00
|
|
|
iq_get_register_info(From, Host, Lang) ->
|
2003-04-17 21:47:43 +02:00
|
|
|
{LUser, LServer, _} = jlib:jid_tolower(From),
|
|
|
|
LUS = {LUser, LServer},
|
2003-12-06 20:58:49 +01:00
|
|
|
{Nick, Registered} = case catch mnesia:dirty_read(muc_registered, LUS) of
|
2004-05-17 22:36:41 +02:00
|
|
|
{'EXIT', _Reason} ->
|
2003-12-06 20:58:49 +01:00
|
|
|
{"", []};
|
2003-04-17 21:47:43 +02:00
|
|
|
[] ->
|
2003-12-06 20:58:49 +01:00
|
|
|
{"", []};
|
2003-04-17 21:47:43 +02:00
|
|
|
[#muc_registered{nick = N}] ->
|
2003-12-06 20:58:49 +01:00
|
|
|
{N, [{xmlelement, "registered", [], []}]}
|
2003-04-17 21:47:43 +02:00
|
|
|
end,
|
2003-12-06 20:58:49 +01:00
|
|
|
Registered ++
|
|
|
|
[{xmlelement, "instructions", [],
|
|
|
|
[{xmlcdata,
|
|
|
|
translate:translate(
|
2004-02-26 23:00:04 +01:00
|
|
|
Lang, "You need an x:data capable client to register nickname")}]},
|
2003-12-06 20:58:49 +01:00
|
|
|
{xmlelement, "x",
|
|
|
|
[{"xmlns", ?NS_XDATA}],
|
|
|
|
[{xmlelement, "title", [],
|
|
|
|
[{xmlcdata,
|
|
|
|
translate:translate(
|
2004-02-26 23:00:04 +01:00
|
|
|
Lang, "Nickname Registration at ") ++ Host}]},
|
2003-12-06 20:58:49 +01:00
|
|
|
{xmlelement, "instructions", [],
|
|
|
|
[{xmlcdata,
|
|
|
|
translate:translate(
|
2004-02-26 23:00:04 +01:00
|
|
|
Lang, "Enter nickname you want to register")}]},
|
2003-12-06 20:58:49 +01:00
|
|
|
?XFIELD("text-single", "Nickname", "nick", Nick)]}].
|
2003-04-17 21:47:43 +02:00
|
|
|
|
2004-03-02 22:16:55 +01:00
|
|
|
iq_set_register_info(From, XData, Lang) ->
|
2003-04-17 21:47:43 +02:00
|
|
|
{LUser, LServer, _} = jlib:jid_tolower(From),
|
|
|
|
LUS = {LUser, LServer},
|
|
|
|
case lists:keysearch("nick", 1, XData) of
|
|
|
|
false ->
|
2004-03-02 22:16:55 +01:00
|
|
|
ErrText = "You must fill in field \"nick\" in the form",
|
|
|
|
{error, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)};
|
2003-04-17 21:47:43 +02:00
|
|
|
{value, {_, [Nick]}} ->
|
|
|
|
F = fun() ->
|
|
|
|
case Nick of
|
|
|
|
"" ->
|
|
|
|
mnesia:delete({muc_registered, LUS}),
|
|
|
|
ok;
|
|
|
|
_ ->
|
|
|
|
Allow = case mnesia:index_read(
|
|
|
|
muc_registered,
|
|
|
|
Nick,
|
|
|
|
#muc_registered.nick) of
|
|
|
|
[] ->
|
|
|
|
true;
|
|
|
|
[#muc_registered{user = U}] ->
|
|
|
|
U == LUS
|
|
|
|
end,
|
|
|
|
if
|
|
|
|
Allow ->
|
|
|
|
mnesia:write(
|
|
|
|
#muc_registered{user = LUS,
|
|
|
|
nick = Nick}),
|
|
|
|
ok;
|
|
|
|
true ->
|
|
|
|
false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end,
|
|
|
|
case mnesia:transaction(F) of
|
|
|
|
{atomic, ok} ->
|
|
|
|
{result, []};
|
|
|
|
{atomic, false} ->
|
2004-03-02 22:16:55 +01:00
|
|
|
ErrText = "Specified nickname is already registered",
|
|
|
|
{error, ?ERRT_CONFLICT(Lang, ErrText)};
|
2003-04-17 21:47:43 +02:00
|
|
|
_ ->
|
|
|
|
{error, ?ERR_INTERNAL_SERVER_ERROR}
|
|
|
|
end
|
|
|
|
end.
|
|
|
|
|
2004-03-02 22:16:55 +01:00
|
|
|
process_iq_register_set(From, SubEl, Lang) ->
|
2004-05-17 22:36:41 +02:00
|
|
|
{xmlelement, _Name, _Attrs, Els} = SubEl,
|
2003-04-17 21:47:43 +02:00
|
|
|
case xml:remove_cdata(Els) of
|
2004-05-17 22:36:41 +02:00
|
|
|
[{xmlelement, "x", _Attrs1, _Els1} = XEl] ->
|
2003-04-17 21:47:43 +02:00
|
|
|
case {xml:get_tag_attr_s("xmlns", XEl),
|
|
|
|
xml:get_tag_attr_s("type", XEl)} of
|
|
|
|
{?NS_XDATA, "cancel"} ->
|
|
|
|
{result, []};
|
|
|
|
{?NS_XDATA, "submit"} ->
|
|
|
|
XData = jlib:parse_xdata_submit(XEl),
|
|
|
|
case XData of
|
|
|
|
invalid ->
|
|
|
|
{error, ?ERR_BAD_REQUEST};
|
|
|
|
_ ->
|
2004-03-02 22:16:55 +01:00
|
|
|
iq_set_register_info(From, XData, Lang)
|
2003-05-07 16:17:53 +02:00
|
|
|
end;
|
|
|
|
_ ->
|
|
|
|
{error, ?ERR_BAD_REQUEST}
|
2003-04-17 21:47:43 +02:00
|
|
|
end;
|
|
|
|
_ ->
|
|
|
|
{error, ?ERR_BAD_REQUEST}
|
|
|
|
end.
|
|
|
|
|
2003-05-09 21:32:59 +02:00
|
|
|
iq_get_vcard(Lang) ->
|
|
|
|
[{xmlelement, "FN", [],
|
|
|
|
[{xmlcdata, "ejabberd/mod_muc"}]},
|
|
|
|
{xmlelement, "URL", [],
|
|
|
|
[{xmlcdata,
|
|
|
|
"http://ejabberd.jabberstudio.org/"}]},
|
|
|
|
{xmlelement, "DESC", [],
|
2003-12-06 20:58:49 +01:00
|
|
|
[{xmlcdata, translate:translate(Lang, "ejabberd MUC module\n"
|
2004-02-26 23:00:04 +01:00
|
|
|
"Copyright (c) 2003-2004 Alexey Shchepin")}]}].
|
2003-05-09 21:32:59 +02:00
|
|
|
|
|
|
|
|
2003-05-18 18:41:15 +02:00
|
|
|
broadcast_service_message(Msg) ->
|
|
|
|
lists:foreach(
|
2004-05-17 22:36:41 +02:00
|
|
|
fun(#muc_online_room{pid = Pid}) ->
|
2003-05-18 18:41:15 +02:00
|
|
|
gen_fsm:send_all_state_event(
|
|
|
|
Pid, {service_message, Msg})
|
|
|
|
end, ets:tab2list(muc_online_room)).
|
|
|
|
|
|
|
|
|
2003-04-17 21:47:43 +02:00
|
|
|
|
2004-05-17 22:36:41 +02:00
|
|
|
can_use_nick(_JID, "") ->
|
2003-05-08 13:46:38 +02:00
|
|
|
false;
|
2003-04-17 21:47:43 +02:00
|
|
|
can_use_nick(JID, Nick) ->
|
|
|
|
{LUser, LServer, _} = jlib:jid_tolower(JID),
|
|
|
|
LUS = {LUser, LServer},
|
|
|
|
case catch mnesia:dirty_index_read(muc_registered,
|
|
|
|
Nick,
|
|
|
|
#muc_registered.nick) of
|
2004-05-17 22:36:41 +02:00
|
|
|
{'EXIT', _Reason} ->
|
2003-04-17 21:47:43 +02:00
|
|
|
true;
|
|
|
|
[] ->
|
|
|
|
true;
|
|
|
|
[#muc_registered{user = U}] ->
|
|
|
|
U == LUS
|
|
|
|
end.
|
|
|
|
|
2003-03-26 21:51:18 +01:00
|
|
|
|
|
|
|
|