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