[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [kopete] /: ported otr plugin to libotr 4.0.0
From: Michael Zanetti <mzanetti () kde ! org>
Date: 2013-09-17 17:17:30
Message-ID: E1VLyu2-0003lE-Is () scm ! kde ! org
[Download RAW message or body]
Git commit b977f1f701afd1f9192f35e0263f2f1c04bef53e by Michael Zanetti.
Committed on 24/06/2013 at 22:20.
Pushed by mzanetti into branch 'master'.
ported otr plugin to libotr 4.0.0
BUG: 195328
BUG: 218570
BUG: 298681
BUG: 304105
BUG: 306276
BUG: 309987
BUG: 318255
BUG: 204502
M +1 -3 CMakeLists.txt
M +5 -5 cmake/modules/FindLibOTR.cmake
M +17 -16 plugins/otr/authenticationwizard.cpp
M +1 -1 plugins/otr/authenticationwizard.h
M +1 -1 plugins/otr/kopete_otr.desktop
M +1 -1 plugins/otr/otrguiclient.cpp
M +1 -1 plugins/otr/otrguiclient.h
M +455 -316 plugins/otr/otrlchatinterface.cpp
M +42 -7 plugins/otr/otrlchatinterface.h
M +2 -6 plugins/otr/otrlconfinterface.cpp
M +1 -1 plugins/otr/otrlconfinterface.h
M +22 -68 plugins/otr/otrplugin.cpp
M +1 -1 plugins/otr/otrplugin.h
M +1 -1 plugins/otr/otrpreferences.cpp
M +1 -1 plugins/otr/otrpreferences.h
M +1 -1 plugins/otr/privkeypopup.cpp
M +1 -1 plugins/otr/privkeypopup.h
http://commits.kde.org/kopete/b977f1f701afd1f9192f35e0263f2f1c04bef53e
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9f59f39..8cec3e0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -88,11 +88,9 @@ macro_optional_find_package(LibXslt)
macro_bool_to_01(LIBXSLT_FOUND HAVE_XSLT)
macro_log_feature(LIBXSLT_FOUND "LibXSLT" "A library to transform XML files into \
other XML files" "http://xmlsoft.org/XSLT" FALSE "" "Required for the Kopete \
webpresence plugin.")
-# LibOTR 4 have undergone significant changes leading to compilation errors, so this \
plugin should be disabled to let kopete compile (quick fix)
-# TODO: fix otr plugin to make it work sith LibOTR 4
macro_optional_find_package(LibOTR)
macro_bool_to_01(LIBOTR_FOUND HAVE_LIBOTR)
-macro_log_feature(LIBOTR_FOUND "libotr" "A library to encrypt messages with \
Off-the-Record encryption (versions 3.2.0 to 4.0.0)" "http://www.cypherpunks.ca/otr" \
FALSE "3.2.0" "Required for the Kopete otr plugin.") +macro_log_feature(LIBOTR_FOUND \
"libotr" "A library to encrypt messages with Off-the-Record encryption (version \
4.0.0) or greater" "http://www.cypherpunks.ca/otr" FALSE "4.0.0" "Required for the \
Kopete otr plugin.")
macro_optional_find_package(Libmsn)
macro_bool_to_01(LIBMSN_FOUND HAVE_LIBMSN)
diff --git a/cmake/modules/FindLibOTR.cmake b/cmake/modules/FindLibOTR.cmake
index e9dbf31..9c771d2 100644
--- a/cmake/modules/FindLibOTR.cmake
+++ b/cmake/modules/FindLibOTR.cmake
@@ -1,6 +1,6 @@
-# cmake macro to test LibOTR
+## cmake macro to test LibOTR
-# Copyright (c) 2008, Michael Zanetti <michael_zanetti @ gnx.net>
+# Copyright (c) 2008-2013, Michael Zanetti <mzanetti @ kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
@@ -22,15 +22,15 @@ IF( LIBOTR_INCLUDE_DIR AND LIBOTR_LIBRARY )
EXECUTE_PROCESS(COMMAND grep "OTRL_VERSION" \
"${LIBOTR_INCLUDE_DIR}/libotr/version.h" OUTPUT_VARIABLE output) STRING(REGEX MATCH \
"OTRL_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+" LIBOTR_VERSION "${output}") STRING(REGEX \
REPLACE "^OTRL_VERSION \"" "" LIBOTR_VERSION "${LIBOTR_VERSION}")
- # Check if version is at least 3.2.0
- MACRO_ENSURE_VERSION_RANGE("3.2.0" ${LIBOTR_VERSION} "4.0.0" LIBOTR_FOUND)
+ # Check if version is at least 4.0.0
+ MACRO_ENSURE_VERSION("4.0.0" ${LIBOTR_VERSION} LIBOTR_FOUND)
IF( LIBOTR_FOUND )
IF( NOT LIBOTR_FIND_QUIETLY )
MESSAGE( STATUS "Found libotr: ${LIBOTR_LIBRARY} (version ${LIBOTR_VERSION})")
ENDIF( NOT LIBOTR_FIND_QUIETLY )
ELSE( LIBOTR_FOUND )
- MESSAGE(STATUS "libotr version between 3.2.0 and 4.0.0 required but found \
${LIBOTR_VERSION}.") + MESSAGE(STATUS "libotr version 4.0.0 or greater required \
but found ${LIBOTR_VERSION}.") ENDIF( LIBOTR_FOUND )
ENDIF( LIBOTR_INCLUDE_DIR AND LIBOTR_LIBRARY )
diff --git a/plugins/otr/authenticationwizard.cpp \
b/plugins/otr/authenticationwizard.cpp index e4d5d13..1c76cf0 100644
--- a/plugins/otr/authenticationwizard.cpp
+++ b/plugins/otr/authenticationwizard.cpp
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
+ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@@ -47,9 +47,9 @@ AuthenticationWizard::AuthenticationWizard(QWidget *parent, \
ConnContext *context setAttribute(Qt::WA_DeleteOnClose);
setPage(Page_SelectMethod, createIntroPage());
- setPage(Page_QuestionAnswer, createQAPage());
- setPage(Page_SharedSecret, createSSPage());
- setPage(Page_ManualVerification, createMVPage());
+ setPage(Page_QuestionAnswer, createQAPage());
+ setPage(Page_SharedSecret, createSSPage());
+ setPage(Page_ManualVerification, createMVPage());
setPage(Page_Wait1, new WaitPage(i18n("Waiting for %1...", \
OtrlChatInterface::self()->formatContact(session->members().first()->contactId())))); \
setPage(Page_Wait2, new WaitPage(i18n("Checking if answers match..."))); \
setPage(Page_Final, createFinalPage()); @@ -72,8 +72,9 @@ \
AuthenticationWizard::AuthenticationWizard(QWidget *parent, ConnContext *context if \
( session->account()->isBusy() ) return;
+ resize(rbMV->width() * 1.5, rbMV->width() * 0.75);
show();
-
+
if ( !session->view()->mainWidget() || \
!session->view()->mainWidget()->isActiveWindow() ) { KNotification *notification = \
new KNotification( "kopete_info_event", KNotification::CloseWhenWidgetActivated | \
KNotification::CloseOnTimeout ); notification->setText( i18n( "Incoming \
authentication request from %1", OtrlChatInterface::self()->formatContact( \
session->members().first()->contactId() ) ) ); @@ -83,7 +84,7 @@ \
AuthenticationWizard::AuthenticationWizard(QWidget *parent, ConnContext *context \
connect( notification, SIGNAL(activated(uint)), SLOT(notificationActivated(uint)) ); \
notification->sendEvent(); }
-
+
}
@@ -97,7 +98,7 @@ AuthenticationWizard \
*AuthenticationWizard::findWizard(Kopete::ChatSession *sess return wizardList.at(i);
}
}
- return 0;
+ return 0;
}
QWizardPage *AuthenticationWizard::createIntroPage(){
@@ -108,7 +109,7 @@ QWizardPage *AuthenticationWizard::createIntroPage(){
rbQA = new QRadioButton(i18n("Question and Answer"));
rbSS = new QRadioButton(i18n("Shared Secret"));
rbMV = new QRadioButton(i18n("Manual fingerprint verification"));
-
+
QGroupBox *frame = new QGroupBox();
QVBoxLayout *frameLayout = new QVBoxLayout();
frame->setLayout(frameLayout);
@@ -117,8 +118,8 @@ QWizardPage *AuthenticationWizard::createIntroPage(){
frameLayout->addWidget(infoLabel);
QVBoxLayout *layout = new QVBoxLayout();
- layout->addWidget(rbQA);
- layout->addWidget(rbSS);
+ layout->addWidget(rbQA);
+ layout->addWidget(rbSS);
layout->addWidget(rbMV);
layout->addSpacing(30);
@@ -126,7 +127,7 @@ QWizardPage *AuthenticationWizard::createIntroPage(){
page->setLayout(layout);
- rbQA->setChecked(true);
+ rbQA->setChecked(true);
return page;
}
@@ -176,7 +177,7 @@ QWizardPage *AuthenticationWizard::createSSPage(){
layout->addWidget(new QLabel(i18nc("@info", "Enter the secret passphrase known \
only to you and %1:", session->members().first()->contactId()))); }
leSecret = new QLineEdit();
- layout->addWidget(leSecret);
+ layout->addWidget(leSecret);
page->setLayout(layout);
page->setCommitPage(true);
@@ -192,7 +193,7 @@ QWizardPage *AuthenticationWizard::createMVPage(){
QLabel *lMessage1 = new QLabel(i18nc("@info", "Contact %1 via another secure \
channel and verify that the following fingerprint is correct:", \
session->members().first()->contactId())); lMessage1->setWordWrap(true);
layout->addWidget(lMessage1);
- layout->addWidget(new \
QLabel(OtrlChatInterface::self()->findActiveFingerprint(session))); \
+ layout->addWidget(new QLabel(OtrlChatInterface::self()->fingerprint(session)));
cbManualAuth = new QComboBox();
cbManualAuth->addItem(i18nc("@item:inlistbox ...verified that", "I have not"));
@@ -330,9 +331,9 @@ void AuthenticationWizard::finished(bool success, bool trust){
lFinal->setText(i18n("The authentication with %1 failed. To make sure you are not \
talking to an imposter, try again using the manual fingerprint verification method. \
Note that the conversation is now insecure.", \
OtrlChatInterface::self()->formatContact(session->members().first()->contactId()))); \
} }
-
+
setOption(QWizard::NoCancelButton, true);
-
+
}
void AuthenticationWizard::aborted(){
@@ -347,7 +348,7 @@ void AuthenticationWizard::aborted(){
}
currentPage()->setTitle(i18n("Authentication aborted"));
lFinal->setText(i18n("%1 has aborted the authentication process. To make sure you \
are not talking to an imposter, try again using the manual fingerprint verification \
method.", OtrlChatInterface::self()->formatContact(session->members().first()->contactId())));
-
+
setOption(QWizard::NoCancelButton, true);
}
diff --git a/plugins/otr/authenticationwizard.h b/plugins/otr/authenticationwizard.h
index a4dea40..244f2e0 100644
--- a/plugins/otr/authenticationwizard.h
+++ b/plugins/otr/authenticationwizard.h
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
+ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
diff --git a/plugins/otr/kopete_otr.desktop b/plugins/otr/kopete_otr.desktop
index 36ec0c8..4554a26 100644
--- a/plugins/otr/kopete_otr.desktop
+++ b/plugins/otr/kopete_otr.desktop
@@ -7,7 +7,7 @@ X-KDE-Library=kopete_otr
X-KDE-PluginInfo-Author=Michael Zanetti
X-KDE-PluginInfo-Email=michael_zanetti@gmx.net
X-KDE-PluginInfo-Name=kopete_otr
-X-KDE-PluginInfo-Version=0.9
+X-KDE-PluginInfo-Version=0.10
X-KDE-PluginInfo-Website=http://kopete-otr.follefuder.org
X-KDE-PluginInfo-Category=Plugins
X-KDE-PluginInfo-Depends=
diff --git a/plugins/otr/otrguiclient.cpp b/plugins/otr/otrguiclient.cpp
index 11329db..605f388 100644
--- a/plugins/otr/otrguiclient.cpp
+++ b/plugins/otr/otrguiclient.cpp
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
+ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
diff --git a/plugins/otr/otrguiclient.h b/plugins/otr/otrguiclient.h
index 0347075..200ea46 100644
--- a/plugins/otr/otrguiclient.h
+++ b/plugins/otr/otrguiclient.h
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
+ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
diff --git a/plugins/otr/otrlchatinterface.cpp b/plugins/otr/otrlchatinterface.cpp
index 56ffd0c..5edf576 100644
--- a/plugins/otr/otrlchatinterface.cpp
+++ b/plugins/otr/otrlchatinterface.cpp
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
+ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@@ -63,13 +63,13 @@ static OtrlPolicy confPolicy;
static Kopete::Plugin *chatPlugin = 0;
/***************************** Gui_UI_Ops for libotr \
**********************************/
-static OtrlPolicy policy(void *opdata, ConnContext *context){
+OtrlPolicy OtrlChatInterface::policy(void *opdata, ConnContext *context){
Q_UNUSED(context)
Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
bool noerr;
-
+
// Disable OTR for IRC
if( session->protocol()->pluginId() == "IRCProtocol" ){
// kdDebug() << "Disabling OTR for: " << session->protocol()->pluginId() << endl;
@@ -92,7 +92,9 @@ static OtrlPolicy policy(void *opdata, ConnContext *context){
}
}
-static void create_privkey(void *opdata, const char *accountname, const char \
*protocol){ +void OtrlChatInterface::create_privkey(void *opdata, const char \
*accountname, const char *protocol){ + Q_UNUSED(accountname)
+ Q_UNUSED(protocol)
Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
if( !session->view() ){
@@ -102,23 +104,21 @@ static void create_privkey(void *opdata, const char \
*accountname, const char *pr popup->show();
popup->setCloseLock( true );
- KeyGenThread *keyGenThread = new KeyGenThread ( accountname, protocol );
- keyGenThread->start();
- while( !keyGenThread->wait(100) ){
- qApp->processEvents(QEventLoop::ExcludeUserInputEvents | \
QEventLoop::ExcludeSocketNotifiers, 100);
- }
+ OtrlChatInterface::self()->generatePrivateKey(session->account()->accountId(), \
session->protocol()->displayName());
popup->setCloseLock( false );
popup->close();
+
+ OtrlChatInterface::self()->replayStoredMessages();
}
-static int is_logged_in(void *opdata, const char *accountname, const char *protocol, \
const char *recipient){ +int OtrlChatInterface::is_logged_in(void *opdata, const char \
*accountname, const char *protocol, const char *recipient){
Q_UNUSED(accountname)
Q_UNUSED(protocol)
Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
- Kopete::ContactPtrList list = session->members();
+ Kopete::ContactPtrList list = session->members();
for( int i = 0; i < list.size(); i++ ){
if( list.at(i)->contactId().compare( recipient) == 0 ){
Kopete::OnlineStatus status = session->contactOnlineStatus( list.at(i) );
@@ -134,7 +134,7 @@ static int is_logged_in(void *opdata, const char *accountname, \
const char *proto return -1;
}
-static void inject_message( void *opdata, const char *accountname, const char \
*protocol, const char *recipient, const char *message ){ +void \
OtrlChatInterface::inject_message( void *opdata, const char *accountname, const char \
*protocol, const char *recipient, const char *message ){
Q_UNUSED(accountname)
Q_UNUSED(protocol)
@@ -142,7 +142,7 @@ static void inject_message( void *opdata, const char \
*accountname, const char *p // kDebug(14318) << "Sending message:" << message;
Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
- Kopete::ContactPtrList list = session->members();
+ Kopete::ContactPtrList list = session->members();
for( int i = 0; i < list.size(); i++ ){
if( list.at(i)->contactId().compare( recipient ) == 0 ){
Kopete::Message msg( session->account()->myself(), list.at(i) );
@@ -154,61 +154,12 @@ static void inject_message( void *opdata, const char \
*accountname, const char *p }
}
-static void notify(void *opdata, OtrlNotifyLevel level, const char *accountname, \
const char *protocol, const char *username, const char *title, const char *primary, \
const char *secondary){
-
- Q_UNUSED(opdata)
- Q_UNUSED(level)
- Q_UNUSED(accountname)
- Q_UNUSED(protocol)
- Q_UNUSED(username)
-
- KMessageBox::information(NULL, QString( primary ) + QString( secondary ), QString( \
title ) );
-}
-
-static int display_otr_message( void *opdata, const char *accountname, const char \
*protocol, const char *username, const char *message ){
-
- Q_UNUSED(accountname)
- Q_UNUSED(protocol)
-
- Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
- Kopete::ContactPtrList list = session->members();
- for( int i = 0; i < list.size(); i++ ){
- if( list.at(i)->contactId().compare( username ) == 0 ){
- Kopete::Message msg( session->members().first(), session->account()->myself() );
- msg.setHtmlBody( QString( message ) );
- msg.setDirection( Kopete::Message::Internal );
- session->appendMessage( msg );
- return 0;
- }
- }
- return 1;
-}
-
-static void update_context_list(void *opdata){
+void OtrlChatInterface::update_context_list(void *opdata){
//Not used...
Q_UNUSED(opdata)
}
-static const char *protocol_name(void *opdata, const char *protocol){
-//Never seen...
-
- Q_UNUSED(opdata)
- Q_UNUSED(protocol)
-
-// kdDebug() << "protocol_name called" << endl;
- return 0;
-}
-
-static void protocol_name_free(void *opdata, const char *protocol_name){
-//Never seen...
-
- Q_UNUSED(opdata)
- Q_UNUSED(protocol_name)
-
-// kdDebug() << "protocol_name_free called" << endl;
-}
-
-static void new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, \
const char *protocol, const char *username, unsigned char fingerprint[20]){ +void \
OtrlChatInterface::new_fingerprint(void *opdata, OtrlUserState us, const char \
*accountname, const char *protocol, const char *username, unsigned char \
fingerprint[20]){
Q_UNUSED(us)
Q_UNUSED(accountname)
@@ -224,7 +175,7 @@ static void new_fingerprint(void *opdata, OtrlUserState us, const \
char *accountn session->appendMessage( msg );
}
-static void write_fingerprints(void *opdata){
+void OtrlChatInterface::write_fingerprints(void *opdata){
Q_UNUSED(opdata)
@@ -233,8 +184,7 @@ static void write_fingerprints(void *opdata){
otrl_privkey_write_fingerprints( userstate, savePath.toLocal8Bit() );
}
-static void gone_secure(void *opdata, ConnContext *context){
-// kdDebug() << "gone secure" << endl;
+void OtrlChatInterface::gone_secure(void *opdata, ConnContext *context){
Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
if( context->active_fingerprint->trust && context->active_fingerprint->trust[0] ){
@@ -250,9 +200,11 @@ static void gone_secure(void *opdata, ConnContext *context){
session->appendMessage( msg );
OtrlChatInterface::self()->emitGoneSecure( ((Kopete::ChatSession*)opdata), 1 );
}
+
+ session->setProperty("otr-instag", QString::number(context->their_instance));
}
-static void gone_insecure(void *opdata, ConnContext *context){
+void OtrlChatInterface::gone_insecure(void *opdata, ConnContext *context){
Q_UNUSED(context)
@@ -265,12 +217,12 @@ static void gone_insecure(void *opdata, ConnContext *context){
session->appendMessage( msg );
}
-static void still_secure(void *opdata, ConnContext *context, int is_reply){
+void OtrlChatInterface::still_secure(void *opdata, ConnContext *context, int \
is_reply){
Q_UNUSED(is_reply)
-// kdDebug() << "still secure" << endl;
Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
+
Kopete::Message msg( session->members().first(), session->account()->myself() );
msg.setHtmlBody( i18n("<b>OTR connection refreshed successfully.</b>") );
msg.setDirection( Kopete::Message::Internal );
@@ -283,18 +235,11 @@ static void still_secure(void *opdata, ConnContext *context, \
int is_reply){ }
}
-static void log_message(void *opdata, const char *message){
-
- Q_UNUSED(opdata)
-
- kDebug(14318) << "libotr: "<< message;
-}
-
-static int max_message_size(void *opdata, ConnContext *context){
+int OtrlChatInterface::max_message_size(void *opdata, ConnContext *context){
Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
Q_UNUSED(context)
-
+
kDebug(14318) << session->protocol()->pluginId();
if( session->protocol()->pluginId() == "WlmProtocol" ){
@@ -305,32 +250,264 @@ static int max_message_size(void *opdata, ConnContext \
*context){ return 1274;
} else if( session->protocol()->pluginId() == "YahooProtocol" ){
return 700;
- }
+ }
// Jabber doesn't need fragmentation. Return 0 to disable.
// GaduGadu seems to not need fragmentation too.
return 0;
}
-static OtrlMessageAppOps ui_ops = {
- policy,
- create_privkey,
- is_logged_in,
- inject_message,
- notify,
- display_otr_message,
- update_context_list,
- protocol_name,
- protocol_name_free,
- new_fingerprint,
- write_fingerprints,
- gone_secure,
- gone_insecure,
- still_secure,
- log_message,
- max_message_size,
- 0, //not used yet...
- 0 //not used yet...
+const char* OtrlChatInterface::otr_error_message(void *opdata, ConnContext *context, \
OtrlErrorCode err_code) { + Q_UNUSED(opdata)
+
+ char *err_msg = 0;
+ switch (err_code)
+ {
+ case OTRL_ERRCODE_NONE :
+ break;
+ case OTRL_ERRCODE_ENCRYPTION_ERROR : {
+ QString message = i18n("Error occurred encrypting message.");
+ err_msg = (char*)malloc(message.length() + 1);
+ memset(err_msg, 0, message.length() + 1);
+ memcpy(err_msg, message.toUtf8().data(), message.length());
+ break;
+ }
+ case OTRL_ERRCODE_MSG_NOT_IN_PRIVATE :
+ if (context) {
+ QString message = i18n("You sent encrypted data to %s, who wasn't expecting \
it.").arg(context->accountname); + err_msg = (char*)malloc(message.length() + 1);
+ memset(err_msg, 0, message.length() + 1);
+ memcpy(err_msg, message.toUtf8().data(), message.length());
+ }
+ break;
+ case OTRL_ERRCODE_MSG_UNREADABLE : {
+ QString message = i18n("You transmitted an unreadable encrypted message.");
+ err_msg = (char*)malloc(message.length() + 1);
+ memset(err_msg, 0, message.length() + 1);
+ memcpy(err_msg, message.toUtf8().data(), message.length());
+ break;
+ }
+ case OTRL_ERRCODE_MSG_MALFORMED : {
+ QString message = i18n("You transmitted a malformed data message.");
+ err_msg = (char*)malloc(message.length() + 1);
+ memset(err_msg, 0, message.length() + 1);
+ memcpy(err_msg, message.toUtf8().data(), message.length());
+ break;
+ }
+ }
+ return err_msg;
+}
+
+void OtrlChatInterface::otr_error_message_free(void *opdata, const char *err_msg) {
+ Q_UNUSED(opdata)
+ if (err_msg) {
+ free((char*)err_msg);
+ }
+}
+
+const char *OtrlChatInterface::resent_msg_prefix(void *opdata, ConnContext *context) \
{ + Q_UNUSED(opdata)
+ Q_UNUSED(context)
+
+ QString message = i18n("[resent]");
+ char *msg_prefix = (char*)malloc(message.length() + 1);
+ memset(msg_prefix, 0, message.length() + 1);
+ memcpy(msg_prefix, message.toUtf8().data(), message.length());
+ return msg_prefix;
+}
+
+void OtrlChatInterface::resent_msg_prefix_free(void *opdata, const char *prefix) {
+ Q_UNUSED(opdata)
+
+ if (prefix) {
+ free((char*)prefix);
+ }
+}
+
+void OtrlChatInterface::handle_smp_event(void *opdata, OtrlSMPEvent smp_event, \
ConnContext *context, unsigned short progress_percent, char *question) { + \
Q_UNUSED(progress_percent) +
+ Kopete::ChatSession *chatSession = (Kopete::ChatSession*)opdata;
+
+ if (!context) {
+ return;
+ }
+
+ switch (smp_event) {
+ case OTRL_SMPEVENT_NONE :
+ break;
+ case OTRL_SMPEVENT_ASK_FOR_SECRET :
+ new AuthenticationWizard( chatSession->view(true)->mainWidget(), context, \
chatSession, false ); + break;
+ case OTRL_SMPEVENT_ASK_FOR_ANSWER :
+ new AuthenticationWizard( chatSession->view(true)->mainWidget(), context, \
chatSession, false, QLatin1String(question) ); + break;
+ case OTRL_SMPEVENT_IN_PROGRESS :
+ AuthenticationWizard::findWizard(chatSession)->nextState();
+ break;
+ case OTRL_SMPEVENT_SUCCESS :
+ if (context->active_fingerprint->trust && context->active_fingerprint->trust[0]) {
+ AuthenticationWizard::findWizard(chatSession)->finished(true, true);
+ kDebug(14318) << "trust found";
+ Kopete::Message msg( chatSession->members().first(), \
chatSession->account()->myself() ); + msg.setHtmlBody( i18n("Authentication with \
<b>%1</b> successful. The conversation is now secure.", \
formatContact(chatSession->members().first()->contactId()))); + msg.setDirection( \
Kopete::Message::Internal ); + chatSession->appendMessage( msg );
+ OtrlChatInterface::self()->emitGoneSecure( chatSession, 2 );
+ } else {
+ AuthenticationWizard::findWizard(chatSession)->finished(true, false);
+ kDebug(14318) << "trust _NOT_ found";
+ Kopete::Message msg( chatSession->members().first(), \
chatSession->account()->myself() ); + msg.setHtmlBody( i18n("<b>%1</b> has \
successfully authenticated you. You may want to authenticate this contact as well by \
asking your own question.", \
formatContact(chatSession->members().first()->contactId()))); + msg.setDirection( \
Kopete::Message::Internal ); + chatSession->appendMessage( msg );
+ OtrlChatInterface::self()->emitGoneSecure( chatSession, 1 );
+ }
+ break;
+ case OTRL_SMPEVENT_FAILURE : {
+ AuthenticationWizard::findWizard(chatSession)->finished(false, false);
+ Kopete::Message msg( chatSession->members().first(), \
chatSession->account()->myself() ); + msg.setHtmlBody( i18n("Authentication with \
<b>%1</b> failed. The conversation is now insecure.", \
formatContact(chatSession->members().first()->contactId()))); + msg.setDirection( \
Kopete::Message::Internal ); + chatSession->appendMessage( msg );
+ OtrlChatInterface::self()->emitGoneSecure( chatSession, 1 );
+ break;
+ }
+ case OTRL_SMPEVENT_ABORT :
+ case OTRL_SMPEVENT_CHEATED :
+ case OTRL_SMPEVENT_ERROR :
+ AuthenticationWizard::findWizard(chatSession)->finished(false, false);
+ OtrlChatInterface::self()->abortSMP( context, chatSession );
+ break;
+ }
+}
+
+void OtrlChatInterface::handle_msg_event(void *opdata, OtrlMessageEvent msg_event, \
ConnContext *context, const char* message, gcry_error_t err) { +
+ Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
+ Kopete::ContactPtrList list = session->members();
+ Kopete::Message msg( session->members().first(), session->account()->myself() );
+
+ switch (msg_event)
+ {
+ case OTRL_MSGEVENT_NONE:
+ break;
+ case OTRL_MSGEVENT_ENCRYPTION_REQUIRED:
+ msg.setHtmlBody( i18n( "You attempted to send an unencrypted message to %1" \
).arg(QLatin1String(context->username)) ); + msg.setDirection( \
Kopete::Message::Internal ); + break;
+ case OTRL_MSGEVENT_ENCRYPTION_ERROR:
+ msg.setHtmlBody( i18n( "An error occurred when encrypting your message. The \
message was not sent." ).arg(QLatin1String(context->username)) ); \
+ msg.setDirection( Kopete::Message::Internal ); + break;
+ case OTRL_MSGEVENT_CONNECTION_ENDED:
+ msg.setHtmlBody( i18n( "%1 has already closed his/her private connection to you. \
Your message was not sent. Either end your private conversation, or restart it." \
).arg(QLatin1String(context->username)) ); + msg.setDirection( \
Kopete::Message::Internal ); + break;
+ case OTRL_MSGEVENT_SETUP_ERROR:
+ if (!err) {
+ err = GPG_ERR_INV_VALUE;
+ }
+ switch(gcry_err_code(err)) {
+ case GPG_ERR_INV_VALUE:
+ kDebug(14318) << "Error setting up private conversation: Malformed message \
received"; + default:
+ kDebug(14318) << "Error setting up private conversation:" << err;
+ }
+
+ msg.setHtmlBody( i18n( "OTR error" ) );
+ msg.setDirection( Kopete::Message::Internal );
+ break;
+ case OTRL_MSGEVENT_MSG_REFLECTED:
+ msg.setHtmlBody( i18n( "We are receiving our own OTR messages. You are either \
trying to talk to yourself, or someone is reflecting your messages back at you." ) ); \
+ msg.setDirection( Kopete::Message::Internal ); + break;
+ case OTRL_MSGEVENT_MSG_RESENT:
+ msg.setHtmlBody( i18n( "<b>The last message to %1 was resent.</b>" \
).arg(QLatin1String(context->username)) ); + msg.setDirection( \
Kopete::Message::Internal ); + break;
+ case OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE:
+ msg.setHtmlBody( i18n( "<b>The encrypted message received from %1 is unreadable, \
as you are not currently communicating privately.</b>" \
).arg(QLatin1String(context->username)) ); + msg.setDirection( \
Kopete::Message::Inbound ); \
+ OtrlChatInterface::self()->m_blackistIds.append(msg.id()); + break;
+ case OTRL_MSGEVENT_RCVDMSG_UNREADABLE:
+ msg.setHtmlBody( i18n( "We received an unreadable encrypted message from %1." \
).arg(QLatin1String(context->username)) ); + msg.setDirection( \
Kopete::Message::Internal ); + break;
+ case OTRL_MSGEVENT_RCVDMSG_MALFORMED:
+ msg.setHtmlBody( i18n( "We received a malformed data message from %1." \
).arg(QLatin1String(context->username)) ); + msg.setDirection( \
Kopete::Message::Internal ); + break;
+ case OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD:
+ kDebug(14318) << "Heartbeat received from" << context->username;
+ return;
+ case OTRL_MSGEVENT_LOG_HEARTBEAT_SENT:
+ kDebug(14318) << "Heartbeat sent to" << context->username;
+ break;
+ case OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR:
+ msg.setHtmlBody( QLatin1String(message) );
+ msg.setDirection( Kopete::Message::Internal );
+ session->appendMessage( msg );
+ break;
+ case OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED:
+ msg.setHtmlBody( i18n("<b>The following message received from %1 was <i>not</i> \
encrypted: [</b>%2<b>]</b>").arg(QLatin1String(context->username), \
QLatin1String(message) )); + msg.setDirection( Kopete::Message::Inbound );
+ OtrlChatInterface::self()->m_blackistIds.append(msg.id());
+ break;
+ case OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED:
+ kDebug(14318) << "Unrecognized OTR message received from" << context->username;
+ break;
+ case OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE:
+ msg.setHtmlBody( i18n( "%1 has sent an encrypted message intended for a different \
session. If you are logged in multiple times, another session may have received the \
message.").arg(QLatin1String(context->username) )); + msg.setDirection( \
Kopete::Message::Inbound ); \
+ OtrlChatInterface::self()->m_blackistIds.append(msg.id()); + break;
+ }
+
+ session->appendMessage( msg );
+}
+
+void OtrlChatInterface::create_instag(void *opdata, const char *accountname, const \
char *protocol) { + Q_UNUSED(opdata)
+ QString storeFile = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", \
true )) + "instags"; \
+ otrl_instag_generate(OtrlChatInterface::self()->getUserstate(), \
storeFile.toLocal8Bit(), accountname, protocol); +}
+
+void OtrlChatInterface::timer_control(void *opdata, unsigned int interval) {
+ Q_UNUSED(opdata)
+ if (interval > 0) {
+ OtrlChatInterface::self()->m_forwardSecrecyTimer.start(interval * 1000);
+ } else {
+ OtrlChatInterface::self()->m_forwardSecrecyTimer.stop();
+ }
+}
+
+OtrlMessageAppOps OtrlChatInterface::ui_ops = {
+ OtrlChatInterface::policy,
+ OtrlChatInterface::create_privkey,
+ OtrlChatInterface::is_logged_in,
+ OtrlChatInterface::inject_message,
+ OtrlChatInterface::update_context_list,
+ OtrlChatInterface::new_fingerprint,
+ OtrlChatInterface::write_fingerprints,
+ OtrlChatInterface::gone_secure,
+ OtrlChatInterface::gone_insecure,
+ OtrlChatInterface::still_secure,
+ OtrlChatInterface::max_message_size,
+ NULL, /* account_name */
+ NULL, /* account_name_free */
+ NULL, /* received symkey */
+ OtrlChatInterface::otr_error_message,
+ OtrlChatInterface::otr_error_message_free,
+ OtrlChatInterface::resent_msg_prefix,
+ OtrlChatInterface::resent_msg_prefix_free,
+ OtrlChatInterface::handle_smp_event,
+ OtrlChatInterface::handle_msg_event,
+ OtrlChatInterface::create_instag,
+ NULL, /* convert_data */
+ NULL, /* convert_data_free */
+ OtrlChatInterface::timer_control
};
/*********************** Gui_UI_Ops finished *************************/
@@ -338,25 +515,31 @@ static OtrlMessageAppOps ui_ops = {
/*********************** Constructor/Destructor **********************/
-OtrlChatInterface::OtrlChatInterface(){
+OtrlChatInterface::OtrlChatInterface():
+ m_keyGenThread(0)
+{
mSelf = this;
- OTRL_INIT;
+ OTRL_INIT;
userstate = otrl_userstate_create();
QString readPath = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", \
true )) + "privkeys"; otrl_privkey_read( userstate, readPath.toLocal8Bit() );
-
-
- QString savePath = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", \
true )) + "fingerprints";
- otrl_privkey_read_fingerprints(userstate, savePath.toLocal8Bit(), NULL, NULL);
+ unsigned int interval = otrl_message_poll_get_default_interval(userstate);
+ m_forwardSecrecyTimer.start(interval * 1000);
+ QObject::connect(&m_forwardSecrecyTimer, SIGNAL(timeout()), this, \
SLOT(otrlMessagePoll())); +
+ readPath = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + \
"fingerprints"; + otrl_privkey_read_fingerprints(userstate, readPath.toLocal8Bit(), \
NULL, NULL); +
+ readPath = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true)) + \
"instags"; + otrl_instag_read(userstate, readPath.toLocal8Bit());
}
OtrlChatInterface::~ OtrlChatInterface(){
otrl_userstate_free(userstate);
}
-
OtrlChatInterface *OtrlChatInterface::self(){
if( !mSelf ){
new OtrlChatInterface();
@@ -375,159 +558,59 @@ OtrlUserState OtrlChatInterface::getUserstate(){
}
-int OtrlChatInterface::decryptMessage( QString *msg, const QString &accountId,
- const QString &protocol, const QString &contactId , Kopete::ChatSession \
*chatSession){
-
- int ignoremessage;
- char *newMessage = NULL;
- OtrlTLV *tlvs = NULL;
- OtrlTLV *tlv = NULL;
- ConnContext *context;
- NextExpectedSMP nextMsg;
-
- ignoremessage = otrl_message_receiving( userstate, &ui_ops, chatSession, \
accountId.toLocal8Bit(), protocol.toLocal8Bit(), contactId.toLocal8Bit(), \
msg->toLocal8Bit(), &newMessage, &tlvs, NULL, NULL ); +int \
OtrlChatInterface::decryptMessage( Kopete::Message &message){
- tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED);
- if( tlv ){
- Kopete::Message msg( chatSession->members().first(), \
chatSession->account()->myself() );
- msg.setHtmlBody( i18n("<b>%1</b> has ended the OTR session. You should do the \
same.",chatSession->members().first()->contactId() ) );
- msg.setDirection( Kopete::Message::Internal );
- chatSession->appendMessage( msg );
- OtrlChatInterface::self()->emitGoneSecure( chatSession, 3 );
+ if (m_blackistIds.contains(message.id())) {
+ m_blackistIds.removeAll(message.id());
+ return 1;
}
- context = otrl_context_find( userstate, contactId.toLocal8Bit(), \
accountId.toLocal8Bit(), protocol.toLocal8Bit(), 0, NULL, NULL, \
NULL);
- if (context) {
- nextMsg = context->smstate->nextExpected;
+ Kopete::ChatSession *chatSession = message.manager();
+ QString accountId = chatSession->account()->accountId();
+ QString protocol = chatSession->protocol()->displayName();
+ QString contactId = message.from()->contactId();
+ QString body = message.plainBody();
+ OtrlTLV *tlvs = NULL;
+ char *newMessage = NULL;
- if (context->smstate->sm_prog_state == OTRL_SMP_PROG_CHEATED) {
- abortSMP(context, chatSession);
- context->smstate->nextExpected = OTRL_SMP_EXPECT1;
- context->smstate->sm_prog_state = OTRL_SMP_PROG_OK;
- } else {
- tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q);
- if (tlv) {
- if (nextMsg != OTRL_SMP_EXPECT1){
- kDebug(14318) << "Abording SMP: 1Q";
- abortSMP( context, chatSession );
- } else {
- kDebug(14318) << "Update SMP state: 1Q";
- new AuthenticationWizard( chatSession->view(true)->mainWidget(), context, \
chatSession, false, QString((char*)tlvs->data) );
- }
- }
+ if (m_keyGenThread != 0) {
+ // Currently generating the private key... must be a plaintext message anyways...
- tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1);
- if (tlv) {
- if (nextMsg != OTRL_SMP_EXPECT1){
- kDebug(14318) << "Abording SMP: 1";
- abortSMP( context, chatSession );
- } else {
- kDebug(14318) << "Update SMP state: 1 ";
- new AuthenticationWizard( chatSession->view(true)->mainWidget(), context, \
chatSession, false );
- }
- }
- tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2);
- if (tlv) {
- if (nextMsg != OTRL_SMP_EXPECT2){
- kDebug(14318) << "Abording SMP: 2";
- abortSMP( context, chatSession );
- } else {
- kDebug(14318) << "Update SMP state: 2 -> 3";
- AuthenticationWizard::findWizard(chatSession)->nextState();
- context->smstate->nextExpected = OTRL_SMP_EXPECT4;
- }
+ if (otrl_proto_message_type(body.toLatin1()) == OTRL_MSGTYPE_DATA) {
+ // an OTR message while we are generating the key... cache the message and replay \
once the key is generated... + connect(message.manager(), \
SIGNAL(closing(Kopete::ChatSession*)), \
SLOT(chatSessionDestroyed(Kopete::ChatSession*))); \
+ m_storedMessages.append(message); }
- tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3);
- if (tlv) {
- if (nextMsg != OTRL_SMP_EXPECT3){
- kDebug(14318) << "Abording SMP: 3";
- abortSMP( context, chatSession );
- } else {
- kDebug(14318) << "SMP: 3";
- if(context->smstate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED){
- if (context->active_fingerprint->trust && \
context->active_fingerprint->trust[0]) {
- AuthenticationWizard::findWizard(chatSession)->finished(true, true);
- kDebug(14318) << "trust found";
- Kopete::Message msg( chatSession->members().first(), \
chatSession->account()->myself() );
- msg.setHtmlBody( i18n("Authentication with <b>%1</b> successful. The \
conversation is now secure.", \
formatContact(chatSession->members().first()->contactId())));
- msg.setDirection( Kopete::Message::Internal );
- chatSession->appendMessage( msg );
- OtrlChatInterface::self()->emitGoneSecure( chatSession, 2 );
- } else {
- AuthenticationWizard::findWizard(chatSession)->finished(true, false);
- kDebug(14318) << "trust _NOT_ found";
- Kopete::Message msg( chatSession->members().first(), \
chatSession->account()->myself() );
- msg.setHtmlBody( i18n("<b>%1</b> has successfully authenticated you. You may \
want to authenticate this contact as well by asking your own question.", \
formatContact(chatSession->members().first()->contactId())));
- msg.setDirection( Kopete::Message::Internal );
- chatSession->appendMessage( msg );
- OtrlChatInterface::self()->emitGoneSecure( chatSession, 1 );
- }
-
- } else {
- AuthenticationWizard::findWizard(chatSession)->finished(false, false);
- Kopete::Message msg( chatSession->members().first(), \
chatSession->account()->myself() );
- msg.setHtmlBody( i18n("Authentication with <b>%1</b> failed. The conversation \
is now insecure.", \
formatContact(chatSession->members().first()->contactId())));
- msg.setDirection( Kopete::Message::Internal );
- chatSession->appendMessage( msg );
- OtrlChatInterface::self()->emitGoneSecure( chatSession, 1 );
-
- }
- context->smstate->nextExpected = OTRL_SMP_EXPECT1;
- }
- }
- tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4);
- if (tlv) {
- if (nextMsg != OTRL_SMP_EXPECT4) {
- kDebug(14318) << "Abording SMP: 4";
- abortSMP( context, chatSession );
- } else {
- kDebug(14318) << "SMP: 4";
- if (context->active_fingerprint->trust && context->active_fingerprint->trust[0]) \
{
- AuthenticationWizard::findWizard(chatSession)->finished(true, true);
- kDebug(14318) << "trust found";
- Kopete::Message msg( chatSession->members().first(), \
chatSession->account()->myself() );
- msg.setHtmlBody( i18n("<b>Authentication successful. The conversation is now \
secure.</b>") );
- msg.setDirection( Kopete::Message::Internal );
- chatSession->appendMessage( msg );
- OtrlChatInterface::self()->emitGoneSecure( chatSession, 2 );
- } else {
- AuthenticationWizard::findWizard(chatSession)->finished(false, false);
- kDebug(14318) << "trust _NOT_ found";
- Kopete::Message msg( chatSession->members().first(), \
chatSession->account()->myself() );
- msg.setHtmlBody( i18n("<b>Authentication failed. Note that the conversation is \
now insecure.</b>") );
- msg.setDirection( Kopete::Message::Internal );
- chatSession->appendMessage( msg );
- OtrlChatInterface::self()->emitGoneSecure( chatSession, 1 );
- }
- context->smstate->nextExpected = OTRL_SMP_EXPECT1;
- }
- }
- tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT);
- if (tlv) {
- kDebug(14318) << "other end aborted SMP";
+ return 1;
+ }
+
+ int ignoremessage = otrl_message_receiving( userstate, &ui_ops, chatSession, \
accountId.toLocal8Bit(), protocol.toLocal8Bit(), contactId.toLocal8Bit(), \
body.toLocal8Bit(), &newMessage, &tlvs, NULL, NULL, NULL ); +
+ ConnContext *context = otrl_context_find( userstate, contactId.toLocal8Bit(), \
accountId.toLocal8Bit(), protocol.toLocal8Bit(), 0, 0, NULL, NULL, NULL); + if \
(context) { + OtrlTLV *tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED);
+ if( tlv ){
Kopete::Message msg( chatSession->members().first(), \
chatSession->account()->myself() );
- msg.setHtmlBody( i18n("<b>Authentication error.</b>") );
+ msg.setHtmlBody( i18n("<b>%1</b> has ended the OTR session. You should do the \
same.",chatSession->members().first()->contactId() ) ); msg.setDirection( \
Kopete::Message::Internal ); chatSession->appendMessage( msg );
- AuthenticationWizard *currentWizard = \
AuthenticationWizard::findWizard(chatSession);
- if(currentWizard){
- currentWizard->aborted();
- }
- context->smstate->nextExpected = OTRL_SMP_EXPECT1;
+ OtrlChatInterface::self()->emitGoneSecure( chatSession, 3 );
+
+ otrl_tlv_free(tlvs);
}
-
- otrl_tlv_free(tlvs);
- }
+
}
-
+
// message is now decrypted or is a Plaintext message and ready to deliver
if( !ignoremessage ){
// message is decrypted
if( newMessage != NULL ){
- *msg = QString::fromUtf8(newMessage);
+ body = QString::fromUtf8(newMessage);
otrl_message_free( newMessage );
- msg->replace( QString('\n'), QString("<br>") );
+ body.replace( QString('\n'), QString("<br>") );
+ message.setHtmlBody( body );
+
return 0; // message is decrypted and ready to deliver
} else {
return 1; // message was a plaintext message. Better not touching it :)
@@ -536,75 +619,95 @@ int OtrlChatInterface::decryptMessage( QString *msg, const \
QString &accountId, return 2; // internal OTR message. Ignore it.
}
-int OtrlChatInterface::encryptMessage( QString *msg, const QString &accountId,
- const QString &protocol, const QString &contactId , Kopete::ChatSession \
*chatSession ){
- int err;
+int OtrlChatInterface::encryptMessage( Kopete::Message &message ){
char *newMessage = 0;
- char *fragment = 0;
- if( otrl_proto_message_type( msg->toLocal8Bit() ) == OTRL_MSGTYPE_NOTOTR ){
-// msg->replace( QString('<'), QString("<") );
- err = otrl_message_sending( userstate, &ui_ops, chatSession, \
accountId.toLocal8Bit(), protocol.toLocal8Bit(), contactId.toLocal8Bit(), \
msg->toUtf8(), NULL, &newMessage, NULL, NULL );
-
+ QString msgBody;
+ bool plaintext = message.format() == Qt::PlainText;
+
+ if(plaintext){
+ msgBody = message.plainBody().replace('<', "<");
+ } else {
+ msgBody = message.escapedBody();
+ }
+
+ Kopete::ChatSession *chatSession = message.manager();
+ QString accountId = chatSession->account()->accountId();
+ QString protocol = chatSession->protocol()->displayName();
+ QString contactId = message.to().first()->contactId();
+
+ if( otrl_proto_message_type( msgBody.toLocal8Bit() ) == OTRL_MSGTYPE_NOTOTR ){
+
+ otrl_instag_t instance = message.manager()->property("otr-instag").toUInt();
+
+ int err = otrl_message_sending( userstate, &ui_ops, chatSession, \
accountId.toLocal8Bit(), protocol.toLocal8Bit(), contactId.toLocal8Bit(), instance, \
msgBody.toUtf8(), NULL, &newMessage, OTRL_FRAGMENT_SEND_ALL_BUT_LAST, NULL, NULL, \
NULL ); +
if( err != 0 ){
+ message.setPlainBody(i18n("An error occurred while encrypting the message."));
return -1;
- } else if( newMessage ){
-
- /* Fragment the message if needed */
- /* If fragmentation is needed libotr will send out all fragments but the last \
one. */
- ConnContext *context = otrl_context_find(userstate, contactId.toLocal8Bit(), \
accountId.toLocal8Bit(), protocol.toLocal8Bit(), 0, NULL, NULL, NULL); + } else if \
(newMessage) { + msgBody = QString::fromUtf8(newMessage);
+ otrl_message_free(newMessage);
+ }
- //kDebug(14318) << "message to be sent out: " << newMessage;
- err = otrl_message_fragment_and_send(&ui_ops, chatSession, context, newMessage,
- OTRL_FRAGMENT_SEND_ALL_BUT_LAST, &fragment);
+ OtrlMessageType type = otrl_proto_message_type( msgBody.toLatin1() );
+ if( type == OTRL_MSGTYPE_TAGGEDPLAINTEXT ){
+ kDebug(14318) << "Tagged plaintext!";
-// kDebug(14318) << "fragment left to be sent by kopete: " << fragment;
+ /* Here we have a problem... libotr tags messages with whitespaces to
+ be recognized by other clients. Those whitespaces are discarded
+ if we use setHtmlBody() and breaks opportunistic mode.
+ If we use setPlainBody() for messages containing tags, those tags
+ are escaped and will be visible in the other sides chatwindow.
- if( err != 0){
- *msg = i18n("Encryption error");
- } else if ( fragment ){
- *msg = QString::fromUtf8( fragment );
- otrl_message_free( newMessage );
- otrl_message_free( fragment );
- }
- OtrlMessageType type = otrl_proto_message_type( msg->toLocal8Bit() );
- if( type == OTRL_MSGTYPE_TAGGEDPLAINTEXT ){
- return 1; // Message is still plaintext, but tagged for opportunistic mode
+ This approach should always send out correct messages but will
+ break opportunistic mode if the user enables RTF formatting.
+ Sorry folks. No way to deal with this currently (Would need changes
+ in the rich text handling in libkopete).
+ */
+ if(plaintext){
+ message.setPlainBody(msgBody);
+ } else {
+ message.setHtmlBody(msgBody);
}
- return 0; // Encrypted successfully
+ return 1;
}
+
+ // Always set plaintext if the message has been encrypted.
+ // The parser wouldn't understand anything after encryption anyways...
+ message.setPlainBody( msgBody );
+ message.setType(Kopete::Message::TypeNormal);
+ return 0;
}
-
+
return 2; // Message is still plaintext. Better not touching it
}
QString OtrlChatInterface::getDefaultQuery( const QString &accountId ){
char *message;
- message = otrl_proto_default_query_msg( accountId.toLatin1(), OTRL_POLICY_ALLOW_V2 \
); + message = otrl_proto_default_query_msg( accountId.toLatin1(), \
OTRL_POLICY_ALLOW_V3 | OTRL_POLICY_ALLOW_V2 ); QString msg( message );
otrl_message_free( message );
return msg;
}
void OtrlChatInterface::disconnectSession( Kopete::ChatSession *chatSession ){
- otrl_message_disconnect( userstate, &ui_ops, chatSession, \
chatSession->account()->accountId().toLatin1(), \
chatSession->account()->protocol()->displayName().toLatin1(), \
chatSession->members().first()->contactId().toLocal8Bit() ); + otrl_instag_t instance \
= chatSession->property("otr-instag").toUInt(); + otrl_message_disconnect( userstate, \
&ui_ops, chatSession, chatSession->account()->accountId().toLatin1(), \
chatSession->account()->protocol()->displayName().toLatin1(), \
chatSession->members().first()->contactId().toLocal8Bit(), instance); \
OtrlChatInterface::self()->emitGoneSecure( chatSession, 0 );
Kopete::Message msg( chatSession->account()->myself(), \
chatSession->members().first() ); msg.setPlainBody( i18n("Terminating OTR session.") \
); msg.setDirection( Kopete::Message::Internal );
-// msg.setBody( QString( message ), Kopete::Message::RichText );
chatSession->appendMessage( msg );
-
}
bool OtrlChatInterface::shouldDiscard( const QString &message ){
if( !message.isEmpty() && !message.isNull() ){
-// kDebug(14318) << otrl_proto_message_type( message.toLatin1() );
switch( otrl_proto_message_type( message.toLatin1() ) ){
case OTRL_MSGTYPE_TAGGEDPLAINTEXT:
-// case OTRL_MSGTYPE_UNKNOWN: // Fragmented messages seem to be type UNKNOWN
+ //case OTRL_MSGTYPE_UNKNOWN: // Fragmented messages seem to be type UNKNOWN
case OTRL_MSGTYPE_NOTOTR:
return false;
default:
@@ -622,33 +725,35 @@ void OtrlChatInterface::setPolicy( OtrlPolicy policy ){
int OtrlChatInterface::privState( Kopete::ChatSession *session ){
- ConnContext *context;
-
- context = otrl_context_find(userstate, \
session->members().first()->contactId().toLocal8Bit(), \
session->account()->accountId().toLocal8Bit(), \
session->account()->protocol()->displayName().toLocal8Bit(), 0, NULL, NULL, NULL); \
+ otrl_instag_t instance = session->property("otr-instag").toUInt(); + if (instance \
== 0) { + instance = OTRL_INSTAG_BEST;
+ }
+ ConnContext *context = otrl_context_find(userstate, \
session->members().first()->contactId().toLocal8Bit(), \
session->account()->accountId().toLocal8Bit(), \
session->account()->protocol()->displayName().toLocal8Bit(), instance, 0, NULL, NULL, \
NULL);
if( context ){
switch( context->msgstate ){
- case OTRL_MSGSTATE_PLAINTEXT:
- return 0;
- case OTRL_MSGSTATE_ENCRYPTED:
- if( context->active_fingerprint->trust && context->active_fingerprint->trust[0] \
!= '\0' )
- return 2;
- else
- return 1;
- case OTRL_MSGSTATE_FINISHED:
- return 3;
+ case OTRL_MSGSTATE_PLAINTEXT:
+ return 0;
+ case OTRL_MSGSTATE_ENCRYPTED:
+ if( context->active_fingerprint->trust && context->active_fingerprint->trust[0] \
!= '\0' ) + return 2;
+ else
+ return 1;
+ case OTRL_MSGSTATE_FINISHED:
+ return 3;
}
}
return 0;
-}
+ }
+
+ QString OtrlChatInterface::formatContact(const QString &contactId){
-QString OtrlChatInterface::formatContact(const QString &contactId){
-
Kopete::MetaContact *metaContact = \
Kopete::ContactList::self()->findMetaContactByContactId(contactId); if( metaContact \
){ QString displayName = metaContact->displayName();
if((displayName != contactId) && !displayName.isNull()){
- return displayName + " (" + contactId + ')';
+ return displayName + " (" + contactId + ')';
}
}
return contactId;
@@ -657,7 +762,8 @@ QString OtrlChatInterface::formatContact(const QString \
&contactId){ void OtrlChatInterface::verifyFingerprint( Kopete::ChatSession *session \
){ ConnContext *context;
- context = otrl_context_find( userstate, \
session->members().first()->contactId().toLocal8Bit(), \
session->account()->accountId().toLocal8Bit(), \
session->protocol()->displayName().toLocal8Bit(), 0, NULL, NULL, NULL); \
+ otrl_instag_t instance = session->property("otr-instag").toUInt(); + context = \
otrl_context_find( userstate, session->members().first()->contactId().toLocal8Bit(), \
session->account()->accountId().toLocal8Bit(), \
session->protocol()->displayName().toLocal8Bit(), instance, 0, NULL, NULL, NULL);
new AuthenticationWizard( session->view()->mainWidget(), context, session, true );
}
@@ -665,33 +771,34 @@ void OtrlChatInterface::verifyFingerprint( Kopete::ChatSession \
*session ){ Fingerprint *OtrlChatInterface::findFingerprint( Kopete::ChatSession \
*session ){ ConnContext *context;
- for( context = userstate->context_root; context != NULL; context = context->next ){
- if( ( session->members().first()->contactId().toLocal8Bit() == context->username ) \
&&
- (session->account()->accountId().toLocal8Bit() == context->accountname ) ){
- return context->active_fingerprint ? context->active_fingerprint : NULL;
- }
+
+ otrl_instag_t instance = session->property("otr-instag").toUInt();
+ if (instance == 0) {
+ instance = OTRL_INSTAG_BEST;
+ }
+ context = otrl_context_find( userstate, \
session->members().first()->contactId().toLocal8Bit(), \
session->account()->accountId().toLocal8Bit(), \
session->protocol()->displayName().toLocal8Bit(), instance, 0, NULL, NULL, NULL); \
+ if (context && context->active_fingerprint && \
context->active_fingerprint->fingerprint) { + return context->active_fingerprint;
}
return NULL;
}
-QString OtrlChatInterface::findActiveFingerprint( Kopete::ChatSession *session ){
- ConnContext *context;
+QString OtrlChatInterface::fingerprint( Kopete::ChatSession *session ){
char hash[45];
+ memset(hash, 0, 45);
- for( context = userstate->context_root; context != NULL; context = context->next ){
- if( ( session->members().first()->contactId().toLocal8Bit() == context->username ) \
&&
- (session->account()->accountId().toLocal8Bit() == context->accountname ) ){
- otrl_privkey_hash_to_human( hash, context->active_fingerprint->fingerprint );
- return hash;
- }
+ Fingerprint *fp = findFingerprint(session);
+ if (fp) {
+ otrl_privkey_hash_to_human( hash, fp->fingerprint );
+ return QLatin1String(hash);
+ }
+
+ return QString();
}
- return NULL;
-}
-bool OtrlChatInterface::isVerified( Kopete::ChatSession *session ){
+ bool OtrlChatInterface::isVerified( Kopete::ChatSession *session ){
Fingerprint *fingerprint = findFingerprint( session );
- kDebug() << "fingerprint" << fingerprint;
if( fingerprint->trust && fingerprint->trust[0] != '\0' ){
return true;
} else {
@@ -710,7 +817,7 @@ void OtrlChatInterface::checkFilePermissions( const QString &file \
){ privkeysInfo.permission( QFile::ReadOther ) |
privkeysInfo.permission( QFile::WriteOther ) |
privkeysInfo.permission( QFile::ExeOther ) ){
- chmod( file.toLocal8Bit(), 0600);
+ chmod( file.toLocal8Bit(), 0600);
}
}
@@ -738,6 +845,17 @@ void OtrlChatInterface::setTrust( Kopete::ChatSession *session, \
bool trust ){ }
}
+void OtrlChatInterface::generatePrivateKey(const QString &account, const QString \
&protocol) +{
+ m_keyGenThread = new KeyGenThread ( account.toLatin1(), protocol.toLatin1() );
+ m_keyGenThread->start();
+ while( !m_keyGenThread->wait(100) ){
+ qApp->processEvents(QEventLoop::ExcludeUserInputEvents | \
QEventLoop::ExcludeSocketNotifiers, 100); + }
+ m_keyGenThread->deleteLater();
+ m_keyGenThread = 0;
+}
+
/****************** SMP implementations ****************/
void OtrlChatInterface::abortSMP( ConnContext *context, Kopete::ChatSession *session \
){ @@ -753,7 +871,6 @@ void OtrlChatInterface::abortSMP( ConnContext *context, \
Kopete::ChatSession *ses }
void OtrlChatInterface::initSMP( ConnContext *context, Kopete::ChatSession *session, \
const QString &secret){
- context = otrl_context_find( userstate, \
session->members().first()->contactId().toLocal8Bit(), \
session->account()->accountId().toLocal8Bit(), \
session->protocol()->displayName().toLocal8Bit(), 0, NULL, NULL, NULL); \
otrl_message_initiate_smp( userstate, &ui_ops, session, context, (unsigned \
char*)secret.toLocal8Bit().data(), secret.length() );
Kopete::Message msg( session->members().first(), session->account()->myself() );
@@ -761,11 +878,9 @@ void OtrlChatInterface::initSMP( ConnContext *context, \
Kopete::ChatSession *sess msg.setDirection( Kopete::Message::Internal );
session->appendMessage( msg );
-
}
void OtrlChatInterface::initSMPQ( ConnContext *context, Kopete::ChatSession \
*session, const QString &question, const QString &secret){
- context = otrl_context_find( userstate, \
session->members().first()->contactId().toLocal8Bit(), \
session->account()->accountId().toLocal8Bit(), \
session->protocol()->displayName().toLocal8Bit(), 0, NULL, NULL, NULL); \
otrl_message_initiate_smp_q( userstate, &ui_ops, session, context, (const \
char*)question.toLocal8Bit().data(), (unsigned char*)secret.toLocal8Bit().data(), \
secret.length() );
Kopete::Message msg( session->members().first(), session->account()->myself() );
@@ -777,7 +892,7 @@ void OtrlChatInterface::initSMPQ( ConnContext *context, \
Kopete::ChatSession *ses
void OtrlChatInterface::respondSMP( ConnContext *context, Kopete::ChatSession \
*session, const QString &secret ){
- kDebug(14318) << "resonding SMP";
+ kDebug(14318) << "resonding SMP";
otrl_message_respond_smp( userstate, &ui_ops, session, context, (unsigned \
char*)secret.toLocal8Bit().data(), secret.length());
@@ -788,6 +903,29 @@ void OtrlChatInterface::respondSMP( ConnContext *context, \
Kopete::ChatSession *s session->appendMessage( msg );
}
+void OtrlChatInterface::otrlMessagePoll()
+{
+ otrl_message_poll(userstate, 0, 0);
+}
+
+void OtrlChatInterface::replayStoredMessages()
+{
+ while (m_storedMessages.isEmpty()) {
+ Kopete::Message msg = m_storedMessages.takeFirst();
+ msg.manager()->appendMessage(msg);
+ }
+}
+
+void OtrlChatInterface::chatSessionDestroyed(Kopete::ChatSession *chatSession)
+{
+ QList<Kopete::Message> tmpList;
+ foreach (const Kopete::Message &msg, m_storedMessages) {
+ if (msg.manager() != chatSession) {
+ tmpList.append(msg);
+ }
+ }
+ m_storedMessages = tmpList;
+}
/****************** KeyGenThread *******************/
KeyGenThread::KeyGenThread( const QString &accountname, const QString &protocol ){
@@ -802,3 +940,4 @@ void KeyGenThread::run()
otrl_privkey_generate(OtrlChatInterface::self()->getUserstate(), \
storeFile.toLocal8Bit(), accountname.toLocal8Bit(), protocol.toLocal8Bit()); \
OtrlChatInterface::self()->checkFilePermissions( \
QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkeys" ); \
} +
diff --git a/plugins/otr/otrlchatinterface.h b/plugins/otr/otrlchatinterface.h
index 5bb6e1d..9ba844c 100644
--- a/plugins/otr/otrlchatinterface.h
+++ b/plugins/otr/otrlchatinterface.h
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
+ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@@ -28,6 +28,8 @@
#include <qstring.h>
#include <qthread.h>
#include <qmutex.h>
+#include <qmetatype.h>
+#include <qtimer.h>
#include <kopete_export.h>
#include <kopetechatsession.h>
@@ -42,6 +44,9 @@ extern "C" {
#include <libotr/userstate.h>
}
+Q_DECLARE_METATYPE(otrl_instag_t)
+
+class KeyGenThread;
class KOPETE_OTR_SHARED_EXPORT OtrlChatInterface: public QObject
{
@@ -50,19 +55,17 @@ public:
~OtrlChatInterface();
static OtrlChatInterface *self();
- int decryptMessage( QString *msg, const QString &accountId, const QString \
&protocol, const QString &contactId, Kopete::ChatSession *chatSession \
);
- int encryptMessage( QString *msg, const QString &accountId,
- const QString &protocol, const QString &contactId , Kopete::ChatSession \
*chatSession ); + int decryptMessage( Kopete::Message &message );
+ int encryptMessage( Kopete::Message &message );
QString getDefaultQuery( const QString &accountId );
void disconnectSession( Kopete::ChatSession *chatSession );
void setPolicy( OtrlPolicy policy );
bool shouldDiscard( const QString &message );
OtrlUserState getUserstate();
int privState( Kopete::ChatSession *session );
- QString formatContact( const QString &contactId);
bool isVerified( Kopete::ChatSession *session );
void checkFilePermissions( const QString &file );
- QString findActiveFingerprint( Kopete::ChatSession *session );
+ QString fingerprint( Kopete::ChatSession *session );
void verifyFingerprint( Kopete::ChatSession *session );
void setPlugin(Kopete::Plugin *plugin);
void emitGoneSecure(Kopete::ChatSession *sesseion, int state);
@@ -71,17 +74,49 @@ public:
void initSMPQ( ConnContext *context, Kopete::ChatSession *session, const QString \
&question, const QString &secret ); void respondSMP( ConnContext *context, \
Kopete::ChatSession *session, const QString &secret ); void setTrust( \
Kopete::ChatSession *session, bool trust ); + void generatePrivateKey(const QString \
&account, const QString &protocol);
+ static QString formatContact( const QString &contactId);
private:
OtrlChatInterface();
static OtrlChatInterface *mSelf;
Fingerprint *findFingerprint( Kopete::ChatSession *session );
+ QList<uint> m_blackistIds;
+ KeyGenThread *m_keyGenThread;
+ QTimer m_forwardSecrecyTimer;
+ QList<Kopete::Message> m_storedMessages;
+
+ static OtrlMessageAppOps ui_ops;
+ static OtrlPolicy policy(void *opdata, ConnContext *context);
+ static void create_privkey(void *opdata, const char *accountname, const char \
*protocol); + static int is_logged_in(void *opdata, const char *accountname, const \
char *protocol, const char *recipient); + static void inject_message( void *opdata, \
const char *accountname, const char *protocol, const char *recipient, const char \
*message ); + static void update_context_list(void *opdata);
+ static void new_fingerprint(void *opdata, OtrlUserState us, const char \
*accountname, const char *protocol, const char *username, unsigned char \
fingerprint[20]); + static void write_fingerprints(void *opdata);
+ static void gone_secure(void *opdata, ConnContext *context);
+ static void gone_insecure(void *opdata, ConnContext *context);
+ static void still_secure(void *opdata, ConnContext *context, int is_reply);
+ static int max_message_size(void *opdata, ConnContext *context);
+ static const char* otr_error_message(void *opdata, ConnContext *context, \
OtrlErrorCode err_code); + static void otr_error_message_free(void *opdata, const \
char *err_msg); + static const char *resent_msg_prefix(void *opdata, ConnContext \
*context); + static void resent_msg_prefix_free(void *opdata, const char *prefix);
+ static void handle_msg_event(void *opdata, OtrlMessageEvent msg_event, ConnContext \
*context, const char* message, gcry_error_t err); + static void handle_smp_event(void \
*opdata, OtrlSMPEvent smp_event, ConnContext *context, unsigned short \
progress_percent, char *question); + static void create_instag(void *opdata, const \
char *accountname, const char *protocol); + static void timer_control(void *opdata, \
unsigned int interval); +
+private slots:
+ void otrlMessagePoll();
+ void replayStoredMessages();
+ void chatSessionDestroyed(Kopete::ChatSession *chatSession);
signals:
void goneSecure(Kopete::ChatSession* session, int state);
};
- class KeyGenThread : public QThread {
+class KeyGenThread : public QThread {
private:
QString accountname;
diff --git a/plugins/otr/otrlconfinterface.cpp b/plugins/otr/otrlconfinterface.cpp
index 7d58462..692189b 100644
--- a/plugins/otr/otrlconfinterface.cpp
+++ b/plugins/otr/otrlconfinterface.cpp
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
+ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@@ -83,11 +83,7 @@ void OtrlConfInterface::generateNewPrivKey( const QString \
&accountId, const QStr popup->show();
popup->setCloseLock( true );
- KeyGenThread *keyGenThread = new KeyGenThread ( accountId, protocol );
- keyGenThread->start();
- while( !keyGenThread->wait(100) ){
- qApp->processEvents(QEventLoop::ExcludeUserInputEvents | \
QEventLoop::ExcludeSocketNotifiers, 100);
- }
+ OtrlChatInterface::self()->generatePrivateKey(accountId, protocol);
popup->setCloseLock( false );
popup->close();
diff --git a/plugins/otr/otrlconfinterface.h b/plugins/otr/otrlconfinterface.h
index 0cfdf29..f619c56 100644
--- a/plugins/otr/otrlconfinterface.h
+++ b/plugins/otr/otrlconfinterface.h
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
+ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
diff --git a/plugins/otr/otrplugin.cpp b/plugins/otr/otrplugin.cpp
index ef973ed..50b2d7c 100644
--- a/plugins/otr/otrplugin.cpp
+++ b/plugins/otr/otrplugin.cpp
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
+ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@@ -153,68 +153,23 @@ void OTRPlugin::slotNewChatSessionWindow( Kopete::ChatSession \
*KMM ) void OTRPlugin::slotOutgoingMessage( Kopete::Message& msg )
{
if( msg.direction() == Kopete::Message::Outbound ){
- QString accountId = msg.manager()->account()->accountId();
- Kopete::Contact *contact = msg.to().first();
-
- QString msgBody;
- QString cacheBody;
- bool plaintext = msg.format() == Qt::PlainText;
- kDebug(14318) << "Message format is" << (plaintext ? "plaintext" : "richtext");
- if(plaintext){
- msgBody = msg.plainBody().replace('<', "<");
- cacheBody = msgBody;
- } else {
- msgBody = msg.escapedBody();
- cacheBody = msgBody;
- }
- kDebug(14318) << "Outgoing message before processing:" << msgBody << "escaped" << \
Kopete::Message::escape(msgBody);
- int encryptionState = otrlChatInterface->encryptMessage( &msgBody, accountId, \
msg.manager()->account()->protocol()->displayName(), contact->contactId(), \
msg.manager() );
-
- if(encryptionState == -1){
- // Failure. Shouldn't happen. However, if it does DON'T
- // send the message out in plaintext. overwrite with something else...
- msg.setPlainBody(i18n("An error occurred while encrypting the message."));
-
- } else if(encryptionState == 0){
- kDebug(14318) << "Encrypted successfully";
-
- // Always set plaintext if the message has been encrypted.
- // The parser wouldn't understand anything after encryption anyways...
- msg.setPlainBody( msgBody );
- msg.setType(Kopete::Message::TypeNormal);
- if( !msg.plainBody().isEmpty() ){
- messageCache.insert( msgBody, cacheBody );
- } else {
- messageCache.insert( "!OTR:MsgDelByOTR", cacheBody );
- }
- } else if(encryptionState == 1){
- kDebug(14318) << "Tagged plaintext!";
-
- /* Here we have a problem... libotr tags messages with whitespaces to
- be recognized by other clients. Those whitespaces are discarded
- if we use setHtmlBody() and breaks opportunistic mode.
- If we use setPlainBody() for messages containing tags, those tags
- are escaped and will be visible in the other sides chatwindow.
-
- This approach should always send out correct messages but will
- break opportunistic mode if the user enables RTF formatting.
- Sorry folks. No way to deal with this currently (Would need changes
- in the rich text handling in libkopete).
- */
- if(plaintext){
- msg.setPlainBody(msgBody);
- } else {
- msg.setHtmlBody(msgBody);
- }
-
- messageCache.insert( msgBody, cacheBody );
- } /* else {
- Don't touch msg If encryptionState is something else than above!!!
- } */
+ QString cacheBody;
+ if(msg.format() == Qt::PlainText){
+ cacheBody = msg.plainBody().replace('<', "<");
+ } else {
+ cacheBody = msg.escapedBody();
+ }
+ otrlChatInterface->encryptMessage( msg );
+
+ if( !msg.plainBody().isEmpty() ){
+ messageCache.insert( msg.plainBody(), cacheBody );
+ } else {
+ messageCache.insert( "!OTR:MsgDelByOTR", cacheBody );
+ }
- kDebug(14318) << "Outgoing message after processing:" << msgBody << msg.format();
+ kDebug(14318) << "Outgoing message after processing:" << msg.plainBody() << \
msg.format(); }
}
@@ -287,23 +242,22 @@ void OtrMessageHandler::handleMessage( Kopete::MessageEvent \
*event ){ return;
}
+
Kopete::Message msg = event->message();
// Kopete::ChatSession *session = msg.manager();
QMap<QString, QString> messageCache = plugin->getMessageCache();
- if( msg.direction() == Kopete::Message::Inbound ){
- if( msg.type() == Kopete::Message::TypeFileTransferRequest )
+ kDebug(14318) << "OtrMessageHandler::handleMessage:" << msg.plainBody();
+
+ if( msg.direction() == Kopete::Message::Inbound){
+ if( msg.type() == Kopete::Message::TypeFileTransferRequest )
{
// file transfers aren't encrypted. Proceed with next plugin
MessageHandler::handleMessage( event );
return;
}
- QString body = msg.plainBody();
- QString accountId = msg.manager()->account()->accountId();
- QString contactId = msg.from()->contactId();
- int retValue = OtrlChatInterface::self()->decryptMessage( &body, accountId, \
msg.manager()->account()->protocol()->displayName(), contactId, \
msg.manager() );
- msg.setHtmlBody( body );
- if( (retValue == 2) | OtrlChatInterface::self()->shouldDiscard( msg.plainBody() ) \
){ + int retValue = OtrlChatInterface::self()->decryptMessage( msg );
+ if( (retValue == 2) | OtrlChatInterface::self()->shouldDiscard( \
msg.plainBody() ) ){ // internal OTR message
event->discard();
return;
diff --git a/plugins/otr/otrplugin.h b/plugins/otr/otrplugin.h
index 35ecb7b..21cff35 100644
--- a/plugins/otr/otrplugin.h
+++ b/plugins/otr/otrplugin.h
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
+ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
diff --git a/plugins/otr/otrpreferences.cpp b/plugins/otr/otrpreferences.cpp
index ece403a..08052d9 100644
--- a/plugins/otr/otrpreferences.cpp
+++ b/plugins/otr/otrpreferences.cpp
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
+ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
diff --git a/plugins/otr/otrpreferences.h b/plugins/otr/otrpreferences.h
index 7aa742c..9286cca 100644
--- a/plugins/otr/otrpreferences.h
+++ b/plugins/otr/otrpreferences.h
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
+ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
diff --git a/plugins/otr/privkeypopup.cpp b/plugins/otr/privkeypopup.cpp
index 3fea9e2..4fad8be 100644
--- a/plugins/otr/privkeypopup.cpp
+++ b/plugins/otr/privkeypopup.cpp
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
+ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
diff --git a/plugins/otr/privkeypopup.h b/plugins/otr/privkeypopup.h
index 4b271e9..442d9ab 100644
--- a/plugins/otr/privkeypopup.h
+++ b/plugins/otr/privkeypopup.h
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
+ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic