diff options
Diffstat (limited to 'src/mod_last_odbc.erl')
-rw-r--r-- | src/mod_last_odbc.erl | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/mod_last_odbc.erl b/src/mod_last_odbc.erl new file mode 100644 index 00000000..4937778d --- /dev/null +++ b/src/mod_last_odbc.erl @@ -0,0 +1,135 @@ +%%%---------------------------------------------------------------------- +%%% File : mod_last_odbc.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_odbc). +-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/3, + remove_user/1]). + +-include("ejabberd.hrl"). +-include("jlib.hrl"). + + +start(Opts) -> + IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), + 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), + ejabberd_hooks:add(unset_presence_hook, + ?MODULE, on_presence_update, 50). + +stop() -> + gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_LAST), + gen_iq_handler:remove_iq_handler(ejabberd_sm, ?NS_LAST). + +process_local_iq(_From, _To, #iq{type = Type, sub_el = SubEl} = IQ) -> + case Type of + set -> + IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; + get -> + Sec = trunc(element(1, erlang:statistics(wall_clock))/1000), + IQ#iq{type = result, + sub_el = [{xmlelement, "query", + [{"xmlns", ?NS_LAST}, + {"seconds", integer_to_list(Sec)}], + []}]} + end. + + +process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) -> + case Type of + set -> + IQ#iq{type = error, sub_el = [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(IQ, SubEl, User); + List -> + case catch mod_privacy:check_packet( + User, List, + {From, To, + {xmlelement, "presence", [], []}}, + out) of + {'EXIT', _Reason} -> + get_last(IQ, SubEl, User); + allow -> + get_last(IQ, SubEl, User); + deny -> + IQ#iq{type = error, + sub_el = [SubEl, ?ERR_NOT_ALLOWED]} + end + end; + true -> + IQ#iq{type = error, + sub_el = [SubEl, ?ERR_NOT_ALLOWED]} + end + end. + +get_last(IQ, SubEl, LUser) -> + Username = ejabberd_odbc:escape(LUser), + case catch ejabberd_odbc:sql_query( + ["select seconds, state from last " + "where username='", Username, "'"]) of + {'EXIT', _Reason} -> + IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]}; + {selected, ["seconds","state"], []} -> + IQ#iq{type = error, sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]}; + {selected, ["seconds","state"], [{STimeStamp, Status}]} -> + case catch list_to_integer(STimeStamp) of + TimeStamp when is_integer(TimeStamp) -> + {MegaSecs, Secs, _MicroSecs} = now(), + TimeStamp2 = MegaSecs * 1000000 + Secs, + Sec = TimeStamp2 - TimeStamp, + IQ#iq{type = result, + sub_el = [{xmlelement, "query", + [{"xmlns", ?NS_LAST}, + {"seconds", integer_to_list(Sec)}], + [{xmlcdata, Status}]}]}; + _ -> + IQ#iq{type = error, + sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]} + end + end. + + + +on_presence_update(User, _Resource, Status) -> + LUser = jlib:nodeprep(User), + {MegaSecs, Secs, _MicroSecs} = now(), + TimeStamp = MegaSecs * 1000000 + Secs, + Username = ejabberd_odbc:escape(LUser), + Seconds = ejabberd_odbc:escape(integer_to_list(TimeStamp)), + State = ejabberd_odbc:escape(Status), + ejabberd_odbc:sql_query( + ["begin;" + "delete from last where username='", Username, "';" + "insert into last(username, seconds, state) " + "values ('", Username, "', '", Seconds, "', '", State, "');", + "commit"]). + + +remove_user(User) -> + LUser = jlib:nodeprep(User), + Username = ejabberd_odbc:escape(LUser), + ejabberd_odbc:sql_query( + ["delete from last where username='", Username, "'"]). + |