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:[EMAIL PROTECTED] xmpp://[EMAIL PROTECTED]) ++%%% 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('[EMAIL PROTECTED]'). ++-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>> _______________________________________________ pld-cvs-commit mailing list [email protected] http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit
