about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorMichael Vetter <jubalh@iodoru.org>2020-02-10 16:17:01 +0100
committerMichael Vetter <jubalh@iodoru.org>2020-02-10 16:17:01 +0100
commit11181100712fc2a1c2f310b4470d752488e8961e (patch)
treecd5b5341d86e48e7df09c6bfc9414dfc296144ca
parent83b61e5160b6624eb0b2898c1321d33341e6510c (diff)
downloadprofani-tty-11181100712fc2a1c2f310b4470d752488e8961e.tar.gz
xep-0308: Implement `/correct` to correct the last send message
So far the correction is sent. But the UI in Profanity itself is not
updated.

Also autocompletion for `/correct` with the last sent message is
missing.
-rw-r--r--src/command/cmd_ac.c11
-rw-r--r--src/command/cmd_defs.c17
-rw-r--r--src/command/cmd_funcs.c41
-rw-r--r--src/command/cmd_funcs.h1
-rw-r--r--src/event/client_events.c26
-rw-r--r--src/event/client_events.h1
-rw-r--r--src/ui/chatwin.c16
-rw-r--r--src/ui/win_types.h3
-rw-r--r--src/ui/window.c4
-rw-r--r--src/xmpp/message.c7
-rw-r--r--src/xmpp/stanza.c12
-rw-r--r--src/xmpp/stanza.h1
-rw-r--r--src/xmpp/xmpp.h3
13 files changed, 132 insertions, 11 deletions
diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c
index 0b411bcb..17629d87 100644
--- a/src/command/cmd_ac.c
+++ b/src/command/cmd_ac.c
@@ -114,6 +114,7 @@ static char* _logging_autocomplete(ProfWin *window, const char *const input, gbo
 static char* _color_autocomplete(ProfWin *window, const char *const input, gboolean previous);
 static char* _avatar_autocomplete(ProfWin *window, const char *const input, gboolean previous);
 static char* _correction_autocomplete(ProfWin *window, const char *const input, gboolean previous);
+static char* _correct_autocomplete(ProfWin *window, const char *const input, gboolean previous);
 
 static char* _script_autocomplete_func(const char *const prefix, gboolean previous, void *context);
 
@@ -1640,6 +1641,7 @@ _cmd_ac_complete_params(ProfWin *window, const char *const input, gboolean previ
     g_hash_table_insert(ac_funcs, "/color",         _color_autocomplete);
     g_hash_table_insert(ac_funcs, "/avatar",        _avatar_autocomplete);
     g_hash_table_insert(ac_funcs, "/correction",    _correction_autocomplete);
+    g_hash_table_insert(ac_funcs, "/correct",       _correct_autocomplete);
 
     int len = strlen(input);
     char parsed[len+1];
@@ -3736,3 +3738,12 @@ _correction_autocomplete(ProfWin *window, const char *const input, gboolean prev
 
     return NULL;
 }
+
+static char*
+_correct_autocomplete(ProfWin *window, const char *const input, gboolean previous)
+{
+    char *result = NULL;
+
+    //TODO: get last message
+    return result;
+}
diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c
index 982d81f6..db719b17 100644
--- a/src/command/cmd_defs.c
+++ b/src/command/cmd_defs.c
@@ -2367,6 +2367,7 @@ static struct cmd_t command_defs[] =
         CMD_NOSUBFUNCS
         CMD_MAINFUNC(cmd_correction)
         CMD_TAGS(
+            CMD_TAG_UI,
             CMD_TAG_CHAT,
             CMD_TAG_GROUPCHAT)
         CMD_SYN(
@@ -2379,6 +2380,22 @@ static struct cmd_t command_defs[] =
             { "char",    "Set character that will prefix corrected messages. Default: +"})
         CMD_NOEXAMPLES
     },
+
+    { "/correct",
+        parse_args, 1, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_correct)
+        CMD_TAGS(
+            CMD_TAG_CHAT,
+            CMD_TAG_GROUPCHAT)
+        CMD_SYN(
+            "/correct <message>")
+        CMD_DESC(
+            "Correct and resend the last message (XEP-0308).")
+        CMD_ARGS(
+            { "<message>",    "The corrected message."})
+        CMD_NOEXAMPLES
+    },
 };
 
 static GHashTable *search_index;
diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c
index 70a6dcc0..9620f0d7 100644
--- a/src/command/cmd_funcs.c
+++ b/src/command/cmd_funcs.c
@@ -8680,3 +8680,44 @@ cmd_correction(ProfWin *window, const char *const command, gchar **args)
 
     return TRUE;
 }
+
+gboolean
+cmd_correct(ProfWin *window, const char *const command, gchar **args)
+{
+    jabber_conn_status_t conn_status = connection_get_status();
+    if (conn_status != JABBER_CONNECTED) {
+        cons_show("You are currently not connected.");
+        return TRUE;
+    }
+
+    if (window->type == WIN_CHAT) {
+        ProfChatWin *chatwin = (ProfChatWin*)window;
+        assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
+
+        if (chatwin->last_msg_id == NULL || chatwin->last_message == NULL) {
+            win_println(window, THEME_DEFAULT, '!', "No last message to correct.");
+            return TRUE;
+        }
+
+        /*
+        char *session_jid = chat_session_get_jid(chatwin->barejid);
+        if (session_jid == NULL) {
+            win_println(window, THEME_DEFAULT, '!', "Cannot determine if recipeint supports last message correction.");
+            free(session_jid);
+            return TRUE;
+        }
+
+        if (caps_jid_has_feature(session_jid, XMPP_FEATURE_LAST_MESSAGE_CORRECTION) == FALSE) {
+            win_println(window, THEME_DEFAULT, '!', "Recipient does not support last message correction.");
+            free(session_jid);
+            return TRUE;
+        }
+
+        */
+        // speciel send with replace tag
+        cl_ev_send_msg_correct(chatwin, args[0], FALSE, TRUE);
+    }
+
+    win_println(window, THEME_DEFAULT, '!', "Command /correct only valid in regular chat windows.");
+    return TRUE;
+}
diff --git a/src/command/cmd_funcs.h b/src/command/cmd_funcs.h
index a2ccd000..768e14a2 100644
--- a/src/command/cmd_funcs.h
+++ b/src/command/cmd_funcs.h
@@ -228,4 +228,5 @@ gboolean cmd_color(ProfWin *window, const char *const command, gchar **args);
 gboolean cmd_avatar(ProfWin *window, const char *const command, gchar **args);
 gboolean cmd_os(ProfWin *window, const char *const command, gchar **args);
 gboolean cmd_correction(ProfWin *window, const char *const command, gchar **args);
+gboolean cmd_correct(ProfWin *window, const char *const command, gchar **args);
 #endif
diff --git a/src/event/client_events.c b/src/event/client_events.c
index 6716b7e2..50a46ccc 100644
--- a/src/event/client_events.c
+++ b/src/event/client_events.c
@@ -115,7 +115,7 @@ cl_ev_presence_send(const resource_presence_t presence_type, const int idle_secs
 }
 
 void
-cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oob_url)
+cl_ev_send_msg_correct(ProfChatWin *chatwin, const char *const msg, const char *const oob_url, gboolean correct_last_msg)
 {
     chat_state_active(chatwin->state);
 
@@ -139,11 +139,17 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
         return;
     }
 
+    char *replace_id = NULL;
+    if (correct_last_msg) {
+        replace_id = chatwin->last_msg_id;
+    }
+
 // OTR suported, PGP supported, OMEMO unsupported
 #ifdef HAVE_LIBOTR
 #ifdef HAVE_LIBGPGME
 #ifndef HAVE_OMEMO
     if (chatwin->pgp_send) {
+        // TODO: replace_id
         char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg, request_receipt);
         chat_log_pgp_msg_out(chatwin->barejid, plugin_msg, NULL);
         chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PGP, request_receipt);
@@ -151,7 +157,7 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
     } else {
         gboolean handled = otr_on_message_send(chatwin, plugin_msg, request_receipt);
         if (!handled) {
-            char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt);
+            char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt, replace_id);
             chat_log_msg_out(chatwin->barejid, plugin_msg, NULL);
             chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt);
             free(id);
