diff options
Diffstat (limited to 'src')
43 files changed, 3189 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..f168bd9 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,48 @@ +METASOURCES = AUTO + +messages: + extractrc `find . -name \*.ui -o -name \*.rc` > rc.cpp + $(XGETTEXT) --keyword=i18n *.cpp -o $(top_srcdir)/po/kopete_otr.pot + +INCLUDES = $(all_includes) -I$(kde_includes)/kopete -I$(kde_includes)/kopete/ui + +kde_module_LTLIBRARIES = kcm_kopete_otr.la kopete_otr.la + +kopete_otr_la_SOURCES = kopete_otr.kcfgc otrguiclient.cpp otrplugin.cpp + + +kopete_otr_la_LDFLAGS = -module -no-undefined $(KDE_PLUGIN) $(all_libraries) \ + -lkopete + +kcm_kopete_otr_la_SOURCES = kopete_otr.kcfgc otrpreferences.cpp otrprefs.ui + +kcm_kopete_otr_la_LDFLAGS = -module -no-undefined $(KDE_PLUGIN) \ + $(all_libraries) -lkopete +kcm_kopete_otr_la_LIBADD = libkotr.la -lotr $(LIB_KUTILS) + +service_DATA = kopete_otr.desktop +servicedir = $(kde_servicesdir) + +kde_kcfg_DATA = kopete_otr.kcfg + +kcm_DATA = kopete_otr_config.desktop +kcmdir = $(kde_servicesdir)/kconfiguredialog + +kopete_otr_la_LIBADD = libkotr.la -lotr + +noinst_HEADERS = otrguiclient.h otrlchatinterface.h otrlconfinterface.h \ + otrplugin.h otrpreferences.h otrprefs.h privkeypopup.h smppopup.h verifypopup.h + + +rcdir = $(kde_datadir)/kopete_otr +rc_DATA = otrchatui.rc otrui.rc + +lib_LTLIBRARIES = libkotr.la +libkotr_la_LDFLAGS = $(all_libraries) +libkotr_la_SOURCES = otrlchatinterface.cpp otrlconfinterface.cpp \ + privkeypopup.cpp privkeypopupui.ui smppopup.cpp smppopupui.ui verifypopup.cpp \ + verifypopupui.ui +libkotr_la_LIBADD = -lotr + +SUBDIRS = pics + diff --git a/src/kopete_otr.desktop b/src/kopete_otr.desktop new file mode 100644 index 0000000..82c6a30 --- /dev/null +++ b/src/kopete_otr.desktop @@ -0,0 +1,20 @@ +[Desktop Entry] +Encoding=UTF-8 +Type=Service +X-Kopete-Version=1000900 +Icon=kopete_otr +ServiceTypes=Kopete/Plugin +X-KDE-Library=kopete_otr +X-KDE-PluginInfo-Author=Michael Zanetti +X-KDE-PluginInfo-Email=michael_zanetti@gmx.net +X-KDE-PluginInfo-Name=kopete_otr +X-KDE-PluginInfo-Version=0.7 +X-KDE-PluginInfo-Website=http://kopete-otr.follefuder.org +X-KDE-PluginInfo-Category=Plugins +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=false +Comment=Encrypt chat sessions with Off-The-Record encryption +Comment[de]=Verschlüsselt Chat-Sitzungen mit Off-The-Record Verschlüsselung +Name=OTR +Name[de]=OTR
\ No newline at end of file diff --git a/src/kopete_otr.kcfg b/src/kopete_otr.kcfg new file mode 100644 index 0000000..1db6935 --- /dev/null +++ b/src/kopete_otr.kcfg @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE kcfg SYSTEM "http://www.kde.org/standards/kcfg/1.0/kcfg.dtd"> +<kcfg> +<kcfgfile name="kopete_otr"/> + <group name="Policy"> + <entry name="rbAlways" type="Bool"> + <label>Always encrypt outgoing messages</label> + <default>false</default> + </entry> + <entry name="rbOpportunistic" type="Bool"> + <label>Automatically encrypt mesages if the other side supports OTR</label> + <default>true</default> + </entry> + <entry name="rbManual" type="Bool"> + <label>Encrypt mesages if the other side requests an OTR connection</label> + <default>false</default> + </entry> + <entry name="rbNever" type="Bool"> + <label>Never encrypt outgoing messages</label> + <default>false</default> + </entry> + </group> +</kcfg>
\ No newline at end of file diff --git a/src/kopete_otr.kcfgc b/src/kopete_otr.kcfgc new file mode 100644 index 0000000..71216cf --- /dev/null +++ b/src/kopete_otr.kcfgc @@ -0,0 +1,7 @@ +File=kopete_otr.kcfg +ClassName=KopeteOtrKcfg +Singleton=true +Mutators=true +MemberVariables=private +ItemAccessors=true +GlobalEnums=true diff --git a/src/kopete_otr.lsm b/src/kopete_otr.lsm new file mode 100644 index 0000000..2e2aa8f --- /dev/null +++ b/src/kopete_otr.lsm @@ -0,0 +1,16 @@ +Begin3 +Title: kopete-otr -- Some description +Version: 0.6 +Entered-date: +Description: +Keywords: KDE Qt +Author: Michael Zanetti <michael_zanetti@gmx.net> +Maintained-by: Michael Zanetti <michael_zanetti@gmx.net> +Home-page: +Alternate-site: +Primary-site: htto://kopete-otr.follefuder.org + xxxxxx kopete-otr-0.6.tar.gz + xxx kopete_otr-0.6.lsm +Platform: Linux. Needs KDE +Copying-policy: GPL +End diff --git a/src/kopete_otr_config.desktop b/src/kopete_otr_config.desktop new file mode 100644 index 0000000..b3ad3ad --- /dev/null +++ b/src/kopete_otr_config.desktop @@ -0,0 +1,16 @@ +[Desktop Entry] +Encoding=UTF-8 +Type=Service +Icon=kopete_otr +ServiceTypes=KCModule + +X-KDE-ModuleType=Library +X-KDE-Library=kopete_otr +X-KDE-FactoryName=OTRPreferencesFactory +X-KDE-ParentApp=kopete_otr +X-KDE-ParentComponents=kopete_otr + +Comment=Encrypt chat sessions with Off-The-Record encryption +Comment[de]=Verschlüsselt Chat-Sitzungen mit Off-The-Record Verschlüsselung +Name=OTR +Name[de]=OTR
\ No newline at end of file diff --git a/src/otrchatui.rc b/src/otrchatui.rc new file mode 100644 index 0000000..2c3d710 --- /dev/null +++ b/src/otrchatui.rc @@ -0,0 +1,19 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui name="kopete_otr" version="1"> + <MenuBar> + <Menu name="tools"><text>&Tools</text> + <Menu name="otr_menu"><text>OTR Encryption</text> + <Action name="enable_otr" /> + <Action name="disable_otr" /> + <Action name="verify_fingerprint"/> + </Menu> + </Menu> + </MenuBar> + + <ToolBar name="mainToolBar"> + <text>OTR Encryption</text> + <Separator name="separator_0" /> + <Action name="otr_settings" /> + <Separator name="separator_0" /> + </ToolBar> +</kpartgui> diff --git a/src/otrguiclient.cpp b/src/otrguiclient.cpp new file mode 100644 index 0000000..544ae94 --- /dev/null +++ b/src/otrguiclient.cpp @@ -0,0 +1,128 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ + + +#include <kaction.h> +#include <klocale.h> +#include <kactionclasses.h> +#include <kopetechatsession.h> +#include <kopeteview.h> +#include <kopetemessage.h> +#include <kdebug.h> +#include <kstandarddirs.h> +#include <kmessagebox.h> + + +#include "otrguiclient.h" +#include "otrplugin.h" + +/** + * @author Frank Scheffold + * @author Michael Zanetti + */ + + +OtrGUIClient::OtrGUIClient( Kopete::ChatSession *parent, const char *name ) +: QObject( parent, name ), KXMLGUIClient( parent ) +{ + setInstance( OTRPlugin::plugin()->instance() ); + + connect( OTRPlugin::plugin(), + SIGNAL( destroyed( QObject * ) ), this, + SLOT( deleteLater() ) + + ); + + connect(this, SIGNAL( signalOtrChatsession(Kopete::ChatSession*, bool) ), OTRPlugin::plugin(), SLOT(slotEnableOtr(Kopete::ChatSession*, bool))); + + connect( OTRPlugin::plugin(), SIGNAL( goneSecure( Kopete::ChatSession *, int ) ), + this, SLOT( encryptionEnabled( Kopete::ChatSession *, int ) ) ); + + connect( this, SIGNAL( signalVerifyFingerprint( Kopete::ChatSession * ) ), OTRPlugin::plugin(), SLOT(slotVerifyFingerprint( Kopete::ChatSession * )) ); + + m_manager = parent; + otrActionMenu = new KActionMenu(i18n("OTR Settings"),"otr_disabled", actionCollection(), "otr_settings"); + otrActionMenu->setDelayed( false ); + actionEnableOtr = new KAction(i18n( "Start OTR session" ), "otr_private", 0,this,SLOT(slotEnableOtr()),actionCollection(), "enable_otr"); + actionDisableOtr = new KAction(i18n("End OTR session"), "otr_disabled",0, this,SLOT(slotDisableOtr()), actionCollection(), "disable_otr"); + actionVerifyFingerprint = new KAction(i18n("Authenticate Contact"), "signature",0, this,SLOT(slotVerifyFingerprint()), actionCollection(), "verify_fingerprint"); + + otrActionMenu->insert(actionEnableOtr); + otrActionMenu->insert(actionDisableOtr); + otrActionMenu->insert(actionVerifyFingerprint); + + setXMLFile("otrchatui.rc"); + + encryptionEnabled( parent, OtrlChatInterface::self()->privState(parent) ); + + +} + +OtrGUIClient::~OtrGUIClient() +{ +} + +void OtrGUIClient::slotEnableOtr() +{ + emit signalOtrChatsession( m_manager, true ); +} +void OtrGUIClient::slotDisableOtr() +{ + emit signalOtrChatsession( m_manager, false ); +} + +void OtrGUIClient::slotVerifyFingerprint(){ + emit signalVerifyFingerprint( m_manager ); +} + +void OtrGUIClient::encryptionEnabled(Kopete::ChatSession *session, int state){ + if( session == m_manager ){ + switch(state){ + case 0: + otrActionMenu->setIcon("otr_disabled"); + actionEnableOtr->setText( i18n("Start OTR session") ); + actionDisableOtr->setEnabled(false); + actionVerifyFingerprint->setEnabled(false); + break; + case 1: + otrActionMenu->setIcon("otr_unverified"); + actionEnableOtr->setText( i18n("Refresh OTR session") ); + actionDisableOtr->setEnabled(true); + actionVerifyFingerprint->setEnabled(true); + break; + case 2: + otrActionMenu->setIcon("otr_private"); + actionEnableOtr->setText( i18n("Refresh OTR session") ); + actionDisableOtr->setEnabled(true); + actionVerifyFingerprint->setEnabled(true); + break; + case 3: + otrActionMenu->setIcon("otr_finished"); + actionEnableOtr->setText( i18n("Start OTR session") ); + actionDisableOtr->setEnabled(true); + actionVerifyFingerprint->setEnabled(false); + break; + } + } +} + +#include "otrguiclient.moc" + +// vim: set noet ts=4 sts=4 sw=4: diff --git a/src/otrguiclient.h b/src/otrguiclient.h new file mode 100644 index 0000000..3776195 --- /dev/null +++ b/src/otrguiclient.h @@ -0,0 +1,80 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ + + +#ifndef OTRGUICLIENT_H +#define OTRGUICLIENT_H + +#include <qobject.h> +#include <kxmlguiclient.h> + +//#include <kio/job.h> + +#include <kglobal.h> +#include <kstandarddirs.h> +#include <kiconloader.h> + +#include <kopetemessage.h> +#include <kopeteplugin.h> + + +class KActionMenu; +class KAction; + +namespace Kopete { class ChatSession; } + +/** + * @author Frank Scheffold + */ + + + + +class OtrGUIClient : public QObject , public KXMLGUIClient +{ + Q_OBJECT + +public: + + OtrGUIClient( Kopete::ChatSession *parent, const char *name=0L ); + ~OtrGUIClient(); + + +private: + Kopete::ChatSession *m_manager; + KActionMenu *otrActionMenu; + KAction *actionEnableOtr; + KAction *actionDisableOtr; + KAction *actionVerifyFingerprint; + +private slots: + void slotEnableOtr(); + void slotDisableOtr(); + void encryptionEnabled( Kopete::ChatSession* session, int state ); + void slotVerifyFingerprint(); + +signals: + void signalOtrChatsession( Kopete::ChatSession* session, bool enable ); + void signalVerifyFingerprint( Kopete::ChatSession *session ); + + +}; + +#endif 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( '<', "<", 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( "<", "<", 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" ); +} + diff --git a/src/otrlchatinterface.h b/src/otrlchatinterface.h new file mode 100644 index 0000000..9fcf632 --- /dev/null +++ b/src/otrlchatinterface.h @@ -0,0 +1,87 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ + +#ifndef OTRLCHATINTERFACE_H +#define OTRLCHATINTERFACE_H + +/** + * @author Michael Zanetti + */ + +#include <qstring.h> +#include <qptrlist.h> +#include <qvaluelist.h> +#include <qthread.h> +#include <qmutex.h> + +#include <kopetechatsession.h> + +extern "C" { +#include <libotr/privkey.h> +#include <libotr/proto.h> +#include <libotr/message.h> +#include <libotr/userstate.h> +} + +class OtrlChatInterface: public QObject +{ + +public: + ~OtrlChatInterface(); + static OtrlChatInterface *self(); + + int decryptMessage( QString *msg, QString accountId, QString protocol, QString contactId, Kopete::ChatSession *chatSession ); + QString encryptMessage( QString msg, QString accountId, + QString protocol, QString contactId , Kopete::ChatSession *chatSession ); + QString getDefaultQuery( QString accountId ); + void disconnectSession( Kopete::ChatSession *chatSession ); + void setPolicy( OtrlPolicy policy ); + bool shouldDiscard( QString message ); + OtrlUserState getUserstate(); + int privState( Kopete::ChatSession *session ); + QString formatContact(QString contactId); + bool isVerified( Kopete::ChatSession *session ); + void updateKeyfile( Kopete::Account *account ); + void checkFilePermissions( QString file ); +// bool verifyQuestion( Kopete::ChatSession *session, QString fingerprint ); + QString findActiveFingerprint( Kopete::ChatSession *session ); + void verifyFingerprint( Kopete::ChatSession *session ); + void abortSMP( ConnContext *context, Kopete::ChatSession *session ); + void respondSMP( ConnContext *context, Kopete::ChatSession *session, QString secret, bool initiate ); + void setTrust( Kopete::ChatSession *session, bool trust ); + +private: + OtrlChatInterface(); + static OtrlChatInterface *mSelf; + Fingerprint *findFingerprint( QString username ); +}; + + class KeyGenThread : public QThread { + +private: + QString accountname; + QString protocol; + +public: + KeyGenThread( QString accountname, QString protocol ); + virtual void run(); +}; + +#endif diff --git a/src/otrlconfinterface.cpp b/src/otrlconfinterface.cpp new file mode 100644 index 0000000..5d95d06 --- /dev/null +++ b/src/otrlconfinterface.cpp @@ -0,0 +1,231 @@ +/*************************************************************************** + * 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 <qapplication.h> +#include <qeventloop.h> + +#include <kopetechatsession.h> +#include <kopeteaccount.h> + +#include <kdebug.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <klocale.h> +#include <kanimwidget.h> + + +#include "otrlconfinterface.h" +#include "otrlchatinterface.h" +#include "otrplugin.h" +#include "privkeypopup.h" + + + +/*********************** Konstruktor/Destruktor **********************/ + +OtrlConfInterface::OtrlConfInterface( QWidget *preferencesDialog ){ + + this->preferencesDialog = preferencesDialog; + + OTRL_INIT; + + userstate = OtrlChatInterface::self()->getUserstate(); + + kdDebug() << "OtrlConfInterface created" << endl; +} + +OtrlConfInterface::~ OtrlConfInterface(){ + otrl_userstate_free(userstate); +} + +/*********************** Functions for kcm module ************************/ + +QString OtrlConfInterface::getPrivFingerprint( QString accountId, QString protocol){ +// if (otrl_privkey_read(userstate, QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkey" ) == 0){ + char fingerprint[45]; + if( otrl_privkey_fingerprint( userstate, fingerprint, accountId.latin1(), protocol.latin1()) != 0 ){ + return fingerprint; + } +// } + return i18n("No fingerprint present."); +} + + +bool OtrlConfInterface::hasPrivFingerprint( QString accountId, QString protocol ){ + char fingerprint[45]; + if( otrl_privkey_fingerprint( userstate, fingerprint, accountId.latin1(), protocol.latin1() ) != 0 ){ + return true; + } + return false; +} + + +void OtrlConfInterface::generateNewPrivKey( QString accountId, QString protocol ){ + PrivKeyPopup *popup = new PrivKeyPopup( preferencesDialog, 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 ( accountId, protocol ); + keyGenThread->start(); + while( !keyGenThread->wait(100) ){ + qApp->eventLoop()->processEvents(QEventLoop::ExcludeUserInput | QEventLoop::ExcludeSocketNotifiers, 100); + } + popup->setCloseLock( false ); + popup->close(); +} + +QValueList<QString[5]> OtrlConfInterface::readAllFingerprints(){ + ConnContext *context; + Fingerprint *fingerprint; + QString entry[5]; + char hash[45]; + QValueList<QString[5]> list; + + for( context = userstate->context_root; context != NULL; context = context->next ){ + fingerprint = context->fingerprint_root.next; + while( fingerprint ){ + entry[0] = context->username; + + if( ( context->msgstate == OTRL_MSGSTATE_ENCRYPTED ) && ( context->active_fingerprint != fingerprint ) ){ + entry[1] = i18n("Unused"); + } else { + if (context && context->msgstate == OTRL_MSGSTATE_ENCRYPTED) { + if (context->active_fingerprint->trust && context->active_fingerprint->trust[0] != NULL) { + entry[1] = i18n("Private"); + } else { + entry[1] = i18n("Unverified"); + } + } else if (context && context->msgstate == OTRL_MSGSTATE_FINISHED) { + entry[1] = i18n("Finished"); + } else { + entry[1] = i18n("Not Private"); + } + } + entry[2] = ( fingerprint->trust && fingerprint->trust[0] ) ? i18n("Yes") : i18n("No") ; + otrl_privkey_hash_to_human( hash, fingerprint->fingerprint ); + entry[3] = hash; + entry[4] = context->protocol; + list << entry; + fingerprint = fingerprint->next; + } + } + return list; +} + +void OtrlConfInterface::verifyFingerprint( QString strFingerprint, bool trust ){ + Fingerprint *fingerprint; + + fingerprint = findFingerprint( strFingerprint ); + + 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" ); + } else { + kdDebug() << "could not find fingerprint" << endl; + } +} + +bool OtrlConfInterface::isVerified( QString strFingerprint ){ + Fingerprint *fingerprint; + + fingerprint = findFingerprint( strFingerprint ); + + if( fingerprint->trust && fingerprint->trust[0] ){ + kdDebug() << "found trust" << endl; + return true; + } else { + kdDebug() << "not trusted" << endl; + return false; + } +} + + +void OtrlConfInterface::forgetFingerprint( QString strFingerprint ){ + Fingerprint *fingerprint; + + fingerprint = findFingerprint( strFingerprint ); + otrl_context_forget_fingerprint( fingerprint, 1 ); + otrl_privkey_write_fingerprints( userstate, QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "fingerprints" ); +} + +Fingerprint *OtrlConfInterface::findFingerprint( QString strFingerprint ){ +// const char *cFingerprint = ; +// Fingerprint *fingerprintRoot = &userstate->context_root->fingerprint_root; + ConnContext *context; + Fingerprint *fingerprint; + Fingerprint *foundFingerprint = NULL; + char hash[45]; + + for( context = userstate->context_root; context != NULL; context = context->next ){ + fingerprint = context->fingerprint_root.next; + while( fingerprint ){ + otrl_privkey_hash_to_human(hash, fingerprint->fingerprint); + if( strcmp( hash, strFingerprint.latin1()) == 0 ){ + foundFingerprint = fingerprint; + } + fingerprint = fingerprint->next; + } + } + return foundFingerprint; +} + +bool OtrlConfInterface::isEncrypted( QString strFingerprint ){ + Fingerprint *fingerprint; + Fingerprint *tmpFingerprint; + Fingerprint *foundFingerprint; + ConnContext *context; + ConnContext *foundContext = NULL; + + context = userstate->context_root; + + fingerprint = findFingerprint( strFingerprint ); + for( context = userstate->context_root; context != NULL; context = context->next ){ + tmpFingerprint = context->fingerprint_root.next; + while( tmpFingerprint ){ + if( tmpFingerprint == fingerprint ){ + kdDebug() << "Found context" << endl; + foundContext = context; + foundFingerprint = tmpFingerprint; + } + tmpFingerprint = tmpFingerprint->next; + } + } + + if( foundContext && foundContext->msgstate != OTRL_MSGSTATE_ENCRYPTED ){ + return false; + } else if( foundContext && foundFingerprint && foundContext->active_fingerprint == foundFingerprint ){ + return true; + } else { + return false; + } +} diff --git a/src/otrlconfinterface.h b/src/otrlconfinterface.h new file mode 100644 index 0000000..bb89b3c --- /dev/null +++ b/src/otrlconfinterface.h @@ -0,0 +1,66 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ + +#ifndef OTRLCONFINTERFACE_H +#define OTRLCONFINTERFACE_H + +/** + * @author Michael Zanetti + */ + +#include <qstring.h> +#include <qptrlist.h> +#include <qvaluelist.h> +#include <qthread.h> + +#include <kopetechatsession.h> + +extern "C" { +#include <libotr/privkey.h> +#include <libotr/proto.h> +#include <libotr/message.h> +#include <libotr/userstate.h> +#include <libotr/context.h> +} + +class OtrlConfInterface +{ + +public: + ~OtrlConfInterface(); + OtrlConfInterface( QWidget *preferencesDialog ); + + QString getPrivFingerprint( QString accountId, QString protocol ); + void generateNewPrivKey( QString accountId, QString protocol ); + QValueList<QString[5]> readAllFingerprints(); + bool hasPrivFingerprint( QString accountId, QString protocol); + void forgetFingerprint( QString strFingerprint ); + void verifyFingerprint( QString strFingerprint, bool trust ); + bool isVerified( QString strFingerprint ); + bool isEncrypted( QString strFingerprint ); + +private: + OtrlUserState userstate; + QWidget *preferencesDialog; + + Fingerprint *findFingerprint( QString strFingerprint ); +}; + +#endif diff --git a/src/otrplugin.cpp b/src/otrplugin.cpp new file mode 100644 index 0000000..873c800 --- /dev/null +++ b/src/otrplugin.cpp @@ -0,0 +1,344 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ + +#include <qstylesheet.h> +#include <qtimer.h> +#include <qregexp.h> +#include <qfile.h> +#include <qcolor.h> + +#include <kdebug.h> +#include <kaction.h> +#include <kactionclasses.h> +#include <kpopupmenu.h> +#include <kconfig.h> +#include <kgenericfactory.h> +#include <kdeversion.h> +#include <kaboutdata.h> +#include <kstandarddirs.h> +#include <kmessagebox.h> + +#include <kopetemetacontact.h> +#include <kopetecontactlist.h> +#include <kopetechatsessionmanager.h> +#include <kopetesimplemessagehandler.h> +#include <kopeteuiglobal.h> +#include <kopetecontact.h> +#include <kopetemessage.h> +#include <kopeteaccount.h> +#include <kopeteaccountmanager.h> +#include <kopetemessageevent.h> +#include <kopeteprotocol.h> + +#include "otrplugin.h" +#include "otrguiclient.h" +#include "otrlchatinterface.h" +#include "kopete_otr.h" + +/** + * @author Michael Zanetti + */ + + + +typedef KGenericFactory<OTRPlugin> OTRPluginFactory; +static const KAboutData aboutdata("kopete_otr", I18N_NOOP("OTR") , "0.7" ); +K_EXPORT_COMPONENT_FACTORY( kopete_otr, OTRPluginFactory( &aboutdata ) ) + +OTRPlugin::OTRPlugin( QObject *parent, const char *name, const QStringList & /* args */ ) +: Kopete::Plugin( OTRPluginFactory::instance(), parent, name ) +{ + if( !pluginStatic_ ) + pluginStatic_=this; + + m_inboundHandler = new OtrMessageHandlerFactory(this); + + connect( Kopete::ChatSessionManager::self(), SIGNAL( aboutToSend( Kopete::Message & ) ), + SLOT( slotOutgoingMessage( Kopete::Message & ) ) ); +// connect( Kopete::ChatSessionManager::self(), SIGNAL( aboutToDisplay( Kopete::Message & ) ), +// this, SLOT( slotIncomingMessage( Kopete::Message & ) ) ); + + connect( Kopete::ChatSessionManager::self(), SIGNAL( chatSessionCreated( Kopete::ChatSession * ) ), + this, SLOT( slotNewChatSessionWindow( Kopete::ChatSession * ) ) ); + QObject::connect( this, SIGNAL( settingsChanged() ), this, SLOT( slotSettingsChanged() ) ); + + + + //initialize the otrlib and create the interface object + otrlChatInterface = OtrlChatInterface::self(); + + //update key files when an account is ready to use + if( QFile::exists( QString( KGlobal::dirs()->saveLocation( "data", "kopete_otr/", true ) ) + "privkey" ) && + !QFile::exists( QString( KGlobal::dirs()->saveLocation( "data", "kopete_otr/", true ) ) + "privkeys" ) ){ + kdDebug() << "Detected old format keyfile. Doing updates!" << endl; + kdDebug() << "Reading old keyfile..." << endl; + QFile fpold( QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkey" ); + QString line; + QString file; + if( fpold.open( IO_ReadWrite ) ){ + while( fpold.readLine( line, 100 ) != -1){ + file.append( line ); + } + } + kdDebug() << "Writing new keyfile" << endl; + QFile fpnew( QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkeys" ); + fpnew.open( IO_ReadWrite ); + fpnew.writeBlock( file.latin1(), file.length() ); + fpnew.close(); + kdDebug() << "Writing backup for old keyfile" << endl; + QFile fpbup( QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkey.old" ); + fpbup.open( IO_ReadWrite ); + fpbup.writeBlock( file.latin1(), file.length() ); + fpbup.close(); + kdDebug() << "Deleting old keyfile" << endl; + fpold.remove(); + + kdDebug() << "Reading old fingerprintsfile..." << endl; + QFile fpfingerprintsold( QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "fingerprints" ); + line = ""; + file = ""; + if( fpfingerprintsold.open( IO_ReadWrite ) ){ + while( fpfingerprintsold.readLine( line, 100 ) != -1){ + file.append( line ); + } + } + kdDebug() << "Writing backup for old fingerprintsfile" << endl; + QFile fpfingerprintsbup( QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "fingerprints.old" ); + fpfingerprintsbup.open( IO_ReadWrite ); + fpfingerprintsbup.writeBlock( file.latin1(), file.length() ); + fpfingerprintsbup.close(); + + kdDebug() << "Waiting for accounts to update keyfile format" << endl; + connect( Kopete::AccountManager::self(), SIGNAL( accountRegistered( Kopete::Account * ) ), + this, SLOT( accountReady( Kopete::Account * ) ) ); + } + + // Checking file Permissions + OtrlChatInterface::self()->checkFilePermissions( QString( KGlobal::dirs()->saveLocation( "data", "kopete_otr/", true ) ) + "privkeys" ); + OtrlChatInterface::self()->checkFilePermissions( QString( KGlobal::dirs()->saveLocation( "data", "kopete_otr/", true ) ) + "fingerprints" ); + // Check also file permissions for eventuallly old beckup files + OtrlChatInterface::self()->checkFilePermissions( QString( KGlobal::dirs()->saveLocation( "data", "kopete_otr/", true ) ) + "privkey.old" ); + OtrlChatInterface::self()->checkFilePermissions( QString( KGlobal::dirs()->saveLocation( "data", "kopete_otr/", true ) ) + "fingerprints.old" ); + + //setting the policy + slotSettingsChanged(); + + //adding menu to contaclists menubar and contacts popup menu + QStringList policies; + policies << i18n("&Default") << i18n("Al&ways") << i18n("&Opportunistic") << i18n("&Manual") << i18n("Ne&ver"); + otrPolicyMenu = new KSelectAction( i18n( "&OTR Policy" ), QString::fromLatin1("kopete_otr"), 0, actionCollection(), "otr_policy" ); + otrPolicyMenu->setItems( policies ); + otrPolicyMenu->popupMenu()->insertSeparator( 1 ); + otrPolicyMenu->setEnabled( false ); + connect( otrPolicyMenu, SIGNAL( activated() ), this, SLOT( slotSetPolicy() ) ); + connect( Kopete::ContactList::self(), SIGNAL( metaContactSelected( bool ) ), this, SLOT( slotSelectionChanged( bool ) ) ); + + + setXMLFile( "otrui.rc" ); + + + + //Add GUI action to all already existing kmm + // (if the plugin is launched when kopete already runing) + QValueList<Kopete::ChatSession*> sessions = + Kopete::ChatSessionManager::self()->sessions(); + QValueListIterator<Kopete::ChatSession*> it; + for (it= sessions.begin(); it!=sessions.end() ; ++it){ + slotNewChatSessionWindow( *it ); + } +} + +OTRPlugin::~OTRPlugin() +{ + delete m_inboundHandler; + pluginStatic_ = 0L; + kdDebug() << "Exiting plugin" << endl; +} + + +OTRPlugin* OTRPlugin::plugin() +{ + return pluginStatic_ ; +} + +OTRPlugin* OTRPlugin::pluginStatic_ = 0L; + + +void OTRPlugin::slotNewChatSessionWindow( Kopete::ChatSession *KMM ) +{ + //Check if there is another user in the session. + //If not it could be a Jabber-MUC + //If there are more then one members it is a MUC + // Also don't add the Button on an IRC window! + if( KMM->members().count() == 1 && (KMM->protocol()) && ( KMM->protocol()->pluginId() != "IRCProtocol" ) ){ + new OtrGUIClient( KMM ); + } +} + + +void OTRPlugin::slotOutgoingMessage( Kopete::Message& msg ) +{ + if( msg.direction() == Kopete::Message::Outbound ){ + QString plainBody = msg.plainBody(); + QString accountId = msg.manager()->account()->accountId(); + Kopete::Contact *contact = msg.to().first(); + + QString encBody = otrlChatInterface->encryptMessage( plainBody, accountId, msg.manager()->account()->protocol()->displayName(), contact->contactId(), msg.manager() ); + msg.setBody( encBody, Kopete::Message::Crypted ); + if( !msg.plainBody().isEmpty() ){ + messageCache.insert( encBody, plainBody ); + } + } +} + +void OTRPlugin::slotEnableOtr( Kopete::ChatSession *session, bool enable ){ + + + if( enable ){ + QString policy = session->members().getFirst()->metaContact()->pluginData( OTRPlugin::plugin(), "otr_policy" ); + bool noerr; + KopeteOtrKcfg::self()->readConfig(); + if( policy.toInt( &noerr, 10 ) == 4 || ( policy.toInt( &noerr, 10 ) == 0 && KopeteOtrKcfg::self()->rbNever() ) ){ + Kopete::Message msg( session->account()->myself(), session->members(), i18n( "Your policy settings do not allow encrypted sessions to this contact." ), Kopete::Message::Internal, Kopete::Message::RichText ); + session->appendMessage( msg ); + } else { + QString body = otrlChatInterface->getDefaultQuery( session->account()->accountId() ); + Kopete::Message msg1( session->account()->myself(), session->members().getFirst(), QString( body ), Kopete::Message::Outbound ); + if( otrlChatInterface->privState( session ) > 0 ){ + body = i18n("Attempting to refresh the OTR session with <b>%1</b>...").arg( otrlChatInterface->formatContact( session->members().getFirst()->contactId() ) ); + } else { + body = i18n("Attempting to start a private OTR session with <b>%1</b>...").arg( otrlChatInterface->formatContact( session->members().getFirst()->contactId() ) ); + } + Kopete::Message msg2( session->account()->myself(), session->members().getFirst(), body, Kopete::Message::Internal, Kopete::Message::RichText ); + + session->sendMessage( msg1 ); + session->appendMessage( msg2 ); + } + } else { + otrlChatInterface->disconnectSession( session ); + } + +} + +void OTRPlugin::slotVerifyFingerprint( Kopete::ChatSession *session ){ + otrlChatInterface->verifyFingerprint( session ); +} + +void OTRPlugin::slotSettingsChanged(){ + KopeteOtrKcfg::self()->readConfig(); + if( KopeteOtrKcfg::self()->rbAlways() ){ + otrlChatInterface->setPolicy( OTRL_POLICY_ALWAYS ); + } else if( KopeteOtrKcfg::self()->rbOpportunistic() ){ + otrlChatInterface->setPolicy( OTRL_POLICY_OPPORTUNISTIC ); + } else if( KopeteOtrKcfg::self()->rbManual() ){ + otrlChatInterface->setPolicy( OTRL_POLICY_MANUAL ); + } else if( KopeteOtrKcfg::self()->rbNever() ){ + otrlChatInterface->setPolicy( OTRL_POLICY_NEVER ); + } else { + otrlChatInterface->setPolicy( OTRL_POLICY_DEFAULT ); + } +} + +void OTRPlugin::emitGoneSecure( Kopete::ChatSession *session, int status){ + emit goneSecure( session, status ); +} + +QMap<QString, QString> OTRPlugin::getMessageCache(){ + return messageCache; +} + +void OtrMessageHandler::handleMessage( Kopete::MessageEvent *event ){ + Kopete::Message msg = event->message(); + Kopete::ChatSession *session = msg.manager(); + QMap<QString, QString> messageCache = OTRPlugin::plugin()->getMessageCache(); + + if( msg.direction() == Kopete::Message::Inbound ){ + QString body = msg.parsedBody(); +kdDebug() << "Received Message: " << msg.parsedBody() << endl; + QString accountId = msg.manager()->account()->accountId(); + QString contactId = msg.from()->contactId(); + int ignoremessage = OtrlChatInterface::self()->decryptMessage( &body, accountId, msg.manager()->account()->protocol()->displayName(), contactId, msg.manager() ); + msg.setBody( body, Kopete::Message::RichText ); + if( ignoremessage | OtrlChatInterface::self()->shouldDiscard( msg.plainBody() ) ){ + event->discard(); + return; + } + } else if( msg.direction() == Kopete::Message::Outbound ){ + if( messageCache.contains( msg.plainBody() ) ){ + msg.setBody( messageCache[msg.plainBody()] ); + messageCache.remove( messageCache[msg.plainBody()] ); + if(messageCache.count() > 5) messageCache.clear(); + } + // Check if Message is an OTR message. Should it be discarded or shown? + if( OtrlChatInterface::self()->shouldDiscard( msg.plainBody() ) ){ + event->discard(); + kdDebug() << "discarding" << endl; + return; + } + // If the message is sent while a Finished state libotr deletes the messagetext. + // This prevents the empty message from beeing shown in out chatwindow + if( msg.plainBody().isEmpty() ){ + event->discard(); + return; + } + } + + event->setMessage( msg ); + + MessageHandler::handleMessage( event ); +} + + +void OTRPlugin::slotSelectionChanged( bool single){ + otrPolicyMenu->setEnabled( single ); + + if ( !single ) + return; + + Kopete::MetaContact *metaContact = Kopete::ContactList::self()->selectedMetaContacts().first(); + + QString policy = metaContact->pluginData( this, "otr_policy" ); + + bool noerr; + if ( !policy.isEmpty() && policy != "null" ) + otrPolicyMenu->setCurrentItem( policy.toInt( &noerr, 10 )); + else + otrPolicyMenu->setCurrentItem( 0 ); + +} + +void OTRPlugin::slotSetPolicy(){ + kdDebug() << "Setting contact policy" << endl; + Kopete::MetaContact *metaContact = Kopete::ContactList::self()->selectedMetaContacts().first(); + if( metaContact ){ + metaContact->setPluginData( this, "otr_policy", QString::number( otrPolicyMenu->currentItem() ) ); + } +} + +void OTRPlugin::accountReady( Kopete::Account *account ){ + kdDebug() << "Account " << account->accountId() << " ready. Calling update function."<< endl; + otrlChatInterface->updateKeyfile( account ); +} + + +#include "otrplugin.moc" + +// vim: set noet ts=4 sts=4 sw=4: + diff --git a/src/otrplugin.h b/src/otrplugin.h new file mode 100644 index 0000000..2ce051d --- /dev/null +++ b/src/otrplugin.h @@ -0,0 +1,118 @@ +/*************************************************************************** + otrplugin.h - description + ------------------- + begin : 11 03 2007 + copyright : (C) 2007-2007 by Michael Zanetti + email : michael_zanetti@gmx.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. * + * * + ***************************************************************************/ + +#ifndef OTRPLUGIN_H +#define OTRPLUGIN_H + + +#include "kdebug.h" + +#include <kopeteplugin.h> +#include <kopetemessagehandler.h> + +#include "otrlchatinterface.h" + + +/** + * @author Michael Zanetti + */ + +class OTRPlugin; +class KSelectAction; + +class OtrMessageHandler : public Kopete::MessageHandler +{ +private: + OTRPlugin *plugin; +public: + OtrMessageHandler( OTRPlugin *plugin ) : plugin(plugin) { + kdDebug() << "MessageHandler created" << endl; + } + ~OtrMessageHandler(){ + kdDebug() << "MessageHandler destroyed" << endl; + } + void handleMessage( Kopete::MessageEvent *event ); +}; + +class OtrMessageHandlerFactory : public Kopete::MessageHandlerFactory +{ +private: + OTRPlugin *plugin; + OtrMessageHandler *messageHandler; +public: + OtrMessageHandlerFactory( OTRPlugin *plugin ) : plugin(plugin) {} + Kopete::MessageHandler *create( Kopete::ChatSession *, Kopete::Message::MessageDirection direction ) + { + return new OtrMessageHandler(plugin); + } + int filterPosition( Kopete::ChatSession *, Kopete::Message::MessageDirection ) + { + return Kopete::MessageHandlerFactory::InStageToSent+1; + } +}; + +class OTRPlugin : public Kopete::Plugin +{ + Q_OBJECT + +public: + + static OTRPlugin *plugin(); + + OTRPlugin( QObject *parent, const char *name, const QStringList &args ); + ~OTRPlugin(); + + void emitGoneSecure( Kopete::ChatSession *session, int status ); + QMap<QString, QString> getMessageCache(); + +public slots: + + void slotOutgoingMessage( Kopete::Message& msg ); + void slotEnableOtr( Kopete::ChatSession *session, bool enable ); + void slotSettingsChanged(); + void slotVerifyFingerprint( Kopete::ChatSession *session ); + +private slots: + void slotNewChatSessionWindow(Kopete::ChatSession * ); + void slotSelectionChanged( bool single ); + void slotSetPolicy(); + void accountReady( Kopete::Account *account ); + +private: + static OTRPlugin* pluginStatic_; + OtrMessageHandlerFactory *m_inboundHandler; + OtrlChatInterface *otrlChatInterface; + QMap<QString, QString> messageCache; + KSelectAction* otrPolicyMenu; + +/* KActionMenu *otrPolicyMenuBar; + KActionMenu *otrPolicyPopup; + KAction *otrPolicyDefault; + KAction *otrPolicyAlways; + KAction *otrPolicyOpportunistic; + KAction *otrPolicyManual; + KAction *otrPolicyNever; +// SessionManager manager +*/ + +signals: + void goneSecure( Kopete::ChatSession *session, int state ); + + +}; + +#endif diff --git a/src/otrpreferences.cpp b/src/otrpreferences.cpp new file mode 100644 index 0000000..b056d58 --- /dev/null +++ b/src/otrpreferences.cpp @@ -0,0 +1,199 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ + +#include <qlayout.h> +#include <qlabel.h> +#include <qmap.h> +#include <qptrlist.h> +#include <qcombobox.h> +#include <qstringlist.h> +#include <qtable.h> +#include <qpaintdevicemetrics.h> +#include <qvbox.h> +#include <qradiobutton.h> +#include <qtabwidget.h> + +#include <kgenericfactory.h> +#include <kurlrequester.h> +#include <kmessagebox.h> +#include <kconfig.h> +#include <kapplication.h> +#include <kanimwidget.h> +#include <kpassivepopup.h> +#include <kiconloader.h> +#include <kstandarddirs.h> +#include <kactivelabel.h> + +#include <kopeteaccountmanager.h> +#include <kopeteaccount.h> +#include <kopeteprotocol.h> + +#include "otrprefs.h" +#include "otrpreferences.h" +#include "otrplugin.h" +#include "kopete_otr.h" + +/** + * @author Michael Zanetti + */ + +typedef KGenericFactory<OTRPreferences> OTRPreferencesFactory; +K_EXPORT_COMPONENT_FACTORY( kcm_kopete_otr, OTRPreferencesFactory("kcm_kopete_otr")) + +OTRPreferences::OTRPreferences(QWidget *parent, const char* /*name*/, const QStringList &args) + : KCModule(OTRPreferencesFactory::instance(), parent, args) +{ + ( new QVBoxLayout( this ) )->setAutoAdd( true ); + preferencesDialog = new OTRPrefsUI(this); + + + this->addConfig( KopeteOtrKcfg::self(), preferencesDialog ); + KopeteOtrKcfg::self()->readConfig(); + load(); + + + + otrlConfInterface = new OtrlConfInterface( preferencesDialog ); + + connect( preferencesDialog->btGenFingerprint, SIGNAL(clicked()), SLOT(generateFingerprint())); + connect( preferencesDialog->cbKeys, SIGNAL(activated(int)), SLOT(showPrivFingerprint(int))); + connect( preferencesDialog->btVerify, SIGNAL(clicked()), SLOT(verifyFingerprint())); + connect( preferencesDialog->twSettings, SIGNAL(currentChanged(QWidget *)), SLOT(fillFingerprints())); + connect( preferencesDialog->tbFingerprints, SIGNAL(currentChanged(int, int)), SLOT(updateButtons(int, int))); + connect( preferencesDialog->btForget, SIGNAL( clicked() ), SLOT( forgetFingerprint() ) ); + + int index = 0; + int accountnr = 0; + QPtrList<Kopete::Account> accounts = Kopete::AccountManager::self()->accounts(); + if( !accounts.isEmpty() ){ + for ( QPtrListIterator<Kopete::Account> it( accounts ); + Kopete::Account *account = it.current(); + ++it ){ + if ( account->protocol()->pluginId() != "IRCProtocol" ){ + preferencesDialog->cbKeys->insertItem(account->accountId() + " (" + account->protocol()->displayName() + ")"); + privKeys.insert(index++, accountnr); + } + accountnr++; + } + } + showPrivFingerprint( preferencesDialog->cbKeys->currentItem() ); + + preferencesDialog->tbFingerprints->setColumnWidth( 0, 200 ); + preferencesDialog->tbFingerprints->setColumnWidth( 1, 80 ); + preferencesDialog->tbFingerprints->setColumnWidth( 2, 60 ); + preferencesDialog->tbFingerprints->setColumnWidth( 3, 400 ); + preferencesDialog->tbFingerprints->setColumnWidth( 4, 200 ); + +} + +OTRPreferences::~OTRPreferences(){ +} + +void OTRPreferences::generateFingerprint() +{ + QPtrList<Kopete::Account> accounts = Kopete::AccountManager::self()->accounts(); + + if( (accounts.isEmpty())){ + return; + } + + + Kopete::Account *account = accounts.at( privKeys[preferencesDialog->cbKeys->currentItem()] ); + + if ((otrlConfInterface->hasPrivFingerprint( account->accountId(), account->protocol()->displayName() ) ) && (KMessageBox::questionYesNo(this, i18n("Selected account already has a key. Do you want to create a new one?"), i18n("Overwrite key?")) !=3)) return; + + otrlConfInterface->generateNewPrivKey( account->accountId(), account->protocol()->displayName() ); + showPrivFingerprint( preferencesDialog->cbKeys->currentItem() ); +} + +void OTRPreferences::showPrivFingerprint( int accountnr ) +{ + QPtrList<Kopete::Account> accounts = Kopete::AccountManager::self()->accounts(); + if( !accounts.isEmpty() ){ + Kopete::Account *account = accounts.at(privKeys[accountnr]); + preferencesDialog->tlFingerprint->setText( otrlConfInterface->getPrivFingerprint( account->accountId(), account->protocol()->displayName() ) ); + } +} + +void OTRPreferences::fillFingerprints(){ + QTable *fingerprintsTable = preferencesDialog->tbFingerprints; + preferencesDialog->tbFingerprints->setNumRows(0); + QValueList<QString[5]> list = otrlConfInterface->readAllFingerprints(); + QValueList<QString[5]>::iterator it; + int j = 0; + for( it = list.begin(); it != list.end(); ++it ){ + preferencesDialog->tbFingerprints->setNumRows( preferencesDialog->tbFingerprints->numRows() +1 ); + (*it)[0] = OtrlChatInterface::self()->formatContact((*it)[0]); + for( int i = 0; i < 5; i++ ){ + //preferencesDialog->tbFingerprints->setText(j, i, (*it)[i] ); + fingerprintsTable->setItem(j,i, new QAlignTableItem(fingerprintsTable, QTableItem::Never,(*it)[i],Qt::AlignLeft)); + } + j++; + } + updateButtons( preferencesDialog->tbFingerprints->currentRow(), preferencesDialog->tbFingerprints->currentColumn() ); +} + +void OTRPreferences::verifyFingerprint(){ + + int doVerify = KMessageBox::questionYesNo( + this, + i18n("Please contact %1 via another secure way and verify that the following Fingerprint is correct:").arg(preferencesDialog->tbFingerprints->text( preferencesDialog->tbFingerprints->currentRow(), 0 )) + "\n\n" + preferencesDialog->tbFingerprints->text( preferencesDialog->tbFingerprints->currentRow(), 3 ) + "\n\n" + i18n("Are you sure you want to trust this fingerprint?"), i18n("Verify fingerprint") ); + + + if( doVerify == KMessageBox::Yes ){ + otrlConfInterface->verifyFingerprint( preferencesDialog->tbFingerprints->text( preferencesDialog->tbFingerprints->currentRow(), 3 ), true ); + } else { + otrlConfInterface->verifyFingerprint( preferencesDialog->tbFingerprints->text( preferencesDialog->tbFingerprints->currentRow(), 3 ), false ); + } + fillFingerprints(); +} + +void OTRPreferences::updateButtons( int row, int col ){ + if( row != -1 ){ + if( !otrlConfInterface->isEncrypted( preferencesDialog->tbFingerprints->text( row, 3 ) ) ){ + preferencesDialog->btForget->setEnabled( true ); + } else { + preferencesDialog->btForget->setEnabled( false ); + } + preferencesDialog->btVerify->setEnabled( true ); + } else { + preferencesDialog->btVerify->setEnabled( false ); + preferencesDialog->btForget->setEnabled( false ); + } +} + +void OTRPreferences::forgetFingerprint(){ + if( !otrlConfInterface->isEncrypted( preferencesDialog->tbFingerprints->text( preferencesDialog->tbFingerprints->currentRow(), 3 ) ) ){ + otrlConfInterface->forgetFingerprint( preferencesDialog->tbFingerprints->text( preferencesDialog->tbFingerprints->currentRow(), 3 ) ); + fillFingerprints(); + } else { + updateButtons( preferencesDialog->tbFingerprints->currentRow(), preferencesDialog->tbFingerprints->currentColumn() ); + } +} + +QAlignTableItem :: QAlignTableItem( QTable *table, EditType editType, const QString& text, int alignment ) + : QTableItem( table, editType, text ) { + align = alignment; +} + + +#include "otrpreferences.moc" + +// vim: set noet ts=4 sts=4 sw=4: diff --git a/src/otrpreferences.h b/src/otrpreferences.h new file mode 100644 index 0000000..0de6d5d --- /dev/null +++ b/src/otrpreferences.h @@ -0,0 +1,64 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ + +#ifndef OTRPREFERECES_H +#define OTRPREFERECES_H + +#include <kcmodule.h> +#include "otrlconfinterface.h" + +/** + * Preference widget for the OTR plugin + * @author Michael Zanetti + */ + +class OTRPreferences : public KCModule { + Q_OBJECT + +public: + OTRPreferences(QWidget *parent = 0, const char *name = 0, const QStringList &args = QStringList()); + ~OTRPreferences(); + +private: + OTRPrefsUI *preferencesDialog; + OtrlConfInterface *otrlConfInterface; + QMap<int, int> privKeys; + +private slots: // Public slots + void generateFingerprint(); + void showPrivFingerprint(int accountnr); + void verifyFingerprint(); + void fillFingerprints(); + void updateButtons(int row, int col); + void forgetFingerprint(); + +}; + + +class QAlignTableItem : public QTableItem { + +public : + QAlignTableItem(QTable *table, EditType editType, const QString& text, int alignment); + +private : + int align; +}; + +#endif diff --git a/src/otrprefs.ui b/src/otrprefs.ui new file mode 100644 index 0000000..da1e238 --- /dev/null +++ b/src/otrprefs.ui @@ -0,0 +1,295 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>OTRPrefsUI</class> +<widget class="QWidget"> + <property name="name"> + <cstring>OTRPrefsUI</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>480</width> + <height>358</height> + </rect> + </property> + <property name="caption"> + <string>Form1</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QTabWidget" row="0" column="0"> + <property name="name"> + <cstring>twSettings</cstring> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>settings</cstring> + </property> + <attribute name="title"> + <string>&Settings</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox" row="0" column="0"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Private Keys</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton" row="0" column="2"> + <property name="name"> + <cstring>btGenFingerprint</cstring> + </property> + <property name="text"> + <string>&Generate</string> + </property> + <property name="accel"> + <string>Alt+G</string> + </property> + </widget> + <widget class="QComboBox" row="0" column="1"> + <property name="name"> + <cstring>cbKeys</cstring> + </property> + <property name="maximumSize"> + <size> + <width>400</width> + <height>32767</height> + </size> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Account:</string> + </property> + </widget> + <widget class="KActiveLabel" row="1" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>tlFingerprint</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>No Fingerprint</string> + </property> + </widget> + </grid> + </widget> + <widget class="QButtonGroup" row="1" column="0"> + <property name="name"> + <cstring>bgPolicy</cstring> + </property> + <property name="title"> + <string>Default Policy</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton" row="1" column="0"> + <property name="name"> + <cstring>kcfg_rbOpportunistic</cstring> + </property> + <property name="text"> + <string>&Opportunistic</string> + </property> + <property name="accel"> + <string>Alt+O</string> + </property> + <property name="toolTip" stdset="0"> + <string>Encrypt messages automatically if the other side supports OTR</string> + </property> + </widget> + <widget class="QRadioButton" row="1" column="1"> + <property name="name"> + <cstring>kcfg_rbNever</cstring> + </property> + <property name="text"> + <string>Ne&ver</string> + </property> + <property name="accel"> + <string>Alt+V</string> + </property> + <property name="toolTip" stdset="0"> + <string>Never encrypt messages</string> + </property> + </widget> + <widget class="QRadioButton" row="0" column="1"> + <property name="name"> + <cstring>kcfg_rbManual</cstring> + </property> + <property name="text"> + <string>&Manual</string> + </property> + <property name="accel"> + <string>Alt+M</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <property name="toolTip" stdset="0"> + <string>Encrypt messages if the other side requests an OTR connection</string> + </property> + </widget> + <widget class="QRadioButton" row="0" column="0"> + <property name="name"> + <cstring>kcfg_rbAlways</cstring> + </property> + <property name="autoMask"> + <bool>false</bool> + </property> + <property name="text"> + <string>Al&ways</string> + </property> + <property name="accel"> + <string>Alt+W</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <property name="toolTip" stdset="0"> + <string>Always encrypt messages</string> + </property> + </widget> + </grid> + </widget> + <spacer row="2" column="0"> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>161</height> + </size> + </property> + </spacer> + </grid> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>fingerprints</cstring> + </property> + <attribute name="title"> + <string>K&nown Fingerprints</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QTable" row="0" column="0" rowspan="1" colspan="2"> + <column> + <property name="text"> + <string>User</string> + </property> + </column> + <column> + <property name="text"> + <string>Status</string> + </property> + </column> + <column> + <property name="text"> + <string>Verified</string> + </property> + </column> + <column> + <property name="text"> + <string>Fingerprint</string> + </property> + </column> + <column> + <property name="text"> + <string>Protocol</string> + </property> + </column> + <property name="name"> + <cstring>tbFingerprints</cstring> + </property> + <property name="numRows"> + <number>1</number> + </property> + <property name="numCols"> + <number>5</number> + </property> + <property name="showGrid"> + <bool>true</bool> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="sorting"> + <bool>false</bool> + </property> + <property name="selectionMode"> + <enum>SingleRow</enum> + </property> + <property name="focusStyle"> + <enum>FollowStyle</enum> + </property> + </widget> + <widget class="QPushButton" row="1" column="0"> + <property name="name"> + <cstring>btVerify</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>&Verify Fingerprint</string> + </property> + <property name="accel"> + <string>Alt+V</string> + </property> + </widget> + <widget class="QPushButton" row="1" column="1"> + <property name="name"> + <cstring>btForget</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>F&orget Fingerprint</string> + </property> + <property name="accel"> + <string>Alt+O</string> + </property> + </widget> + </grid> + </widget> + </widget> + </grid> +</widget> +<slots> + <slot access="private">generateFingerprint()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kactivelabel.h</includehint> +</includehints> +</UI> diff --git a/src/otrui.rc b/src/otrui.rc new file mode 100644 index 0000000..7b889e3 --- /dev/null +++ b/src/otrui.rc @@ -0,0 +1,12 @@ +<!DOCTYPE kpartgui> +<kpartgui name="kopete_otr" version="1"> + <MenuBar> + <Menu name="edit"> + <text>&Edit</text> + <Action name="otr_policy" /> + </Menu> + </MenuBar> + <Menu name="contact_popup"> + <Action name="otr_policy" /> + </Menu> +</kpartgui> diff --git a/src/pics/Makefile.am b/src/pics/Makefile.am new file mode 100644 index 0000000..60c5e4f --- /dev/null +++ b/src/pics/Makefile.am @@ -0,0 +1,4 @@ +icondir = $(kde_datadir)/kopete_otr/icons +icon_ICON = AUTO +KDE_ICON = kopete_otr + diff --git a/src/pics/cr16-action-otr_disabled.png b/src/pics/cr16-action-otr_disabled.png Binary files differnew file mode 100644 index 0000000..90e5806 --- /dev/null +++ b/src/pics/cr16-action-otr_disabled.png diff --git a/src/pics/cr16-action-otr_finished.png b/src/pics/cr16-action-otr_finished.png Binary files differnew file mode 100644 index 0000000..ab9a68d --- /dev/null +++ b/src/pics/cr16-action-otr_finished.png diff --git a/src/pics/cr16-action-otr_private.png b/src/pics/cr16-action-otr_private.png Binary files differnew file mode 100644 index 0000000..2fc54e2 --- /dev/null +++ b/src/pics/cr16-action-otr_private.png diff --git a/src/pics/cr16-action-otr_unverified.png b/src/pics/cr16-action-otr_unverified.png Binary files differnew file mode 100644 index 0000000..e1db6c6 --- /dev/null +++ b/src/pics/cr16-action-otr_unverified.png diff --git a/src/pics/cr16-app-kopete_otr.png b/src/pics/cr16-app-kopete_otr.png Binary files differnew file mode 100644 index 0000000..0f2ce8e --- /dev/null +++ b/src/pics/cr16-app-kopete_otr.png diff --git a/src/pics/cr16-app-otr.png b/src/pics/cr16-app-otr.png Binary files differnew file mode 100644 index 0000000..2fc54e2 --- /dev/null +++ b/src/pics/cr16-app-otr.png diff --git a/src/pics/cr22-action-otr_disabled.png b/src/pics/cr22-action-otr_disabled.png Binary files differnew file mode 100644 index 0000000..fe9332a --- /dev/null +++ b/src/pics/cr22-action-otr_disabled.png diff --git a/src/pics/cr22-action-otr_finished.png b/src/pics/cr22-action-otr_finished.png Binary files differnew file mode 100644 index 0000000..f85fa05 --- /dev/null +++ b/src/pics/cr22-action-otr_finished.png diff --git a/src/pics/cr22-action-otr_private.png b/src/pics/cr22-action-otr_private.png Binary files differnew file mode 100644 index 0000000..767f0a0 --- /dev/null +++ b/src/pics/cr22-action-otr_private.png diff --git a/src/pics/cr22-action-otr_unverified.png b/src/pics/cr22-action-otr_unverified.png Binary files differnew file mode 100644 index 0000000..b37b39e --- /dev/null +++ b/src/pics/cr22-action-otr_unverified.png diff --git a/src/pics/cr32-action-otr_disabled.png b/src/pics/cr32-action-otr_disabled.png Binary files differnew file mode 100644 index 0000000..39e2aba --- /dev/null +++ b/src/pics/cr32-action-otr_disabled.png diff --git a/src/pics/cr32-action-otr_finished.png b/src/pics/cr32-action-otr_finished.png Binary files differnew file mode 100644 index 0000000..c0158fc --- /dev/null +++ b/src/pics/cr32-action-otr_finished.png diff --git a/src/pics/cr32-action-otr_private.png b/src/pics/cr32-action-otr_private.png Binary files differnew file mode 100644 index 0000000..cbf4b6a --- /dev/null +++ b/src/pics/cr32-action-otr_private.png diff --git a/src/pics/cr32-action-otr_unverified.png b/src/pics/cr32-action-otr_unverified.png Binary files differnew file mode 100644 index 0000000..fa3d91e --- /dev/null +++ b/src/pics/cr32-action-otr_unverified.png diff --git a/src/privkeypopup.cpp b/src/privkeypopup.cpp new file mode 100644 index 0000000..0fbdc60 --- /dev/null +++ b/src/privkeypopup.cpp @@ -0,0 +1,52 @@ +/*************************************************************************** + * 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 "privkeypopup.h" + +PrivKeyPopup::PrivKeyPopup(QWidget* parent, const char* name, WFlags fl) +: PrivKeyPopupUI(parent,name,fl) +{ +} + +PrivKeyPopup::~PrivKeyPopup() +{ +} + +void PrivKeyPopup::setCloseLock( bool locked ){ + closeLock = locked; +} + +void PrivKeyPopup::closeEvent( QCloseEvent *e ){ + if( closeLock ){ + e->ignore(); + } else { + e->accept(); + } +} +/*$SPECIALIZATION$*/ + + +#include "privkeypopup.moc" + diff --git a/src/privkeypopup.h b/src/privkeypopup.h new file mode 100644 index 0000000..7730356 --- /dev/null +++ b/src/privkeypopup.h @@ -0,0 +1,55 @@ +/*************************************************************************** + * Copyright (C) 2007 by Michael Zanetti * + * michael_zanetti@gmx.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. * + ***************************************************************************/ + +#ifndef PRIVKEYPOPUP_H +#define PRIVKEYPOPUP_H + +#include "privkeypopupui.h" + +/** + * @author Michael Zanetti + */ + +class PrivKeyPopup : public PrivKeyPopupUI +{ + Q_OBJECT + +public: + PrivKeyPopup(QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~PrivKeyPopup(); + void setCloseLock( bool locked ); + /*$PUBLIC_FUNCTIONS$*/ + +public slots: + /*$PUBLIC_SLOTS$*/ + +protected: + /*$PROTECTED_FUNCTIONS$*/ + bool closeLock; + + void closeEvent( QCloseEvent *e ); + +protected slots: + /*$PROTECTED_SLOTS$*/ + +}; + +#endif + diff --git a/src/privkeypopupui.ui b/src/privkeypopupui.ui new file mode 100644 index 0000000..e9fdd75 --- /dev/null +++ b/src/privkeypopupui.ui @@ -0,0 +1,64 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>PrivKeyPopupUI</class> +<widget class="QWidget"> + <property name="name"> + <cstring>PrivKeyPopupUI</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>507</width> + <height>111</height> + </rect> + </property> + <property name="caption"> + <string>Generating private key</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>tlWait</cstring> + </property> + <property name="font"> + <font> + <bold>1</bold> + <italic>1</italic> + </font> + </property> + <property name="text"> + <string>Please wait while generating the private key</string> + </property> + </widget> + <widget class="QFrame" row="0" column="1"> + <property name="name"> + <cstring>animFrame</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>72</width> + <height>72</height> + </size> + </property> + <property name="frameShape"> + <enum>StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + </widget> + </grid> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/src/smppopup.cpp b/src/smppopup.cpp new file mode 100644 index 0000000..a431e10 --- /dev/null +++ b/src/smppopup.cpp @@ -0,0 +1,71 @@ +/*************************************************************************** + * Copyright (C) 2007 by Michael Zanetti * + * michael_zanetti@gmx.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. * + ***************************************************************************/ + +#include "qlabel.h" + +#include "kdebug.h" +#include "klocale.h" +#include "klineedit.h" +#include "kurl.h" +#include "krun.h" + +#include "smppopup.h" +#include "verifypopup.h" + +SMPPopup::SMPPopup(QWidget* parent, const char* name, WFlags fl, ConnContext *context, Kopete::ChatSession *session, bool initiate ) +: SMPPopupUI(parent,name,fl) +{ + this->context = context; + this->session = session; + this->initiate = initiate; + tlText->setText( i18n("Please enter the secret passphrase to authenticate %1:").arg(OtrlChatInterface::self()->formatContact(session->members().getFirst()->contactId()))); +} + +SMPPopup::~SMPPopup() +{ +} + +/*$SPECIALIZATION$*/ +void SMPPopup::cancelSMP() +{ + OtrlChatInterface::self()->abortSMP( context, session ); + this->close(); +} + +void SMPPopup::respondSMP() +{ + OtrlChatInterface::self()->respondSMP( context, session, leSecret->text(), initiate ); + this->close(); +} + +void SMPPopup::openHelp() +{ + KURL *url = new KURL("http://www.cypherpunks.ca/otr/help/authenticate.php?lang=en"); + new KRun(*url, 0, false, true); +} + +void SMPPopup::manualAuth(){ + VerifyPopup *vfPopup = new VerifyPopup(this, i18n("Verify Fingerprint"), session); + vfPopup->show(); + this->close(); +} + +#include "smppopup.moc" + diff --git a/src/smppopup.h b/src/smppopup.h new file mode 100644 index 0000000..b486c65 --- /dev/null +++ b/src/smppopup.h @@ -0,0 +1,62 @@ +/*************************************************************************** + * Copyright (C) 2007 by Michael Zanetti * + * michael_zanetti@gmx.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. * + ***************************************************************************/ + +#ifndef SMPPOPUP_H +#define SMPPOPUP_H + +#include "kopetechatsession.h" + +#include "smppopupui.h" +#include "otrlchatinterface.h" + +extern "C"{ +#include "libotr/proto.h" +} + +class SMPPopup : public SMPPopupUI +{ + Q_OBJECT + +public: + SMPPopup(QWidget* parent = 0, const char* name = 0, WFlags fl = 0, ConnContext *context = 0, Kopete::ChatSession *session = 0, bool initiate = true ); + ~SMPPopup(); + /*$PUBLIC_FUNCTIONS$*/ + +public slots: + /*$PUBLIC_SLOTS$*/ + virtual void cancelSMP(); + virtual void respondSMP(); + virtual void openHelp(); + virtual void manualAuth(); + +protected: + /*$PROTECTED_FUNCTIONS$*/ + + ConnContext *context; + Kopete::ChatSession *session; + bool initiate; + +protected slots: + /*$PROTECTED_SLOTS$*/ + +}; + +#endif + diff --git a/src/smppopupui.ui b/src/smppopupui.ui new file mode 100644 index 0000000..4120e3c --- /dev/null +++ b/src/smppopupui.ui @@ -0,0 +1,191 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>SMPPopupUI</class> +<widget class="QWidget"> + <property name="name"> + <cstring>SMPPopupUI</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>536</width> + <height>158</height> + </rect> + </property> + <property name="caption"> + <string>Enter authentication secret</string> + </property> + <widget class="KPushButton"> + <property name="name"> + <cstring>pbOK</cstring> + </property> + <property name="geometry"> + <rect> + <x>430</x> + <y>110</y> + <width>90</width> + <height>30</height> + </rect> + </property> + <property name="text"> + <string>&OK</string> + </property> + <property name="accel"> + <string>Alt+O</string> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>pbCancel</cstring> + </property> + <property name="geometry"> + <rect> + <x>330</x> + <y>110</y> + <width>91</width> + <height>31</height> + </rect> + </property> + <property name="text"> + <string>&Cancel</string> + </property> + <property name="accel"> + <string>Alt+C</string> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>leSecret</cstring> + </property> + <property name="geometry"> + <rect> + <x>120</x> + <y>70</y> + <width>400</width> + <height>23</height> + </rect> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>tlText</cstring> + </property> + <property name="geometry"> + <rect> + <x>124</x> + <y>10</y> + <width>390</width> + <height>50</height> + </rect> + </property> + <property name="text"> + <string>Please enter the secret passphrase to authenticate this contact.</string> + </property> + <property name="alignment"> + <set>WordBreak|AlignVCenter</set> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>pLIcon</cstring> + </property> + <property name="geometry"> + <rect> + <x>30</x> + <y>30</y> + <width>50</width> + <height>50</height> + </rect> + </property> + <property name="pixmap"> + <pixmap>image0</pixmap> + </property> + <property name="scaledContents"> + <bool>true</bool> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>pbManual</cstring> + </property> + <property name="geometry"> + <rect> + <x>110</x> + <y>110</y> + <width>160</width> + <height>30</height> + </rect> + </property> + <property name="text"> + <string>&Manual Authentication</string> + </property> + <property name="accel"> + <string>Alt+M</string> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>pbHelp</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>110</y> + <width>90</width> + <height>30</height> + </rect> + </property> + <property name="text"> + <string>&Help</string> + </property> + <property name="accel"> + <string>Alt+H</string> + </property> + </widget> +</widget> +<images> + <image name="image0"> + <data format="PNG" length="1360">89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af400000517494441545885c5975d68544714c77f7b5db39b98adf95851a34913158dd1b452db2a488badb5155bfba22f3e54a4da421ffa609fa42fea83a0f8509fc5071529a894422988156cc552d4b40113129ae826249b8fc664f3b17befeede3b7766fa70633edc9bcdfa517ae0b2c3ec9df9ffce393367e6c2ff6c81671d70f6ecb5b052aa1ea80b0428d39acf95523d528a96870fdb2e9e3f7f7a0490ff09c09933df6f0f04025b57adaa0aad5cb98468743152cae3c9a4c5a347fdf4f58d904e9be75a5bef9fb87af5dc502120c142844f9ebc180e040207972faf5cba7bf756caca220402b3d9376d5acbe0e030376ffef9a5d65bde1d1a1af8f8f6ed9fe380c837f782f9c48f1d3b1f564a1f6c6c5cbd74dfbef7282e0e23a5249d4e639a2696656dcf64321886414545191b36d4313c3c1e0d85a2bb1c277bbdbfbf3b05a8e706d8b66df70735354bd7eddfbf13e089287d7d8f696fefa1ab6b60bb942eb69dc6b66d2291080d0d75c462f16830f84a4553d3ad5f0107d0cf0c70e4c877658661ec3d74e8138a8bc32493499249936bd76e73e7ce03f1e0415b4f2cd65bdad939581a8f274a4b4a0c5cd7211a8d5255554e6b6bfc3521c42f7d7db17f00d74f23ef1a504a6fddb8b18ecaca322ccbc2b66d2e5fbe4947c7c3aeebd72f350d0dc54da005d0070e1cfd7a74347978cf9e370887c3545757b3624505f5f56f7e71f7ee8d76c0f68330f2010821963534d4a1b5c6344d9a9b3be9ea8a8f5db870f2f7a1a1f828300e7403dd972e9dfa369148fc78efde437a7b7b0158bffe550c63613d100116fa69e405705df9eaaa55556432198410343777d2d3d3f13790054cc00292400a48f4f5751defee7e4c369b656c6c8cdada65048345af038b9e0bc0715c8a8b4308211042e03882f1f144122f9c4f2f2c75e3c6a576cbca2284606464844864118ee302143147bae74b018ee3e0380eaeeb22844029adf10a8cdfd6924208b4d64829a7c0f116bb6fd19b270202dbb6b16d7b7232172925ccb1a500ed385edd715d77123e6f1dca0fa0b5c6b66d1cc799f45ea1e7929e316626809e67806f5edace36d41b06cb7febed24db761129250b1c87cd65dd6cfe30b1a66aefdaf2c5c50b8461a0811d33c7fe31d049c59843d029412e2c62476d279f1d5d7d3800773e3d15bbcc53e9cbc94bd3e9865d0b17b025525343a4ba26bfbb9e1d9fef8554bc97546f2f89943cbfe344c73778bb47f946209d61cb9a8fdea7eaed46d08ff016fb8bd992b7d631d0b48c891bf70f03a7810120ed0b30616942e551b0aebc1471004c9b506c88096b11403990981320696adc4c3f64ad9723ee2a6819c44d2b92a606af204d2d7e9f0880b415647dcf8e6733a9a0fd31a46ca41364c2c7a7dc08581ad75690cdbf7fe7354742f728980e488deb289256ee96cc8d80a9716d099917888069c3401284f2a2a03c8009b300005782769f330552c1681a5236280d524f0168a9717d6e88fef7019127056ad20bada70bb2ab4048b09c59a2d3bf936d1ff30770d5740a828657aeb49e9e4ca9c94967b4fdfa6601f897e4390024d8024a439eb8d4d31ecd122db0efb922505234dd7e2a9fd30279fa72009e2502a1a0e7b9abc8c9a35f6e0b85f231dfe37860d800a3d203987aa43749bebe9cffa79f8154a8b00848a5e33ffdf05775ac71392b226970b39e074f56fdccf6938539ab9dfb5e7faa88b69152d28e6cc53b8ea7f291731cefac5f1aa9ad2c79a72868546b5dd0b7e35705bcc34446b4dcea787c6530998d0171bc4badaf8001848030de65723e88658500e09dff16308677937601fe058d04715d6cb9690e0000000049454e44ae426082</data> + </image> +</images> +<connections> + <connection> + <sender>pbCancel</sender> + <signal>clicked()</signal> + <receiver>SMPPopupUI</receiver> + <slot>cancelSMP()</slot> + </connection> + <connection> + <sender>pbOK</sender> + <signal>clicked()</signal> + <receiver>SMPPopupUI</receiver> + <slot>respondSMP()</slot> + </connection> + <connection> + <sender>pbHelp</sender> + <signal>clicked()</signal> + <receiver>SMPPopupUI</receiver> + <slot>openHelp()</slot> + </connection> + <connection> + <sender>pbManual</sender> + <signal>clicked()</signal> + <receiver>SMPPopupUI</receiver> + <slot>manualAuth()</slot> + </connection> +</connections> +<slots> + <slot>manualAuth()</slot> + <slot>respondSMP()</slot> + <slot>openHelp()</slot> + <slot>cancelSMP()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/src/verifypopup.cpp b/src/verifypopup.cpp new file mode 100644 index 0000000..d647948 --- /dev/null +++ b/src/verifypopup.cpp @@ -0,0 +1,69 @@ +/*************************************************************************** + * Copyright (C) 2007 by Michael Zanetti * + * michael_zanetti@gmx.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. * + ***************************************************************************/ + + +#include "verifypopup.h" +#include "otrlchatinterface.h" +#include "otrplugin.h" + +#include "qlabel.h" + +#include "klocale.h" +#include "kactivelabel.h" +#include "kcombobox.h" + +#include "kopetechatsession.h" +#include "kopetecontact.h" + +VerifyPopup::VerifyPopup(QWidget* parent, const char* name, Kopete::ChatSession *session, bool modal, WFlags fl) +: VerifyPopupUI(parent,name, modal,fl) +{ + this->session = session; + alContact->setText(i18n("Verify fingerprint for %1.").arg(OtrlChatInterface::self()->formatContact(session->members().getFirst()->contactId()))); + alFingerprint->setText(i18n("The received fingerprint is:\n\n%1\n\nContact %2 via another secure channel and verify that this fingerprint is correct.").arg(OtrlChatInterface::self()->findActiveFingerprint(session)).arg(OtrlChatInterface::self()->formatContact(session->members().getFirst()->contactId()))); + alVerified->setText(i18n("verified that this is in fact the correct fingerprint for %1").arg(OtrlChatInterface::self()->formatContact(session->members().getFirst()->contactId()))); + cbVerify->insertItem(i18n("I have not")); + cbVerify->insertItem(i18n("I have")); + if( OtrlChatInterface::self()->isVerified(session)){ + cbVerify->setCurrentItem(1); + } else { + cbVerify->setCurrentItem(0); + } +} + +VerifyPopup::~VerifyPopup() +{ +} + +void VerifyPopup::cbChanged(){ + kdDebug() << "combobox changed" << endl; + if( cbVerify->currentItem() == 0 ){ + OtrlChatInterface::self()->setTrust(session, false); + } else { + OtrlChatInterface::self()->setTrust(session, true); + } + OTRPlugin::plugin()->emitGoneSecure( session, OtrlChatInterface::self()->privState( session ) ); +} + +/*$SPECIALIZATION$*/ + + +#include "verifypopup.moc" + diff --git a/src/verifypopup.h b/src/verifypopup.h new file mode 100644 index 0000000..212f692 --- /dev/null +++ b/src/verifypopup.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (C) 2007 by Michael Zanetti * + * michael_zanetti@gmx.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. * + ***************************************************************************/ + +#ifndef VERIFYPOPUP_H +#define VERIFYPOPUP_H + +#include "verifypopupui.h" +#include "kopetechatsession.h" + +class VerifyPopup : public VerifyPopupUI +{ + Q_OBJECT + +public: + VerifyPopup(QWidget* parent = 0, const char* name = 0, Kopete::ChatSession *session = NULL, bool modal = FALSE, WFlags fl = 0 ); + ~VerifyPopup(); + /*$PUBLIC_FUNCTIONS$*/ + +public slots: + /*$PUBLIC_SLOTS$*/ + virtual void cbChanged(); + +protected: + /*$PROTECTED_FUNCTIONS$*/ + Kopete::ChatSession *session; + +protected slots: + /*$PROTECTED_SLOTS$*/ + +}; + +#endif + diff --git a/src/verifypopupui.ui b/src/verifypopupui.ui new file mode 100644 index 0000000..054858e --- /dev/null +++ b/src/verifypopupui.ui @@ -0,0 +1,113 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>VerifyPopupUI</class> +<widget class="QDialog"> + <property name="name"> + <cstring>VerifyPopupUI</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>605</width> + <height>250</height> + </rect> + </property> + <property name="caption"> + <string>Verify Fingerprint</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KPushButton" row="3" column="2"> + <property name="name"> + <cstring>pbOK</cstring> + </property> + <property name="text"> + <string>&OK</string> + </property> + <property name="accel"> + <string>Alt+O</string> + </property> + </widget> + <spacer row="3" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>461</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KActiveLabel" row="2" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>alVerified</cstring> + </property> + </widget> + <widget class="KComboBox" row="2" column="0"> + <property name="name"> + <cstring>cbVerify</cstring> + </property> + <property name="maximumSize"> + <size> + <width>130</width> + <height>32767</height> + </size> + </property> + </widget> + <widget class="KActiveLabel" row="0" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>alContact</cstring> + </property> + <property name="font"> + <font> + <pointsize>12</pointsize> + </font> + </property> + </widget> + <widget class="QLabel" row="1" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>alFingerprint</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="alignment"> + <set>WordBreak|AlignVCenter</set> + </property> + </widget> + </grid> +</widget> +<connections> + <connection> + <sender>cbVerify</sender> + <signal>activated(int)</signal> + <receiver>VerifyPopupUI</receiver> + <slot>cbChanged()</slot> + </connection> + <connection> + <sender>pbOK</sender> + <signal>clicked()</signal> + <receiver>VerifyPopupUI</receiver> + <slot>close()</slot> + </connection> +</connections> +<slots> + <slot>cbChanged()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kpushbutton.h</includehint> + <includehint>kactivelabel.h</includehint> + <includehint>kcombobox.h</includehint> + <includehint>kactivelabel.h</includehint> +</includehints> +</UI> |