From fe9b520c42ad404dee6137fc5c0937a6bd30bbc4 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Wed, 8 Apr 2020 16:22:36 +0200 Subject: [PATCH 01/11] First MAM test Send a request (which we can't handle yet) :-) Regards https://github.com/profanity-im/profanity/issues/660 --- src/xmpp/iq.c | 19 +++++++++++ src/xmpp/stanza.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++ src/xmpp/stanza.h | 3 ++ src/xmpp/xmpp.h | 1 + 4 files changed, 105 insertions(+) diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index 07a68bce..b36ca229 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -2499,3 +2499,22 @@ _iq_free_affiliation_list(ProfAffiliationList *affiliation_list) free(affiliation_list); } } + +void +iq_mam_request(ProfChatWin *win) +{ + //TODDO: check for mam feature + //if (connection_supports(XMPP_FEATURE_PING) == FALSE) { + + xmpp_ctx_t * const ctx = connection_get_ctx(); + char *id = connection_create_stanza_id(); + xmpp_stanza_t *iq = stanza_create_mam_iq(ctx, win->barejid, "2020-01-06T00:00:00Z"); + +// iq_id_handler_add(id, _http_upload_response_id_handler, NULL, upload); + free(id); + + iq_send_stanza(iq); + xmpp_stanza_release(iq); + + return; +} diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index 56185843..a247cfc4 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -2635,3 +2635,85 @@ stanza_attach_correction(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza, const char *con return stanza; } + +xmpp_stanza_t* +stanza_create_mam_iq(xmpp_ctx_t *ctx, const char *const jid, const char *const startdate) +{ + char *id = connection_create_stanza_id(); + xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); + free(id); + //xmpp_stanza_set_to(iq, jid); + + xmpp_stanza_t *query = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(query, STANZA_NAME_QUERY); + xmpp_stanza_set_ns(query, STANZA_NS_MAM2); + + xmpp_stanza_t *x = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(x, STANZA_NAME_X); + xmpp_stanza_set_ns(x, STANZA_NS_DATA); + xmpp_stanza_set_type(x, "submit"); + + // field FORM_TYPE MAM2 + xmpp_stanza_t *field_form_type = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(field_form_type, STANZA_NAME_FIELD); + xmpp_stanza_set_attribute(field_form_type, STANZA_ATTR_VAR, "FORM_TYPE"); + xmpp_stanza_set_type(field_form_type, "hidden"); + + xmpp_stanza_t *value_mam = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(value_mam, STANZA_NAME_VALUE); + + xmpp_stanza_t *mam_text = xmpp_stanza_new(ctx); + xmpp_stanza_set_text(mam_text, STANZA_NS_MAM2); + xmpp_stanza_add_child(value_mam, mam_text); + + xmpp_stanza_add_child(field_form_type, value_mam); + + // field 'with' + xmpp_stanza_t *field_with = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(field_with, STANZA_NAME_FIELD); + xmpp_stanza_set_attribute(field_with, STANZA_ATTR_VAR, "with"); + + xmpp_stanza_t *value_with = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(value_with, STANZA_NAME_VALUE); + + xmpp_stanza_t *with_text = xmpp_stanza_new(ctx); + xmpp_stanza_set_text(with_text, jid); + xmpp_stanza_add_child(value_with, with_text); + + xmpp_stanza_add_child(field_with, value_with); + + // field 'start' + xmpp_stanza_t *field_start = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(field_start, STANZA_NAME_FIELD); + xmpp_stanza_set_attribute(field_start, STANZA_ATTR_VAR, "start"); + + xmpp_stanza_t *value_start = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(value_start, STANZA_NAME_VALUE); + + xmpp_stanza_t *date_text = xmpp_stanza_new(ctx); + xmpp_stanza_set_text(date_text, startdate); + xmpp_stanza_add_child(value_start, date_text); + + xmpp_stanza_add_child(field_start, value_start); + + // add and release + xmpp_stanza_add_child(iq, query); + xmpp_stanza_add_child(query, x); + xmpp_stanza_add_child(x, field_form_type); + xmpp_stanza_add_child(x, field_with); + xmpp_stanza_add_child(x, field_start); + + xmpp_stanza_release(mam_text); + xmpp_stanza_release(with_text); + xmpp_stanza_release(date_text); + xmpp_stanza_release(value_mam); + xmpp_stanza_release(value_with); + xmpp_stanza_release(value_start); + xmpp_stanza_release(field_form_type); + xmpp_stanza_release(field_with); + xmpp_stanza_release(field_start); + xmpp_stanza_release(x); + xmpp_stanza_release(query); + + return iq; +} diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index ee5c6772..80bebba5 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -202,6 +202,7 @@ #define STANZA_NS_USER_AVATAR_DATA "urn:xmpp:avatar:data" #define STANZA_NS_USER_AVATAR_METADATA "urn:xmpp:avatar:metadata" #define STANZA_NS_LAST_MESSAGE_CORRECTION "urn:xmpp:message-correct:0" +#define STANZA_NS_MAM2 "urn:xmpp:mam:2" #define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo" @@ -359,4 +360,6 @@ xmpp_stanza_t* stanza_get_child_by_name_and_ns(xmpp_stanza_t * const stanza, con xmpp_stanza_t* stanza_create_avatar_retrieve_data_request(xmpp_ctx_t *ctx, const char *stanza_id, const char *const item_id, const char *const jid); +xmpp_stanza_t* stanza_create_mam_iq(xmpp_ctx_t *ctx, const char *const jid, const char *const startdate); + #endif diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index 4dff46cc..7544189b 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -237,6 +237,7 @@ void iq_autoping_check(void); void iq_http_upload_request(HTTPUpload *upload); void iq_command_list(const char *const target); void iq_command_exec(const char *const target, const char *const command); +void iq_mam_request(ProfChatWin *win); EntityCapabilities* caps_lookup(const char *const jid); void caps_close(void); From e878b6d266fba2ce8dfabedcbb83163d7ec75178 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Wed, 8 Apr 2020 17:12:16 +0200 Subject: [PATCH 02/11] Don't crash if we get a message without from or type MAM messages don't have a type nor a from. If we detect a message without type let's log it and exit without continuing to try to parse it. Otherwise we go into _handle_chat() and crash on the no from. --- src/xmpp/message.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/xmpp/message.c b/src/xmpp/message.c index 81928d90..0f5e644d 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -99,13 +99,20 @@ _message_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *con size_t text_size; xmpp_stanza_to_text(stanza, &text, &text_size); gboolean cont = plugins_on_message_stanza_receive(text); - xmpp_free(connection_get_ctx(), text); if (!cont) { + xmpp_free(connection_get_ctx(), text); return 1; } const char *type = xmpp_stanza_get_type(stanza); + if (type == NULL) { + log_info("Received without 'type': %s", text); + xmpp_free(connection_get_ctx(), text); + return 1; + } + xmpp_free(connection_get_ctx(), text); + if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { _handle_error(stanza); } From f3b8cc407dc5ab5a5075095393bfffe5f1c09a33 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Wed, 8 Apr 2020 17:20:35 +0200 Subject: [PATCH 03/11] _handle_chat: return if no 'from' Let's not crash :-) --- src/xmpp/message.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/xmpp/message.c b/src/xmpp/message.c index 0f5e644d..98ab40c8 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -1179,6 +1179,9 @@ _handle_chat(xmpp_stanza_t *const stanza) } const gchar *from = xmpp_stanza_get_from(stanza); + if (!from) { + return; + } Jid *jid = jid_create(from); // private message from chat room use full jid (room/nick) From 38273fef5c04b9777fd4e030e5a2d15619623bb0 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Wed, 8 Apr 2020 17:51:10 +0200 Subject: [PATCH 04/11] First test with receiving MAM --- src/xmpp/message.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/xmpp/message.c b/src/xmpp/message.c index 98ab40c8..73ae8549 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -85,6 +85,7 @@ static void _handle_conference(xmpp_stanza_t *const stanza); static void _handle_captcha(xmpp_stanza_t *const stanza); static void _handle_receipt_received(xmpp_stanza_t *const stanza); static void _handle_chat(xmpp_stanza_t *const stanza); +static gboolean _handle_mam(xmpp_stanza_t *const stanza); static void _send_message_stanza(xmpp_stanza_t *const stanza); @@ -107,10 +108,16 @@ _message_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *con const char *type = xmpp_stanza_get_type(stanza); if (type == NULL) { + if (_handle_mam(stanza)) { + xmpp_free(connection_get_ctx(), text); + return 1; + } + log_info("Received without 'type': %s", text); xmpp_free(connection_get_ctx(), text); return 1; } + xmpp_free(connection_get_ctx(), text); if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { @@ -1266,6 +1273,26 @@ _handle_chat(xmpp_stanza_t *const stanza) message_free(message); } +static gboolean +_handle_mam(xmpp_stanza_t *const stanza) +{ + xmpp_stanza_t *result = stanza_get_child_by_name_and_ns(stanza, "result", STANZA_NS_MAM2); + if (!result) { + return FALSE; + } + + xmpp_stanza_t *forwarded = xmpp_stanza_get_child_by_ns(result, STANZA_NS_FORWARD); + if (!forwarded) { + log_warning("MAM received with no forwarded element"); + return FALSE; + } + + xmpp_stanza_t *message_stanza = xmpp_stanza_get_child_by_ns(forwarded, "jabber:client"); + _handle_chat(message_stanza); + + return TRUE; +} + static void _send_message_stanza(xmpp_stanza_t *const stanza) { From e23bc3808350a4fbf6086bde71108c56e2b1c69f Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Wed, 8 Apr 2020 17:51:55 +0200 Subject: [PATCH 05/11] Quick and dirty display of MAM messages --- src/ui/chatwin.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ui/chatwin.c b/src/ui/chatwin.c index 975c6b2a..656ac2a9 100644 --- a/src/ui/chatwin.c +++ b/src/ui/chatwin.c @@ -57,7 +57,7 @@ #include "omemo/omemo.h" #endif -static void _chatwin_history(ProfChatWin *chatwin, const char *const contact_barejid); +/*static void _chatwin_history(ProfChatWin *chatwin, const char *const contact_barejid);*/ static void _chatwin_set_last_message(ProfChatWin *chatwin, const char *const id, const char *const message); ProfChatWin* @@ -67,7 +67,7 @@ chatwin_new(const char *const barejid) ProfChatWin *chatwin = (ProfChatWin *)window; if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) { - _chatwin_history(chatwin, barejid); + //_chatwin_history(chatwin, barejid); } // if the contact is offline, show a message @@ -87,6 +87,7 @@ chatwin_new(const char *const barejid) } #endif + iq_mam_request(chatwin); return chatwin; } @@ -278,7 +279,7 @@ chatwin_incoming_msg(ProfChatWin *chatwin, ProfMessage *message, gboolean win_cr chatwin->unread++; if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) { - _chatwin_history(chatwin, chatwin->barejid); +// _chatwin_history(chatwin, chatwin->barejid); } // show users status first, when receiving message via delayed delivery @@ -477,6 +478,7 @@ chatwin_unset_outgoing_char(ProfChatWin *chatwin) } } +/* static void _chatwin_history(ProfChatWin *chatwin, const char *const contact_barejid) { @@ -494,6 +496,7 @@ _chatwin_history(ProfChatWin *chatwin, const char *const contact_barejid) g_slist_free_full(history, (GDestroyNotify)message_free); } } +*/ static void _chatwin_set_last_message(ProfChatWin *chatwin, const char *const id, const char *const message) From 180ec2b474b39de0b22964adbfc5e13bc3d2c791 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Sat, 11 Apr 2020 17:11:53 +0200 Subject: [PATCH 06/11] Add to_jid field to ProfMessage struct Is usefult in many cases if we want cleaner code. Hope this edit didn't break anything though ;-) --- src/database.c | 9 +++--- src/event/server_events.c | 68 ++++++++++++++++++++------------------- src/log.c | 28 ++++++++-------- src/plugins/api.c | 2 +- src/ui/chatwin.c | 6 ++-- src/ui/mucwin.c | 6 ++-- src/ui/window.c | 16 ++++----- src/xmpp/message.c | 56 ++++++++++++++++++-------------- src/xmpp/xmpp.h | 3 +- 9 files changed, 103 insertions(+), 91 deletions(-) diff --git a/src/database.c b/src/database.c index ddff84cc..d268a5d2 100644 --- a/src/database.c +++ b/src/database.c @@ -166,7 +166,7 @@ log_database_add_incoming(ProfMessage *message) const char *jid = connection_get_fulljid(); Jid *myjid = jid_create(jid); - _add_to_db(message, NULL, message->jid, myjid); + _add_to_db(message, NULL, message->from_jid, myjid); jid_destroy(myjid); } @@ -177,7 +177,7 @@ _log_database_add_outgoing(char *type, const char * const id, const char * const ProfMessage *msg = message_init(); msg->id = id ? strdup(id) : NULL; - msg->jid = jid_create(barejid); + msg->from_jid = jid_create(barejid); msg->plain = message ? strdup(message) : NULL; msg->replace_id = replace_id ? strdup(replace_id) : NULL; msg->timestamp = g_date_time_new_now_local(); //TODO: get from outside. best to have whole ProfMessage from outside @@ -186,7 +186,7 @@ _log_database_add_outgoing(char *type, const char * const id, const char * const const char *jid = connection_get_fulljid(); Jid *myjid = jid_create(jid); - _add_to_db(msg, type, myjid, msg->jid); + _add_to_db(msg, type, myjid, msg->from_jid); // TODO: myjid now in profmessage jid_destroy(myjid); message_free(msg); @@ -234,13 +234,14 @@ log_database_get_previous_chat(const gchar *const contact_barejid) GSList *history = NULL; while( sqlite3_step(stmt) == SQLITE_ROW ) { + // TODO: also save to jid. since now part of profmessage char *message = (char*)sqlite3_column_text(stmt, 0); char *date = (char*)sqlite3_column_text(stmt, 1); char *from = (char*)sqlite3_column_text(stmt, 2); char *type = (char*)sqlite3_column_text(stmt, 3); ProfMessage *msg = message_init(); - msg->jid = jid_create(from); + msg->from_jid = jid_create(from); msg->plain = strdup(message); msg->timestamp = g_date_time_new_from_iso8601(date, NULL); msg->type = _get_message_type_type(type); diff --git a/src/event/server_events.c b/src/event/server_events.c index 7a09aaa6..11b5d877 100644 --- a/src/event/server_events.c +++ b/src/event/server_events.c @@ -275,7 +275,7 @@ sv_ev_room_subject(const char *const room, const char *const nick, const char *c void sv_ev_room_history(ProfMessage *message) { - ProfMucWin *mucwin = wins_get_muc(message->jid->barejid); + ProfMucWin *mucwin = wins_get_muc(message->from_jid->barejid); if (mucwin) { // if this is the first successful connection if (ev_is_first_connect()) { @@ -297,9 +297,9 @@ sv_ev_room_history(ProfMessage *message) static void _log_muc(ProfMessage *message) { if (message->enc == PROF_MSG_ENC_OMEMO) { - groupchat_log_omemo_msg_in(message->jid->barejid, message->jid->resourcepart, message->plain); + groupchat_log_omemo_msg_in(message->from_jid->barejid, message->from_jid->resourcepart, message->plain); } else { - groupchat_log_msg_in(message->jid->barejid, message->jid->resourcepart, message->plain); + groupchat_log_msg_in(message->from_jid->barejid, message->from_jid->resourcepart, message->plain); } log_database_add_incoming(message); } @@ -307,7 +307,7 @@ static void _log_muc(ProfMessage *message) void sv_ev_room_message(ProfMessage *message) { - ProfMucWin *mucwin = wins_get_muc(message->jid->barejid); + ProfMucWin *mucwin = wins_get_muc(message->from_jid->barejid); if (!mucwin) { return; } @@ -316,12 +316,12 @@ sv_ev_room_message(ProfMessage *message) // only log message not coming from this client (but maybe same account, different client) // our messages are logged when outgoing - if (!(g_strcmp0(mynick, message->jid->resourcepart) == 0 && message_is_sent_by_us(message, TRUE))) { + if (!(g_strcmp0(mynick, message->from_jid->resourcepart) == 0 && message_is_sent_by_us(message, TRUE))) { _log_muc(message); } char *old_plain = message->plain; - message->plain = plugins_pre_room_message_display(message->jid->barejid, message->jid->resourcepart, message->plain); + message->plain = plugins_pre_room_message_display(message->from_jid->barejid, message->from_jid->resourcepart, message->plain); GSList *mentions = get_mentions(prefs_get_boolean(PREF_NOTIFY_MENTION_WHOLE_WORD), prefs_get_boolean(PREF_NOTIFY_MENTION_CASE_SENSITIVE), message->plain, mynick); gboolean mention = g_slist_length(mentions) > 0; @@ -341,7 +341,7 @@ sv_ev_room_message(ProfMessage *message) is_current = TRUE; status_bar_active(num, WIN_MUC, mucwin->roomjid); - if ((g_strcmp0(mynick, message->jid->resourcepart) != 0) && (prefs_get_boolean(PREF_BEEP))) { + if ((g_strcmp0(mynick, message->from_jid->resourcepart) != 0) && (prefs_get_boolean(PREF_BEEP))) { beep(); } @@ -349,11 +349,11 @@ sv_ev_room_message(ProfMessage *message) } else { status_bar_new(num, WIN_MUC, mucwin->roomjid); - if ((g_strcmp0(mynick, message->jid->resourcepart) != 0) && (prefs_get_boolean(PREF_FLASH))) { + if ((g_strcmp0(mynick, message->from_jid->resourcepart) != 0) && (prefs_get_boolean(PREF_FLASH))) { flash(); } - cons_show_incoming_room_message(message->jid->resourcepart, mucwin->roomjid, num, mention, triggers, mucwin->unread); + cons_show_incoming_room_message(message->from_jid->resourcepart, mucwin->roomjid, num, mention, triggers, mucwin->unread); mucwin->unread++; @@ -371,9 +371,9 @@ sv_ev_room_message(ProfMessage *message) } mucwin->last_msg_timestamp = g_date_time_new_now_local(); - if (prefs_do_room_notify(is_current, mucwin->roomjid, mynick, message->jid->resourcepart, message->plain, mention, triggers != NULL)) { + if (prefs_do_room_notify(is_current, mucwin->roomjid, mynick, message->from_jid->resourcepart, message->plain, mention, triggers != NULL)) { Jid *jidp = jid_create(mucwin->roomjid); - notify_room_message(message->jid->resourcepart, jidp->localpart, num, message->plain); + notify_room_message(message->from_jid->resourcepart, jidp->localpart, num, message->plain); jid_destroy(jidp); } @@ -383,7 +383,7 @@ sv_ev_room_message(ProfMessage *message) rosterwin_roster(); - plugins_post_room_message_display(message->jid->barejid, message->jid->resourcepart, message->plain); + plugins_post_room_message_display(message->from_jid->barejid, message->from_jid->resourcepart, message->plain); free(message->plain); message->plain = old_plain; } @@ -392,11 +392,11 @@ void sv_ev_incoming_private_message(ProfMessage *message) { char *old_plain = message->plain; - message->plain = plugins_pre_priv_message_display(message->jid->fulljid, message->plain); + message->plain = plugins_pre_priv_message_display(message->from_jid->fulljid, message->plain); - ProfPrivateWin *privatewin = wins_get_private(message->jid->fulljid); + ProfPrivateWin *privatewin = wins_get_private(message->from_jid->fulljid); if (privatewin == NULL) { - ProfWin *window = wins_new_private(message->jid->fulljid); + ProfWin *window = wins_new_private(message->from_jid->fulljid); privatewin = (ProfPrivateWin*)window; } @@ -405,7 +405,7 @@ sv_ev_incoming_private_message(ProfMessage *message) log_database_add_incoming(message); chat_log_msg_in(message); - plugins_post_priv_message_display(message->jid->fulljid, message->plain); + plugins_post_priv_message_display(message->from_jid->fulljid, message->plain); free(message->plain); message->plain = old_plain; @@ -416,11 +416,11 @@ void sv_ev_delayed_private_message(ProfMessage *message) { char *old_plain = message->plain; - message->plain = plugins_pre_priv_message_display(message->jid->fulljid, message->plain); + message->plain = plugins_pre_priv_message_display(message->from_jid->fulljid, message->plain); - ProfPrivateWin *privatewin = wins_get_private(message->jid->fulljid); + ProfPrivateWin *privatewin = wins_get_private(message->from_jid->fulljid); if (privatewin == NULL) { - ProfWin *window = wins_new_private(message->jid->fulljid); + ProfWin *window = wins_new_private(message->from_jid->fulljid); privatewin = (ProfPrivateWin*)window; } @@ -428,7 +428,7 @@ sv_ev_delayed_private_message(ProfMessage *message) privwin_incoming_msg(privatewin, message); chat_log_msg_in(message); - plugins_post_priv_message_display(message->jid->fulljid, message->plain); + plugins_post_priv_message_display(message->from_jid->fulljid, message->plain); free(message->plain); message->plain = old_plain; @@ -437,19 +437,20 @@ sv_ev_delayed_private_message(ProfMessage *message) void sv_ev_outgoing_carbon(ProfMessage *message) { - ProfChatWin *chatwin = wins_get_chat(message->jid->barejid); + ProfChatWin *chatwin = wins_get_chat(message->from_jid->barejid); if (!chatwin) { - chatwin = chatwin_new(message->jid->barejid); + chatwin = chatwin_new(message->from_jid->barejid); } chat_state_active(chatwin->state); + //TODO: check whether we need to change from and to for carbon. now that we have profmessage->to_jid? if (message->plain) { if (message->type == PROF_MSG_TYPE_MUCPM) { // MUC PM, should have resource (nick) in filename - chat_log_msg_out(message->jid->barejid, message->plain, message->jid->resourcepart); + chat_log_msg_out(message->from_jid->barejid, message->plain, message->from_jid->resourcepart); } else { - chat_log_msg_out(message->jid->barejid, message->plain, NULL); + chat_log_msg_out(message->from_jid->barejid, message->plain, NULL); } } @@ -566,7 +567,7 @@ static void _sv_ev_incoming_otr(ProfChatWin *chatwin, gboolean new_win, ProfMessage *message) { gboolean decrypted = FALSE; - message->plain = otr_on_message_recv(message->jid->barejid, message->jid->resourcepart, message->body, &decrypted); + message->plain = otr_on_message_recv(message->from_jid->barejid, message->from_jid->resourcepart, message->body, &decrypted); if (message->plain) { if (decrypted) { message->enc = PROF_MSG_ENC_OTR; @@ -621,15 +622,15 @@ void sv_ev_incoming_message(ProfMessage *message) { gboolean new_win = FALSE; - ProfChatWin *chatwin = wins_get_chat(message->jid->barejid); + ProfChatWin *chatwin = wins_get_chat(message->from_jid->barejid); if (!chatwin) { - ProfWin *window = wins_new_chat(message->jid->barejid); + ProfWin *window = wins_new_chat(message->from_jid->barejid); chatwin = (ProfChatWin*)window; new_win = TRUE; #ifdef HAVE_OMEMO - if (omemo_automatic_start(message->jid->barejid)) { - omemo_start_session(message->jid->barejid); + if (omemo_automatic_start(message->from_jid->barejid)) { + omemo_start_session(message->from_jid->barejid); chatwin->is_omemo = TRUE; } #endif @@ -763,16 +764,17 @@ sv_ev_incoming_message(ProfMessage *message) void sv_ev_incoming_carbon(ProfMessage *message) { + //TODO: check whether we need to change from and to for carbon. now that we have profmessage->to_jid? gboolean new_win = FALSE; - ProfChatWin *chatwin = wins_get_chat(message->jid->barejid); + ProfChatWin *chatwin = wins_get_chat(message->from_jid->barejid); if (!chatwin) { - ProfWin *window = wins_new_chat(message->jid->barejid); + ProfWin *window = wins_new_chat(message->from_jid->barejid); chatwin = (ProfChatWin*)window; new_win = TRUE; #ifdef HAVE_OMEMO - if (omemo_automatic_start(message->jid->barejid)) { - omemo_start_session(message->jid->barejid); + if (omemo_automatic_start(message->from_jid->barejid)) { + omemo_start_session(message->from_jid->barejid); chatwin->is_omemo = TRUE; } #endif diff --git a/src/log.c b/src/log.c index ae8f1542..f5c489e2 100644 --- a/src/log.c +++ b/src/log.c @@ -357,15 +357,15 @@ chat_log_otr_msg_in(ProfMessage *message) char *pref_otr_log = prefs_get_string(PREF_OTR_LOG); if (message->enc == PROF_MSG_ENC_NONE || (strcmp(pref_otr_log, "on") == 0)) { if (message->type == PROF_MSG_TYPE_MUCPM) { - _chat_log_chat(jidp->barejid, message->jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, message->jid->resourcepart); + _chat_log_chat(jidp->barejid, message->from_jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, message->from_jid->resourcepart); } else { - _chat_log_chat(jidp->barejid, message->jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, NULL); + _chat_log_chat(jidp->barejid, message->from_jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, NULL); } } else if (strcmp(pref_otr_log, "redact") == 0) { if (message->type == PROF_MSG_TYPE_MUCPM) { - _chat_log_chat(jidp->barejid, message->jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, message->jid->resourcepart); + _chat_log_chat(jidp->barejid, message->from_jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, message->from_jid->resourcepart); } else { - _chat_log_chat(jidp->barejid, message->jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, NULL); + _chat_log_chat(jidp->barejid, message->from_jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, NULL); } } prefs_free_string(pref_otr_log); @@ -382,15 +382,15 @@ chat_log_pgp_msg_in(ProfMessage *message) char *pref_pgp_log = prefs_get_string(PREF_PGP_LOG); if (strcmp(pref_pgp_log, "on") == 0) { if (message->type == PROF_MSG_TYPE_MUCPM) { - _chat_log_chat(jidp->barejid, message->jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, message->jid->resourcepart); + _chat_log_chat(jidp->barejid, message->from_jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, message->from_jid->resourcepart); } else { - _chat_log_chat(jidp->barejid, message->jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, NULL); + _chat_log_chat(jidp->barejid, message->from_jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, NULL); } } else if (strcmp(pref_pgp_log, "redact") == 0) { if (message->type == PROF_MSG_TYPE_MUCPM) { - _chat_log_chat(jidp->barejid, message->jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, message->jid->resourcepart); + _chat_log_chat(jidp->barejid, message->from_jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, message->from_jid->resourcepart); } else { - _chat_log_chat(jidp->barejid, message->jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, NULL); + _chat_log_chat(jidp->barejid, message->from_jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, NULL); } } prefs_free_string(pref_pgp_log); @@ -407,15 +407,15 @@ chat_log_omemo_msg_in(ProfMessage *message) char *pref_omemo_log = prefs_get_string(PREF_OMEMO_LOG); if (strcmp(pref_omemo_log, "on") == 0) { if (message->type == PROF_MSG_TYPE_MUCPM) { - _chat_log_chat(jidp->barejid, message->jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, message->jid->resourcepart); + _chat_log_chat(jidp->barejid, message->from_jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, message->from_jid->resourcepart); } else { - _chat_log_chat(jidp->barejid, message->jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, NULL); + _chat_log_chat(jidp->barejid, message->from_jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, NULL); } } else if (strcmp(pref_omemo_log, "redact") == 0) { if (message->type == PROF_MSG_TYPE_MUCPM) { - _chat_log_chat(jidp->barejid, message->jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, message->jid->resourcepart); + _chat_log_chat(jidp->barejid, message->from_jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, message->from_jid->resourcepart); } else { - _chat_log_chat(jidp->barejid, message->jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, message->jid->resourcepart); + _chat_log_chat(jidp->barejid, message->from_jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, message->from_jid->resourcepart); } } prefs_free_string(pref_omemo_log); @@ -431,9 +431,9 @@ chat_log_msg_in(ProfMessage *message) Jid *jidp = jid_create(jid); if (message->type == PROF_MSG_TYPE_MUCPM) { - _chat_log_chat(jidp->barejid, message->jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, message->jid->resourcepart); + _chat_log_chat(jidp->barejid, message->from_jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, message->from_jid->resourcepart); } else { - _chat_log_chat(jidp->barejid, message->jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, NULL); + _chat_log_chat(jidp->barejid, message->from_jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, NULL); } jid_destroy(jidp); } diff --git a/src/plugins/api.c b/src/plugins/api.c index 745e65c3..59d1694a 100644 --- a/src/plugins/api.c +++ b/src/plugins/api.c @@ -475,7 +475,7 @@ void api_incoming_message(const char *const barejid, const char *const resource, const char *const plain) { ProfMessage *message = message_init(); - message->jid = jid_create_from_bare_and_resource(barejid, resource); + message->from_jid = jid_create_from_bare_and_resource(barejid, resource); message->plain = strdup(plain); sv_ev_incoming_message(message); diff --git a/src/ui/chatwin.c b/src/ui/chatwin.c index 656ac2a9..6846eb71 100644 --- a/src/ui/chatwin.c +++ b/src/ui/chatwin.c @@ -251,12 +251,12 @@ chatwin_incoming_msg(ProfChatWin *chatwin, ProfMessage *message, gboolean win_cr assert(chatwin != NULL); char *old_plain = message->plain; - message->plain = plugins_pre_chat_message_display(chatwin->barejid, message->jid->resourcepart, message->plain); + message->plain = plugins_pre_chat_message_display(chatwin->barejid, message->from_jid->resourcepart, message->plain); ProfWin *window = (ProfWin*)chatwin; int num = wins_get_num(window); - char *display_name = roster_get_msg_display_name(chatwin->barejid, message->jid->resourcepart); + char *display_name = roster_get_msg_display_name(chatwin->barejid, message->from_jid->resourcepart); gboolean is_current = wins_is_current(window); gboolean notify = prefs_do_chat_notify(is_current); @@ -304,7 +304,7 @@ chatwin_incoming_msg(ProfChatWin *chatwin, ProfMessage *message, gboolean win_cr free(display_name); - plugins_post_chat_message_display(chatwin->barejid, message->jid->resourcepart, message->plain); + plugins_post_chat_message_display(chatwin->barejid, message->from_jid->resourcepart, message->plain); free(message->plain); message->plain = old_plain; diff --git a/src/ui/mucwin.c b/src/ui/mucwin.c index a47b82f1..7674d636 100644 --- a/src/ui/mucwin.c +++ b/src/ui/mucwin.c @@ -366,7 +366,7 @@ mucwin_history(ProfMucWin *mucwin, const ProfMessage *const message) assert(mucwin != NULL); ProfWin *window = (ProfWin*)mucwin; - char *nick = message->jid->resourcepart; + char *nick = message->from_jid->resourcepart; // 'unanimous' all in one color (like always was) // 'regular' colored like new messages too @@ -570,9 +570,9 @@ mucwin_incoming_msg(ProfMucWin *mucwin, const ProfMessage *const message, GSList win_insert_last_read_position_marker((ProfWin*)mucwin, mucwin->roomjid); if (g_slist_length(mentions) > 0) { - _mucwin_print_mention(window, message->plain, message->jid->resourcepart, mynick, mentions, ch, flags); + _mucwin_print_mention(window, message->plain, message->from_jid->resourcepart, mynick, mentions, ch, flags); } else if (triggers) { - win_print_them(window, THEME_ROOMTRIGGER, ch, flags, message->jid->resourcepart); + win_print_them(window, THEME_ROOMTRIGGER, ch, flags, message->from_jid->resourcepart); _mucwin_print_triggers(window, message->plain, triggers); } else { win_println_incoming_muc_msg(window, ch, flags, message); diff --git a/src/ui/window.c b/src/ui/window.c index a44e2e4c..8bfc216e 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -1150,16 +1150,16 @@ win_print_incoming(ProfWin *window, const char *const display_name_from, ProfMes } if (prefs_get_boolean(PREF_CORRECTION_ALLOW) && message->replace_id) { - _win_correct(window, message->plain, message->id, message->replace_id, message->jid->barejid); + _win_correct(window, message->plain, message->id, message->replace_id, message->from_jid->barejid); } else { - _win_printf(window, enc_char, 0, message->timestamp, flags, THEME_TEXT_THEM, display_name_from, message->jid->barejid, message->id, "%s", message->plain); + _win_printf(window, enc_char, 0, message->timestamp, flags, THEME_TEXT_THEM, display_name_from, message->from_jid->barejid, message->id, "%s", message->plain); } free(enc_char); break; } case WIN_PRIVATE: - _win_printf(window, "-", 0, message->timestamp, flags, THEME_TEXT_THEM, display_name_from, message->jid->barejid, message->id, "%s", message->plain); + _win_printf(window, "-", 0, message->timestamp, flags, THEME_TEXT_THEM, display_name_from, message->from_jid->barejid, message->id, "%s", message->plain); break; default: assert(FALSE); @@ -1177,9 +1177,9 @@ void win_println_incoming_muc_msg(ProfWin *window, char *show_char, int flags, const ProfMessage *const message) { if (prefs_get_boolean(PREF_CORRECTION_ALLOW) && message->replace_id) { - _win_correct(window, message->plain, message->id, message->replace_id, message->jid->fulljid); + _win_correct(window, message->plain, message->id, message->replace_id, message->from_jid->fulljid); } else { - _win_printf(window, show_char, 0, message->timestamp, flags | NO_ME, THEME_TEXT_THEM, message->jid->resourcepart, message->jid->fulljid, message->id, "%s", message->plain); + _win_printf(window, show_char, 0, message->timestamp, flags | NO_ME, THEME_TEXT_THEM, message->from_jid->resourcepart, message->from_jid->fulljid, message->id, "%s", message->plain); } inp_nonblocking(TRUE); @@ -1226,7 +1226,7 @@ win_print_history(ProfWin *window, const ProfMessage *const message) char *display_name; if (message->type == PROF_MSG_TYPE_MUC) { - display_name = strdup(message->jid->resourcepart); + display_name = strdup(message->from_jid->resourcepart); char *muc_history_color = prefs_get_string(PREF_HISTORY_COLOR_MUC); if (g_strcmp0(muc_history_color, "unanimous") == 0) { @@ -1237,10 +1237,10 @@ win_print_history(ProfWin *window, const ProfMessage *const message) const char *jid = connection_get_fulljid(); Jid *jidp = jid_create(jid); - if (g_strcmp0(jidp->barejid, message->jid->barejid) == 0) { + if (g_strcmp0(jidp->barejid, message->from_jid->barejid) == 0) { display_name = strdup("me"); } else { - display_name = roster_get_msg_display_name(message->jid->barejid, message->jid->resourcepart); + display_name = roster_get_msg_display_name(message->from_jid->barejid, message->from_jid->resourcepart); } jid_destroy(jidp); } diff --git a/src/xmpp/message.c b/src/xmpp/message.c index 73ae8549..59970012 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -200,7 +200,8 @@ message_init(void) { ProfMessage *message = malloc(sizeof(ProfMessage)); - message->jid = NULL; + message->from_jid = NULL; + message->to_jid = NULL; message->id = NULL; message->originid = NULL; message->replace_id = NULL; @@ -219,8 +220,12 @@ void message_free(ProfMessage *message) { xmpp_ctx_t *ctx = connection_get_ctx(); - if (message->jid) { - jid_destroy(message->jid); + if (message->from_jid) { + jid_destroy(message->from_jid); + } + + if (message->to_jid) { + jid_destroy(message->to_jid); } if (message->id) { @@ -801,51 +806,51 @@ _handle_groupchat(xmpp_stanza_t *const stanza) } const char *room_jid = xmpp_stanza_get_from(stanza); - Jid *jid = jid_create(room_jid); + Jid *from_jid = jid_create(room_jid); // handle room subject xmpp_stanza_t *subject = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_SUBJECT); if (subject) { char *subject_text; subject_text = xmpp_stanza_get_text(subject); - sv_ev_room_subject(jid->barejid, jid->resourcepart, subject_text); + sv_ev_room_subject(from_jid->barejid, from_jid->resourcepart, subject_text); xmpp_free(ctx, subject_text); - jid_destroy(jid); + jid_destroy(from_jid); return; } // handle room broadcasts - if (!jid->resourcepart) { + if (!from_jid->resourcepart) { char *broadcast; broadcast = xmpp_message_get_body(stanza); if (!broadcast) { - jid_destroy(jid); + jid_destroy(from_jid); return; } sv_ev_room_broadcast(room_jid, broadcast); xmpp_free(ctx, broadcast); - jid_destroy(jid); + jid_destroy(from_jid); return; } - if (!jid_is_valid_room_form(jid)) { - log_error("Invalid room JID: %s", jid->str); - jid_destroy(jid); + if (!jid_is_valid_room_form(from_jid)) { + log_error("Invalid room JID: %s", from_jid->str); + jid_destroy(from_jid); return; } // room not active in profanity - if (!muc_active(jid->barejid)) { - log_error("Message received for inactive chat room: %s", jid->str); - jid_destroy(jid); + if (!muc_active(from_jid->barejid)) { + log_error("Message received for inactive chat room: %s", from_jid->str); + jid_destroy(from_jid); return; } ProfMessage *message = message_init(); - message->jid = jid; + message->from_jid = from_jid; message->type = PROF_MSG_TYPE_MUC; if (id) { @@ -875,17 +880,17 @@ _handle_groupchat(xmpp_stanza_t *const stanza) #endif if (!message->plain && !message->body) { - log_error("Message received without body for room: %s", jid->str); + log_error("Message received without body for room: %s", from_jid->str); goto out; } else if (!message->plain) { message->plain = strdup(message->body); } // determine if the notifications happened whilst offline (MUC history) - message->timestamp = stanza_get_delay_from(stanza, jid->barejid); + message->timestamp = stanza_get_delay_from(stanza, from_jid->barejid); if (message->timestamp == NULL) { // checking the domainpart is a workaround for some prosody versions (gh#1190) - message->timestamp = stanza_get_delay_from(stanza, jid->domainpart); + message->timestamp = stanza_get_delay_from(stanza, from_jid->domainpart); } bool is_muc_history = FALSE; @@ -996,7 +1001,7 @@ _handle_muc_private_message(xmpp_stanza_t *const stanza) message->type = PROF_MSG_TYPE_MUCPM; const gchar *from = xmpp_stanza_get_from(stanza); - message->jid = jid_create(from); + message->from_jid = jid_create(from); // message stanza id const char *id = xmpp_stanza_get_id(stanza); @@ -1016,7 +1021,7 @@ _handle_muc_private_message(xmpp_stanza_t *const stanza) message->body = xmpp_message_get_body(stanza); if (!message->plain && !message->body) { - log_error("Message received without body from: %s", message->jid->str); + log_error("Message received without body from: %s", message->from_jid->str); goto out; } else if (!message->plain) { message->plain = strdup(message->body); @@ -1133,17 +1138,18 @@ _handle_carbons(xmpp_stanza_t *const stanza) message->encrypted = xmpp_stanza_get_text(x); } + //TODO: now that profmessage has from_jid AND to_jid we should save both. and maybe also add is_carbon so we can decide later on. if (message->plain || message->encrypted || message->body) { // if we are the recipient, treat as standard incoming message if (g_strcmp0(my_jid->barejid, jid_to->barejid) == 0) { jid_destroy(jid_to); - message->jid = jid_from; + message->from_jid = jid_from; sv_ev_incoming_carbon(message); // else treat as a sent message } else { jid_destroy(jid_from); - message->jid = jid_to; + message->from_jid = jid_to; sv_ev_outgoing_carbon(message); } } @@ -1200,7 +1206,9 @@ _handle_chat(xmpp_stanza_t *const stanza) // standard chat message, use jid without resource ProfMessage *message = message_init(); - message->jid = jid; + // TODO: safe to_jid too. also need to have the same check like in carbons. in case this is MAM. + // or have a is_mam and handle later. + message->from_jid = jid; message->type = PROF_MSG_TYPE_CHAT; // message stanza id diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index 7544189b..3f384fb7 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -137,7 +137,8 @@ typedef enum { } prof_msg_type_t; typedef struct prof_message_t { - Jid *jid; + Jid *from_jid; + Jid *to_jid; /* regular */ char *id; /* XEP-0359 */ From dd566d8d561099bbfc81b2fab22318bbad0cf3da Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Sat, 11 Apr 2020 23:56:01 +0200 Subject: [PATCH 07/11] MAM: Correctly display incoming MAM chat message --- src/event/server_events.c | 24 +++++++++++++++++++----- src/ui/chatwin.c | 13 ++++++++++--- src/xmpp/message.c | 19 ++++++++++++------- src/xmpp/xmpp.h | 1 + 4 files changed, 42 insertions(+), 15 deletions(-) diff --git a/src/event/server_events.c b/src/event/server_events.c index 11b5d877..057af9bf 100644 --- a/src/event/server_events.c +++ b/src/event/server_events.c @@ -622,16 +622,30 @@ void sv_ev_incoming_message(ProfMessage *message) { gboolean new_win = FALSE; - ProfChatWin *chatwin = wins_get_chat(message->from_jid->barejid); + ProfChatWin *chatwin; + char *looking_for_jid = message->from_jid->barejid; + + if (message->is_mam) { + Jid *my_jid = jid_create(connection_get_fulljid()); + if (g_strcmp0(my_jid->barejid, message->from_jid->barejid) == 0) { + looking_for_jid = message->to_jid->barejid; + } + jid_destroy(my_jid); + } + + chatwin = wins_get_chat(looking_for_jid); + if (!chatwin) { - ProfWin *window = wins_new_chat(message->from_jid->barejid); + ProfWin *window = wins_new_chat(looking_for_jid); chatwin = (ProfChatWin*)window; new_win = TRUE; #ifdef HAVE_OMEMO - if (omemo_automatic_start(message->from_jid->barejid)) { - omemo_start_session(message->from_jid->barejid); - chatwin->is_omemo = TRUE; + if (!message->is_mam) { + if (omemo_automatic_start(message->from_jid->barejid)) { + omemo_start_session(message->from_jid->barejid); + chatwin->is_omemo = TRUE; + } } #endif } diff --git a/src/ui/chatwin.c b/src/ui/chatwin.c index 6846eb71..1c04432c 100644 --- a/src/ui/chatwin.c +++ b/src/ui/chatwin.c @@ -251,12 +251,19 @@ chatwin_incoming_msg(ProfChatWin *chatwin, ProfMessage *message, gboolean win_cr assert(chatwin != NULL); char *old_plain = message->plain; - message->plain = plugins_pre_chat_message_display(chatwin->barejid, message->from_jid->resourcepart, message->plain); + message->plain = plugins_pre_chat_message_display(message->from_jid->barejid, message->from_jid->resourcepart, message->plain); ProfWin *window = (ProfWin*)chatwin; int num = wins_get_num(window); - char *display_name = roster_get_msg_display_name(chatwin->barejid, message->from_jid->resourcepart); + char *display_name; + Jid *my_jid = jid_create(connection_get_fulljid()); + if (g_strcmp0(my_jid->barejid, message->from_jid->barejid) == 0) { + display_name = strdup("me"); + } else { + display_name = roster_get_msg_display_name(message->from_jid->barejid, message->from_jid->resourcepart); + } + jid_destroy(my_jid); gboolean is_current = wins_is_current(window); gboolean notify = prefs_do_chat_notify(is_current); @@ -304,7 +311,7 @@ chatwin_incoming_msg(ProfChatWin *chatwin, ProfMessage *message, gboolean win_cr free(display_name); - plugins_post_chat_message_display(chatwin->barejid, message->from_jid->resourcepart, message->plain); + plugins_post_chat_message_display(message->from_jid->barejid, message->from_jid->resourcepart, message->plain); free(message->plain); message->plain = old_plain; diff --git a/src/xmpp/message.c b/src/xmpp/message.c index 59970012..d8d12a74 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -84,7 +84,7 @@ static void _handle_muc_private_message(xmpp_stanza_t *const stanza); static void _handle_conference(xmpp_stanza_t *const stanza); static void _handle_captcha(xmpp_stanza_t *const stanza); static void _handle_receipt_received(xmpp_stanza_t *const stanza); -static void _handle_chat(xmpp_stanza_t *const stanza); +static void _handle_chat(xmpp_stanza_t *const stanza, gboolean is_mam); static gboolean _handle_mam(xmpp_stanza_t *const stanza); static void _send_message_stanza(xmpp_stanza_t *const stanza); @@ -166,7 +166,7 @@ _message_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *con } } - _handle_chat(stanza); + _handle_chat(stanza, FALSE); return 1; } @@ -1161,7 +1161,7 @@ out: } static void -_handle_chat(xmpp_stanza_t *const stanza) +_handle_chat(xmpp_stanza_t *const stanza, gboolean is_mam) { // ignore if type not chat or absent const char *type = xmpp_stanza_get_type(stanza); @@ -1206,10 +1206,15 @@ _handle_chat(xmpp_stanza_t *const stanza) // standard chat message, use jid without resource ProfMessage *message = message_init(); - // TODO: safe to_jid too. also need to have the same check like in carbons. in case this is MAM. - // or have a is_mam and handle later. - message->from_jid = jid; message->type = PROF_MSG_TYPE_CHAT; + message->from_jid = jid; + + const gchar *to_text = xmpp_stanza_get_to(stanza); + if (to_text) { + message->to_jid = jid_create(to_text); + } + + message->is_mam = is_mam; // message stanza id const char *id = xmpp_stanza_get_id(stanza); @@ -1296,7 +1301,7 @@ _handle_mam(xmpp_stanza_t *const stanza) } xmpp_stanza_t *message_stanza = xmpp_stanza_get_child_by_ns(forwarded, "jabber:client"); - _handle_chat(message_stanza); + _handle_chat(message_stanza, TRUE); return TRUE; } diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index 3f384fb7..cb0004e3 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -155,6 +155,7 @@ typedef struct prof_message_t { GDateTime *timestamp; prof_enc_t enc; gboolean trusted; + gboolean is_mam; prof_msg_type_t type; } ProfMessage; From aedecee962ab3bf72402bde5783cf953d6e24fd0 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Sun, 12 Apr 2020 00:06:36 +0200 Subject: [PATCH 08/11] Get MAM since yesterday Later we will have several options. Getting everything since last timestamp (if none everything at all). Getting everything since today + configure time (1 week). Should also have a reload all command like conversations once you cleared the history. All MAM messages should be written into sql db. And then probably displayed from there so that regular history works too. --- src/xmpp/iq.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index b36ca229..e6d34d9d 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -2508,7 +2508,13 @@ iq_mam_request(ProfChatWin *win) xmpp_ctx_t * const ctx = connection_get_ctx(); char *id = connection_create_stanza_id(); - xmpp_stanza_t *iq = stanza_create_mam_iq(ctx, win->barejid, "2020-01-06T00:00:00Z"); + + GDateTime *timestamp = g_date_time_new_now_local(); + timestamp = g_date_time_add_days(timestamp, -1); + gchar *datestr = g_date_time_format(timestamp,"%FT%T%:::z"); + xmpp_stanza_t *iq = stanza_create_mam_iq(ctx, win->barejid, datestr); + g_free(datestr); + g_date_time_unref(timestamp); // iq_id_handler_add(id, _http_upload_response_id_handler, NULL, upload); free(id); From 98200ebd43e90d8662fee5e014bbe3dc1709a6d7 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Sun, 12 Apr 2020 00:24:00 +0200 Subject: [PATCH 09/11] Check if server suppors MAM --- src/xmpp/iq.c | 7 +++++-- src/xmpp/xmpp.h | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index e6d34d9d..8152ec01 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -2503,8 +2503,11 @@ _iq_free_affiliation_list(ProfAffiliationList *affiliation_list) void iq_mam_request(ProfChatWin *win) { - //TODDO: check for mam feature - //if (connection_supports(XMPP_FEATURE_PING) == FALSE) { + if (connection_supports(XMPP_FEATURE_MAM2) == FALSE) { + log_warning("Server doesn't advertise %s feature.", XMPP_FEATURE_PING); + cons_show_error("Server doesn't support MAM."); + return; + } xmpp_ctx_t * const ctx = connection_get_ctx(); char *id = connection_create_stanza_id(); diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index cb0004e3..fa26cfbf 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -69,6 +69,7 @@ #define XMPP_FEATURE_PUBSUB_PUBLISH_OPTIONS "http://jabber.org/protocol/pubsub#publish-options" #define XMPP_FEATURE_USER_AVATAR_METADATA_NOTIFY "urn:xmpp:avatar:metadata+notify" #define XMPP_FEATURE_LAST_MESSAGE_CORRECTION "urn:xmpp:message-correct:0" +#define XMPP_FEATURE_MAM2 "urn:xmpp:mam:2" typedef enum { JABBER_CONNECTING, From 51518497e5bb11aa795ef2267512786eb16467df Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Sun, 12 Apr 2020 00:37:20 +0200 Subject: [PATCH 10/11] Add hidden MAM setting and trigger MAM retrievel when opening new window Only when we start the conversation. Not yet when we get messaged and a new window is opened. Need to have sorting of messages in the window buffer then, I guess. Also MAM IQ should only be send one time in such a case. If MAM is enabled history from sql backend will not be shown. `mam` in profrc enables experimental MAM. Can change soon again. Don't rely on stuff in this stage ;) --- src/config/preferences.c | 3 +++ src/config/preferences.h | 1 + src/ui/chatwin.c | 21 +++++++++++++-------- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/config/preferences.c b/src/config/preferences.c index ba3b08e9..0ec5a0c0 100644 --- a/src/config/preferences.c +++ b/src/config/preferences.c @@ -1799,6 +1799,7 @@ _get_group(preference_t pref) case PREF_REVEAL_OS: case PREF_TLS_CERTPATH: case PREF_CORRECTION_ALLOW: + case PREF_MAM: return PREF_GROUP_CONNECTION; case PREF_OTR_LOG: case PREF_OTR_POLICY: @@ -2070,6 +2071,8 @@ _get_key(preference_t pref) return "avatar.cmd"; case PREF_SLASH_GUARD: return "slashguard"; + case PREF_MAM: + return "mam"; default: return NULL; } diff --git a/src/config/preferences.h b/src/config/preferences.h index ffc93a52..f3c32ebd 100644 --- a/src/config/preferences.h +++ b/src/config/preferences.h @@ -170,6 +170,7 @@ typedef enum { PREF_HISTORY_COLOR_MUC, PREF_AVATAR_CMD, PREF_SLASH_GUARD, + PREF_MAM, } preference_t; typedef struct prof_alias_t { diff --git a/src/ui/chatwin.c b/src/ui/chatwin.c index 1c04432c..22992ecd 100644 --- a/src/ui/chatwin.c +++ b/src/ui/chatwin.c @@ -57,7 +57,7 @@ #include "omemo/omemo.h" #endif -/*static void _chatwin_history(ProfChatWin *chatwin, const char *const contact_barejid);*/ +static void _chatwin_history(ProfChatWin *chatwin, const char *const contact_barejid); static void _chatwin_set_last_message(ProfChatWin *chatwin, const char *const id, const char *const message); ProfChatWin* @@ -66,8 +66,8 @@ chatwin_new(const char *const barejid) ProfWin *window = wins_new_chat(barejid); ProfChatWin *chatwin = (ProfChatWin *)window; - if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) { - //_chatwin_history(chatwin, barejid); + if (!prefs_get_boolean(PREF_MAM) && prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) { + _chatwin_history(chatwin, barejid); } // if the contact is offline, show a message @@ -87,7 +87,9 @@ chatwin_new(const char *const barejid) } #endif - iq_mam_request(chatwin); + if (prefs_get_boolean(PREF_MAM)) { + iq_mam_request(chatwin); + } return chatwin; } @@ -285,8 +287,13 @@ chatwin_incoming_msg(ProfChatWin *chatwin, ProfMessage *message, gboolean win_cr chatwin->unread++; - if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) { -// _chatwin_history(chatwin, chatwin->barejid); + //TODO: so far we don't ask for MAM when incoming message occurs. + //Need to figure out: + //1) only send IQ once + //2) sort incoming messages on timestamp + //for now if experimental MAM is enabled we dont show no history from sql either + if (!prefs_get_boolean(PREF_MAM) && prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) { + _chatwin_history(chatwin, chatwin->barejid); } // show users status first, when receiving message via delayed delivery @@ -485,7 +492,6 @@ chatwin_unset_outgoing_char(ProfChatWin *chatwin) } } -/* static void _chatwin_history(ProfChatWin *chatwin, const char *const contact_barejid) { @@ -503,7 +509,6 @@ _chatwin_history(ProfChatWin *chatwin, const char *const contact_barejid) g_slist_free_full(history, (GDestroyNotify)message_free); } } -*/ static void _chatwin_set_last_message(ProfChatWin *chatwin, const char *const id, const char *const message) From 18c64c05806646033199a11ee9bb38aebda723d5 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Mon, 13 Apr 2020 10:04:37 +0200 Subject: [PATCH 11/11] Free timestamp correctly g_date_time_add_days() actually creates a new one. --- src/xmpp/iq.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index 8152ec01..2bcf9bba 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -2512,8 +2512,9 @@ iq_mam_request(ProfChatWin *win) xmpp_ctx_t * const ctx = connection_get_ctx(); char *id = connection_create_stanza_id(); - GDateTime *timestamp = g_date_time_new_now_local(); - timestamp = g_date_time_add_days(timestamp, -1); + GDateTime *now = g_date_time_new_now_local(); + GDateTime *timestamp = g_date_time_add_days(now, -1); + g_date_time_unref(now); gchar *datestr = g_date_time_format(timestamp,"%FT%T%:::z"); xmpp_stanza_t *iq = stanza_create_mam_iq(ctx, win->barejid, datestr); g_free(datestr);