/***************************************************************************
 *   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 <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"),  TQt::WStyle_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;
		}
	}
}

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

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

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, TQString(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, TQString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkeys" );
	
	

	otrl_privkey_read_fingerprints(userstate, TQString(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( 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;


	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"),  TQt::WStyle_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 ) == OTRL_MSGTYPE_NOTOTR ){
		msg.replace( TQString("<"), TQString("&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 = TQString::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;
}

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 ){
	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( 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;
	
	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;
}

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;

	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"),  TQt::WStyle_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(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "fingerprints" );
		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( strcmp( context->username, account ) == 0 ){
			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( 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;
	TQFile keyfile( TQString(KGlobal::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(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkeys" );

	file = "";
	line = "";
// Updating fingerprints from <=0.3
	kdDebug() << "updating fingerprints" << endl;
	TQFile fingerprintfile( TQString(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, TQString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "fingerprints", 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, 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 ){
		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( TQString accountname, TQString protocol ){
	this->accountname = accountname;
	this->protocol = protocol;
}


void KeyGenThread::run()
{
	kdDebug() << "Creating private key... Storing to: " + TQString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true)) + "privkeys" << endl;
	otrl_privkey_generate(OtrlChatInterface::self()->getUserstate(), TQString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkeys", accountname, protocol);
	OtrlChatInterface::self()->checkFilePermissions( TQString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkeys" );
}

