aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlexey Shchepin <alexey@process-one.net>2003-10-24 19:21:07 +0000
committerAlexey Shchepin <alexey@process-one.net>2003-10-24 19:21:07 +0000
commite595ab91a058212424cd2e7e83df11cc4d499a41 (patch)
tree0266d8d152fbe78d812c3c4f1b3f307a36da7a69 /src
parent* src/ejabberd_logger_h.erl: New error_logger handler (diff)
* src/mod_offline.erl: Added function remove_old_messages/1
* src/mod_last.erl: jabber:iq:last support (JEP-0012) * src/ejabberd_sm.erl: Likewise * src/jlib.hrl: Added NS_LAST macros SVN Revision: 159
Diffstat (limited to 'src')
-rw-r--r--src/ejabberd.app2
-rw-r--r--src/ejabberd.cfg.example3
-rw-r--r--src/ejabberd_sm.erl13
-rw-r--r--src/jlib.hrl1
-rw-r--r--src/mod_last.erl114
-rw-r--r--src/mod_offline.erl17
6 files changed, 143 insertions, 7 deletions
diff --git a/src/ejabberd.app b/src/ejabberd.app
index 02b111181..df772dbab 100644
--- a/src/ejabberd.app
+++ b/src/ejabberd.app
@@ -14,6 +14,7 @@
ejabberd_c2s,
ejabberd_config,
ejabberd_listener,
+ ejabberd_logger_h,
ejabberd_local,
ejabberd_router,
ejabberd_s2s,
@@ -30,6 +31,7 @@
mod_configure,
mod_disco,
mod_echo,
+ mod_last,
mod_offline,
mod_private,
mod_register,
diff --git a/src/ejabberd.cfg.example b/src/ejabberd.cfg.example
index f1d915c4e..0626cfce4 100644
--- a/src/ejabberd.cfg.example
+++ b/src/ejabberd.cfg.example
@@ -90,7 +90,8 @@
{mod_irc, []},
{mod_muc, []},
{mod_pubsub, []},
- {mod_time, [{iqdisc, no_queue}]},
+ {mod_time, []},
+ {mod_last, []},
{mod_version, []}
]}.
diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl
index 1e2bc204c..32c333b9e 100644
--- a/src/ejabberd_sm.erl
+++ b/src/ejabberd_sm.erl
@@ -177,9 +177,9 @@ clean_table_from_bad_node(Node) ->
do_route(From, To, Packet) ->
?DEBUG("session manager~n\tfrom ~p~n\tto ~p~n\tpacket ~P~n",
[From, To, Packet, 8]),
- #jid{user = User, server = Server, resource = Resource,
+ #jid{user = User, resource = Resource,
luser = LUser, lserver = LServer, lresource = LResource} = To,
- {xmlelement, Name, Attrs, Els} = Packet,
+ {xmlelement, Name, Attrs, _Els} = Packet,
case Resource of
"" ->
case Name of
@@ -316,7 +316,7 @@ route_message(From, To, Packet) ->
get_user_resources(User) ->
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_index_read(session, LUser, #session.user) of
- {'EXIT', Reason} ->
+ {'EXIT', _Reason} ->
[];
Rs ->
lists:map(fun(R) ->
@@ -342,11 +342,12 @@ unset_presence(User, Resource) ->
UR = {User, Resource},
mnesia:delete({presence, UR})
end,
- mnesia:transaction(F).
+ mnesia:transaction(F),
+ catch mod_last:on_presence_update(LUser).
get_user_present_resources(LUser) ->
case catch mnesia:dirty_index_read(presence, LUser, #presence.user) of
- {'EXIT', Reason} ->
+ {'EXIT', _Reason} ->
[];
Rs ->
lists:map(fun(R) ->
@@ -366,7 +367,7 @@ dirty_get_my_sessions_list() ->
process_iq(From, To, Packet) ->
IQ = jlib:iq_query_info(Packet),
case IQ of
- {iq, ID, Type, XMLNS, SubEl} ->
+ {iq, _ID, _Type, XMLNS, _SubEl} ->
case ets:lookup(sm_iqtable, XMLNS) of
[{_, Module, Function}] ->
ResIQ = Module:Function(From, To, IQ),
diff --git a/src/jlib.hrl b/src/jlib.hrl
index 4ca09fc34..fdbf35dae 100644
--- a/src/jlib.hrl
+++ b/src/jlib.hrl
@@ -17,6 +17,7 @@
-define(NS_PRIVATE, "jabber:iq:private").
-define(NS_VERSION, "jabber:iq:version").
-define(NS_TIME, "jabber:iq:time").
+-define(NS_LAST, "jabber:iq:last").
-define(NS_XDATA, "jabber:x:data").
-define(NS_IQDATA, "jabber:iq:data").
-define(NS_DELAY, "jabber:x:delay").
diff --git a/src/mod_last.erl b/src/mod_last.erl
new file mode 100644
index 000000000..50f16fd24
--- /dev/null
+++ b/src/mod_last.erl
@@ -0,0 +1,114 @@
+%%%----------------------------------------------------------------------
+%%% File : mod_last.erl
+%%% Author : Alexey Shchepin <alexey@sevcom.net>
+%%% Purpose : jabber:iq:last support (JEP-0012)
+%%% Created : 24 Oct 2003 by Alexey Shchepin <alexey@sevcom.net>
+%%% Id : $Id$
+%%%----------------------------------------------------------------------
+
+-module(mod_last).
+-author('alexey@sevcom.net').
+-vsn('$Revision$ ').
+
+-behaviour(gen_mod).
+
+-export([start/1,
+ stop/0,
+ process_local_iq/3,
+ process_sm_iq/3,
+ on_presence_update/1]).
+
+-include("ejabberd.hrl").
+-include("jlib.hrl").
+
+-record(last_activity, {user, timestamp}).
+
+
+start(Opts) ->
+ IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
+ mnesia:create_table(last_activity,
+ [{disc_copies, [node()]},
+ {attributes, record_info(fields, last_activity)}]),
+ 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,
+ ?MODULE, process_sm_iq, IQDisc).
+
+stop() ->
+ gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_LAST).
+
+process_local_iq(_From, _To, {iq, ID, Type, XMLNS, SubEl}) ->
+ case Type of
+ set ->
+ {iq, ID, error, XMLNS,
+ [SubEl, ?ERR_NOT_ALLOWED]};
+ get ->
+ Sec = trunc(element(1, erlang:statistics(wall_clock))/1000),
+ {iq, ID, result, XMLNS,
+ [{xmlelement, "query",
+ [{"xmlns", ?NS_LAST},
+ {"seconds", integer_to_list(Sec)}],
+ []}]}
+ end.
+
+
+process_sm_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
+ case Type of
+ set ->
+ {iq, ID, error, XMLNS, [SubEl, ?ERR_NOT_ALLOWED]};
+ get ->
+ User = To#jid.luser,
+ {Subscription, _Groups} =
+ mod_roster:get_jid_info(User, From),
+ if
+ (Subscription == both) or (Subscription == from) ->
+ case catch mod_privacy:get_user_list(User) of
+ {'EXIT', _Reason} ->
+ get_last(ID, XMLNS, SubEl, User);
+ List ->
+ case mod_privacy:check_packet(
+ User, List,
+ {From, To,
+ {xmlelement, "presence", [], []}},
+ out) of
+ allow ->
+ get_last(ID, XMLNS, SubEl, User);
+ deny ->
+ {iq, ID, error, XMLNS,
+ [SubEl, ?ERR_NOT_ALLOWED]}
+ end
+ end;
+ true ->
+ {iq, ID, error, XMLNS, [SubEl, ?ERR_NOT_ALLOWED]}
+ end
+ end.
+
+get_last(ID, XMLNS, SubEl, LUser) ->
+ case catch mnesia:dirty_read(last_activity, LUser) of
+ {'EXIT', _Reason} ->
+ {iq, ID, error, XMLNS, [SubEl, ?ERR_INTERNAL_SERVER_ERROR]};
+ [] ->
+ {iq, ID, error, XMLNS, [SubEl, ?ERR_SERVICE_UNAVAILABLE]};
+ [#last_activity{timestamp = TimeStamp}] ->
+ {MegaSecs, Secs, _MicroSecs} = now(),
+ TimeStamp2 = MegaSecs * 1000000 + Secs,
+ Sec = TimeStamp2 - TimeStamp,
+ {iq, ID, result, XMLNS,
+ [{xmlelement, "query",
+ [{"xmlns", ?NS_LAST},
+ {"seconds", integer_to_list(Sec)}],
+ []}]}
+ end.
+
+
+
+on_presence_update(LUser) ->
+ {MegaSecs, Secs, _MicroSecs} = now(),
+ TimeStamp = MegaSecs * 1000000 + Secs,
+ F = fun() ->
+ mnesia:write(#last_activity{user = LUser,
+ timestamp = TimeStamp})
+ end,
+ mnesia:transaction(F).
+
+
diff --git a/src/mod_offline.erl b/src/mod_offline.erl
index 9462d77f0..63537600e 100644
--- a/src/mod_offline.erl
+++ b/src/mod_offline.erl
@@ -16,6 +16,7 @@
stop/0,
store_packet/3,
resend_offline_messages/1,
+ remove_old_messages/1,
remove_user/1]).
-include("jlib.hrl").
@@ -150,6 +151,22 @@ resend_offline_messages(User) ->
ok
end.
+remove_old_messages(Days) ->
+ {MegaSecs, Secs, _MicroSecs} = now(),
+ S = MegaSecs * 1000000 + Secs - 60 * 60 * 24 * Days,
+ MegaSecs1 = S div 1000000,
+ Secs1 = S rem 1000000,
+ TimeStamp = {MegaSecs1, Secs1, 0},
+ F = fun() ->
+ mnesia:foldl(
+ fun(#offline_msg{timestamp = TS} = Rec, _Acc)
+ when TS < TimeStamp ->
+ mnesia:delete_object(Rec);
+ (_Rec, _Acc) -> ok
+ end, ok, offline_msg)
+ end,
+ mnesia:transaction(F).
+
remove_user(User) ->
LUser = jlib:nodeprep(User),
F = fun() ->