summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlexey Shchepin <alexey@process-one.net>2003-04-17 19:47:43 +0000
committerAlexey Shchepin <alexey@process-one.net>2003-04-17 19:47:43 +0000
commit097f73643a994a679f97d0e69d5696933a0278e3 (patch)
tree2674b92d9b0db600f2a39d6c93420405c027f248 /src
parent* src/ejabberd_c2s.erl: Some fixes in work with socket (diff)
* src/mod_muc/mod_muc.erl: Support for nick registration
SVN Revision: 100
Diffstat (limited to 'src')
-rw-r--r--src/mod_muc/mod_muc.erl151
-rw-r--r--src/mod_muc/mod_muc_room.erl3
2 files changed, 147 insertions, 7 deletions
diff --git a/src/mod_muc/mod_muc.erl b/src/mod_muc/mod_muc.erl
index e3e39168..f8a6d12e 100644
--- a/src/mod_muc/mod_muc.erl
+++ b/src/mod_muc/mod_muc.erl
@@ -19,7 +19,8 @@
store_room/2,
restore_room/1,
forget_room/1,
- process_iq_disco_items/5]).
+ process_iq_disco_items/5,
+ can_use_nick/2]).
-include("ejabberd.hrl").
-include("jlib.hrl").
@@ -27,11 +28,17 @@
-record(muc_room, {name, opts}).
-record(muc_online_room, {name, pid}).
+-record(muc_registered, {user, nick}).
+
start(Opts) ->
mnesia:create_table(muc_room,
[{disc_copies, [node()]},
{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),
register(ejabberd_mod_muc, spawn(?MODULE, init, [Host])).
@@ -85,14 +92,36 @@ do_route(Host, From, To, Packet) ->
spawn(?MODULE,
process_iq_disco_items,
[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(
Packet, ?ERR_SERVICE_UNAVAILABLE),
ejabberd_router:route(To, From, Err)
end;
_ ->
- Err = jlib:make_error_reply(Packet,
- ?ERR_JID_NOT_FOUND),
+ Err = jlib:make_error_reply(Packet, ?ERR_JID_NOT_FOUND),
ejabberd_router:route(To, From, Err)
end;
_ ->
@@ -182,8 +211,8 @@ iq_disco_info() ->
[{"category", "conference"},
{"type", "text"},
{"name", "ejabberd/mod_muc"}], []},
- {xmlelement, "feature",
- [{"var", ?NS_MUC}], []}].
+ {xmlelement, "feature", [{"var", ?NS_MUC}], []},
+ {xmlelement, "feature", [{"var", ?NS_REGISTER}], []}].
process_iq_disco_items(Host, From, To, ID, SubEl) ->
@@ -195,7 +224,6 @@ process_iq_disco_items(Host, From, To, ID, SubEl) ->
From,
jlib:iq_to_xml(Res)).
-% TODO: ask more info from room processes
iq_disco_items(Host, From) ->
lists:zf(fun(#muc_online_room{name = Name, pid = Pid}) ->
case catch gen_fsm:sync_send_all_state_event(
@@ -211,5 +239,116 @@ iq_disco_items(Host, From) ->
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.
+
diff --git a/src/mod_muc/mod_muc_room.erl b/src/mod_muc/mod_muc_room.erl
index 67cc2fdc..aeffd03b 100644
--- a/src/mod_muc/mod_muc_room.erl
+++ b/src/mod_muc/mod_muc_room.erl
@@ -323,7 +323,8 @@ normal_state({route, From, Nick,
NewState
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 ->
Err = jlib:make_error_reply(
Packet, ?ERR_MUC_NICK_CONFLICT),