summaryrefslogtreecommitdiffstats
path: root/src/otrlchatinterface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/otrlchatinterface.cpp')
-rw-r--r--src/otrlchatinterface.cpp685
1 files changed, 685 insertions, 0 deletions
diff --git a/src/otrlchatinterface.cpp b/src/otrlchatinterface.cpp
new file mode 100644
index 0000000..85f1e7f
--- /dev/null
+++ b/src/otrlchatinterface.cpp
@@ -0,0 +1,685 @@
+/***************************************************************************
+ * Copyright (C) 2007 by Michael Zanetti
+ *
+ * *
+ * This program 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 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+
+/**
+ * @author Michael Zanetti
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <kopetechatsession.h>
+#include <kopeteaccount.h>
+#include <kopeteaccountmanager.h>
+#include <kopetemessageevent.h>
+#include <kopetecontactlist.h>
+#include <kopetemetacontact.h>
+#include <kopeteview.h>
+#include <kopeteprotocol.h>
+
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <klocale.h>
+#include <kprogress.h>
+#include <kpassivepopup.h>
+#include <kanimwidget.h>
+#include <kpushbutton.h>
+
+#include <qvbox.h>
+#include <qlabel.h>
+#include <qnamespace.h>
+#include <qeventloop.h>
+#include <qapplication.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qptrlist.h>
+
+#include "otrlchatinterface.h"
+#include "otrguiclient.h"
+#include "otrplugin.h"
+#include "privkeypopup.h"
+#include "smppopup.h"
+
+OtrlChatInterface *OtrlChatInterface::mSelf = 0;
+static OtrlUserState userstate;
+static OtrlPolicy confPolicy;
+static void *updateContextList = 0;
+
+/***************************** Gui_UI_Ops for libotr **********************************/
+static OtrlPolicy policy(void *opdata, ConnContext *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;
+ return OTRL_POLICY_NEVER;
+ }
+ QString policy = session->members().getFirst()->metaContact()->pluginData( OTRPlugin::plugin(), "otr_policy" );
+ switch( policy.toInt( &noerr, 10 ) ){
+ case 1:
+ return OTRL_POLICY_ALWAYS;
+ case 2:
+ return OTRL_POLICY_OPPORTUNISTIC;
+ case 3:
+ return OTRL_POLICY_MANUAL;
+ case 4:
+ return OTRL_POLICY_NEVER;
+ default:
+ return confPolicy;
+ }
+}
+
+static void create_privkey(void *opdata, const char *accountname, const char *protocol){
+
+ Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
+
+ PrivKeyPopup *popup = new PrivKeyPopup( session->view()->mainWidget(), i18n("Generating private key"), Qt::WStyle_Dialog | Qt::WStyle_StaysOnTop );
+ KAnimWidget *anim = new KAnimWidget( "kde", 72, popup->animFrame, "kopete" );
+ anim->start();
+ anim->show();
+
+ popup->setCloseLock( true );
+ popup->show();
+ KeyGenThread *keyGenThread = new KeyGenThread( accountname, protocol );
+ keyGenThread->start();
+ while( !keyGenThread->wait(100) ){
+ qApp->eventLoop()->processEvents(QEventLoop::ExcludeUserInput | QEventLoop::ExcludeSocketNotifiers, 100);
+ }
+ popup->setCloseLock( false );
+ popup->close();
+}
+
+static int is_logged_in(void *opdata, const char *accountname, const char *protocol, const char *recipient){
+ Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
+ Kopete::ContactPtrList list = session->members();
+ for ( QPtrListIterator<Kopete::Contact> it( list ); Kopete::Contact *contact = it.current(); ++it ){
+ if( contact->contactId().compare( recipient ) == 0 ){
+ Kopete::OnlineStatus status = session->contactOnlineStatus( contact );
+ if( status == Kopete::OnlineStatus::Unknown){
+ return -1;
+ } else if( status == Kopete::OnlineStatus::Offline ){
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+ }
+ return -1;
+}
+
+static void inject_message( void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message ){
+ //KMessageBox::information( NULL, QString(accountname) + ":" + QString(protocol) + ":" + QString(recipient) + ":" + QString(message) );
+ Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
+ Kopete::ContactPtrList list = session->members();
+ for ( QPtrListIterator<Kopete::Contact> it( list ); Kopete::Contact *contact = it.current(); ++it ){
+ if( contact->contactId().compare( recipient ) == 0 ){
+ Kopete::Message msg( session->account()->myself(), contact, QString( message ), Kopete::Message::Outbound );
+ session->sendMessage( msg );
+ return;
+ }
+ }
+}
+
+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){
+ 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 ){
+ Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
+ Kopete::ContactPtrList list = session->members();
+ for ( QPtrListIterator<Kopete::Contact> it( list ); Kopete::Contact *contact = it.current(); ++it ){
+ if( contact->contactId().compare( username ) == 0 ){
+ Kopete::Message msg( session->members().getFirst(), session->account()->myself(), QString( message ), Kopete::Message::Internal );
+ msg.setBody( QString( message ), Kopete::Message::RichText );
+ session->appendMessage( msg );
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void update_context_list(void *opdata){
+//Not used...
+}
+
+static const char *protocol_name(void *opdata, const char *protocol){
+//Never seen...
+ kdDebug() << "protocol_name called" << endl;
+}
+
+static void protocol_name_free(void *opdata, const char *protocol_name){
+//Never seen...
+ 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]){
+ kdDebug() << "Received a new Fingerprint" << endl;
+ Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
+ Kopete::Message msg( session->members().getFirst(), session->account()->myself(), i18n("<b>Received a new fingerprint from <a>%1</a>. You should authenticate this contact.</b>").arg( session->members().getFirst()->contactId() ), Kopete::Message::Internal, Kopete::Message::RichText );
+ session->appendMessage( msg );
+}
+
+static void write_fingerprints(void *opdata){
+ kdDebug() << "Writing fingerprints" << endl;
+ otrl_privkey_write_fingerprints( userstate, QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "fingerprints" );
+}
+
+static void gone_secure(void *opdata, ConnContext *context){
+ kdDebug() << "gone secure" << endl;
+ Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
+
+ if( context->active_fingerprint->trust && context->active_fingerprint->trust[0] ){
+ Kopete::Message msg( session->members().getFirst(), session->account()->myself(), i18n("<b>Private OTR session started.</b>"), Kopete::Message::Internal, Kopete::Message::RichText );
+ session->appendMessage( msg );
+ OTRPlugin::plugin()->emitGoneSecure( ((Kopete::ChatSession*)opdata), 2 );
+ } else {
+ Kopete::Message msg( session->members().getFirst(), session->account()->myself(), i18n("<b>Unverified OTR session started.</b>"), Kopete::Message::Internal, Kopete::Message::RichText );
+ session->appendMessage( msg );
+ OTRPlugin::plugin()->emitGoneSecure( ((Kopete::ChatSession*)opdata), 1 );
+ }
+}
+
+/* Actually I've never seen this event but its implemented in case someone should receive it
+ kopete, gaim and miranda send a heartbeat message at disconnect. See log_message.
+ Searching libotr I could not find any call of gone_insecure. */
+static void gone_insecure(void *opdata, ConnContext *context){
+ kdDebug() << "gone insecure" << endl;
+ OTRPlugin::plugin()->emitGoneSecure(((Kopete::ChatSession*)opdata), 0);
+ Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
+ Kopete::Message msg( session->members().getFirst(), session->account()->myself(), i18n("<b>OTR Session ended. The conversation is now insecure!</b>"), Kopete::Message::Internal, Kopete::Message::RichText );
+ session->appendMessage( msg );
+}
+
+static void still_secure(void *opdata, ConnContext *context, int is_reply){
+ kdDebug() << "still secure" << endl;
+ Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
+ Kopete::Message msg( session->members().getFirst(), session->account()->myself(), i18n("<b>OTR connection refreshed successfully.</b>") , Kopete::Message::Internal, Kopete::Message::RichText );
+ session->appendMessage( msg );
+
+ if( context->active_fingerprint->trust && context->active_fingerprint->trust[0] ){
+ OTRPlugin::plugin()->emitGoneSecure( session, 2);
+ } else {
+ OTRPlugin::plugin()->emitGoneSecure( session, 1);
+ }
+}
+
+static void log_message(void *opdata, const char *message){
+ kdDebug() << "libotr: "<< message << endl;
+}
+
+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
+};
+
+/*********************** Gui_UI_Ops finished *************************/
+
+
+/*********************** Constructor/Destructor **********************/
+
+OtrlChatInterface::OtrlChatInterface(){
+ kdDebug() << "Creating OtrlChatInterface" << endl;
+ mSelf = this;
+ OTRL_INIT;
+
+ userstate = otrl_userstate_create();
+
+ otrl_privkey_read( userstate, QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkeys" );
+
+
+
+ otrl_privkey_read_fingerprints(userstate, QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "fingerprints", NULL, NULL);
+
+}
+
+OtrlChatInterface::~ OtrlChatInterface(){
+ otrl_userstate_free(userstate);
+}
+
+
+OtrlChatInterface *OtrlChatInterface::self(){
+ if( !mSelf ){
+ new OtrlChatInterface();
+ }
+ return mSelf;
+}
+
+/********************* Chat section ***************************/
+
+OtrlUserState OtrlChatInterface::getUserstate(){
+ return userstate;
+}
+
+
+int OtrlChatInterface::decryptMessage( QString *msg, QString accountId,
+ QString protocol, 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.latin1(), protocol.latin1(), contactId.latin1(), msg->latin1(), &newMessage, &tlvs, NULL, NULL );
+
+
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED);
+ if( tlv ){
+ Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), i18n("<b>%1</b> has ended the OTR session. You should do the same.").arg(chatSession->members().getFirst()->contactId()) , Kopete::Message::Internal, Kopete::Message::RichText );
+ chatSession->appendMessage( msg );
+
+ OTRPlugin::plugin()->emitGoneSecure( chatSession, 3 );
+ }
+
+ context = otrl_context_find( userstate, contactId.latin1(), accountId.latin1(), protocol.latin1(), 0, NULL, NULL, NULL);
+ if (context) {
+ nextMsg = context->smstate->nextExpected;
+
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1);
+ if (tlv) {
+ if (nextMsg != OTRL_SMP_EXPECT1){
+ abortSMP( context, chatSession );
+ } else {
+ SMPPopup *popup = new SMPPopup( chatSession->view()->mainWidget(), i18n("Enter authentication secret"), Qt::WStyle_Dialog | Qt::WStyle_StaysOnTop, context, chatSession, false );
+ popup->show();
+ }
+ }
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2);
+ if (tlv) {
+ if (nextMsg != OTRL_SMP_EXPECT2)
+ abortSMP( context, chatSession );
+ else {
+ kdDebug() << "Update SMP state: 2 -> 3" << endl;
+ context->smstate->nextExpected = OTRL_SMP_EXPECT4;
+ }
+ }
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3);
+ if (tlv) {
+ if (nextMsg != OTRL_SMP_EXPECT3)
+ abortSMP( context, chatSession );
+ else {
+ if (context->active_fingerprint->trust && context->active_fingerprint->trust[0]) {
+ Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), i18n("<b>Authentication successful. The conversation is now secure!</b>"), Kopete::Message::Internal, Kopete::Message::RichText );
+ chatSession->appendMessage( msg );
+ OTRPlugin::plugin()->emitGoneSecure( chatSession, 2 );
+ } else {
+ Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), i18n("<b>Authentication failed. The conversation is now insecure!</b>"), Kopete::Message::Internal, Kopete::Message::RichText );
+ chatSession->appendMessage( msg );
+ OTRPlugin::plugin()->emitGoneSecure( chatSession, 1 );
+ }
+
+ context->smstate->nextExpected = OTRL_SMP_EXPECT1;
+ }
+ }
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4);
+ if (tlv) {
+ if (nextMsg != OTRL_SMP_EXPECT4)
+ abortSMP( context, chatSession );
+ else {
+ if (context->active_fingerprint->trust && context->active_fingerprint->trust[0]) {
+ Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), i18n("<b>Authentication successful. The conversation is now secure!</b>"), Kopete::Message::Internal, Kopete::Message::RichText );
+ chatSession->appendMessage( msg );
+ OTRPlugin::plugin()->emitGoneSecure( chatSession, 2 );
+ } else {
+ Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), i18n("<b>Authentication failed. The conversation is now insecure!</b>"), Kopete::Message::Internal, Kopete::Message::RichText );
+ chatSession->appendMessage( msg );
+ OTRPlugin::plugin()->emitGoneSecure( chatSession, 1 );
+ }
+ context->smstate->nextExpected = OTRL_SMP_EXPECT1;
+ }
+ }
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT);
+ if (tlv) {
+ Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), i18n("<b>Authentication error!</b>"), Kopete::Message::Internal, Kopete::Message::RichText );
+ chatSession->appendMessage( msg );
+ context->smstate->nextExpected = OTRL_SMP_EXPECT1;
+ }
+
+ 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);
+ otrl_message_free( newMessage );
+ msg->replace( '\n', "<br>", false );
+ }
+ }
+ return ignoremessage;
+}
+
+QString OtrlChatInterface::encryptMessage( QString msg, QString accountId,
+ QString protocol, QString contactId , Kopete::ChatSession *chatSession ){
+ int err;
+ char * newMessage;
+ if( otrl_proto_message_type( msg ) == OTRL_MSGTYPE_NOTOTR ){
+ msg.replace( '<', "&lt;", false );
+ err = otrl_message_sending( userstate, &ui_ops, chatSession, accountId.latin1(), protocol.latin1(), contactId.latin1(), msg.utf8(), NULL, &newMessage, NULL, NULL );
+
+ if( err != 0 ){
+ msg = i18n("Encryption error");
+ } else {
+ if( newMessage != NULL ){
+ msg = QString::fromUtf8( newMessage );
+ otrl_message_free( newMessage );
+ }
+ }
+ }
+ OtrlMessageType type = otrl_proto_message_type( msg );
+ if( type == OTRL_MSGTYPE_NOTOTR | type == OTRL_MSGTYPE_TAGGEDPLAINTEXT ){
+ msg.replace( "&lt;", "<", false );
+ }
+ return msg;
+}
+
+QString OtrlChatInterface::getDefaultQuery( QString accountId ){
+ char *message;
+ message = otrl_proto_default_query_msg( accountId.latin1(), 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().latin1(), chatSession->account()->protocol()->displayName().latin1(), chatSession->members().getFirst()->contactId() );
+ OTRPlugin::plugin()->emitGoneSecure( chatSession, false );
+
+ Kopete::Message msg( chatSession->account()->myself(), chatSession->members().getFirst(), i18n("Terminating OTR session."), Kopete::Message::Internal );
+// msg.setBody( QString( message ), Kopete::Message::RichText );
+ chatSession->appendMessage( msg );
+
+}
+
+bool OtrlChatInterface::shouldDiscard( QString message ){
+ if( !message.isEmpty() && !message.isNull() ){
+ switch( otrl_proto_message_type( message.latin1() ) ){
+ case OTRL_MSGTYPE_TAGGEDPLAINTEXT:
+ case OTRL_MSGTYPE_UNKNOWN:
+ case OTRL_MSGTYPE_NOTOTR:
+ return false;
+ default:
+ return true;
+ }
+ } else {
+ return false;
+ }
+}
+
+
+void OtrlChatInterface::setPolicy( OtrlPolicy policy ){
+ confPolicy = policy;
+}
+
+
+int OtrlChatInterface::privState( Kopete::ChatSession *session ){
+ ConnContext *context;
+
+ context = otrl_context_find(userstate, session->members().getFirst()->contactId(), session->account()->accountId(), session->account()->protocol()->displayName(), 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;
+ }
+ }
+ return 0;
+}
+
+QString OtrlChatInterface::formatContact(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 contactId;
+}
+
+void OtrlChatInterface::verifyFingerprint( Kopete::ChatSession *session ){
+ ConnContext *context;
+
+ context = otrl_context_find( userstate, session->members().getFirst()->contactId().latin1(), session->account()->accountId().latin1(), session->protocol()->displayName().latin1(), 0, NULL, NULL, NULL);
+
+ SMPPopup *popup = new SMPPopup( session->view()->mainWidget(), i18n("Enter authentication secret"), Qt::WStyle_Dialog | Qt::WStyle_StaysOnTop, context, session, true );
+ popup->show();
+
+
+}
+
+void OtrlChatInterface::setTrust( Kopete::ChatSession *session, bool trust ){
+ Fingerprint *fingerprint;
+
+ fingerprint = findFingerprint( session->members().getFirst()->contactId() );
+ if( fingerprint != 0 ){
+ if( trust ){
+ otrl_context_set_trust( fingerprint, "verified" );
+ } else {
+ otrl_context_set_trust( fingerprint, NULL );
+ }
+ kdDebug() << "Writing fingerprints" << endl;
+ otrl_privkey_write_fingerprints( userstate, QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "fingerprints" );
+ OTRPlugin::plugin()->emitGoneSecure( session, privState( session ) );
+ } else {
+ kdDebug() << "could not find fingerprint" << endl;
+ }
+}
+
+Fingerprint *OtrlChatInterface::findFingerprint( QString account ){
+ ConnContext *context;
+
+ for( context = userstate->context_root; context != NULL; context = context->next ){
+ kdDebug() << context->username << endl;
+ if( strcmp( context->username, account ) == 0 ){
+ kdDebug() << "found Context" << endl;
+ return context->active_fingerprint ? context->active_fingerprint : NULL;
+ }
+ }
+ return NULL;
+}
+
+QString OtrlChatInterface::findActiveFingerprint( Kopete::ChatSession *session ){
+ ConnContext *context;
+ char hash[45];
+
+ for( context = userstate->context_root; context != NULL; context = context->next ){
+ kdDebug() << context->username << endl;
+ if( strcmp( context->username, session->members().getFirst()->contactId() ) == 0 ){
+// otrl_privkey_hash_to_human( hash, context->fingerprint_root.next->fingerprint );
+ otrl_privkey_hash_to_human( hash, context->active_fingerprint->fingerprint );
+ return hash;
+ }
+ }
+ return NULL;
+}
+
+bool OtrlChatInterface::isVerified( Kopete::ChatSession *session ){
+ kdDebug() << "checking for trust" << endl;
+ Fingerprint *fingerprint = findFingerprint( session->members().getFirst()->contactId() );
+
+ if( fingerprint->trust && fingerprint->trust[0] != '\0' ){
+ kdDebug() << "verified" << endl;
+ return true;
+ } else {
+ kdDebug() << "not verified" << endl;
+ return false;
+ }
+}
+
+void OtrlChatInterface::updateKeyfile( Kopete::Account *account ){
+// Updating private keys from <=0.3
+ kdDebug() << "updating keys" << endl;
+ QFile keyfile( QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkeys" );
+ QString line;
+ QString file;
+
+ if( keyfile.open( IO_ReadWrite ) ){
+ kdDebug() << "file open" << endl;
+ while( keyfile.readLine( line, 200 ) != -1){
+ if( line.find( "protocol" ) != -1 ){
+ if( line.find( account->accountLabel() ) != -1 ){
+ line.replace( account->accountLabel(), account->protocol()->displayName() );
+ kdDebug() << "Successfully updated keyfile for account " << account->accountId() << endl;
+ }
+ }
+ file.append( line );
+ }
+ }
+ keyfile.remove();
+ keyfile.open( IO_ReadWrite );
+ keyfile.writeBlock( file.latin1(), file.length() );
+ keyfile.close();
+ otrl_privkey_forget_all( userstate );
+ otrl_privkey_read( userstate, QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkeys" );
+
+ file = "";
+ line = "";
+// Updating fingerprints from <=0.3
+ kdDebug() << "updating fingerprints" << endl;
+ QFile fingerprintfile( QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "fingerprints" );
+
+ if( fingerprintfile.open( IO_ReadWrite ) ){
+ kdDebug() << "file open" << endl;
+ while( fingerprintfile.readLine( line, 200 ) != -1){
+ int pos = line.findRev( account->accountLabel() );
+ if( pos != -1 ){
+ line.replace( pos, account->accountLabel().length(), account->protocol()->displayName() );
+ kdDebug() << "Successfully updated fingerprint for account " << account->accountId() << endl;
+ }
+ file.append( line );
+ }
+ }
+ fingerprintfile.remove();
+ fingerprintfile.open( IO_ReadWrite );
+ fingerprintfile.writeBlock( file.latin1(), file.length() );
+ fingerprintfile.close();
+ otrl_context_forget_all( userstate );
+ otrl_privkey_read_fingerprints(userstate, QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "fingerprints", NULL, NULL);
+
+}
+
+void OtrlChatInterface::checkFilePermissions( QString file ){
+ if( QFile::exists( file ) ){
+ QFile privkeys( file );
+ QFileInfo privkeysInfo( privkeys );
+ if( !privkeysInfo.permission( QFileInfo::ReadOwner | QFileInfo::WriteOwner ) |
+ privkeysInfo.permission( QFileInfo::ReadGroup ) |
+ privkeysInfo.permission( QFileInfo::WriteGroup ) |
+ privkeysInfo.permission( QFileInfo::ExeGroup ) |
+ privkeysInfo.permission( QFileInfo::ReadOther ) |
+ privkeysInfo.permission( QFileInfo::WriteOther ) |
+ privkeysInfo.permission( QFileInfo::ExeOther ) ){
+ kdDebug() << "Permissions of OTR storage file are wrong! Correcting..." << endl;
+ chmod( file, 0600);
+ }
+ }
+
+}
+
+/*bool OtrlChatInterface::verifyQuestion( Kopete::ChatSession *session, QString fingerprint ){
+ kdDebug() << "searching for Fingerprint" << endl;
+
+ if( fingerprint != NULL ){
+ int doVerify = KMessageBox::questionYesNo(
+ NULL,
+ i18n("Please contact %1 via another secure way and verify that the following Fingerprint is correct:").arg( formatContact(session->members().getFirst()->contactId())) + "\n\n" + fingerprint + "\n\n" + i18n("Are you sure you want to trust this fingerprint?"),
+ i18n("Verify fingerprint") );
+ if( doVerify == KMessageBox::Yes ){
+ return true;
+ } else {
+ return false;
+ verifyFingerprint( session, false );
+ }
+ } else {
+ KMessageBox::error( NULL, i18n( "No fingerprint yet received from this contact." ), i18n( "No fingerprint found" ) );
+ }
+ return false;
+}
+*/
+
+/****************** SMP implementations ****************/
+
+void OtrlChatInterface::abortSMP( ConnContext *context, Kopete::ChatSession *session ){
+ otrl_message_abort_smp( userstate, &ui_ops, session, context);
+ if (context->active_fingerprint->trust && !context->active_fingerprint->trust[0]) {
+ OTRPlugin::plugin()->emitGoneSecure( session, 1 );
+ Kopete::Message msg( session->members().getFirst(), session->account()->myself(), i18n("<b>Authentication aborded. The conversation is now insecure!</b>"), Kopete::Message::Internal, Kopete::Message::RichText );
+ session->appendMessage( msg );
+ }
+}
+
+void OtrlChatInterface::respondSMP( ConnContext *context, Kopete::ChatSession *session, QString secret, bool initiate ){
+ if( initiate ){
+ context = otrl_context_find( userstate, session->members().getFirst()->contactId().latin1(), session->account()->accountId().latin1(), session->protocol()->displayName().latin1(), 0, NULL, NULL, NULL);
+ otrl_message_initiate_smp( userstate, &ui_ops, session, context, (unsigned char*)secret.latin1(), secret.length() );
+
+
+ } else {
+ otrl_message_respond_smp( userstate, &ui_ops, session, context, (unsigned char*)secret.latin1(), secret.length());
+ }
+
+ Kopete::Message msg( session->members().getFirst(), session->account()->myself(), i18n("<b>Authenticating contact...</b>"), Kopete::Message::Internal, Kopete::Message::RichText );
+ session->appendMessage( msg );
+}
+
+/****************** KeyGenThread *******************/
+
+KeyGenThread::KeyGenThread( QString accountname, QString protocol ){
+ this->accountname = accountname;
+ this->protocol = protocol;
+}
+
+
+void KeyGenThread::run()
+{
+ kdDebug() << "Creating private key... Storing to: " + QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true)) + "privkeys" << endl;
+ otrl_privkey_generate(OtrlChatInterface::self()->getUserstate(), QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkeys", accountname, protocol);
+ OtrlChatInterface::self()->checkFilePermissions( QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkeys" );
+}
+