From a846fe815c099d6519818e4fb47ba2e5975c974d Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Sun, 11 Jul 2004 20:51:54 +0000 Subject: [PATCH] * src/mod_last.erl: Supprot for storing status from latest unavailable presence (thanks to Sergei Golovan) * src/ejabberd_sm.erl: Likewise * src/ejabberd_c2s.erl: Likewise * src/mod_vcard.erl: Minor update (thanks to Sergei Golovan) * src/mod_register.erl: Added "access" option (thanks to Sergei Golovan) * src/mod_irc/mod_irc.erl: Likewise * src/ejabberd.cfg.example: Updated * src/win32/ejabberd.cfg: Likewise * src/mod_privacy.erl: Fixed module stopping (thanks to Sergei Golovan) * src/mod_private.erl: Likewise * src/gen_mod.erl: Added function get_module_opt/3 (thanks to Sergei Golovan) * src/ejabberd_local.erl: Minor fix (thanks to Sergei Golovan) * doc/guide.tex: Updated (thanks to Sergei Golovan) SVN Revision: 244 --- ChangeLog | 26 +++++++++++++++++++++++++ doc/guide.html | 23 ++++++++++++++++------ doc/guide.tex | 20 ++++++++++++++++---- src/ejabberd.cfg.example | 2 +- src/ejabberd_c2s.erl | 41 +++++++++++++++++++++++++++++----------- src/ejabberd_local.erl | 18 +++++++++--------- src/ejabberd_sm.erl | 6 +++--- src/gen_mod.erl | 11 +++++++++++ src/mod_irc/mod_irc.erl | 32 ++++++++++++++++++++++--------- src/mod_last.erl | 33 ++++++++++++++++++++++++++------ src/mod_privacy.erl | 2 +- src/mod_private.erl | 8 ++++---- src/mod_register.erl | 3 ++- src/mod_vcard.erl | 4 ++-- src/win32/ejabberd.cfg | 2 +- 15 files changed, 173 insertions(+), 58 deletions(-) diff --git a/ChangeLog b/ChangeLog index 97472ba5b..090ec3dce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2004-07-11 Alexey Shchepin + + * src/mod_last.erl: Supprot for storing status from latest + unavailable presence (thanks to Sergei Golovan) + * src/ejabberd_sm.erl: Likewise + * src/ejabberd_c2s.erl: Likewise + + * src/mod_vcard.erl: Minor update (thanks to Sergei Golovan) + + * src/mod_register.erl: Added "access" option (thanks to Sergei + Golovan) + * src/mod_irc/mod_irc.erl: Likewise + * src/ejabberd.cfg.example: Updated + * src/win32/ejabberd.cfg: Likewise + + * src/mod_privacy.erl: Fixed module stopping (thanks to Sergei + Golovan) + * src/mod_private.erl: Likewise + + * src/gen_mod.erl: Added function get_module_opt/3 (thanks to + Sergei Golovan) + + * src/ejabberd_local.erl: Minor fix (thanks to Sergei Golovan) + + * doc/guide.tex: Updated (thanks to Sergei Golovan) + 2004-07-10 Alexey Shchepin * src/mod_roster.erl: Removed superfluous include_lib line diff --git a/doc/guide.html b/doc/guide.html index 9e6c0c6fa..2db534258 100644 --- a/doc/guide.html +++ b/doc/guide.html @@ -871,7 +871,17 @@ Options: host
Defines hostname of service (see A.1.2). If not present then prefix irc. is added to main ejabberd hostname. +
access
Specifies who is allowed to use IRC transport (default value is all). +Example: +
+  {modules,
+   [
+    ...
+    {mod_irc, [{access, all}]},
+    ...
+   ]}.
+

A.6  mod_last

@@ -981,14 +991,15 @@ Example:

A.12  mod_register

-This module adds support for JEP-0077 (In-Band Registration). -It is possible to restrict registration via ``register'' -access rule. If this rule returns ``deny'' on requested user name, then -registration is not allowed for it.
+This module adds support for JEP-0077 (In-Band Registration).

