You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1077 lines
43 KiB
C++
1077 lines
43 KiB
C++
/***************************************************************************
|
|
* Copyright (C) 2007 by Michael Zanetti *
|
|
* Copyright (C) 2014 by Timothy Pearson <kb9vqf@pearsoncomputing.net> *
|
|
* *
|
|
* *
|
|
* 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
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config-kopete.h"
|
|
#endif
|
|
|
|
#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 <tdemessagebox.h>
|
|
#include <kstandarddirs.h>
|
|
#include <tdelocale.h>
|
|
#include <kprogress.h>
|
|
#include <kpassivepopup.h>
|
|
#include <kanimwidget.h>
|
|
#include <kpushbutton.h>
|
|
|
|
#include <tqvbox.h>
|
|
#include <tqlabel.h>
|
|
#include <tqnamespace.h>
|
|
#include <tqeventloop.h>
|
|
#include <tqapplication.h>
|
|
#include <tqfile.h>
|
|
#include <tqfileinfo.h>
|
|
#include <tqptrlist.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;
|
|
}
|
|
TQString 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").utf8(), TQt::WType_Dialog | TQt::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) ){
|
|
tqApp->eventLoop()->processEvents(TQEventLoop::ExcludeUserInput | TQEventLoop::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 ( TQPtrListIterator<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, TQString(accountname) + ":" + TQString(protocol) + ":" + TQString(recipient) + ":" + TQString(message) );
|
|
Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
|
|
Kopete::ContactPtrList list = session->members();
|
|
for ( TQPtrListIterator<Kopete::Contact> it( list ); Kopete::Contact *contact = it.current(); ++it ){
|
|
if( contact->contactId().compare( recipient ) == 0 ){
|
|
Kopete::Message msg( session->account()->myself(), contact, TQString( message ), Kopete::Message::Outbound );
|
|
session->sendMessage( msg );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifndef HAVE_LIBOTR_0400
|
|
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, TQString( primary ) + TQString( secondary ), TQString( title ) );
|
|
}
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
#ifndef HAVE_LIBOTR_0400
|
|
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 ( TQPtrListIterator<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(), TQString( message ), Kopete::Message::Internal );
|
|
msg.setBody( TQString( message ), Kopete::Message::RichText );
|
|
session->appendMessage( msg );
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
static void update_context_list(void *opdata){
|
|
//Not used...
|
|
}
|
|
|
|
#ifndef HAVE_LIBOTR_0400
|
|
static const char *protocol_name(void *opdata, const char *protocol){
|
|
//Never seen...
|
|
kdDebug() << "protocol_name called" << endl;
|
|
}
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
#ifndef HAVE_LIBOTR_0400
|
|
static void protocol_name_free(void *opdata, const char *protocol_name){
|
|
//Never seen...
|
|
kdDebug() << "protocol_name_free called" << endl;
|
|
}
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
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, TQString("%1%2").arg(TDEGlobal::dirs()->saveLocation("data", "kopete_otr/", true )).arg("fingerprints").local8Bit() );
|
|
}
|
|
|
|
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 );
|
|
}
|
|
|
|
#ifdef HAVE_LIBOTR_0400
|
|
session->setProperty("otr-instag", QString::number(context->their_instance));
|
|
#endif // HAVE_LIBOTR_0400
|
|
}
|
|
|
|
/* 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);
|
|
}
|
|
}
|
|
|
|
#ifndef HAVE_LIBOTR_0400
|
|
static void log_message(void *opdata, const char *message){
|
|
kdDebug() << "libotr: "<< message << endl;
|
|
}
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
#ifdef HAVE_LIBOTR_0400
|
|
static void received_symkey(void *opdata, ConnContext *context, unsigned int use, const unsigned char *usedata, size_t usedatalen, const unsigned char *symkey){
|
|
// Not used
|
|
}
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
#ifdef HAVE_LIBOTR_0400
|
|
static const char *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 : {
|
|
TQString message = i18n("Error occurred encrypting message.");
|
|
err_msg = (char*)malloc(message.length() + 1);
|
|
memset(err_msg, 0, message.length() + 1);
|
|
memcpy(err_msg, message.utf8().data(), message.length());
|
|
break;
|
|
}
|
|
case OTRL_ERRCODE_MSG_NOT_IN_PRIVATE :
|
|
if (context) {
|
|
TQString 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.utf8().data(), message.length());
|
|
}
|
|
break;
|
|
case OTRL_ERRCODE_MSG_UNREADABLE : {
|
|
TQString 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.utf8().data(), message.length());
|
|
break;
|
|
}
|
|
case OTRL_ERRCODE_MSG_MALFORMED : {
|
|
TQString 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.utf8().data(), message.length());
|
|
break;
|
|
}
|
|
}
|
|
return err_msg;
|
|
}
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
#ifdef HAVE_LIBOTR_0400
|
|
void otr_error_message_free(void *opdata, const char *err_msg){
|
|
Q_UNUSED(opdata)
|
|
|
|
if (err_msg) {
|
|
free((char*)err_msg);
|
|
}
|
|
}
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
#ifdef HAVE_LIBOTR_0400
|
|
const char *resent_msg_prefix(void *opdata, ConnContext *context){
|
|
Q_UNUSED(opdata)
|
|
Q_UNUSED(context)
|
|
|
|
TQString message = i18n("[resent]");
|
|
char *msg_prefix = (char*)malloc(message.length() + 1);
|
|
memset(msg_prefix, 0, message.length() + 1);
|
|
memcpy(msg_prefix, message.utf8().data(), message.length());
|
|
return msg_prefix;
|
|
}
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
#ifdef HAVE_LIBOTR_0400
|
|
void resent_msg_prefix_free(void *opdata, const char *prefix){
|
|
Q_UNUSED(opdata)
|
|
|
|
if (prefix) {
|
|
free((char*)prefix);
|
|
}
|
|
}
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
#ifdef HAVE_LIBOTR_0400
|
|
void 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: {
|
|
SMPPopup *popup = new SMPPopup( chatSession->view()->mainWidget(), i18n("Enter authentication secret").utf8(), TQString::null, TQt::WType_Dialog | TQt::WStyle_StaysOnTop, context, chatSession, false );
|
|
popup->show();
|
|
break;
|
|
}
|
|
case OTRL_SMPEVENT_ASK_FOR_ANSWER: {
|
|
SMPPopup *popup = new SMPPopup( chatSession->view()->mainWidget(), question, question, TQt::WType_Dialog | TQt::WStyle_StaysOnTop, context, chatSession, false );
|
|
popup->show();
|
|
break;
|
|
}
|
|
case OTRL_SMPEVENT_IN_PROGRESS: {
|
|
Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), i18n("<b>Authenticating contact...</b>"), Kopete::Message::Internal, Kopete::Message::RichText );
|
|
chatSession->appendMessage( msg );
|
|
break;
|
|
}
|
|
case OTRL_SMPEVENT_SUCCESS: {
|
|
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 );
|
|
}
|
|
break;
|
|
}
|
|
case OTRL_SMPEVENT_FAILURE: {
|
|
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 );
|
|
break;
|
|
}
|
|
case OTRL_SMPEVENT_ABORT:
|
|
case OTRL_SMPEVENT_CHEATED:
|
|
case OTRL_SMPEVENT_ERROR: {
|
|
Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), i18n("<b>Authentication error!</b>"), Kopete::Message::Internal, Kopete::Message::RichText );
|
|
chatSession->appendMessage( msg );
|
|
OtrlChatInterface::self()->abortSMP( context, chatSession );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
#ifdef HAVE_LIBOTR_0400
|
|
void handle_msg_event(void *opdata, OtrlMessageEvent msg_event, ConnContext *context, const char *message, gcry_error_t err){
|
|
Kopete::ChatSession *chatSession= ((Kopete::ChatSession*)opdata);
|
|
Kopete::ContactPtrList list = chatSession->members();
|
|
|
|
switch (msg_event)
|
|
{
|
|
case OTRL_MSGEVENT_NONE:
|
|
break;
|
|
case OTRL_MSGEVENT_ENCRYPTION_REQUIRED: {
|
|
Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), i18n("You attempted to send an unencrypted message to <b>%1</b>").arg(context->username) , Kopete::Message::Internal, Kopete::Message::RichText );
|
|
chatSession->appendMessage( msg );
|
|
break;
|
|
}
|
|
case OTRL_MSGEVENT_ENCRYPTION_ERROR: {
|
|
Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), i18n("An error occurred when encrypting your message. The message was not sent."), Kopete::Message::Internal, Kopete::Message::RichText );
|
|
chatSession->appendMessage( msg );
|
|
break;
|
|
}
|
|
case OTRL_MSGEVENT_CONNECTION_ENDED: {
|
|
Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), i18n("<b>%1</b> has ended the OTR session. You should do the same.").arg(context->username) , Kopete::Message::Internal, Kopete::Message::RichText );
|
|
chatSession->appendMessage( msg );
|
|
break;
|
|
}
|
|
case OTRL_MSGEVENT_SETUP_ERROR: {
|
|
if (!err) {
|
|
err = GPG_ERR_INV_VALUE;
|
|
}
|
|
switch(gcry_err_code(err)) {
|
|
case GPG_ERR_INV_VALUE:
|
|
kdDebug() << "Error setting up private conversation: Malformed message received";
|
|
default:
|
|
kdDebug() << "Error setting up private conversation:" << err;
|
|
}
|
|
|
|
Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), i18n("OTR error"), Kopete::Message::Internal, Kopete::Message::RichText );
|
|
chatSession->appendMessage( msg );
|
|
break;
|
|
}
|
|
case OTRL_MSGEVENT_MSG_REFLECTED: {
|
|
Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), 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."), Kopete::Message::Internal, Kopete::Message::RichText );
|
|
chatSession->appendMessage( msg );
|
|
break;
|
|
}
|
|
case OTRL_MSGEVENT_MSG_RESENT: {
|
|
Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), i18n("The last message to <b>%1</b> was resent.").arg(context->username) , Kopete::Message::Internal, Kopete::Message::RichText );
|
|
chatSession->appendMessage( msg );
|
|
break;
|
|
}
|
|
case OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE: {
|
|
Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), i18n("The encrypted message received from <b>%1</b> is unreadable, as you are not currently communicating privately.").arg(context->username) , Kopete::Message::Inbound, Kopete::Message::RichText );
|
|
chatSession->appendMessage( msg );
|
|
//OtrlChatInterface::self()->m_blacklistIds.append(msg.id());
|
|
break;
|
|
}
|
|
case OTRL_MSGEVENT_RCVDMSG_UNREADABLE: {
|
|
Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), i18n("We received an unreadable encrypted message from <b>%1</b>."), Kopete::Message::Internal, Kopete::Message::RichText );
|
|
chatSession->appendMessage( msg );
|
|
break;
|
|
}
|
|
case OTRL_MSGEVENT_RCVDMSG_MALFORMED: {
|
|
Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), i18n("We received a malformed data message from <b>%1</b>."), Kopete::Message::Internal, Kopete::Message::RichText );
|
|
chatSession->appendMessage( msg );
|
|
break;
|
|
}
|
|
case OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD: {
|
|
kdDebug() << "Heartbeat received from" << context->username;
|
|
return;
|
|
}
|
|
case OTRL_MSGEVENT_LOG_HEARTBEAT_SENT: {
|
|
kdDebug() << "Heartbeat sent to" << context->username;
|
|
break;
|
|
}
|
|
case OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR: {
|
|
Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), message, Kopete::Message::Inbound, Kopete::Message::RichText );
|
|
chatSession->appendMessage( msg );
|
|
break;
|
|
}
|
|
case OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED: {
|
|
Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), i18n("<b>The following message received from <b>%1</b> was <i>not</i> encrypted: [</b>%2<b>]</b>").arg(context->username).arg(message), Kopete::Message::Inbound, Kopete::Message::RichText );
|
|
chatSession->appendMessage( msg );
|
|
//OtrlChatInterface::self()->m_blacklistIds.append(msg.id());
|
|
break;
|
|
}
|
|
case OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED: {
|
|
kdDebug() << "Unrecognized OTR message received from" << context->username;
|
|
break;
|
|
}
|
|
case OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE: {
|
|
Kopete::Message msg( chatSession->members().getFirst(), chatSession->account()->myself(), i18n("<b>%1</b> 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(context->username), Kopete::Message::Inbound, Kopete::Message::RichText );
|
|
chatSession->appendMessage( msg );
|
|
//OtrlChatInterface::self()->m_blacklistIds.append(msg.id());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
#ifdef HAVE_LIBOTR_0400
|
|
void create_instag(void *opdata, const char *accountname, const char *protocol){
|
|
Q_UNUSED(opdata)
|
|
|
|
otrl_instag_generate(OtrlChatInterface::self()->getUserstate(), TQString("%1%2").arg(TDEGlobal::dirs()->saveLocation("data", "kopete_otr/", true )).arg("instags").local8Bit(), accountname, protocol);
|
|
}
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
#ifdef HAVE_LIBOTR_0400
|
|
void convert_msg(void *opdata, ConnContext *context, OtrlConvertType convert_type, char ** dest, const char *src){
|
|
// Not used
|
|
}
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
#ifdef HAVE_LIBOTR_0400
|
|
void convert_free(void *opdata, ConnContext *context, char *dest){
|
|
// Not used
|
|
}
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
#ifdef HAVE_LIBOTR_0400
|
|
void timer_control(void *opdata, unsigned int interval){
|
|
kdDebug() << "timer_control called" << endl;
|
|
|
|
Q_UNUSED(opdata)
|
|
if (interval > 0) {
|
|
OtrlChatInterface::self()->forwardSecrecyTimerStart(interval);
|
|
}
|
|
else {
|
|
OtrlChatInterface::self()->forwardSecrecyTimerStop();
|
|
}
|
|
}
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
#ifdef HAVE_LIBOTR_0400
|
|
static OtrlMessageAppOps ui_ops = {
|
|
policy,
|
|
create_privkey,
|
|
is_logged_in,
|
|
inject_message,
|
|
update_context_list,
|
|
new_fingerprint,
|
|
write_fingerprints,
|
|
gone_secure,
|
|
gone_insecure,
|
|
still_secure,
|
|
NULL, // max_message_size,
|
|
NULL, // account_name,
|
|
NULL, // account_name_free,
|
|
received_symkey,
|
|
otr_error_message,
|
|
otr_error_message_free,
|
|
resent_msg_prefix,
|
|
resent_msg_prefix_free,
|
|
handle_smp_event,
|
|
handle_msg_event,
|
|
create_instag,
|
|
NULL, // convert_msg,
|
|
NULL, // convert_free,
|
|
timer_control
|
|
};
|
|
#else // HAVE_LIBOTR_0400
|
|
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
|
|
};
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
/*********************** Gui_UI_Ops finished *************************/
|
|
|
|
|
|
/*********************** Constructor/Destructor **********************/
|
|
|
|
OtrlChatInterface::OtrlChatInterface(){
|
|
kdDebug() << "Creating OtrlChatInterface" << endl;
|
|
mSelf = this;
|
|
OTRL_INIT;
|
|
|
|
userstate = otrl_userstate_create();
|
|
|
|
otrl_privkey_read( userstate, TQString("%1%2").arg(TDEGlobal::dirs()->saveLocation("data", "kopete_otr/", true )).arg("privkeys").local8Bit() );
|
|
|
|
otrl_privkey_read_fingerprints(userstate, TQString("%1%2").arg(TDEGlobal::dirs()->saveLocation("data", "kopete_otr/", true )).arg("fingerprints").local8Bit(), NULL, NULL);
|
|
|
|
#ifdef HAVE_LIBOTR_0400
|
|
otrl_instag_read(userstate, TQString("%1%2").arg(TDEGlobal::dirs()->saveLocation("data", "kopete_otr/", true )).arg("instags").local8Bit());
|
|
|
|
unsigned int interval = otrl_message_poll_get_default_interval(userstate);
|
|
forwardSecrecyTimerStart(interval);
|
|
connect(&m_forwardSecrecyTimer, SIGNAL(timeout()), this, SLOT(otrlMessagePoll()));
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
}
|
|
|
|
OtrlChatInterface::~ OtrlChatInterface(){
|
|
otrl_userstate_free(userstate);
|
|
}
|
|
|
|
|
|
OtrlChatInterface *OtrlChatInterface::self(){
|
|
if( !mSelf ){
|
|
new OtrlChatInterface();
|
|
}
|
|
return mSelf;
|
|
}
|
|
|
|
void OtrlChatInterface::forwardSecrecyTimerStart(int interval){
|
|
m_forwardSecrecyTimer.start(interval * 1000);
|
|
}
|
|
|
|
void OtrlChatInterface::forwardSecrecyTimerStop(){
|
|
m_forwardSecrecyTimer.stop();
|
|
}
|
|
|
|
void OtrlChatInterface::otrlMessagePoll(){
|
|
#ifdef HAVE_LIBOTR_0400
|
|
otrl_message_poll(userstate, 0, 0);
|
|
#endif // HAVE_LIBOTR_0400
|
|
}
|
|
|
|
/********************* Chat section ***************************/
|
|
|
|
OtrlUserState OtrlChatInterface::getUserstate(){
|
|
return userstate;
|
|
}
|
|
|
|
|
|
int OtrlChatInterface::decryptMessage( TQString *msg, TQString accountId,
|
|
TQString protocol, TQString contactId , Kopete::ChatSession *chatSession){
|
|
|
|
int ignoremessage;
|
|
char *newMessage = NULL;
|
|
OtrlTLV *tlvs = NULL;
|
|
OtrlTLV *tlv = NULL;
|
|
ConnContext *context;
|
|
NextExpectedSMP nextMsg;
|
|
|
|
#ifdef HAVE_LIBOTR_0400
|
|
ignoremessage = otrl_message_receiving( userstate, &ui_ops, chatSession, accountId.latin1(), protocol.latin1(), contactId.latin1(), msg->latin1(), &newMessage, &tlvs, NULL, NULL, NULL );
|
|
#else // HAVE_LIBOTR_0400
|
|
ignoremessage = otrl_message_receiving( userstate, &ui_ops, chatSession, accountId.latin1(), protocol.latin1(), contactId.latin1(), msg->latin1(), &newMessage, &tlvs, NULL, NULL );
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
|
|
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 );
|
|
}
|
|
|
|
#ifdef HAVE_LIBOTR_0400
|
|
context = otrl_context_find( userstate, contactId.latin1(), accountId.latin1(), protocol.latin1(), 0, 0, NULL, NULL, NULL);
|
|
#else // HAVE_LIBOTR_0400
|
|
context = otrl_context_find( userstate, contactId.latin1(), accountId.latin1(), protocol.latin1(), 0, NULL, NULL, NULL);
|
|
#endif // HAVE_LIBOTR_0400
|
|
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").utf8(), TQString::null, TQt::WType_Dialog | TQt::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 = TQString::fromUtf8(newMessage);
|
|
otrl_message_free( newMessage );
|
|
msg->replace( TQString("\n"), TQString("<br>"), false );
|
|
}
|
|
}
|
|
return ignoremessage;
|
|
}
|
|
|
|
TQString OtrlChatInterface::encryptMessage( TQString msg, TQString accountId,
|
|
TQString protocol, TQString contactId , Kopete::ChatSession *chatSession ){
|
|
int err;
|
|
char * newMessage;
|
|
if( otrl_proto_message_type( msg.latin1() ) == OTRL_MSGTYPE_NOTOTR ){
|
|
msg.replace( TQString("<"), TQString("<"), false );
|
|
#ifdef HAVE_LIBOTR_0400
|
|
otrl_instag_t instance = chatSession->property("otr-instag").toUInt();
|
|
err = otrl_message_sending( userstate, &ui_ops, chatSession, accountId.latin1(), protocol.latin1(), contactId.latin1(), instance, msg.utf8(), NULL, &newMessage, OTRL_FRAGMENT_SEND_ALL_BUT_LAST, NULL, NULL, NULL );
|
|
#else // HAVE_LIBOTR_0400
|
|
err = otrl_message_sending( userstate, &ui_ops, chatSession, accountId.latin1(), protocol.latin1(), contactId.latin1(), msg.utf8(), NULL, &newMessage, NULL, NULL );
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
if( err != 0 ){
|
|
msg = i18n("Encryption error");
|
|
} else {
|
|
if( newMessage != NULL ){
|
|
msg = TQString::fromUtf8( newMessage );
|
|
otrl_message_free( newMessage );
|
|
}
|
|
}
|
|
}
|
|
OtrlMessageType type = otrl_proto_message_type( msg.latin1() );
|
|
if( type == OTRL_MSGTYPE_NOTOTR | type == OTRL_MSGTYPE_TAGGEDPLAINTEXT ){
|
|
msg.replace( "<", "<", false );
|
|
}
|
|
return msg;
|
|
}
|
|
|
|
TQString OtrlChatInterface::getDefaultQuery( TQString accountId ){
|
|
char *message;
|
|
message = otrl_proto_default_query_msg( accountId.latin1(), OTRL_POLICY_ALLOW_V2 );
|
|
TQString msg( message );
|
|
otrl_message_free( message );
|
|
return msg;
|
|
}
|
|
|
|
void OtrlChatInterface::disconnectSession( Kopete::ChatSession *chatSession ){
|
|
#ifdef HAVE_LIBOTR_0400
|
|
otrl_instag_t instance = chatSession->property("otr-instag").toUInt();
|
|
otrl_message_disconnect( userstate, &ui_ops, chatSession, chatSession->account()->accountId().latin1(), chatSession->account()->protocol()->displayName().latin1(), chatSession->members().getFirst()->contactId().latin1(), instance );
|
|
#else // HAVE_LIBOTR_0400
|
|
otrl_message_disconnect( userstate, &ui_ops, chatSession, chatSession->account()->accountId().latin1(), chatSession->account()->protocol()->displayName().latin1(), chatSession->members().getFirst()->contactId().latin1() );
|
|
#endif // HAVE_LIBOTR_0400
|
|
OTRPlugin::plugin()->emitGoneSecure( chatSession, false );
|
|
|
|
Kopete::Message msg( chatSession->account()->myself(), chatSession->members().getFirst(), i18n("Terminating OTR session."), Kopete::Message::Internal );
|
|
// msg.setBody( TQString( message ), Kopete::Message::RichText );
|
|
chatSession->appendMessage( msg );
|
|
|
|
}
|
|
|
|
bool OtrlChatInterface::shouldDiscard( TQString 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;
|
|
|
|
#ifdef HAVE_LIBOTR_0400
|
|
otrl_instag_t instance = session->property("otr-instag").toUInt();
|
|
context = otrl_context_find(userstate, session->members().getFirst()->contactId().latin1(), session->account()->accountId().latin1(), session->account()->protocol()->displayName().latin1(), instance, 0, NULL, NULL, NULL);
|
|
#else // HAVE_LIBOTR_0400
|
|
context = otrl_context_find(userstate, session->members().getFirst()->contactId().latin1(), session->account()->accountId().latin1(), session->account()->protocol()->displayName().latin1(), 0, NULL, NULL, NULL);
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
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;
|
|
}
|
|
|
|
TQString OtrlChatInterface::formatContact(TQString contactId){
|
|
|
|
Kopete::MetaContact *metaContact = Kopete::ContactList::self()->findMetaContactByContactId(contactId);
|
|
if( metaContact ){
|
|
TQString displayName = metaContact->displayName();
|
|
if((displayName != contactId) && !displayName.isNull()){
|
|
return displayName + " (" + contactId+")";
|
|
}
|
|
}
|
|
return contactId;
|
|
}
|
|
|
|
void OtrlChatInterface::verifyFingerprint( Kopete::ChatSession *session ){
|
|
ConnContext *context;
|
|
|
|
#ifdef HAVE_LIBOTR_0400
|
|
otrl_instag_t instance = session->property("otr-instag").toUInt();
|
|
context = otrl_context_find( userstate, session->members().getFirst()->contactId().latin1(), session->account()->accountId().latin1(), session->protocol()->displayName().latin1(), instance, 0, NULL, NULL, NULL);
|
|
#else // HAVE_LIBOTR_0400
|
|
context = otrl_context_find( userstate, session->members().getFirst()->contactId().latin1(), session->account()->accountId().latin1(), session->protocol()->displayName().latin1(), 0, NULL, NULL, NULL);
|
|
#endif // HAVE_LIBOTR_0400
|
|
|
|
SMPPopup *popup = new SMPPopup( session->view()->mainWidget(), i18n("Enter authentication secret").utf8(), TQString::null, TQt::WType_Dialog | TQt::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, TQString("%1%2").arg(TDEGlobal::dirs()->saveLocation("data", "kopete_otr/", true )).arg("fingerprints").local8Bit() );
|
|
OTRPlugin::plugin()->emitGoneSecure( session, privState( session ) );
|
|
} else {
|
|
kdDebug() << "could not find fingerprint" << endl;
|
|
}
|
|
}
|
|
|
|
Fingerprint *OtrlChatInterface::findFingerprint( TQString account ){
|
|
ConnContext *context;
|
|
|
|
for( context = userstate->context_root; context != NULL; context = context->next ){
|
|
kdDebug() << context->username << endl;
|
|
if (context->username == account)
|
|
{
|
|
kdDebug() << "found Context" << endl;
|
|
return context->active_fingerprint ? context->active_fingerprint : NULL;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
TQString 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 (context->username == session->members().getFirst()->contactId())
|
|
{
|
|
// 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;
|
|
TQFile keyfile( TQString(TDEGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkeys" );
|
|
TQString line;
|
|
TQString 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, TQString("%1%2").arg(TDEGlobal::dirs()->saveLocation("data", "kopete_otr/", true )).arg("privkeys").local8Bit() );
|
|
|
|
file = "";
|
|
line = "";
|
|
// Updating fingerprints from <=0.3
|
|
kdDebug() << "updating fingerprints" << endl;
|
|
TQFile fingerprintfile( TQString("%1%2").arg(TDEGlobal::dirs()->saveLocation("data", "kopete_otr/", true )).arg("fingerprints").local8Bit() );
|
|
|
|
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, TQString("%1%2").arg(TDEGlobal::dirs()->saveLocation("data", "kopete_otr/", true )).arg("fingerprints").local8Bit(), NULL, NULL);
|
|
|
|
}
|
|
|
|
void OtrlChatInterface::checkFilePermissions( TQString file ){
|
|
if( TQFile::exists( file ) ){
|
|
TQFile privkeys( file );
|
|
TQFileInfo privkeysInfo( privkeys );
|
|
if( !privkeysInfo.permission( TQFileInfo::ReadOwner | TQFileInfo::WriteOwner ) |
|
|
privkeysInfo.permission( TQFileInfo::ReadGroup ) |
|
|
privkeysInfo.permission( TQFileInfo::WriteGroup ) |
|
|
privkeysInfo.permission( TQFileInfo::ExeGroup ) |
|
|
privkeysInfo.permission( TQFileInfo::ReadOther ) |
|
|
privkeysInfo.permission( TQFileInfo::WriteOther ) |
|
|
privkeysInfo.permission( TQFileInfo::ExeOther ) ){
|
|
kdDebug() << "Permissions of OTR storage file are wrong! Correcting..." << endl;
|
|
chmod( file.local8Bit(), 0600);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*bool OtrlChatInterface::verifyQuestion( Kopete::ChatSession *session, TQString 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, TQString secret, bool initiate ){
|
|
if( initiate ){
|
|
#ifdef HAVE_LIBOTR_0400
|
|
otrl_instag_t instance = session->property("otr-instag").toUInt();
|
|
context = otrl_context_find( userstate, session->members().getFirst()->contactId().latin1(), session->account()->accountId().latin1(), session->protocol()->displayName().latin1(), instance, 0, NULL, NULL, NULL);
|
|
#else // HAVE_LIBOTR_0400
|
|
context = otrl_context_find( userstate, session->members().getFirst()->contactId().latin1(), session->account()->accountId().latin1(), session->protocol()->displayName().latin1(), 0, NULL, NULL, NULL);
|
|
#endif // HAVE_LIBOTR_0400
|
|
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 );
|
|
}
|
|
|
|
void OtrlChatInterface::respondSMPQ( ConnContext *context, Kopete::ChatSession *session, TQString question, TQString secret, bool initiate ){
|
|
if( initiate ){
|
|
#ifdef HAVE_LIBOTR_0400
|
|
otrl_instag_t instance = session->property("otr-instag").toUInt();
|
|
context = otrl_context_find( userstate, session->members().getFirst()->contactId().latin1(), session->account()->accountId().latin1(), session->protocol()->displayName().latin1(), instance, 0, NULL, NULL, NULL);
|
|
#else // HAVE_LIBOTR_0400
|
|
context = otrl_context_find( userstate, session->members().getFirst()->contactId().latin1(), session->account()->accountId().latin1(), session->protocol()->displayName().latin1(), 0, NULL, NULL, NULL);
|
|
#endif // HAVE_LIBOTR_0400
|
|
otrl_message_initiate_smp_q( userstate, &ui_ops, session, context, (const char*)question.latin1(), (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( TQString accountname, TQString protocol ){
|
|
this->accountname = accountname;
|
|
this->protocol = protocol;
|
|
}
|
|
|
|
|
|
void KeyGenThread::run()
|
|
{
|
|
kdDebug() << "Creating private key... Storing to: " + TQString(TDEGlobal::dirs()->saveLocation("data", "kopete_otr/", true)) + "privkeys" << endl;
|
|
otrl_privkey_generate(OtrlChatInterface::self()->getUserstate(), TQString("%1%2").arg(TDEGlobal::dirs()->saveLocation("data", "kopete_otr/", true )).arg("privkeys").local8Bit(), accountname.latin1(), protocol.latin1());
|
|
OtrlChatInterface::self()->checkFilePermissions( TQString("%1%2").arg(TDEGlobal::dirs()->saveLocation("data", "kopete_otr/", true )).arg("privkeys").local8Bit() );
|
|
}
|
|
|
|
#include "otrlchatinterface.moc"
|