From f16d56a15eb521e14d03779c19edfe96dc2e55ac Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Mon, 10 Feb 2020 13:19:54 +0100 Subject: [PATCH] xep-0308: Initial support for incoming LMC --- src/ui/window.c | 57 ++++++++++++++++++++++++++++++++++++----- src/xmpp/capabilities.c | 2 ++ src/xmpp/message.c | 19 ++++++++++++++ src/xmpp/stanza.h | 1 + src/xmpp/xmpp.h | 3 +++ 5 files changed, 75 insertions(+), 7 deletions(-) diff --git a/src/ui/window.c b/src/ui/window.c index c7bb359a..b031ac22 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -3,6 +3,7 @@ * vim: expandtab:ts=4:sts=4:sw=4 * * Copyright (C) 2012 - 2019 James Booth + * Copyright (C) 2019 - 2020 Michael Vetter * * This file is part of Profanity. * @@ -49,6 +50,7 @@ #include #endif +#include "log.h" #include "config/theme.h" #include "config/preferences.h" #include "ui/ui.h" @@ -62,8 +64,7 @@ #define CEILING(X) (X-(int)(X) > 0 ? (int)(X+1) : (int)(X)) -static void _win_printf(ProfWin *window, const char show_char, int pad_indent, GDateTime *timestamp, - int flags, theme_item_t theme_item, const char *const from, const char *const message, ...); +static void _win_printf(ProfWin *window, const char show_char, int pad_indent, GDateTime *timestamp, int flags, theme_item_t theme_item, const char *const from, const char *const message_id, const char *const message, ...); static void _win_print(ProfWin *window, const char show_char, int pad_indent, GDateTime *time, int flags, theme_item_t theme_item, const char *const from, const char *const message, DeliveryReceipt *receipt); static void _win_print_wrapped(WINDOW *win, const char *const message, size_t indent, int pad_indent); @@ -1055,6 +1056,43 @@ win_show_status_string(ProfWin *window, const char *const from, win_appendln(window, presence_colour, ""); } +void +win_correct_incoming(ProfWin *window, const char *const message, const char *const id, const char *const replace_id) +{ + ProfBuffEntry *entry = buffer_get_entry_by_id(window->layout->buffer, replace_id); + if (!entry) { + log_debug("Replace ID %s could not be found in buffer. Message: %s", replace_id, message); + return; + } + + /* + if (entry->date) { + if (entry->date->timestamp) { + g_date_time_unref(entry->date->timestamp); + } + free(entry->date); + } + + entry->date = buffer_date_new_now(); + */ + + // TODO: setting + //entry->show_char = prefs_get_correction_char(); + entry->show_char = '+'; + + if (entry->message) { + free(entry->message); + } + entry->message = strdup(message); + + if (entry->id) { + free(entry->id); + } + entry->id = strdup(id); + + win_redraw(window); +} + void win_print_incoming(ProfWin *window, const char *const from, ProfMessage *message) { @@ -1079,11 +1117,16 @@ win_print_incoming(ProfWin *window, const char *const from, ProfMessage *message } else if (message->enc == PROF_MSG_ENC_OMEMO) { enc_char = prefs_get_omemo_char(); } - _win_printf(window, enc_char, 0, message->timestamp, flags, THEME_TEXT_THEM, from, "%s", message->plain); + + if (message->replace_id) { + win_correct_incoming(window, message->plain, message->id, message->replace_id); + } else { + _win_printf(window, enc_char, 0, message->timestamp, flags, THEME_TEXT_THEM, from, message->id, "%s", message->plain); + } break; } case WIN_PRIVATE: - _win_printf(window, '-', 0, message->timestamp, flags, THEME_TEXT_THEM, from, "%s", message->plain); + _win_printf(window, '-', 0, message->timestamp, flags, THEME_TEXT_THEM, from, message->id, "%s", message->plain); break; default: assert(FALSE); @@ -1094,7 +1137,7 @@ win_print_incoming(ProfWin *window, const char *const from, ProfMessage *message void win_print_them(ProfWin *window, theme_item_t theme_item, char ch, int flags, const char *const them) { - _win_printf(window, ch, 0, NULL, flags | NO_ME | NO_EOL, theme_item, them, ""); + _win_printf(window, ch, 0, NULL, flags | NO_ME | NO_EOL, theme_item, them, NULL, ""); } void @@ -1373,7 +1416,7 @@ win_newline(ProfWin *window) static void _win_printf(ProfWin *window, const char show_char, int pad_indent, GDateTime *timestamp, - int flags, theme_item_t theme_item, const char *const from, const char *const message, ...) + int flags, theme_item_t theme_item, const char *const from, const char *const message_id, const char *const message, ...) { if (timestamp == NULL) { timestamp = g_date_time_new_now_local(); @@ -1386,7 +1429,7 @@ _win_printf(ProfWin *window, const char show_char, int pad_indent, GDateTime *ti GString *fmt_msg = g_string_new(NULL); g_string_vprintf(fmt_msg, message, arg); - buffer_append(window->layout->buffer, show_char, pad_indent, timestamp, flags, theme_item, from, fmt_msg->str, NULL, NULL); + buffer_append(window->layout->buffer, show_char, pad_indent, timestamp, flags, theme_item, from, fmt_msg->str, NULL, message_id); _win_print(window, show_char, pad_indent, timestamp, flags, theme_item, from, fmt_msg->str, NULL); inp_nonblocking(TRUE); diff --git a/src/xmpp/capabilities.c b/src/xmpp/capabilities.c index e1587ef8..ebccec24 100644 --- a/src/xmpp/capabilities.c +++ b/src/xmpp/capabilities.c @@ -110,6 +110,8 @@ caps_init(void) if (prefs_get_boolean(PREF_LASTACTIVITY)) { g_hash_table_add(prof_features, strdup(STANZA_NS_LASTACTIVITY)); } + //TODO: depend on setting + g_hash_table_add(prof_features, strdup(STANZA_NS_LAST_MESSAGE_CORRECTION)); my_sha1 = NULL; } diff --git a/src/xmpp/message.c b/src/xmpp/message.c index 1a97d9f1..f6100fa8 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -188,6 +188,7 @@ message_init(void) message->jid = NULL; message->id = NULL; message->originid = NULL; + message->replace_id = NULL; message->body = NULL; message->encrypted = NULL; message->plain = NULL; @@ -215,6 +216,10 @@ message_free(ProfMessage *message) xmpp_free(ctx, message->originid); } + if (message->replace_id) { + xmpp_free(ctx, message->replace_id); + } + if (message->body) { xmpp_free(ctx, message->body); } @@ -1113,6 +1118,20 @@ _handle_chat(xmpp_stanza_t *const stanza) ProfMessage *message = message_init(); message->jid = jid; + // message stanza id + const char *id = xmpp_stanza_get_id(stanza); + if (id) { + message->id = strdup(id); + } + + xmpp_stanza_t *replace_id_stanza = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_LAST_MESSAGE_CORRECTION); + if (replace_id_stanza) { + const char *replace_id = xmpp_stanza_get_id(replace_id_stanza); + if (replace_id) { + message->replace_id = strdup(replace_id); + } + } + if (mucuser) { message->mucuser = TRUE; } diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index 7b5cbe35..dc8c4e34 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -201,6 +201,7 @@ #define STANZA_NS_STABLE_ID "urn:xmpp:sid:0" #define STANZA_NS_USER_AVATAR_DATA "urn:xmpp:avatar:data" #define STANZA_NS_USER_AVATAR_METADATA "urn:xmpp:avatar:metadata" +#define STANZA_NS_LAST_MESSAGE_CORRECTION "urn:xmpp:message-correct:0" #define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo" diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index f5b4ce70..dc1cdf27 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -68,6 +68,7 @@ #define XMPP_FEATURE_PUBSUB "http://jabber.org/protocol/pubsub" #define XMPP_FEATURE_PUBSUB_PUBLISH_OPTIONS "http://jabber.org/protocol/pubsub#publish-options" #define XMPP_FEATURE_USER_AVATAR_METADATA_NOTIFY "urn:xmpp:avatar:metadata+notify" +#define XMPP_FEATURE_LAST_MESSAGE_CORRECTION "urn:xmpp:message-correct:0" typedef enum { JABBER_CONNECTING, @@ -130,6 +131,8 @@ typedef struct prof_message_t { char *id; /* XEP-0359 */ char *originid; + /* XEP-0308 LMC */ + char *replace_id; /* The raw body from xmpp message, either plaintext or OTR encrypted text */ char *body; /* The encrypted message as for PGP */