Options:
-iqdisc
jabber:iq:register IQ queries processing +access
Specifies rule to restrict registration. +If this rule returns ``deny'' on requested user name, then +registration is not allowed for it. (default value is all, which means +no restrictions). +
iqdisc
jabber:iq:register IQ queries processing discipline (see A.1.1).
Example: @@ -1004,7 +1015,7 @@ Example: {modules, [ ... - {mod_register, []}, + {mod_register, [{access, register}]}, ... ]}. diff --git a/doc/guide.tex b/doc/guide.tex index 540091a8b..732aec45f 100644 --- a/doc/guide.tex +++ b/doc/guide.tex @@ -860,8 +860,19 @@ This module implements IRC transport. Options: \begin{description} \hostitem{irc} +\titem{access} Specifies who is allowed to use IRC transport (default value is \term{all}). \end{description} +Example: +\begin{verbatim} + {modules, + [ + ... + {mod_irc, [{access, all}]}, + ... + ]}. +\end{verbatim} + \subsection{\modlast{}} \label{sec:modlast} @@ -965,12 +976,13 @@ Example: \label{sec:modregister} This module adds support for \jepref{0077} (In-Band Registration). -It is possible to restrict registration via ``register'' -access rule. If this rule returns ``deny'' on requested user name, then -registration is not allowed for it. Options: \begin{description} +\titem{access} Specifies rule to restrict registration. +If this rule returns ``deny'' on requested user name, then +registration is not allowed for it. (default value is \term{all}, which means +no restrictions). \iqdiscitem{\ns{jabber:iq:register}} \end{description} @@ -987,7 +999,7 @@ Example: {modules, [ ... - {mod_register, []}, + {mod_register, [{access, register}]}, ... ]}. \end{verbatim} diff --git a/src/ejabberd.cfg.example b/src/ejabberd.cfg.example index f9668b665..405f4a2b2 100644 --- a/src/ejabberd.cfg.example +++ b/src/ejabberd.cfg.example @@ -107,7 +107,7 @@ % Used modules: {modules, [ - {mod_register, []}, + {mod_register, [{access, register}]}, {mod_roster, []}, {mod_privacy, []}, {mod_configure, []}, diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 63a19bd8f..8b10d064d 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -856,7 +856,8 @@ terminate(_Reason, StateName, StateData) -> [{xmlelement, "status", [], [{xmlcdata, "Replaced by new connection"}]}]}, ejabberd_sm:unset_presence(StateData#state.user, - StateData#state.resource), + StateData#state.resource, + "Replaced by new connection"), presence_broadcast( StateData, From, StateData#state.pres_a, Packet), presence_broadcast( @@ -867,15 +868,26 @@ terminate(_Reason, StateName, StateData) -> jlib:jid_to_string(StateData#state.jid)]), ejabberd_sm:close_session(StateData#state.user, StateData#state.resource), - From = StateData#state.jid, - Packet = {xmlelement, "presence", - [{"type", "unavailable"}], []}, - ejabberd_sm:unset_presence(StateData#state.user, - StateData#state.resource), - presence_broadcast( - StateData, From, StateData#state.pres_a, Packet), - presence_broadcast( - StateData, From, StateData#state.pres_i, Packet) + + Tmp = ?SETS:new(), + case StateData of + #state{pres_last = undefined, + pres_a = Tmp, + pres_i = Tmp, + pres_invis = false} -> + ok; + _ -> + From = StateData#state.jid, + Packet = {xmlelement, "presence", + [{"type", "unavailable"}], []}, + ejabberd_sm:unset_presence(StateData#state.user, + StateData#state.resource, + ""), + presence_broadcast( + StateData, From, StateData#state.pres_a, Packet), + presence_broadcast( + StateData, From, StateData#state.pres_i, Packet) + end end; _ -> ok @@ -984,8 +996,15 @@ presence_update(From, Packet, StateData) -> {xmlelement, _Name, Attrs, _Els} = Packet, case xml:get_attr_s("type", Attrs) of "unavailable" -> + Status = case xml:get_subtag(Packet, "status") of + false -> + ""; + StatusTag -> + xml:get_tag_cdata(StatusTag) + end, ejabberd_sm:unset_presence(StateData#state.user, - StateData#state.resource), + StateData#state.resource, + Status), presence_broadcast(StateData, From, StateData#state.pres_a, Packet), presence_broadcast(StateData, From, StateData#state.pres_i, Packet), StateData#state{pres_last = undefined, diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl index 5c91e280a..446ec292b 100644 --- a/src/ejabberd_local.erl +++ b/src/ejabberd_local.erl @@ -65,16 +65,16 @@ loop(State) -> catch mod_disco:unregister_feature(XMLNS), loop(State); refresh_iq_handlers -> - lists:map( + lists:foreach( fun(T) -> - case T of - {XMLNS, _Module, _Function, _Opts} -> - catch mod_disco:register_feature(XMLNS); - {XMLNS, _Module, _Function} -> - catch mod_disco:register_feature(XMLNS); - _ -> - ok - end + case T of + {XMLNS, _Module, _Function, _Opts} -> + catch mod_disco:register_feature(XMLNS); + {XMLNS, _Module, _Function} -> + catch mod_disco:register_feature(XMLNS); + _ -> + ok + end end, ets:tab2list(State#state.iqtable)), loop(State); _ -> diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index d2c278545..882c61e0e 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -13,7 +13,7 @@ -export([start_link/0, init/0, open_session/2, close_session/2, get_user_resources/1, set_presence/3, - unset_presence/2, + unset_presence/3, dirty_get_sessions_list/0, dirty_get_my_sessions_list/0, register_iq_handler/3, @@ -317,14 +317,14 @@ set_presence(User, Resource, Priority) -> end, mnesia:transaction(F). -unset_presence(User, Resource) -> +unset_presence(User, Resource, Status) -> LUser = jlib:nodeprep(User), F = fun() -> UR = {User, Resource}, mnesia:delete({presence, UR}) end, mnesia:transaction(F), - catch mod_last:on_presence_update(LUser). + catch mod_last:on_presence_update(LUser, Status). get_user_present_resources(LUser) -> case catch mnesia:dirty_index_read(presence, LUser, #presence.user) of diff --git a/src/gen_mod.erl b/src/gen_mod.erl index 2f9d07382..945754fbf 100644 --- a/src/gen_mod.erl +++ b/src/gen_mod.erl @@ -15,6 +15,7 @@ stop_module/1, get_opt/2, get_opt/3, + get_module_opt/3, loaded_modules/0]). -export([behaviour_info/1]). @@ -73,6 +74,16 @@ get_opt(Opt, Opts, Default) -> Val end. +get_module_opt(Module, Opt, Default) -> + OptsList = ets:lookup(ejabberd_modules, Module), + case OptsList of + [] -> + Default; + [#ejabberd_module{opts = Opts} | _] -> + get_opt(Opt, Opts, Default) + end. + loaded_modules() -> ets:select(ejabberd_modules, [{#ejabberd_module{_ = '_', module = '$1'}, [],['$1']}]). + diff --git a/src/mod_irc/mod_irc.erl b/src/mod_irc/mod_irc.erl index 9cfe26d6a..efa3c995e 100644 --- a/src/mod_irc/mod_irc.erl +++ b/src/mod_irc/mod_irc.erl @@ -12,7 +12,7 @@ -behaviour(gen_mod). --export([start/1, init/1, stop/0, closed_conection/2, +-export([start/1, init/2, stop/0, closed_conection/2, get_user_and_encoding/2]). -include("ejabberd.hrl"). @@ -29,34 +29,48 @@ start(Opts) -> [{disc_copies, [node()]}, {attributes, record_info(fields, irc_custom)}]), Host = gen_mod:get_opt(host, Opts, "irc." ++ ?MYNAME), - register(ejabberd_mod_irc, spawn(?MODULE, init, [Host])). + Access = gen_mod:get_opt(access, Opts, all), + register(ejabberd_mod_irc, spawn(?MODULE, init, [Host, Access])). -init(Host) -> +init(Host, Access) -> catch ets:new(irc_connection, [named_table, public, {keypos, #irc_connection.userserver}]), ejabberd_router:register_route(Host), - loop(Host). + loop(Host, Access). -loop(Host) -> +loop(Host, Access) -> receive {route, From, To, Packet} -> - case catch do_route(Host, From, To, Packet) of + case catch do_route(Host, Access, From, To, Packet) of {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]); _ -> ok end, - loop(Host); + loop(Host, Access); stop -> ejabberd_router:unregister_global_route(Host), ok; _ -> - loop(Host) + loop(Host, Access) end. -do_route(Host, From, To, Packet) -> +do_route(Host, Access, From, To, Packet) -> + case acl:match_rule(Access, From) of + allow -> + do_route1(Host, 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, From, To, Packet) -> #jid{user = ChanServ, resource = Resource} = To, {xmlelement, _Name, Attrs, _Els} = Packet, case ChanServ of diff --git a/src/mod_last.erl b/src/mod_last.erl index bcff1ed8b..8f106d9e3 100644 --- a/src/mod_last.erl +++ b/src/mod_last.erl @@ -16,13 +16,13 @@ stop/0, process_local_iq/3, process_sm_iq/3, - on_presence_update/1, + on_presence_update/2, remove_user/1]). -include("ejabberd.hrl"). -include("jlib.hrl"). --record(last_activity, {user, timestamp}). +-record(last_activity, {user, timestamp, status}). start(Opts) -> @@ -30,6 +30,7 @@ start(Opts) -> mnesia:create_table(last_activity, [{disc_copies, [node()]}, {attributes, record_info(fields, last_activity)}]), + update_table(), gen_iq_handler:add_iq_handler(ejabberd_local, ?NS_LAST, ?MODULE, process_local_iq, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_sm, ?NS_LAST, @@ -93,7 +94,7 @@ get_last(IQ, SubEl, LUser) -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]}; [] -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]}; - [#last_activity{timestamp = TimeStamp}] -> + [#last_activity{timestamp = TimeStamp, status = Status}] -> {MegaSecs, Secs, _MicroSecs} = now(), TimeStamp2 = MegaSecs * 1000000 + Secs, Sec = TimeStamp2 - TimeStamp, @@ -101,17 +102,18 @@ get_last(IQ, SubEl, LUser) -> sub_el = [{xmlelement, "query", [{"xmlns", ?NS_LAST}, {"seconds", integer_to_list(Sec)}], - []}]} + [{xmlcdata, Status}]}]} end. -on_presence_update(LUser) -> +on_presence_update(LUser, Status) -> {MegaSecs, Secs, _MicroSecs} = now(), TimeStamp = MegaSecs * 1000000 + Secs, F = fun() -> mnesia:write(#last_activity{user = LUser, - timestamp = TimeStamp}) + timestamp = TimeStamp, + status = Status}) end, mnesia:transaction(F). @@ -122,3 +124,22 @@ remove_user(User) -> mnesia:delete({last_activity, LUser}) end, mnesia:transaction(F). + + +update_table() -> + Fields = record_info(fields, last_activity), + case mnesia:table_info(last_activity, attributes) of + Fields -> + ok; + [user, timestamp] -> + ?INFO_MSG("Converting last_activity table from {user, timestamp} format", []), + mnesia:transform_table( + last_activity, + fun({_, U, T}) -> + #last_activity{user = U, timestamp = T, status = ""} + end, Fields); + _ -> + ?INFO_MSG("Recreating last_activity table", []), + mnesia:transform_table(last_activity, ignore, Fields) + end. + diff --git a/src/mod_privacy.erl b/src/mod_privacy.erl index 734b1e863..b89012e96 100644 --- a/src/mod_privacy.erl +++ b/src/mod_privacy.erl @@ -50,7 +50,7 @@ start(Opts) -> ?MODULE, process_iq, IQDisc). stop() -> - gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_PRIVACY). + gen_iq_handler:remove_iq_handler(ejabberd_sm, ?NS_PRIVACY). process_iq(From, _To, IQ) -> #iq{type = Type, sub_el = SubEl} = IQ, diff --git a/src/mod_private.erl b/src/mod_private.erl index 868d0ef9e..fa77ab5a1 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -14,7 +14,7 @@ -export([start/1, stop/0, - process_local_iq/3, + process_sm_iq/3, remove_user/1]). -include("ejabberd.hrl"). @@ -28,13 +28,13 @@ start(Opts) -> [{disc_only_copies, [node()]}, {attributes, record_info(fields, private_storage)}]), gen_iq_handler:add_iq_handler(ejabberd_sm, ?NS_PRIVATE, - ?MODULE, process_local_iq, IQDisc). + ?MODULE, process_sm_iq, IQDisc). stop() -> - gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_PRIVATE). + gen_iq_handler:remove_iq_handler(ejabberd_sm, ?NS_PRIVATE). -process_local_iq(From, _To, #iq{type = Type, sub_el = SubEl} = IQ) -> +process_sm_iq(From, _To, #iq{type = Type, sub_el = SubEl} = IQ) -> #jid{luser = LUser, lserver = LServer} = From, case ?MYNAME of LServer -> diff --git a/src/mod_register.erl b/src/mod_register.erl index a07c14e11..3099af0b1 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -122,7 +122,8 @@ try_register(User, Password) -> {error, ?ERR_BAD_REQUEST}; _ -> JID = jlib:make_jid(User, ?MYNAME, ""), - case acl:match_rule(register, JID) of + Access = gen_mod:get_module_opt(?MODULE, access, all), + case acl:match_rule(Access, JID) of deny -> {error, ?ERR_CONFLICT}; allow -> diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index 2dbc987c9..e2257772a 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -70,10 +70,10 @@ start(Opts) -> init(Host, Search) -> case Search of - true -> - ejabberd_router:register_route(Host), + false -> loop(Host); _ -> + ejabberd_router:register_route(Host), loop(Host) end. diff --git a/src/win32/ejabberd.cfg b/src/win32/ejabberd.cfg index 1e2b2081b..b4fdeb0d8 100644 --- a/src/win32/ejabberd.cfg +++ b/src/win32/ejabberd.cfg @@ -103,7 +103,7 @@ % Used modules: {modules, [ - {mod_register, []}, + {mod_register, [{access, register}]}, {mod_roster, []}, {mod_privacy, []}, {mod_configure, []},