forked from calculate/calculate-overlay
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
266 lines
8.3 KiB
266 lines
8.3 KiB
diff -uNr ejabberd-2.0.2-beta1.ORIG/src/mod_logxml.erl ejabberd-2.0.2-beta1/src/mod_logxml.erl
|
|
--- mod_logxml.erl
|
|
+++ mod_logxml.erl
|
|
@@ -0,0 +1,261 @@
|
|
+%%%----------------------------------------------------------------------
|
|
+%%% File : mod_logxml.erl
|
|
+%%% Author : Badlop
|
|
+%%% Purpose : Log XMPP packets to XML file
|
|
+%%% Created :
|
|
+%%% Id :
|
|
+%%%----------------------------------------------------------------------
|
|
+
|
|
+-module(mod_logxml).
|
|
+-author('badlop@ono.com').
|
|
+
|
|
+-behaviour(gen_mod).
|
|
+
|
|
+-export([start/2, init/7, stop/1,
|
|
+ send_packet/3, receive_packet/4]).
|
|
+
|
|
+-include("ejabberd.hrl").
|
|
+-include("jlib.hrl").
|
|
+
|
|
+-define(PROCNAME, ejabberd_mod_logxml).
|
|
+
|
|
+%% -------------------
|
|
+%% Module control
|
|
+%% -------------------
|
|
+
|
|
+start(Host, Opts) ->
|
|
+ Logdir = gen_mod:get_opt(logdir, Opts, "/tmp/jabberlogs/"),
|
|
+
|
|
+ Rd = gen_mod:get_opt(rotate_days, Opts, 1),
|
|
+ Rf = case gen_mod:get_opt(rotate_megs, Opts, 10) of
|
|
+ no -> no;
|
|
+ Rf1 -> Rf1*1024*1024
|
|
+ end,
|
|
+ Rp = case gen_mod:get_opt(rotate_kpackets, Opts, 10) of
|
|
+ no -> no;
|
|
+ Rp1 -> Rp1*1000
|
|
+ end,
|
|
+ RotateO = {Rd, Rf, Rp},
|
|
+ CheckRKP = gen_mod:get_opt(check_rotate_kpackets, Opts, 1),
|
|
+
|
|
+ Timezone = gen_mod:get_opt(timezone, Opts, local),
|
|
+
|
|
+ Orientation = gen_mod:get_opt(orientation, Opts, [send, recv]),
|
|
+ Stanza = gen_mod:get_opt(stanza, Opts, [iq, message, presence, other]),
|
|
+ Direction = gen_mod:get_opt(direction, Opts, [internal, vhosts, external]),
|
|
+ FilterO = {
|
|
+ {orientation, Orientation},
|
|
+ {stanza, Stanza},
|
|
+ {direction, Direction}},
|
|
+ ShowIP = gen_mod:get_opt(show_ip, Opts, false),
|
|
+
|
|
+ ejabberd_hooks:add(user_send_packet, Host, ?MODULE, send_packet, 90),
|
|
+ ejabberd_hooks:add(user_receive_packet, Host, ?MODULE, receive_packet, 90),
|
|
+ register(gen_mod:get_module_proc(Host, ?PROCNAME),
|
|
+ spawn(?MODULE, init, [Host, Logdir, RotateO, CheckRKP,
|
|
+ Timezone, ShowIP, FilterO])).
|
|
+
|
|
+stop(Host) ->
|
|
+ ejabberd_hooks:delete(user_send_packet, Host, ?MODULE, send_packet, 90),
|
|
+ ejabberd_hooks:delete(user_receive_packet, Host, ?MODULE, receive_packet, 90),
|
|
+ Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
|
+ Proc ! stop,
|
|
+ {wait, Proc}.
|
|
+
|
|
+init(Host, Logdir, RotateO, CheckRKP, Timezone, ShowIP, FilterO) ->
|
|
+ {IoDevice, Filename, Gregorian_day} = open_file(Logdir, Host, Timezone),
|
|
+ loop(Host, IoDevice, Filename, Logdir, CheckRKP, RotateO, 0, Gregorian_day,
|
|
+ Timezone, ShowIP, FilterO).
|
|
+
|
|
+%% -------------------
|
|
+%% Main
|
|
+%% -------------------
|
|
+
|
|
+manage_rotate(Host, IoDevice, Filename, Logdir, RotateO, PacketC,
|
|
+ Gregorian_day_log, Timezone) ->
|
|
+ {RO_days, RO_size, RO_packets} = RotateO,
|
|
+
|
|
+ Rotate1 = case RO_packets of
|
|
+ no -> false;
|
|
+ PacketC -> true;
|
|
+ _ -> false
|
|
+ end,
|
|
+
|
|
+ Filesize = filelib:file_size(Filename),
|
|
+ Rotate2 = if
|
|
+ RO_size == no -> false;
|
|
+ Filesize >= RO_size -> true;
|
|
+ true -> false
|
|
+ end,
|
|
+
|
|
+ Gregorian_day_today = get_gregorian_day(),
|
|
+ Rotate3 = if
|
|
+ RO_days == no -> false;
|
|
+ (Gregorian_day_today - Gregorian_day_log) >= RO_days ->
|
|
+ true;
|
|
+ true -> false
|
|
+ end,
|
|
+
|
|
+ case lists:any(fun(E) -> E end, [Rotate1, Rotate2, Rotate3]) of
|
|
+ true ->
|
|
+ {IoDevice2, Filename2, Gregorian_day2} =
|
|
+ rotate_log(IoDevice, Logdir, Host, Timezone),
|
|
+ {IoDevice2, Filename2, Gregorian_day2, 0};
|
|
+ false ->
|
|
+ {IoDevice, Filename, Gregorian_day_log, PacketC+1}
|
|
+ end.
|
|
+
|
|
+filter(FilterO, E) ->
|
|
+ {{orientation, OrientationO},{stanza, StanzaO},{direction, DirectionO}} =
|
|
+ FilterO,
|
|
+ {Orientation, From, To, Packet} = E,
|
|
+
|
|
+ {xmlelement, Stanza_str, _Attrs, _Els} = Packet,
|
|
+ Stanza = list_to_atom(Stanza_str),
|
|
+
|
|
+ Hosts_all = ejabberd_config:get_global_option(hosts),
|
|
+ {Host_local, Host_remote} = case Orientation of
|
|
+ send -> {From#jid.lserver, To#jid.lserver};
|
|
+ recv -> {To#jid.lserver, From#jid.lserver}
|
|
+ end,
|
|
+ Direction = case Host_remote of
|
|
+ Host_local -> internal;
|
|
+ _ ->
|
|
+ case lists:member(Host_remote, Hosts_all) of
|
|
+ true -> vhosts;
|
|
+ false -> external
|
|
+ end
|
|
+ end,
|
|
+
|
|
+ {lists:all(fun(O) -> O end,
|
|
+ [lists:member(Orientation, OrientationO),
|
|
+ lists:member(Stanza, StanzaO),
|
|
+ lists:member(Direction, DirectionO)]),
|
|
+ {Orientation, Stanza, Direction}}.
|
|
+
|
|
+loop(Host, IoDevice, Filename, Logdir, CheckRKP, RotateO, PacketC,
|
|
+ Gregorian_day, Timezone, ShowIP, FilterO) ->
|
|
+ receive
|
|
+ {addlog, E} ->
|
|
+ {IoDevice3, Filename3, Gregorian_day3, PacketC3} =
|
|
+ case filter(FilterO, E) of
|
|
+ {true, OSD} ->
|
|
+ Div = PacketC/CheckRKP,
|
|
+ {IoDevice2, Filename2, Gregorian_day2, PacketC2} =
|
|
+ case Div==round(Div) of
|
|
+ true ->
|
|
+ manage_rotate(Host, IoDevice, Filename,
|
|
+ Logdir, RotateO, PacketC,
|
|
+ Gregorian_day, Timezone);
|
|
+ false ->
|
|
+ {IoDevice, Filename, Gregorian_day,
|
|
+ PacketC+1}
|
|
+ end,
|
|
+ add_log(IoDevice2, Timezone, ShowIP, E, OSD),
|
|
+ {IoDevice2, Filename2, Gregorian_day2, PacketC2};
|
|
+ _ ->
|
|
+ {IoDevice, Filename, Gregorian_day, PacketC}
|
|
+ end,
|
|
+ loop(Host, IoDevice3, Filename3, Logdir, CheckRKP, RotateO,
|
|
+ PacketC3, Gregorian_day3, Timezone, ShowIP, FilterO);
|
|
+ stop ->
|
|
+ close_file(IoDevice),
|
|
+ ok;
|
|
+ _ ->
|
|
+ loop(Host, IoDevice, Filename, Logdir, CheckRKP, RotateO, PacketC,
|
|
+ Gregorian_day, Timezone, ShowIP, FilterO)
|
|
+ end.
|
|
+
|
|
+send_packet(FromJID, ToJID, P) ->
|
|
+ Host = FromJID#jid.lserver,
|
|
+ Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
|
+ Proc ! {addlog, {send, FromJID, ToJID, P}}.
|
|
+
|
|
+receive_packet(_JID, From, To, P) ->
|
|
+ Host = To#jid.lserver,
|
|
+ Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
|
+ Proc ! {addlog, {recv, From, To, P}}.
|
|
+
|
|
+add_log(Io, Timezone, ShowIP, {Orientation, From, To, Packet}, _OSD) ->
|
|
+ %%{Orientation, Stanza, Direction} = OSD,
|
|
+ LocalJID = case Orientation of
|
|
+ send -> From;
|
|
+ recv -> To
|
|
+ end,
|
|
+ LocalIPS = case ShowIP of
|
|
+ true ->
|
|
+ {UserIP, _Port} = ejabberd_sm:get_user_ip(
|
|
+ LocalJID#jid.user,
|
|
+ LocalJID#jid.server,
|
|
+ LocalJID#jid.resource),
|
|
+ io_lib:format("lip=\"~s\" ", [inet_parse:ntoa(UserIP)]);
|
|
+ false -> ""
|
|
+ end,
|
|
+ TimestampISO = get_now_iso(Timezone),
|
|
+ io:fwrite(Io, "<packet or=\"~p\" ljid=\"~s\" ~sts=\"~s\">~s</packet>~n",
|
|
+ [Orientation, jlib:jid_to_string(LocalJID), LocalIPS,
|
|
+ TimestampISO, xml:element_to_string(Packet)]).
|
|
+
|
|
+%% -------------------
|
|
+%% File
|
|
+%% -------------------
|
|
+
|
|
+open_file(Logdir, Host, Timezone) ->
|
|
+ TimeStamp = get_now_iso(Timezone),
|
|
+ Year = string:substr(TimeStamp, 1, 4),
|
|
+ Month = string:substr(TimeStamp, 5, 2),
|
|
+ Day = string:substr(TimeStamp, 7, 2),
|
|
+ Hour = string:substr(TimeStamp, 10, 2),
|
|
+ Min = string:substr(TimeStamp, 13, 2),
|
|
+ Sec = string:substr(TimeStamp, 16, 2),
|
|
+ S = "-",
|
|
+ Logname = lists:flatten([Host,S,Year,S,Month,S,Day,S,Hour,S,Min,S,Sec,
|
|
+ ".xml"]),
|
|
+ Filename = filename:join([Logdir, Logname]),
|
|
+
|
|
+ Gregorian_day = get_gregorian_day(),
|
|
+
|
|
+ %% Open file, create if it does not exist, create parent dirs if needed
|
|
+ case file:read_file_info(Filename) of
|
|
+ {ok, _} ->
|
|
+ {ok, IoDevice} = file:open(Filename, [append]);
|
|
+ {error, enoent} ->
|
|
+ make_dir_rec(Logdir),
|
|
+ {ok, IoDevice} = file:open(Filename, [append]),
|
|
+ io:fwrite(IoDevice, "~s~n", ["<?xml version=\"1.0\"?>"]),
|
|
+ io:fwrite(IoDevice, "~s~n", ["<?xml-stylesheet href=\"xmpp.xsl\" type=\"text/xsl\"?>"]),
|
|
+ io:fwrite(IoDevice, "~s~n", ["<log>"])
|
|
+ end,
|
|
+ {IoDevice, Filename, Gregorian_day}.
|
|
+
|
|
+close_file(IoDevice) ->
|
|
+ io:fwrite(IoDevice, "~s~n", ["</log>"]),
|
|
+ file:close(IoDevice).
|
|
+
|
|
+rotate_log(IoDevice, Logdir, Host, Timezone) ->
|
|
+ close_file(IoDevice),
|
|
+ open_file(Logdir, Host, Timezone).
|
|
+
|
|
+make_dir_rec(Dir) ->
|
|
+ case file:read_file_info(Dir) of
|
|
+ {ok, _} ->
|
|
+ ok;
|
|
+ {error, enoent} ->
|
|
+ DirS = filename:split(Dir),
|
|
+ DirR = lists:sublist(DirS, length(DirS)-1),
|
|
+ make_dir_rec(filename:join(DirR)),
|
|
+ file:make_dir(Dir)
|
|
+ end.
|
|
+
|
|
+%% -------------------
|
|
+%% Utils
|
|
+%% -------------------
|
|
+
|
|
+get_gregorian_day() -> calendar:date_to_gregorian_days(date()).
|
|
+
|
|
+get_now_iso(Timezone) ->
|
|
+ TimeStamp = case Timezone of
|
|
+ local -> calendar:now_to_local_time(now());
|
|
+ universal -> calendar:now_to_universal_time(now())
|
|
+ end,
|
|
+ jlib:timestamp_to_iso(TimeStamp).
|