about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorPaul Fariello <paul@fariello.eu>2019-04-01 20:39:39 +0320
committerPaul Fariello <paul@fariello.eu>2019-04-10 17:23:46 +0200
commite69f947547160ea2c965a3d4f5966c5f4a289340 (patch)
treeebb71704f3ce98fdb9494dfcfb1b555dc2d212ce
parente7be3a605bbb47e462265a379d48aad9cc565fc2 (diff)
downloadprofani-tty-e69f947547160ea2c965a3d4f5966c5f4a289340.tar.gz
Rework MUC reflected message filtering
Reflected messages can't be filtered by nick only otherwise you might
ignore messages comming from you on another devices.

Consequently we maintain a list of sent messages id in mucwin.
To be sure the id will be correctly reflected we use the origin-id
stanza.
-rw-r--r--src/event/client_events.c12
-rw-r--r--src/event/server_events.c10
-rw-r--r--src/event/server_events.h2
-rw-r--r--src/ui/mucwin.c11
-rw-r--r--src/ui/ui.h4
-rw-r--r--src/ui/win_types.h1
-rw-r--r--src/ui/window.c1
-rw-r--r--src/ui/window_list.c1
-rw-r--r--src/xmpp/message.c18
-rw-r--r--src/xmpp/stanza.c15
-rw-r--r--src/xmpp/stanza.h3
-rw-r--r--src/xmpp/xmpp.h2
-rw-r--r--tests/unittests/ui/stub_ui.c4
-rw-r--r--tests/unittests/xmpp/stub_xmpp.c5
14 files changed, 64 insertions, 25 deletions
diff --git a/src/event/client_events.c b/src/event/client_events.c
index adcffbf2..c2149985 100644
--- a/src/event/client_events.c
+++ b/src/event/client_events.c
@@ -353,12 +353,13 @@ cl_ev_send_muc_msg(ProfMucWin *mucwin, const char *const msg, const char *const
     if (mucwin->is_omemo) {
         char *id = omemo_on_message_send((ProfWin *)mucwin, plugin_msg, FALSE, TRUE);
         groupchat_log_omemo_msg_out(mucwin->roomjid, plugin_msg);
-        mucwin_outgoing_msg(mucwin, plugin_msg, PROF_MSG_OMEMO);
+        mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_OMEMO);
         free(id);
     } else {
-        message_send_groupchat(mucwin->roomjid, plugin_msg, oob_url);
+        char *id = message_send_groupchat(mucwin->roomjid, plugin_msg, oob_url);
         groupchat_log_msg_out(mucwin->roomjid, plugin_msg);
-        mucwin_outgoing_msg(mucwin, plugin_msg, PROF_MSG_PLAIN);
+        mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_PLAIN);
+        free(id);
     }
 
     plugins_post_room_message_send(mucwin->roomjid, plugin_msg);
@@ -367,9 +368,10 @@ cl_ev_send_muc_msg(ProfMucWin *mucwin, const char *const msg, const char *const
 #endif
 
 #ifndef HAVE_OMEMO
-    message_send_groupchat(mucwin->roomjid, plugin_msg, oob_url);
+    char *id = message_send_groupchat(mucwin->roomjid, plugin_msg, oob_url);
     groupchat_log_msg_out(mucwin->roomjid, plugin_msg);
-    mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_PLAIN, request_receipt);
+    mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_PLAIN);
+    free(id);
 
     plugins_post_room_message_send(mucwin->roomjid, plugin_msg);
     free(plugin_msg);
diff --git a/src/event/server_events.c b/src/event/server_events.c
index 023e8a13..f6c640f3 100644
--- a/src/event/server_events.c
+++ b/src/event/server_events.c
@@ -260,7 +260,7 @@ sv_ev_room_history(const char *const room_jid, const char *const nick,
 }
 
 void
-sv_ev_room_message(const char *const room_jid, const char *const nick, const char *const message, gboolean omemo)
+sv_ev_room_message(const char *const room_jid, const char *const nick, const char *const message, const char *const id, gboolean omemo)
 {
     ProfMucWin *mucwin = wins_get_muc(room_jid);
     if (!mucwin) {
@@ -268,10 +268,6 @@ sv_ev_room_message(const char *const room_jid, const char *const nick, const cha
     }
 
     char *mynick = muc_nick(mucwin->roomjid);
-    if (g_strcmp0(mynick, nick) == 0) {
-        /* Ignore message reflection */
-        return;
-    }
 
     if (omemo) {
         groupchat_log_omemo_msg_in(room_jid, nick, message);
@@ -295,9 +291,9 @@ sv_ev_room_message(const char *const room_jid, const char *const nick, const cha
     GList *triggers = prefs_message_get_triggers(new_message);
 
     if (omemo) {
-        mucwin_incoming_msg(mucwin, nick, new_message, mentions, triggers, PROF_MSG_OMEMO);
+        mucwin_incoming_msg(mucwin, nick, new_message, id, mentions, triggers, PROF_MSG_OMEMO);
     } else {
-        mucwin_incoming_msg(mucwin, nick, new_message, mentions, triggers, PROF_MSG_PLAIN);
+        mucwin_incoming_msg(mucwin, nick, new_message, id, mentions, triggers, PROF_MSG_PLAIN);
     }
 
     g_slist_free(mentions);
diff --git a/src/event/server_events.h b/src/event/server_events.h
index cf437f9a..713e50f5 100644
--- a/src/event/server_events.h
+++ b/src/event/server_events.h
@@ -48,7 +48,7 @@ void sv_ev_room_subject(const char *const room, const char *const nick, const ch
 void sv_ev_room_history(const char *const room_jid, const char *const nick,
     GDateTime *timestamp, const char *const message, gboolean omemo);
 void sv_ev_room_message(const char *const room_jid, const char *const nick,
-    const char *const message, gboolean omemo);
+    const char *const message, const char *const id, gboolean omemo);
 void sv_ev_incoming_message(char *barejid, char *resource, char *message, char *pgp_message, GDateTime *timestamp, gboolean omemo);
 void sv_ev_incoming_private_message(const char *const fulljid, char *message);
 void sv_ev_delayed_private_message(const char *const fulljid, char *message, GDateTime *timestamp);
diff --git a/src/ui/mucwin.c b/src/ui/mucwin.c
index abbcd21c..0122950a 100644
--- a/src/ui/mucwin.c
+++ b/src/ui/mucwin.c
@@ -478,10 +478,12 @@ _mucwin_print_triggers(ProfWin *window, const char *const message, GList *trigge
 }
 
 void
-mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, prof_enc_t enc_mode)
+mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, const char *const id, prof_enc_t enc_mode)
 {
     assert(mucwin != NULL);
 
+    g_hash_table_insert(mucwin->sent_messages, strdup(id), NULL);
+
     ProfWin *window = (ProfWin*)mucwin;
     char *mynick = muc_nick(mucwin->roomjid);
 
@@ -500,10 +502,15 @@ mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, prof_enc_t en
 }
 
 void
-mucwin_incoming_msg(ProfMucWin *mucwin, const char *const nick, const char *const message, GSList *mentions, GList *triggers, prof_enc_t enc_mode)
+mucwin_incoming_msg(ProfMucWin *mucwin, const char *const nick, const char *const message, const char *const id, GSList *mentions, GList *triggers, prof_enc_t enc_mode)
 {
     assert(mucwin != NULL);
 
+    if (g_hash_table_remove(mucwin->sent_messages, id)) {
+        /* Ignore reflection messages */
+        return;
+    }
+
     ProfWin *window = (ProfWin*)mucwin;
     char *mynick = muc_nick(mucwin->roomjid);
 
diff --git a/src/ui/ui.h b/src/ui/ui.h
index 79701a27..b94fe475 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -162,8 +162,8 @@ void mucwin_occupant_role_and_affiliation_change(ProfMucWin *mucwin, const char
     const char *const role, const char *const affiliation, const char *const actor, const char *const reason);
 void mucwin_roster(ProfMucWin *mucwin, GList *occupants, const char *const presence);
 void mucwin_history(ProfMucWin *mucwin, const char *const nick, GDateTime *timestamp, const char *const message);
-void mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, prof_enc_t enc_mode);
-void mucwin_incoming_msg(ProfMucWin *mucwin, const char *const nick, const char *const message, GSList *mentions, GList *triggers, prof_enc_t enc_mode);
+void mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, const char *const id, prof_enc_t enc_mode);
+void mucwin_incoming_msg(ProfMucWin *mucwin, const char *const nick, const char *const message, const char *const id, GSList *mentions, GList *triggers, prof_enc_t enc_mode);
 void mucwin_subject(ProfMucWin *mucwin, const char *const nick, const char *const subject);
 void mucwin_requires_config(ProfMucWin *mucwin);
 void mucwin_info(ProfMucWin *mucwin);
diff --git a/src/ui/win_types.h b/src/ui/win_types.h
index 498d9bbe..e1e64bf9 100644
--- a/src/ui/win_types.h
+++ b/src/ui/win_types.h
@@ -172,6 +172,7 @@ typedef struct prof_muc_win_t {
     unsigned long memcheck;
     char *enctext;
     char *message_char;
+    GHashTable *sent_messages;
 } ProfMucWin;
 
 typedef struct prof_conf_win_t ProfConfWin;
diff --git a/src/ui/window.c b/src/ui/window.c
index 64b04365..12b6c15b 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -198,6 +198,7 @@ win_create_muc(const char *const roomjid)
     new_win->enctext = NULL;
     new_win->message_char = NULL;
     new_win->is_omemo = FALSE;
+    new_win->sent_messages = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
 
     new_win->memcheck = PROFMUCWIN_MEMCHECK;
 
diff --git a/src/ui/window_list.c b/src/ui/window_list.c
index 5ce68d63..43230b57 100644
--- a/src/ui/window_list.c
+++ b/src/ui/window_list.c
@@ -561,6 +561,7 @@ wins_close_by_num(int i)
                 ProfMucWin *mucwin = (ProfMucWin*)window;
                 autocomplete_remove(wins_ac, mucwin->roomjid);
                 autocomplete_remove(wins_close_ac, mucwin->roomjid);
+                g_hash_table_remove_all(mucwin->sent_messages);
                 break;
             }
             case WIN_PRIVATE:
diff --git a/src/xmpp/message.c b/src/xmpp/message.c
index 2a6ad234..47cf35d7 100644
--- a/src/xmpp/message.c
+++ b/src/xmpp/message.c
@@ -326,6 +326,7 @@ message_send_chat_omemo(const char *const jid, uint32_t sid, GList *keys,
     if (muc) {
         id = connection_create_stanza_id("muc");
         message = xmpp_message_new(ctx, STANZA_TYPE_GROUPCHAT, jid, id);
+        stanza_attach_origin_id(ctx, message, id);
     } else {
         id = connection_create_stanza_id("msg");
         message = xmpp_message_new(ctx, STANZA_TYPE_CHAT, jid, id);
@@ -442,23 +443,24 @@ message_send_private(const char *const fulljid, const char *const msg, const cha
     xmpp_stanza_release(message);
 }
 
-void
+char*
 message_send_groupchat(const char *const roomjid, const char *const msg, const char *const oob_url)
 {
     xmpp_ctx_t * const ctx = connection_get_ctx();
     char *id = connection_create_stanza_id("muc");
 
     xmpp_stanza_t *message = xmpp_message_new(ctx, STANZA_TYPE_GROUPCHAT, roomjid, id);
+    stanza_attach_origin_id(ctx, message, id);
     xmpp_message_set_body(message, msg);
 
-    free(id);
-
     if (oob_url) {
         stanza_attach_x_oob_url(ctx, message, oob_url);
     }
 
     _send_message_stanza(message);
     xmpp_stanza_release(message);
+
+    return id;
 }
 
 void
@@ -687,6 +689,14 @@ _handle_groupchat(xmpp_stanza_t *const stanza)
 {
     xmpp_ctx_t *ctx = connection_get_ctx();
     char *message = NULL;
+
+    const char *id = xmpp_stanza_get_id(stanza);
+
+    xmpp_stanza_t *origin = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_STABLE_ID);
+    if (origin && g_strcmp0(xmpp_stanza_get_name(origin), STANZA_NAME_ORIGIN_ID) == 0) {
+        id = xmpp_stanza_get_attribute(origin, STANZA_ATTR_ID);
+    }
+
     const char *room_jid = xmpp_stanza_get_from(stanza);
     Jid *jid = jid_create(room_jid);
 
@@ -750,7 +760,7 @@ _handle_groupchat(xmpp_stanza_t *const stanza)
         sv_ev_room_history(jid->barejid, jid->resourcepart, timestamp, message, omemo);
         g_date_time_unref(timestamp);
     } else {
-        sv_ev_room_message(jid->barejid, jid->resourcepart, message, omemo);
+        sv_ev_room_message(jid->barejid, jid->resourcepart, message, id, omemo);
     }
 
     xmpp_free(ctx, message);
diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c
index f4fd8aa8..615de44f 100644
--- a/src/xmpp/stanza.c
+++ b/src/xmpp/stanza.c
@@ -2417,6 +2417,21 @@ stanza_create_pubsub_configure_submit(xmpp_ctx_t *ctx, const char *const id, con
     return iq;
 }
 
+xmpp_stanza_t*
+stanza_attach_origin_id(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza, const char *const id)
+{
+    xmpp_stanza_t *origin_id = xmpp_stanza_new(ctx);
+    xmpp_stanza_set_name(origin_id, STANZA_NAME_ORIGIN_ID);
+    xmpp_stanza_set_ns(origin_id, STANZA_NS_STABLE_ID);
+    xmpp_stanza_set_attribute(origin_id, STANZA_ATTR_ID, id);
+
+    xmpp_stanza_add_child(stanza, origin_id);
+
+    xmpp_stanza_release(origin_id);
+
+    return stanza;
+}
+
 static void
 _stanza_add_unique_id(xmpp_stanza_t *stanza, char *prefix)
 {
diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h
index eaf76a27..e5e17ba4 100644
--- a/src/xmpp/stanza.h
+++ b/src/xmpp/stanza.h
@@ -102,6 +102,7 @@
 #define STANZA_NAME_URL "url"
 #define STANZA_NAME_COMMAND "command"
 #define STANZA_NAME_CONFIGURE "configure"
+#define STANZA_NAME_ORIGIN_ID "origin-id"
 
 // error conditions
 #define STANZA_NAME_BAD_REQUEST "bad-request"
@@ -196,6 +197,7 @@
 #define STANZA_NS_OMEMO "eu.siacs.conversations.axolotl"
 #define STANZA_NS_OMEMO_DEVICELIST "eu.siacs.conversations.axolotl.devicelist"
 #define STANZA_NS_OMEMO_BUNDLES "eu.siacs.conversations.axolotl.bundles"
+#define STANZA_NS_STABLE_ID "urn:xmpp:sid:0"
 
 #define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo"
 
@@ -238,6 +240,7 @@ xmpp_stanza_t* stanza_attach_hints_no_store(xmpp_ctx_t *ctx, xmpp_stanza_t *stan
 xmpp_stanza_t* stanza_attach_hints_store(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza);
 xmpp_stanza_t* stanza_attach_receipt_request(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza);
 xmpp_stanza_t* stanza_attach_x_oob_url(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza, const char *const url);
+xmpp_stanza_t* stanza_attach_origin_id(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza, const char *const id);
 
 xmpp_stanza_t* stanza_create_room_join_presence(xmpp_ctx_t *const ctx,
     const char *const full_room_jid, const char *const passwd);
diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h
index 39877bc2..54a56f02 100644
--- a/src/xmpp/xmpp.h
+++ b/src/xmpp/xmpp.h
@@ -144,7 +144,7 @@ char* message_send_chat_otr(const char *const barejid, const char *const msg, gb
 char* message_send_chat_pgp(const char *const barejid, const char *const msg, gboolean request_receipt);
 char* message_send_chat_omemo(const char *const jid, uint32_t sid, GList *keys, const unsigned char *const iv, size_t iv_len, const unsigned char *const ciphertext, size_t ciphertext_len, gboolean request_receipt, gboolean muc);
 void message_send_private(const char *const fulljid, const char *const msg, const char *const oob_url);
-void message_send_groupchat(const char *const roomjid, const char *const msg, const char *const oob_url);
+char* message_send_groupchat(const char *const roomjid, const char *const msg, const char *const oob_url);
 void message_send_groupchat_subject(const char *const roomjid, const char *const subject);
 void message_send_inactive(const char *const jid);
 void message_send_composing(const char *const jid);
diff --git a/tests/unittests/ui/stub_ui.c b/tests/unittests/ui/stub_ui.c
index 950036bc..361a42e2 100644
--- a/tests/unittests/ui/stub_ui.c
+++ b/tests/unittests/ui/stub_ui.c
@@ -190,8 +190,8 @@ void mucwin_occupant_role_and_affiliation_change(ProfMucWin *mucwin, const char
     const char * const affiliation, const char * const actor, const char * const reason) {}
 void mucwin_roster(ProfMucWin *mucwin, GList *occupants, const char * const presence) {}
 void mucwin_history(ProfMucWin *mucwin, const char * const nick, GDateTime *timestamp, const char * const message) {}
-void mucwin_incoming_msg(ProfMucWin *mucwin, const char *const nick, const char *const message, GSList *mentions, GList *triggers, prof_enc_t enc_mode) {}
-void mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, prof_enc_t enc_mode) {}
+void mucwin_incoming_msg(ProfMucWin *mucwin, const char *const nick, const char *const message, const char *const id, GSList *mentions, GList *triggers, prof_enc_t enc_mode) {}
+void mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, const char *const id, prof_enc_t enc_mode) {}
 void mucwin_subject(ProfMucWin *mucwin, const char * const nick, const char * const subject) {}
 void mucwin_requires_config(ProfMucWin *mucwin) {}
 void ui_room_destroy(const char * const roomjid) {}
diff --git a/tests/unittests/xmpp/stub_xmpp.c b/tests/unittests/xmpp/stub_xmpp.c
index bc2c50db..53a729e6 100644
--- a/tests/unittests/xmpp/stub_xmpp.c
+++ b/tests/unittests/xmpp/stub_xmpp.c
@@ -114,7 +114,10 @@ char* message_send_chat_pgp(const char * const barejid, const char * const msg,
 }
 
 void message_send_private(const char * const fulljid, const char * const msg, const char *const oob_url) {}
-void message_send_groupchat(const char * const roomjid, const char * const msg, const char *const oob_url) {}
+char* message_send_groupchat(const char * const roomjid, const char * const msg, const char *const oob_url)
+{
+    return NULL;
+}
 void message_send_groupchat_subject(const char * const roomjid, const char * const subject) {}
 
 void message_send_inactive(const char * const barejid) {}