Import mod_post_log from 2.1.x branch
This commit is contained in:
parent
8b3a3b47a4
commit
b897489dab
|
@ -0,0 +1,2 @@
|
|||
{'../ejabberd-dev/src/gen_mod', [{outdir, "../ejabberd-dev/ebin"},{i,"../ejabberd-dev/include"}]}.
|
||||
{'src/mod_post_log', [{outdir, "ebin"},{i,"../ejabberd-dev/include"}]}.
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
erl -pa ../ejabberd-dev/ebin -pz ebin -make
|
|
@ -0,0 +1,157 @@
|
|||
%%%----------------------------------------------------------------------
|
||||
%%% File : mod_post_log.erl
|
||||
%%% Author : Tim Stewart <tim@stoo.org>
|
||||
%%% Purpose : POST user messages to server via HTTP
|
||||
%%% Created : 02 Aug 2014 by Tim Stewart <tim@stoo.org>
|
||||
%%%
|
||||
%%% Based on mod_service_log.erl
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
-module(mod_post_log).
|
||||
-author('tim@stoo.org').
|
||||
|
||||
-behaviour(gen_mod).
|
||||
|
||||
-export([start/2,
|
||||
stop/1,
|
||||
log_user_send/3,
|
||||
post_result/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("jlib.hrl").
|
||||
|
||||
start(Host, _Opts) ->
|
||||
ok = case inets:start() of
|
||||
{error, {already_started, inets}} ->
|
||||
ok;
|
||||
ok ->
|
||||
ok
|
||||
end,
|
||||
ejabberd_hooks:add(user_send_packet, Host,
|
||||
?MODULE, log_user_send, 50),
|
||||
ok.
|
||||
|
||||
stop(Host) ->
|
||||
ejabberd_hooks:delete(user_send_packet, Host,
|
||||
?MODULE, log_user_send, 50),
|
||||
ok.
|
||||
|
||||
log_user_send(From, To, Packet) ->
|
||||
ok = log_packet(From, To, Packet).
|
||||
|
||||
log_packet(From, To, {xmlelement, "message", _Attrs, _Els} = Packet) ->
|
||||
ok = log_message(From, To, Packet);
|
||||
|
||||
log_packet(_From, _To, {xmlelement, _Name, _Attrs, _Els}) ->
|
||||
ok.
|
||||
|
||||
log_message(From, To, {xmlelement, _Name, Attrs, _Els} = Packet) ->
|
||||
Type = lists:keyfind("type", 1, Attrs),
|
||||
log_message_filter(Type, From, To, Packet).
|
||||
|
||||
log_message_filter({"type", Type}, From, To, Packet)
|
||||
when Type =:= "chat";
|
||||
Type =:= "groupchat" ->
|
||||
log_chat(From, To, Packet);
|
||||
log_message_filter(_Other, _From, _To, _Packet) ->
|
||||
ok.
|
||||
|
||||
log_chat(From, To, {xmlelement, _Name, _Attrs, Els} = Packet) ->
|
||||
case get_body(Els) of
|
||||
no_body ->
|
||||
ok;
|
||||
{ok, _Body} ->
|
||||
log_chat_with_body(From, To, Packet)
|
||||
end.
|
||||
|
||||
log_chat_with_body(From, To, Packet) ->
|
||||
post_xml(From, To, xml:element_to_binary(Packet)).
|
||||
|
||||
post_xml(From, To, Xml) ->
|
||||
Ts = to_iso_8601_date(os:timestamp()),
|
||||
|
||||
Body = Xml,
|
||||
|
||||
Url = get_opt(url),
|
||||
TsHeader = get_opt(ts_header, "X-Message-Timestamp"),
|
||||
FromHeader = get_opt(from_header, "X-Message-From"),
|
||||
ToHeader = get_opt(to_header, "X-Message-To"),
|
||||
Headers = [ {TsHeader, Ts},
|
||||
{FromHeader, format_jid(From)},
|
||||
{ToHeader, format_jid(To)}
|
||||
| get_opt(headers, []) ],
|
||||
ContentType = get_opt(content_type, "text/xml"),
|
||||
HttpOptions = get_opt(http_options, []),
|
||||
ReqOptions = get_opt(req_options, []),
|
||||
|
||||
{ok, _ReqId} = httpc:request(post,
|
||||
{Url, Headers, ContentType, Body},
|
||||
HttpOptions,
|
||||
[ {sync, false},
|
||||
{receiver, {?MODULE, post_result, []}}
|
||||
| ReqOptions ]),
|
||||
ok.
|
||||
|
||||
post_result({_ReqId, {error, Reason}}) ->
|
||||
report_error([ {error, Reason } ]);
|
||||
post_result({_ReqId, Result}) ->
|
||||
{StatusLine, Headers, Body} = Result,
|
||||
{_HttpVersion, StatusCode, ReasonPhrase} = StatusLine,
|
||||
if StatusCode < 200;
|
||||
StatusCode > 299 ->
|
||||
ok = report_error([ {status_code, StatusCode},
|
||||
{reason_phrase, ReasonPhrase},
|
||||
{headers, Headers},
|
||||
{body, Body} ]),
|
||||
ok;
|
||||
true ->
|
||||
ok
|
||||
end.
|
||||
|
||||
get_body(Els) ->
|
||||
XmlElements = [ El || El <- Els, element(1, El) =:= xmlelement ],
|
||||
case lists:keyfind("body", 2, XmlElements) of
|
||||
false ->
|
||||
no_body;
|
||||
{xmlelement, "body", _, InnerEls} ->
|
||||
case lists:keyfind(xmlcdata, 1, InnerEls) of
|
||||
false ->
|
||||
no_body;
|
||||
{xmlcdata, Body} ->
|
||||
{ok, Body}
|
||||
end
|
||||
end.
|
||||
|
||||
get_opt(Opt) ->
|
||||
get_opt(Opt, undefined).
|
||||
|
||||
get_opt(Opt, Default) ->
|
||||
gen_mod:get_module_opt(global, ?MODULE, Opt, Default).
|
||||
|
||||
report_error(ReportArgs) ->
|
||||
ok = error_logger:error_report([ mod_post_log_cannot_post | ReportArgs ]).
|
||||
|
||||
format_jid(#jid{luser = User, lserver = Server, lresource = Resource})
|
||||
when Resource =:= undefined;
|
||||
Resource =:= "";
|
||||
Resource =:= <<"">> ->
|
||||
%% The guard above feels defensive, but I don't yet know the full
|
||||
%% set of ways that ejabberd will represent an empty resource
|
||||
io_lib:format("~s@~s", [User, Server]);
|
||||
format_jid(#jid{luser = User, lserver = Server, lresource = Resource}) ->
|
||||
io_lib:format("~s@~s/~s", [User, Server, Resource]).
|
||||
|
||||
%% Erlang now()-style timestamps are in UTC by definition, and we are
|
||||
%% assuming ISO 8601 dates should be printed in UTC as well, so no
|
||||
%% conversion necessary
|
||||
%%
|
||||
%% Example:
|
||||
%% {1385,388790,334905}
|
||||
%% -becomes-
|
||||
%% 2013-11-25 14:13:10.334905Z
|
||||
-spec to_iso_8601_date(erlang:timestamp()) -> string().
|
||||
to_iso_8601_date(Timestamp) when is_tuple(Timestamp) ->
|
||||
{{Y, Mo, D}, {H, M, S}} = calendar:now_to_universal_time(Timestamp),
|
||||
{_, _, US} = Timestamp,
|
||||
lists:flatten(io_lib:format("~4.10.0B-~2.10.0B-~2.10.0B ~2.10.0B:~2.10.0B:~2.10.0B.~6.10.0BZ",
|
||||
[Y, Mo, D, H, M, S, US])).
|
Loading…
Reference in New Issue