* 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
This commit is contained in:
Alexey Shchepin 2004-07-11 20:51:54 +00:00
parent b64cc8f662
commit a846fe815c
15 changed files with 173 additions and 58 deletions

View File

@ -1,3 +1,29 @@
2004-07-11 Alexey Shchepin <alexey@sevcom.net>
* 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 <alexey@sevcom.net>
* src/mod_roster.erl: Removed superfluous include_lib line

View File

@ -871,7 +871,17 @@ Options:
<B><TT>host</TT></B><DD> Defines hostname of service
(see&nbsp;<A HREF="#sec:modhostoption">A.1.2</A>). If not present
then prefix <TT>irc.</TT> is added to main <TT>ejabberd</TT> hostname.
<DT><B><TT>access</TT></B><DD> Specifies who is allowed to use IRC transport (default value is <TT>all</TT>).
</DL>
Example:
<PRE>
{modules,
[
...
{mod_irc, [{access, all}]},
...
]}.
</PRE>
<!--TOC subsection <TT>mod_last</TT>-->
<H3><A NAME="htoc36">A.6</A>&nbsp;&nbsp;<TT>mod_last</TT></H3><!--SEC END -->
@ -981,14 +991,15 @@ Example:
<H3><A NAME="htoc42">A.12</A>&nbsp;&nbsp;<TT>mod_register</TT></H3><!--SEC END -->
<A NAME="sec:modregister"></A>
This module adds support for <A HREF="http://www.jabber.org/jeps/jep-0077.html">JEP-0077</A> (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.<BR>
This module adds support for <A HREF="http://www.jabber.org/jeps/jep-0077.html">JEP-0077</A> (In-Band Registration).<BR>
<BR>
Options:
<DL COMPACT=compact><DT>
<B><TT>iqdisc</TT></B><DD> <TT>jabber:iq:register</TT> IQ queries processing
<B><TT>access</TT></B><DD> Specifies rule to restrict registration.
If this rule returns ``deny'' on requested user name, then
registration is not allowed for it. (default value is <TT>all</TT>, which means
no restrictions).
<DT><B><TT>iqdisc</TT></B><DD> <TT>jabber:iq:register</TT> IQ queries processing
discipline (see&nbsp;<A HREF="#sec:modiqdiscoption">A.1.1</A>).
</DL>
Example:
@ -1004,7 +1015,7 @@ Example:
{modules,
[
...
{mod_register, []},
{mod_register, [{access, register}]},
...
]}.
</PRE>

View File

@ -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}

View File

@ -107,7 +107,7 @@
% Used modules:
{modules,
[
{mod_register, []},
{mod_register, [{access, register}]},
{mod_roster, []},
{mod_privacy, []},
{mod_configure, []},

View File

@ -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,

View File

@ -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);
_ ->

View File

@ -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

View File

@ -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']}]).

View File

@ -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

View File

@ -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.

View File

@ -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,

View File

@ -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 ->

View File

@ -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 ->

View File

@ -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.

View File

@ -103,7 +103,7 @@
% Used modules:
{modules,
[
{mod_register, []},
{mod_register, [{access, register}]},
{mod_roster, []},
{mod_privacy, []},
{mod_configure, []},