SOURCES: ejabberd-mod_logdb.patch (NEW) - sever-side message loggi...
shadzik
shadzik at pld-linux.org
Fri Jan 25 20:24:04 CET 2008
Author: shadzik Date: Fri Jan 25 19:24:04 2008 GMT
Module: SOURCES Tag: HEAD
---- Log message:
- sever-side message logging support
---- Files affected:
SOURCES:
ejabberd-mod_logdb.patch (NONE -> 1.1) (NEW)
---- Diffs:
================================================================
Index: SOURCES/ejabberd-mod_logdb.patch
diff -u /dev/null SOURCES/ejabberd-mod_logdb.patch:1.1
--- /dev/null Fri Jan 25 20:24:04 2008
+++ SOURCES/ejabberd-mod_logdb.patch Fri Jan 25 20:23:58 2008
@@ -0,0 +1,5992 @@
+--- src/mod_logdb.erl.orig Tue Dec 11 14:23:19 2007
++++ src/mod_logdb.erl Thu Sep 20 15:26:21 2007
+@@ -0,0 +1,1656 @@
++%%%----------------------------------------------------------------------
++%%% File : mod_logdb.erl
++%%% Author : Oleg Palij (mailto:o.palij at gmail.com xmpp://malik@jabber.te.ua)
++%%% Purpose : Frontend for log user messages to db
++%%% Version : trunk
++%%% Id : $Id$
++%%% Url : http://www.dp.uz.gov.ua/o.palij/mod_logdb/
++%%%----------------------------------------------------------------------
++
++-module(mod_logdb).
++-author('o.palij at gmail.com').
++-vsn('$Revision$').
++
++-behaviour(gen_server).
++-behaviour(gen_mod).
++
++% supervisor
++-export([start_link/2]).
++% gen_mod
++-export([start/2,stop/1]).
++% gen_server
++-export([code_change/3,handle_call/3,handle_cast/2,handle_info/2,init/1,terminate/2]).
++% hooks
++-export([send_packet/3, receive_packet/4, offline_packet/3]).
++-export([get_local_identity/5,
++ get_local_features/5,
++ get_local_items/5,
++ adhoc_local_items/4,
++ adhoc_local_commands/4
++% get_sm_identity/5,
++% get_sm_features/5,
++% get_sm_items/5,
++% adhoc_sm_items/4,
++% adhoc_sm_commands/4]).
++ ]).
++% ejabberdctl
++-export([rebuild_stats/3,
++ copy_messages/1, copy_messages_ctl/3, copy_messages_int_tc/1]).
++%
++-export([get_vhost_stats/1, get_vhost_stats_at/2,
++ get_user_stats/2, get_user_messages_at/3,
++ get_dates/1,
++ sort_stats/1,
++ convert_timestamp/1, convert_timestamp_brief/1,
++ get_user_settings/2, set_user_settings/3,
++ user_messages_at_parse_query/4, user_messages_parse_query/3,
++ vhost_messages_parse_query/2, vhost_messages_at_parse_query/4,
++ list_to_bool/1, bool_to_list/1,
++ list_to_string/1, string_to_list/1,
++ get_module_settings/1, set_module_settings/2,
++ purge_old_records/2]).
++
++-include("mod_logdb.hrl").
++-include("ejabberd.hrl").
++-include("jlib.hrl").
++-include("ejabberd_ctl.hrl").
++-include("adhoc.hrl").
++
++-define(PROCNAME, ejabberd_mod_logdb).
++% gen_server call timeout
++-define(CALL_TIMEOUT, 60000).
++
++-record(state, {vhost, dbmod, backendPid, monref, purgeRef, pollRef, dbopts, dbs, dolog_default, ignore_jids, groupchat, purge_older_days, poll_users_settings}).
++
++ets_settings_table(VHost) -> list_to_atom("ets_logdb_settings_" ++ VHost).
++
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%
++% gen_mod/gen_server callbacks
++%
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++% ejabberd starts module
++start(VHost, Opts) ->
++ ChildSpec =
++ {gen_mod:get_module_proc(VHost, ?PROCNAME),
++ {?MODULE, start_link, [VHost, Opts]},
++ permanent,
++ 1000,
++ worker,
++ [?MODULE]},
++ % add child to ejabberd_sup
++ supervisor:start_child(ejabberd_sup, ChildSpec).
++
++% supervisor starts gen_server
++start_link(VHost, Opts) ->
++ Proc = gen_mod:get_module_proc(VHost, ?PROCNAME),
++ gen_server:start_link({local, Proc}, ?MODULE, [VHost, Opts], []).
++
++init([VHost, Opts]) ->
++ process_flag(trap_exit, true),
++ DBs = gen_mod:get_opt(dbs, Opts, [{mnesia, []}]),
++ VHostDB = gen_mod:get_opt(vhosts, Opts, [{VHost, mnesia}]),
++ % 10 is default becouse of using in clustered environment
++ PollUsersSettings = gen_mod:get_opt(poll_users_settings, Opts, 10),
++
++ {value,{_, DBName}} = lists:keysearch(VHost, 1, VHostDB),
++ {value, {DBName, DBOpts}} = lists:keysearch(DBName, 1, DBs),
++
++ ?MYDEBUG("Starting mod_logdb for ~p with ~p backend", [VHost, DBName]),
++
++ DBMod = list_to_atom(atom_to_list(?MODULE) ++ "_" ++ atom_to_list(DBName)),
++
++ % actually all work begin on receiving start signal
++ timer:send_after(1000, start),
++
++ {ok, #state{vhost=VHost,
++ dbmod=DBMod,
++ dbopts=DBOpts,
++ % dbs used for convert messages from one backend to other
++ dbs=DBs,
++ dolog_default=gen_mod:get_opt(dolog_default, Opts, true),
++ ignore_jids=gen_mod:get_opt(ignore_jids, Opts, []),
++ groupchat=gen_mod:get_opt(groupchat, Opts, none),
++ purge_older_days=gen_mod:get_opt(purge_older_days, Opts, never),
++ poll_users_settings=PollUsersSettings}}.
++
++cleanup(#state{vhost=VHost} = State) ->
++ ?MYDEBUG("Stopping ~s for ~p", [?MODULE, VHost]),
++
++ %ets:delete(ets_settings_table(VHost)),
++
++ ejabberd_hooks:delete(user_send_packet, VHost, ?MODULE, send_packet, 90),
++ ejabberd_hooks:delete(user_receive_packet, VHost, ?MODULE, receive_packet, 90),
++ ejabberd_hooks:delete(offline_message_hook, VHost, ?MODULE, offline_packet, 10),
++ %ejabberd_hooks:delete(adhoc_sm_commands, VHost, ?MODULE, adhoc_sm_commands, 110),
++ %ejabberd_hooks:delete(adhoc_sm_items, VHost, ?MODULE, adhoc_sm_items, 110),
++ ejabberd_hooks:delete(adhoc_local_commands, VHost, ?MODULE, adhoc_local_commands, 110),
++ ejabberd_hooks:delete(adhoc_local_items, VHost, ?MODULE, adhoc_local_items, 110),
++ %ejabberd_hooks:delete(disco_sm_identity, VHost, ?MODULE, get_sm_identity, 110),
++ %ejabberd_hooks:delete(disco_sm_features, VHost, ?MODULE, get_sm_features, 110),
++ %ejabberd_hooks:delete(disco_sm_items, VHost, ?MODULE, get_sm_items, 110),
++ ejabberd_hooks:delete(disco_local_identity, VHost, ?MODULE, get_local_identity, 110),
++ ejabberd_hooks:delete(disco_local_features, VHost, ?MODULE, get_local_features, 110),
++ ejabberd_hooks:delete(disco_local_items, VHost, ?MODULE, get_local_items, 110),
++
++ ?MYDEBUG("Removed hooks for ~p", [VHost]),
++
++ ejabberd_ctl:unregister_commands(VHost, [{"rebuild_stats", "rebuild mod_logdb module stats for vhost"}], ?MODULE, rebuild_stats),
++ Supported_backends = lists:flatmap(fun({Backend, _Opts}) ->
++ [atom_to_list(Backend), " "]
++ end, State#state.dbs),
++ ejabberd_ctl:unregister_commands(
++ VHost,
++ [{"copy_messages backend", "copy messages from backend to current backend. backends could be: " ++ Supported_backends }],
++ ?MODULE, copy_messages_ctl),
++ ?MYDEBUG("Unregistered commands for ~p", [VHost]).
++
++stop(VHost) ->
++ Proc = gen_mod:get_module_proc(VHost, ?PROCNAME),
++ %gen_server:call(Proc, {cleanup}),
++ %?MYDEBUG("Cleanup in stop finished!!!!", []),
++ %timer:sleep(10000),
++ ok = supervisor:terminate_child(ejabberd_sup, Proc),
++ ok = supervisor:delete_child(ejabberd_sup, Proc).
++
++handle_call({cleanup}, _From, State) ->
++ cleanup(State),
++ ?MYDEBUG("Cleanup finished!!!!!", []),
++ {reply, ok, State};
++handle_call({get_dates}, _From, #state{dbmod=DBMod, vhost=VHost}=State) ->
++ Reply = DBMod:get_dates(VHost),
++ {reply, Reply, State};
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++% ejabberd_web_admin callbacks
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++handle_call({delete_messages_by_user_at, PMsgs, Date}, _From, #state{dbmod=DBMod, vhost=VHost}=State) ->
++ Reply = DBMod:delete_messages_by_user_at(VHost, PMsgs, Date),
++ {reply, Reply, State};
++handle_call({delete_all_messages_by_user_at, User, Date}, _From, #state{dbmod=DBMod, vhost=VHost}=State) ->
++ Reply = DBMod:delete_all_messages_by_user_at(User, VHost, Date),
++ {reply, Reply, State};
++handle_call({delete_messages_at, Date}, _From, #state{dbmod=DBMod, vhost=VHost}=State) ->
++ Reply = DBMod:delete_messages_at(VHost, Date),
++ {reply, Reply, State};
++handle_call({get_vhost_stats}, _From, #state{dbmod=DBMod, vhost=VHost}=State) ->
++ Reply = DBMod:get_vhost_stats(VHost),
++ {reply, Reply, State};
++handle_call({get_vhost_stats_at, Date}, _From, #state{dbmod=DBMod, vhost=VHost}=State) ->
++ Reply = DBMod:get_vhost_stats_at(VHost, Date),
++ {reply, Reply, State};
++handle_call({get_user_stats, User}, _From, #state{dbmod=DBMod, vhost=VHost}=State) ->
++ Reply = DBMod:get_user_stats(User, VHost),
++ {reply, Reply, State};
++handle_call({get_user_messages_at, User, Date}, _From, #state{dbmod=DBMod, vhost=VHost}=State) ->
++ Reply = DBMod:get_user_messages_at(User, VHost, Date),
++ {reply, Reply, State};
++handle_call({get_user_settings, User}, _From, #state{dbmod=_DBMod, vhost=VHost}=State) ->
++ Reply = case ets:match_object(ets_settings_table(VHost),
++ #user_settings{owner_name=User, _='_'}) of
++ [Set] -> Set;
++ _ -> #user_settings{owner_name=User,
++ dolog_default=State#state.dolog_default,
++ dolog_list=[],
++ donotlog_list=[]}
++ end,
++ {reply, Reply, State};
++% TODO: remove User ??
++handle_call({set_user_settings, User, GSet}, _From, #state{dbmod=DBMod, vhost=VHost}=State) ->
++ Set = GSet#user_settings{owner_name=User},
++ Reply =
++ case ets:match_object(ets_settings_table(VHost),
++ #user_settings{owner_name=User, _='_'}) of
++ [Set] ->
++ ?MYDEBUG("Settings is equal", []),
++ ok;
++ _ ->
++ case DBMod:set_user_settings(User, VHost, Set) of
++ error ->
++ error;
++ ok ->
++ true = ets:insert(ets_settings_table(VHost), Set),
++ ok
++ end
++ end,
++ {reply, Reply, State};
++handle_call({get_module_settings}, _From, State) ->
++ {reply, State, State};
++handle_call({set_module_settings, #state{purge_older_days=PurgeDays,
++ poll_users_settings=PollSec} = Settings},
++ _From,
++ #state{purgeRef=PurgeRefOld,
++ pollRef=PollRefOld,
++ purge_older_days=PurgeDaysOld,
++ poll_users_settings=PollSecOld} = State) ->
++ PurgeRef = if
++ PurgeDays == never, PurgeDaysOld /= never ->
++ {ok, cancel} = timer:cancel(PurgeRefOld),
++ disabled;
++ is_integer(PurgeDays), PurgeDaysOld == never ->
++ set_purge_timer(PurgeDays);
++ true ->
++ PurgeRefOld
++ end,
++
++ PollRef = if
++ PollSec == PollSecOld ->
++ PollRefOld;
++ PollSec == 0, PollSecOld /= 0 ->
++ {ok, cancel} = timer:cancel(PollRefOld),
++ disabled;
++ is_integer(PollSec), PollSecOld == 0 ->
++ set_poll_timer(PollSec);
++ is_integer(PollSec), PollSecOld /= 0 ->
++ {ok, cancel} = timer:cancel(PollRefOld),
++ set_poll_timer(PollSec)
++ end,
++
++ NewState = State#state{dolog_default=Settings#state.dolog_default,
++ ignore_jids=Settings#state.ignore_jids,
++ groupchat=Settings#state.groupchat,
++ purge_older_days=PurgeDays,
++ poll_users_settings=PollSec,
++ purgeRef=PurgeRef,
++ pollRef=PollRef},
++ {reply, ok, NewState};
++handle_call(Msg, _From, State) ->
++ ?INFO_MSG("Got call Msg: ~p, State: ~p", [Msg, State]),
++ {noreply, State}.
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++% end ejabberd_web_admin callbacks
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++
++% ejabberd_hooks call
++handle_cast({addlog, Direction, Owner, Peer, Packet}, #state{dbmod=DBMod, vhost=VHost}=State) ->
++ case filter(Owner, Peer, State) of
++ true ->
++ case catch packet_parse(Owner, Peer, Packet, Direction, State) of
++ ignore ->
++ ok;
++ {'EXIT', Reason} ->
++ ?ERROR_MSG("Failed to parse: ~p", [Reason]);
++ Msg ->
++ DBMod:log_message(VHost, Msg)
++ end;
++ false ->
++ ok
++ end,
++ {noreply, State};
++% ejabberdctl rebuild_stats/3
++handle_cast({rebuild_stats}, #state{dbmod=DBMod, vhost=VHost}=State) ->
++ % TODO: maybe spawn?
++ DBMod:rebuild_stats(VHost),
++ {noreply, State};
++handle_cast({copy_messages, Backend}, State) ->
++ spawn(?MODULE, copy_messages, [[State, Backend]]),
++ {noreply, State};
++handle_cast({copy_messages, Backend, Date}, State) ->
++ spawn(?MODULE, copy_messages, [[State, Backend, Date]]),
++ {noreply, State};
++handle_cast(Msg, State) ->
++ ?INFO_MSG("Got cast Msg:~p, State:~p", [Msg, State]),
++ {noreply, State}.
++
++% return: disabled | timer reference
++set_purge_timer(PurgeDays) ->
++ case PurgeDays of
++ never -> disabled;
++ Days when is_integer(Days) ->
++ {ok, Ref1} = timer:send_interval(timer:hours(24), scheduled_purging),
++ Ref1
++ end.
++
++% return: disabled | timer reference
++set_poll_timer(PollSec) ->
++ if
++ PollSec > 0 ->
++ {ok, Ref2} = timer:send_interval(timer:seconds(PollSec), poll_users_settings),
++ Ref2;
++ % db polling disabled
++ PollSec == 0 ->
++ disabled;
++ true ->
++ {ok, Ref3} = timer:send_interval(timer:seconds(10), poll_users_settings),
++ Ref3
++ end.
++
++% actual starting of logging
++% from timer:send_after (in init)
++handle_info(start, #state{dbmod=DBMod, vhost=VHost}=State) ->
++ case DBMod:start(VHost, State#state.dbopts) of
++ {error, _Reason} ->
++ timer:sleep(30000),
++ {stop, db_connection_failed, State};
++ {ok, SPid} ->
++
++ ?INFO_MSG("~p connection established", [DBMod]),
++
++ MonRef = erlang:monitor(process, SPid),
++
++ ets:new(ets_settings_table(VHost), [named_table,public,set,{keypos, #user_settings.owner_name}]),
++ {ok, DoLog} = DBMod:get_users_settings(VHost),
++ ets:insert(ets_settings_table(VHost), DoLog),
++
++ TrefPurge = set_purge_timer(State#state.purge_older_days),
++ TrefPoll = set_poll_timer(State#state.poll_users_settings),
++
++ ejabberd_hooks:add(user_send_packet, VHost, ?MODULE, send_packet, 90),
++ ejabberd_hooks:add(user_receive_packet, VHost, ?MODULE, receive_packet, 90),
++ ejabberd_hooks:add(offline_message_hook, VHost, ?MODULE, offline_packet, 10),
++
++ ejabberd_hooks:add(disco_local_items, VHost, ?MODULE, get_local_items, 110),
++ ejabberd_hooks:add(disco_local_features, VHost, ?MODULE, get_local_features, 110),
++ ejabberd_hooks:add(disco_local_identity, VHost, ?MODULE, get_local_identity, 110),
++ %ejabberd_hooks:add(disco_sm_items, VHost, ?MODULE, get_sm_items, 110),
++ %ejabberd_hooks:add(disco_sm_features, VHost, ?MODULE, get_sm_features, 110),
++ %ejabberd_hooks:add(disco_sm_identity, VHost, ?MODULE, get_sm_identity, 110),
++ ejabberd_hooks:add(adhoc_local_items, VHost, ?MODULE, adhoc_local_items, 110),
++ ejabberd_hooks:add(adhoc_local_commands, VHost, ?MODULE, adhoc_local_commands, 110),
++ %ejabberd_hooks:add(adhoc_sm_items, VHost, ?MODULE, adhoc_sm_items, 110),
++ %ejabberd_hooks:add(adhoc_sm_commands, VHost, ?MODULE, adhoc_sm_commands, 110),
++
++ ?MYDEBUG("Added hooks for ~p", [VHost]),
++
++ ejabberd_ctl:register_commands(
++ VHost,
++ [{"rebuild_stats", "rebuild mod_logdb module stats for vhost"}],
++ ?MODULE, rebuild_stats),
++ Supported_backends = lists:flatmap(fun({Backend, _Opts}) ->
++ [atom_to_list(Backend), " "]
++ end, State#state.dbs),
++ ejabberd_ctl:register_commands(
++ VHost,
++ [{"copy_messages backend", "copy messages from backend to current backend. backends could be: " ++ Supported_backends }],
++ ?MODULE, copy_messages_ctl),
++ ?MYDEBUG("Registered commands for ~p", [VHost]),
++
++ NewState=State#state{monref = MonRef, backendPid=SPid, purgeRef=TrefPurge, pollRef=TrefPoll},
++ {noreply, NewState};
++ Rez ->
++ ?ERROR_MSG("Rez=~p", [Rez]),
++ timer:sleep(30000),
++ {stop, db_connection_failed, State}
++ end;
++% from timer:send_interval/2 (in start handle_info)
++handle_info(scheduled_purging, #state{vhost=VHost, purge_older_days=Days} = State) ->
++ ?MYDEBUG("Starting scheduled purging of old records for ~p", [VHost]),
++ spawn(?MODULE, purge_old_records, [VHost, integer_to_list(Days)]),
++ {noreply, State};
++% from timer:send_interval/2 (in start handle_info)
++handle_info(poll_users_settings, #state{dbmod=DBMod, vhost=VHost}=State) ->
++ {ok, DoLog} = DBMod:get_users_settings(VHost),
++ ?MYDEBUG("DoLog=~p", [DoLog]),
++ true = ets:delete_all_objects(ets_settings_table(VHost)),
++ ets:insert(ets_settings_table(VHost), DoLog),
++ {noreply, State};
++handle_info({'DOWN', _MonitorRef, process, _Pid, _Info}, State) ->
++ {stop, db_connection_dropped, State};
++handle_info({fetch_result, _, _}, State) ->
++ ?MYDEBUG("Got timed out mysql fetch result", []),
++ {noreply, State};
++handle_info(Info, State) ->
++ ?INFO_MSG("Got Info:~p, State:~p", [Info, State]),
++ {noreply, State}.
++
++terminate(db_connection_failed, _State) ->
++ ok;
++terminate(db_connection_dropped, State) ->
++ cleanup(State),
++ ok;
++terminate(_Reason, #state{monref=undefined} = State) ->
++ cleanup(State),
++ ok;
++terminate(Reason, #state{dbmod=DBMod, vhost=VHost, monref=MonRef, backendPid=Pid} = State) ->
++ ?INFO_MSG("Reason: ~p", [Reason]),
++ case erlang:is_process_alive(Pid) of
++ true ->
++ erlang:demonitor(MonRef, [flush]),
++ DBMod:stop(VHost);
++ false ->
++ ok
++ end,
++ cleanup(State),
++ ok.
++
++code_change(_OldVsn, State, _Extra) ->
++ {ok, State}.
++
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%
++% ejabberd_hooks callbacks
++%
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++% TODO: change to/from to list as sql stores it as list
++send_packet(Owner, Peer, P) ->
++ VHost = Owner#jid.lserver,
++ Proc = gen_mod:get_module_proc(VHost, ?PROCNAME),
++ gen_server:cast(Proc, {addlog, to, Owner, Peer, P}).
++
++offline_packet(Peer, Owner, P) ->
++ VHost = Owner#jid.lserver,
++ Proc = gen_mod:get_module_proc(VHost, ?PROCNAME),
++ gen_server:cast(Proc, {addlog, from, Owner, Peer, P}).
++
++receive_packet(_JID, Peer, Owner, P) ->
++ VHost = Owner#jid.lserver,
++ Proc = gen_mod:get_module_proc(VHost, ?PROCNAME),
++ gen_server:cast(Proc, {addlog, from, Owner, Peer, P}).
++
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%
++% ejabberdctl
++%
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++rebuild_stats(_Val, VHost, ["rebuild_stats"]) ->
++ Proc = gen_mod:get_module_proc(VHost, ?PROCNAME),
++ gen_server:cast(Proc, {rebuild_stats}),
++ {stop, ?STATUS_SUCCESS};
++rebuild_stats(Val, _VHost, _Args) ->
++ Val.
++
++copy_messages_ctl(_Val, VHost, ["copy_messages", Backend]) ->
++ Proc = gen_mod:get_module_proc(VHost, ?PROCNAME),
++ gen_server:cast(Proc, {copy_messages, Backend}),
++ {stop, ?STATUS_SUCCESS};
++copy_messages_ctl(_Val, VHost, ["copy_messages", Backend, Date]) ->
++ Proc = gen_mod:get_module_proc(VHost, ?PROCNAME),
++ gen_server:cast(Proc, {copy_messages, Backend, Date}),
++ {stop, ?STATUS_SUCCESS};
++copy_messages_ctl(Val, _VHost, _Args) ->
++ Val.
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%
++% misc operations
++%
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++
++% handle_cast({addlog, E}, _)
++% raw packet -> #msg
++packet_parse(Owner, Peer, Packet, Direction, State) ->
++ case xml:get_subtag(Packet, "body") of
++ false ->
++ ignore;
++ Body_xml ->
++ Message_type =
++ case xml:get_tag_attr_s("type", Packet) of
++ [] -> "normal";
++ MType -> MType
++ end,
++
++ case Message_type of
++ "groupchat" when State#state.groupchat == send, Direction == to ->
++ ok;
++ "groupchat" when State#state.groupchat == send, Direction == from ->
++ throw(ignore);
++ "groupchat" when State#state.groupchat == half ->
++ Rooms = ets:match(muc_online_room, '$1'),
++ Ni=lists:foldl(fun([{muc_online_room, {GName, GHost}, Pid}], Names) ->
++ case gen_fsm:sync_send_all_state_event(Pid, {get_jid_nick,Owner}) of
++ [] -> Names;
++ Nick ->
++ lists:append(Names, [jlib:jid_to_string({GName, GHost, Nick})])
++ end
++ end, [], Rooms),
++ case lists:member(jlib:jid_to_string(Peer), Ni) of
++ true when Direction == from ->
++ throw(ignore);
++ _ ->
++ ok
++ end;
++ "groupchat" when State#state.groupchat == none ->
++ throw(ignore);
++ _ ->
++ ok
++ end,
++
++ Message_body = xml:get_tag_cdata(Body_xml),
++ Message_subject =
++ case xml:get_subtag(Packet, "subject") of
++ false ->
++ "";
++ Subject_xml ->
++ xml:get_tag_cdata(Subject_xml)
++ end,
++
++ OwnerName = stringprep:tolower(Owner#jid.user),
++ PName = stringprep:tolower(Peer#jid.user),
++ PServer = stringprep:tolower(Peer#jid.server),
++ PResource = Peer#jid.resource,
++
++ #msg{timestamp=get_timestamp(),
++ owner_name=OwnerName,
++ peer_name=PName,
++ peer_server=PServer,
++ peer_resource=PResource,
++ direction=Direction,
++ type=Message_type,
++ subject=Message_subject,
++ body=Message_body}
++ end.
++
++% called from handle_cast({addlog, _}, _) -> true (log messages) | false (do not log messages)
++filter(Owner, Peer, State) ->
++ OwnerStr = Owner#jid.luser++"@"++Owner#jid.lserver,
++ OwnerServ = "@"++Owner#jid.lserver,
++ PeerStr = Peer#jid.luser++"@"++Peer#jid.lserver,
++ PeerServ = "@"++Peer#jid.lserver,
++
++ LogTo = case ets:match_object(ets_settings_table(State#state.vhost),
++ #user_settings{owner_name=Owner#jid.luser, _='_'}) of
++ [#user_settings{dolog_default=Default,
++ dolog_list=DLL,
++ donotlog_list=DNLL}] ->
++ A = lists:member(PeerStr, DLL),
++ B = lists:member(PeerStr, DNLL),
++ if
++ A -> true;
++ B -> false;
++ Default == true -> true;
++ Default == false -> false;
++ true -> State#state.dolog_default
++ end;
++ _ -> State#state.dolog_default
++ end,
++
++ lists:all(fun(O) -> O end,
++ [not lists:member(OwnerStr, State#state.ignore_jids),
++ not lists:member(PeerStr, State#state.ignore_jids),
++ not lists:member(OwnerServ, State#state.ignore_jids),
++ not lists:member(PeerServ, State#state.ignore_jids),
++ LogTo]).
++
++purge_old_records(VHost, Days) ->
++ Proc = gen_mod:get_module_proc(VHost, ?PROCNAME),
++
++ Dates = gen_server:call(Proc, {get_dates, {VHost}}),
++ DateNow = calendar:datetime_to_gregorian_seconds({date(), {0,0,1}}),
++ DateDiff = list_to_integer(Days)*24*60*60,
++ ?MYDEBUG("Purging tables older than ~s days", [Days]),
++ lists:foreach(fun(Date) ->
++ {ok, [Year, Month, Day]} = regexp:split(Date, "[^0-9]+"),
++ DateInSec = calendar:datetime_to_gregorian_seconds({{list_to_integer(Year), list_to_integer(Month), list_to_integer(Day)}, {0,0,1}}),
++ if
++ (DateNow - DateInSec) > DateDiff ->
++ gen_server:call(Proc, {delete_messages_at, Date});
++ true ->
++ ?MYDEBUG("Skipping messages at ~p", [Date])
++ end
++ end, Dates).
++
++% called from get_vhost_stats/2, get_user_stats/3
++sort_stats(Stats) ->
++ % Stats = [{"2003-4-15",1}, {"2006-8-18",1}, ... ]
++ CFun = fun({TableName, Count}) ->
++ {ok, [Year, Month, Day]} = regexp:split(TableName, "[^0-9]+"),
++ { calendar:datetime_to_gregorian_seconds({{list_to_integer(Year), list_to_integer(Month), list_to_integer(Day)}, {0,0,1}}), Count }
++ end,
++ % convert to [{63364377601,1}, {63360662401,1}, ... ]
++ CStats = lists:map(CFun, Stats),
<<Diff was trimmed, longer than 597 lines>>
More information about the pld-cvs-commit
mailing list