1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-11-03 19:37:16 -05:00

Merge pull request #1282 from profanity-im/feature/sqlite-log

SQLite backend
This commit is contained in:
Michael Vetter 2020-04-06 22:25:40 +02:00 committed by GitHub
commit 6c158a9af8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 578 additions and 148 deletions

View File

@ -21,6 +21,7 @@ packages:
- libgpg-error
- libgcrypt
- libsignal-protocol-c
- sqlite3
sources:
- https://github.com/profanity-im/profanity

View File

@ -28,6 +28,7 @@ matrix:
- PKG_CONFIG_PATH="/usr/local/opt/curl/lib/pkgconfig:$PKG_CONFIG_PATH"
- PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig:$PKG_CONFIG_PATH"
- PKG_CONFIG_PATH="/usr/local/opt/libffi/lib/pkgconfig:$PKG_CONFIG_PATH"
- PKG_CONFIG_PATH="/usr/local/opt/sqlite/lib/pkgconfig:$PKG_CONFIG_PATH"
before_install:
- >

View File

@ -19,3 +19,4 @@ brew 'openssl'
brew 'ossp-uuid'
brew 'pkg-config'
brew 'readline'
brew 'sqlite'

View File

@ -25,7 +25,8 @@ RUN pacman -Syu --noconfirm && pacman -S --needed --noconfirm \
openssl \
pkg-config \
python \
wget
wget \
sqlite
RUN mkdir -p /usr/src/{stabber,profanity}

View File

@ -25,7 +25,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libxss-dev \
make \
pkg-config \
python-dev
python-dev \
libsqlite3-dev
RUN mkdir -p /usr/src/{stabber,libmesode,profanity}
WORKDIR /usr/src

View File

@ -33,7 +33,8 @@ RUN zypper --non-interactive in --no-recommends \
python-devel \
python3 \
python3-devel \
readline-devel
readline-devel \
sqlite3-devel
# https://github.com/openSUSE/docker-containers-build/issues/26
ENV LANG en_US.UTF-8

View File

@ -1,5 +1,7 @@
core_sources = \
src/xmpp/contact.c src/xmpp/contact.h src/log.c src/common.c \
src/xmpp/contact.c src/xmpp/contact.h \
src/log.c src/common.c \
src/database.h src/database.c \
src/log.h src/profanity.c src/common.h \
src/profanity.h src/xmpp/chat_session.c \
src/xmpp/chat_session.h src/xmpp/muc.c src/xmpp/muc.h src/xmpp/jid.h src/xmpp/jid.c \
@ -110,6 +112,7 @@ unittest_sources = \
tests/unittests/xmpp/stub_message.c \
tests/unittests/ui/stub_ui.c tests/unittests/ui/stub_ui.h \
tests/unittests/log/stub_log.c \
tests/unittests/database/stub_database.c \
tests/unittests/config/stub_accounts.c \
tests/unittests/tools/stub_http_upload.c \
tests/unittests/helpers.c tests/unittests/helpers.h \

View File

@ -179,6 +179,9 @@ PKG_CHECK_MODULES([curl], [libcurl], [],
[AC_CHECK_LIB([curl], [main], [],
[AC_MSG_ERROR([libcurl is required for profanity])])])
PKG_CHECK_MODULES([SQLITE], [sqlite3 >= 3.30.0], [],
[AC_MSG_ERROR([sqlite3 3.30.0 or higher is required for profanity profanity])])
AS_IF([test "x$enable_icons_and_clipboard" != xno],
[PKG_CHECK_MODULES([GTK], [gtk+-2.0 >= 2.24.10],
[AC_DEFINE([HAVE_GTK], [1], [libgtk module])],
@ -332,9 +335,9 @@ AS_IF([test "x$PACKAGE_STATUS" = xdevelopment],
AS_IF([test "x$PLATFORM" = xosx],
[AM_CFLAGS="$AM_CFLAGS -Qunused-arguments"])
AM_LDFLAGS="$AM_LDFLAGS -export-dynamic"
AM_CPPFLAGS="$AM_CPPFLAGS $glib_CFLAGS $gio_CFLAGS $curl_CFLAGS $libnotify_CFLAGS $PYTHON_CPPFLAGS ${GTK_CFLAGS}"
AM_CPPFLAGS="$AM_CPPFLAGS $glib_CFLAGS $gio_CFLAGS $curl_CFLAGS $libnotify_CFLAGS $PYTHON_CPPFLAGS ${GTK_CFLAGS} ${SQLITE_CFLAGS}"
AM_CPPFLAGS="$AM_CPPFLAGS -DTHEMES_PATH=\"\\\"$THEMES_PATH\\\"\" -DICONS_PATH=\"\\\"$ICONS_PATH\\\"\""
LIBS="$glib_LIBS $gio_LIBS $curl_LIBS $libnotify_LIBS $PYTHON_LIBS $PYTHON_EXTRA_LIBS $PYTHON_LDFLAGS ${GTK_LIBS} $LIBS"
LIBS="$glib_LIBS $gio_LIBS $curl_LIBS $libnotify_LIBS $PYTHON_LIBS $PYTHON_EXTRA_LIBS $PYTHON_LDFLAGS ${GTK_LIBS} ${SQLITE_LIBS} $LIBS"
AC_SUBST(AM_LDFLAGS)
AC_SUBST(AM_CFLAGS)

View File

@ -3,6 +3,7 @@
* vim: expandtab:ts=4:sts=4:sw=4
*
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
* Copyright (C) 2020 Michael Vetter <jubalh@idoru.org>
*
* This file is part of Profanity.
*

View File

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

325
src/database.c Normal file
View File

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

52
src/database.h Normal file
View File

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

View File

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

View File

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

View File

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

View File

@ -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)
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,36 @@
/*
* stub_database.c
*
* Copyright (C) 2020 Michael Vetter <jubalh@iodoru.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 <http://www.gnu.org/licenses/>.
*
*/
#include <glib.h>
#include <setjmp.h>
#include <cmocka.h>
#include "database.h"
gboolean log_database_init(ProfAccount *account) { return TRUE; }
void log_database_add_incoming_chat(ProfMessage *message) {}
void log_database_add_incoming_muc(ProfMessage *message) {}
void log_database_add_incoming_muc_pm(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) {}
void log_database_close(void) {}

View File

@ -67,11 +67,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)
{
return mock_ptr_type(GSList *);
}
void groupchat_log_init(void) {}
void groupchat_log_msg_in(const gchar *const room, const gchar *const nick, const gchar *const msg) {}

View File

@ -116,11 +116,16 @@ char* message_send_chat_pgp(const char * const barejid, const char * const msg,
return NULL;
}
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)
{
return NULL;
}
char* message_send_groupchat(const char *const roomjid, const char *const msg, const char *const oob_url, const char *const replace_id)
{
return NULL;
}
void message_send_groupchat_subject(const char * const roomjid, const char * const subject) {}
void message_send_inactive(const char * const barejid) {}