From 0fb27dc4961608eb9b088ca659eb087dd2c1cae7 Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Tue, 26 Feb 2019 20:33:06 +0140 Subject: Add OMEMO message encryption and decryption --- src/ui/ui.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/ui/ui.h') diff --git a/src/ui/ui.h b/src/ui/ui.h index ad5a1216..95d291b4 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -56,7 +56,8 @@ typedef enum { PROF_MSG_PLAIN, PROF_MSG_OTR, - PROF_MSG_PGP + PROF_MSG_PGP, + PROF_MSG_OMEMO } prof_enc_t; // core UI -- cgit 1.4.1-2-gfad0 From 4e1ffa6bdb89269fa5eff9e5ee2484106d52d149 Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Mon, 18 Mar 2019 20:30:28 +0140 Subject: Log and print outgoing encrypted message --- src/event/client_events.c | 29 +++++++++++++++---- src/event/server_events.c | 66 +++++++++++++++++++++++++++++++++++-------- src/event/server_events.h | 4 +-- src/log.c | 64 ++++++++++++++++++++++++++++++++++++++++- src/log.h | 7 +++-- src/omemo/omemo.c | 72 ++++++++++++++++++++++------------------------- src/omemo/omemo.h | 2 +- src/ui/mucwin.c | 46 ++++++++++++++++++++++-------- src/ui/ui.h | 3 +- src/ui/window.c | 1 + src/xmpp/message.c | 7 +++-- 11 files changed, 227 insertions(+), 74 deletions(-) (limited to 'src/ui/ui.h') diff --git a/src/event/client_events.c b/src/event/client_events.c index 1488174a..d1cdc797 100644 --- a/src/event/client_events.c +++ b/src/event/client_events.c @@ -218,7 +218,10 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo #ifndef HAVE_LIBGPGME #ifdef HAVE_OMEMO if (chatwin->is_omemo) { - omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE); + char *id = omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE); + chat_log_omemo_msg_out(chatwin->barejid, plugin_msg); + chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_OMEMO, request_receipt); + free(id); } else { char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt); chat_log_msg_out(chatwin->barejid, plugin_msg); @@ -238,7 +241,10 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo #ifndef HAVE_LIBGPGME #ifdef HAVE_OMEMO if (chatwin->is_omemo) { - omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE); + char *id = omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE); + chat_log_omemo_msg_out(chatwin->barejid, plugin_msg); + chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_OMEMO, request_receipt); + free(id); } else { gboolean handled = otr_on_message_send(chatwin, plugin_msg, request_receipt); if (!handled) { @@ -261,7 +267,10 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo #ifdef HAVE_LIBGPGME #ifdef HAVE_OMEMO if (chatwin->is_omemo) { - omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE); + char *id = omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE); + chat_log_omemo_msg_out(chatwin->barejid, plugin_msg); + chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_OMEMO, request_receipt); + free(id); } else if (chatwin->pgp_send) { char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg, request_receipt); chat_log_pgp_msg_out(chatwin->barejid, plugin_msg); @@ -286,7 +295,10 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo #ifdef HAVE_LIBGPGME #ifdef HAVE_OMEMO if (chatwin->is_omemo) { - omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE); + char *id = omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE); + chat_log_omemo_msg_out(chatwin->barejid, plugin_msg); + chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_OMEMO, request_receipt); + free(id); } else if (chatwin->pgp_send) { char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg, request_receipt); chat_log_pgp_msg_out(chatwin->barejid, plugin_msg); @@ -336,9 +348,14 @@ cl_ev_send_muc_msg(ProfMucWin *mucwin, const char *const msg, const char *const #ifdef HAVE_OMEMO if (mucwin->is_omemo) { - omemo_on_message_send((ProfWin *)mucwin, plugin_msg, FALSE, TRUE); + char *id = omemo_on_message_send((ProfWin *)mucwin, plugin_msg, FALSE, TRUE); + groupchat_log_omemo_msg_out(mucwin->roomjid, plugin_msg); + mucwin_outgoing_msg(mucwin, plugin_msg, PROF_MSG_OMEMO); + free(id); } else { message_send_groupchat(mucwin->roomjid, plugin_msg, oob_url); + groupchat_log_msg_out(mucwin->roomjid, plugin_msg); + mucwin_outgoing_msg(mucwin, plugin_msg, PROF_MSG_PLAIN); } plugins_post_room_message_send(mucwin->roomjid, plugin_msg); @@ -348,6 +365,8 @@ cl_ev_send_muc_msg(ProfMucWin *mucwin, const char *const msg, const char *const #ifndef HAVE_OMEMO message_send_groupchat(mucwin->roomjid, plugin_msg, oob_url); + groupchat_log_msg_out(mucwin->roomjid, plugin_msg); + mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_PLAIN, request_receipt); plugins_post_room_message_send(mucwin->roomjid, plugin_msg); free(plugin_msg); diff --git a/src/event/server_events.c b/src/event/server_events.c index 7f293198..fd719cc1 100644 --- a/src/event/server_events.c +++ b/src/event/server_events.c @@ -260,21 +260,26 @@ sv_ev_room_history(const char *const room_jid, const char *const nick, } void -sv_ev_room_message(const char *const room_jid, const char *const nick, const char *const message) +sv_ev_room_message(const char *const room_jid, const char *const nick, const char *const message, gboolean omemo) { - if (prefs_get_boolean(PREF_GRLOG)) { - Jid *jid = jid_create(connection_get_fulljid()); - groupchat_log_chat(jid->barejid, room_jid, nick, message); - jid_destroy(jid); - } - ProfMucWin *mucwin = wins_get_muc(room_jid); if (!mucwin) { return; } - char *new_message = plugins_pre_room_message_display(room_jid, nick, message); char *mynick = muc_nick(mucwin->roomjid); + if (g_strcmp0(mynick, nick) == 0) { + /* Ignore message reflection */ + return; + } + + if (omemo) { + groupchat_log_omemo_msg_in(room_jid, nick, message); + } else { + groupchat_log_msg_in(room_jid, nick, message); + } + + char *new_message = plugins_pre_room_message_display(room_jid, nick, message); gboolean whole_word = prefs_get_boolean(PREF_NOTIFY_MENTION_WHOLE_WORD); gboolean case_sensitive = prefs_get_boolean(PREF_NOTIFY_MENTION_CASE_SENSITIVE); @@ -289,7 +294,11 @@ sv_ev_room_message(const char *const room_jid, const char *const nick, const cha GList *triggers = prefs_message_get_triggers(new_message); - mucwin_message(mucwin, nick, new_message, mentions, triggers); + if (omemo) { + mucwin_incoming_msg(mucwin, nick, new_message, mentions, triggers, PROF_MSG_OMEMO); + } else { + mucwin_incoming_msg(mucwin, nick, new_message, mentions, triggers, PROF_MSG_PLAIN); + } g_slist_free(mentions); @@ -607,15 +616,50 @@ sv_ev_incoming_carbon(char *barejid, char *resource, char *message, char *pgp_me } #ifdef HAVE_LIBGPGME +#ifndef HAVE_OMEMO if (pgp_message) { _sv_ev_incoming_pgp(chatwin, new_win, barejid, resource, message, pgp_message, NULL); } else { _sv_ev_incoming_plain(chatwin, new_win, barejid, resource, message, NULL); } -#else - _sv_ev_incoming_plain(chatwin, new_win, barejid, resource, message, NULL); + rosterwin_roster(); + return; +#endif #endif + +#ifdef HAVE_LIBGPGME +#ifdef HAVE_OMEMO + if (pgp_message) { + _sv_ev_incoming_pgp(chatwin, new_win, barejid, resource, message, pgp_message, NULL); + } else if (omemo) { + _sv_ev_incoming_omemo(chatwin, new_win, barejid, resource, message, NULL); + } else { + _sv_ev_incoming_plain(chatwin, new_win, barejid, resource, message, NULL); + } rosterwin_roster(); + return; +#endif +#endif + +#ifndef HAVE_LIBGPGME +#ifdef HAVE_OMEMO + if (omemo) { + _sv_ev_incoming_omemo(chatwin, new_win, barejid, resource, message, NULL); + } else { + _sv_ev_incoming_plain(chatwin, new_win, barejid, resource, message, NULL); + } + rosterwin_roster(); + return; +#endif +#endif + +#ifndef HAVE_LIBGPGME +#ifndef HAVE_OMEMO + _sv_ev_incoming_plain(chatwin, new_win, barejid, resource, message, NULL); + rosterwin_roster(); + return; +#endif +#endif } void diff --git a/src/event/server_events.h b/src/event/server_events.h index 96fdb58c..0fa9989f 100644 --- a/src/event/server_events.h +++ b/src/event/server_events.h @@ -46,9 +46,9 @@ void sv_ev_room_invite(jabber_invite_t invite_type, void sv_ev_room_broadcast(const char *const room_jid, const char *const message); void sv_ev_room_subject(const char *const room, const char *const nick, const char *const subject); void sv_ev_room_history(const char *const room_jid, const char *const nick, - GDateTime *timestamp, const char *const message); + GDateTime *timestamp, const char *const message, gboolean omemo); void sv_ev_room_message(const char *const room_jid, const char *const nick, - const char *const message); + const char *const message, gboolean omemo); void sv_ev_incoming_message(char *barejid, char *resource, char *message, char *pgp_message, GDateTime *timestamp, gboolean omemo); void sv_ev_incoming_private_message(const char *const fulljid, char *message); void sv_ev_delayed_private_message(const char *const fulljid, char *message, GDateTime *timestamp); diff --git a/src/log.c b/src/log.c index 090fd2f8..b679eb1a 100644 --- a/src/log.c +++ b/src/log.c @@ -48,6 +48,7 @@ #include "config/files.h" #include "config/preferences.h" #include "xmpp/xmpp.h" +#include "xmpp/muc.h" #define PROF "prof" @@ -89,6 +90,8 @@ static void _rotate_log_file(void); static char* _log_string_from_level(log_level_t level); static void _chat_log_chat(const char *const login, const char *const other, const gchar *const msg, chat_log_direction_t direction, GDateTime *timestamp); +static void _groupchat_log_chat(const gchar *const login, const gchar *const room, const gchar *const nick, + const gchar *const msg); void log_debug(const char *const msg, ...) @@ -440,7 +443,66 @@ _chat_log_chat(const char *const login, const char *const other, const char *con } void -groupchat_log_chat(const gchar *const login, const gchar *const room, const gchar *const nick, const gchar *const msg) +groupchat_log_msg_out(const gchar *const room, const gchar *const msg) +{ + if (prefs_get_boolean(PREF_GRLOG)) { + const char *jid = connection_get_fulljid(); + Jid *jidp = jid_create(jid); + char *mynick = muc_nick(room); + _groupchat_log_chat(jidp->barejid, room, mynick, msg); + jid_destroy(jidp); + } +} + +void +groupchat_log_msg_in(const gchar *const room, const gchar *const nick, const gchar *const msg) +{ + if (prefs_get_boolean(PREF_GRLOG)) { + const char *jid = connection_get_fulljid(); + Jid *jidp = jid_create(jid); + _groupchat_log_chat(jidp->barejid, room, nick, msg); + jid_destroy(jidp); + } +} + +void +groupchat_log_omemo_msg_out(const gchar *const room, const gchar *const msg) +{ + if (prefs_get_boolean(PREF_CHLOG)) { + const char *jid = connection_get_fulljid(); + Jid *jidp = jid_create(jid); + char *pref_omemo_log = prefs_get_string(PREF_OMEMO_LOG); + char *mynick = muc_nick(room); + if (strcmp(pref_omemo_log, "on") == 0) { + _groupchat_log_chat(jidp->barejid, room, mynick, msg); + } else if (strcmp(pref_omemo_log, "redact") == 0) { + _groupchat_log_chat(jidp->barejid, room, mynick, "[redacted]"); + } + prefs_free_string(pref_omemo_log); + jid_destroy(jidp); + } +} + +void +groupchat_log_omemo_msg_in(const gchar *const room, const gchar *const nick, const gchar *const msg) +{ + if (prefs_get_boolean(PREF_CHLOG)) { + const char *jid = connection_get_fulljid(); + Jid *jidp = jid_create(jid); + char *pref_omemo_log = prefs_get_string(PREF_OMEMO_LOG); + if (strcmp(pref_omemo_log, "on") == 0) { + _groupchat_log_chat(jidp->barejid, room, nick, msg); + } else if (strcmp(pref_omemo_log, "redact") == 0) { + _groupchat_log_chat(jidp->barejid, room, nick, "[redacted]"); + } + prefs_free_string(pref_omemo_log); + jid_destroy(jidp); + } +} + +void +_groupchat_log_chat(const gchar *const login, const gchar *const room, const gchar *const nick, + const gchar *const msg) { struct dated_chat_log *dated_log = g_hash_table_lookup(groupchat_logs, room); diff --git a/src/log.h b/src/log.h index b14231b7..1f45545c 100644 --- a/src/log.h +++ b/src/log.h @@ -82,7 +82,10 @@ void chat_log_close(void); GSList* chat_log_get_previous(const gchar *const login, const gchar *const recipient); void groupchat_log_init(void); -void groupchat_log_chat(const gchar *const login, const gchar *const room, const gchar *const nick, - const gchar *const msg); + +void groupchat_log_msg_out(const gchar *const room, const gchar *const msg); +void groupchat_log_msg_in(const gchar *const room, const gchar *const nick, const gchar *const msg); +void groupchat_log_omemo_msg_out(const gchar *const room, const gchar *const msg); +void groupchat_log_omemo_msg_in(const gchar *const room, const gchar *const nick, const gchar *const msg); #endif diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c index 3fb52b08..548c3b9c 100644 --- a/src/omemo/omemo.c +++ b/src/omemo/omemo.c @@ -542,16 +542,14 @@ out: jid_destroy(ownjid); } -gboolean +char * omemo_on_message_send(ProfWin *win, const char *const message, gboolean request_receipt, gboolean muc) { + char *id = NULL; int res; - gboolean ret = FALSE; Jid *jid = jid_create(connection_get_fulljid()); GList *keys = NULL; - GList *sender_device_id = g_hash_table_lookup(omemo_ctx.device_list, jid->barejid); - unsigned char *key; unsigned char *iv; unsigned char *ciphertext; @@ -643,50 +641,48 @@ omemo_on_message_send(ProfWin *win, const char *const message, gboolean request_ g_list_free_full(recipients, free); - for (device_ids_iter = sender_device_id; device_ids_iter != NULL; device_ids_iter = device_ids_iter->next) { - int res; - ciphertext_message *ciphertext; - session_cipher *cipher; - signal_protocol_address address = { - .name = jid->barejid, - .name_len = strlen(jid->barejid), - .device_id = GPOINTER_TO_INT(device_ids_iter->data) - }; - - res = session_cipher_create(&cipher, omemo_ctx.store, &address, omemo_ctx.signal); - if (res != 0) { - log_error("OMEMO: cannot create cipher for %s device id %d", address.name, address.device_id); - continue; - } + if (!muc) { + GList *sender_device_id = g_hash_table_lookup(omemo_ctx.device_list, jid->barejid); + for (device_ids_iter = sender_device_id; device_ids_iter != NULL; device_ids_iter = device_ids_iter->next) { + int res; + ciphertext_message *ciphertext; + session_cipher *cipher; + signal_protocol_address address = { + .name = jid->barejid, + .name_len = strlen(jid->barejid), + .device_id = GPOINTER_TO_INT(device_ids_iter->data) + }; - res = session_cipher_encrypt(cipher, key_tag, AES128_GCM_KEY_LENGTH + AES128_GCM_TAG_LENGTH, &ciphertext); - if (res != 0) { - log_error("OMEMO: cannot encrypt key for %s device id %d", address.name, address.device_id); - continue; + res = session_cipher_create(&cipher, omemo_ctx.store, &address, omemo_ctx.signal); + if (res != 0) { + log_error("OMEMO: cannot create cipher for %s device id %d", address.name, address.device_id); + continue; + } + + res = session_cipher_encrypt(cipher, key_tag, AES128_GCM_KEY_LENGTH + AES128_GCM_TAG_LENGTH, &ciphertext); + if (res != 0) { + log_error("OMEMO: cannot encrypt key for %s device id %d", address.name, address.device_id); + continue; + } + signal_buffer *buffer = ciphertext_message_get_serialized(ciphertext); + omemo_key_t *key = malloc(sizeof(omemo_key_t)); + key->data = signal_buffer_data(buffer); + key->length = signal_buffer_len(buffer); + key->device_id = GPOINTER_TO_INT(device_ids_iter->data); + key->prekey = ciphertext_message_get_type(ciphertext) == CIPHERTEXT_PREKEY_TYPE; + keys = g_list_append(keys, key); } - signal_buffer *buffer = ciphertext_message_get_serialized(ciphertext); - omemo_key_t *key = malloc(sizeof(omemo_key_t)); - key->data = signal_buffer_data(buffer); - key->length = signal_buffer_len(buffer); - key->device_id = GPOINTER_TO_INT(device_ids_iter->data); - key->prekey = ciphertext_message_get_type(ciphertext) == CIPHERTEXT_PREKEY_TYPE; - keys = g_list_append(keys, key); } if (muc) { ProfMucWin *mucwin = (ProfMucWin *)win; assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); - char *id = message_send_chat_omemo(mucwin->roomjid, omemo_ctx.device_id, keys, iv, AES128_GCM_IV_LENGTH, ciphertext, ciphertext_len, request_receipt, TRUE); - free(id); + id = message_send_chat_omemo(mucwin->roomjid, omemo_ctx.device_id, keys, iv, AES128_GCM_IV_LENGTH, ciphertext, ciphertext_len, request_receipt, TRUE); } else { ProfChatWin *chatwin = (ProfChatWin *)win; assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); - char *id = message_send_chat_omemo(chatwin->barejid, omemo_ctx.device_id, keys, iv, AES128_GCM_IV_LENGTH, ciphertext, ciphertext_len, request_receipt, FALSE); - chat_log_omemo_msg_out(chatwin->barejid, message); - chatwin_outgoing_msg(chatwin, message, id, PROF_MSG_OMEMO, request_receipt); - free(id); + id = message_send_chat_omemo(chatwin->barejid, omemo_ctx.device_id, keys, iv, AES128_GCM_IV_LENGTH, ciphertext, ciphertext_len, request_receipt, FALSE); } - ret = TRUE; out: jid_destroy(jid); @@ -697,7 +693,7 @@ out: gcry_free(tag); gcry_free(key_tag); - return ret; + return id; } char * diff --git a/src/omemo/omemo.h b/src/omemo/omemo.h index a8af1a66..e78bd09b 100644 --- a/src/omemo/omemo.h +++ b/src/omemo/omemo.h @@ -40,5 +40,5 @@ void omemo_start_muc_sessions(const char *const roomjid); void omemo_start_device_session(const char *const jid, uint32_t device_id, GList *prekeys, uint32_t signed_prekey_id, const unsigned char *const signed_prekey, size_t signed_prekey_len, const unsigned char *const signature, size_t signature_len, const unsigned char *const identity_key, size_t identity_key_len); gboolean omemo_loaded(void); -gboolean 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); 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); diff --git a/src/ui/mucwin.c b/src/ui/mucwin.c index 0f9f4f2b..abbcd21c 100644 --- a/src/ui/mucwin.c +++ b/src/ui/mucwin.c @@ -478,7 +478,7 @@ _mucwin_print_triggers(ProfWin *window, const char *const message, GList *trigge } void -mucwin_message(ProfMucWin *mucwin, const char *const nick, const char *const message, GSList *mentions, GList *triggers) +mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, prof_enc_t enc_mode) { assert(mucwin != NULL); @@ -488,19 +488,43 @@ mucwin_message(ProfMucWin *mucwin, const char *const nick, const char *const mes char ch = '-'; if (mucwin->message_char) { ch = mucwin->message_char[0]; + } else if (enc_mode == PROF_MSG_OTR) { + ch = prefs_get_otr_char(); + } else if (enc_mode == PROF_MSG_PGP) { + ch = prefs_get_pgp_char(); + } else if (enc_mode == PROF_MSG_OMEMO) { + ch = prefs_get_omemo_char(); } - if (g_strcmp0(nick, mynick) != 0) { - if (g_slist_length(mentions) > 0) { - _mucwin_print_mention(window, message, nick, mynick, mentions, &ch); - } else if (triggers) { - win_print_them(window, THEME_ROOMTRIGGER, ch, nick); - _mucwin_print_triggers(window, message, triggers); - } else { - win_println_them_message(window, ch, nick, "%s", message); - } + win_println_me_message(window, ch, mynick, "%s", message); +} + +void +mucwin_incoming_msg(ProfMucWin *mucwin, const char *const nick, const char *const message, GSList *mentions, GList *triggers, prof_enc_t enc_mode) +{ + assert(mucwin != NULL); + + ProfWin *window = (ProfWin*)mucwin; + char *mynick = muc_nick(mucwin->roomjid); + + char ch = '-'; + if (mucwin->message_char) { + ch = mucwin->message_char[0]; + } else if (enc_mode == PROF_MSG_OTR) { + ch = prefs_get_otr_char(); + } else if (enc_mode == PROF_MSG_PGP) { + ch = prefs_get_pgp_char(); + } else if (enc_mode == PROF_MSG_OMEMO) { + ch = prefs_get_omemo_char(); + } + + if (g_slist_length(mentions) > 0) { + _mucwin_print_mention(window, message, nick, mynick, mentions, &ch); + } else if (triggers) { + win_print_them(window, THEME_ROOMTRIGGER, ch, nick); + _mucwin_print_triggers(window, message, triggers); } else { - win_println_me_message(window, ch, mynick, "%s", message); + win_println_them_message(window, ch, nick, "%s", message); } } diff --git a/src/ui/ui.h b/src/ui/ui.h index 95d291b4..e3cece81 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -162,7 +162,8 @@ void mucwin_occupant_role_and_affiliation_change(ProfMucWin *mucwin, const char const char *const role, const char *const affiliation, const char *const actor, const char *const reason); void mucwin_roster(ProfMucWin *mucwin, GList *occupants, const char *const presence); void mucwin_history(ProfMucWin *mucwin, const char *const nick, GDateTime *timestamp, const char *const message); -void mucwin_message(ProfMucWin *mucwin, const char *const nick, const char *const message, GSList *mentions, GList *triggers); +void mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, prof_enc_t enc_mode); +void mucwin_incoming_msg(ProfMucWin *mucwin, const char *const nick, const char *const message, GSList *mentions, GList *triggers, prof_enc_t enc_mode); void mucwin_subject(ProfMucWin *mucwin, const char *const nick, const char *const subject); void mucwin_requires_config(ProfMucWin *mucwin); void mucwin_info(ProfMucWin *mucwin); diff --git a/src/ui/window.c b/src/ui/window.c index ef0f93d2..64b04365 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -197,6 +197,7 @@ win_create_muc(const char *const roomjid) } new_win->enctext = NULL; new_win->message_char = NULL; + new_win->is_omemo = FALSE; new_win->memcheck = PROFMUCWIN_MEMCHECK; diff --git a/src/xmpp/message.c b/src/xmpp/message.c index 47a21438..cc3d66bd 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -729,8 +729,11 @@ _handle_groupchat(xmpp_stanza_t *const stanza) return; } + // check omemo encryption + gboolean omemo = FALSE; #ifdef HAVE_OMEMO message = omemo_receive_message(stanza); + omemo = message != NULL; #endif if (!message) { @@ -744,10 +747,10 @@ _handle_groupchat(xmpp_stanza_t *const stanza) // determine if the notifications happened whilst offline GDateTime *timestamp = stanza_get_delay(stanza); if (timestamp) { - sv_ev_room_history(jid->barejid, jid->resourcepart, timestamp, message); + sv_ev_room_history(jid->barejid, jid->resourcepart, timestamp, message, omemo); g_date_time_unref(timestamp); } else { - sv_ev_room_message(jid->barejid, jid->resourcepart, message); + sv_ev_room_message(jid->barejid, jid->resourcepart, message, omemo); } xmpp_free(ctx, message); -- cgit 1.4.1-2-gfad0 From e7be3a605bbb47e462265a379d48aad9cc565fc2 Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Mon, 1 Apr 2019 13:53:29 +0200 Subject: Add OMEMO in prefs command --- src/command/cmd_ac.c | 1 + src/command/cmd_defs.c | 5 +++-- src/command/cmd_funcs.c | 4 ++++ src/ui/console.c | 24 ++++++++++++++++++++++++ src/ui/ui.h | 1 + tests/unittests/ui/stub_ui.c | 1 + 6 files changed, 34 insertions(+), 2 deletions(-) (limited to 'src/ui/ui.h') diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index 7b6a865b..0cc28bb3 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -244,6 +244,7 @@ cmd_ac_init(void) autocomplete_add(prefs_ac, "presence"); autocomplete_add(prefs_ac, "otr"); autocomplete_add(prefs_ac, "pgp"); + autocomplete_add(prefs_ac, "omemo"); notify_ac = autocomplete_new(); autocomplete_add(notify_ac, "chat"); diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index b1270f63..ab4112c7 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -2134,7 +2134,7 @@ static struct cmd_t command_defs[] = CMD_MAINFUNC(cmd_prefs) CMD_NOTAGS CMD_SYN( - "/prefs [ui|desktop|chat|log|conn|presence|otr|pgp]") + "/prefs [ui|desktop|chat|log|conn|presence|otr|pgp|omemo]") CMD_DESC( "Show preferences for different areas of functionality. " "Passing no arguments shows all preferences.") @@ -2146,7 +2146,8 @@ static struct cmd_t command_defs[] = { "conn", "Connection handling preferences." }, { "presence", "Chat presence preferences." }, { "otr", "Off The Record preferences." }, - { "pgp", "OpenPGP preferences." }) + { "pgp", "OpenPGP preferences." }, + { "omemo", "OMEMO preferences." }) CMD_NOEXAMPLES }, diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index c2696c31..e1f62ace 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -1679,6 +1679,10 @@ cmd_prefs(ProfWin *window, const char *const command, gchar **args) cons_show(""); cons_show_pgp_prefs(); cons_show(""); + } else if (strcmp(args[0], "omemo") == 0) { + cons_show(""); + cons_show_omemo_prefs(); + cons_show(""); } else { cons_bad_cmd_usage(command); } diff --git a/src/ui/console.c b/src/ui/console.c index e5c12158..260658c8 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -1998,6 +1998,28 @@ cons_show_pgp_prefs(void) cons_alert(); } +void +cons_show_omemo_prefs(void) +{ + cons_show("OMEMO preferences:"); + cons_show(""); + + char *log_value = prefs_get_string(PREF_OMEMO_LOG); + if (strcmp(log_value, "on") == 0) { + cons_show("OMEMO logging (/omemo log) : ON"); + } else if (strcmp(log_value, "off") == 0) { + cons_show("OMEMO logging (/omemo log) : OFF"); + } else { + cons_show("OMEMO logging (/omemo log) : Redacted"); + } + prefs_free_string(log_value); + + char ch = prefs_get_omemo_char(); + cons_show("OMEMO char (/omemo char) : %c", ch); + + cons_alert(); +} + void cons_show_themes(GSList *themes) { @@ -2072,6 +2094,8 @@ cons_prefs(void) cons_show(""); cons_show_pgp_prefs(); cons_show(""); + cons_show_omemo_prefs(); + cons_show(""); cons_alert(); } diff --git a/src/ui/ui.h b/src/ui/ui.h index e3cece81..79701a27 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -252,6 +252,7 @@ void cons_show_presence_prefs(void); void cons_show_connection_prefs(void); void cons_show_otr_prefs(void); void cons_show_pgp_prefs(void); +void cons_show_omemo_prefs(void); void cons_show_account(ProfAccount *account); void cons_debug(const char *const msg, ...); void cons_show_error(const char *const cmd, ...); diff --git a/tests/unittests/ui/stub_ui.c b/tests/unittests/ui/stub_ui.c index e08c3ce1..950036bc 100644 --- a/tests/unittests/ui/stub_ui.c +++ b/tests/unittests/ui/stub_ui.c @@ -338,6 +338,7 @@ void cons_show_presence_prefs(void) {} void cons_show_connection_prefs(void) {} void cons_show_otr_prefs(void) {} void cons_show_pgp_prefs(void) {} +void cons_show_omemo_prefs(void) {} void cons_show_account(ProfAccount *account) { -- cgit 1.4.1-2-gfad0 From e69f947547160ea2c965a3d4f5966c5f4a289340 Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Mon, 1 Apr 2019 20:39:39 +0320 Subject: Rework MUC reflected message filtering Reflected messages can't be filtered by nick only otherwise you might ignore messages comming from you on another devices. Consequently we maintain a list of sent messages id in mucwin. To be sure the id will be correctly reflected we use the origin-id stanza. --- src/event/client_events.c | 12 +++++++----- src/event/server_events.c | 10 +++------- src/event/server_events.h | 2 +- src/ui/mucwin.c | 11 +++++++++-- src/ui/ui.h | 4 ++-- src/ui/win_types.h | 1 + src/ui/window.c | 1 + src/ui/window_list.c | 1 + src/xmpp/message.c | 18 ++++++++++++++---- src/xmpp/stanza.c | 15 +++++++++++++++ src/xmpp/stanza.h | 3 +++ src/xmpp/xmpp.h | 2 +- tests/unittests/ui/stub_ui.c | 4 ++-- tests/unittests/xmpp/stub_xmpp.c | 5 ++++- 14 files changed, 64 insertions(+), 25 deletions(-) (limited to 'src/ui/ui.h') diff --git a/src/event/client_events.c b/src/event/client_events.c index adcffbf2..c2149985 100644 --- a/src/event/client_events.c +++ b/src/event/client_events.c @@ -353,12 +353,13 @@ cl_ev_send_muc_msg(ProfMucWin *mucwin, const char *const msg, const char *const if (mucwin->is_omemo) { char *id = omemo_on_message_send((ProfWin *)mucwin, plugin_msg, FALSE, TRUE); groupchat_log_omemo_msg_out(mucwin->roomjid, plugin_msg); - mucwin_outgoing_msg(mucwin, plugin_msg, PROF_MSG_OMEMO); + mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_OMEMO); free(id); } else { - message_send_groupchat(mucwin->roomjid, plugin_msg, oob_url); + char *id = message_send_groupchat(mucwin->roomjid, plugin_msg, oob_url); groupchat_log_msg_out(mucwin->roomjid, plugin_msg); - mucwin_outgoing_msg(mucwin, plugin_msg, PROF_MSG_PLAIN); + mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_PLAIN); + free(id); } plugins_post_room_message_send(mucwin->roomjid, plugin_msg); @@ -367,9 +368,10 @@ cl_ev_send_muc_msg(ProfMucWin *mucwin, const char *const msg, const char *const #endif #ifndef HAVE_OMEMO - message_send_groupchat(mucwin->roomjid, plugin_msg, oob_url); + char *id = message_send_groupchat(mucwin->roomjid, plugin_msg, oob_url); groupchat_log_msg_out(mucwin->roomjid, plugin_msg); - mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_PLAIN, request_receipt); + mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_PLAIN); + free(id); plugins_post_room_message_send(mucwin->roomjid, plugin_msg); free(plugin_msg); diff --git a/src/event/server_events.c b/src/event/server_events.c index 023e8a13..f6c640f3 100644 --- a/src/event/server_events.c +++ b/src/event/server_events.c @@ -260,7 +260,7 @@ sv_ev_room_history(const char *const room_jid, const char *const nick, } void -sv_ev_room_message(const char *const room_jid, const char *const nick, const char *const message, gboolean omemo) +sv_ev_room_message(const char *const room_jid, const char *const nick, const char *const message, const char *const id, gboolean omemo) { ProfMucWin *mucwin = wins_get_muc(room_jid); if (!mucwin) { @@ -268,10 +268,6 @@ sv_ev_room_message(const char *const room_jid, const char *const nick, const cha } char *mynick = muc_nick(mucwin->roomjid); - if (g_strcmp0(mynick, nick) == 0) { - /* Ignore message reflection */ - return; - } if (omemo) { groupchat_log_omemo_msg_in(room_jid, nick, message); @@ -295,9 +291,9 @@ sv_ev_room_message(const char *const room_jid, const char *const nick, const cha GList *triggers = prefs_message_get_triggers(new_message); if (omemo) { - mucwin_incoming_msg(mucwin, nick, new_message, mentions, triggers, PROF_MSG_OMEMO); + mucwin_incoming_msg(mucwin, nick, new_message, id, mentions, triggers, PROF_MSG_OMEMO); } else { - mucwin_incoming_msg(mucwin, nick, new_message, mentions, triggers, PROF_MSG_PLAIN); + mucwin_incoming_msg(mucwin, nick, new_message, id, mentions, triggers, PROF_MSG_PLAIN); } g_slist_free(mentions); diff --git a/src/event/server_events.h b/src/event/server_events.h index cf437f9a..713e50f5 100644 --- a/src/event/server_events.h +++ b/src/event/server_events.h @@ -48,7 +48,7 @@ void sv_ev_room_subject(const char *const room, const char *const nick, const ch void sv_ev_room_history(const char *const room_jid, const char *const nick, GDateTime *timestamp, const char *const message, gboolean omemo); void sv_ev_room_message(const char *const room_jid, const char *const nick, - const char *const message, gboolean omemo); + const char *const message, const char *const id, gboolean omemo); void sv_ev_incoming_message(char *barejid, char *resource, char *message, char *pgp_message, GDateTime *timestamp, gboolean omemo); void sv_ev_incoming_private_message(const char *const fulljid, char *message); void sv_ev_delayed_private_message(const char *const fulljid, char *message, GDateTime *timestamp); diff --git a/src/ui/mucwin.c b/src/ui/mucwin.c index abbcd21c..0122950a 100644 --- a/src/ui/mucwin.c +++ b/src/ui/mucwin.c @@ -478,10 +478,12 @@ _mucwin_print_triggers(ProfWin *window, const char *const message, GList *trigge } void -mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, prof_enc_t enc_mode) +mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, const char *const id, prof_enc_t enc_mode) { assert(mucwin != NULL); + g_hash_table_insert(mucwin->sent_messages, strdup(id), NULL); + ProfWin *window = (ProfWin*)mucwin; char *mynick = muc_nick(mucwin->roomjid); @@ -500,10 +502,15 @@ mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, prof_enc_t en } void -mucwin_incoming_msg(ProfMucWin *mucwin, const char *const nick, const char *const message, GSList *mentions, GList *triggers, prof_enc_t enc_mode) +mucwin_incoming_msg(ProfMucWin *mucwin, const char *const nick, const char *const message, const char *const id, GSList *mentions, GList *triggers, prof_enc_t enc_mode) { assert(mucwin != NULL); + if (g_hash_table_remove(mucwin->sent_messages, id)) { + /* Ignore reflection messages */ + return; + } + ProfWin *window = (ProfWin*)mucwin; char *mynick = muc_nick(mucwin->roomjid); diff --git a/src/ui/ui.h b/src/ui/ui.h index 79701a27..b94fe475 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -162,8 +162,8 @@ void mucwin_occupant_role_and_affiliation_change(ProfMucWin *mucwin, const char const char *const role, const char *const affiliation, const char *const actor, const char *const reason); void mucwin_roster(ProfMucWin *mucwin, GList *occupants, const char *const presence); void mucwin_history(ProfMucWin *mucwin, const char *const nick, GDateTime *timestamp, const char *const message); -void mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, prof_enc_t enc_mode); -void mucwin_incoming_msg(ProfMucWin *mucwin, const char *const nick, const char *const message, GSList *mentions, GList *triggers, prof_enc_t enc_mode); +void mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, const char *const id, prof_enc_t enc_mode); +void mucwin_incoming_msg(ProfMucWin *mucwin, const char *const nick, const char *const message, const char *const id, GSList *mentions, GList *triggers, prof_enc_t enc_mode); void mucwin_subject(ProfMucWin *mucwin, const char *const nick, const char *const subject); void mucwin_requires_config(ProfMucWin *mucwin); void mucwin_info(ProfMucWin *mucwin); diff --git a/src/ui/win_types.h b/src/ui/win_types.h index 498d9bbe..e1e64bf9 100644 --- a/src/ui/win_types.h +++ b/src/ui/win_types.h @@ -172,6 +172,7 @@ typedef struct prof_muc_win_t { unsigned long memcheck; char *enctext; char *message_char; + GHashTable *sent_messages; } ProfMucWin; typedef struct prof_conf_win_t ProfConfWin; diff --git a/src/ui/window.c b/src/ui/window.c index 64b04365..12b6c15b 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -198,6 +198,7 @@ win_create_muc(const char *const roomjid) new_win->enctext = NULL; new_win->message_char = NULL; new_win->is_omemo = FALSE; + new_win->sent_messages = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL); new_win->memcheck = PROFMUCWIN_MEMCHECK; diff --git a/src/ui/window_list.c b/src/ui/window_list.c index 5ce68d63..43230b57 100644 --- a/src/ui/window_list.c +++ b/src/ui/window_list.c @@ -561,6 +561,7 @@ wins_close_by_num(int i) ProfMucWin *mucwin = (ProfMucWin*)window; autocomplete_remove(wins_ac, mucwin->roomjid); autocomplete_remove(wins_close_ac, mucwin->roomjid); + g_hash_table_remove_all(mucwin->sent_messages); break; } case WIN_PRIVATE: diff --git a/src/xmpp/message.c b/src/xmpp/message.c index 2a6ad234..47cf35d7 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -326,6 +326,7 @@ message_send_chat_omemo(const char *const jid, uint32_t sid, GList *keys, if (muc) { id = connection_create_stanza_id("muc"); message = xmpp_message_new(ctx, STANZA_TYPE_GROUPCHAT, jid, id); + stanza_attach_origin_id(ctx, message, id); } else { id = connection_create_stanza_id("msg"); message = xmpp_message_new(ctx, STANZA_TYPE_CHAT, jid, id); @@ -442,23 +443,24 @@ message_send_private(const char *const fulljid, const char *const msg, const cha xmpp_stanza_release(message); } -void +char* message_send_groupchat(const char *const roomjid, const char *const msg, const char *const oob_url) { xmpp_ctx_t * const ctx = connection_get_ctx(); char *id = connection_create_stanza_id("muc"); xmpp_stanza_t *message = xmpp_message_new(ctx, STANZA_TYPE_GROUPCHAT, roomjid, id); + stanza_attach_origin_id(ctx, message, id); xmpp_message_set_body(message, msg); - free(id); - if (oob_url) { stanza_attach_x_oob_url(ctx, message, oob_url); } _send_message_stanza(message); xmpp_stanza_release(message); + + return id; } void @@ -687,6 +689,14 @@ _handle_groupchat(xmpp_stanza_t *const stanza) { xmpp_ctx_t *ctx = connection_get_ctx(); char *message = NULL; + + const char *id = xmpp_stanza_get_id(stanza); + + xmpp_stanza_t *origin = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_STABLE_ID); + if (origin && g_strcmp0(xmpp_stanza_get_name(origin), STANZA_NAME_ORIGIN_ID) == 0) { + id = xmpp_stanza_get_attribute(origin, STANZA_ATTR_ID); + } + const char *room_jid = xmpp_stanza_get_from(stanza); Jid *jid = jid_create(room_jid); @@ -750,7 +760,7 @@ _handle_groupchat(xmpp_stanza_t *const stanza) sv_ev_room_history(jid->barejid, jid->resourcepart, timestamp, message, omemo); g_date_time_unref(timestamp); } else { - sv_ev_room_message(jid->barejid, jid->resourcepart, message, omemo); + sv_ev_room_message(jid->barejid, jid->resourcepart, message, id, omemo); } xmpp_free(ctx, message); diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index f4fd8aa8..615de44f 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -2417,6 +2417,21 @@ stanza_create_pubsub_configure_submit(xmpp_ctx_t *ctx, const char *const id, con return iq; } +xmpp_stanza_t* +stanza_attach_origin_id(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza, const char *const id) +{ + xmpp_stanza_t *origin_id = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(origin_id, STANZA_NAME_ORIGIN_ID); + xmpp_stanza_set_ns(origin_id, STANZA_NS_STABLE_ID); + xmpp_stanza_set_attribute(origin_id, STANZA_ATTR_ID, id); + + xmpp_stanza_add_child(stanza, origin_id); + + xmpp_stanza_release(origin_id); + + return stanza; +} + static void _stanza_add_unique_id(xmpp_stanza_t *stanza, char *prefix) { diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index eaf76a27..e5e17ba4 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -102,6 +102,7 @@ #define STANZA_NAME_URL "url" #define STANZA_NAME_COMMAND "command" #define STANZA_NAME_CONFIGURE "configure" +#define STANZA_NAME_ORIGIN_ID "origin-id" // error conditions #define STANZA_NAME_BAD_REQUEST "bad-request" @@ -196,6 +197,7 @@ #define STANZA_NS_OMEMO "eu.siacs.conversations.axolotl" #define STANZA_NS_OMEMO_DEVICELIST "eu.siacs.conversations.axolotl.devicelist" #define STANZA_NS_OMEMO_BUNDLES "eu.siacs.conversations.axolotl.bundles" +#define STANZA_NS_STABLE_ID "urn:xmpp:sid:0" #define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo" @@ -238,6 +240,7 @@ xmpp_stanza_t* stanza_attach_hints_no_store(xmpp_ctx_t *ctx, xmpp_stanza_t *stan xmpp_stanza_t* stanza_attach_hints_store(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza); xmpp_stanza_t* stanza_attach_receipt_request(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza); xmpp_stanza_t* stanza_attach_x_oob_url(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza, const char *const url); +xmpp_stanza_t* stanza_attach_origin_id(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza, const char *const id); xmpp_stanza_t* stanza_create_room_join_presence(xmpp_ctx_t *const ctx, const char *const full_room_jid, const char *const passwd); diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index 39877bc2..54a56f02 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -144,7 +144,7 @@ char* message_send_chat_otr(const char *const barejid, const char *const msg, gb 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); void message_send_private(const char *const fulljid, const char *const msg, const char *const oob_url); -void 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); void message_send_groupchat_subject(const char *const roomjid, const char *const subject); void message_send_inactive(const char *const jid); void message_send_composing(const char *const jid); diff --git a/tests/unittests/ui/stub_ui.c b/tests/unittests/ui/stub_ui.c index 950036bc..361a42e2 100644 --- a/tests/unittests/ui/stub_ui.c +++ b/tests/unittests/ui/stub_ui.c @@ -190,8 +190,8 @@ void mucwin_occupant_role_and_affiliation_change(ProfMucWin *mucwin, const char const char * const affiliation, const char * const actor, const char * const reason) {} void mucwin_roster(ProfMucWin *mucwin, GList *occupants, const char * const presence) {} void mucwin_history(ProfMucWin *mucwin, const char * const nick, GDateTime *timestamp, const char * const message) {} -void mucwin_incoming_msg(ProfMucWin *mucwin, const char *const nick, const char *const message, GSList *mentions, GList *triggers, prof_enc_t enc_mode) {} -void mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, prof_enc_t enc_mode) {} +void mucwin_incoming_msg(ProfMucWin *mucwin, const char *const nick, const char *const message, const char *const id, GSList *mentions, GList *triggers, prof_enc_t enc_mode) {} +void mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, const char *const id, prof_enc_t enc_mode) {} void mucwin_subject(ProfMucWin *mucwin, const char * const nick, const char * const subject) {} void mucwin_requires_config(ProfMucWin *mucwin) {} void ui_room_destroy(const char * const roomjid) {} diff --git a/tests/unittests/xmpp/stub_xmpp.c b/tests/unittests/xmpp/stub_xmpp.c index bc2c50db..53a729e6 100644 --- a/tests/unittests/xmpp/stub_xmpp.c +++ b/tests/unittests/xmpp/stub_xmpp.c @@ -114,7 +114,10 @@ char* message_send_chat_pgp(const char * const barejid, const char * const msg, } void message_send_private(const char * const fulljid, const char * const msg, const char *const oob_url) {} -void 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) +{ + return NULL; +} void message_send_groupchat_subject(const char * const roomjid, const char * const subject) {} void message_send_inactive(const char * const barejid) {} -- cgit 1.4.1-2-gfad0