2015-10-26 18:35:30 -04:00
/*
* chatwin . c
2019-11-13 06:11:05 -05:00
* vim : expandtab : ts = 4 : sts = 4 : sw = 4
2015-10-26 18:35:30 -04:00
*
2019-01-22 05:31:45 -05:00
* Copyright ( C ) 2012 - 2019 James Booth < boothj5 @ gmail . com >
2023-01-10 04:37:25 -05:00
* Copyright ( C ) 2019 - 2023 Michael Vetter < jubalh @ iodoru . org >
2015-10-26 18:35:30 -04:00
*
* 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
2016-07-23 20:14:49 -04:00
* along with Profanity . If not , see < https : //www.gnu.org/licenses/>.
2015-10-26 18:35:30 -04:00
*
* 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 .
*
*/
2016-03-31 16:05:02 -04:00
# include "config.h"
2015-10-31 19:38:08 -04:00
2015-10-26 18:35:30 -04:00
# include <string.h>
2020-07-07 07:53:30 -04:00
# include <stdlib.h>
# include <assert.h>
2015-10-26 18:35:30 -04:00
2020-07-07 07:53:30 -04:00
# include "xmpp/chat_session.h"
# include "window_list.h"
# include "xmpp/roster_list.h"
2015-10-26 18:35:30 -04:00
# include "log.h"
2020-07-07 07:53:30 -04:00
# include "database.h"
# include "config/preferences.h"
2015-10-26 18:35:30 -04:00
# include "ui/ui.h"
# include "ui/window.h"
2020-07-07 07:53:30 -04:00
# include "ui/titlebar.h"
# include "plugins/plugins.h"
2016-03-31 16:05:02 -04:00
# ifdef HAVE_LIBOTR
2015-10-31 19:38:08 -04:00
# include "otr/otr.h"
# endif
2023-06-30 08:33:17 -04:00
# ifdef HAVE_LIBGPGME
# include "pgp/gpg.h"
# endif
2019-04-15 16:09:47 -04:00
# ifdef HAVE_OMEMO
# include "omemo/omemo.h"
# endif
2015-10-26 18:35:30 -04:00
2020-07-07 08:18:57 -04:00
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 ) ;
2015-10-26 18:35:30 -04:00
2022-06-17 08:43:54 -04:00
gboolean
_pgp_automatic_start ( const char * const recipient )
{
gboolean result = FALSE ;
char * account_name = session_get_account_name ( ) ;
ProfAccount * account = accounts_get_account ( account_name ) ;
if ( g_list_find_custom ( account - > pgp_enabled , recipient , ( GCompareFunc ) g_strcmp0 ) ) {
result = TRUE ;
}
account_free ( account ) ;
return result ;
}
gboolean
_ox_automatic_start ( const char * const recipient )
{
gboolean result = FALSE ;
char * account_name = session_get_account_name ( ) ;
ProfAccount * account = accounts_get_account ( account_name ) ;
if ( g_list_find_custom ( account - > ox_enabled , recipient , ( GCompareFunc ) g_strcmp0 ) ) {
result = TRUE ;
}
account_free ( account ) ;
return result ;
}
2015-10-27 19:18:42 -04:00
ProfChatWin *
2020-07-07 08:18:57 -04:00
chatwin_new ( const char * const barejid )
2015-10-27 19:18:42 -04:00
{
2020-07-07 08:18:57 -04:00
ProfWin * window = wins_new_chat ( barejid ) ;
ProfChatWin * chatwin = ( ProfChatWin * ) window ;
2015-10-27 19:18:42 -04:00
2022-07-05 04:30:04 -04:00
if ( ! prefs_get_boolean ( PREF_MAM ) & & ( prefs_get_boolean ( PREF_CHLOG ) & & prefs_get_boolean ( PREF_HISTORY ) ) ) {
2020-04-11 18:37:20 -04:00
_chatwin_history ( chatwin , barejid ) ;
2015-10-27 19:18:42 -04:00
}
// if the contact is offline, show a message
PContact contact = roster_get_contact ( barejid ) ;
if ( contact ) {
if ( strcmp ( p_contact_presence ( contact ) , " offline " ) = = 0 ) {
2020-07-07 08:18:57 -04:00
const char * const show = p_contact_presence ( contact ) ;
const char * const status = p_contact_status ( contact ) ;
2015-10-27 19:18:42 -04:00
win_show_status_string ( window , barejid , show , status , NULL , " -- " , " offline " ) ;
}
}
2021-03-28 20:47:35 -04:00
// We start a new OMEMO session if this contact has been configured accordingly.
// However, if OTR is *also* configured, ask the user to choose between OMEMO and OTR.
2022-06-17 08:43:54 -04:00
gboolean is_ox_secure = FALSE ;
2021-03-28 20:47:35 -04:00
gboolean is_otr_secure = FALSE ;
2022-06-17 08:43:54 -04:00
gboolean is_omemo_secure = FALSE ;
# ifdef HAVE_LIBGPGME
is_ox_secure = _ox_automatic_start ( barejid ) ;
# endif
# ifdef HAVE_OMEMO
is_omemo_secure = omemo_automatic_start ( barejid ) ;
# endif
2021-03-28 20:47:35 -04:00
# ifdef HAVE_LIBOTR
is_otr_secure = otr_is_secure ( barejid ) ;
2022-06-17 08:43:54 -04:00
# endif
if ( is_omemo_secure + is_otr_secure + _pgp_automatic_start ( barejid ) + is_ox_secure > 1 ) {
win_println ( window , THEME_DEFAULT , " ! " , " This chat could be either OMEMO, PGP, OX or OTR encrypted, but not more than one. "
" Use '/omemo start', '/pgp start', '/ox start' or '/otr start' to select the encryption method. " ) ;
} else if ( is_omemo_secure ) {
2022-06-17 08:51:45 -04:00
# ifdef HAVE_OMEMO
2021-03-28 20:47:35 -04:00
// Start the OMEMO session
2019-04-15 16:09:47 -04:00
omemo_start_session ( barejid ) ;
chatwin - > is_omemo = TRUE ;
2022-06-17 08:51:45 -04:00
# endif
2022-06-17 08:43:54 -04:00
} else if ( _pgp_automatic_start ( barejid ) ) {
// Start the PGP session
chatwin - > pgp_send = TRUE ;
} else if ( is_ox_secure ) {
// Start the OX session
chatwin - > is_ox = TRUE ;
2019-04-15 16:09:47 -04:00
}
2020-04-11 18:37:20 -04:00
if ( prefs_get_boolean ( PREF_MAM ) ) {
2022-08-20 15:48:02 -04:00
iq_mam_request ( chatwin , NULL ) ;
2022-07-05 04:12:29 -04:00
win_print_loading_history ( window ) ;
2020-04-11 18:37:20 -04:00
}
2020-12-09 13:02:37 -05:00
2015-10-27 19:18:42 -04:00
return chatwin ;
}
2015-10-26 18:35:30 -04:00
void
2020-07-07 08:18:57 -04:00
chatwin_receipt_received ( ProfChatWin * chatwin , const char * const id )
2015-10-26 18:35:30 -04:00
{
2015-10-26 19:11:38 -04:00
assert ( chatwin ! = NULL ) ;
2020-07-07 08:18:57 -04:00
ProfWin * win = ( ProfWin * ) chatwin ;
2015-10-26 18:54:06 -04:00
win_mark_received ( win , id ) ;
2015-10-26 18:35:30 -04:00
}
2016-03-31 16:05:02 -04:00
# ifdef HAVE_LIBOTR
2015-10-26 18:35:30 -04:00
void
2020-07-07 08:18:57 -04:00
chatwin_otr_secured ( ProfChatWin * chatwin , gboolean trusted )
2015-10-26 18:35:30 -04:00
{
2015-10-26 19:11:38 -04:00
assert ( chatwin ! = NULL ) ;
2015-10-26 18:35:30 -04:00
chatwin - > is_otr = TRUE ;
chatwin - > otr_is_trusted = trusted ;
2015-10-26 19:04:45 -04:00
2020-07-07 08:18:57 -04:00
ProfWin * window = ( ProfWin * ) chatwin ;
2015-10-26 18:35:30 -04:00
if ( trusted ) {
2020-02-20 12:11:08 -05:00
win_println ( window , THEME_OTR_STARTED_TRUSTED , " ! " , " OTR session started (trusted). " ) ;
2015-10-26 18:35:30 -04:00
} else {
2020-02-20 12:11:08 -05:00
win_println ( window , THEME_OTR_STARTED_UNTRUSTED , " ! " , " OTR session started (untrusted). " ) ;
2015-10-26 18:35:30 -04:00
}
if ( wins_is_current ( window ) ) {
2020-07-07 08:18:57 -04:00
title_bar_switch ( ) ;
2015-10-26 18:35:30 -04:00
} else {
int num = wins_get_num ( window ) ;
2018-03-09 16:11:59 -05:00
status_bar_new ( num , WIN_CHAT , chatwin - > barejid ) ;
2015-10-26 18:35:30 -04:00
int ui_index = num ;
if ( ui_index = = 10 ) {
ui_index = 0 ;
}
2015-10-26 19:04:45 -04:00
cons_show ( " %s started an OTR session (%d). " , chatwin - > barejid , ui_index ) ;
2020-07-09 09:44:35 -04:00
cons_alert ( window ) ;
2015-10-26 18:35:30 -04:00
}
}
void
2020-07-07 08:18:57 -04:00
chatwin_otr_unsecured ( ProfChatWin * chatwin )
2015-10-26 18:35:30 -04:00
{
2015-10-26 19:11:38 -04:00
assert ( chatwin ! = NULL ) ;
2015-10-26 19:10:30 -04:00
chatwin - > is_otr = FALSE ;
chatwin - > otr_is_trusted = FALSE ;
2015-10-26 18:35:30 -04:00
2020-07-07 08:18:57 -04:00
ProfWin * window = ( ProfWin * ) chatwin ;
2020-02-20 12:11:08 -05:00
win_println ( window , THEME_OTR_ENDED , " ! " , " OTR session ended. " ) ;
2015-10-26 19:10:30 -04:00
if ( wins_is_current ( window ) ) {
title_bar_switch ( ) ;
2015-10-26 18:35:30 -04:00
}
}
void
2020-07-07 08:18:57 -04:00
chatwin_otr_smp_event ( ProfChatWin * chatwin , prof_otr_smp_event_t event , void * data )
2015-10-26 18:35:30 -04:00
{
2015-10-26 19:22:59 -04:00
assert ( chatwin ! = NULL ) ;
2015-10-27 18:25:02 -04:00
switch ( event ) {
2020-07-07 08:18:57 -04:00
case PROF_OTR_SMP_INIT :
win_println ( ( ProfWin * ) chatwin , THEME_DEFAULT , " ! " ,
" %s wants to authenticate your identity, use '/otr secret <secret>'. " , chatwin - > barejid ) ;
break ;
case PROF_OTR_SMP_INIT_Q :
win_println ( ( ProfWin * ) chatwin , THEME_DEFAULT , " ! " ,
" %s wants to authenticate your identity with the following question: " , chatwin - > barejid ) ;
win_println ( ( ProfWin * ) chatwin , THEME_DEFAULT , " ! " , " %s " , ( char * ) data ) ;
win_println ( ( ProfWin * ) chatwin , THEME_DEFAULT , " ! " , " use '/otr answer <answer>'. " ) ;
break ;
case PROF_OTR_SMP_SENDER_FAIL :
win_println ( ( ProfWin * ) chatwin , THEME_DEFAULT , " ! " ,
" Authentication failed, the secret you entered does not match the secret entered by %s. " ,
chatwin - > barejid ) ;
break ;
case PROF_OTR_SMP_RECEIVER_FAIL :
win_println ( ( ProfWin * ) chatwin , THEME_DEFAULT , " ! " ,
" Authentication failed, the secret entered by %s does not match yours. " , chatwin - > barejid ) ;
break ;
case PROF_OTR_SMP_ABORT :
win_println ( ( ProfWin * ) chatwin , THEME_DEFAULT , " ! " , " SMP session aborted. " ) ;
break ;
case PROF_OTR_SMP_SUCCESS :
win_println ( ( ProfWin * ) chatwin , THEME_DEFAULT , " ! " , " Authentication successful. " ) ;
break ;
case PROF_OTR_SMP_SUCCESS_Q :
win_println ( ( ProfWin * ) chatwin , THEME_DEFAULT , " ! " , " %s successfully authenticated you. " , chatwin - > barejid ) ;
break ;
case PROF_OTR_SMP_FAIL_Q :
win_println ( ( ProfWin * ) chatwin , THEME_DEFAULT , " ! " , " %s failed to authenticate you. " , chatwin - > barejid ) ;
break ;
case PROF_OTR_SMP_AUTH :
2023-04-09 06:19:18 -04:00
win_println ( ( ProfWin * ) chatwin , THEME_DEFAULT , " ! " , " Authenticating %s… " , chatwin - > barejid ) ;
2020-07-07 08:18:57 -04:00
break ;
case PROF_OTR_SMP_AUTH_WAIT :
2023-04-09 06:19:18 -04:00
win_println ( ( ProfWin * ) chatwin , THEME_DEFAULT , " ! " , " Awaiting authentication from %s… " , chatwin - > barejid ) ;
2020-07-07 08:18:57 -04:00
break ;
default :
break ;
2015-10-27 18:25:02 -04:00
}
2015-10-26 18:35:30 -04:00
}
void
2020-07-07 08:18:57 -04:00
chatwin_otr_trust ( ProfChatWin * chatwin )
2015-10-26 18:35:30 -04:00
{
2015-10-26 20:19:22 -04:00
assert ( chatwin ! = NULL ) ;
chatwin - > is_otr = TRUE ;
chatwin - > otr_is_trusted = TRUE ;
2020-07-07 08:18:57 -04:00
ProfWin * window = ( ProfWin * ) chatwin ;
2020-02-20 12:11:08 -05:00
win_println ( window , THEME_OTR_TRUSTED , " ! " , " OTR session trusted. " ) ;
2015-10-26 20:19:22 -04:00
if ( wins_is_current ( window ) ) {
title_bar_switch ( ) ;
2015-10-26 18:35:30 -04:00
}
}
void
2020-07-07 08:18:57 -04:00
chatwin_otr_untrust ( ProfChatWin * chatwin )
2015-10-26 18:35:30 -04:00
{
2015-10-26 20:19:22 -04:00
assert ( chatwin ! = NULL ) ;
2015-10-26 18:35:30 -04:00
2015-10-26 20:19:22 -04:00
chatwin - > is_otr = TRUE ;
chatwin - > otr_is_trusted = FALSE ;
2020-07-07 08:18:57 -04:00
ProfWin * window = ( ProfWin * ) chatwin ;
2020-02-20 12:11:08 -05:00
win_println ( window , THEME_OTR_UNTRUSTED , " ! " , " OTR session untrusted. " ) ;
2015-10-26 20:19:22 -04:00
if ( wins_is_current ( window ) ) {
title_bar_switch ( ) ;
2015-10-26 18:35:30 -04:00
}
}
2015-10-31 19:22:23 -04:00
# endif
2015-10-26 18:35:30 -04:00
void
2020-07-07 08:18:57 -04:00
chatwin_recipient_gone ( ProfChatWin * chatwin )
2015-10-26 18:35:30 -04:00
{
2015-10-27 19:25:18 -04:00
assert ( chatwin ! = NULL ) ;
2020-07-07 08:18:57 -04:00
const char * display_usr = NULL ;
2015-10-27 19:05:20 -04:00
PContact contact = roster_get_contact ( chatwin - > barejid ) ;
if ( contact ) {
if ( p_contact_name ( contact ) ) {
display_usr = p_contact_name ( contact ) ;
} else {
display_usr = chatwin - > barejid ;
2015-10-26 18:35:30 -04:00
}
2015-10-27 19:05:20 -04:00
} else {
display_usr = chatwin - > barejid ;
2015-10-26 18:35:30 -04:00
}
2015-10-27 19:05:20 -04:00
2020-02-20 12:11:08 -05:00
win_println ( ( ProfWin * ) chatwin , THEME_GONE , " ! " , " <- %s has left the conversation. " , display_usr ) ;
2015-10-26 18:35:30 -04:00
}
void
2020-07-07 08:18:57 -04:00
chatwin_incoming_msg ( ProfChatWin * chatwin , ProfMessage * message , gboolean win_created )
2015-10-26 18:35:30 -04:00
{
2015-10-27 19:25:18 -04:00
assert ( chatwin ! = NULL ) ;
2022-07-04 10:45:18 -04:00
if ( message - > plain = = NULL ) {
log_error ( " chatwin_incoming_msg: Message with no plain field from: %s " , message - > from_jid ) ;
return ;
}
2020-07-07 08:18:57 -04:00
char * old_plain = message - > plain ;
2015-10-27 19:25:18 -04:00
2020-04-11 17:56:01 -04:00
message - > plain = plugins_pre_chat_message_display ( message - > from_jid - > barejid , message - > from_jid - > resourcepart , message - > plain ) ;
2023-06-30 08:33:17 -04:00
gboolean show_message = true ;
2016-02-14 17:28:55 -05:00
2020-07-07 08:18:57 -04:00
ProfWin * window = ( ProfWin * ) chatwin ;
2015-10-26 18:35:30 -04:00
int num = wins_get_num ( window ) ;
2023-06-13 16:01:08 -04:00
auto_gchar gchar * display_name ;
2020-07-07 08:18:57 -04:00
char * mybarejid = connection_get_barejid ( ) ;
2020-05-25 07:04:19 -04:00
if ( g_strcmp0 ( mybarejid , message - > from_jid - > barejid ) = = 0 ) {
2020-04-11 17:56:01 -04:00
display_name = strdup ( " me " ) ;
} else {
display_name = roster_get_msg_display_name ( message - > from_jid - > barejid , message - > from_jid - > resourcepart ) ;
}
2020-05-25 07:04:19 -04:00
free ( mybarejid ) ;
2015-10-26 18:35:30 -04:00
2023-06-30 08:33:17 -04:00
# ifdef HAVE_LIBGPGME
if ( prefs_get_boolean ( PREF_PGP_PUBKEY_AUTOIMPORT ) ) {
if ( p_gpg_is_public_key_format ( message - > plain ) ) {
ProfPGPKey * key = p_gpg_import_pubkey ( message - > plain ) ;
if ( key ! = NULL ) {
show_message = false ;
win_println ( window , THEME_DEFAULT , " - " , " Received and imported PGP key %s: \" %s \" . To assign it to the correspondent using /pgp setkey %s %s " , key - > fp , key - > name , display_name , key - > id ) ;
p_gpg_free_key ( key ) ;
} else {
win_println ( window , THEME_DEFAULT , " - " , " Received PGP key, but couldn't import PGP key above. " ) ;
}
}
}
# endif
2015-11-25 17:08:33 -05:00
gboolean is_current = wins_is_current ( window ) ;
2022-08-20 16:03:46 -04:00
gboolean notify = prefs_do_chat_notify ( is_current ) & & ! message - > is_mam ;
2015-11-25 17:08:33 -05:00
2015-10-26 18:35:30 -04:00
// currently viewing chat window with sender
if ( wins_is_current ( window ) ) {
2023-06-30 08:33:17 -04:00
if ( show_message ) {
win_print_incoming ( window , display_name , message ) ;
}
2015-10-26 18:35:30 -04:00
title_bar_set_typing ( FALSE ) ;
2018-03-09 16:11:59 -05:00
status_bar_active ( num , WIN_CHAT , chatwin - > barejid ) ;
2015-10-26 18:35:30 -04:00
2020-07-07 08:18:57 -04:00
// not currently viewing chat window with sender
2015-10-26 18:35:30 -04:00
} else {
2018-03-09 16:11:59 -05:00
status_bar_new ( num , WIN_CHAT , chatwin - > barejid ) ;
2015-10-26 18:35:30 -04:00
2022-08-20 16:03:46 -04:00
if ( ! message - > is_mam ) {
cons_show_incoming_message ( display_name , num , chatwin - > unread , window ) ;
if ( prefs_get_boolean ( PREF_FLASH ) ) {
flash ( ) ;
}
2015-10-26 18:35:30 -04:00
2022-08-20 16:03:46 -04:00
chatwin - > unread + + ;
}
2016-02-03 20:24:37 -05:00
2020-04-11 18:37:20 -04:00
// TODO: so far we don't ask for MAM when incoming message occurs.
// Need to figure out:
// 1) only send IQ once
// 2) sort incoming messages on timestamp
// for now if experimental MAM is enabled we dont show no history from sql either
2020-05-20 03:48:42 -04:00
2020-04-13 15:57:28 -04:00
// MUCPMs also get printed here. In their case we don't save any logs (because nick owners can change) and thus we shouldn't read logs
// (and if we do we need to check the resourcepart)
if ( ! prefs_get_boolean ( PREF_MAM ) & & prefs_get_boolean ( PREF_CHLOG ) & & prefs_get_boolean ( PREF_HISTORY ) & & message - > type = = PROF_MSG_TYPE_CHAT ) {
2020-04-11 18:37:20 -04:00
_chatwin_history ( chatwin , chatwin - > barejid ) ;
2015-10-26 18:35:30 -04:00
}
// show users status first, when receiving message via delayed delivery
2019-06-17 00:23:40 -04:00
if ( message - > timestamp & & win_created ) {
2015-10-26 18:35:30 -04:00
PContact pcontact = roster_get_contact ( chatwin - > barejid ) ;
if ( pcontact ) {
win_show_contact ( window , pcontact ) ;
}
}
2019-12-13 06:05:24 -05:00
win_insert_last_read_position_marker ( ( ProfWin * ) chatwin , chatwin - > barejid ) ;
2023-06-30 08:33:17 -04:00
if ( show_message ) {
win_print_incoming ( window , display_name , message ) ;
}
2015-10-26 18:35:30 -04:00
}
2023-02-13 16:40:58 -05:00
if ( ! message - > is_mam ) {
wins_add_urls_ac ( window , message , FALSE ) ;
wins_add_quotes_ac ( window , message - > plain , FALSE ) ;
2020-05-20 03:48:42 -04:00
2023-02-13 16:40:58 -05:00
if ( prefs_get_boolean ( PREF_BEEP ) ) {
beep ( ) ;
}
2015-10-26 18:35:30 -04:00
}
2016-02-03 19:41:53 -05:00
if ( notify ) {
2019-06-17 00:23:40 -04:00
notify_message ( display_name , num , message - > plain ) ;
2015-10-26 18:35:30 -04:00
}
2020-04-11 17:56:01 -04:00
plugins_post_chat_message_display ( message - > from_jid - > barejid , message - > from_jid - > resourcepart , message - > plain ) ;
2016-02-14 17:28:55 -05:00
2019-06-17 00:23:40 -04:00
free ( message - > plain ) ;
message - > plain = old_plain ;
2015-10-26 18:35:30 -04:00
}
void
2020-07-07 08:18:57 -04:00
chatwin_outgoing_msg ( ProfChatWin * chatwin , const char * const message , char * id , prof_enc_t enc_mode ,
gboolean request_receipt , const char * const replace_id )
2015-10-26 18:35:30 -04:00
{
2015-10-27 19:25:18 -04:00
assert ( chatwin ! = NULL ) ;
2022-03-20 18:10:07 -04:00
ProfWin * window = ( ProfWin * ) chatwin ;
2023-02-13 16:40:58 -05:00
wins_add_quotes_ac ( window , message , FALSE ) ;
2022-03-20 18:10:07 -04:00
2020-07-07 08:18:57 -04:00
char * enc_char ;
2017-01-20 16:03:55 -05:00
if ( chatwin - > outgoing_char ) {
2020-02-20 12:11:08 -05:00
enc_char = chatwin - > outgoing_char ;
2019-06-17 00:23:40 -04:00
} else if ( enc_mode = = PROF_MSG_ENC_OTR ) {
2015-10-26 18:35:30 -04:00
enc_char = prefs_get_otr_char ( ) ;
2019-06-17 00:23:40 -04:00
} else if ( enc_mode = = PROF_MSG_ENC_PGP ) {
2015-10-26 18:35:30 -04:00
enc_char = prefs_get_pgp_char ( ) ;
2019-06-17 00:23:40 -04:00
} else if ( enc_mode = = PROF_MSG_ENC_OMEMO ) {
2019-02-26 13:53:06 -05:00
enc_char = prefs_get_omemo_char ( ) ;
2020-06-21 03:43:42 -04:00
} else if ( enc_mode = = PROF_MSG_ENC_OX ) {
enc_char = prefs_get_ox_char ( ) ;
2020-02-20 12:11:08 -05:00
} else {
enc_char = strdup ( " - " ) ;
2015-10-26 18:35:30 -04:00
}
2016-08-18 17:51:06 -04:00
if ( request_receipt & & id ) {
2020-02-13 06:24:12 -05:00
win_print_outgoing_with_receipt ( ( ProfWin * ) chatwin , enc_char , " me " , message , id , replace_id ) ;
2015-10-26 18:35:30 -04:00
} else {
2020-02-17 05:48:50 -05:00
win_print_outgoing ( ( ProfWin * ) chatwin , enc_char , id , replace_id , message ) ;
2020-02-11 09:26:58 -05:00
}
2020-02-20 12:11:08 -05:00
free ( enc_char ) ;
2020-02-11 09:26:58 -05:00
// save last id and message for LMC
if ( id ) {
_chatwin_set_last_message ( chatwin , id , message ) ;
2015-10-26 18:35:30 -04:00
}
}
void
2020-07-07 08:18:57 -04:00
chatwin_outgoing_carbon ( ProfChatWin * chatwin , ProfMessage * message )
2015-10-26 18:35:30 -04:00
{
2015-10-27 19:25:18 -04:00
assert ( chatwin ! = NULL ) ;
2015-10-26 18:35:30 -04:00
2020-07-07 08:18:57 -04:00
char * enc_char ;
2019-06-21 07:49:17 -04:00
if ( message - > enc = = PROF_MSG_ENC_PGP ) {
2016-03-21 20:20:29 -04:00
enc_char = prefs_get_pgp_char ( ) ;
2019-06-21 07:49:17 -04:00
} else if ( message - > enc = = PROF_MSG_ENC_OMEMO ) {
2019-03-27 08:37:09 -04:00
enc_char = prefs_get_omemo_char ( ) ;
2020-02-20 12:11:08 -05:00
} else {
enc_char = strdup ( " - " ) ;
2016-03-21 20:20:29 -04:00
}
2020-07-07 08:18:57 -04:00
ProfWin * window = ( ProfWin * ) chatwin ;
2018-03-08 14:55:17 -05:00
2020-02-17 05:48:50 -05:00
win_print_outgoing ( window , enc_char , message - > id , message - > replace_id , message - > plain ) ;
2018-03-08 14:55:17 -05:00
int num = wins_get_num ( window ) ;
2018-03-09 16:11:59 -05:00
status_bar_active ( num , WIN_CHAT , chatwin - > barejid ) ;
2020-02-20 12:11:08 -05:00
free ( enc_char ) ;
2015-10-26 18:35:30 -04:00
}
void
2020-07-07 08:18:57 -04:00
chatwin_contact_online ( ProfChatWin * chatwin , Resource * resource , GDateTime * last_activity )
2015-10-26 18:35:30 -04:00
{
2015-10-27 19:39:26 -04:00
assert ( chatwin ! = NULL ) ;
2020-07-07 08:18:57 -04:00
const char * show = string_from_resource_presence ( resource - > presence ) ;
2015-10-27 19:39:26 -04:00
PContact contact = roster_get_contact ( chatwin - > barejid ) ;
2020-07-07 08:18:57 -04:00
char * display_str = p_contact_create_display_string ( contact , resource - > name ) ;
2015-10-26 18:35:30 -04:00
2015-10-27 19:39:26 -04:00
win_show_status_string ( ( ProfWin * ) chatwin , display_str , show , resource - > status , last_activity , " ++ " , " online " ) ;
2015-10-26 18:35:30 -04:00
free ( display_str ) ;
}
void
2020-07-07 08:18:57 -04:00
chatwin_contact_offline ( ProfChatWin * chatwin , char * resource , char * status )
2015-10-26 18:35:30 -04:00
{
2015-10-27 19:39:26 -04:00
assert ( chatwin ! = NULL ) ;
PContact contact = roster_get_contact ( chatwin - > barejid ) ;
2020-07-07 08:18:57 -04:00
char * display_str = p_contact_create_display_string ( contact , resource ) ;
2015-10-26 18:35:30 -04:00
2015-10-27 19:39:26 -04:00
win_show_status_string ( ( ProfWin * ) chatwin , display_str , " offline " , status , NULL , " -- " , " offline " ) ;
2015-10-26 18:35:30 -04:00
free ( display_str ) ;
}
2015-11-29 18:58:52 -05:00
char *
2020-07-07 08:18:57 -04:00
chatwin_get_string ( ProfChatWin * chatwin )
2015-11-29 18:58:52 -05:00
{
assert ( chatwin ! = NULL ) ;
2020-07-07 08:18:57 -04:00
GString * res = g_string_new ( " Chat " ) ;
2015-11-29 18:58:52 -05:00
2016-05-05 18:51:49 -04:00
jabber_conn_status_t conn_status = connection_get_status ( ) ;
2016-01-04 19:06:50 -05:00
if ( conn_status = = JABBER_CONNECTED ) {
PContact contact = roster_get_contact ( chatwin - > barejid ) ;
if ( contact = = NULL ) {
g_string_append ( res , chatwin - > barejid ) ;
} else {
2020-07-07 08:18:57 -04:00
const char * display_name = p_contact_name_or_jid ( contact ) ;
2016-01-04 19:06:50 -05:00
g_string_append ( res , display_name ) ;
g_string_append_printf ( res , " - %s " , p_contact_presence ( contact ) ) ;
}
2015-11-29 18:58:52 -05:00
} else {
2016-01-04 19:06:50 -05:00
g_string_append ( res , chatwin - > barejid ) ;
2015-11-29 18:58:52 -05:00
}
if ( chatwin - > unread > 0 ) {
g_string_append_printf ( res , " , %d unread " , chatwin - > unread ) ;
}
2023-03-23 05:23:51 -04:00
return g_string_free ( res , FALSE ) ;
2015-11-29 18:58:52 -05:00
}
2017-01-19 17:33:29 -05:00
void
2020-07-07 08:18:57 -04:00
chatwin_set_enctext ( ProfChatWin * chatwin , const char * const enctext )
2017-01-19 17:33:29 -05:00
{
if ( chatwin - > enctext ) {
free ( chatwin - > enctext ) ;
}
chatwin - > enctext = strdup ( enctext ) ;
}
void
2020-07-07 08:18:57 -04:00
chatwin_unset_enctext ( ProfChatWin * chatwin )
2017-01-19 17:33:29 -05:00
{
if ( chatwin - > enctext ) {
free ( chatwin - > enctext ) ;
chatwin - > enctext = NULL ;
}
}
2017-01-20 16:03:55 -05:00
void
2020-07-07 08:18:57 -04:00
chatwin_set_incoming_char ( ProfChatWin * chatwin , const char * const ch )
2017-01-20 16:03:55 -05:00
{
if ( chatwin - > incoming_char ) {
free ( chatwin - > incoming_char ) ;
}
chatwin - > incoming_char = strdup ( ch ) ;
}
void
2020-07-07 08:18:57 -04:00
chatwin_unset_incoming_char ( ProfChatWin * chatwin )
2017-01-20 16:03:55 -05:00
{
if ( chatwin - > incoming_char ) {
free ( chatwin - > incoming_char ) ;
chatwin - > incoming_char = NULL ;
}
}
void
2020-07-07 08:18:57 -04:00
chatwin_set_outgoing_char ( ProfChatWin * chatwin , const char * const ch )
2017-01-20 16:03:55 -05:00
{
if ( chatwin - > outgoing_char ) {
free ( chatwin - > outgoing_char ) ;
}
chatwin - > outgoing_char = strdup ( ch ) ;
}
void
2020-07-07 08:18:57 -04:00
chatwin_unset_outgoing_char ( ProfChatWin * chatwin )
2017-01-20 16:03:55 -05:00
{
if ( chatwin - > outgoing_char ) {
free ( chatwin - > outgoing_char ) ;
chatwin - > outgoing_char = NULL ;
}
}
2015-10-26 18:35:30 -04:00
static void
2020-07-07 08:18:57 -04:00
_chatwin_history ( ProfChatWin * chatwin , const char * const contact_barejid )
2015-10-26 18:35:30 -04:00
{
if ( ! chatwin - > history_shown ) {
2022-07-10 03:44:06 -04:00
GSList * history = log_database_get_previous_chat ( contact_barejid , NULL , NULL , FALSE , FALSE ) ;
2020-07-07 08:18:57 -04:00
GSList * curr = history ;
2019-10-21 09:26:40 -04:00
2015-10-26 18:35:30 -04:00
while ( curr ) {
2020-07-07 08:18:57 -04:00
ProfMessage * msg = curr - > data ;
2021-07-20 15:13:13 -04:00
char * msg_plain = msg - > plain ;
2021-04-27 20:42:30 -04:00
msg - > plain = plugins_pre_chat_message_display ( msg - > from_jid - > barejid , msg - > from_jid - > resourcepart , msg - > plain ) ;
2021-07-20 15:13:13 -04:00
// This is dirty workaround for memory leak. We reassign msg->plain above so have to free previous object
// TODO: Make a better solution, for example, pass msg object to the function and it will replace msg->plain properly if needed.
free ( msg_plain ) ;
2020-04-08 06:50:23 -04:00
win_print_history ( ( ProfWin * ) chatwin , msg ) ;
2015-10-26 18:35:30 -04:00
curr = g_slist_next ( curr ) ;
}
chatwin - > history_shown = TRUE ;
2020-04-06 10:04:34 -04:00
g_slist_free_full ( history , ( GDestroyNotify ) message_free ) ;
2015-10-26 18:35:30 -04:00
}
}
2020-02-10 10:17:01 -05:00
2022-07-05 06:09:16 -04:00
// Print history starting from start_time to end_time if end_time is null the
2022-08-20 15:48:02 -04:00
// first entry's timestamp in the buffer is used. Flip true to prepend to buffer.
// Timestamps should be in iso8601
2022-07-03 14:29:36 -04:00
gboolean
2023-05-11 04:52:54 -04:00
chatwin_db_history ( ProfChatWin * chatwin , const char * start_time , char * end_time , gboolean flip )
2022-07-03 14:29:36 -04:00
{
2022-07-05 06:09:16 -04:00
if ( ! end_time ) {
end_time = buffer_size ( ( ( ProfWin * ) chatwin ) - > layout - > buffer ) = = 0 ? NULL : g_date_time_format_iso8601 ( buffer_get_entry ( ( ( ProfWin * ) chatwin ) - > layout - > buffer , 0 ) - > time ) ;
}
2022-07-10 03:44:06 -04:00
GSList * history = log_database_get_previous_chat ( chatwin - > barejid , start_time , end_time , ! flip , flip ) ;
2022-07-03 14:29:36 -04:00
gboolean has_items = g_slist_length ( history ) ! = 0 ;
GSList * curr = history ;
while ( curr ) {
ProfMessage * msg = curr - > data ;
char * msg_plain = msg - > plain ;
msg - > plain = plugins_pre_chat_message_display ( msg - > from_jid - > barejid , msg - > from_jid - > resourcepart , msg - > plain ) ;
// This is dirty workaround for memory leak. We reassign msg->plain above so have to free previous object
// TODO: Make a better solution, for example, pass msg object to the function and it will replace msg->plain properly if needed.
free ( msg_plain ) ;
2022-07-05 06:09:16 -04:00
if ( flip ) {
win_print_old_history ( ( ProfWin * ) chatwin , msg ) ;
} else {
win_print_history ( ( ProfWin * ) chatwin , msg ) ;
}
2022-07-03 14:29:36 -04:00
curr = g_slist_next ( curr ) ;
}
g_slist_free_full ( history , ( GDestroyNotify ) message_free ) ;
win_redraw ( ( ProfWin * ) chatwin ) ;
return has_items ;
}
2020-02-10 10:17:01 -05:00
static void
2020-07-07 08:18:57 -04:00
_chatwin_set_last_message ( ProfChatWin * chatwin , const char * const id , const char * const message )
2020-02-10 10:17:01 -05:00
{
free ( chatwin - > last_message ) ;
chatwin - > last_message = strdup ( message ) ;
free ( chatwin - > last_msg_id ) ;
chatwin - > last_msg_id = strdup ( id ) ;
}