summaryrefslogtreecommitdiffstats
path: root/libkpimidentities/identity.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libkpimidentities/identity.cpp')
-rw-r--r--libkpimidentities/identity.cpp636
1 files changed, 636 insertions, 0 deletions
diff --git a/libkpimidentities/identity.cpp b/libkpimidentities/identity.cpp
new file mode 100644
index 00000000..204e997e
--- /dev/null
+++ b/libkpimidentities/identity.cpp
@@ -0,0 +1,636 @@
+// -*- mode: C++; c-file-style: "gnu" -*-
+// kmidentity.cpp
+// License: GPL
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "identity.h"
+
+#include <libkdepim/kfileio.h>
+#include <libkdepim/collectingprocess.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kconfig.h>
+#include <kurl.h>
+
+#include <qfileinfo.h>
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <assert.h>
+
+using namespace KPIM;
+
+
+Signature::Signature()
+ : mType( Disabled )
+{
+
+}
+
+Signature::Signature( const QString & text )
+ : mText( text ),
+ mType( Inlined )
+{
+
+}
+
+Signature::Signature( const QString & url, bool isExecutable )
+ : mUrl( url ),
+ mType( isExecutable ? FromCommand : FromFile )
+{
+}
+
+bool Signature::operator==( const Signature & other ) const {
+ if ( mType != other.mType ) return false;
+ switch ( mType ) {
+ case Inlined: return mText == other.mText;
+ case FromFile:
+ case FromCommand: return mUrl == other.mUrl;
+ default:
+ case Disabled: return true;
+ }
+}
+
+QString Signature::rawText( bool * ok ) const
+{
+ switch ( mType ) {
+ case Disabled:
+ if ( ok ) *ok = true;
+ return QString::null;
+ case Inlined:
+ if ( ok ) *ok = true;
+ return mText;
+ case FromFile:
+ return textFromFile( ok );
+ case FromCommand:
+ return textFromCommand( ok );
+ };
+ kdFatal( 5006 ) << "Signature::type() returned unknown value!" << endl;
+ return QString::null; // make compiler happy
+}
+
+QString Signature::textFromCommand( bool * ok ) const
+{
+ assert( mType == FromCommand );
+
+ // handle pathological cases:
+ if ( mUrl.isEmpty() ) {
+ if ( ok ) *ok = true;
+ return QString::null;
+ }
+
+ // create a shell process:
+ CollectingProcess proc;
+ proc.setUseShell(true);
+ proc << mUrl;
+
+ // run the process:
+ int rc = 0;
+ if ( !proc.start( KProcess::Block, KProcess::Stdout ) )
+ rc = -1;
+ else
+ rc = ( proc.normalExit() ) ? proc.exitStatus() : -1 ;
+
+ // handle errors, if any:
+ if ( rc != 0 ) {
+ if ( ok ) *ok = false;
+ QString wmsg = i18n("<qt>Failed to execute signature script<br><b>%1</b>:<br>%2</qt>")
+ .arg( mUrl ).arg( strerror(rc) );
+ KMessageBox::error(0, wmsg);
+ return QString::null;
+ }
+
+ // no errors:
+ if ( ok ) *ok = true;
+
+ // get output:
+ QByteArray output = proc.collectedStdout();
+
+ // ### hmm, should we allow other encodings, too?
+ return QString::fromLocal8Bit( output.data(), output.size() );
+}
+
+QString Signature::textFromFile( bool * ok ) const
+{
+ assert( mType == FromFile );
+
+ // ### FIXME: Use KIO::NetAccess to download non-local files!
+ if ( !KURL(mUrl).isLocalFile() && !(QFileInfo(mUrl).isRelative()
+ && QFileInfo(mUrl).exists()) ) {
+ kdDebug( 5006 ) << "Signature::textFromFile: non-local URLs are unsupported" << endl;
+ if ( ok ) *ok = false;
+ return QString::null;
+ }
+ if ( ok ) *ok = true;
+ // ### hmm, should we allow other encodings, too?
+ return QString::fromLocal8Bit( kFileToString( mUrl, false ) );
+}
+
+QString Signature::withSeparator( bool * ok ) const
+{
+ bool internalOK = false;
+ QString signature = rawText( &internalOK );
+ if ( !internalOK ) {
+ if ( ok ) *ok = false;
+ return QString::null;
+ }
+ if ( ok ) *ok = true;
+ if ( signature.isEmpty() ) return signature; // don't add a separator in this case
+ if ( signature.startsWith( QString::fromLatin1("-- \n") ) )
+ // already have signature separator at start of sig:
+ return QString::fromLatin1("\n") += signature;
+ else if ( signature.find( QString::fromLatin1("\n-- \n") ) != -1 )
+ // already have signature separator inside sig; don't prepend '\n'
+ // to improve abusing signatures as templates:
+ return signature;
+ else
+ // need to prepend one:
+ return QString::fromLatin1("\n-- \n") + signature;
+}
+
+
+void Signature::setUrl( const QString & url, bool isExecutable )
+{
+ mUrl = url;
+ mType = isExecutable ? FromCommand : FromFile ;
+}
+
+// config keys and values:
+static const char sigTypeKey[] = "Signature Type";
+static const char sigTypeInlineValue[] = "inline";
+static const char sigTypeFileValue[] = "file";
+static const char sigTypeCommandValue[] = "command";
+static const char sigTypeDisabledValue[] = "disabled";
+static const char sigTextKey[] = "Inline Signature";
+static const char sigFileKey[] = "Signature File";
+static const char sigCommandKey[] = "Signature Command";
+
+void Signature::readConfig( const KConfigBase * config )
+{
+ QString sigType = config->readEntry( sigTypeKey );
+ if ( sigType == sigTypeInlineValue ) {
+ mType = Inlined;
+ } else if ( sigType == sigTypeFileValue ) {
+ mType = FromFile;
+ mUrl = config->readPathEntry( sigFileKey );
+ } else if ( sigType == sigTypeCommandValue ) {
+ mType = FromCommand;
+ mUrl = config->readPathEntry( sigCommandKey );
+ } else {
+ mType = Disabled;
+ }
+ mText = config->readEntry( sigTextKey );
+}
+
+void Signature::writeConfig( KConfigBase * config ) const
+{
+ switch ( mType ) {
+ case Inlined:
+ config->writeEntry( sigTypeKey, sigTypeInlineValue );
+ break;
+ case FromFile:
+ config->writeEntry( sigTypeKey, sigTypeFileValue );
+ config->writePathEntry( sigFileKey, mUrl );
+ break;
+ case FromCommand:
+ config->writeEntry( sigTypeKey, sigTypeCommandValue );
+ config->writePathEntry( sigCommandKey, mUrl );
+ break;
+ case Disabled:
+ config->writeEntry( sigTypeKey, sigTypeDisabledValue );
+ default: ;
+ }
+ config->writeEntry( sigTextKey, mText );
+}
+
+QDataStream & KPIM::operator<<( QDataStream & stream, const KPIM::Signature & sig ) {
+ return stream << static_cast<Q_UINT8>(sig.mType)
+ << sig.mUrl
+ << sig.mText;
+}
+
+QDataStream & KPIM::operator>>( QDataStream & stream, KPIM::Signature & sig ) {
+ Q_UINT8 s;
+ stream >> s
+ >> sig.mUrl
+ >> sig.mText;
+ sig.mType = static_cast<Signature::Type>(s);
+ return stream;
+}
+
+// ### should use a kstaticdeleter?
+static Identity* identityNull = 0;
+const Identity& Identity::null()
+{
+ if ( !identityNull )
+ identityNull = new Identity;
+ return *identityNull;
+}
+
+bool Identity::isNull() const {
+ return mIdentity.isEmpty() && mFullName.isEmpty() && mEmailAddr.isEmpty() &&
+ mOrganization.isEmpty() && mReplyToAddr.isEmpty() && mBcc.isEmpty() &&
+ mVCardFile.isEmpty() &&
+ mFcc.isEmpty() && mDrafts.isEmpty() && mTemplates.isEmpty() &&
+ mPGPEncryptionKey.isEmpty() && mPGPSigningKey.isEmpty() &&
+ mSMIMEEncryptionKey.isEmpty() && mSMIMESigningKey.isEmpty() &&
+ mTransport.isEmpty() && mDictionary.isEmpty() &&
+ mPreferredCryptoMessageFormat == Kleo::AutoFormat &&
+ mSignature.type() == Signature::Disabled &&
+ mXFace.isEmpty();
+}
+
+bool Identity::operator==( const Identity & other ) const {
+ bool same = mUoid == other.mUoid &&
+ mIdentity == other.mIdentity && mFullName == other.mFullName &&
+ mEmailAddr == other.mEmailAddr && mOrganization == other.mOrganization &&
+ mReplyToAddr == other.mReplyToAddr && mBcc == other.mBcc &&
+ mVCardFile == other.mVCardFile &&
+ mFcc == other.mFcc &&
+ mPGPEncryptionKey == other.mPGPEncryptionKey &&
+ mPGPSigningKey == other.mPGPSigningKey &&
+ mSMIMEEncryptionKey == other.mSMIMEEncryptionKey &&
+ mSMIMESigningKey == other.mSMIMESigningKey &&
+ mPreferredCryptoMessageFormat == other.mPreferredCryptoMessageFormat &&
+ mDrafts == other.mDrafts && mTemplates == other.mTemplates &&
+ mTransport == other.mTransport &&
+ mDictionary == other.mDictionary && mSignature == other.mSignature &&
+ mXFace == other.mXFace && mXFaceEnabled == other.mXFaceEnabled;
+
+#if 0
+ if ( same )
+ return true;
+ if ( mUoid != other.mUoid ) kdDebug() << "mUoid differs : " << mUoid << " != " << other.mUoid << endl;
+ if ( mIdentity != other.mIdentity ) kdDebug() << "mIdentity differs : " << mIdentity << " != " << other.mIdentity << endl;
+ if ( mFullName != other.mFullName ) kdDebug() << "mFullName differs : " << mFullName << " != " << other.mFullName << endl;
+ if ( mEmailAddr != other.mEmailAddr ) kdDebug() << "mEmailAddr differs : " << mEmailAddr << " != " << other.mEmailAddr << endl;
+ if ( mOrganization != other.mOrganization ) kdDebug() << "mOrganization differs : " << mOrganization << " != " << other.mOrganization << endl;
+ if ( mReplyToAddr != other.mReplyToAddr ) kdDebug() << "mReplyToAddr differs : " << mReplyToAddr << " != " << other.mReplyToAddr << endl;
+ if ( mBcc != other.mBcc ) kdDebug() << "mBcc differs : " << mBcc << " != " << other.mBcc << endl;
+ if ( mVCardFile != other.mVCardFile ) kdDebug() << "mVCardFile differs : " << mVCardFile << " != " << other.mVCardFile << endl;
+ if ( mFcc != other.mFcc ) kdDebug() << "mFcc differs : " << mFcc << " != " << other.mFcc << endl;
+ if ( mPGPEncryptionKey != other.mPGPEncryptionKey ) kdDebug() << "mPGPEncryptionKey differs : " << mPGPEncryptionKey << " != " << other.mPGPEncryptionKey << endl;
+ if ( mPGPSigningKey != other.mPGPSigningKey ) kdDebug() << "mPGPSigningKey differs : " << mPGPSigningKey << " != " << other.mPGPSigningKey << endl;
+ if ( mSMIMEEncryptionKey != other.mSMIMEEncryptionKey ) kdDebug() << "mSMIMEEncryptionKey differs : '" << mSMIMEEncryptionKey << "' != '" << other.mSMIMEEncryptionKey << "'" << endl;
+ if ( mSMIMESigningKey != other.mSMIMESigningKey ) kdDebug() << "mSMIMESigningKey differs : " << mSMIMESigningKey << " != " << other.mSMIMESigningKey << endl;
+ if ( mPreferredCryptoMessageFormat != other.mPreferredCryptoMessageFormat ) kdDebug() << "mPreferredCryptoMessageFormat differs : " << mPreferredCryptoMessageFormat << " != " << other.mPreferredCryptoMessageFormat << endl;
+ if ( mDrafts != other.mDrafts ) kdDebug() << "mDrafts differs : " << mDrafts << " != " << other.mDrafts << endl;
+ if ( mTemplates != other.mTemplates ) kdDebug() << "mTemplates differs : " << mTemplates << " != " << other.mTemplates << endl;
+ if ( mTransport != other.mTransport ) kdDebug() << "mTransport differs : " << mTransport << " != " << other.mTransport << endl;
+ if ( mDictionary != other.mDictionary ) kdDebug() << "mDictionary differs : " << mDictionary << " != " << other.mDictionary << endl;
+ if ( ! ( mSignature == other.mSignature ) ) kdDebug() << "mSignature differs" << endl;
+#endif
+ return same;
+}
+
+Identity::Identity( const QString & id, const QString & fullName,
+ const QString & emailAddr, const QString & organization,
+ const QString & replyToAddr )
+ : mUoid( 0 ), mIdentity( id ), mFullName( fullName ),
+ mEmailAddr( emailAddr ), mOrganization( organization ),
+ mReplyToAddr( replyToAddr ),
+ // Using "" instead of null to make operator==() not fail
+ // (readConfig returns "")
+ mBcc( "" ), mVCardFile( "" ), mPGPEncryptionKey( "" ), mPGPSigningKey( "" ),
+ mSMIMEEncryptionKey( "" ), mSMIMESigningKey( "" ), mFcc( "" ),
+ mDrafts( "" ), mTemplates( "" ), mTransport( "" ),
+ mDictionary( "" ),
+ mXFace( "" ), mXFaceEnabled( false ),
+ mIsDefault( false ),
+ mPreferredCryptoMessageFormat( Kleo::AutoFormat )
+{
+}
+
+Identity::~Identity()
+{
+}
+
+
+void Identity::readConfig( const KConfigBase * config )
+{
+ mUoid = config->readUnsignedNumEntry("uoid",0);
+
+ mIdentity = config->readEntry("Identity");
+ mFullName = config->readEntry("Name");
+ mEmailAddr = config->readEntry("Email Address");
+ mVCardFile = config->readPathEntry("VCardFile");
+ mOrganization = config->readEntry("Organization");
+ mPGPSigningKey = config->readEntry("PGP Signing Key").latin1();
+ mPGPEncryptionKey = config->readEntry("PGP Encryption Key").latin1();
+ mSMIMESigningKey = config->readEntry("SMIME Signing Key").latin1();
+ mSMIMEEncryptionKey = config->readEntry("SMIME Encryption Key").latin1();
+ mPreferredCryptoMessageFormat = Kleo::stringToCryptoMessageFormat( config->readEntry("Preferred Crypto Message Format", "none" ) );
+ mReplyToAddr = config->readEntry( "Reply-To Address" );
+ mBcc = config->readEntry( "Bcc" );
+ mFcc = config->readEntry( "Fcc", "sent-mail" );
+ if( mFcc.isEmpty() )
+ mFcc = "sent-mail";
+ mDrafts = config->readEntry( "Drafts", "drafts" );
+ if( mDrafts.isEmpty() )
+ mDrafts = "drafts";
+ mTemplates = config->readEntry( "Templates", "templates" );
+ if( mTemplates.isEmpty() )
+ mTemplates = "templates";
+ mTransport = config->readEntry( "Transport" );
+ mDictionary = config->readEntry( "Dictionary" );
+ mXFace = config->readEntry( "X-Face" );
+ mXFaceEnabled = config->readBoolEntry( "X-FaceEnabled", false );
+
+ mSignature.readConfig( config );
+ kdDebug(5006) << "Identity::readConfig(): UOID = " << mUoid
+ << " for identity named \"" << mIdentity << "\"" << endl;
+}
+
+
+void Identity::writeConfig( KConfigBase * config ) const
+{
+ config->writeEntry("uoid", mUoid);
+
+ config->writeEntry("Identity", mIdentity);
+ config->writeEntry("Name", mFullName);
+ config->writeEntry("Organization", mOrganization);
+ config->writeEntry("PGP Signing Key", mPGPSigningKey.data());
+ config->writeEntry("PGP Encryption Key", mPGPEncryptionKey.data());
+ config->writeEntry("SMIME Signing Key", mSMIMESigningKey.data());
+ config->writeEntry("SMIME Encryption Key", mSMIMEEncryptionKey.data());
+ config->writeEntry("Preferred Crypto Message Format", Kleo::cryptoMessageFormatToString( mPreferredCryptoMessageFormat ) );
+ config->writeEntry("Email Address", mEmailAddr);
+ config->writeEntry("Reply-To Address", mReplyToAddr);
+ config->writeEntry("Bcc", mBcc);
+ config->writePathEntry("VCardFile", mVCardFile);
+ config->writeEntry("Transport", mTransport);
+ config->writeEntry("Fcc", mFcc);
+ config->writeEntry("Drafts", mDrafts);
+ config->writeEntry("Templates", mTemplates);
+ config->writeEntry( "Dictionary", mDictionary );
+ config->writeEntry( "X-Face", mXFace );
+ config->writeEntry( "X-FaceEnabled", mXFaceEnabled );
+
+ mSignature.writeConfig( config );
+}
+
+QDataStream & KPIM::operator<<( QDataStream & stream, const KPIM::Identity & i ) {
+ return stream << static_cast<Q_UINT32>(i.uoid())
+ << i.identityName()
+ << i.fullName()
+ << i.organization()
+ << i.pgpSigningKey()
+ << i.pgpEncryptionKey()
+ << i.smimeSigningKey()
+ << i.smimeEncryptionKey()
+ << i.emailAddr()
+ << i.replyToAddr()
+ << i.bcc()
+ << i.vCardFile()
+ << i.transport()
+ << i.fcc()
+ << i.drafts()
+ << i.templates()
+ << i.mSignature
+ << i.dictionary()
+ << i.xface()
+ << QString( Kleo::cryptoMessageFormatToString( i.mPreferredCryptoMessageFormat ) );
+}
+
+QDataStream & KPIM::operator>>( QDataStream & stream, KPIM::Identity & i ) {
+ Q_UINT32 uoid;
+ QString format;
+ stream >> uoid
+ >> i.mIdentity
+ >> i.mFullName
+ >> i.mOrganization
+ >> i.mPGPSigningKey
+ >> i.mPGPEncryptionKey
+ >> i.mSMIMESigningKey
+ >> i.mSMIMEEncryptionKey
+ >> i.mEmailAddr
+ >> i.mReplyToAddr
+ >> i.mBcc
+ >> i.mVCardFile
+ >> i.mTransport
+ >> i.mFcc
+ >> i.mDrafts
+ >> i.mTemplates
+ >> i.mSignature
+ >> i.mDictionary
+ >> i.mXFace
+ >> format;
+ i.mUoid = uoid;
+ i.mPreferredCryptoMessageFormat = Kleo::stringToCryptoMessageFormat( format.latin1() );
+
+ return stream;
+}
+
+//-----------------------------------------------------------------------------
+bool Identity::mailingAllowed() const
+{
+ return !mEmailAddr.isEmpty();
+}
+
+
+void Identity::setIsDefault( bool flag ) {
+ mIsDefault = flag;
+}
+
+void Identity::setIdentityName( const QString & name ) {
+ mIdentity = name;
+}
+
+void Identity::setFullName(const QString &str)
+{
+ mFullName = str;
+}
+
+
+//-----------------------------------------------------------------------------
+void Identity::setOrganization(const QString &str)
+{
+ mOrganization = str;
+}
+
+void Identity::setPGPSigningKey(const QCString &str)
+{
+ mPGPSigningKey = str;
+ if ( mPGPSigningKey.isNull() )
+ mPGPSigningKey = "";
+}
+
+void Identity::setPGPEncryptionKey(const QCString &str)
+{
+ mPGPEncryptionKey = str;
+ if ( mPGPEncryptionKey.isNull() )
+ mPGPEncryptionKey = "";
+}
+
+void Identity::setSMIMESigningKey(const QCString &str)
+{
+ mSMIMESigningKey = str;
+ if ( mSMIMESigningKey.isNull() )
+ mSMIMESigningKey = "";
+}
+
+void Identity::setSMIMEEncryptionKey(const QCString &str)
+{
+ mSMIMEEncryptionKey = str;
+ if ( mSMIMEEncryptionKey.isNull() )
+ mSMIMEEncryptionKey = "";
+}
+
+//-----------------------------------------------------------------------------
+void Identity::setEmailAddr(const QString &str)
+{
+ mEmailAddr = str;
+}
+
+
+//-----------------------------------------------------------------------------
+void Identity::setVCardFile(const QString &str)
+{
+ mVCardFile = str;
+}
+
+
+//-----------------------------------------------------------------------------
+QString Identity::fullEmailAddr(void) const
+{
+ if (mFullName.isEmpty()) return mEmailAddr;
+
+ const QString specials("()<>@,.;:[]");
+
+ QString result;
+
+ // add DQUOTE's if necessary:
+ bool needsQuotes=false;
+ for (unsigned int i=0; i < mFullName.length(); i++) {
+ if ( specials.contains( mFullName[i] ) )
+ needsQuotes = true;
+ else if ( mFullName[i] == '\\' || mFullName[i] == '"' ) {
+ needsQuotes = true;
+ result += '\\';
+ }
+ result += mFullName[i];
+ }
+
+ if (needsQuotes) {
+ result.insert(0,'"');
+ result += '"';
+ }
+
+ result += " <" + mEmailAddr + '>';
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+void Identity::setReplyToAddr(const QString& str)
+{
+ mReplyToAddr = str;
+}
+
+
+//-----------------------------------------------------------------------------
+void Identity::setSignatureFile(const QString &str)
+{
+ mSignature.setUrl( str, signatureIsCommand() );
+}
+
+
+//-----------------------------------------------------------------------------
+void Identity::setSignatureInlineText(const QString &str )
+{
+ mSignature.setText( str );
+}
+
+
+//-----------------------------------------------------------------------------
+void Identity::setTransport( const QString &str )
+{
+ mTransport = str;
+ if ( mTransport.isNull() )
+ mTransport = "";
+}
+
+//-----------------------------------------------------------------------------
+void Identity::setFcc( const QString &str )
+{
+ mFcc = str;
+ if ( mFcc.isNull() )
+ mFcc = "";
+}
+
+//-----------------------------------------------------------------------------
+void Identity::setDrafts( const QString &str )
+{
+ mDrafts = str;
+ if ( mDrafts.isNull() )
+ mDrafts = "";
+}
+
+//-----------------------------------------------------------------------------
+void Identity::setTemplates( const QString &str )
+{
+ mTemplates = str;
+ if ( mTemplates.isNull() )
+ mTemplates = "";
+}
+
+//-----------------------------------------------------------------------------
+void Identity::setDictionary( const QString &str )
+{
+ mDictionary = str;
+ if ( mDictionary.isNull() )
+ mDictionary = "";
+}
+
+
+//-----------------------------------------------------------------------------
+void Identity::setXFace( const QString &str )
+{
+ mXFace = str;
+ mXFace.remove( " " );
+ mXFace.remove( "\n" );
+ mXFace.remove( "\r" );
+}
+
+
+//-----------------------------------------------------------------------------
+void Identity::setXFaceEnabled( const bool on )
+{
+ mXFaceEnabled = on;
+}
+
+
+//-----------------------------------------------------------------------------
+QString Identity::signatureText( bool * ok ) const
+{
+ bool internalOK = false;
+ QString signatureText = mSignature.withSeparator( &internalOK );
+ if ( internalOK ) {
+ if ( ok ) *ok=true;
+ return signatureText;
+ }
+
+ // OK, here comes the funny part. The call to
+ // Signature::withSeparator() failed, so we should probably fix the
+ // cause:
+ if ( ok ) *ok = false;
+ return QString::null;
+
+#if 0 // ### FIXME: error handling
+ if (mSignatureFile.endsWith("|"))
+ {
+ }
+ else
+ {
+ }
+#endif
+
+ return QString::null;
+}