@@ -171,7 +177,7 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
 #ifndef HAVE_OMEMO
     gboolean handled = otr_on_message_send(chatwin, plugin_msg, request_receipt);
     if (!handled) {
-        char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt);
+        char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt, replace_id);
         chat_log_msg_out(chatwin->barejid, plugin_msg, NULL);
         chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt);
         free(id);
@@ -194,7 +200,7 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
         chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PGP, request_receipt);
         free(id);
     } else {
-        char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt);
+        char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt, replace_id);
         chat_log_msg_out(chatwin->barejid, plugin_msg, NULL);
         chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt);
         free(id);
@@ -217,7 +223,7 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
         chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_OMEMO, request_receipt);
         free(id);
     } else {
-        char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt);
+        char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt, replace_id);
         chat_log_msg_out(chatwin->barejid, plugin_msg, NULL);
         chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt);
         free(id);
@@ -242,7 +248,7 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
     } else {
         gboolean handled = otr_on_message_send(chatwin, plugin_msg, request_receipt);
         if (!handled) {
-            char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt);
+            char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt, replace_id);
             chat_log_msg_out(chatwin->barejid, plugin_msg, NULL);
             chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt);
             free(id);
@@ -301,7 +307,7 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
     } else {
         gboolean handled = otr_on_message_send(chatwin, plugin_msg, request_receipt);
         if (!handled) {
-            char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt);
+            char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt, replace_id);
             chat_log_msg_out(chatwin->barejid, plugin_msg, NULL);
             chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt);
             free(id);
@@ -333,6 +339,12 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
 }
 
 void
+cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oob_url)
+{
+    cl_ev_send_msg_correct(chatwin, msg, oob_url, FALSE);
+}
+
+void
 cl_ev_send_muc_msg(ProfMucWin *mucwin, const char *const msg, const char *const oob_url)
 {
     char *plugin_msg = plugins_pre_room_message_send(mucwin->roomjid, msg);
diff --git a/src/event/client_events.h b/src/event/client_events.h
index 82150f2e..66ade679 100644
--- a/src/event/client_events.h
+++ b/src/event/client_events.h
@@ -45,6 +45,7 @@ void cl_ev_disconnect(void);
 
 void cl_ev_presence_send(const resource_presence_t presence_type, const int idle_secs);
 
+void cl_ev_send_msg_correct(ProfChatWin *chatwin, const char *const msg, const char *const oob_url, gboolean correct_last_msg);
 void cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oob_url);
 void cl_ev_send_muc_msg(ProfMucWin *mucwin, const char *const msg, const char *const oob_url);
 void cl_ev_send_priv_msg(ProfPrivateWin *privwin, const char *const msg, const char *const oob_url);
diff --git a/src/ui/chatwin.c b/src/ui/chatwin.c
index 8faf4934..d7906815 100644
--- a/src/ui/chatwin.c
+++ b/src/ui/chatwin.c
@@ -56,6 +56,7 @@
 #endif
 
 static void _chatwin_history(ProfChatWin *chatwin, const char *const contact);
+static void _chatwin_set_last_message(ProfChatWin *chatwin, const char *const id, const char *const message);
 
 ProfChatWin*
 chatwin_new(const char *const barejid)
@@ -323,6 +324,11 @@ chatwin_outgoing_msg(ProfChatWin *chatwin, const char *const message, char *id,
         enc_char = prefs_get_omemo_char();
     }
 
+    // save last id and message for LMC
+    if (id) {
+        _chatwin_set_last_message(chatwin, id, message);
+    }
+
     if (request_receipt && id) {
         win_print_with_receipt((ProfWin*)chatwin, enc_char, "me", message, id);
     } else {
@@ -496,3 +502,13 @@ _chatwin_history(ProfChatWin *chatwin, const char *const contact)
         g_slist_free_full(history, free);
     }
 }
