1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-09-29 19:56:07 -04:00

Merge pull request #1267 from profanity-im/feature/xep-0308-lmc

XEP-0308 Last Message Correction
This commit is contained in:
Michael Vetter 2020-02-14 11:09:45 +01:00 committed by GitHub
commit c995f3150e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 594 additions and 154 deletions

View File

@ -113,6 +113,8 @@ static char* _status_autocomplete(ProfWin *window, const char *const input, gboo
static char* _logging_autocomplete(ProfWin *window, const char *const input, gboolean previous);
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);
@ -234,6 +236,7 @@ static Autocomplete status_ac;
static Autocomplete status_state_ac;
static Autocomplete logging_ac;
static Autocomplete color_ac;
static Autocomplete correction_ac;
void
cmd_ac_init(void)
@ -928,6 +931,11 @@ cmd_ac_init(void)
autocomplete_add(color_ac, "off");
autocomplete_add(color_ac, "redgreen");
autocomplete_add(color_ac, "blue");
correction_ac = autocomplete_new();
autocomplete_add(correction_ac, "on");
autocomplete_add(correction_ac, "off");
autocomplete_add(correction_ac, "char");
}
void
@ -1233,6 +1241,7 @@ cmd_ac_reset(ProfWin *window)
autocomplete_reset(status_state_ac);
autocomplete_reset(logging_ac);
autocomplete_reset(color_ac);
autocomplete_reset(correction_ac);
autocomplete_reset(script_ac);
if (script_show_ac) {
@ -1380,6 +1389,7 @@ cmd_ac_uninit(void)
autocomplete_free(status_state_ac);
autocomplete_free(logging_ac);
autocomplete_free(color_ac);
autocomplete_free(correction_ac);
}
static void
@ -1630,6 +1640,8 @@ _cmd_ac_complete_params(ProfWin *window, const char *const input, gboolean previ
g_hash_table_insert(ac_funcs, "/logging", _logging_autocomplete);
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];
@ -3713,3 +3725,50 @@ _avatar_autocomplete(ProfWin *window, const char *const input, gboolean previous
return NULL;
}
static char*
_correction_autocomplete(ProfWin *window, const char *const input, gboolean previous)
{
char *result = NULL;
result = autocomplete_param_with_ac(input, "/correction", correction_ac, TRUE, previous);
if (result) {
return result;
}
return NULL;
}
static char*
_correct_autocomplete(ProfWin *window, const char *const input, gboolean previous)
{
char *last_message = NULL;
switch(window->type) {
case WIN_CHAT:
{
ProfChatWin *chatwin = (ProfChatWin*)window;
assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
last_message = chatwin->last_message;
break;
}
case WIN_MUC:
{
ProfMucWin *mucwin = (ProfMucWin*)window;
assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
last_message = mucwin->last_message;
}
default:
break;
}
if (last_message == NULL) {
return NULL;
}
GString *result_str = g_string_new("/correct ");
g_string_append(result_str, last_message);
char *result = result_str->str;
g_string_free(result_str, FALSE);
return result;
}

View File

@ -2361,6 +2361,41 @@ static struct cmd_t command_defs[] =
{ "on|off", ""})
CMD_NOEXAMPLES
},
{ "/correction",
parse_args, 1, 2, &cons_correction_setting,
CMD_NOSUBFUNCS
CMD_MAINFUNC(cmd_correction)
CMD_TAGS(
CMD_TAG_UI,
CMD_TAG_CHAT,
CMD_TAG_GROUPCHAT)
CMD_SYN(
"/correction <on>|<off>",
"/correction char <char>")
CMD_DESC(
"Settings regarding Last Message Correction (XEP-0308). Caution: We do not yet check the 'from' field. So it could happen that someone else is overwriting the actual message.")
CMD_ARGS(
{ "on|off", "Enable/Disable support for last message correction."},
{ "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;

View File

@ -7529,7 +7529,7 @@ cmd_otr_start(ProfWin *window, const char *const command, gchar **args)
if (!otr_is_secure(barejid)) {
char *otr_query_message = otr_start_query();
char *id = message_send_chat_otr(barejid, otr_query_message, FALSE);
char *id = message_send_chat_otr(barejid, otr_query_message, FALSE, NULL);
free(id);
return TRUE;
}
@ -7562,7 +7562,8 @@ cmd_otr_start(ProfWin *window, const char *const command, gchar **args)
}
char *otr_query_message = otr_start_query();
char *id = message_send_chat_otr(chatwin->barejid, otr_query_message, FALSE);
char *id = message_send_chat_otr(chatwin->barejid, otr_query_message, FALSE, NULL);
free(id);
return TRUE;
}
@ -8651,3 +8652,77 @@ cmd_os(ProfWin *window, const char *const command, gchar **args)
return TRUE;
}
gboolean
cmd_correction(ProfWin *window, const char *const command, gchar **args)
{
// enable/disable
if (g_strcmp0(args[0], "on") == 0) {
_cmd_set_boolean_preference(args[0], command, "Last Message Correction", PREF_CORRECTION_ALLOW);
caps_add_feature(XMPP_FEATURE_LAST_MESSAGE_CORRECTION);
return TRUE;
} else if (g_strcmp0(args[0], "off") == 0) {
_cmd_set_boolean_preference(args[0], command, "Last Message Correction", PREF_CORRECTION_ALLOW);
caps_remove_feature(XMPP_FEATURE_LAST_MESSAGE_CORRECTION);
return TRUE;
}
// char
if (g_strcmp0(args[0], "char") == 0) {
if (args[1] == NULL) {
cons_bad_cmd_usage(command);
} else if (strlen(args[1]) != 1) {
cons_bad_cmd_usage(command);
} else {
prefs_set_correction_char(args[1][0]);
cons_show("LMC char set to %c.", args[1][0]);
}
}
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;
}
// send message again, with replace flag
gchar *message = g_strjoinv(" ", args);
cl_ev_send_msg_correct(chatwin, message, FALSE, TRUE);
free(message);
return TRUE;
} else if (window->type == WIN_MUC) {
ProfMucWin *mucwin = (ProfMucWin*)window;
assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
if (mucwin->last_msg_id == NULL || mucwin->last_message == NULL) {
win_println(window, THEME_DEFAULT, '!', "No last message to correct.");
return TRUE;
}
// send message again, with replace flag
gchar *message = g_strjoinv(" ", args);
cl_ev_send_muc_msg_corrected(mucwin, message, FALSE, TRUE);
free(message);
return TRUE;
}
win_println(window, THEME_DEFAULT, '!', "Command /correct only valid in regular chat windows.");
return TRUE;
}

View File

@ -54,7 +54,7 @@ typedef struct cmd_help_t {
* cmd - The command string including leading '/'
* parser - The function used to parse arguments
* min_args - Minimum number of arguments
* max_args - Maximum number of arguments
* max_args - Maximum number of arguments, -1 for infinite
* setting_func - Function to display current settings to the console
* sub_funcs - Optional list of functions mapped to the first argument
* func - Main function to call when no arguments, or sub_funcs not implemented
@ -227,4 +227,6 @@ gboolean cmd_paste(ProfWin *window, const char *const command, gchar **args);
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

View File

@ -1201,6 +1201,32 @@ prefs_set_roster_presence_indent(gint value)
g_key_file_set_integer(prefs, PREF_GROUP_UI, "roster.presence.indent", value);
}
char
prefs_get_correction_char(void)
{
char result = '+';
char *resultstr = g_key_file_get_string(prefs, PREF_GROUP_UI, "correction.char", NULL);
if (!resultstr) {
result = '+';
} else {
result = resultstr[0];
}
free(resultstr);
return result;
}
void
prefs_set_correction_char(char ch)
{
char str[2];
str[0] = ch;
str[1] = '\0';
g_key_file_set_string(prefs, PREF_GROUP_UI, "correction.char", str);
}
gboolean
prefs_add_room_notify_trigger(const char * const text)
{
@ -1760,6 +1786,7 @@ _get_group(preference_t pref)
case PREF_RECEIPTS_REQUEST:
case PREF_REVEAL_OS:
case PREF_TLS_CERTPATH:
case PREF_CORRECTION_ALLOW:
return PREF_GROUP_CONNECTION;
case PREF_OTR_LOG:
case PREF_OTR_POLICY:
@ -2010,6 +2037,8 @@ _get_key(preference_t pref)
return "log";
case PREF_OMEMO_POLICY:
return "policy";
case PREF_CORRECTION_ALLOW:
return "correction.allow";
default:
return NULL;
}

View File

@ -161,6 +161,7 @@ typedef enum {
PREF_OMEMO_LOG,
PREF_OMEMO_POLICY,
PREF_OCCUPANTS_WRAP,
PREF_CORRECTION_ALLOW,
} preference_t;
typedef struct prof_alias_t {
@ -268,6 +269,9 @@ void prefs_set_roster_presence_indent(gint value);
gint prefs_get_occupants_indent(void);
void prefs_set_occupants_indent(gint value);
char prefs_get_correction_char(void);
void prefs_set_correction_char(char ch);
void prefs_add_login(const char *jid);
void prefs_set_tray_timer(gint value);

View File

@ -483,6 +483,14 @@ _load_preferences(void)
}
}
if (g_key_file_has_key(theme, "ui", "correction.char", NULL)) {
gchar *ch = g_key_file_get_string(theme, "ui", "correction.char", NULL);
if (ch && strlen(ch) > 0) {
prefs_set_omemo_char(ch[0]);
g_free(ch);
}
}
// load window positions
if (g_key_file_has_key(theme, "ui", "titlebar.position", NULL) &&
g_key_file_has_key(theme, "ui", "mainwin.position", NULL) &&

View File

@ -115,45 +115,37 @@ 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);
gboolean request_receipt = FALSE;
if (prefs_get_boolean(PREF_RECEIPTS_REQUEST)) {
char *session_jid = chat_session_get_jid(chatwin->barejid);
if (session_jid) {
Jid *session_jidp = jid_create(session_jid);
if (session_jidp && session_jidp->resourcepart) {
if (caps_jid_has_feature(session_jid, XMPP_FEATURE_RECEIPTS)) {
request_receipt = TRUE;
}
}
jid_destroy(session_jidp);
free(session_jid);
}
}
gboolean request_receipt = prefs_get_boolean(PREF_RECEIPTS_REQUEST);
char *plugin_msg = plugins_pre_chat_message_send(chatwin->barejid, msg);
if (plugin_msg == NULL) {
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) {
char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg, request_receipt);
char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg, request_receipt, replace_id);
chat_log_pgp_msg_out(chatwin->barejid, plugin_msg, NULL);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PGP, request_receipt);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PGP, request_receipt, replace_id);
free(id);
} else {
gboolean handled = otr_on_message_send(chatwin, plugin_msg, request_receipt);
gboolean handled = otr_on_message_send(chatwin, plugin_msg, request_receipt, replace_id);
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);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt, replace_id);
free(id);
}
}
@ -169,9 +161,9 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
#ifdef HAVE_LIBOTR
#ifndef HAVE_LIBGPGME
#ifndef HAVE_OMEMO
gboolean handled = otr_on_message_send(chatwin, plugin_msg, request_receipt);
gboolean handled = otr_on_message_send(chatwin, plugin_msg, request_receipt, replace_id);
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);
@ -189,14 +181,14 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
#ifdef HAVE_LIBGPGME
#ifndef HAVE_OMEMO
if (chatwin->pgp_send) {
char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg, request_receipt);
char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg, request_receipt, replace_id);
chat_log_pgp_msg_out(chatwin->barejid, plugin_msg, NULL);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PGP, request_receipt);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PGP, request_receipt, replace_id);
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);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt, replace_id);
free(id);
}
@ -212,14 +204,14 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
#ifndef HAVE_LIBGPGME
#ifdef HAVE_OMEMO
if (chatwin->is_omemo) {
char *id = omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE);
char *id = omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE, replace_id);
chat_log_omemo_msg_out(chatwin->barejid, plugin_msg, NULL);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_OMEMO, request_receipt);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_OMEMO, request_receipt, replace_id);
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);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt, replace_id);
free(id);
}
@ -235,16 +227,16 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
#ifndef HAVE_LIBGPGME
#ifdef HAVE_OMEMO
if (chatwin->is_omemo) {
char *id = omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE);
char *id = omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE, replace_id);
chat_log_omemo_msg_out(chatwin->barejid, plugin_msg, NULL);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_OMEMO, request_receipt);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_OMEMO, request_receipt, replace_id);
free(id);
} else {
gboolean handled = otr_on_message_send(chatwin, plugin_msg, request_receipt);
gboolean handled = otr_on_message_send(chatwin, plugin_msg, request_receipt, replace_id);
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);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt, replace_id);
free(id);
}
}
@ -261,19 +253,19 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
#ifdef HAVE_LIBGPGME
#ifdef HAVE_OMEMO
if (chatwin->is_omemo) {
char *id = omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE);
char *id = omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE, replace_id);
chat_log_omemo_msg_out(chatwin->barejid, plugin_msg, NULL);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_OMEMO, request_receipt);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_OMEMO, request_receipt, replace_id);
free(id);
} else if (chatwin->pgp_send) {
char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg, request_receipt);
char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg, request_receipt, replace_id);
chat_log_pgp_msg_out(chatwin->barejid, plugin_msg, NULL);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PGP, request_receipt);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PGP, request_receipt, replace_id);
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);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt, replace_id);
free(id);
}
@ -289,21 +281,21 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
#ifdef HAVE_LIBGPGME
#ifdef HAVE_OMEMO
if (chatwin->is_omemo) {
char *id = omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE);
char *id = omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE, replace_id);
chat_log_omemo_msg_out(chatwin->barejid, plugin_msg, NULL);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_OMEMO, request_receipt);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_OMEMO, request_receipt, replace_id);
free(id);
} else if (chatwin->pgp_send) {
char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg, request_receipt);
char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg, request_receipt, replace_id);
chat_log_pgp_msg_out(chatwin->barejid, plugin_msg, NULL);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PGP, request_receipt);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PGP, request_receipt, replace_id);
free(id);
} else {
gboolean handled = otr_on_message_send(chatwin, plugin_msg, request_receipt);
gboolean handled = otr_on_message_send(chatwin, plugin_msg, request_receipt, replace_id);
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);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt, replace_id);
free(id);
}
}
@ -319,9 +311,9 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
#ifndef HAVE_LIBOTR
#ifndef HAVE_LIBGPGME
#ifndef HAVE_OMEMO
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);
chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt, replace_id);
free(id);
plugins_post_chat_message_send(chatwin->barejid, plugin_msg);
@ -333,23 +325,34 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
}
void
cl_ev_send_muc_msg(ProfMucWin *mucwin, const char *const msg, const char *const oob_url)
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_corrected(ProfMucWin *mucwin, const char *const msg, const char *const oob_url, gboolean correct_last_msg)
{
char *plugin_msg = plugins_pre_room_message_send(mucwin->roomjid, msg);
if (plugin_msg == NULL) {
return;
}
char *replace_id = NULL;
if (correct_last_msg) {
replace_id = mucwin->last_msg_id;
}
#ifdef HAVE_OMEMO
if (mucwin->is_omemo) {
char *id = omemo_on_message_send((ProfWin *)mucwin, plugin_msg, FALSE, TRUE);
char *id = omemo_on_message_send((ProfWin *)mucwin, plugin_msg, FALSE, TRUE, replace_id);
groupchat_log_omemo_msg_out(mucwin->roomjid, plugin_msg);
mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_ENC_OMEMO);
mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_ENC_OMEMO, replace_id);
free(id);
} else {
char *id = message_send_groupchat(mucwin->roomjid, plugin_msg, oob_url);
char *id = message_send_groupchat(mucwin->roomjid, plugin_msg, oob_url, replace_id);
groupchat_log_msg_out(mucwin->roomjid, plugin_msg);
mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_ENC_PLAIN);
mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, replace_id);
free(id);
}
@ -359,9 +362,9 @@ cl_ev_send_muc_msg(ProfMucWin *mucwin, const char *const msg, const char *const
#endif
#ifndef HAVE_OMEMO
char *id = message_send_groupchat(mucwin->roomjid, plugin_msg, oob_url);
char *id = message_send_groupchat(mucwin->roomjid, plugin_msg, oob_url, replace_id);
groupchat_log_msg_out(mucwin->roomjid, plugin_msg);
mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_ENC_PLAIN);
mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, replace_id);
free(id);
plugins_post_room_message_send(mucwin->roomjid, plugin_msg);
@ -370,6 +373,12 @@ cl_ev_send_muc_msg(ProfMucWin *mucwin, const char *const msg, const char *const
#endif
}
void
cl_ev_send_muc_msg(ProfMucWin *mucwin, const char *const msg, const char *const oob_url)
{
cl_ev_send_muc_msg_corrected(mucwin, msg, oob_url, FALSE);
}
void
cl_ev_send_priv_msg(ProfPrivateWin *privwin, const char *const msg, const char *const oob_url)
{

View File

@ -45,7 +45,9 @@ 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_corrected(ProfMucWin *mucwin, const char *const msg, const char *const oob_url, gboolean correct_last_msg);
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);

View File

@ -671,7 +671,7 @@ out:
}
char *
omemo_on_message_send(ProfWin *win, const char *const message, gboolean request_receipt, gboolean muc)
omemo_on_message_send(ProfWin *win, const char *const message, gboolean request_receipt, gboolean muc, const char *const replace_id)
{
char *id = NULL;
int res;
@ -809,11 +809,11 @@ omemo_on_message_send(ProfWin *win, const char *const message, gboolean request_
if (muc) {
ProfMucWin *mucwin = (ProfMucWin *)win;
assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
id = message_send_chat_omemo(mucwin->roomjid, omemo_ctx.device_id, keys, iv, AES128_GCM_IV_LENGTH, ciphertext, ciphertext_len, request_receipt, TRUE);
id = message_send_chat_omemo(mucwin->roomjid, omemo_ctx.device_id, keys, iv, AES128_GCM_IV_LENGTH, ciphertext, ciphertext_len, request_receipt, TRUE, replace_id);
} else {
ProfChatWin *chatwin = (ProfChatWin *)win;
assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
id = message_send_chat_omemo(chatwin->barejid, omemo_ctx.device_id, keys, iv, AES128_GCM_IV_LENGTH, ciphertext, ciphertext_len, request_receipt, FALSE);
id = message_send_chat_omemo(chatwin->barejid, omemo_ctx.device_id, keys, iv, AES128_GCM_IV_LENGTH, ciphertext, ciphertext_len, request_receipt, FALSE, replace_id);
}
out:

View File

@ -92,5 +92,5 @@ void omemo_start_muc_sessions(const char *const roomjid);
void omemo_start_device_session(const char *const jid, uint32_t device_id, GList *prekeys, uint32_t signed_prekey_id, const unsigned char *const signed_prekey, size_t signed_prekey_len, const unsigned char *const signature, size_t signature_len, const unsigned char *const identity_key, size_t identity_key_len);
gboolean omemo_loaded(void);
char * omemo_on_message_send(ProfWin *win, const char *const message, gboolean request_receipt, gboolean muc);
char * omemo_on_message_send(ProfWin *win, const char *const message, gboolean request_receipt, gboolean muc, const char *const replace_id);
char * omemo_on_message_recv(const char *const from, uint32_t sid, const unsigned char *const iv, size_t iv_len, GList *keys, const unsigned char *const payload, size_t payload_len, gboolean muc, gboolean *trusted);

View File

@ -118,7 +118,7 @@ static void
cb_inject_message(void *opdata, const char *accountname,
const char *protocol, const char *recipient, const char *message)
{
char *id = message_send_chat_otr(recipient, message, FALSE);
char *id = message_send_chat_otr(recipient, message, FALSE, NULL);
free(id);
}
@ -315,7 +315,7 @@ otr_on_message_recv(const char *const barejid, const char *const resource, const
memmove(whitespace_base, whitespace_base+tag_length, tag_length);
char *otr_query_message = otr_start_query();
cons_show("OTR Whitespace pattern detected. Attempting to start OTR session...");
char *id = message_send_chat_otr(barejid, otr_query_message, FALSE);
char *id = message_send_chat_otr(barejid, otr_query_message, FALSE, NULL);
free(id);
}
}
@ -329,7 +329,7 @@ otr_on_message_recv(const char *const barejid, const char *const resource, const
if (policy == PROF_OTRPOLICY_ALWAYS && *decrypted == FALSE && !whitespace_base) {
char *otr_query_message = otr_start_query();
cons_show("Attempting to start OTR session...");
char *id = message_send_chat_otr(barejid, otr_query_message, FALSE);
char *id = message_send_chat_otr(barejid, otr_query_message, FALSE, NULL);
free(id);
}
@ -337,7 +337,7 @@ otr_on_message_recv(const char *const barejid, const char *const resource, const
}
gboolean
otr_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean request_receipt)
otr_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean request_receipt, const char *const replace_id)
{
char *id = NULL;
prof_otrpolicy_t policy = otr_get_policy(chatwin->barejid);
@ -346,9 +346,9 @@ otr_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean re
if (otr_is_secure(chatwin->barejid)) {
char *encrypted = otr_encrypt_message(chatwin->barejid, message);
if (encrypted) {
id = message_send_chat_otr(chatwin->barejid, encrypted, request_receipt);
id = message_send_chat_otr(chatwin->barejid, encrypted, request_receipt, replace_id);
chat_log_otr_msg_out(chatwin->barejid, message, NULL);
chatwin_outgoing_msg(chatwin, message, id, PROF_MSG_ENC_OTR, request_receipt);
chatwin_outgoing_msg(chatwin, message, id, PROF_MSG_ENC_OTR, request_receipt, replace_id);
otr_free_message(encrypted);
free(id);
return TRUE;
@ -367,8 +367,8 @@ otr_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean re
// tag and send for policy opportunistic
if (policy == PROF_OTRPOLICY_OPPORTUNISTIC) {
char *otr_tagged_msg = otr_tag_message(message);
id = message_send_chat_otr(chatwin->barejid, otr_tagged_msg, request_receipt);
chatwin_outgoing_msg(chatwin, message, id, PROF_MSG_ENC_PLAIN, request_receipt);
id = message_send_chat_otr(chatwin->barejid, otr_tagged_msg, request_receipt, replace_id);
chatwin_outgoing_msg(chatwin, message, id, PROF_MSG_ENC_PLAIN, request_receipt, replace_id);
chat_log_msg_out(chatwin->barejid, message, NULL);
free(otr_tagged_msg);
free(id);

View File

@ -73,7 +73,7 @@ void otr_poll(void);
void otr_on_connect(ProfAccount *account);
char* otr_on_message_recv(const char *const barejid, const char *const resource, const char *const message, gboolean *decrypted);
gboolean otr_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean request_receipt);
gboolean otr_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean request_receipt, const char *const replace_id);
void otr_keygen(ProfAccount *account);

View File

@ -48,7 +48,7 @@
*
* inp - The line of input
* min - The minimum allowed number of arguments
* max - The maximum allowed number of arguments
* max - The maximum allowed number of arguments, -1 for infinite
*
* Returns - An NULL terminated array of strings representing the arguments
* of the command, or NULL if the validation fails.
@ -135,7 +135,7 @@ parse_args(const char *const inp, int min, int max, gboolean *result)
int num = g_slist_length(tokens) - 1;
// if num args not valid return NULL
if ((num < min) || (num > max)) {
if ((num < min) || ((max != -1) && (num > max))) {
g_slist_free_full(tokens, free);
g_free(copy);
*result = FALSE;

View File

@ -3,6 +3,7 @@
* vim: expandtab:ts=4:sts=4:sw=4
*
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
* Copyright (C) 2019 - 2020 Michael Vetter <jubalh@iodoru.org>
*
* This file is part of Profanity.
*
@ -81,7 +82,7 @@ buffer_free(ProfBuff buffer)
void
buffer_append(ProfBuff buffer, 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, const char *const id)
int flags, theme_item_t theme_item, const char *const display_from, const char *const message, DeliveryReceipt *receipt, const char *const id)
{
ProfBuffEntry *e = malloc(sizeof(struct prof_buff_entry_t));
e->show_char = show_char;
@ -89,7 +90,7 @@ buffer_append(ProfBuff buffer, const char show_char, int pad_indent, GDateTime *
e->flags = flags;
e->theme_item = theme_item;
e->time = g_date_time_ref(time);
e->from = from ? strdup(from) : NULL;
e->display_from = display_from ? strdup(display_from) : NULL;
e->message = strdup(message);
e->receipt = receipt;
if (id) {
@ -163,7 +164,7 @@ static void
_free_entry(ProfBuffEntry *entry)
{
free(entry->message);
free(entry->from);
free(entry->display_from);
free(entry->id);
free(entry->receipt);
g_date_time_unref(entry->time);

View File

@ -3,6 +3,7 @@
* vim: expandtab:ts=4:sts=4:sw=4
*
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
* Copyright (C) 2019 - 2020 Michael Vetter <jubalh@iodoru.org>
*
* This file is part of Profanity.
*
@ -51,7 +52,9 @@ typedef struct prof_buff_entry_t {
GDateTime *time;
int flags;
theme_item_t theme_item;
char *from;
// from as it is displayed
// might be nick, jid..
char *display_from;
char *message;
DeliveryReceipt *receipt;
// message id, in case we have it
@ -63,7 +66,7 @@ typedef struct prof_buff_t *ProfBuff;
ProfBuff buffer_create();
void buffer_free(ProfBuff buffer);
void buffer_append(ProfBuff buffer, 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, const char *const id);
int flags, theme_item_t theme_item, const char *const display_from, const char *const message, DeliveryReceipt *receipt, const char *const id);
void buffer_remove_entry_by_id(ProfBuff buffer, const char *const id);
int buffer_size(ProfBuff buffer);
ProfBuffEntry* buffer_get_entry(ProfBuff buffer, int entry);

View File

@ -3,6 +3,7 @@
* vim: expandtab:ts=4:sts=4:sw=4
*
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
* Copyright (C) 2019 - 2020 Michael Vetter <jubalh@iodoru.org>
*
* This file is part of Profanity.
*
@ -56,6 +57,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)
@ -308,7 +310,7 @@ chatwin_incoming_msg(ProfChatWin *chatwin, ProfMessage *message, gboolean win_cr
void
chatwin_outgoing_msg(ProfChatWin *chatwin, const char *const message, char *id, prof_enc_t enc_mode,
gboolean request_receipt)
gboolean request_receipt, const char *const replace_id)
{
assert(chatwin != NULL);
@ -324,9 +326,14 @@ chatwin_outgoing_msg(ProfChatWin *chatwin, const char *const message, char *id,
}
if (request_receipt && id) {
win_print_with_receipt((ProfWin*)chatwin, enc_char, "me", message, id);
win_print_outgoing_with_receipt((ProfWin*)chatwin, enc_char, "me", message, id, replace_id);
} else {
win_print_outgoing((ProfWin*)chatwin, enc_char, "%s", message);
win_print_outgoing((ProfWin*)chatwin, enc_char, id, replace_id, "%s", message);
}
// save last id and message for LMC
if (id) {
_chatwin_set_last_message(chatwin, id, message);
}
}
@ -344,7 +351,7 @@ chatwin_outgoing_carbon(ProfChatWin *chatwin, ProfMessage *message)
ProfWin *window = (ProfWin*)chatwin;
win_print_outgoing(window, enc_char, "%s", message->plain);
win_print_outgoing(window, enc_char, message->id, message->replace_id, "%s", message->plain);
int num = wins_get_num(window);
status_bar_active(num, WIN_CHAT, chatwin->barejid);
}
@ -496,3 +503,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);
}

View File

@ -2021,6 +2021,19 @@ cons_os_setting(void)
}
}
void
cons_correction_setting(void)
{
if (prefs_get_boolean(PREF_CORRECTION_ALLOW)) {
cons_show("Last Message Correction (XEP-0308) (/correction) : ON");
} else {
cons_show("Last Message Correction (XEP-0308) (/correction) : OFF");
}
char cc = prefs_get_correction_char();
cons_show("LMC indication char (/correction char) : %c", cc);
}
void
cons_show_connection_prefs(void)
{

View File

@ -50,6 +50,8 @@
#include "omemo/omemo.h"
#endif
static void _mucwin_set_last_message(ProfMucWin *mucwin, const char *const id, const char *const message);
ProfMucWin*
mucwin_new(const char *const barejid)
{
@ -501,7 +503,7 @@ _mucwin_print_triggers(ProfWin *window, const char *const message, GList *trigge
}
void
mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, const char *const id, prof_enc_t enc_mode)
mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, const char *const id, prof_enc_t enc_mode, const char *const replace_id)
{
assert(mucwin != NULL);
@ -519,7 +521,12 @@ mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, const char *c
ch = prefs_get_omemo_char();
}
win_println_me_message(window, ch, mynick, "%s", message);
win_print_outgoing_muc_msg(window, ch, mynick, id, replace_id, "%s", message);
// save last id and message for LMC
if (id) {
_mucwin_set_last_message(mucwin, id, message);
}
}
void
@ -559,7 +566,7 @@ mucwin_incoming_msg(ProfMucWin *mucwin, ProfMessage *message, GSList *mentions,
win_print_them(window, THEME_ROOMTRIGGER, ch, flags, message->jid->resourcepart);
_mucwin_print_triggers(window, message->plain, triggers);
} else {
win_println_them_message(window, ch, flags, message->jid->resourcepart, "%s", message->plain);
win_println_incoming_muc_msg(window, ch, flags, message->jid->resourcepart, message->id, message->replace_id, "%s", message->plain);
}
}
@ -951,3 +958,13 @@ mucwin_unset_message_char(ProfMucWin *mucwin)
mucwin->message_char = NULL;
}
}
static void
_mucwin_set_last_message(ProfMucWin *mucwin, const char *const id, const char *const message)
{
free(mucwin->last_message);
mucwin->last_message = strdup(message);
free(mucwin->last_msg_id);
mucwin->last_msg_id = strdup(id);
}

View File

@ -95,7 +95,7 @@ privwin_outgoing_msg(ProfPrivateWin *privwin, const char *const message)
{
assert(privwin != NULL);
win_print_outgoing((ProfWin*)privwin, '-', "%s", message);
win_print_outgoing((ProfWin*)privwin, '-', NULL, NULL ,"%s", message);
}
void

View File

@ -124,8 +124,7 @@ ProfChatWin* chatwin_new(const char *const barejid);
void chatwin_incoming_msg(ProfChatWin *chatwin, ProfMessage *message, gboolean win_created);
void chatwin_receipt_received(ProfChatWin *chatwin, const char *const id);
void chatwin_recipient_gone(ProfChatWin *chatwin);
void chatwin_outgoing_msg(ProfChatWin *chatwin, const char *const message, char *id, prof_enc_t enc_mode,
gboolean request_receipt);
void chatwin_outgoing_msg(ProfChatWin *chatwin, const char *const message, char *id, prof_enc_t enc_mode, gboolean request_receipt, const char *const replace_id);
void chatwin_outgoing_carbon(ProfChatWin *chatwin, ProfMessage *message);
void chatwin_contact_online(ProfChatWin *chatwin, Resource *resource, GDateTime *last_activity);
void chatwin_contact_offline(ProfChatWin *chatwin, char *resource, char *status);
@ -159,7 +158,7 @@ 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, const char *const id, prof_enc_t enc_mode);
void mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, const char *const id, prof_enc_t enc_mode, const char *const replace_id);
void mucwin_incoming_msg(ProfMucWin *mucwin, ProfMessage *message, GSList *mentions, GList *triggers);
void mucwin_subject(ProfMucWin *mucwin, const char *const nick, const char *const subject);
void mucwin_requires_config(ProfMucWin *mucwin);
@ -319,6 +318,7 @@ void cons_statusbar_setting(void);
void cons_winpos_setting(void);
void cons_color_setting(void);
void cons_os_setting(void);
void cons_correction_setting(void);
void cons_show_contact_online(PContact contact, Resource *resource, GDateTime *last_activity);
void cons_show_contact_offline(PContact contact, char *resource, char *status);
void cons_theme_properties(void);

