diff options
| author | Alexey Shchepin <alexey@process-one.net> | 2003-10-24 19:21:07 +0000 | 
|---|---|---|
| committer | Alexey Shchepin <alexey@process-one.net> | 2003-10-24 19:21:07 +0000 | 
| commit | e595ab91a058212424cd2e7e83df11cc4d499a41 (patch) | |
| tree | 0266d8d152fbe78d812c3c4f1b3f307a36da7a69 | |
| 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
| -rw-r--r-- | ChangeLog | 9 | ||||
| -rw-r--r-- | src/ejabberd.app | 2 | ||||
| -rw-r--r-- | src/ejabberd.cfg.example | 3 | ||||
| -rw-r--r-- | src/ejabberd_sm.erl | 13 | ||||
| -rw-r--r-- | src/jlib.hrl | 1 | ||||
| -rw-r--r-- | src/mod_last.erl | 114 | ||||
| -rw-r--r-- | src/mod_offline.erl | 17 | 
7 files changed, 152 insertions, 7 deletions
| @@ -1,3 +1,12 @@ +2003-10-24  Alexey Shchepin  <alexey@sevcom.net> + +	* 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 +  2003-10-23  Alexey Shchepin  <alexey@sevcom.net>  	* src/ejabberd_logger_h.erl: New error_logger handler 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() -> | 