+
+static void
+_chatwin_set_last_message(ProfChatWin *chatwin, const char *const id, const char *const message)
+{
+    free(chatwin->last_message);
+    chatwin->last_message = strdup(message);
+
+    free(chatwin->last_msg_id);
+    chatwin->last_msg_id = strdup(id);
+}
diff --git a/src/ui/win_types.h b/src/ui/win_types.h
index 68ed719e..0a0545bd 100644
--- a/src/ui/win_types.h
+++ b/src/ui/win_types.h
@@ -160,6 +160,9 @@ typedef struct prof_chat_win_t {
     char *enctext;
     char *incoming_char;
     char *outgoing_char;
+    // For LMC
+    char *last_message;
+    char *last_msg_id;
 } ProfChatWin;
 
 typedef struct prof_muc_win_t {
diff --git a/src/ui/window.c b/src/ui/window.c
index 339f4456..c668bd34 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -152,6 +152,8 @@ win_create_chat(const char *const barejid)
     new_win->enctext = NULL;
     new_win->incoming_char = NULL;
     new_win->outgoing_char = NULL;
+    new_win->last_message = NULL;
+    new_win->last_msg_id = NULL;
 
     new_win->memcheck = PROFCHATWIN_MEMCHECK;
 
@@ -488,6 +490,8 @@ win_free(ProfWin* window)
         free(chatwin->enctext);
         free(chatwin->incoming_char);
         free(chatwin->outgoing_char);
+        free(chatwin->last_message);
+        free(chatwin->last_msg_id);
         chat_state_free(chatwin->state);
         break;
     }
diff --git a/src/xmpp/message.c b/src/xmpp/message.c
index f6100fa8..027b88f1 100644
--- a/src/xmpp/message.c
+++ b/src/xmpp/message.c
@@ -259,8 +259,7 @@ message_pubsub_event_handler_add(const char *const node, ProfMessageCallback fun
 }
 
 char*
-message_send_chat(const char *const barejid, const char *const msg, const char *const oob_url,
-    gboolean request_receipt)
+message_send_chat(const char *const barejid, const char *const msg, const char *const oob_url, gboolean request_receipt, const char *const replace_id)
 {
     xmpp_ctx_t * const ctx = connection_get_ctx();
 
@@ -284,6 +283,10 @@ message_send_chat(const char *const barejid, const char *const msg, const char *
         stanza_attach_receipt_request(ctx, message);
     }
 
+    if (replace_id) {
+        stanza_attach_correction(ctx, message, replace_id);
+    }
+
     _send_message_stanza(message);
     xmpp_stanza_release(message);
 
diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c
index f398a268..7b0db5c7 100644
--- a/src/xmpp/stanza.c
+++ b/src/xmpp/stanza.c
@@ -2606,3 +2606,15 @@ stanza_create_avatar_retrieve_data_request(xmpp_ctx_t *ctx, const char *stanza_i
 
     return iq;
 }
+
+xmpp_stanza_t*
+stanza_attach_correction(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza, const char *const replace_id)
+{
+    xmpp_stanza_t *replace_stanza = xmpp_stanza_new(ctx);
+    xmpp_stanza_set_name(replace_stanza, "replace");
+    xmpp_stanza_set_id(replace_stanza, replace_id);
+    xmpp_stanza_set_ns(replace_stanza, STANZA_NS_LAST_MESSAGE_CORRECTION);
+    xmpp_stanza_add_child(stanza, replace_stanza);
+
+    return stanza;
+}
diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h
index dc8c4e34..ee5c6772 100644
--- a/src/xmpp/stanza.h
+++ b/src/xmpp/stanza.h
@@ -245,6 +245,7 @@ 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_attach_correction(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza, const char *const replace_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 dc1cdf27..15c61fa8 100644
--- a/src/xmpp/xmpp.h
+++ b/src/xmpp/xmpp.h
@@ -171,8 +171,7 @@ char* connection_jid_for_feature(const char *const feature);
 
 const char* connection_get_profanity_identifier(void);
 
-char* message_send_chat(const char *const barejid, const char *const msg, const char *const oob_url,
-    gboolean request_receipt);
+char* message_send_chat(const char *const barejid, const char *const msg, const char *const oob_url, gboolean request_receipt, const char *const replace_id);
 char* message_send_chat_otr(const char *const barejid, const char *const msg, gboolean request_receipt);
 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);