From 3dc4494ee184f033b21a992676f1935c174b2577 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 9 Feb 2017 11:22:17 +0300 Subject: [PATCH] Make mod_post_log working with ejabberd 16.12+ --- mod_post_log/src/mod_post_log.erl | 115 +++++++++++++----------------- 1 file changed, 50 insertions(+), 65 deletions(-) diff --git a/mod_post_log/src/mod_post_log.erl b/mod_post_log/src/mod_post_log.erl index 7ca981e..20e7770 100644 --- a/mod_post_log/src/mod_post_log.erl +++ b/mod_post_log/src/mod_post_log.erl @@ -14,11 +14,14 @@ -export([start/2, stop/1, - log_user_send/4, + depends/2, + mod_opt_type/1, + log_user_send/1, + log_user_send/4, post_result/1]). -include("ejabberd.hrl"). --include("jlib.hrl"). +-include("xmpp.hrl"). start(Host, _Opts) -> ok = case inets:start() of @@ -36,54 +39,57 @@ stop(Host) -> ?MODULE, log_user_send, 50), ok. -log_user_send(Packet, _C2SState, From, To) -> - ok = log_packet(From, To, Packet), +depends(_Host, _Opts) -> + []. + +mod_opt_type(url) -> fun iolist_to_binary/1; +mod_opt_type(ts_header) -> fun iolist_to_binary/1; +mod_opt_type(from_header) -> fun iolist_to_binary/1; +mod_opt_type(to_header) -> fun iolist_to_binary/1; +mod_opt_type(headers) -> fun(L) when is_list(L) -> L end; +mod_opt_type(content_type) -> fun iolist_to_binary/1; +mod_opt_type(req_options) -> fun(L) when is_list(L) -> L end; +mod_opt_type(_) -> + [url, ts_header, from_header, to_header, headers, + content_type, req_options]. + +%% TODO: remove log_user_send/4 after 17.02 is released +log_user_send(Packet, C2SState, From, To) -> + log_user_send({xmpp:set_from_to(Packet, From, To), C2SState}), Packet. -log_packet(From, To, #xmlel{name = <<"message">>} = Packet) -> - ok = log_message(From, To, Packet); +log_user_send({#message{type = T} = Packet, _C2SState} = Acc) + when T == chat; T == groupchat -> + ok = log_message(Packet), + Acc; +log_user_send(Acc) -> + Acc. -log_packet(_From, _To, _Packet) -> - ok. - -log_message(From, To, #xmlel{attrs = Attrs} = 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, #xmlel{children = Els} = Packet) -> - case get_body(Els) of - no_body -> - ok; - {ok, _Body} -> - log_chat_with_body(From, To, Packet) +log_message(#message{from = From, to = To, body = Body} = Msg) -> + case xmpp:get_text(Body) of + <<"">> -> + ok; + _ -> + XML = fxml:element_to_binary(xmpp:encode(Msg)), + post_xml(From, To, XML) end. -log_chat_with_body(From, To, Packet) -> - post_xml(From, To, fxml:element_to_binary(Packet)). - -post_xml(From, To, Xml) -> +post_xml(#jid{lserver = LServer} = 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"), + Url = get_opt(LServer, url), + TsHeader = get_opt(LServer, ts_header, "X-Message-Timestamp"), + FromHeader = get_opt(LServer, from_header, "X-Message-From"), + ToHeader = get_opt(LServer, 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, []), + | get_opt(LServer, headers, []) ], + ContentType = get_opt(LServer, content_type, "text/xml"), + HttpOptions = get_opt(LServer, http_options, []), + ReqOptions = get_opt(LServer, req_options, []), {ok, _ReqId} = httpc:request(post, {Url, Headers, ContentType, Body}, @@ -109,41 +115,20 @@ post_result({_ReqId, Result}) -> ok end. -get_body(Els) -> - XmlEls = [ El || El <- Els, is_record(El, xmlel) ], - case lists:keyfind(<<"body">>, #xmlel.name, XmlEls) of - false -> - no_body; - #xmlel{children = InnerEls} -> - case lists:keyfind(xmlcdata, 1, InnerEls) of - false -> - no_body; - {xmlcdata, Body} -> - {ok, Body} - end - end. +get_opt(LServer, Opt) -> + get_opt(LServer, Opt, undefined). -get_opt(Opt) -> - get_opt(Opt, undefined). - -get_opt(Opt, Default) -> +get_opt(LServer, Opt, Default) -> F = fun(Val) when is_binary(Val) -> binary_to_list(Val); (Val) -> Val end, - gen_mod:get_module_opt(global, ?MODULE, Opt, F, Default). + gen_mod:get_module_opt(LServer, ?MODULE, Opt, F, 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]). +format_jid(JID) -> + binary_to_list(jid:to_string(JID)). %% 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