From 4d5eab66625b9693933bdea8abbf5d25799f1fde Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Fri, 3 Jun 2016 20:28:48 +0200 Subject: [PATCH] Unwrap carbon copies when checking for chat states Detect standalone chat states that were carbon-copied. --- src/jlib.erl | 45 +++++++++++++++++++++++++++++++++++++++- src/mod_client_state.erl | 2 +- src/mod_offline.erl | 3 ++- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/jlib.erl b/src/jlib.erl index 8fe2b9774..42ac4bff3 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -43,7 +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, + unwrap_carbon/1, is_standalone_chat_state/1, add_delay_info/3, add_delay_info/4, timestamp_to_legacy/1, timestamp_to_iso_basic/1, timestamp_to_iso/2, now_to_utc_string/1, now_to_local_string/1, @@ -529,6 +529,49 @@ rsm_encode_count(Count, Arr) -> children = [{xmlcdata, i2l(Count)}]} | Arr]. +-spec unwrap_carbon(xmlel()) -> xmlel(). + +unwrap_carbon(#xmlel{name = <<"message">>} = Stanza) -> + case unwrap_carbon(Stanza, <<"sent">>) of + #xmlel{} = Payload -> + Payload; + false -> + case unwrap_carbon(Stanza, <<"received">>) of + #xmlel{} = Payload -> + Payload; + false -> + Stanza + end + end; +unwrap_carbon(Stanza) -> Stanza. + +-spec unwrap_carbon(xmlel(), binary()) -> xmlel() | false. + +unwrap_carbon(Stanza, Direction) -> + case fxml:get_subtag(Stanza, Direction) of + #xmlel{name = Direction, attrs = Attrs} = El -> + case fxml:get_attr_s(<<"xmlns">>, Attrs) of + NS when NS == ?NS_CARBONS_2; + NS == ?NS_CARBONS_1 -> + case fxml:get_subtag_with_xmlns(El, <<"forwarded">>, + ?NS_FORWARD) of + #xmlel{children = Els} -> + case fxml:remove_cdata(Els) of + [#xmlel{} = Payload] -> + Payload; + _ -> + false + end; + false -> + false + end; + _NS -> + false + end; + false -> + false + end. + -spec is_standalone_chat_state(xmlel()) -> boolean(). is_standalone_chat_state(#xmlel{name = <<"message">>, children = Els}) -> diff --git a/src/mod_client_state.erl b/src/mod_client_state.erl index 0d3a289a3..6b79aec0d 100644 --- a/src/mod_client_state.erl +++ b/src/mod_client_state.erl @@ -165,7 +165,7 @@ filter_presence(Acc, _Host, _Stanza) -> Acc. filter_chat_states({C2SState, _OutStanzas} = Acc, Host, #xmlel{name = <<"message">>} = Stanza) -> - case jlib:is_standalone_chat_state(Stanza) of + case jlib:is_standalone_chat_state(jlib:unwrap_carbon(Stanza)) of true -> ?DEBUG("Got standalone chat state notification", []), queue_add(chatstate, Stanza, Host, C2SState); diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 4d8aba762..74fbcd99b 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -455,7 +455,8 @@ need_to_store(LServer, Packet) -> false -> fxml:get_subtag(Packet, <<"body">>) /= false; unless_chat_state -> - not jlib:is_standalone_chat_state(Packet); + not jlib:is_standalone_chat_state( + jlib:unwrap_carbon(Packet)); true -> true end