From 44f5e411c52c89b7d544eefa7ced637a56e9648d Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 25 Nov 2015 08:58:22 +0100 Subject: [PATCH] mod_offline: Support discarding chat states XEP-0160 says that standalone chat state notifications should not be stored offline. By default, mod_offline discards them now. Closes #842. --- src/jlib.erl | 21 +++++++++++++++++++++ src/mod_client_state.erl | 18 ++++-------------- src/mod_offline.erl | 12 +++++++++--- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/jlib.erl b/src/jlib.erl index edeb6cd01..321781216 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -43,6 +43,7 @@ get_iq_namespace/1, iq_query_info/1, iq_query_or_response_info/1, is_iq_request_type/1, iq_to_xml/1, parse_xdata_submit/1, + is_standalone_chat_state/1, add_delay_info/3, add_delay_info/4, timestamp_to_iso/1, timestamp_to_iso/2, now_to_utc_string/1, now_to_local_string/1, @@ -527,6 +528,26 @@ rsm_encode_count(Count, Arr) -> children = [{xmlcdata, i2l(Count)}]} | Arr]. +-spec is_standalone_chat_state(xmlel()) -> boolean(). + +is_standalone_chat_state(#xmlel{name = <<"message">>} = El) -> + ChatStates = [<<"active">>, <<"inactive">>, <<"gone">>, <<"composing">>, + <<"paused">>], + Stripped = + lists:foldl(fun(ChatState, AccEl) -> + xml:remove_subtags(AccEl, ChatState, + {<<"xmlns">>, ?NS_CHATSTATES}) + end, El, ChatStates), + case Stripped of + #xmlel{children = [#xmlel{name = <<"thread">>}]} -> + true; + #xmlel{children = []} -> + true; + _ -> + false + end; +is_standalone_chat_state(_El) -> false. + -spec add_delay_info(xmlel(), jid() | ljid() | binary(), erlang:timestamp()) -> xmlel(). diff --git a/src/mod_client_state.erl b/src/mod_client_state.erl index 4934db3bc..e89ec6883 100644 --- a/src/mod_client_state.erl +++ b/src/mod_client_state.erl @@ -91,22 +91,12 @@ filter_presence(_Action, #xmlel{name = <<"presence">>, attrs = Attrs}) -> filter_presence(Action, _Stanza) -> Action. filter_chat_states(_Action, #xmlel{name = <<"message">>} = Stanza) -> - %% All XEP-0085 chat states except for : - ChatStates = [<<"active">>, <<"inactive">>, <<"composing">>, <<"paused">>], - Stripped = - lists:foldl(fun(ChatState, AccStanza) -> - xml:remove_subtags(AccStanza, ChatState, - {<<"xmlns">>, ?NS_CHATSTATES}) - end, Stanza, ChatStates), - case Stripped of - #xmlel{children = [#xmlel{name = <<"thread">>}]} -> + case jlib:is_standalone_chat_state(Stanza) of + true -> ?DEBUG("Got standalone chat state notification", []), {stop, drop}; - #xmlel{children = []} -> - ?DEBUG("Got standalone chat state notification", []), - {stop, drop}; - _ -> - ?DEBUG("Got message with chat state notification", []), + false -> + ?DEBUG("Got message stanza", []), {stop, send} end; filter_chat_states(Action, _Stanza) -> Action. diff --git a/src/mod_offline.erl b/src/mod_offline.erl index a9f823707..c41770d32 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -286,10 +286,14 @@ need_to_store(LServer, Packet) -> and (Type /= <<"headline">>) -> case gen_mod:get_module_opt( LServer, ?MODULE, store_empty_body, - fun(V) when is_boolean(V) -> V end, - true) of + fun(V) when is_boolean(V) -> V; + (unless_chat_state) -> unless_chat_state + end, + unless_chat_state) of false -> xml:get_subtag(Packet, <<"body">>) /= false; + unless_chat_state -> + not jlib:is_standalone_chat_state(Packet); true -> true end; @@ -1129,6 +1133,8 @@ mod_opt_type(access_max_user_messages) -> fun (A) -> A end; mod_opt_type(db_type) -> fun gen_mod:v_db/1; mod_opt_type(store_empty_body) -> - fun (V) when is_boolean(V) -> V end; + fun (V) when is_boolean(V) -> V; + (unless_chat_state) -> unless_chat_state + end; mod_opt_type(_) -> [access_max_user_messages, db_type, store_empty_body].