diff options
Diffstat (limited to 'kopete/plugins/cryptography/cryptographyplugin.cpp')
-rw-r--r-- | kopete/plugins/cryptography/cryptographyplugin.cpp | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/kopete/plugins/cryptography/cryptographyplugin.cpp b/kopete/plugins/cryptography/cryptographyplugin.cpp new file mode 100644 index 00000000..701ad8bd --- /dev/null +++ b/kopete/plugins/cryptography/cryptographyplugin.cpp @@ -0,0 +1,326 @@ +/*************************************************************************** + cryptographyplugin.cpp - description + ------------------- + begin : jeu nov 14 2002 + copyright : (C) 2002-2004 by Olivier Goffart + email : ogoffart @ kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include <qstylesheet.h> +#include <qtimer.h> +#include <qregexp.h> + +#include <kdebug.h> +#include <kaction.h> +#include <kconfig.h> +#include <kgenericfactory.h> +#include <kdeversion.h> +#include <kaboutdata.h> + +#include "kopetemetacontact.h" +#include "kopetecontactlist.h" +#include "kopetechatsessionmanager.h" +#include "kopetesimplemessagehandler.h" +#include "kopeteuiglobal.h" +#include "kopetecontact.h" + +#include "cryptographyplugin.h" +#include "cryptographyselectuserkey.h" +#include "cryptographyguiclient.h" + +#include "kgpginterface.h" + +//This regexp try to match an HTML text, but only some authorized tags. +// used in slotIncomingMessage +//There are not rules to know if the test should be sent in html or not. +//In Jabber, the JEP says it's not. so we don't use richtext in our message, but some client did. +//We limit the html to some basis tag to limit security problem (bad links) +// - Olivier +const QRegExp CryptographyPlugin::isHTML( QString::fromLatin1( "^[^<>]*(</?(html|body|br|p|font|center|b|i|u|span|div|pre)(>|[\\s/][^><]*>)[^><]*)+$" ) , false ); + +typedef KGenericFactory<CryptographyPlugin> CryptographyPluginFactory; +static const KAboutData aboutdata("kopete_cryptography", I18N_NOOP("Cryptography") , "1.0" ); +K_EXPORT_COMPONENT_FACTORY( kopete_cryptography, CryptographyPluginFactory( &aboutdata ) ) + +CryptographyPlugin::CryptographyPlugin( QObject *parent, const char *name, const QStringList & /* args */ ) +: Kopete::Plugin( CryptographyPluginFactory::instance(), parent, name ), + m_cachedPass() +{ + if( !pluginStatic_ ) + pluginStatic_=this; + + m_inboundHandler = new Kopete::SimpleMessageHandlerFactory( Kopete::Message::Inbound, + Kopete::MessageHandlerFactory::InStageToSent, this, SLOT( slotIncomingMessage( Kopete::Message& ) ) ); + connect( Kopete::ChatSessionManager::self(), + SIGNAL( aboutToSend( Kopete::Message & ) ), + SLOT( slotOutgoingMessage( Kopete::Message & ) ) ); + + m_cachedPass_timer = new QTimer(this, "m_cachedPass_timer" ); + QObject::connect(m_cachedPass_timer, SIGNAL(timeout()), this, SLOT(slotForgetCachedPass() )); + + + KAction *action=new KAction( i18n("&Select Cryptography Public Key..."), "encrypted", 0, this, SLOT (slotSelectContactKey()), actionCollection() , "contactSelectKey"); + connect ( Kopete::ContactList::self() , SIGNAL( metaContactSelected(bool)) , action , SLOT(setEnabled(bool))); + action->setEnabled(Kopete::ContactList::self()->selectedMetaContacts().count()==1 ); + + setXMLFile("cryptographyui.rc"); + loadSettings(); + connect(this, SIGNAL(settingsChanged()), this, SLOT( loadSettings() ) ); + + connect( Kopete::ChatSessionManager::self(), SIGNAL( chatSessionCreated( Kopete::ChatSession * )) , SLOT( slotNewKMM( Kopete::ChatSession * ) ) ); + //Add GUI action to all already existing kmm (if the plugin is launched when kopete already rining) + QValueList<Kopete::ChatSession*> sessions = Kopete::ChatSessionManager::self()->sessions(); + for (QValueListIterator<Kopete::ChatSession*> it= sessions.begin(); it!=sessions.end() ; ++it) + { + slotNewKMM(*it); + } + +} + +CryptographyPlugin::~CryptographyPlugin() +{ + delete m_inboundHandler; + pluginStatic_ = 0L; +} + +void CryptographyPlugin::loadSettings() +{ + KConfig *config = KGlobal::config(); + config->setGroup("Cryptography Plugin"); + + mPrivateKeyID = config->readEntry("PGP_private_key"); + mAlsoMyKey = config->readBoolEntry("Also_my_key", false); + + if(config->readBoolEntry("Cache_Till_App_Close", false)) + mCachePassPhrase = Keep; + if(config->readBoolEntry("Cache_Till_Time", false)) + mCachePassPhrase = Time; + if(config->readBoolEntry("Cache_Never", false)) + mCachePassPhrase = Never; + mCacheTime = config->readNumEntry("Cache_Time", 15); + mAskPassPhrase = config->readBoolEntry("No_Passphrase_Handling", false); +} + +CryptographyPlugin* CryptographyPlugin::plugin() +{ + return pluginStatic_ ; +} + +CryptographyPlugin* CryptographyPlugin::pluginStatic_ = 0L; + +QCString CryptographyPlugin::cachedPass() +{ + return pluginStatic_->m_cachedPass; +} + +void CryptographyPlugin::setCachedPass(const QCString& p) +{ + if(pluginStatic_->mCacheMode==Never) + return; + if(pluginStatic_->mCacheMode==Time) + pluginStatic_->m_cachedPass_timer->start(pluginStatic_->mCacheTime * 60000, false); + + pluginStatic_->m_cachedPass=p; +} + +bool CryptographyPlugin::passphraseHandling() +{ + return !pluginStatic_->mAskPassPhrase; +} + + +/*KActionCollection *CryptographyPlugin::customChatActions(Kopete::ChatSession *KMM) +{ + delete m_actionCollection; + + m_actionCollection = new KActionCollection(this); + KAction *actionTranslate = new KAction( i18n ("Translate"), 0, + this, SLOT( slotTranslateChat() ), m_actionCollection, "actionTranslate" ); + m_actionCollection->insert( actionTranslate ); + + m_currentChatSession=KMM; + return m_actionCollection; +}*/ + +void CryptographyPlugin::slotIncomingMessage( Kopete::Message& msg ) +{ + QString body = msg.plainBody(); + if( !body.startsWith( QString::fromLatin1("-----BEGIN PGP MESSAGE----") ) + || !body.contains( QString::fromLatin1("-----END PGP MESSAGE----") ) ) + return; + + if( msg.direction() != Kopete::Message::Inbound ) + { + QString plainBody; + if ( m_cachedMessages.contains( body ) ) + { + plainBody = m_cachedMessages[ body ]; + m_cachedMessages.remove( body ); + } + else + { + plainBody = KgpgInterface::KgpgDecryptText( body, mPrivateKeyID ); + } + + if( !plainBody.isEmpty() ) + { + //Check if this is a RTF message before escaping it + if( !isHTML.exactMatch( plainBody ) ) + { + plainBody = QStyleSheet::escape( plainBody ); + + //this is the same algoritm as in Kopete::Message::escapedBody(); + plainBody.replace( QString::fromLatin1( "\n" ), QString::fromLatin1( "<br/>" ) ) + .replace( QString::fromLatin1( "\t" ), QString::fromLatin1( " " ) ) + .replace( QRegExp( QString::fromLatin1( "\\s\\s" ) ), QString::fromLatin1( " " ) ); + } + + msg.setBody( QString::fromLatin1("<table width=\"100%\" border=0 cellspacing=0 cellpadding=0><tr><td class=\"highlight\"><font size=\"-1\"><b>") + + i18n("Outgoing Encrypted Message: ") + + QString::fromLatin1("</b></font></td></tr><tr><td class=\"highlight\">") + + plainBody + + QString::fromLatin1(" </td></tr></table>") + , Kopete::Message::RichText ); + } + + //if there are too messages in cache, clear the cache + if(m_cachedMessages.count() > 5) + m_cachedMessages.clear(); + + return; + } + + + //the Message::unescape is there because client like fire replace linebreak by <BR> to work even if the protocol doesn't allow newlines (IRC) + // cf http://fire.sourceforge.net/forums/viewtopic.php?t=174 and Bug #96052 + if(body.contains("<")) + body= Kopete::Message::unescape(body); + + body = KgpgInterface::KgpgDecryptText( body, mPrivateKeyID ); + + if( !body.isEmpty() ) + { + //Check if this is a RTF message before escaping it + if( !isHTML.exactMatch( body ) ) + { + body = Kopete::Message::escape( body ); + } + + msg.setBody( QString::fromLatin1("<table width=\"100%\" border=0 cellspacing=0 cellpadding=0><tr><td class=\"highlight\"><font size=\"-1\"><b>") + + i18n("Incoming Encrypted Message: ") + + QString::fromLatin1("</b></font></td></tr><tr><td class=\"highlight\">") + + body + + QString::fromLatin1(" </td></tr></table>") + , Kopete::Message::RichText ); + } + +} + +void CryptographyPlugin::slotOutgoingMessage( Kopete::Message& msg ) +{ + if(msg.direction() != Kopete::Message::Outbound) + return; + + QStringList keys; + QPtrList<Kopete::Contact> contactlist = msg.to(); + for( Kopete::Contact *c = contactlist.first(); c; c = contactlist.next() ) + { + QString tmpKey; + if( c->metaContact() ) + { + if(c->metaContact()->pluginData( this, "encrypt_messages" ) == "off" ) + return; + tmpKey = c->metaContact()->pluginData( this, "gpgKey" ); + } + if( tmpKey.isEmpty() ) + { + // kdDebug( 14303 ) << "CryptographyPlugin::slotOutgoingMessage: no key selected for one contact" <<endl; + return; + } + keys.append( tmpKey ); + } + if(mAlsoMyKey) //encrypt also with the self key + keys.append( mPrivateKeyID ); + + QString key = keys.join( " " ); + + if(key.isEmpty()) + { + kdDebug(14303) << "CryptographyPlugin::slotOutgoingMessage: empty key" <<endl; + return; + } + + QString original=msg.plainBody(); + + /* Code From KGPG */ + + ////////////////// encode from editor + QString encryptOptions=""; + + //if (utrust==true) + encryptOptions+=" --always-trust "; + //if (arm==true) + encryptOptions+=" --armor "; + + /* if (pubcryptography==true) + { + if (gpgversion<120) encryptOptions+=" --compress-algo 1 --cipher-algo cast5 "; + else encryptOptions+=" --cryptography6 "; + }*/ + +// if (selec==NULL) {KMessageBox::sorry(Kopete::UI::Global::mainWidget(),i18n("You have not chosen an encryption key..."));return;} + + QString resultat=KgpgInterface::KgpgEncryptText(original,key,encryptOptions); + if (!resultat.isEmpty()) + { + msg.setBody(resultat,Kopete::Message::PlainText); + m_cachedMessages.insert(resultat,original); + } + else + kdDebug(14303) << "CryptographyPlugin::slotOutgoingMessage: empty result" <<endl; + +} + +void CryptographyPlugin::slotSelectContactKey() +{ + Kopete::MetaContact *m=Kopete::ContactList::self()->selectedMetaContacts().first(); + if(!m) + return; + QString key = m->pluginData( this, "gpgKey" ); + CryptographySelectUserKey *opts = new CryptographySelectUserKey( key, m ); + opts->exec(); + if( opts->result() ) + { + key = opts->publicKey(); + m->setPluginData( this, "gpgKey", key ); + } + delete opts; +} + +void CryptographyPlugin::slotForgetCachedPass() +{ + m_cachedPass=QCString(); + m_cachedPass_timer->stop(); +} + +void CryptographyPlugin::slotNewKMM(Kopete::ChatSession *KMM) +{ + connect(this , SIGNAL( destroyed(QObject*)) , + new CryptographyGUIClient(KMM) , SLOT(deleteLater())); +} + + + +#include "cryptographyplugin.moc" + +// vim: set noet ts=4 sts=4 sw=4: + |