/***************************************************************************
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 <tqstylesheet.h>
# include <tqtimer.h>
# include <tqregexp.h>
# include <kdebug.h>
# include <kaction.h>
# include <kconfig.h>
# include <kgenericfactory.h>
# include <tdeversion.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 TQRegExp CryptographyPlugin : : isHTML ( TQString : : fromLatin1 ( " ^[^<>]*(</?(html|body|br|p|font|center|b|i|u|span|div|pre)(>|[ \\ s/][^><]*>)[^><]*)+$ " ) , false ) ;
typedef KGenericFactory < CryptographyPlugin > 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 ( ) ) ) ;
KAction * action = new KAction ( 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 < Kopete : : ChatSession * > sessions = Kopete : : ChatSessionManager : : self ( ) - > sessions ( ) ;
for ( TQValueListIterator < Kopete : : ChatSession * > 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 ;
}
/*KActionCollection *CryptographyPlugin::customChatActions(Kopete::ChatSession *KMM)
{
delete m_actionCollection ;
m_actionCollection = new KActionCollection ( this ) ;
KAction * actionTranslate = new KAction ( 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 ( " <br/> " ) )
. replace ( TQString : : fromLatin1 ( " \t " ) , TQString : : fromLatin1 ( " " ) )
. replace ( TQRegExp ( TQString : : fromLatin1 ( " \\ s \\ s " ) ) , TQString : : fromLatin1 ( " " ) ) ;
}
msg . setBody ( TQString : : fromLatin1 ( " <table width= \" 100% \" border=0 cellspacing=0 cellpadding=0><tr><td class= \" highlight \" ><font size= \" -1 \" ><b> " )
+ i18n ( " Outgoing Encrypted Message: " )
+ TQString : : fromLatin1 ( " </b></font></td></tr><tr><td class= \" highlight \" > " )
+ plainBody
+ TQString : : 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 ( TQString : : fromLatin1 ( " <table width= \" 100% \" border=0 cellspacing=0 cellpadding=0><tr><td class= \" highlight \" ><font size= \" -1 \" ><b> " )
+ i18n ( " Incoming Encrypted Message: " )
+ TQString : : fromLatin1 ( " </b></font></td></tr><tr><td class= \" highlight \" > " )
+ body
+ TQString : : fromLatin1 ( " </td></tr></table> " )
, Kopete : : Message : : RichText ) ;
}
}
void CryptographyPlugin : : slotOutgoingMessage ( Kopete : : Message & msg )
{
if ( msg . direction ( ) ! = Kopete : : Message : : Outbound )
return ;
TQStringList keys ;
TQPtrList < Kopete : : Contact > 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" <<endl;
return ;
}
keys . append ( tmpKey ) ;
}
if ( mAlsoMyKey ) //encrypt also with the self key
keys . append ( mPrivateKeyID ) ;
TQString key = keys . join ( " " ) ;
if ( key . isEmpty ( ) )
{
kdDebug ( 14303 ) < < " CryptographyPlugin::slotOutgoingMessage: empty key " < < endl ;
return ;
}
TQString original = msg . plainBody ( ) ;
/* Code From KGPG */
////////////////// encode from editor
TQString 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;}
TQString 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 ;
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: