1
1
mirror of https://github.com/profanity-im/profanity.git synced 2025-02-02 15:08:15 -05: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* _logging_autocomplete(ProfWin *window, const char *const input, gboolean previous);
static char* _color_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* _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); 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 status_state_ac;
static Autocomplete logging_ac; static Autocomplete logging_ac;
static Autocomplete color_ac; static Autocomplete color_ac;
static Autocomplete correction_ac;
void void
cmd_ac_init(void) cmd_ac_init(void)
@ -928,6 +931,11 @@ cmd_ac_init(void)
autocomplete_add(color_ac, "off"); autocomplete_add(color_ac, "off");
autocomplete_add(color_ac, "redgreen"); autocomplete_add(color_ac, "redgreen");
autocomplete_add(color_ac, "blue"); 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 void
@ -1233,6 +1241,7 @@ cmd_ac_reset(ProfWin *window)
autocomplete_reset(status_state_ac); autocomplete_reset(status_state_ac);
autocomplete_reset(logging_ac); autocomplete_reset(logging_ac);
autocomplete_reset(color_ac); autocomplete_reset(color_ac);
autocomplete_reset(correction_ac);
autocomplete_reset(script_ac); autocomplete_reset(script_ac);
if (script_show_ac) { if (script_show_ac) {
@ -1380,6 +1389,7 @@ cmd_ac_uninit(void)
autocomplete_free(status_state_ac); autocomplete_free(status_state_ac);
autocomplete_free(logging_ac); autocomplete_free(logging_ac);
autocomplete_free(color_ac); autocomplete_free(color_ac);
autocomplete_free(correction_ac);
} }
static void 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, "/logging", _logging_autocomplete);
g_hash_table_insert(ac_funcs, "/color", _color_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, "/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); int len = strlen(input);
char parsed[len+1]; char parsed[len+1];
@ -3713,3 +3725,50 @@ _avatar_autocomplete(ProfWin *window, const char *const input, gboolean previous
return NULL; 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", ""}) { "on|off", ""})
CMD_NOEXAMPLES 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; 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)) { if (!otr_is_secure(barejid)) {
char *otr_query_message = otr_start_query(); 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); free(id);
return TRUE; 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 *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); free(id);
return TRUE; return TRUE;
} }
@ -8651,3 +8652,77 @@ cmd_os(ProfWin *window, const char *const command, gchar **args)
return TRUE; 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 '/' * cmd - The command string including leading '/'
* parser - The function used to parse arguments * parser - The function used to parse arguments
* min_args - Minimum number of 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 * setting_func - Function to display current settings to the console
* sub_funcs - Optional list of functions mapped to the first argument * sub_funcs - Optional list of functions mapped to the first argument
* func - Main function to call when no arguments, or sub_funcs not implemented * 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_color(ProfWin *window, const char *const command, gchar **args);
gboolean cmd_avatar(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_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 #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); 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 gboolean
prefs_add_room_notify_trigger(const char * const text) prefs_add_room_notify_trigger(const char * const text)
{ {
@ -1760,6 +1786,7 @@ _get_group(preference_t pref)
case PREF_RECEIPTS_REQUEST: case PREF_RECEIPTS_REQUEST:
case PREF_REVEAL_OS: case PREF_REVEAL_OS:
case PREF_TLS_CERTPATH: case PREF_TLS_CERTPATH:
case PREF_CORRECTION_ALLOW:
return PREF_GROUP_CONNECTION; return PREF_GROUP_CONNECTION;
case PREF_OTR_LOG: case PREF_OTR_LOG:
case PREF_OTR_POLICY: case PREF_OTR_POLICY:
@ -2010,6 +2037,8 @@ _get_key(preference_t pref)
return "log"; return "log";
case PREF_OMEMO_POLICY: case PREF_OMEMO_POLICY:
return "policy"; return "policy";
case PREF_CORRECTION_ALLOW:
return "correction.allow";
default: default:
return NULL; return NULL;
} }

View File

@ -161,6 +161,7 @@ typedef enum {
PREF_OMEMO_LOG, PREF_OMEMO_LOG,
PREF_OMEMO_POLICY, PREF_OMEMO_POLICY,
PREF_OCCUPANTS_WRAP, PREF_OCCUPANTS_WRAP,
PREF_CORRECTION_ALLOW,
} preference_t; } preference_t;
typedef struct prof_alias_t { typedef struct prof_alias_t {
@ -268,6 +269,9 @@ void prefs_set_roster_presence_indent(gint value);
gint prefs_get_occupants_indent(void); gint prefs_get_occupants_indent(void);
void prefs_set_occupants_indent(gint value); 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_add_login(const char *jid);
void prefs_set_tray_timer(gint value); 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 // load window positions
if (g_key_file_has_key(theme, "ui", "titlebar.position", NULL) && if (g_key_file_has_key(theme, "ui", "titlebar.position", NULL) &&
g_key_file_has_key(theme, "ui", "mainwin.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 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); chat_state_active(chatwin->state);
gboolean request_receipt = FALSE; gboolean request_receipt = prefs_get_boolean(PREF_RECEIPTS_REQUEST);
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);
}
}
char *plugin_msg = plugins_pre_chat_message_send(chatwin->barejid, msg); char *plugin_msg = plugins_pre_chat_message_send(chatwin->barejid, msg);
if (plugin_msg == NULL) { if (plugin_msg == NULL) {
return; return;
} }
char *replace_id = NULL;
if (correct_last_msg) {
replace_id = chatwin->last_msg_id;
}
// OTR suported, PGP supported, OMEMO unsupported // OTR suported, PGP supported, OMEMO unsupported
#ifdef HAVE_LIBOTR #ifdef HAVE_LIBOTR
#ifdef HAVE_LIBGPGME #ifdef HAVE_LIBGPGME
#ifndef HAVE_OMEMO #ifndef HAVE_OMEMO
if (chatwin->pgp_send) { 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); 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); free(id);
} else { } 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) { 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); 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); free(id);
} }
} }
@ -169,9 +161,9 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
#ifdef HAVE_LIBOTR #ifdef HAVE_LIBOTR
#ifndef HAVE_LIBGPGME #ifndef HAVE_LIBGPGME
#ifndef HAVE_OMEMO #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) { 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); 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);
free(id); free(id);
@ -189,14 +181,14 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
#ifdef HAVE_LIBGPGME #ifdef HAVE_LIBGPGME
#ifndef HAVE_OMEMO #ifndef HAVE_OMEMO
if (chatwin->pgp_send) { 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); 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); free(id);
} else { } 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); 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); free(id);
} }
@ -212,14 +204,14 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
#ifndef HAVE_LIBGPGME #ifndef HAVE_LIBGPGME
#ifdef HAVE_OMEMO #ifdef HAVE_OMEMO
if (chatwin->is_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); 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); free(id);
} else { } 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); 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); free(id);
} }
@ -235,16 +227,16 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
#ifndef HAVE_LIBGPGME #ifndef HAVE_LIBGPGME
#ifdef HAVE_OMEMO #ifdef HAVE_OMEMO
if (chatwin->is_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); 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); free(id);
} else { } 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) { 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); 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); 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_LIBGPGME
#ifdef HAVE_OMEMO #ifdef HAVE_OMEMO
if (chatwin->is_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); 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); free(id);
} else if (chatwin->pgp_send) { } 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); 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); free(id);
} else { } 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); 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); 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_LIBGPGME
#ifdef HAVE_OMEMO #ifdef HAVE_OMEMO
if (chatwin->is_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); 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); free(id);
} else if (chatwin->pgp_send) { } 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); 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); free(id);
} else { } 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) { 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); 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); 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_LIBOTR
#ifndef HAVE_LIBGPGME #ifndef HAVE_LIBGPGME
#ifndef HAVE_OMEMO #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); 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); free(id);
plugins_post_chat_message_send(chatwin->barejid, plugin_msg); 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 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); char *plugin_msg = plugins_pre_room_message_send(mucwin->roomjid, msg);
if (plugin_msg == NULL) { if (plugin_msg == NULL) {
return; return;
} }
char *replace_id = NULL;
if (correct_last_msg) {
replace_id = mucwin->last_msg_id;
}
#ifdef HAVE_OMEMO #ifdef HAVE_OMEMO
if (mucwin->is_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); 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); free(id);
} else { } 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); 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); free(id);
} }
@ -359,9 +362,9 @@ cl_ev_send_muc_msg(ProfMucWin *mucwin, const char *const msg, const char *const
#endif #endif
#ifndef HAVE_OMEMO #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); 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); free(id);
plugins_post_room_message_send(mucwin->roomjid, plugin_msg); 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 #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 void
cl_ev_send_priv_msg(ProfPrivateWin *privwin, const char *const msg, const char *const oob_url) 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_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_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_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); 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 * 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; char *id = NULL;
int res; int res;
@ -809,11 +809,11 @@ omemo_on_message_send(ProfWin *win, const char *const message, gboolean request_
if (muc) { if (muc) {
ProfMucWin *mucwin = (ProfMucWin *)win; ProfMucWin *mucwin = (ProfMucWin *)win;
assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); 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 { } else {
ProfChatWin *chatwin = (ProfChatWin *)win; ProfChatWin *chatwin = (ProfChatWin *)win;
assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); 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: 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); 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); 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); 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, cb_inject_message(void *opdata, const char *accountname,
const char *protocol, const char *recipient, const char *message) 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); 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); memmove(whitespace_base, whitespace_base+tag_length, tag_length);
char *otr_query_message = otr_start_query(); char *otr_query_message = otr_start_query();
cons_show("OTR Whitespace pattern detected. Attempting to start OTR session..."); 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); 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) { if (policy == PROF_OTRPOLICY_ALWAYS && *decrypted == FALSE && !whitespace_base) {
char *otr_query_message = otr_start_query(); char *otr_query_message = otr_start_query();
cons_show("Attempting to start OTR session..."); 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); free(id);
} }
@ -337,7 +337,7 @@ otr_on_message_recv(const char *const barejid, const char *const resource, const
} }
gboolean 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; char *id = NULL;
prof_otrpolicy_t policy = otr_get_policy(chatwin->barejid); 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)) { if (otr_is_secure(chatwin->barejid)) {
char *encrypted = otr_encrypt_message(chatwin->barejid, message); char *encrypted = otr_encrypt_message(chatwin->barejid, message);
if (encrypted) { 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); 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); otr_free_message(encrypted);
free(id); free(id);
return TRUE; return TRUE;
@ -367,8 +367,8 @@ otr_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean re
// tag and send for policy opportunistic // tag and send for policy opportunistic
if (policy == PROF_OTRPOLICY_OPPORTUNISTIC) { if (policy == PROF_OTRPOLICY_OPPORTUNISTIC) {
char *otr_tagged_msg = otr_tag_message(message); char *otr_tagged_msg = otr_tag_message(message);
id = message_send_chat_otr(chatwin->barejid, otr_tagged_msg, 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); chatwin_outgoing_msg(chatwin, message, id, PROF_MSG_ENC_PLAIN, request_receipt, replace_id);
chat_log_msg_out(chatwin->barejid, message, NULL); chat_log_msg_out(chatwin->barejid, message, NULL);
free(otr_tagged_msg); free(otr_tagged_msg);
free(id); free(id);

View File

@ -73,7 +73,7 @@ void otr_poll(void);
void otr_on_connect(ProfAccount *account); 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); 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); void otr_keygen(ProfAccount *account);

View File

@ -48,7 +48,7 @@
* *
* inp - The line of input * inp - The line of input
* min - The minimum allowed number of arguments * 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 * Returns - An NULL terminated array of strings representing the arguments
* of the command, or NULL if the validation fails. * 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; int num = g_slist_length(tokens) - 1;
// if num args not valid return NULL // 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_slist_free_full(tokens, free);
g_free(copy); g_free(copy);
*result = FALSE; *result = FALSE;

View File

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

View File

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

View File

@ -3,6 +3,7 @@
* vim: expandtab:ts=4:sts=4:sw=4 * vim: expandtab:ts=4:sts=4:sw=4
* *
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
* Copyright (C) 2019 - 2020 Michael Vetter <jubalh@iodoru.org>
* *
* This file is part of Profanity. * This file is part of Profanity.
* *
@ -56,6 +57,7 @@
#endif #endif
static void _chatwin_history(ProfChatWin *chatwin, const char *const contact); 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* ProfChatWin*
chatwin_new(const char *const barejid) chatwin_new(const char *const barejid)
@ -308,7 +310,7 @@ chatwin_incoming_msg(ProfChatWin *chatwin, ProfMessage *message, gboolean win_cr
void void
chatwin_outgoing_msg(ProfChatWin *chatwin, const char *const message, char *id, prof_enc_t enc_mode, 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); assert(chatwin != NULL);
@ -324,9 +326,14 @@ chatwin_outgoing_msg(ProfChatWin *chatwin, const char *const message, char *id,
} }
if (request_receipt && 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 { } 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; 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); int num = wins_get_num(window);
status_bar_active(num, WIN_CHAT, chatwin->barejid); 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); 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 void
cons_show_connection_prefs(void) cons_show_connection_prefs(void)
{ {

View File

@ -50,6 +50,8 @@
#include "omemo/omemo.h" #include "omemo/omemo.h"
#endif #endif
static void _mucwin_set_last_message(ProfMucWin *mucwin, const char *const id, const char *const message);
ProfMucWin* ProfMucWin*
mucwin_new(const char *const barejid) mucwin_new(const char *const barejid)
{ {
@ -501,7 +503,7 @@ _mucwin_print_triggers(ProfWin *window, const char *const message, GList *trigge
} }
void 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); assert(mucwin != NULL);
@ -519,7 +521,12 @@ mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, const char *c
ch = prefs_get_omemo_char(); 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 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); win_print_them(window, THEME_ROOMTRIGGER, ch, flags, message->jid->resourcepart);
_mucwin_print_triggers(window, message->plain, triggers); _mucwin_print_triggers(window, message->plain, triggers);
} else { } 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; 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); assert(privwin != NULL);
win_print_outgoing((ProfWin*)privwin, '-', "%s", message); win_print_outgoing((ProfWin*)privwin, '-', NULL, NULL ,"%s", message);
} }
void 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_incoming_msg(ProfChatWin *chatwin, ProfMessage *message, gboolean win_created);
void chatwin_receipt_received(ProfChatWin *chatwin, const char *const id); void chatwin_receipt_received(ProfChatWin *chatwin, const char *const id);
void chatwin_recipient_gone(ProfChatWin *chatwin); void chatwin_recipient_gone(ProfChatWin *chatwin);
void chatwin_outgoing_msg(ProfChatWin *chatwin, const char *const message, char *id, prof_enc_t enc_mode, 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);
gboolean request_receipt);
void chatwin_outgoing_carbon(ProfChatWin *chatwin, ProfMessage *message); void chatwin_outgoing_carbon(ProfChatWin *chatwin, ProfMessage *message);
void chatwin_contact_online(ProfChatWin *chatwin, Resource *resource, GDateTime *last_activity); void chatwin_contact_online(ProfChatWin *chatwin, Resource *resource, GDateTime *last_activity);
void chatwin_contact_offline(ProfChatWin *chatwin, char *resource, char *status); 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); 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_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_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_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_subject(ProfMucWin *mucwin, const char *const nick, const char *const subject);
void mucwin_requires_config(ProfMucWin *mucwin); void mucwin_requires_config(ProfMucWin *mucwin);
@ -319,6 +318,7 @@ void cons_statusbar_setting(void);
void cons_winpos_setting(void); void cons_winpos_setting(void);
void cons_color_setting(void); void cons_color_setting(void);
void cons_os_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_online(PContact contact, Resource *resource, GDateTime *last_activity);
void cons_show_contact_offline(PContact contact, char *resource, char *status); void cons_show_contact_offline(PContact contact, char *resource, char *status);
void cons_theme_properties(void); void cons_theme_properties(void);

View File

@ -160,6 +160,9 @@ typedef struct prof_chat_win_t {
char *enctext; char *enctext;
char *incoming_char; char *incoming_char;
char *outgoing_char; char *outgoing_char;
// For LMC
char *last_message;
char *last_msg_id;
} ProfChatWin; } ProfChatWin;
typedef struct prof_muc_win_t { typedef struct prof_muc_win_t {
@ -175,6 +178,9 @@ typedef struct prof_muc_win_t {
char *enctext; char *enctext;
char *message_char; char *message_char;
GDateTime *last_msg_timestamp; GDateTime *last_msg_timestamp;
// For LMC
char *last_message;
char *last_msg_id;
} ProfMucWin; } ProfMucWin;
typedef struct prof_conf_win_t ProfConfWin; typedef struct prof_conf_win_t ProfConfWin;

View File

@ -3,6 +3,7 @@
* vim: expandtab:ts=4:sts=4:sw=4 * vim: expandtab:ts=4:sts=4:sw=4
* *
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
* Copyright (C) 2019 - 2020 Michael Vetter <jubalh@iodoru.org>
* *
* This file is part of Profanity. * This file is part of Profanity.
* *
@ -49,6 +50,7 @@
#include <ncurses.h> #include <ncurses.h>
#endif #endif
#include "log.h"
#include "config/theme.h" #include "config/theme.h"
#include "config/preferences.h" #include "config/preferences.h"
#include "ui/ui.h" #include "ui/ui.h"
@ -62,9 +64,8 @@
#define CEILING(X) (X-(int)(X) > 0 ? (int)(X+1) : (int)(X)) #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, 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, ...);
int flags, theme_item_t theme_item, const char *const from, const char *const message, ...); static void _win_print_internal(ProfWin *window, const char show_char, int pad_indent, GDateTime *time,
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); 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); 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->enctext = NULL;
new_win->incoming_char = NULL; new_win->incoming_char = NULL;
new_win->outgoing_char = NULL; new_win->outgoing_char = NULL;
new_win->last_message = NULL;
new_win->last_msg_id = NULL;
new_win->memcheck = PROFCHATWIN_MEMCHECK; new_win->memcheck = PROFCHATWIN_MEMCHECK;
@ -200,6 +203,8 @@ win_create_muc(const char *const roomjid)
new_win->enctext = NULL; new_win->enctext = NULL;
new_win->message_char = NULL; new_win->message_char = NULL;
new_win->is_omemo = FALSE; new_win->is_omemo = FALSE;
new_win->last_message = NULL;
new_win->last_msg_id = NULL;
new_win->memcheck = PROFMUCWIN_MEMCHECK; new_win->memcheck = PROFMUCWIN_MEMCHECK;
@ -487,6 +492,8 @@ win_free(ProfWin* window)
free(chatwin->enctext); free(chatwin->enctext);
free(chatwin->incoming_char); free(chatwin->incoming_char);
free(chatwin->outgoing_char); free(chatwin->outgoing_char);
free(chatwin->last_message);
free(chatwin->last_msg_id);
chat_state_free(chatwin->state); chat_state_free(chatwin->state);
break; break;
} }
@ -1055,8 +1062,43 @@ win_show_status_string(ProfWin *window, const char *const from,
win_appendln(window, presence_colour, ""); 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 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 = '-'; char enc_char = '-';
int flags = NO_ME; 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) { } else if (message->enc == PROF_MSG_ENC_OMEMO) {
enc_char = prefs_get_omemo_char(); 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; break;
} }
case WIN_PRIVATE: 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; break;
default: default:
assert(FALSE); assert(FALSE);
@ -1094,12 +1141,13 @@ win_print_incoming(ProfWin *window, const char *const from, ProfMessage *message
void void
win_print_them(ProfWin *window, theme_item_t theme_item, char ch, int flags, const char *const them) 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 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(); GDateTime *timestamp = g_date_time_new_now_local();
va_list arg; 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); GString *fmt_msg = g_string_new(NULL);
g_string_vprintf(fmt_msg, message, arg); 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); inp_nonblocking(TRUE);
g_date_time_unref(timestamp); g_date_time_unref(timestamp);
@ -1118,7 +1171,7 @@ win_println_them_message(ProfWin *window, char ch, int flags, const char *const
} }
void 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(); 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); GString *fmt_msg = g_string_new(NULL);
g_string_vprintf(fmt_msg, message, arg); 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); inp_nonblocking(TRUE);
g_date_time_unref(timestamp); g_date_time_unref(timestamp);
@ -1138,7 +1196,7 @@ win_println_me_message(ProfWin *window, char ch, const char *const me, const cha
} }
void 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(); 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); GString *fmt_msg = g_string_new(NULL);
g_string_vprintf(fmt_msg, message, arg); 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); inp_nonblocking(TRUE);
g_date_time_unref(timestamp); 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); g_string_vprintf(fmt_msg, message, arg);
buffer_append(window->layout->buffer, '-', 0, timestamp, 0, THEME_TEXT_HISTORY, "", fmt_msg->str, NULL, NULL); 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); inp_nonblocking(TRUE);
g_date_time_unref(timestamp); 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); g_string_vprintf(fmt_msg, message, arg);
buffer_append(window->layout->buffer, ch, 0, timestamp, NO_EOL, theme_item, "", fmt_msg->str, NULL, NULL); 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); inp_nonblocking(TRUE);
g_date_time_unref(timestamp); 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); g_string_vprintf(fmt_msg, message, arg);
buffer_append(window->layout->buffer, ch, 0, timestamp, 0, theme_item, "", fmt_msg->str, NULL, NULL); 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); inp_nonblocking(TRUE);
g_date_time_unref(timestamp); 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); g_string_vprintf(fmt_msg, message, arg);
buffer_append(window->layout->buffer, '-', pad, timestamp, 0, THEME_DEFAULT, "", fmt_msg->str, NULL, NULL); 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); inp_nonblocking(TRUE);
g_date_time_unref(timestamp); 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); 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); 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); inp_nonblocking(TRUE);
g_date_time_unref(timestamp); 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); g_string_vprintf(fmt_msg, message, arg);
buffer_append(window->layout->buffer, '-', 0, timestamp, NO_DATE, theme_item, "", fmt_msg->str, NULL, NULL); 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); inp_nonblocking(TRUE);
g_date_time_unref(timestamp); 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); 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); 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); inp_nonblocking(TRUE);
g_date_time_unref(timestamp); 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); 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); 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); inp_nonblocking(TRUE);
g_date_time_unref(timestamp); g_date_time_unref(timestamp);
@ -1320,19 +1381,24 @@ win_appendln_highlight(ProfWin *window, theme_item_t theme_item, const char *con
void void
win_print_http_upload(ProfWin *window, const char *const message, char *url) 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 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(); GDateTime *time = g_date_time_new_now_local();
DeliveryReceipt *receipt = malloc(sizeof(struct delivery_receipt_t)); DeliveryReceipt *receipt = malloc(sizeof(struct delivery_receipt_t));
receipt->received = FALSE; receipt->received = FALSE;
buffer_append(window->layout->buffer, show_char, 0, time, 0, THEME_TEXT_ME, from, message, receipt, id); if (replace_id) {
_win_print(window, show_char, 0, time, 0, THEME_TEXT_ME, from, message, receipt); _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 // TODO: cross-reference.. this should be replaced by a real event-based system
inp_nonblocking(TRUE); inp_nonblocking(TRUE);
g_date_time_unref(time); g_date_time_unref(time);
@ -1373,7 +1439,7 @@ win_newline(ProfWin *window)
static void static void
_win_printf(ProfWin *window, const char show_char, int pad_indent, GDateTime *timestamp, _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) { if (timestamp == NULL) {
timestamp = g_date_time_new_now_local(); 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); GString *fmt_msg = g_string_new(NULL);
g_string_vprintf(fmt_msg, message, arg); 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); inp_nonblocking(TRUE);
g_date_time_unref(timestamp); g_date_time_unref(timestamp);
@ -1397,7 +1464,7 @@ _win_printf(ProfWin *window, const char show_char, int pad_indent, GDateTime *ti
} }
static void 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) 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 // flags : 1st bit = 0/1 - me/not me
@ -1676,12 +1743,12 @@ win_redraw(ProfWin *window)
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
ProfBuffEntry *e = buffer_get_entry(window->layout->buffer, 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 // just an indicator to print the separator not the actual message
win_print_separator(window); win_print_separator(window);
} else { } else {
// regular thing to print // 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 * vim: expandtab:ts=4:sts=4:sw=4
* *
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
* Copyright (C) 2019 - 2020 Michael Vetter <jubalh@iodoru.org>
* *
* This file is part of Profanity. * 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); 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_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_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_println_me_message(ProfWin *window, char ch, const char *const me, 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_incoming(ProfWin *window, const char *const from, ProfMessage *message);
void win_print_history(ProfWin *window, GDateTime *timestamp, const char *const 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_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, 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);
char *id);
void win_newline(ProfWin *window); void win_newline(ProfWin *window);
void win_redraw(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_CHATSTATES));
g_hash_table_add(prof_features, strdup(STANZA_NS_PING)); g_hash_table_add(prof_features, strdup(STANZA_NS_PING));
g_hash_table_add(prof_features, strdup(STANZA_NS_STABLE_ID)); g_hash_table_add(prof_features, strdup(STANZA_NS_STABLE_ID));
if (prefs_get_boolean(PREF_RECEIPTS_SEND)) { if (prefs_get_boolean(PREF_RECEIPTS_SEND)) {
g_hash_table_add(prof_features, strdup(STANZA_NS_RECEIPTS)); g_hash_table_add(prof_features, strdup(STANZA_NS_RECEIPTS));
} }
if (prefs_get_boolean(PREF_LASTACTIVITY)) { if (prefs_get_boolean(PREF_LASTACTIVITY)) {
g_hash_table_add(prof_features, strdup(STANZA_NS_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; my_sha1 = NULL;
} }

View File

@ -76,11 +76,11 @@ typedef struct p_message_handle_t {
} ProfMessageHandler; } ProfMessageHandler;
static int _message_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata); 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_error(xmpp_stanza_t *const stanza);
static void _handle_groupchat(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_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_conference(xmpp_stanza_t *const stanza);
static void _handle_captcha(xmpp_stanza_t *const stanza); static void _handle_captcha(xmpp_stanza_t *const stanza);
static void _handle_receipt_received(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->jid = NULL;
message->id = NULL; message->id = NULL;
message->originid = NULL; message->originid = NULL;
message->replace_id = NULL;
message->body = NULL; message->body = NULL;
message->encrypted = NULL; message->encrypted = NULL;
message->plain = NULL; message->plain = NULL;
@ -215,6 +216,10 @@ message_free(ProfMessage *message)
xmpp_free(ctx, message->originid); xmpp_free(ctx, message->originid);
} }
if (message->replace_id) {
xmpp_free(ctx, message->replace_id);
}
if (message->body) { if (message->body) {
xmpp_free(ctx, message->body); xmpp_free(ctx, message->body);
} }
@ -254,8 +259,7 @@ message_pubsub_event_handler_add(const char *const node, ProfMessageCallback fun
} }
char* char*
message_send_chat(const char *const barejid, const char *const msg, const char *const oob_url, message_send_chat(const char *const barejid, const char *const msg, const char *const oob_url, gboolean request_receipt, const char *const replace_id)
gboolean request_receipt)
{ {
xmpp_ctx_t * const ctx = connection_get_ctx(); 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); stanza_attach_receipt_request(ctx, message);
} }
if (replace_id) {
stanza_attach_correction(ctx, message, replace_id);
}
_send_message_stanza(message); _send_message_stanza(message);
xmpp_stanza_release(message); xmpp_stanza_release(message);
@ -286,7 +294,7 @@ message_send_chat(const char *const barejid, const char *const msg, const char *
} }
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(); 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); stanza_attach_receipt_request(ctx, message);
} }
if (replace_id) {
stanza_attach_correction(ctx, message, replace_id);
}
_send_message_stanza(message); _send_message_stanza(message);
xmpp_stanza_release(message); xmpp_stanza_release(message);
@ -345,7 +357,7 @@ message_send_chat_pgp(const char *const barejid, const char *const msg, gboolean
} }
char* 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(); 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); stanza_attach_receipt_request(ctx, message);
} }
if (replace_id) {
stanza_attach_correction(ctx, message, replace_id);
}
_send_message_stanza(message); _send_message_stanza(message);
xmpp_stanza_release(message); xmpp_stanza_release(message);
@ -381,7 +397,7 @@ char*
message_send_chat_omemo(const char *const jid, uint32_t sid, GList *keys, 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 iv, size_t iv_len,
const unsigned char *const ciphertext, size_t ciphertext_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); char *state = chat_session_get_state(jid);
xmpp_ctx_t * const ctx = connection_get_ctx(); 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); stanza_attach_receipt_request(ctx, message);
} }
if (replace_id) {
stanza_attach_correction(ctx, message, replace_id);
}
_send_message_stanza(message); _send_message_stanza(message);
xmpp_stanza_release(message); xmpp_stanza_release(message);
@ -508,7 +528,7 @@ message_send_private(const char *const fulljid, const char *const msg, const cha
} }
char* 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(); xmpp_ctx_t * const ctx = connection_get_ctx();
char *id = connection_create_stanza_id(); 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); stanza_attach_x_oob_url(ctx, message, oob_url);
} }
if (replace_id) {
stanza_attach_correction(ctx, message, replace_id);
}
_send_message_stanza(message); _send_message_stanza(message);
xmpp_stanza_release(message); xmpp_stanza_release(message);
@ -807,13 +831,23 @@ _handle_groupchat(xmpp_stanza_t *const stanza)
ProfMessage *message = message_init(); ProfMessage *message = message_init();
message->jid = jid; message->jid = jid;
if (id) { if (id) {
message->id = strdup(id); message->id = strdup(id);
} }
if (originid) { if (originid) {
message->originid = strdup(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); message->body = xmpp_message_get_body(stanza);
// check omemo encryption // check omemo encryption
@ -927,7 +961,7 @@ _receipt_request_handler(xmpp_stanza_t *const stanza)
} }
static void 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 // standard chat message, use jid without resource
ProfMessage *message = message_init(); ProfMessage *message = message_init();
@ -936,6 +970,12 @@ _private_chat_handler(xmpp_stanza_t *const stanza)
const gchar *from = xmpp_stanza_get_from(stanza); const gchar *from = xmpp_stanza_get_from(stanza);
message->jid = jid_create(from); 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 // check omemo encryption
#ifdef HAVE_OMEMO #ifdef HAVE_OMEMO
message->plain = omemo_receive_message(stanza, &message->trusted); message->plain = omemo_receive_message(stanza, &message->trusted);
@ -1015,6 +1055,21 @@ _handle_carbons(xmpp_stanza_t *const stanza)
message->mucuser = TRUE; 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 // check omemo encryption
#ifdef HAVE_OMEMO #ifdef HAVE_OMEMO
message->plain = omemo_receive_message(message_stanza, &message->trusted); 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) // private message from chat room use full jid (room/nick)
if (muc_active(jid->barejid)) { if (muc_active(jid->barejid)) {
_private_chat_handler(stanza); _handle_muc_private_message(stanza);
jid_destroy(jid); jid_destroy(jid);
return; return;
} }
@ -1113,6 +1168,20 @@ _handle_chat(xmpp_stanza_t *const stanza)
ProfMessage *message = message_init(); ProfMessage *message = message_init();
message->jid = jid; 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) { if (mucuser) {
message->mucuser = TRUE; 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; 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_STABLE_ID "urn:xmpp:sid:0"
#define STANZA_NS_USER_AVATAR_DATA "urn:xmpp:avatar:data" #define STANZA_NS_USER_AVATAR_DATA "urn:xmpp:avatar:data"
#define STANZA_NS_USER_AVATAR_METADATA "urn:xmpp:avatar:metadata" #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" #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_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_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_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, xmpp_stanza_t* stanza_create_room_join_presence(xmpp_ctx_t *const ctx,
const char *const full_room_jid, const char *const passwd); 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 "http://jabber.org/protocol/pubsub"
#define XMPP_FEATURE_PUBSUB_PUBLISH_OPTIONS "http://jabber.org/protocol/pubsub#publish-options" #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_USER_AVATAR_METADATA_NOTIFY "urn:xmpp:avatar:metadata+notify"
#define XMPP_FEATURE_LAST_MESSAGE_CORRECTION "urn:xmpp:message-correct:0"
typedef enum { typedef enum {
JABBER_CONNECTING, JABBER_CONNECTING,
@ -130,6 +131,8 @@ typedef struct prof_message_t {
char *id; char *id;
/* </origin-id> XEP-0359 */ /* </origin-id> XEP-0359 */
char *originid; char *originid;
/* <replace id> XEP-0308 LMC */
char *replace_id;
/* The raw body from xmpp message, either plaintext or OTR encrypted text */ /* The raw body from xmpp message, either plaintext or OTR encrypted text */
char *body; char *body;
/* The encrypted message as for PGP */ /* 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); const char* connection_get_profanity_identifier(void);
char* message_send_chat(const char *const barejid, const char *const msg, const char *const oob_url, 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);
gboolean request_receipt); 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_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, const char *const replace_id);
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, 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);
void message_send_private(const char *const fulljid, const char *const msg, const char *const oob_url); 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_groupchat_subject(const char *const roomjid, const char *const subject);
void message_send_inactive(const char *const jid); void message_send_inactive(const char *const jid);
void message_send_composing(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; 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; return FALSE;
} }

View File

@ -160,8 +160,7 @@ void privwin_incoming_msg(ProfPrivateWin *privatewin, ProfMessage *message) {}
void ui_disconnected(void) {} void ui_disconnected(void) {}
void chatwin_recipient_gone(ProfChatWin *chatwin) {} void chatwin_recipient_gone(ProfChatWin *chatwin) {}
void chatwin_outgoing_msg(ProfChatWin *chatwin, const char * const message, char *id, prof_enc_t enc_mode, 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) {}
gboolean request_receipt) {}
void chatwin_outgoing_carbon(ProfChatWin *chatwin, ProfMessage *message) {} void chatwin_outgoing_carbon(ProfChatWin *chatwin, ProfMessage *message) {}
void privwin_outgoing_msg(ProfPrivateWin *privwin, const char * const 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_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_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_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_subject(ProfMucWin *mucwin, const char * const nick, const char * const subject) {}
void mucwin_requires_config(ProfMucWin *mucwin) {} void mucwin_requires_config(ProfMucWin *mucwin) {}
void ui_room_destroy(const char * const roomjid) {} void ui_room_destroy(const char * const roomjid) {}
@ -452,6 +451,7 @@ void cons_winpos_setting(void) {}
void cons_statusbar_setting(void) {} void cons_statusbar_setting(void) {}
void cons_tray_setting(void) {} void cons_tray_setting(void) {}
void cons_os_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_online(PContact contact, Resource *resource, GDateTime *last_activity)
{ {

View File

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

View File

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

View File

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