]> granicus.if.org Git - ejabberd/commitdiff
mod_offline: Support discarding chat states
authorHolger Weiss <holger@zedat.fu-berlin.de>
Wed, 25 Nov 2015 07:58:22 +0000 (08:58 +0100)
committerHolger Weiss <holger@zedat.fu-berlin.de>
Thu, 26 Nov 2015 07:35:49 +0000 (08:35 +0100)
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
src/mod_client_state.erl
src/mod_offline.erl

index edeb6cd0189e7baf73f1f3a8d2145157f9ae8d2f..321781216a4350aa14456c80bb3d027ed4187d3f 100644 (file)
@@ -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().
 
index 4934db3bc2c4e75fe49ae77dc8513f2e19719162..e89ec6883d04a983df435ef59dbcffd56e0ccc90 100644 (file)
@@ -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 <gone/>:
-    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.
index a9f8237072dec346101948bb186e7d25d1bec3a5..c41770d3201c80e56566f58d95c7c84c10a2a0ff 100644 (file)
@@ -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].