/*************************************************************************** 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 #include #include #include #include #include #include #include #include #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 TQRegExp CryptographyPlugin::isHTML( TQString::fromLatin1( "^[^<>]*(|[\\s/][^><]*>)[^><]*)+$" ) , false ); typedef KGenericFactory CryptographyPluginFactory; static const TDEAboutData aboutdata("kopete_cryptography", I18N_NOOP("Cryptography") , "1.0" ); K_EXPORT_COMPONENT_FACTORY( kopete_cryptography, CryptographyPluginFactory( &aboutdata ) ) CryptographyPlugin::CryptographyPlugin( TQObject *parent, const char *name, const TQStringList & /* 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, TQT_SLOT( slotIncomingMessage( Kopete::Message& ) ) ); connect( Kopete::ChatSessionManager::self(), TQT_SIGNAL( aboutToSend( Kopete::Message & ) ), TQT_SLOT( slotOutgoingMessage( Kopete::Message & ) ) ); m_cachedPass_timer = new TQTimer(this, "m_cachedPass_timer" ); TQObject::connect(m_cachedPass_timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotForgetCachedPass() )); TDEAction *action=new TDEAction( i18n("&Select Cryptography Public Key..."), "encrypted", 0, this, TQT_SLOT (slotSelectContactKey()), actionCollection() , "contactSelectKey"); connect ( Kopete::ContactList::self() , TQT_SIGNAL( metaContactSelected(bool)) , action , TQT_SLOT(setEnabled(bool))); action->setEnabled(Kopete::ContactList::self()->selectedMetaContacts().count()==1 ); setXMLFile("cryptographyui.rc"); loadSettings(); connect(this, TQT_SIGNAL(settingsChanged()), this, TQT_SLOT( loadSettings() ) ); connect( Kopete::ChatSessionManager::self(), TQT_SIGNAL( chatSessionCreated( Kopete::ChatSession * )) , TQT_SLOT( slotNewKMM( Kopete::ChatSession * ) ) ); //Add GUI action to all already existing kmm (if the plugin is launched when kopete already rining) TQValueList sessions = Kopete::ChatSessionManager::self()->sessions(); for (TQValueListIterator it= sessions.begin(); it!=sessions.end() ; ++it) { slotNewKMM(*it); } } CryptographyPlugin::~CryptographyPlugin() { delete m_inboundHandler; pluginStatic_ = 0L; } void CryptographyPlugin::loadSettings() { TDEConfig *config = TDEGlobal::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; TQCString CryptographyPlugin::cachedPass() { return pluginStatic_->m_cachedPass; } void CryptographyPlugin::setCachedPass(const TQCString& 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; } /*TDEActionCollection *CryptographyPlugin::customChatActions(Kopete::ChatSession *KMM) { delete m_actionCollection; m_actionCollection = new TDEActionCollection(this); TDEAction *actionTranslate = new TDEAction( i18n ("Translate"), 0, this, TQT_SLOT( slotTranslateChat() ), m_actionCollection, "actionTranslate" ); m_actionCollection->insert( actionTranslate ); m_currentChatSession=KMM; return m_actionCollection; }*/ void CryptographyPlugin::slotIncomingMessage( Kopete::Message& msg ) { TQString body = msg.plainBody(); if( !body.startsWith( TQString::fromLatin1("-----BEGIN PGP MESSAGE----") ) || !body.contains( TQString::fromLatin1("-----END PGP MESSAGE----") ) ) return; if( msg.direction() != Kopete::Message::Inbound ) { TQString 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 = TQStyleSheet::escape( plainBody ); //this is the same algoritm as in Kopete::Message::escapedBody(); plainBody.replace( TQString::fromLatin1( "\n" ), TQString::fromLatin1( "
" ) ) .replace( TQString::fromLatin1( "\t" ), TQString::fromLatin1( "    " ) ) .replace( TQRegExp( TQString::fromLatin1( "\\s\\s" ) ), TQString::fromLatin1( "  " ) ); } msg.setBody( TQString::fromLatin1("
") + i18n("Outgoing Encrypted Message: ") + TQString::fromLatin1("
") + plainBody + TQString::fromLatin1("
") , 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
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( TQString::fromLatin1("
") + i18n("Incoming Encrypted Message: ") + TQString::fromLatin1("
") + body + TQString::fromLatin1("
") , Kopete::Message::RichText ); } } void CryptographyPlugin::slotOutgoingMessage( Kopete::Message& msg ) { if(msg.direction() != Kopete::Message::Outbound) return; TQStringList keys; TQPtrList contactlist = msg.to(); for( Kopete::Contact *c = contactlist.first(); c; c = contactlist.next() ) { TQString 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" <selectedMetaContacts().first(); if(!m) return; TQString 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=TQCString(); m_cachedPass_timer->stop(); } void CryptographyPlugin::slotNewKMM(Kopete::ChatSession *KMM) { connect(this , TQT_SIGNAL( destroyed(TQObject*)) , new CryptographyGUIClient(KMM) , TQT_SLOT(deleteLater())); } #include "cryptographyplugin.moc" // vim: set noet ts=4 sts=4 sw=4: