]> www.infradead.org Git - pidgin-chime.git/commitdiff
Prevent double-replacements in mentions
authorMichael Gruenewald <gruenem@amazon.com>
Fri, 2 Feb 2018 14:39:56 +0000 (15:39 +0100)
committerMichael Gruenewald <gruenem@amazon.com>
Sun, 25 Feb 2018 21:42:09 +0000 (22:42 +0100)
Outgoing mentions replace a name with a reference to the Chime user.
Sometimes you have two users with the same name in a chat room, or two
people where one name is a prefix of another one. This could end up with
something like `<@id1|<@id2|Last, First>>`, which is broken.

This change makes sure to only replace at word borders and not if a `|`
is in front. This isn't perfect, but better than before.

chat.c

diff --git a/chat.c b/chat.c
index 8b1b96de278f590abc81e8bf1c60e551298ccfa7..ded11de164401c2b3c6510f97a078321091faac9 100644 (file)
--- a/chat.c
+++ b/chat.c
@@ -75,13 +75,13 @@ static int parse_inbound_mentions(ChimeConnection *cxn, GRegex *mention_regex, c
                strstr(message, "&lt;@present|");
 }
 
-static void replace(gchar **dst, const gchar *a, const gchar *b)
+static void replace(gchar **dst, const gchar *pattern, const gchar *replacement)
 {
-       gchar **parts = g_strsplit(*dst, a, 0);
-       gchar *replaced = g_strjoinv(b, parts);
-       g_strfreev(parts);
-       g_free(*dst);
-       *dst = replaced;
+       GRegex *regex = g_regex_new(pattern, 0, 0, NULL);
+       gchar* replaced = g_regex_replace_literal(regex, *dst, -1, 0, replacement, 0, NULL);
+       g_regex_unref(regex);
+       g_free(*dst);
+       *dst = replaced;
 }
 
 /*
@@ -102,8 +102,12 @@ static gchar *parse_outbound_mentions(ChimeRoom *room, const gchar *message)
                const gchar *display_name = chime_contact_get_display_name(member->contact);
 
                if (strstr(parsed, display_name)) {
+                       gchar *display_name_escaped = g_regex_escape_string(display_name, -1);
+                       gchar *search = g_strdup_printf("(?<!\\|)\\b%s\\b", display_name_escaped);
+                       g_free(display_name_escaped);
                        gchar *chime_mention = g_strdup_printf("<@%s|%s>", id, display_name);
-                       replace(&parsed, display_name, chime_mention);
+                       replace(&parsed, search, chime_mention);
+                       g_free(search);
                        g_free(chime_mention);
                }