mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
* src/mod_muc/mod_muc.erl: Support for nick registration
SVN Revision: 100
This commit is contained in:
parent
0a166ec7a6
commit
097f73643a
@ -19,7 +19,8 @@
|
|||||||
store_room/2,
|
store_room/2,
|
||||||
restore_room/1,
|
restore_room/1,
|
||||||
forget_room/1,
|
forget_room/1,
|
||||||
process_iq_disco_items/5]).
|
process_iq_disco_items/5,
|
||||||
|
can_use_nick/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
-include("jlib.hrl").
|
||||||
@ -27,11 +28,17 @@
|
|||||||
|
|
||||||
-record(muc_room, {name, opts}).
|
-record(muc_room, {name, opts}).
|
||||||
-record(muc_online_room, {name, pid}).
|
-record(muc_online_room, {name, pid}).
|
||||||
|
-record(muc_registered, {user, nick}).
|
||||||
|
|
||||||
|
|
||||||
start(Opts) ->
|
start(Opts) ->
|
||||||
mnesia:create_table(muc_room,
|
mnesia:create_table(muc_room,
|
||||||
[{disc_copies, [node()]},
|
[{disc_copies, [node()]},
|
||||||
{attributes, record_info(fields, muc_room)}]),
|
{attributes, record_info(fields, muc_room)}]),
|
||||||
|
mnesia:create_table(muc_registered,
|
||||||
|
[{disc_copies, [node()]},
|
||||||
|
{attributes, record_info(fields, muc_registered)}]),
|
||||||
|
mnesia:add_table_index(muc_registered, nick),
|
||||||
Host = gen_mod:get_opt(host, Opts, "conference." ++ ?MYNAME),
|
Host = gen_mod:get_opt(host, Opts, "conference." ++ ?MYNAME),
|
||||||
register(ejabberd_mod_muc, spawn(?MODULE, init, [Host])).
|
register(ejabberd_mod_muc, spawn(?MODULE, init, [Host])).
|
||||||
|
|
||||||
@ -85,14 +92,36 @@ do_route(Host, From, To, Packet) ->
|
|||||||
spawn(?MODULE,
|
spawn(?MODULE,
|
||||||
process_iq_disco_items,
|
process_iq_disco_items,
|
||||||
[Host, From, To, ID, SubEl]);
|
[Host, From, To, ID, SubEl]);
|
||||||
|
{iq, ID, get, ?NS_REGISTER = XMLNS, SubEl} ->
|
||||||
|
Lang = xml:get_tag_attr_s("xml:lang", SubEl),
|
||||||
|
Res = {iq, ID, result, XMLNS,
|
||||||
|
[{xmlelement, "query",
|
||||||
|
[{"xmlns", XMLNS}],
|
||||||
|
iq_get_register_info(From, Lang)}]},
|
||||||
|
ejabberd_router:route(To,
|
||||||
|
From,
|
||||||
|
jlib:iq_to_xml(Res));
|
||||||
|
{iq, ID, set, ?NS_REGISTER = XMLNS, SubEl} ->
|
||||||
|
case process_iq_register_set(From, SubEl) of
|
||||||
|
{result, IQRes} ->
|
||||||
|
Res = {iq, ID, result, XMLNS,
|
||||||
|
[{xmlelement, "query",
|
||||||
|
[{"xmlns", XMLNS}],
|
||||||
|
IQRes}]},
|
||||||
|
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;
|
||||||
_ ->
|
_ ->
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERR_SERVICE_UNAVAILABLE),
|
Packet, ?ERR_SERVICE_UNAVAILABLE),
|
||||||
ejabberd_router:route(To, From, Err)
|
ejabberd_router:route(To, From, Err)
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
Err = jlib:make_error_reply(Packet,
|
Err = jlib:make_error_reply(Packet, ?ERR_JID_NOT_FOUND),
|
||||||
?ERR_JID_NOT_FOUND),
|
|
||||||
ejabberd_router:route(To, From, Err)
|
ejabberd_router:route(To, From, Err)
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
@ -182,8 +211,8 @@ iq_disco_info() ->
|
|||||||
[{"category", "conference"},
|
[{"category", "conference"},
|
||||||
{"type", "text"},
|
{"type", "text"},
|
||||||
{"name", "ejabberd/mod_muc"}], []},
|
{"name", "ejabberd/mod_muc"}], []},
|
||||||
{xmlelement, "feature",
|
{xmlelement, "feature", [{"var", ?NS_MUC}], []},
|
||||||
[{"var", ?NS_MUC}], []}].
|
{xmlelement, "feature", [{"var", ?NS_REGISTER}], []}].
|
||||||
|
|
||||||
|
|
||||||
process_iq_disco_items(Host, From, To, ID, SubEl) ->
|
process_iq_disco_items(Host, From, To, ID, SubEl) ->
|
||||||
@ -195,7 +224,6 @@ process_iq_disco_items(Host, From, To, ID, SubEl) ->
|
|||||||
From,
|
From,
|
||||||
jlib:iq_to_xml(Res)).
|
jlib:iq_to_xml(Res)).
|
||||||
|
|
||||||
% TODO: ask more info from room processes
|
|
||||||
iq_disco_items(Host, From) ->
|
iq_disco_items(Host, From) ->
|
||||||
lists:zf(fun(#muc_online_room{name = Name, pid = Pid}) ->
|
lists:zf(fun(#muc_online_room{name = Name, pid = Pid}) ->
|
||||||
case catch gen_fsm:sync_send_all_state_event(
|
case catch gen_fsm:sync_send_all_state_event(
|
||||||
@ -211,5 +239,116 @@ iq_disco_items(Host, From) ->
|
|||||||
end, ets:tab2list(muc_online_room)).
|
end, ets:tab2list(muc_online_room)).
|
||||||
|
|
||||||
|
|
||||||
|
-define(XFIELD(Type, Label, Var, Val),
|
||||||
|
{xmlelement, "field", [{"type", Type},
|
||||||
|
{"label", translate:translate(Lang, Label)},
|
||||||
|
{"var", Var}],
|
||||||
|
[{xmlelement, "value", [], [{xmlcdata, Val}]}]}).
|
||||||
|
|
||||||
|
iq_get_register_info(From, Lang) ->
|
||||||
|
{LUser, LServer, _} = jlib:jid_tolower(From),
|
||||||
|
LUS = {LUser, LServer},
|
||||||
|
Nick = case catch mnesia:dirty_read(muc_registered, LUS) of
|
||||||
|
{'EXIT', Reason} ->
|
||||||
|
"";
|
||||||
|
[] ->
|
||||||
|
"";
|
||||||
|
[#muc_registered{nick = N}] ->
|
||||||
|
N
|
||||||
|
end,
|
||||||
|
[{xmlelement, "instructions", [],
|
||||||
|
[{xmlcdata, translate:translate(
|
||||||
|
Lang, "You need a x:data capable client to register.")}]},
|
||||||
|
{xmlelement, "x",
|
||||||
|
[{"xmlns", ?NS_XDATA}],
|
||||||
|
[{xmlelement, "title", [],
|
||||||
|
[{xmlcdata,
|
||||||
|
translate:translate(
|
||||||
|
Lang, "Nick Registration")}]},
|
||||||
|
{xmlelement, "instructions", [],
|
||||||
|
[{xmlcdata,
|
||||||
|
translate:translate(
|
||||||
|
Lang, "Enter nick you want to register.")}]},
|
||||||
|
?XFIELD("text-single", "Nick", "nick", Nick)]}].
|
||||||
|
|
||||||
|
iq_set_register_info(From, XData) ->
|
||||||
|
{LUser, LServer, _} = jlib:jid_tolower(From),
|
||||||
|
LUS = {LUser, LServer},
|
||||||
|
case lists:keysearch("nick", 1, XData) of
|
||||||
|
false ->
|
||||||
|
{error, ?ERR_BAD_REQUEST};
|
||||||
|
{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} ->
|
||||||
|
{error, ?ERR_NOT_ALLOWED};
|
||||||
|
_ ->
|
||||||
|
{error, ?ERR_INTERNAL_SERVER_ERROR}
|
||||||
|
end
|
||||||
|
end.
|
||||||
|
|
||||||
|
process_iq_register_set(From, SubEl) ->
|
||||||
|
{xmlelement, Name, Attrs, Els} = SubEl,
|
||||||
|
case xml:remove_cdata(Els) of
|
||||||
|
[{xmlelement, "x", Attrs1, Els1} = XEl] ->
|
||||||
|
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};
|
||||||
|
_ ->
|
||||||
|
iq_set_register_info(From, XData)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
{error, ?ERR_BAD_REQUEST}
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
{'EXIT', Reason} ->
|
||||||
|
true;
|
||||||
|
[] ->
|
||||||
|
true;
|
||||||
|
[#muc_registered{user = U}] ->
|
||||||
|
U == LUS
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -323,7 +323,8 @@ normal_state({route, From, Nick,
|
|||||||
NewState
|
NewState
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
case is_nick_exists(Nick, StateData) of
|
case is_nick_exists(Nick, StateData) or
|
||||||
|
not mod_muc:can_use_nick(From, Nick) of
|
||||||
true ->
|
true ->
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERR_MUC_NICK_CONFLICT),
|
Packet, ?ERR_MUC_NICK_CONFLICT),
|
||||||
|
Loading…
Reference in New Issue
Block a user