diff options
author | Michael Vetter <jubalh@iodoru.org> | 2020-04-06 22:25:40 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-06 22:25:40 +0200 |
commit | 6c158a9af86c0211a2e32aaabcb9a374214d53dd (patch) | |
tree | 65a57e346b56424b57ebd3e22a0ec102d3939e21 /src | |
parent | 49057077b9396a16c600ddd61357a1816a94e791 (diff) | |
parent | 6218a537276ca9c5e6ca3f6956759421c9425c23 (diff) | |
download | profani-tty-6c158a9af86c0211a2e32aaabcb9a374214d53dd.tar.gz |
Merge pull request #1282 from profanity-im/feature/sqlite-log
SQLite backend
Diffstat (limited to 'src')
-rw-r--r-- | src/config/files.c | 1 | ||||
-rw-r--r-- | src/config/files.h | 1 | ||||
-rw-r--r-- | src/database.c | 325 | ||||
-rw-r--r-- | src/database.h | 52 | ||||
-rw-r--r-- | src/event/client_events.c | 44 | ||||
-rw-r--r-- | src/event/common.c | 2 | ||||
-rw-r--r-- | src/event/server_events.c | 30 | ||||
-rw-r--r-- | src/log.c | 64 | ||||
-rw-r--r-- | src/log.h | 1 | ||||
-rw-r--r-- | src/otr/otr.c | 4 | ||||
-rw-r--r-- | src/ui/chatwin.c | 31 | ||||
-rw-r--r-- | src/ui/mucwin.c | 17 | ||||
-rw-r--r-- | src/ui/window.c | 36 | ||||
-rw-r--r-- | src/ui/window.h | 2 | ||||
-rw-r--r-- | src/xmpp/message.c | 26 | ||||
-rw-r--r-- | src/xmpp/xmpp.h | 18 |
16 files changed, 518 insertions, 136 deletions
diff --git a/src/config/files.c b/src/config/files.c index 133a270e..bdaf6a93 100644 --- a/src/config/files.c +++ b/src/config/files.c @@ -3,6 +3,7 @@ * vim: expandtab:ts=4:sts=4:sw=4 * * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> + * Copyright (C) 2020 Michael Vetter <jubalh@idoru.org> * * This file is part of Profanity. * diff --git a/src/config/files.h b/src/config/files.h index 12c3f03a..1e16802a 100644 --- a/src/config/files.h +++ b/src/config/files.h @@ -55,6 +55,7 @@ #define DIR_PGP "pgp" #define DIR_OMEMO "omemo" #define DIR_PLUGINS "plugins" +#define DIR_DATABASE "database" void files_create_directories(void); diff --git a/src/database.c b/src/database.c new file mode 100644 index 00000000..714c4b1a --- /dev/null +++ b/src/database.c @@ -0,0 +1,325 @@ +/* + * database.c + * vim: expandtab:ts=4:sts=4:sw=4 + * + * Copyright (C) 2020 Michael Vetter <jubalh@idoru.org> + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see <https://www.gnu.org/licenses/>. + * + * In addition, as a special exception, the copyright holders give permission to + * link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. + * + * You must obey the GNU General Public License in all respects for all of the + * code used other than OpenSSL. If you modify file(s) with this exception, you + * may extend this exception to your version of the file(s), but you are not + * obligated to do so. If you do not wish to do so, delete this exception + * statement from your version. If you delete this exception statement from all + * source files in the program, then also delete it here. + * + */ + +#define _GNU_SOURCE 1 + +#include <sys/stat.h> +#include <sqlite3.h> +#include <stdio.h> +#include <errno.h> + +#include "log.h" +#include "config/files.h" + +static sqlite3 *g_chatlog_database; + +static void _add_to_db(ProfMessage *message, char *type, const Jid * const from_jid, const Jid * const to_jid); +static char* _get_db_filename(ProfAccount *account); + +static char* +_get_db_filename(ProfAccount *account) +{ + char *databasedir = files_get_data_path(DIR_DATABASE); + GString *basedir = g_string_new(databasedir); + free(databasedir); + + g_string_append(basedir, "/"); + + gchar *account_dir = str_replace(account->jid, "@", "_at_"); + g_string_append(basedir, account_dir); + free(account_dir); + + int res = g_mkdir_with_parents(basedir->str, S_IRWXU); + if (res == -1) { + char *errmsg = strerror(errno); + if (errmsg) { + log_error("DATABASE: error creating directory: %s, %s", basedir->str, errmsg); + } else { + log_error("DATABASE: creating directory: %s", basedir->str); + } + g_string_free(basedir, TRUE); + return NULL; + } + + g_string_append(basedir, "/chatlog.db"); + char *result = strdup(basedir->str); + g_string_free(basedir, TRUE); + + return result; +} + +gboolean +log_database_init(ProfAccount *account) +{ + int ret = sqlite3_initialize(); + if (ret != SQLITE_OK) { + log_error("Error initializing SQLite database: %d", ret); + return FALSE; + } + + char *filename = _get_db_filename(account); + if (!filename) { + return FALSE; + } + + ret = sqlite3_open(filename, &g_chatlog_database); + if (ret != SQLITE_OK) { + const char *err_msg = sqlite3_errmsg(g_chatlog_database); + log_error("Error opening SQLite database: %s", err_msg); + free(filename); + return FALSE; + } + + char *err_msg; + // id is the ID of DB the entry + // from_jid is the senders jid + // to_jid is the receivers jid + // from_resource is the senders resource + // to_jid is the receivers resource + // message is the message text + // timestamp the timestamp like "2020/03/24 11:12:14" + // type is there to distinguish: message (chat), MUC message (muc), muc pm (mucpm) + // stanza_id is the ID from XEP-0359: Unique and Stable Stanza IDs + // archive_id is the ID from XEP-0313: Message Archive Management + // replace_id is the ID from XEP-0308: Last Message Correction + // encryption is to distinguish: none, omemo, otr, pgp + // marked_read is 0/1 whether a message has been marked as read via XEP-0333: Chat Markers + char *query = "CREATE TABLE IF NOT EXISTS `ChatLogs` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `from_jid` TEXT NOT NULL, `to_jid` TEXT NOT NULL, `from_resource` TEXT, `to_resource` TEXT, `message` TEXT, `timestamp` TEXT, `type` TEXT, `stanza_id` TEXT, `archive_id` TEXT, `replace_id` TEXT, `encryption` TEXT, `marked_read` INTEGER)"; + if( SQLITE_OK != sqlite3_exec(g_chatlog_database, query, NULL, 0, &err_msg)) { + goto out; + } + + query = "CREATE TABLE IF NOT EXISTS `DbVersion` ( `dv_id` INTEGER PRIMARY KEY, `version` INTEGER UNIQUE)"; + if( SQLITE_OK != sqlite3_exec(g_chatlog_database, query, NULL, 0, &err_msg)) { + goto out; + } + + query = "INSERT OR IGNORE INTO `DbVersion` (`version`) VALUES('1')"; + if( SQLITE_OK != sqlite3_exec(g_chatlog_database, query, NULL, 0, &err_msg)) { + goto out; + } + + log_debug("Initialized SQLite database: %s", filename); + free(filename); + return TRUE; + +out: + if (err_msg) { + log_error("SQLite error: %s", err_msg); + sqlite3_free(err_msg); + } else { + log_error("Unknown SQLite error"); + } + free(filename); + return FALSE; +} + +void +log_database_close(void) +{ + if (g_chatlog_database) { + sqlite3_close(g_chatlog_database); + sqlite3_shutdown(); + g_chatlog_database = NULL; + } +} + +void +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); + + jid_destroy(myjid); +} + +static void +_log_database_add_outgoing(char *type, const char * const id, const char * const barejid, const char * const message, const char *const replace_id, prof_enc_t enc) +{ + ProfMessage *msg = message_init(); + + msg->id = id ? strdup(id) : NULL; + msg->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 + msg->enc = enc; + + const char *jid = connection_get_fulljid(); + Jid *myjid = jid_create(jid); + + _add_to_db(msg, type, myjid, msg->jid); + + jid_destroy(myjid); + message_free(msg); +} + +void +log_database_add_outgoing_chat(const char * const id, const char * const barejid, const char * const message, const char *const replace_id, prof_enc_t enc) +{ + _log_database_add_outgoing("chat", id, barejid, message, replace_id, enc); +} + +void +log_database_add_outgoing_muc(const char * const id, const char * const barejid, const char * const message, const char *const replace_id, prof_enc_t enc) +{ + _log_database_add_outgoing("muc", id, barejid, message, replace_id, enc); +} + +void +log_database_add_outgoing_muc_pm(const char * const id, const char * const barejid, const char * const message, const char *const replace_id, prof_enc_t enc) +{ + _log_database_add_outgoing("mucpm", id, barejid, message, replace_id, enc); +} + +GSList* +log_database_get_previous_chat(const gchar *const contact_barejid) +{ + sqlite3_stmt *stmt = NULL; + char *query; + + if (asprintf(&query, "SELECT * FROM (SELECT `message`, `timestamp`, `from_jid` from `ChatLogs` WHERE `from_jid` = '%s' OR `to_jid` = '%s' ORDER BY `timestamp` DESC LIMIT 10) ORDER BY `timestamp` ASC;", contact_barejid, contact_barejid) == -1) { + log_error("log_database_get_previous_chat(): SQL query. could not allocate memory"); + return NULL; + } + + int rc = sqlite3_prepare_v2(g_chatlog_database, query, -1, &stmt, NULL); + if( rc!=SQLITE_OK ) { + log_error("log_database_get_previous_chat(): unknown SQLite error"); + return NULL; + } + + GSList *history = NULL; + + while( sqlite3_step(stmt) == SQLITE_ROW ) { + char *message = (char*)sqlite3_column_text(stmt, 0); + char *date = (char*)sqlite3_column_text(stmt, 1); + char *from = (char*)sqlite3_column_text(stmt, 2); + + ProfMessage *msg = message_init(); + msg->jid = jid_create(from); + msg->plain = strdup(message); + msg->timestamp = g_date_time_new_from_iso8601(date, NULL); + // TODO: later we can get more fields like 'enc'. then we can display the history like regular chats with all info the user enabled. + + history = g_slist_append(history, msg); + } + sqlite3_finalize(stmt); + free(query); + + return history; +} + +static const char* _get_message_type_str(prof_msg_type_t type) { + switch (type) { + case PROF_MSG_TYPE_CHAT: + return "chat"; + case PROF_MSG_TYPE_MUC: + return "muc"; + case PROF_MSG_TYPE_MUCPM: + return "mucpm"; + case PROF_MSG_TYPE_UNINITIALIZED: + return NULL; + } + return NULL; +} + +static const char* _get_message_enc_str(prof_enc_t enc) { + switch (enc) { + case PROF_MSG_ENC_PGP: + return "pgp"; + case PROF_MSG_ENC_OTR: + return "otr"; + case PROF_MSG_ENC_OMEMO: + return "omemo"; + case PROF_MSG_ENC_NONE: + return "none"; + } + + return "none"; +} + +static void +_add_to_db(ProfMessage *message, char *type, const Jid * const from_jid, const Jid * const to_jid) +{ + if (!g_chatlog_database) { + log_debug("log_database_add() called but db is not initialized"); + return; + } + + char *err_msg; + char *query; + gchar *date_fmt; + + if (message->timestamp) { + date_fmt = g_date_time_format_iso8601(message->timestamp); + } else { + date_fmt = g_date_time_format_iso8601(g_date_time_new_now_local()); + } + + const char *enc = _get_message_enc_str(message->enc); + + if (!type) { + type = (char*)_get_message_type_str(message->type); + } + + if (asprintf(&query, "INSERT INTO `ChatLogs` (`from_jid`, `from_resource`, `to_jid`, `to_resource`, `message`, `timestamp`, `stanza_id`, `replace_id`, `type`, `encryption`) VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')", + from_jid->barejid, + from_jid->resourcepart ? from_jid->resourcepart : "", + to_jid->barejid, + to_jid->resourcepart ? to_jid->resourcepart : "", + message->plain, + date_fmt, + message->id ? message->id : "", + message->replace_id ? message->replace_id : "", + type, + enc) == -1) { + log_error("log_database_add(): SQL query. could not allocate memory"); + return; + } + g_free(date_fmt); + + if( SQLITE_OK != sqlite3_exec(g_chatlog_database, query, NULL, 0, &err_msg)) { + if (err_msg) { + log_error("SQLite error: %s", err_msg); + sqlite3_free(err_msg); + } else { + log_error("Unknown SQLite error"); + } + } + free(query); +} diff --git a/src/database.h b/src/database.h new file mode 100644 index 00000000..4ad3fc9c --- /dev/null +++ b/src/database.h @@ -0,0 +1,52 @@ +/* + * database.h + * vim: expandtab:ts=4:sts=4:sw=4 + * + * Copyright (C) 2020 Michael Vetter <jubalh@idoru.org> + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see <https://www.gnu.org/licenses/>. + * + * In addition, as a special exception, the copyright holders give permission to + * link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. + * + * You must obey the GNU General Public License in all respects for all of the + * code used other than OpenSSL. If you modify file(s) with this exception, you + * may extend this exception to your version of the file(s), but you are not + * obligated to do so. If you do not wish to do so, delete this exception + * statement from your version. If you delete this exception statement from all + * source files in the program, then also delete it here. + * + */ + +#ifndef DATABASE_H +#define DATABASE_H + +#include <glib.h> +#include "config/account.h" +#include "xmpp/xmpp.h" + +gboolean log_database_init(ProfAccount *account); +void log_database_add_incoming(ProfMessage *message); +void log_database_add_outgoing_chat(const char * const id, const char * const barejid, const char * const message, const char *const replace_id, prof_enc_t enc); +void log_database_add_outgoing_muc(const char * const id, const char * const barejid, const char * const message, const char *const replace_id, prof_enc_t enc); +void log_database_add_outgoing_muc_pm(const char * const id, const char * const barejid, const char * const message, const char *const replace_id, prof_enc_t enc); +GSList* log_database_get_previous_chat(const gchar *const contact_barejid); +void log_database_close(void); + +#endif // DATABASE_H + diff --git a/src/event/client_events.c b/src/event/client_events.c index e0ea85d7..e57f3875 100644 --- a/src/event/client_events.c +++ b/src/event/client_events.c @@ -40,6 +40,7 @@ #include <glib.h> #include "log.h" +#include "database.h" #include "config/preferences.h" #include "event/common.h" #include "plugins/plugins.h" @@ -138,6 +139,7 @@ cl_ev_send_msg_correct(ProfChatWin *chatwin, const char *const msg, const char * if (chatwin->pgp_send) { char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg, request_receipt, replace_id); chat_log_pgp_msg_out(chatwin->barejid, plugin_msg, NULL); + log_database_add_outgoing_chat(id, chatwin->barejid, plugin_msg, replace_id, PROF_MSG_ENC_PGP); chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PGP, request_receipt, replace_id); free(id); } else { @@ -145,7 +147,8 @@ cl_ev_send_msg_correct(ProfChatWin *chatwin, const char *const msg, const char * if (!handled) { char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt, replace_id); chat_log_msg_out(chatwin->barejid, plugin_msg, NULL); - chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt, replace_id); + log_database_add_outgoing_chat(id, chatwin->barejid, plugin_msg, replace_id, PROF_MSG_ENC_NONE); + chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_NONE, request_receipt, replace_id); free(id); } } @@ -165,7 +168,8 @@ cl_ev_send_msg_correct(ProfChatWin *chatwin, const char *const msg, const char * if (!handled) { char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt, replace_id); chat_log_msg_out(chatwin->barejid, plugin_msg, NULL); - chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt); + log_database_add_outgoing_chat(id, chatwin->barejid, plugin_msg, replace_id, PROF_MSG_ENC_NONE); + chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_NONE, request_receipt); free(id); } @@ -183,12 +187,14 @@ cl_ev_send_msg_correct(ProfChatWin *chatwin, const char *const msg, const char * if (chatwin->pgp_send) { char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg, request_receipt, replace_id); chat_log_pgp_msg_out(chatwin->barejid, plugin_msg, NULL); + log_database_add_outgoing_chat(id, chatwin->barejid, plugin_msg, replace_id, PROF_MSG_ENC_PGP); chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PGP, request_receipt, replace_id); free(id); } else { char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt, replace_id); chat_log_msg_out(chatwin->barejid, plugin_msg, NULL); - chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt, replace_id); + log_database_add_outgoing_chat(id, chatwin->barejid, plugin_msg, replace_id, PROF_MSG_ENC_NONE); + chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_NONE, request_receipt, replace_id); free(id); } @@ -206,12 +212,14 @@ cl_ev_send_msg_correct(ProfChatWin *chatwin, const char *const msg, const char * if (chatwin->is_omemo) { char *id = omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE, replace_id); chat_log_omemo_msg_out(chatwin->barejid, plugin_msg, NULL); + log_database_add_outgoing_chat(id, chatwin->barejid, plugin_msg, replace_id, PROF_MSG_ENC_OMEMO); chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_OMEMO, request_receipt, replace_id); free(id); } else { char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt, replace_id); chat_log_msg_out(chatwin->barejid, plugin_msg, NULL); - chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt, replace_id); + log_database_add_outgoing_chat(id, chatwin->barejid, plugin_msg, replace_id, PROF_MSG_ENC_NONE); + chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_NONE, request_receipt, replace_id); free(id); } @@ -229,6 +237,7 @@ cl_ev_send_msg_correct(ProfChatWin *chatwin, const char *const msg, const char * if (chatwin->is_omemo) { char *id = omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE, replace_id); chat_log_omemo_msg_out(chatwin->barejid, plugin_msg, NULL); + log_database_add_outgoing_chat(id, chatwin->barejid, plugin_msg, replace_id, PROF_MSG_ENC_OMEMO); chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_OMEMO, request_receipt, replace_id); free(id); } else { @@ -236,7 +245,8 @@ cl_ev_send_msg_correct(ProfChatWin *chatwin, const char *const msg, const char * if (!handled) { char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt, replace_id); chat_log_msg_out(chatwin->barejid, plugin_msg, NULL); - chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt, replace_id); + log_database_add_outgoing_chat(id, chatwin->barejid, plugin_msg, replace_id, PROF_MSG_ENC_NONE); + chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_NONE, request_receipt, replace_id); free(id); } } @@ -255,17 +265,20 @@ cl_ev_send_msg_correct(ProfChatWin *chatwin, const char *const msg, const char * if (chatwin->is_omemo) { char *id = omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE, replace_id); chat_log_omemo_msg_out(chatwin->barejid, plugin_msg, NULL); + log_database_add_outgoing_chat(id, chatwin->barejid, plugin_msg, replace_id, PROF_MSG_ENC_OMEMO); chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_OMEMO, request_receipt, replace_id); free(id); } else if (chatwin->pgp_send) { char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg, request_receipt, replace_id); chat_log_pgp_msg_out(chatwin->barejid, plugin_msg, NULL); + log_database_add_outgoing_chat(id, chatwin->barejid, plugin_msg, replace_id, PROF_MSG_ENC_PGP); chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PGP, request_receipt, replace_id); free(id); } else { char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt, replace_id); chat_log_msg_out(chatwin->barejid, plugin_msg, NULL); - chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt, replace_id); + log_database_add_outgoing_chat(id, chatwin->barejid, plugin_msg, replace_id, PROF_MSG_ENC_NONE); + chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_NONE, request_receipt, replace_id); free(id); } @@ -283,11 +296,13 @@ cl_ev_send_msg_correct(ProfChatWin *chatwin, const char *const msg, const char * if (chatwin->is_omemo) { char *id = omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE, replace_id); chat_log_omemo_msg_out(chatwin->barejid, plugin_msg, NULL); + log_database_add_outgoing_chat(id, chatwin->barejid, plugin_msg, replace_id, PROF_MSG_ENC_OMEMO); chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_OMEMO, request_receipt, replace_id); free(id); } else if (chatwin->pgp_send) { char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg, request_receipt, replace_id); chat_log_pgp_msg_out(chatwin->barejid, plugin_msg, NULL); + log_database_add_outgoing_chat(id, chatwin->barejid, plugin_msg, replace_id, PROF_MSG_ENC_PGP); chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PGP, request_receipt, replace_id); free(id); } else { @@ -295,7 +310,8 @@ cl_ev_send_msg_correct(ProfChatWin *chatwin, const char *const msg, const char * if (!handled) { char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt, replace_id); chat_log_msg_out(chatwin->barejid, plugin_msg, NULL); - chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt, replace_id); + log_database_add_outgoing_chat(id, chatwin->barejid, plugin_msg, replace_id, PROF_MSG_ENC_NONE); + chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_NONE, request_receipt, replace_id); free(id); } } @@ -313,7 +329,8 @@ cl_ev_send_msg_correct(ProfChatWin *chatwin, const char *const msg, const char * #ifndef HAVE_OMEMO char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt, replace_id); chat_log_msg_out(chatwin->barejid, plugin_msg, NULL); - chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, request_receipt, replace_id); + log_database_add_outgoing_chat(id, chatwin->barejid, plugin_msg, replace_id, PROF_MSG_ENC_NONE); + chatwin_outgoing_msg(chatwin, plugin_msg, id, PROF_MSG_ENC_NONE, request_receipt, replace_id); free(id); plugins_post_chat_message_send(chatwin->barejid, plugin_msg); @@ -347,12 +364,14 @@ cl_ev_send_muc_msg_corrected(ProfMucWin *mucwin, const char *const msg, const ch if (mucwin->is_omemo) { char *id = omemo_on_message_send((ProfWin *)mucwin, plugin_msg, FALSE, TRUE, replace_id); groupchat_log_omemo_msg_out(mucwin->roomjid, plugin_msg); + log_database_add_outgoing_muc(id, mucwin->roomjid, plugin_msg, replace_id, PROF_MSG_ENC_OMEMO); mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_ENC_OMEMO, replace_id); free(id); } else { char *id = message_send_groupchat(mucwin->roomjid, plugin_msg, oob_url, replace_id); groupchat_log_msg_out(mucwin->roomjid, plugin_msg); - mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, replace_id); + log_database_add_outgoing_muc(id, mucwin->roomjid, plugin_msg, replace_id, PROF_MSG_ENC_NONE); + mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_ENC_NONE, replace_id); free(id); } @@ -364,7 +383,8 @@ cl_ev_send_muc_msg_corrected(ProfMucWin *mucwin, const char *const msg, const ch #ifndef HAVE_OMEMO char *id = message_send_groupchat(mucwin->roomjid, plugin_msg, oob_url, replace_id); groupchat_log_msg_out(mucwin->roomjid, plugin_msg); - mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_ENC_PLAIN, replace_id); + log_database_add_outgoing_muc(id, mucwin->roomjid, plugin_msg, replace_id, PROF_MSG_ENC_NONE); + mucwin_outgoing_msg(mucwin, plugin_msg, id, PROF_MSG_ENC_NONE, replace_id); free(id); plugins_post_room_message_send(mucwin->roomjid, plugin_msg); @@ -390,9 +410,11 @@ cl_ev_send_priv_msg(ProfPrivateWin *privwin, const char *const msg, const char * char *plugin_msg = plugins_pre_priv_message_send(privwin->fulljid, msg); Jid *jidp = jid_create(privwin->fulljid); - message_send_private(privwin->fulljid, plugin_msg, oob_url); + char *id = message_send_private(privwin->fulljid, plugin_msg, oob_url); chat_log_msg_out(jidp->barejid, plugin_msg, jidp->resourcepart); + log_database_add_outgoing_muc_pm(id, privwin->fulljid, plugin_msg, NULL, PROF_MSG_ENC_NONE); privwin_outgoing_msg(privwin, plugin_msg); + free(id); plugins_post_priv_message_send(privwin->fulljid, plugin_msg); diff --git a/src/event/common.c b/src/event/common.c index 05c3f30b..2d829e5c 100644 --- a/src/event/common.c +++ b/src/event/common.c @@ -39,6 +39,7 @@ #include "xmpp/roster_list.h" #include "xmpp/muc.h" #include "xmpp/xmpp.h" +#include "database.h" #ifdef HAVE_LIBGPGME #include "pgp/gpg.h" @@ -67,6 +68,7 @@ ev_disconnect_cleanup(void) #ifdef HAVE_OMEMO omemo_on_disconnect(); #endif + log_database_close(); } gboolean diff --git a/src/event/server_events.c b/src/event/server_events.c index ea4277b2..b63af3b6 100644 --- a/src/event/server_events.c +++ b/src/event/server_events.c @@ -42,6 +42,7 @@ #include "profanity.h" #include "log.h" +#include "database.h" #include "config/preferences.h" #include "config/tlscerts.h" #include "config/account.h" @@ -91,6 +92,8 @@ sv_ev_login_account_success(char *account_name, gboolean secured) omemo_on_connect(account); #endif + log_database_init(account); + avatar_pep_subscribe(); ui_handle_login_account_success(account, secured); @@ -298,6 +301,7 @@ static void _log_muc(ProfMessage *message) } else { groupchat_log_msg_in(message->jid->barejid, message->jid->resourcepart, message->plain); } + log_database_add_incoming(message); } void @@ -397,6 +401,7 @@ sv_ev_incoming_private_message(ProfMessage *message) } _clean_incoming_message(message); + log_database_add_incoming(message); privwin_incoming_msg(privatewin, message); chat_log_msg_in(message); @@ -440,7 +445,7 @@ sv_ev_outgoing_carbon(ProfMessage *message) chat_state_active(chatwin->state); if (message->plain) { - if (message->mucuser) { + 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); } else { @@ -460,12 +465,12 @@ sv_ev_outgoing_carbon(ProfMessage *message) log_error("Couldn't decrypt GPG message and body was empty"); return; } - message->enc = PROF_MSG_ENC_PLAIN; + message->enc = PROF_MSG_ENC_NONE; message->plain = strdup(message->body); chatwin_outgoing_carbon(chatwin, message); } } else { - message->enc = PROF_MSG_ENC_PLAIN; + message->enc = PROF_MSG_ENC_NONE; message->plain = strdup(message->body); chatwin_outgoing_carbon(chatwin, message); } @@ -478,7 +483,7 @@ sv_ev_outgoing_carbon(ProfMessage *message) if (message->enc == PROF_MSG_ENC_OMEMO) { chatwin_outgoing_carbon(chatwin, message); } else { - message->enc = PROF_MSG_ENC_PLAIN; + message->enc = PROF_MSG_ENC_NONE; message->plain = strdup(message->body); chatwin_outgoing_carbon(chatwin, message); } @@ -500,12 +505,12 @@ sv_ev_outgoing_carbon(ProfMessage *message) log_error("Couldn't decrypt GPG message and body was empty"); return; } - message->enc = PROF_MSG_ENC_PLAIN; + message->enc = PROF_MSG_ENC_NONE; message->plain = strdup(message->body); chatwin_outgoing_carbon(chatwin, message); } } else { - message->enc = PROF_MSG_ENC_PLAIN; + message->enc = PROF_MSG_ENC_NONE; message->plain = strdup(message->body); chatwin_outgoing_carbon(chatwin, message); } @@ -516,7 +521,7 @@ sv_ev_outgoing_carbon(ProfMessage *message) #ifndef HAVE_LIBGPGME #ifndef HAVE_OMEMO if (message->body) { - message->enc = PROF_MSG_ENC_PLAIN; + message->enc = PROF_MSG_ENC_NONE; message->plain = strdup(message->body); chatwin_outgoing_carbon(chatwin, message); } @@ -532,6 +537,7 @@ _sv_ev_incoming_pgp(ProfChatWin *chatwin, gboolean new_win, ProfMessage *message if (message->plain) { message->enc = PROF_MSG_ENC_PGP; _clean_incoming_message(message); + log_database_add_incoming(message); chatwin_incoming_msg(chatwin, message, new_win); if (logit) { chat_log_pgp_msg_in(message); @@ -544,9 +550,10 @@ _sv_ev_incoming_pgp(ProfChatWin *chatwin, gboolean new_win, ProfMessage *message log_error("Couldn't decrypt GPG message and body was empty"); return; } - message->enc = PROF_MSG_ENC_PLAIN; + message->enc = PROF_MSG_ENC_NONE; message->plain = strdup(message->body); _clean_incoming_message(message); + log_database_add_incoming(message); chatwin_incoming_msg(chatwin, message, new_win); chat_log_msg_in(message); chatwin->pgp_recv = FALSE; @@ -565,10 +572,11 @@ _sv_ev_incoming_otr(ProfChatWin *chatwin, gboolean new_win, ProfMessage *message message->enc = PROF_MSG_ENC_OTR; chatwin->pgp_send = FALSE; } else { - message->enc = PROF_MSG_ENC_PLAIN; + message->enc = PROF_MSG_ENC_NONE; } _clean_incoming_message(message); + log_database_add_incoming(message); chatwin_incoming_msg(chatwin, message, new_win); chat_log_otr_msg_in(message); @@ -584,6 +592,7 @@ static void _sv_ev_incoming_omemo(ProfChatWin *chatwin, gboolean new_win, ProfMessage *message, gboolean logit) { _clean_incoming_message(message); + log_database_add_incoming(message); chatwin_incoming_msg(chatwin, message, new_win); if (logit) { chat_log_omemo_msg_in(message); @@ -596,9 +605,10 @@ static void _sv_ev_incoming_plain(ProfChatWin *chatwin, gboolean new_win, ProfMessage *message, gboolean logit) { if (message->body) { - message->enc = PROF_MSG_ENC_PLAIN; + message->enc = PROF_MSG_ENC_NONE; message->plain = strdup(message->body); _clean_incoming_message(message); + log_database_add_incoming(message); chatwin_incoming_msg(chatwin, message, new_win); if (logit) { chat_log_msg_in(message); diff --git a/src/log.c b/src/log.c index 7304ed03..ae8f1542 100644 --- a/src/log.c +++ b/src/log.c @@ -355,14 +355,14 @@ chat_log_otr_msg_in(ProfMessage *message) const char *jid = connection_get_fulljid(); Jid *jidp = jid_create(jid); char *pref_otr_log = prefs_get_string(PREF_OTR_LOG); - if (message->enc == PROF_MSG_ENC_PLAIN || (strcmp(pref_otr_log, "on") == 0)) { - if (message->mucuser) { + 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); } else { _chat_log_chat(jidp->barejid, message->jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, NULL); } } else if (strcmp(pref_otr_log, "redact") == 0) { - if (message->mucuser) { + if (message->type == PROF_MSG_TYPE_MUCPM) { _chat_log_chat(jidp->barejid, message->jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, message->jid->resourcepart); } else { _chat_log_chat(jidp->barejid, message->jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, NULL); @@ -381,13 +381,13 @@ chat_log_pgp_msg_in(ProfMessage *message) Jid *jidp = jid_create(jid); char *pref_pgp_log = prefs_get_string(PREF_PGP_LOG); if (strcmp(pref_pgp_log, "on") == 0) { - if (message->mucuser) { + 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); } else { _chat_log_chat(jidp->barejid, message->jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, NULL); } } else if (strcmp(pref_pgp_log, "redact") == 0) { - if (message->mucuser) { + if (message->type == PROF_MSG_TYPE_MUCPM) { _chat_log_chat(jidp->barejid, message->jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, message->jid->resourcepart); } else { _chat_log_chat(jidp->barejid, message->jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, NULL); @@ -406,13 +406,13 @@ chat_log_omemo_msg_in(ProfMessage *message) Jid *jidp = jid_create(jid); char *pref_omemo_log = prefs_get_string(PREF_OMEMO_LOG); if (strcmp(pref_omemo_log, "on") == 0) { - if (message->mucuser) { + 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); } else { _chat_log_chat(jidp->barejid, message->jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, NULL); } } else if (strcmp(pref_omemo_log, "redact") == 0) { - if (message->mucuser) { + if (message->type == PROF_MSG_TYPE_MUCPM) { _chat_log_chat(jidp->barejid, message->jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, message->jid->resourcepart); } else { _chat_log_chat(jidp->barejid, message->jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, message->jid->resourcepart); @@ -430,7 +430,7 @@ chat_log_msg_in(ProfMessage *message) const char *jid = connection_get_fulljid(); Jid *jidp = jid_create(jid); - if (message->mucuser) { + 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); } else { _chat_log_chat(jidp->barejid, message->jid->barejid, message->plain, PROF_IN_LOG, message->timestamp, NULL); @@ -619,54 +619,6 @@ _groupchat_log_chat(const gchar *const login, const gchar *const room, const gch g_date_time_unref(dt); } -GSList* -chat_log_get_previous(const gchar *const login, const gchar *const recipient) -{ - GSList *history = NULL; - GDateTime *now = g_date_time_new_now_local(); - GDateTime *log_date = g_date_time_new(tz, - g_date_time_get_year(session_started), - g_date_time_get_month(session_started), - g_date_time_get_day_of_month(session_started), - g_date_time_get_hour(session_started), - g_date_time_get_minute(session_started), - g_date_time_get_second(session_started)); - - // get data from all logs from the day the session was started to today - while (g_date_time_compare(log_date, now) != 1) { - char *filename = _get_log_filename(recipient, login, log_date, FALSE); - - FILE *logp = fopen(filename, "r"); - if (logp) { - GString *header = g_string_new(""); - g_string_append_printf(header, "%d/%d/%d:", - g_date_time_get_day_of_month(log_date), - g_date_time_get_month(log_date), - g_date_time_get_year(log_date)); - history = g_slist_append(history, header->str); - g_string_free(header, FALSE); - - char *line; - while ((line = file_getline(logp)) != NULL) { - history = g_slist_append(history, line); - } - - fclose(logp); - } - - free(filename); - - GDateTime *next = g_date_time_add_days(log_date, 1); - g_date_time_unref(log_date); - log_date = next; - } - - g_date_time_unref(log_date); - g_date_time_unref(now); - - return history; -} - void chat_log_close(void) { diff --git a/src/log.h b/src/log.h index 592c4039..3e29e8ca 100644 --- a/src/log.h +++ b/src/log.h @@ -82,7 +82,6 @@ void chat_log_pgp_msg_in(ProfMessage *message); void chat_log_omemo_msg_in(ProfMessage *message); void chat_log_close(void); -GSList* chat_log_get_previous(const gchar *const login, const gchar *const recipient); void groupchat_log_init(void); diff --git a/src/otr/otr.c b/src/otr/otr.c index c32e708e..3c3ed618 100644 --- a/src/otr/otr.c +++ b/src/otr/otr.c @@ -40,6 +40,7 @@ #include <glib.h> #include "log.h" +#include "database.h" #include "config/preferences.h" #include "config/files.h" #include "otr/otr.h" @@ -348,6 +349,7 @@ otr_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean re if (encrypted) { id = message_send_chat_otr(chatwin->barejid, encrypted, request_receipt, replace_id); chat_log_otr_msg_out(chatwin->barejid, message, NULL); + log_database_add_outgoing_chat(id, chatwin->barejid, message, replace_id, PROF_MSG_ENC_OTR); chatwin_outgoing_msg(chatwin, message, id, PROF_MSG_ENC_OTR, request_receipt, replace_id); otr_free_message(encrypted); free(id); @@ -368,7 +370,7 @@ otr_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean re if (policy == PROF_OTRPOLICY_OPPORTUNISTIC) { char *otr_tagged_msg = otr_tag_message(message); id = message_send_chat_otr(chatwin->barejid, otr_tagged_msg, request_receipt, replace_id); - chatwin_outgoing_msg(chatwin, message, id, PROF_MSG_ENC_PLAIN, request_receipt, replace_id); + chatwin_outgoing_msg(chatwin, message, id, PROF_MSG_ENC_NONE, request_receipt, replace_id); chat_log_msg_out(chatwin->barejid, message, NULL); free(otr_tagged_msg); free(id); diff --git a/src/ui/chatwin.c b/src/ui/chatwin.c index 9ebc8d76..5e2ac8c2 100644 --- a/src/ui/chatwin.c +++ b/src/ui/chatwin.c @@ -44,6 +44,7 @@ #include "window_list.h" #include "xmpp/roster_list.h" #include "log.h" +#include "database.h" #include "config/preferences.h" #include "ui/ui.h" #include "ui/window.h" @@ -56,7 +57,7 @@ #include "omemo/omemo.h" #endif -static void _chatwin_history(ProfChatWin *chatwin, const char *const contact); +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* @@ -477,38 +478,20 @@ chatwin_unset_outgoing_char(ProfChatWin *chatwin) } static void -_chatwin_history(ProfChatWin *chatwin, const char *const contact) +_chatwin_history(ProfChatWin *chatwin, const char *const contact_barejid) { if (!chatwin->history_shown) { - Jid *jid = jid_create(connection_get_fulljid()); - GSList *history = chat_log_get_previous(jid->barejid, contact); - jid_destroy(jid); + GSList *history = log_database_get_previous_chat(contact_barejid); GSList *curr = history; - int idd = 0; - int imo = 0; - int iyy = 0; while (curr) { - char *line = curr->data; - // entry, containing the actual entries with date followed by text - if (line[2] == ':') { - char hh[3]; memcpy(hh, &line[0], 2); hh[2] = '\0'; int ihh = atoi(hh); - char mm[3]; memcpy(mm, &line[3], 2); mm[2] = '\0'; int imm = atoi(mm); - char ss[3]; memcpy(ss, &line[6], 2); ss[2] = '\0'; int iss = atoi(ss); - GDateTime *timestamp = g_date_time_new_local(iyy, imo, idd, ihh, imm, iss); - win_print_history((ProfWin*)chatwin, timestamp, curr->data+11); - g_date_time_unref(timestamp); - // header, containing the date from filename "21/10/2019:" - } else { - char dd[3]; memcpy(dd, &line[0], 2); dd[2] = '\0'; idd = atoi(dd); - char mm[3]; memcpy(mm, &line[3], 2); mm[2] = '\0'; imo = atoi(mm); - char yy[5]; memcpy(yy, &line[6], 4); yy[4] = '\0'; iyy = atoi(yy); - } + ProfMessage *msg = curr->data; + win_print_history((ProfWin*)chatwin, msg, FALSE); curr = g_slist_next(curr); } chatwin->history_shown = TRUE; - g_slist_free_full(history, free); + g_slist_free_full(history, (GDestroyNotify)message_free); } } diff --git a/src/ui/mucwin.c b/src/ui/mucwin.c index 79a82a61..620ac704 100644 --- a/src/ui/mucwin.c +++ b/src/ui/mucwin.c @@ -373,22 +373,7 @@ mucwin_history(ProfMucWin *mucwin, const ProfMessage *const message) char *muc_history_color = prefs_get_string(PREF_HISTORY_COLOR_MUC); if (g_strcmp0(muc_history_color, "unanimous") == 0) { - GString *line = g_string_new(""); - - if (strncmp(message->plain, "/me ", 4) == 0) { - g_string_append(line, "*"); - g_string_append(line, nick); - g_string_append(line, " "); - g_string_append(line, message->plain + 4); - } else { - g_string_append(line, nick); - g_string_append(line, ": "); - g_string_append(line, message->plain); - } - - win_print_history(window, message->timestamp, line->str); - - g_string_free(line, TRUE); + win_print_history(window, message, TRUE); } else { char *mynick = muc_nick(mucwin->roomjid); GSList *mentions = get_mentions(prefs_get_boolean(PREF_NOTIFY_MENTION_WHOLE_WORD), prefs_get_boolean(PREF_NOTIFY_MENTION_CASE_SENSITIVE), message->plain, mynick); diff --git a/src/ui/window.c b/src/ui/window.c index fdf5d3f9..5b0aec8b 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -1218,15 +1218,41 @@ win_print_outgoing(ProfWin *window, const char *show_char, const char *const id, } void -win_print_history(ProfWin *window, GDateTime *timestamp, const char *const message) +win_print_history(ProfWin *window, const ProfMessage *const message, gboolean is_muc) { - g_date_time_ref(timestamp); + g_date_time_ref(message->timestamp); - buffer_append(window->layout->buffer, "-", 0, timestamp, 0, THEME_TEXT_HISTORY, "", NULL, message, NULL, NULL); - _win_print_internal(window, "-", 0, timestamp, 0, THEME_TEXT_HISTORY, "", message, NULL); + int flags = 0; + + // TODO: ProfMessage needs a 'type' field like we have in sql db. then we can know whether each message is a chat, muc, mucpm + char *display_name; + if (is_muc) { + display_name = strdup(message->jid->resourcepart); + + char *muc_history_color = prefs_get_string(PREF_HISTORY_COLOR_MUC); + if (g_strcmp0(muc_history_color, "unanimous") == 0) { + flags = NO_COLOUR_FROM; + } + g_free(muc_history_color); + } else { + const char *jid = connection_get_fulljid(); + Jid *jidp = jid_create(jid); + + if (g_strcmp0(jidp->barejid, message->jid->barejid) == 0) { + display_name = strdup("me"); + } else { + display_name = roster_get_msg_display_name(message->jid->barejid, message->jid->resourcepart); + } + jid_destroy(jidp); + } + + buffer_append(window->layout->buffer, "-", 0, message->timestamp, flags, THEME_TEXT_HISTORY, display_name, NULL, message->plain, NULL, NULL); + _win_print_internal(window, "-", 0, message->timestamp, flags, THEME_TEXT_HISTORY, display_name, message->plain, NULL); + + free(display_name); inp_nonblocking(TRUE); - g_date_time_unref(timestamp); + g_date_time_unref(message->timestamp); } void diff --git a/src/ui/window.h b/src/ui/window.h index d17560bc..378dae24 100644 --- a/src/ui/window.h +++ b/src/ui/window.h @@ -68,7 +68,7 @@ void win_print_outgoing(ProfWin *window, const char *show_char, const char *cons void win_print_outgoing_with_receipt(ProfWin *window, const char *show_char, const char *const from, const char *const message, char *id, const char *const replace_id); void win_println_incoming_muc_msg(ProfWin *window, char *show_char, int flags, const ProfMessage *const message); void win_print_outgoing_muc_msg(ProfWin *window, char *show_char, const char *const me, const char *const id, const char *const replace_id, const char *const message); -void win_print_history(ProfWin *window, GDateTime *timestamp, const char *const message); +void win_print_history(ProfWin *window, const ProfMessage *const message, gboolean is_muc); void win_print_http_upload(ProfWin *window, const char *const message, char *url); diff --git a/src/xmpp/message.c b/src/xmpp/message.c index d9159e81..81928d90 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -110,6 +110,7 @@ _message_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *con _handle_error(stanza); } + // if muc if (g_strcmp0(type, STANZA_TYPE_GROUPCHAT) == 0) { _handle_groupchat(stanza); } @@ -192,10 +193,10 @@ message_init(void) message->body = NULL; message->encrypted = NULL; message->plain = NULL; - message->enc = PROF_MSG_ENC_PLAIN; + message->enc = PROF_MSG_ENC_NONE; message->timestamp = NULL; message->trusted = true; - message->mucuser = false; + message->type = PROF_MSG_TYPE_UNINITIALIZED; return message; } @@ -508,7 +509,7 @@ message_send_chat_omemo(const char *const jid, uint32_t sid, GList *keys, } #endif -void +char* message_send_private(const char *const fulljid, const char *const msg, const char *const oob_url) { xmpp_ctx_t * const ctx = connection_get_ctx(); @@ -517,14 +518,14 @@ message_send_private(const char *const fulljid, const char *const msg, const cha xmpp_stanza_t *message = xmpp_message_new(ctx, STANZA_TYPE_CHAT, fulljid, 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; } char* @@ -831,6 +832,7 @@ _handle_groupchat(xmpp_stanza_t *const stanza) ProfMessage *message = message_init(); message->jid = jid; + message->type = PROF_MSG_TYPE_MUC; if (id) { message->id = strdup(id); @@ -977,7 +979,7 @@ _handle_muc_private_message(xmpp_stanza_t *const stanza) { // standard chat message, use jid without resource ProfMessage *message = message_init(); - message->mucuser = TRUE; + message->type = PROF_MSG_TYPE_MUCPM; const gchar *from = xmpp_stanza_get_from(stanza); message->jid = jid_create(from); @@ -1009,6 +1011,8 @@ _handle_muc_private_message(xmpp_stanza_t *const stanza) if (message->timestamp) { sv_ev_delayed_private_message(message); } else { + message->timestamp = g_date_time_new_now_local(); + sv_ev_incoming_private_message(message); } @@ -1060,11 +1064,12 @@ _handle_carbons(xmpp_stanza_t *const stanza) } ProfMessage *message = message_init(); + message->type = PROF_MSG_TYPE_CHAT; // check whether message was a MUC PM xmpp_stanza_t *mucuser = xmpp_stanza_get_child_by_ns(message_stanza, STANZA_NS_MUC_USER); if (mucuser) { - message->mucuser = TRUE; + message->type = PROF_MSG_TYPE_MUCPM; } // id @@ -1179,6 +1184,7 @@ _handle_chat(xmpp_stanza_t *const stanza) // standard chat message, use jid without resource ProfMessage *message = message_init(); message->jid = jid; + message->type = PROF_MSG_TYPE_CHAT; // message stanza id const char *id = xmpp_stanza_get_id(stanza); @@ -1195,10 +1201,14 @@ _handle_chat(xmpp_stanza_t *const stanza) } if (mucuser) { - message->mucuser = TRUE; + message->type = PROF_MSG_TYPE_MUCPM; } message->timestamp = stanza_get_delay(stanza); + if (!message->timestamp) { + message->timestamp = g_date_time_new_now_local(); + } + if (body) { message->body = xmpp_stanza_get_text(body); } diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index 85c49e03..c83869a5 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -120,19 +120,31 @@ typedef struct disco_item_t { } DiscoItem; typedef enum { - PROF_MSG_ENC_PLAIN, + PROF_MSG_ENC_NONE, PROF_MSG_ENC_OTR, PROF_MSG_ENC_PGP, PROF_MSG_ENC_OMEMO } prof_enc_t; +typedef enum { + PROF_MSG_TYPE_UNINITIALIZED, + // regular 1:1 chat + PROF_MSG_TYPE_CHAT, + // groupchats to whole group + PROF_MSG_TYPE_MUC, + // groupchat private message + PROF_MSG_TYPE_MUCPM +} prof_msg_type_t; + typedef struct prof_message_t { Jid *jid; + /* regular <message id=""> */ char *id; /* </origin-id> XEP-0359 */ char *originid; /* <replace id> XEP-0308 LMC */ char *replace_id; + /* for MAM we will need archive_id (also XEP-0359) (see database.c) /* The raw body from xmpp message, either plaintext or OTR encrypted text */ char *body; /* The encrypted message as for PGP */ @@ -142,7 +154,7 @@ typedef struct prof_message_t { GDateTime *timestamp; prof_enc_t enc; gboolean trusted; - gboolean mucuser; + prof_msg_type_t type; } ProfMessage; void session_init(void); @@ -175,7 +187,7 @@ char* message_send_chat(const char *const barejid, const char *const msg, const char* message_send_chat_otr(const char *const barejid, const char *const msg, gboolean request_receipt, const char *const replace_id); char* message_send_chat_pgp(const char *const barejid, const char *const msg, gboolean request_receipt, const char *const replace_id); char* message_send_chat_omemo(const char *const jid, uint32_t sid, GList *keys, const unsigned char *const iv, size_t iv_len, const unsigned char *const ciphertext, size_t ciphertext_len, gboolean request_receipt, gboolean muc, const char *const replace_id); -void message_send_private(const char *const fulljid, const char *const msg, const char *const oob_url); +char* message_send_private(const char *const fulljid, const char *const msg, const char *const oob_url); char* message_send_groupchat(const char *const roomjid, const char *const msg, const char *const oob_url, const char *const replace_id); void message_send_groupchat_subject(const char *const roomjid, const char *const subject); void message_send_inactive(const char *const jid); |