Compare commits

...

21 Commits

Author SHA1 Message Date
Holger Weiss 8e43a20f12 mod_mam_mnesia: Never store error messages
Don't store messages of type "error", even if it has a <store/> hint.
2015-09-02 20:45:40 +02:00
Holger Weiss 91e4c56e67 mod_mam_mnesia: Check for <store/> hint
Respect the <store/> and <pretty-please-store/> hints.  Both tell the
server to store a message even if it would otherwise not be stored
(e.g., because it doesn't have a body).  These hints are not (yet) part
of XEP-0334, though.
2015-09-01 01:21:43 +02:00
Holger Weiss d7fd0f5d68 mod_mam_mnesia: Ignore whitespace within <value/>
Ignore the whitespace when a form field value is specified like this,
for example:

	<value>
	  juliet@example.com
	</value>
2015-08-19 21:46:13 +02:00
Holger Weiss f2652f613f mod_mam_mnesia: Also strip CDATA from <x/> element 2015-08-19 21:46:11 +02:00
Holger Weiss 3e683a7621 mod_mam_mnesia: Strip CDATA from form fields
Don't let mod_mam_mnesia stumble over additional whitespace when parsing
form fields.
2015-08-15 17:58:45 +02:00
Holger Weiss 92a44dfcda mod_mam_mnesia: Accept <encrypted/> messages
The <axolotl_message/> element has been renamed to <encrypted/>.
2015-08-07 15:39:59 +02:00
Holger Weiss 4feba7a5e6 mod_mam_mnesia: Also check for <no-store/> hint
Check for the <no-store/> and <no-permanent-store/> hints in addition to
<no-storage/> and <no-permanent-storage/>.  XEP-0334 (version 0.1)
mentions both variants, and unfortunately, both of them are in use.
2015-07-21 16:18:01 +02:00
Holger Weiss 7697756fb4 mod_mam_mnesia: Fix Axolotl message detection
The <axolotl_message/> element usually doesn't have CDATA content.
2015-07-20 21:58:24 +02:00
Holger Weiss 7e2eb9a578 mod_mam_mnesia: Also store Axolotl messages 2015-07-20 12:53:14 +02:00
Holger Weiss 1477a92b8a mod_statsdx: Recognize Monal and irssi-xmpp 2015-07-13 15:49:31 +02:00
Badlop 51ab9b2467 Detect session closing, not connection closing (thanks to Holger Weiß) 2015-07-13 15:49:28 +02:00
Holger Weiss 81d926142d Update mod_log_chat to work with ejabberd 15.06 2015-06-26 00:04:26 +02:00
Holger Weiss 1b726e3d9c Update mod_logxml to work with ejabberd 15.06 2015-06-26 00:04:26 +02:00
Holger Weiss 315d66868f Update mod_post_log to work with ejabberd 15.06 2015-06-26 00:04:26 +02:00
Holger Weiss f35d3021f6 Update mod_statsdx to work with ejabberd 15.06 2015-06-26 00:04:26 +02:00
Holger Weiss 1bc92c83d5 Update mod_message_log to work with ejabberd 15.06 2015-06-26 00:04:26 +02:00
Holger Weiss 9c17da232f Update mod_mam_mnesia to work with ejabberd 15.06 2015-06-26 00:04:26 +02:00
Holger Weiss e5d24089d2 Rename mod_mam to mod_mam_mnesia
Rename mod_mam so that users can continue to run it until we provide an
upgrade path to the mod_mam version shipped with ejabberd 15.06.
2015-06-26 00:02:57 +02:00
Holger Weiss e0557b9e26 Advertise feature in disco info for account JID
As per XEP-0313 >= 0.2, advertise the MAM feature in the service
discovery information for the bare account JID.

Some clients check the server's discovery information instead, so we'll
continue to advertise the feature there as well (at least for the
moment).
2015-04-26 17:17:21 +02:00
Holger Weiss 316bac7b8a Revert "mod_mam: Don't route error bounces to clients"
This reverts commit 8b1eead24b.

As of ejabberd 15.04, the session manager won't deliver error messages
that were sent to bare JIDs anymore, so MAM error messages should no
longer arrive.  Also, the 'c2s_filter_packet_in' hook no longer exists.
2015-04-09 21:59:18 +02:00
Holger Weiss 7c55651da7 Update jlib header from ejabberd master 2015-03-21 20:49:04 +01:00
14 changed files with 147 additions and 124 deletions

View File

@ -471,10 +471,10 @@
-type(iq() :: iq_request() | iq_reply()). -type(iq() :: iq_request() | iq_reply()).
-record(rsm_in, {max :: integer(), -record(rsm_in, {max :: integer() | error,
direction :: before | aft, direction :: before | aft,
id :: binary(), id :: binary(),
index :: integer()}). index :: integer() | error}).
-record(rsm_out, {count :: integer(), -record(rsm_out, {count :: integer(),
index :: integer(), index :: integer(),

View File

@ -13,8 +13,8 @@
-export([start/2, -export([start/2,
init/1, init/1,
stop/1, stop/1,
log_packet_send/3, log_packet_send/4,
log_packet_receive/4]). log_packet_receive/5]).
-define(LAGER, 1). -define(LAGER, 1).
@ -75,13 +75,15 @@ stop(Host) ->
gen_mod:get_module_proc(Host, ?PROCNAME) ! stop, gen_mod:get_module_proc(Host, ?PROCNAME) ! stop,
ok. ok.
log_packet_send(From, To, Packet) -> log_packet_send(Packet, _C2SState, From, To) ->
log_packet(From, To, Packet, From#jid.lserver). log_packet(From, To, Packet, From#jid.lserver),
Packet.
log_packet_receive(_JID, From, To, _Packet) when From#jid.lserver == To#jid.lserver-> log_packet_receive(Packet, _C2SState, _JID, From, To) when From#jid.lserver == To#jid.lserver->
ok; % only log at send time if the message is local to the server Packet; % only log at send time if the message is local to the server
log_packet_receive(_JID, From, To, Packet) -> log_packet_receive(Packet, _C2SState, _JID, From, To) ->
log_packet(From, To, Packet, To#jid.lserver). log_packet(From, To, Packet, To#jid.lserver),
Packet.
log_packet(From, To, Packet = #xmlel{name = <<"message">>, attrs = Attrs}, Host) -> log_packet(From, To, Packet = #xmlel{name = <<"message">>, attrs = Attrs}, Host) ->
case xml:get_attr_s(<<"type">>, Attrs) of case xml:get_attr_s(<<"type">>, Attrs) of

View File

@ -12,7 +12,7 @@
-behaviour(gen_mod). -behaviour(gen_mod).
-export([start/2, init/7, stop/1, -export([start/2, init/7, stop/1,
send_packet/3, receive_packet/4]). send_packet/4, receive_packet/5]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
-include("jlib.hrl"). -include("jlib.hrl").
@ -166,15 +166,17 @@ loop(Host, IoDevice, Filename, Logdir, CheckRKP, RotateO, PacketC,
Gregorian_day, Timezone, ShowIP, FilterO) Gregorian_day, Timezone, ShowIP, FilterO)
end. end.
send_packet(FromJID, ToJID, P) -> send_packet(P, _C2SState, FromJID, ToJID) ->
Host = FromJID#jid.lserver, Host = FromJID#jid.lserver,
Proc = gen_mod:get_module_proc(Host, ?PROCNAME), Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
Proc ! {addlog, {send, FromJID, ToJID, P}}. Proc ! {addlog, {send, FromJID, ToJID, P}},
P.
receive_packet(_JID, From, To, P) -> receive_packet(P, _C2SState, _JID, From, To) ->
Host = To#jid.lserver, Host = To#jid.lserver,
Proc = gen_mod:get_module_proc(Host, ?PROCNAME), Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
Proc ! {addlog, {recv, From, To, P}}. Proc ! {addlog, {recv, From, To, P}},
P.
add_log(Io, Timezone, ShowIP, {Orientation, From, To, Packet}, _OSD) -> add_log(Io, Timezone, ShowIP, {Orientation, From, To, Packet}, _OSD) ->
%%{Orientation, Stanza, Direction} = OSD, %%{Orientation, Stanza, Direction} = OSD,

View File

@ -1,4 +1,4 @@
{'../ejabberd-dev/src/gen_mod', [{outdir, "../ejabberd-dev/ebin"}, {i, "../ejabberd-dev/include"}]}. {'../ejabberd-dev/src/gen_mod', [{outdir, "../ejabberd-dev/ebin"}, {i, "../ejabberd-dev/include"}]}.
{'../ejabberd-dev/src/lager_transform', [{outdir, "../ejabberd-dev/ebin"}, {i, "../ejabberd-dev/include"}]}. {'../ejabberd-dev/src/lager_transform', [{outdir, "../ejabberd-dev/ebin"}, {i, "../ejabberd-dev/include"}]}.
{'../ejabberd-dev/src/lager_util', [{outdir, "../ejabberd-dev/ebin"}, {i, "../ejabberd-dev/include"}]}. {'../ejabberd-dev/src/lager_util', [{outdir, "../ejabberd-dev/ebin"}, {i, "../ejabberd-dev/include"}]}.
{'src/mod_mam', [{outdir, "ebin"}, {i, "../ejabberd-dev/include"}, {d, 'LAGER'}]}. {'src/mod_mam_mnesia', [{outdir, "ebin"}, {i, "../ejabberd-dev/include"}, {d, 'LAGER'}]}.

View File

@ -1,5 +1,5 @@
mod_mam - Message Archive Management (XEP-0313) mod_mam_mnesia - Message Archive Management (XEP-0313)
Author: Holger Weiss <holger@zedat.fu-berlin.de> Author: Holger Weiss <holger@zedat.fu-berlin.de>
Requirements: ejabberd 14.12 or newer Requirements: ejabberd 14.12 or newer
@ -19,7 +19,7 @@ synchronization of multiple clients.
In order to use this module with the default settings, add the following In order to use this module with the default settings, add the following
line to the 'modules' section of your ejabberd.yml file: line to the 'modules' section of your ejabberd.yml file:
mod_mam: {} mod_mam_mnesia: {}
The configurable options are: The configurable options are:

View File

@ -1,5 +1,5 @@
Feature requests for mod_mam Feature requests for mod_mam_mnesia
- Add ODBC support. - Add ODBC support.
- Support archiving preferences (XEP-0313, section 6). - Support archiving preferences (XEP-0313, section 6).

View File

@ -1,5 +1,5 @@
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
%%% File : mod_mam.erl %%% File : mod_mam_mnesia.erl
%%% Author : Holger Weiss <holger@zedat.fu-berlin.de> %%% Author : Holger Weiss <holger@zedat.fu-berlin.de>
%%% Purpose : Message Archive Management (XEP-0313) %%% Purpose : Message Archive Management (XEP-0313)
%%% Created : 25 Jan 2015 by Holger Weiss <holger@zedat.fu-berlin.de> %%% Created : 25 Jan 2015 by Holger Weiss <holger@zedat.fu-berlin.de>
@ -23,7 +23,7 @@
%%% %%%
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
-module(mod_mam). -module(mod_mam_mnesia).
-author('holger@zedat.fu-berlin.de'). -author('holger@zedat.fu-berlin.de').
-define(NS_MAM, <<"urn:xmpp:mam:0">>). -define(NS_MAM, <<"urn:xmpp:mam:0">>).
@ -50,10 +50,10 @@
code_change/3]). code_change/3]).
%% ejabberd_hooks callbacks. %% ejabberd_hooks callbacks.
-export([receive_stanza/4, -export([disco_features/5,
send_stanza/3, receive_stanza/5,
remove_user/2, send_stanza/4,
drop_mam_error/4]). remove_user/2]).
%% gen_iq_handler callback. %% gen_iq_handler callback.
-export([handle_iq/3]). -export([handle_iq/3]).
@ -158,7 +158,9 @@ start(Host, Opts) ->
parallel), parallel),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_MAM, ?MODULE, gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_MAM, ?MODULE,
handle_iq, IQDisc), handle_iq, IQDisc),
%% Set up MAM feature announcement.
mod_disco:register_feature(Host, ?NS_MAM), mod_disco:register_feature(Host, ?NS_MAM),
ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, disco_features, 50),
%% Set up message storage process. %% Set up message storage process.
Proc = gen_mod:get_module_proc(Host, ?PROCNAME), Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
Spec = {Proc, {?MODULE, start_link, [Host, Opts]}, permanent, 3000, worker, Spec = {Proc, {?MODULE, start_link, [Host, Opts]}, permanent, 3000, worker,
@ -168,6 +170,8 @@ start(Host, Opts) ->
-spec stop(binary()) -> ok. -spec stop(binary()) -> ok.
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, disco_features, 50),
%% Stop message storage process.
Proc = gen_mod:get_module_proc(Host, ?PROCNAME), Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
ok = supervisor:terminate_child(ejabberd_sup, Proc), ok = supervisor:terminate_child(ejabberd_sup, Proc),
ok = supervisor:delete_child(ejabberd_sup, Proc). ok = supervisor:delete_child(ejabberd_sup, Proc).
@ -202,8 +206,6 @@ init({Host, Opts}) ->
remove_user, 50), remove_user, 50),
ejabberd_hooks:add(anonymous_purge_hook, Host, ?MODULE, ejabberd_hooks:add(anonymous_purge_hook, Host, ?MODULE,
remove_user, 50), remove_user, 50),
ejabberd_hooks:add(c2s_filter_packet_in, Host, ?MODULE,
drop_mam_error, 50),
AccessMaxMsgs = AccessMaxMsgs =
gen_mod:get_opt(access_max_user_messages, Opts, gen_mod:get_opt(access_max_user_messages, Opts,
fun(A) when is_atom(A) -> A end, max_user_mam_messages), fun(A) when is_atom(A) -> A end, max_user_mam_messages),
@ -249,9 +251,7 @@ terminate(Reason, #state{host = Host}) ->
ejabberd_hooks:delete(remove_user, Host, ?MODULE, ejabberd_hooks:delete(remove_user, Host, ?MODULE,
remove_user, 50), remove_user, 50),
ejabberd_hooks:delete(anonymous_purge_hook, Host, ?MODULE, ejabberd_hooks:delete(anonymous_purge_hook, Host, ?MODULE,
remove_user, 50), remove_user, 50).
ejabberd_hooks:delete(c2s_filter_packet_in, Host, ?MODULE,
drop_mam_error, 50).
-spec code_change({down, _} | _, state(), _) -> {ok, state()}. -spec code_change({down, _} | _, state(), _) -> {ok, state()}.
@ -263,10 +263,21 @@ code_change(_OldVsn, #state{host = Host} = State, _Extra) ->
%% ejabberd_hooks callbacks. %% ejabberd_hooks callbacks.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec receive_stanza(jid(), jid(), jid(), xmlel()) -> ok. -spec disco_features(empty | {result, [binary()]}, jid(), jid(), binary(),
binary()) -> {result, [binary()]}.
receive_stanza(#jid{luser = U, lserver = S} = JID, From, To, disco_features(empty, From, To, Node, Lang) ->
#xmlel{name = <<"message">>} = Stanza) -> disco_features({result, []}, From, To, Node, Lang);
disco_features({result, OtherFeatures},
#jid{luser = U, lserver = S},
#jid{luser = U, lserver = S}, <<"">>, _Lang) ->
{result, OtherFeatures ++ [?NS_MAM]};
disco_features(Acc, _From, _To, _Node, _Lang) -> Acc.
-spec receive_stanza(xmlel(), term(), jid(), jid(), jid()) -> xmlel().
receive_stanza(#xmlel{name = <<"message">>} = Stanza, _C2SState,
#jid{luser = U, lserver = S} = JID, From, To) ->
case is_desired(incoming, JID, To, Stanza) of case is_desired(incoming, JID, To, Stanza) of
true -> true ->
Proc = gen_mod:get_module_proc(S, ?PROCNAME), Proc = gen_mod:get_module_proc(S, ?PROCNAME),
@ -277,15 +288,15 @@ receive_stanza(#jid{luser = U, lserver = S} = JID, From, To,
?GEN_SERVER:cast(Proc, {store, {U, S}, Msg}); ?GEN_SERVER:cast(Proc, {store, {U, S}, Msg});
false -> false ->
?DEBUG("Won't archive undesired incoming stanza for ~s", ?DEBUG("Won't archive undesired incoming stanza for ~s",
[jlib:jid_to_string(To)]), [jlib:jid_to_string(To)])
ok end,
end; Stanza;
receive_stanza(_JID, _From, _To, _Stanza) -> ok. receive_stanza(Stanza, _C2SState, _JID, _From, _To) -> Stanza.
-spec send_stanza(jid(), jid(), xmlel()) -> ok. -spec send_stanza(xmlel(), term(), jid(), jid()) -> xmlel().
send_stanza(#jid{luser = U, lserver = S} = From, To, send_stanza(#xmlel{name = <<"message">>} = Stanza, _C2SState,
#xmlel{name = <<"message">>} = Stanza) -> #jid{luser = U, lserver = S} = From, To) ->
case is_desired(outgoing, From, To, Stanza) of case is_desired(outgoing, From, To, Stanza) of
true -> true ->
Proc = gen_mod:get_module_proc(S, ?PROCNAME), Proc = gen_mod:get_module_proc(S, ?PROCNAME),
@ -296,10 +307,10 @@ send_stanza(#jid{luser = U, lserver = S} = From, To,
?GEN_SERVER:cast(Proc, {store, {U, S}, Msg}); ?GEN_SERVER:cast(Proc, {store, {U, S}, Msg});
false -> false ->
?DEBUG("Won't archive undesired outgoing stanza from ~s", ?DEBUG("Won't archive undesired outgoing stanza from ~s",
[jlib:jid_to_string(From)]), [jlib:jid_to_string(From)])
ok end,
end; Stanza;
send_stanza(_From, _To, _Stanza) -> ok. send_stanza(Stanza, _C2SState, _From, _To) -> Stanza.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Check whether stanza should be stored. %% Check whether stanza should be stored.
@ -308,24 +319,18 @@ send_stanza(_From, _To, _Stanza) -> ok.
-spec is_desired(route(), jid(), jid(), xmlel()) -> boolean(). -spec is_desired(route(), jid(), jid(), xmlel()) -> boolean().
is_desired(Route, JID, To, Message) -> is_desired(Route, JID, To, Message) ->
is_chat_or_normal_message(Message) andalso looks_interesting(Message) andalso
has_non_empty_body(Message) andalso not has_no_store_hint(Message) andalso
not has_no_storage_hint(Message) andalso
not is_bare_copy(Route, JID, To) andalso not is_bare_copy(Route, JID, To) andalso
not is_resent(Message). not is_resent(Message).
-spec is_chat_or_normal_message(xmlel()) -> boolean(). -spec looks_interesting(xmlel()) -> boolean().
is_chat_or_normal_message(#xmlel{name = <<"message">>} = Message) -> looks_interesting(Message) ->
case message_type(Message) of Type = message_type(Message),
<<"chat">> -> (is_chat_or_normal(Type) andalso has_non_empty_body(Message))
true; orelse
<<"normal">> -> (has_store_hint(Message) andalso not is_error(Type)).
true;
_ ->
false
end;
is_chat_or_normal_message(_Message) -> false.
-spec message_type(xmlel()) -> binary(). -spec message_type(xmlel()) -> binary().
@ -337,16 +342,40 @@ message_type(#xmlel{attrs = Attrs}) ->
<<"normal">> <<"normal">>
end. end.
-spec is_chat_or_normal(binary()) -> boolean().
is_chat_or_normal(<<"chat">>) -> true;
is_chat_or_normal(<<"normal">>) -> true;
is_chat_or_normal(_Type) -> false.
-spec is_error(binary()) -> boolean().
is_error(<<"error">>) -> true;
is_error(_Type) -> false.
-spec has_non_empty_body(xmlel()) -> boolean(). -spec has_non_empty_body(xmlel()) -> boolean().
has_non_empty_body(Message) -> has_non_empty_body(Message) ->
xml:get_subtag_cdata(Message, <<"body">>) =/= <<"">>. xml:get_subtag_cdata(Message, <<"body">>) =/= <<"">> orelse
xml:get_subtag(Message, <<"encrypted">>) =/= false.
-spec has_no_storage_hint(xmlel()) -> boolean(). -spec has_store_hint(xmlel()) -> boolean().
has_no_storage_hint(Message) -> has_store_hint(Message) ->
xml:get_subtag_with_xmlns(Message, <<"store">>, ?NS_HINTS)
=/= false orelse
xml:get_subtag_with_xmlns(Message, <<"pretty-please-store">>, ?NS_HINTS)
=/= false.
-spec has_no_store_hint(xmlel()) -> boolean().
has_no_store_hint(Message) ->
xml:get_subtag_with_xmlns(Message, <<"no-store">>, ?NS_HINTS)
=/= false orelse
xml:get_subtag_with_xmlns(Message, <<"no-storage">>, ?NS_HINTS) xml:get_subtag_with_xmlns(Message, <<"no-storage">>, ?NS_HINTS)
=/= false orelse =/= false orelse
xml:get_subtag_with_xmlns(Message, <<"no-permanent-store">>, ?NS_HINTS)
=/= false orelse
xml:get_subtag_with_xmlns(Message, <<"no-permanent-storage">>, ?NS_HINTS) xml:get_subtag_with_xmlns(Message, <<"no-permanent-storage">>, ?NS_HINTS)
=/= false. =/= false.
@ -709,21 +738,25 @@ parse_request(Host, Query) ->
parse_form(#xmlel{} = Query) -> parse_form(#xmlel{} = Query) ->
case xml:get_subtag_with_xmlns(Query, <<"x">>, ?NS_XDATA) of case xml:get_subtag_with_xmlns(Query, <<"x">>, ?NS_XDATA) of
#xmlel{children = Fields} -> #xmlel{children = Fields} ->
parse_form(Fields); parse_form(xml:remove_cdata(Fields));
false -> false ->
#mam_filter{} #mam_filter{}
end; end;
parse_form(Fields) when is_list(Fields) -> parse_form(Fields) when is_list(Fields) ->
StripCData =
fun(#xmlel{children = Els} = Field) ->
Field#xmlel{children = xml:remove_cdata(Els)}
end,
Parse = Parse =
fun(#xmlel{name = <<"field">>, fun(#xmlel{name = <<"field">>,
attrs = Attrs, attrs = Attrs,
children = [#xmlel{name = <<"value">>, children = [Value]}]}, children = [#xmlel{name = <<"value">>, children = Els}]},
Form) -> Form) ->
case xml:get_attr_s(<<"var">>, Attrs) of case xml:get_attr_s(<<"var">>, Attrs) of
<<"FORM_TYPE">> -> <<"FORM_TYPE">> ->
Form; Form;
<<"start">> -> <<"start">> ->
CData = xml:get_cdata([Value]), CData = get_cdata_without_whitespace(Els),
case jlib:datetime_string_to_timestamp(CData) of case jlib:datetime_string_to_timestamp(CData) of
undefined -> undefined ->
Form#mam_filter{start = error}; Form#mam_filter{start = error};
@ -731,7 +764,7 @@ parse_form(Fields) when is_list(Fields) ->
Form#mam_filter{start = Start} Form#mam_filter{start = Start}
end; end;
<<"end">> -> <<"end">> ->
CData = xml:get_cdata([Value]), CData = get_cdata_without_whitespace(Els),
case jlib:datetime_string_to_timestamp(CData) of case jlib:datetime_string_to_timestamp(CData) of
undefined -> undefined ->
Form#mam_filter{fin = error}; Form#mam_filter{fin = error};
@ -739,7 +772,7 @@ parse_form(Fields) when is_list(Fields) ->
Form#mam_filter{fin = End} Form#mam_filter{fin = End}
end; end;
<<"with">> -> <<"with">> ->
CData = xml:get_cdata([Value]), CData = get_cdata_without_whitespace(Els),
case jlib:string_to_jid(CData) of case jlib:string_to_jid(CData) of
error -> error ->
Form#mam_filter{with = error}; Form#mam_filter{with = error};
@ -754,7 +787,7 @@ parse_form(Fields) when is_list(Fields) ->
?DEBUG("Got unexpected form element: ~p", [El]), ?DEBUG("Got unexpected form element: ~p", [El]),
Form Form
end, end,
lists:foldl(Parse, #mam_filter{}, Fields). lists:foldl(Parse, #mam_filter{}, lists:map(StripCData, Fields)).
-spec get_page_size_conf(binary()) -> mam_page_size_conf(). -spec get_page_size_conf(binary()) -> mam_page_size_conf().
@ -836,6 +869,12 @@ check_request(#mam_query{index = Index, filter = Filter})
check_request(_Query) -> check_request(_Query) ->
ok. ok.
-spec get_cdata_without_whitespace([xmlel() | cdata()]) -> binary().
get_cdata_without_whitespace(Els) ->
CData = xml:get_cdata(Els),
re:replace(CData, <<"[[:space:]]">>, <<"">>, [global, {return, binary}]).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Send responses. %% Send responses.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
@ -1265,33 +1304,3 @@ remove_user(LUser, LServer, mnesia) ->
end, end,
{atomic, ok} = mnesia:sync_transaction(Remove), {atomic, ok} = mnesia:sync_transaction(Remove),
manage_mnesia_fragments(true). manage_mnesia_fragments(true).
%%--------------------------------------------------------------------
%% Drop MAM error bounces.
%%--------------------------------------------------------------------
drop_mam_error(#xmlel{name = <<"message">>, attrs = Attrs} = Message, _JID,
From, #jid{lresource = <<"">>} = To) ->
case xml:get_attr_s(<<"type">>, Attrs) of
<<"error">> ->
case xml:get_subtag_with_xmlns(Message, <<"result">>, ?NS_MAM) of
#xmlel{} ->
?DEBUG("Dropping MAM result error message from ~s to ~s",
[jlib:jid_to_string(From),
jlib:jid_to_string(To)]),
drop;
false ->
case xml:get_subtag_with_xmlns(Message, <<"fin">>, ?NS_MAM) of
#xmlel{} ->
?DEBUG("Dropping MAM fin error message from ~s to ~s",
[jlib:jid_to_string(From),
jlib:jid_to_string(To)]),
drop;
false ->
Message
end
end;
_ ->
Message
end;
drop_mam_error(Acc, _JID, _From, _To) -> Acc.

View File

@ -25,8 +25,8 @@
code_change/3]). code_change/3]).
%% ejabberd_hooks callbacks. %% ejabberd_hooks callbacks.
-export([log_packet_send/3, -export([log_packet_send/4,
log_packet_receive/4, log_packet_receive/5,
log_packet_offline/3, log_packet_offline/3,
reopen_log/0]). reopen_log/0]).
@ -140,15 +140,17 @@ code_change(_OldVsn, State, _Extra) ->
%% ejabberd_hooks callbacks. %% ejabberd_hooks callbacks.
%% ------------------------------------------------------------------- %% -------------------------------------------------------------------
-spec log_packet_send(jid(), jid(), xmlel()) -> any(). -spec log_packet_send(xmlel(), term(), jid(), jid()) -> xmlel().
log_packet_send(From, To, Packet) -> log_packet_send(Packet, _C2SState, From, To) ->
log_packet(outgoing, From, To, Packet). log_packet(outgoing, From, To, Packet),
Packet.
-spec log_packet_receive(jid(), jid(), jid(), xmlel()) -> any(). -spec log_packet_receive(xmlel(), term(), jid(), jid(), jid()) -> xmlel().
log_packet_receive(JID, From, _To, Packet) -> log_packet_receive(Packet, _C2SState, JID, From, _To) ->
log_packet(incoming, From, JID, Packet). log_packet(incoming, From, JID, Packet),
Packet.
-spec log_packet_offline(jid(), jid(), xmlel()) -> any(). -spec log_packet_offline(jid(), jid(), xmlel()) -> any().

View File

@ -14,7 +14,7 @@
-export([start/2, -export([start/2,
stop/1, stop/1,
log_user_send/3, log_user_send/4,
post_result/1]). post_result/1]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
@ -36,8 +36,9 @@ stop(Host) ->
?MODULE, log_user_send, 50), ?MODULE, log_user_send, 50),
ok. ok.
log_user_send(From, To, Packet) -> log_user_send(Packet, _C2SState, From, To) ->
ok = log_packet(From, To, Packet). ok = log_packet(From, To, Packet),
Packet.
log_packet(From, To, #xmlel{name = <<"message">>} = Packet) -> log_packet(From, To, #xmlel{name = <<"message">>} = Packet) ->
ok = log_message(From, To, Packet); ok = log_message(From, To, Packet);

View File

@ -22,9 +22,10 @@
web_menu_node/3, web_page_node/5, web_menu_node/3, web_page_node/5,
web_menu_host/3, web_page_host/3, web_menu_host/3, web_page_host/3,
%% Hooks %% Hooks
register_user/2, remove_user/2, user_send_packet/3, register_user/2, remove_user/2, user_send_packet/4,
user_send_packet_traffic/3, user_receive_packet_traffic/4, user_send_packet_traffic/4, user_receive_packet_traffic/5,
user_login/1, user_logout/4, user_logout_sm/3]). %%user_logout_sm/3,
user_login/1, user_logout/4]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
-include("ejabberd_commands.hrl"). -include("ejabberd_commands.hrl").
@ -169,8 +170,8 @@ prepare_stats_host(Host, Hooks, CD) ->
ejabberd_hooks:add(register_user, Host, ?MODULE, register_user, 90), ejabberd_hooks:add(register_user, Host, ?MODULE, register_user, 90),
ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 90), ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 90),
ejabberd_hooks:add(user_available_hook, Host, ?MODULE, user_login, 90), ejabberd_hooks:add(user_available_hook, Host, ?MODULE, user_login, 90),
%%ejabberd_hooks:add(unset_presence_hook, Host, ?MODULE, user_logout, 90), ejabberd_hooks:add(unset_presence_hook, Host, ?MODULE, user_logout, 90),
ejabberd_hooks:add(sm_remove_connection_hook, Host, ?MODULE, user_logout_sm, 90), %%ejabberd_hooks:add(sm_remove_connection_hook, Host, ?MODULE, user_logout_sm, 90),
ejabberd_hooks:add(user_send_packet, Host, ?MODULE, user_send_packet, 90); ejabberd_hooks:add(user_send_packet, Host, ?MODULE, user_send_packet, 90);
traffic -> traffic ->
ejabberd_hooks:add(user_receive_packet, Host, ?MODULE, user_receive_packet_traffic, 92), ejabberd_hooks:add(user_receive_packet, Host, ?MODULE, user_receive_packet_traffic, 92),
@ -178,7 +179,8 @@ prepare_stats_host(Host, Hooks, CD) ->
ejabberd_hooks:add(register_user, Host, ?MODULE, register_user, 90), ejabberd_hooks:add(register_user, Host, ?MODULE, register_user, 90),
ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 90), ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 90),
ejabberd_hooks:add(user_available_hook, Host, ?MODULE, user_login, 90), ejabberd_hooks:add(user_available_hook, Host, ?MODULE, user_login, 90),
ejabberd_hooks:add(sm_remove_connection_hook, Host, ?MODULE, user_logout_sm, 90), ejabberd_hooks:add(unset_presence_hook, Host, ?MODULE, user_logout, 90),
%%ejabberd_hooks:add(sm_remove_connection_hook, Host, ?MODULE, user_logout_sm, 90),
ejabberd_hooks:add(user_send_packet, Host, ?MODULE, user_send_packet, 90); ejabberd_hooks:add(user_send_packet, Host, ?MODULE, user_send_packet, 90);
false -> false ->
ok ok
@ -196,8 +198,8 @@ finish_stats() ->
finish_stats(Host) -> finish_stats(Host) ->
ejabberd_hooks:delete(user_available_hook, Host, ?MODULE, user_login, 90), ejabberd_hooks:delete(user_available_hook, Host, ?MODULE, user_login, 90),
%%ejabberd_hooks:delete(unset_presence_hook, Host, ?MODULE, user_logout, 90), ejabberd_hooks:delete(unset_presence_hook, Host, ?MODULE, user_logout, 90),
ejabberd_hooks:delete(sm_remove_connection_hook, Host, ?MODULE, user_logout_sm, 90), %%ejabberd_hooks:delete(sm_remove_connection_hook, Host, ?MODULE, user_logout_sm, 90),
ejabberd_hooks:delete(user_send_packet, Host, ?MODULE, user_send_packet, 90), ejabberd_hooks:delete(user_send_packet, Host, ?MODULE, user_send_packet, 90),
ejabberd_hooks:delete(user_send_packet, Host, ?MODULE, user_send_packet_traffic, 92), ejabberd_hooks:delete(user_send_packet, Host, ?MODULE, user_send_packet_traffic, 92),
ejabberd_hooks:delete(user_receive_packet, Host, ?MODULE, user_receive_packet_traffic, 92), ejabberd_hooks:delete(user_receive_packet, Host, ?MODULE, user_receive_packet_traffic, 92),
@ -224,14 +226,15 @@ remove_user(_User, Host) ->
ets:update_counter(TableHost, {remove_user, Host}, 1), ets:update_counter(TableHost, {remove_user, Host}, 1),
ets:update_counter(TableServer, {remove_user, server}, 1). ets:update_counter(TableServer, {remove_user, server}, 1).
user_send_packet(FromJID, ToJID, NewEl) -> user_send_packet(NewEl, _C2SState, FromJID, ToJID) ->
%% Registrarse para tramitar Host/mod_stats2file %% Registrarse para tramitar Host/mod_stats2file
case catch binary_to_existing_atom(ToJID#jid.lresource, utf8) of case catch binary_to_existing_atom(ToJID#jid.lresource, utf8) of
?MODULE -> received_response(FromJID, ToJID, NewEl); ?MODULE -> received_response(FromJID, ToJID, NewEl);
_ -> ok _ -> ok
end. end,
NewEl.
user_send_packet_traffic(FromJID, ToJID, NewEl) -> user_send_packet_traffic(NewEl, _C2SState, FromJID, ToJID) ->
%% Only required for traffic stats %% Only required for traffic stats
Host = FromJID#jid.lserver, Host = FromJID#jid.lserver,
HostTo = ToJID#jid.lserver, HostTo = ToJID#jid.lserver,
@ -246,10 +249,11 @@ user_send_packet_traffic(FromJID, ToJID, NewEl) ->
false -> out false -> out
end, end,
Table = table_name(Host), Table = table_name(Host),
ets:update_counter(Table, {send, Host, Type2, Dest}, 1). ets:update_counter(Table, {send, Host, Type2, Dest}, 1),
NewEl.
%% Only required for traffic stats %% Only required for traffic stats
user_receive_packet_traffic(_JID, From, To, FixedPacket) -> user_receive_packet_traffic(FixedPacket, _C2SState, _JID, From, To) ->
HostFrom = From#jid.lserver, HostFrom = From#jid.lserver,
Host = To#jid.lserver, Host = To#jid.lserver,
{xmlel, Type, _, _} = FixedPacket, {xmlel, Type, _, _} = FixedPacket,
@ -263,7 +267,8 @@ user_receive_packet_traffic(_JID, From, To, FixedPacket) ->
false -> out false -> out
end, end,
Table = table_name(Host), Table = table_name(Host),
ets:update_counter(Table, {recv, Host, Type2, Dest}, 1). ets:update_counter(Table, {recv, Host, Type2, Dest}, 1),
FixedPacket.
%%%================================== %%%==================================
@ -736,8 +741,8 @@ user_login(U) ->
request_iqversion(User, Host, Resource). request_iqversion(User, Host, Resource).
user_logout_sm(_, JID, _Data) -> %%user_logout_sm(_, JID, _Data) ->
user_logout(JID#jid.luser, JID#jid.lserver, JID#jid.lresource, no_status). %% user_logout(JID#jid.luser, JID#jid.lserver, JID#jid.lresource, no_status).
%% cuando un usuario desconecta, buscar en la tabla su JID/USR y quitarlo %% cuando un usuario desconecta, buscar en la tabla su JID/USR y quitarlo
user_logout(User, Host, Resource, _Status) -> user_logout(User, Host, Resource, _Status) ->
@ -874,11 +879,13 @@ list_elem(clients, full) ->
{"Gabber", gabber}, {"Gabber", gabber},
{"BitlBee", bitlbee}, {"BitlBee", bitlbee},
{"jabber.el", jabberel}, {"jabber.el", jabberel},
{"irssi-xmpp", 'irssi-xmpp'},
{"mcabber", mcabber}, {"mcabber", mcabber},
{"poezio", poezio}, {"poezio", poezio},
{"Profanity", profanity}, {"Profanity", profanity},
{"centerim", centerim}, {"centerim", centerim},
{"Conversations", conversations}, {"Conversations", conversations},
{"Monal", monal},
{"AQQ", aqq}, {"AQQ", aqq},
{"WTW", wtw}, {"WTW", wtw},
{"yaxim", yaxim}, {"yaxim", yaxim},