View File

@ -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 {
@ -175,6 +178,9 @@ typedef struct prof_muc_win_t {
char *enctext;
char *message_char;
GDateTime *last_msg_timestamp;
// For LMC
char *last_message;
char *last_msg_id;
} ProfMucWin;
typedef struct prof_conf_win_t ProfConfWin;

View File

@ -3,6 +3,7 @@
* vim: expandtab:ts=4:sts=4:sw=4
*
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
* Copyright (C) 2019 - 2020 Michael Vetter <jubalh@iodoru.org>
*
* This file is part of Profanity.
*
@ -49,6 +50,7 @@
#include <ncurses.h>
#endif
#include "log.h"
#include "config/theme.h"
#include "config/preferences.h"
#include "ui/ui.h"
@ -62,9 +64,8 @@
#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_print(ProfWin *window, const char show_char, int pad_indent, GDateTime *time,
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_internal(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);
@ -151,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;
@ -200,6 +203,8 @@ win_create_muc(const char *const roomjid)
new_win->enctext = NULL;
new_win->message_char = NULL;
new_win->is_omemo = FALSE;
new_win->last_message = NULL;
new_win->last_msg_id = NULL;
new_win->memcheck = PROFMUCWIN_MEMCHECK;
@ -487,6 +492,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;
}
@ -1055,8 +1062,43 @@ win_show_status_string(ProfWin *window, const char *const from,
win_appendln(window, presence_colour, "");
}
static void
_win_correct(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;
}
/*TODO: set date?
if (entry->date) {
if (entry->date->timestamp) {
g_date_time_unref(entry->date->timestamp);
}
free(entry->date);
}
entry->date = buffer_date_new_now();
*/
entry->show_char = prefs_get_correction_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)
win_print_incoming(ProfWin *window, const char *const display_name_from, ProfMessage *message)
{
char enc_char = '-';
int flags = NO_ME;
@ -1079,11 +1121,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 (prefs_get_boolean(PREF_CORRECTION_ALLOW) && message->replace_id) {
_win_correct(window, message->plain, message->id, message->replace_id);
} else {
_win_printf(window, enc_char, 0, message->timestamp, flags, THEME_TEXT_THEM, display_name_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, display_name_from, message->id, "%s", message->plain);
break;
default:
assert(FALSE);
@ -1094,12 +1141,13 @@ 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
win_println_them_message(ProfWin *window, char ch, int flags, const char *const them, const char *const message, ...)
win_println_incoming_muc_msg(ProfWin *window, char ch, int flags, const char *const them, const char *const id, const char *const replace_id, const char *const message, ...)
{
//TODO: we always use current timestamp here. instead of the message->timestamp one if available. i think somewhere else we check whether it exists first.
GDateTime *timestamp = g_date_time_new_now_local();
va_list arg;
@ -1107,9 +1155,14 @@ win_println_them_message(ProfWin *window, char ch, int flags, const char *const
GString *fmt_msg = g_string_new(NULL);
g_string_vprintf(fmt_msg, message, arg);
buffer_append(window->layout->buffer, ch, 0, timestamp, flags | NO_ME, THEME_TEXT_THEM, them, fmt_msg->str, NULL, NULL);
if (prefs_get_boolean(PREF_CORRECTION_ALLOW) && replace_id) {
_win_correct(window, fmt_msg->str, id, replace_id);
} else {
_win_printf(window, ch, 0, timestamp, flags | NO_ME, THEME_TEXT_THEM, them, id, "%s", fmt_msg->str);
}
// buffer_append(window->layout->buffer, ch, 0, timestamp, flags | NO_ME, THEME_TEXT_THEM, them, fmt_msg->str, NULL, NULL);
// _win_print_internal(window, ch, 0, timestamp, flags | NO_ME, THEME_TEXT_THEM, them, fmt_msg->str, NULL);
_win_print(window, ch, 0, timestamp, flags | NO_ME, THEME_TEXT_THEM, them, fmt_msg->str, NULL);
inp_nonblocking(TRUE);
g_date_time_unref(timestamp);
@ -1118,7 +1171,7 @@ win_println_them_message(ProfWin *window, char ch, int flags, const char *const
}
void
win_println_me_message(ProfWin *window, char ch, const char *const me, const char *const message, ...)
win_print_outgoing_muc_msg(ProfWin *window, char ch, const char *const me, const char *const id, const char *const replace_id, const char *const message, ...)
{
GDateTime *timestamp = g_date_time_new_now_local();
@ -1127,9 +1180,14 @@ win_println_me_message(ProfWin *window, char ch, const char *const me, const cha
GString *fmt_msg = g_string_new(NULL);
g_string_vprintf(fmt_msg, message, arg);
buffer_append(window->layout->buffer, ch, 0, timestamp, 0, THEME_TEXT_ME, me, fmt_msg->str, NULL, NULL);
if (prefs_get_boolean(PREF_CORRECTION_ALLOW) && replace_id) {
_win_correct(window, fmt_msg->str, id, replace_id);
} else {
_win_printf(window, ch, 0, timestamp, 0, THEME_TEXT_ME, me, id, "%s", fmt_msg->str);
}
// buffer_append(window->layout->buffer, ch, 0, timestamp, 0, THEME_TEXT_ME, me, fmt_msg->str, NULL, NULL);
// _win_print_internal(window, ch, 0, timestamp, 0, THEME_TEXT_ME, me, fmt_msg->str, NULL);
_win_print(window, ch, 0, timestamp, 0, THEME_TEXT_ME, me, fmt_msg->str, NULL);
inp_nonblocking(TRUE);
g_date_time_unref(timestamp);
@ -1138,7 +1196,7 @@ win_println_me_message(ProfWin *window, char ch, const char *const me, const cha
}
void
win_print_outgoing(ProfWin *window, const char ch, const char *const message, ...)
win_print_outgoing(ProfWin *window, const char ch, const char *const id, const char *const replace_id, const char *const message, ...)
{
GDateTime *timestamp = g_date_time_new_now_local();
@ -1147,9 +1205,12 @@ win_print_outgoing(ProfWin *window, const char ch, const char *const message, ..
GString *fmt_msg = g_string_new(NULL);
g_string_vprintf(fmt_msg, message, arg);
buffer_append(window->layout->buffer, ch, 0, timestamp, 0, THEME_TEXT_ME, "me", fmt_msg->str, NULL, NULL);
if (replace_id) {
_win_correct(window, fmt_msg->str, id, replace_id);
} else {
_win_printf(window, ch, 0, timestamp, 0, THEME_TEXT_THEM, "me", id, "%s", fmt_msg->str);
}
_win_print(window, ch, 0, timestamp, 0, THEME_TEXT_ME, "me", fmt_msg->str, NULL);
inp_nonblocking(TRUE);
g_date_time_unref(timestamp);
@ -1168,7 +1229,7 @@ win_print_history(ProfWin *window, GDateTime *timestamp, const char *const messa
g_string_vprintf(fmt_msg, message, arg);
buffer_append(window->layout->buffer, '-', 0, timestamp, 0, THEME_TEXT_HISTORY, "", fmt_msg->str, NULL, NULL);
_win_print(window, '-', 0, timestamp, 0, THEME_TEXT_HISTORY, "", fmt_msg->str, NULL);
_win_print_internal(window, '-', 0, timestamp, 0, THEME_TEXT_HISTORY, "", fmt_msg->str, NULL);
inp_nonblocking(TRUE);
g_date_time_unref(timestamp);
@ -1188,8 +1249,8 @@ win_print(ProfWin *window, theme_item_t theme_item, const char ch, const char *c
g_string_vprintf(fmt_msg, message, arg);
buffer_append(window->layout->buffer, ch, 0, timestamp, NO_EOL, theme_item, "", fmt_msg->str, NULL, NULL);
_win_print_internal(window, ch, 0, timestamp, NO_EOL, theme_item, "", fmt_msg->str, NULL);
_win_print(window, ch, 0, timestamp, NO_EOL, theme_item, "", fmt_msg->str, NULL);
inp_nonblocking(TRUE);
g_date_time_unref(timestamp);
@ -1208,8 +1269,8 @@ win_println(ProfWin *window, theme_item_t theme_item, const char ch, const char
g_string_vprintf(fmt_msg, message, arg);
buffer_append(window->layout->buffer, ch, 0, timestamp, 0, theme_item, "", fmt_msg->str, NULL, NULL);
_win_print_internal(window, ch, 0, timestamp, 0, theme_item, "", fmt_msg->str, NULL);
_win_print(window, ch, 0, timestamp, 0, theme_item, "", fmt_msg->str, NULL);
inp_nonblocking(TRUE);
g_date_time_unref(timestamp);
@ -1228,8 +1289,8 @@ win_println_indent(ProfWin *window, int pad, const char *const message, ...)
g_string_vprintf(fmt_msg, message, arg);
buffer_append(window->layout->buffer, '-', pad, timestamp, 0, THEME_DEFAULT, "", fmt_msg->str, NULL, NULL);
_win_print_internal(window, '-', pad, timestamp, 0, THEME_DEFAULT, "", fmt_msg->str, NULL);
_win_print(window, '-', pad, timestamp, 0, THEME_DEFAULT, "", fmt_msg->str, NULL);
inp_nonblocking(TRUE);
g_date_time_unref(timestamp);
@ -1248,8 +1309,8 @@ win_append(ProfWin *window, theme_item_t theme_item, const char *const message,
g_string_vprintf(fmt_msg, message, arg);
buffer_append(window->layout->buffer, '-', 0, timestamp, NO_DATE | NO_EOL, theme_item, "", fmt_msg->str, NULL, NULL);
_win_print_internal(window, '-', 0, timestamp, NO_DATE | NO_EOL, theme_item, "", fmt_msg->str, NULL);
_win_print(window, '-', 0, timestamp, NO_DATE | NO_EOL, theme_item, "", fmt_msg->str, NULL);
inp_nonblocking(TRUE);
g_date_time_unref(timestamp);
@ -1268,8 +1329,8 @@ win_appendln(ProfWin *window, theme_item_t theme_item, const char *const message
g_string_vprintf(fmt_msg, message, arg);
buffer_append(window->layout->buffer, '-', 0, timestamp, NO_DATE, theme_item, "", fmt_msg->str, NULL, NULL);
_win_print_internal(window, '-', 0, timestamp, NO_DATE, theme_item, "", fmt_msg->str, NULL);
_win_print(window, '-', 0, timestamp, NO_DATE, theme_item, "", fmt_msg->str, NULL);
inp_nonblocking(TRUE);
g_date_time_unref(timestamp);
@ -1288,8 +1349,8 @@ win_append_highlight(ProfWin *window, theme_item_t theme_item, const char *const
g_string_vprintf(fmt_msg, message, arg);
buffer_append(window->layout->buffer, '-', 0, timestamp, NO_DATE | NO_ME | NO_EOL, theme_item, "", fmt_msg->str, NULL, NULL);
_win_print_internal(window, '-', 0, timestamp, NO_DATE | NO_ME | NO_EOL, theme_item, "", fmt_msg->str, NULL);
_win_print(window, '-', 0, timestamp, NO_DATE | NO_ME | NO_EOL, theme_item, "", fmt_msg->str, NULL);
inp_nonblocking(TRUE);
g_date_time_unref(timestamp);
@ -1308,8 +1369,8 @@ win_appendln_highlight(ProfWin *window, theme_item_t theme_item, const char *con
g_string_vprintf(fmt_msg, message, arg);
buffer_append(window->layout->buffer, '-', 0, timestamp, NO_DATE | NO_ME, theme_item, "", fmt_msg->str, NULL, NULL);
_win_print_internal(window, '-', 0, timestamp, NO_DATE | NO_ME, theme_item, "", fmt_msg->str, NULL);
_win_print(window, '-', 0, timestamp, NO_DATE | NO_ME, theme_item, "", fmt_msg->str, NULL);
inp_nonblocking(TRUE);
g_date_time_unref(timestamp);
@ -1320,19 +1381,24 @@ win_appendln_highlight(ProfWin *window, theme_item_t theme_item, const char *con
void
win_print_http_upload(ProfWin *window, const char *const message, char *url)
{
win_print_with_receipt(window, '!', NULL, message, url);
win_print_outgoing_with_receipt(window, '!', NULL, message, url, NULL);
}
void
win_print_with_receipt(ProfWin *window, const char show_char, const char *const from, const char *const message, char *id)
win_print_outgoing_with_receipt(ProfWin *window, const char show_char, const char *const from, const char *const message, char *id, const char *const replace_id)
{
GDateTime *time = g_date_time_new_now_local();
DeliveryReceipt *receipt = malloc(sizeof(struct delivery_receipt_t));
receipt->received = FALSE;
buffer_append(window->layout->buffer, show_char, 0, time, 0, THEME_TEXT_ME, from, message, receipt, id);
_win_print(window, show_char, 0, time, 0, THEME_TEXT_ME, from, message, receipt);
if (replace_id) {
_win_correct(window, message, id, replace_id);
} else {
buffer_append(window->layout->buffer, show_char, 0, time, 0, THEME_TEXT_ME, from, message, receipt, id);
_win_print_internal(window, show_char, 0, time, 0, THEME_TEXT_ME, from, message, receipt);
}
// TODO: cross-reference.. this should be replaced by a real event-based system
inp_nonblocking(TRUE);
g_date_time_unref(time);
@ -1373,7 +1439,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,9 +1452,10 @@ _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_internal(window, show_char, pad_indent, timestamp, flags, theme_item, from, fmt_msg->str, NULL);
_win_print(window, show_char, pad_indent, timestamp, flags, theme_item, from, fmt_msg->str, NULL);
inp_nonblocking(TRUE);
g_date_time_unref(timestamp);
@ -1397,7 +1464,7 @@ _win_printf(ProfWin *window, const char show_char, int pad_indent, GDateTime *ti
}
static void
_win_print(ProfWin *window, const char show_char, int pad_indent, GDateTime *time,
_win_print_internal(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)
{
// flags : 1st bit = 0/1 - me/not me
@ -1676,12 +1743,12 @@ win_redraw(ProfWin *window)
for (i = 0; i < size; i++) {
ProfBuffEntry *e = buffer_get_entry(window->layout->buffer, i);
if (e->from == NULL && e->message && e->message[0] == '-') {
if (e->display_from == NULL && e->message && e->message[0] == '-') {
// just an indicator to print the separator not the actual message
win_print_separator(window);
} else {
// regular thing to print
_win_print(window, e->show_char, e->pad_indent, e->time, e->flags, e->theme_item, e->from, e->message, e->receipt);
_win_print_internal(window, e->show_char, e->pad_indent, e->time, e->flags, e->theme_item, e->display_from, e->message, e->receipt);
}
}
}

View File

@ -3,6 +3,7 @@
* vim: expandtab:ts=4:sts=4:sw=4
*
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
* Copyright (C) 2019 - 2020 Michael Vetter <jubalh@iodoru.org>
*
* This file is part of Profanity.
*
@ -62,17 +63,16 @@ void win_show_status_string(ProfWin *window, const char *const from,
const char *const default_show);
void win_print_them(ProfWin *window, theme_item_t theme_item, char ch, int flags, const char *const them);
void win_println_them_message(ProfWin *window, char ch, int flags, const char *const them, const char *const message, ...);
void win_println_me_message(ProfWin *window, char ch, const char *const me, const char *const message, ...);
void win_println_incoming_muc_msg(ProfWin *window, char ch, int flags, const char *const them, const char *const id, const char *const replace_id, const char *const message, ...);
void win_print_outgoing_muc_msg(ProfWin *window, char ch, const char *const me, const char *const id, const char *const replace_id, const char *const message, ...);
void win_print_outgoing(ProfWin *window, const char ch, const char *const message, ...);
void win_print_outgoing(ProfWin *window, const char ch, const char *const id, const char *const replace_id, const char *const message, ...);
void win_print_incoming(ProfWin *window, const char *const from, ProfMessage *message);
void win_print_history(ProfWin *window, GDateTime *timestamp, const char *const message, ...);
void win_print_http_upload(ProfWin *window, const char *const message, char *url);
void win_print_with_receipt(ProfWin *window, const char show_char, const char *const from, const char *const message,
char *id);
void win_print_outgoing_with_receipt(ProfWin *window, const char show_char, const char *const from, const char *const message, char *id, const char *const replace_id);
void win_newline(ProfWin *window);
void win_redraw(ProfWin *window);

View File

@ -104,12 +104,19 @@ caps_init(void)
g_hash_table_add(prof_features, strdup(STANZA_NS_CHATSTATES));
g_hash_table_add(prof_features, strdup(STANZA_NS_PING));
g_hash_table_add(prof_features, strdup(STANZA_NS_STABLE_ID));
if (prefs_get_boolean(PREF_RECEIPTS_SEND)) {
g_hash_table_add(prof_features, strdup(STANZA_NS_RECEIPTS));
}
if (prefs_get_boolean(PREF_LASTACTIVITY)) {
g_hash_table_add(prof_features, strdup(STANZA_NS_LASTACTIVITY));
}
if (prefs_get_boolean(PREF_CORRECTION_ALLOW)) {
g_hash_table_add(prof_features, strdup(STANZA_NS_LAST_MESSAGE_CORRECTION));
}
my_sha1 = NULL;
}

View File

@ -76,11 +76,11 @@ typedef struct p_message_handle_t {
} ProfMessageHandler;
static int _message_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata);
static void _private_chat_handler(xmpp_stanza_t *const stanza);
static void _handle_error(xmpp_stanza_t *const stanza);
static void _handle_groupchat(xmpp_stanza_t *const stanza);
static void _handle_muc_user(xmpp_stanza_t *const stanza);
static void _handle_muc_private_message(xmpp_stanza_t *const stanza);
static void _handle_conference(xmpp_stanza_t *const stanza);
static void _handle_captcha(xmpp_stanza_t *const stanza);
static void _handle_receipt_received(xmpp_stanza_t *const stanza);
@ -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);
}
@ -254,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();
@ -279,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);
@ -286,7 +294,7 @@ message_send_chat(const char *const barejid, const char *const msg, const char *
}
char*
message_send_chat_pgp(const char *const barejid, const char *const msg, gboolean request_receipt)
message_send_chat_pgp(const char *const barejid, const char *const msg, gboolean request_receipt, const char *const replace_id)
{
xmpp_ctx_t * const ctx = connection_get_ctx();
@ -338,6 +346,10 @@ message_send_chat_pgp(const char *const barejid, const char *const msg, gboolean
stanza_attach_receipt_request(ctx, message);
}
if (replace_id) {
stanza_attach_correction(ctx, message, replace_id);
}
_send_message_stanza(message);
xmpp_stanza_release(message);
@ -345,7 +357,7 @@ message_send_chat_pgp(const char *const barejid, const char *const msg, gboolean
}
char*
message_send_chat_otr(const char *const barejid, const char *const msg, gboolean request_receipt)
message_send_chat_otr(const char *const barejid, const char *const msg, gboolean request_receipt, const char *const replace_id)
{
xmpp_ctx_t * const ctx = connection_get_ctx();
@ -370,6 +382,10 @@ message_send_chat_otr(const char *const barejid, const char *const msg, gboolean
stanza_attach_receipt_request(ctx, message);
}
if (replace_id) {
stanza_attach_correction(ctx, message, replace_id);
}
_send_message_stanza(message);
xmpp_stanza_release(message);
@ -381,7 +397,7 @@ 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)
gboolean request_receipt, gboolean muc, const char *const replace_id)
{
char *state = chat_session_get_state(jid);
xmpp_ctx_t * const ctx = connection_get_ctx();
@ -481,6 +497,10 @@ message_send_chat_omemo(const char *const jid, uint32_t sid, GList *keys,
stanza_attach_receipt_request(ctx, message);
}
if (replace_id) {
stanza_attach_correction(ctx, message, replace_id);
}
_send_message_stanza(message);
xmpp_stanza_release(message);
@ -508,7 +528,7 @@ message_send_private(const char *const fulljid, const char *const msg, const cha
}
char*
message_send_groupchat(const char *const roomjid, const char *const msg, const char *const oob_url)
message_send_groupchat(const char *const roomjid, const char *const msg, const char *const oob_url, const char *const replace_id)
{
xmpp_ctx_t * const ctx = connection_get_ctx();
char *id = connection_create_stanza_id();
@ -521,6 +541,10 @@ message_send_groupchat(const char *const roomjid, const char *const msg, const c
stanza_attach_x_oob_url(ctx, message, oob_url);
}
if (replace_id) {
stanza_attach_correction(ctx, message, replace_id);
}
_send_message_stanza(message);
xmpp_stanza_release(message);
@ -807,13 +831,23 @@ _handle_groupchat(xmpp_stanza_t *const stanza)
ProfMessage *message = message_init();
message->jid = jid;
if (id) {
message->id = strdup(id);
}
if (originid) {
message->originid = strdup(originid);
}
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);
}
}
message->body = xmpp_message_get_body(stanza);
// check omemo encryption
@ -927,7 +961,7 @@ _receipt_request_handler(xmpp_stanza_t *const stanza)
}
static void
_private_chat_handler(xmpp_stanza_t *const stanza)
_handle_muc_private_message(xmpp_stanza_t *const stanza)
{
// standard chat message, use jid without resource
ProfMessage *message = message_init();
@ -936,6 +970,12 @@ _private_chat_handler(xmpp_stanza_t *const stanza)
const gchar *from = xmpp_stanza_get_from(stanza);
message->jid = jid_create(from);
// message stanza id
const char *id = xmpp_stanza_get_id(stanza);
if (id) {
message->id = strdup(id);
}
// check omemo encryption
#ifdef HAVE_OMEMO
message->plain = omemo_receive_message(stanza, &message->trusted);
@ -1015,6 +1055,21 @@ _handle_carbons(xmpp_stanza_t *const stanza)
message->mucuser = TRUE;
}
// id
const char *id = xmpp_stanza_get_id(message_stanza);
if (id) {
message->id = strdup(id);
}
// replace id
xmpp_stanza_t *replace_id_stanza = xmpp_stanza_get_child_by_ns(message_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);
}
}
// check omemo encryption
#ifdef HAVE_OMEMO
message->plain = omemo_receive_message(message_stanza, &message->trusted);
@ -1104,7 +1159,7 @@ _handle_chat(xmpp_stanza_t *const stanza)
// private message from chat room use full jid (room/nick)
if (muc_active(jid->barejid)) {
_private_chat_handler(stanza);
_handle_muc_private_message(stanza);
jid_destroy(jid);
return;
}
@ -1113,6 +1168,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;
}

View File

@ -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;
}

View File

@ -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"
@ -244,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);

View File

@ -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;
/* </origin-id> XEP-0359 */
char *originid;
/* <replace id> 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 */
@ -168,13 +171,12 @@ 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_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);
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, const char *const replace_id);
char* message_send_chat_pgp(const char *const barejid, const char *const msg, gboolean request_receipt, const char *const replace_id);
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, const char *const replace_id);
void message_send_private(const char *const fulljid, 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);
char* message_send_groupchat(const char *const roomjid, const char *const msg, const char *const oob_url, const char *const replace_id);
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);

View File

@ -45,7 +45,7 @@ char* otr_on_message_recv(const char * const barejid, const char * const resourc
{
return NULL;
}
gboolean otr_on_message_send(ProfChatWin *chatwin, const char * const message, gboolean request_receipt)
gboolean otr_on_message_send(ProfChatWin *chatwin, const char * const message, gboolean request_receipt, const char *const replace_id)
{
return FALSE;
}

View File

@ -160,8 +160,7 @@ void privwin_incoming_msg(ProfPrivateWin *privatewin, ProfMessage *message) {}
void ui_disconnected(void) {}
void chatwin_recipient_gone(ProfChatWin *chatwin) {}
void chatwin_outgoing_msg(ProfChatWin *chatwin, const char * const message, char *id, prof_enc_t enc_mode,
gboolean request_receipt) {}
void chatwin_outgoing_msg(ProfChatWin *chatwin, const char *const message, char *id, prof_enc_t enc_mode, gboolean request_receipt, const char *const replace_id) {}
void chatwin_outgoing_carbon(ProfChatWin *chatwin, ProfMessage *message) {}
void privwin_outgoing_msg(ProfPrivateWin *privwin, const char * const message) {}
@ -191,7 +190,7 @@ void mucwin_occupant_role_and_affiliation_change(ProfMucWin *mucwin, const char
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, ProfMessage *message, GSList *mentions, GList *triggers) {}
void mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, const char *const id, prof_enc_t enc_mode) {}
void mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, const char *const id, prof_enc_t enc_mode, const char *const replace_id) {}
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) {}
@ -452,6 +451,7 @@ void cons_winpos_setting(void) {}
void cons_statusbar_setting(void) {}
void cons_tray_setting(void) {}
void cons_os_setting(void) {}
void cons_correction_setting(void) {}
void cons_show_contact_online(PContact contact, Resource *resource, GDateTime *last_activity)
{

View File

@ -97,28 +97,27 @@ const char* connection_get_profanity_identifier(void) {
}
// message functions
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)
{
check_expected(barejid);
check_expected(msg);
return NULL;
}
char* message_send_chat_otr(const char * const barejid, const char * const msg, gboolean request_receipt)
char* message_send_chat_otr(const char * const barejid, const char * const msg, gboolean request_receipt, const char *const replace_id)
{
check_expected(barejid);
check_expected(msg);
return NULL;
}
char* message_send_chat_pgp(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, const char *const replace_id)
{
return NULL;
}
void message_send_private(const char * const fulljid, 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)
char* message_send_groupchat(const char *const roomjid, const char *const msg, const char *const oob_url, const char *const replace_id)
{
return NULL;
}

View File

@ -149,3 +149,4 @@ console.muc=
console.chat=
console.private=
inputwin.position=
correction.char=

View File

@ -152,4 +152,5 @@ statusbar.tabs=10
statusbar.tablen=7
statusbar.show.name=true
statusbar.show.number=true
correction.char=+