summaryrefslogtreecommitdiffstats
path: root/libkpimidentities
diff options
context:
space:
mode:
Diffstat (limited to 'libkpimidentities')
-rw-r--r--libkpimidentities/Makefile.am18
-rw-r--r--libkpimidentities/identity.cpp636
-rw-r--r--libkpimidentities/identity.h319
-rw-r--r--libkpimidentities/identitycombo.cpp129
-rw-r--r--libkpimidentities/identitycombo.h99
-rw-r--r--libkpimidentities/identitymanager.cpp518
-rw-r--r--libkpimidentities/identitymanager.h242
7 files changed, 1961 insertions, 0 deletions
diff --git a/libkpimidentities/Makefile.am b/libkpimidentities/Makefile.am
new file mode 100644
index 000000000..663e4c8e1
--- /dev/null
+++ b/libkpimidentities/Makefile.am
@@ -0,0 +1,18 @@
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/certmanager/lib $(all_includes)
+
+lib_LTLIBRARIES = libkpimidentities.la
+libkpimidentities_la_SOURCES = \
+ identitymanager.cpp identity.cpp identitymanager.skel \
+ identitycombo.cpp
+libkpimidentities_la_LIBADD = ../certmanager/lib/libkleopatra.la \
+ ../libkdepim/libkdepim.la ../libemailfunctions/libemailfunctions.la
+libkpimidentities_la_LDFLAGS = $(all_libraries) -no-undefined \
+ -version-info 1:0:0
+
+identitymanager_DCOPIDLNG = true
+
+METASOURCES = AUTO
+
+include $(top_srcdir)/admin/Doxyfile.am
+
+# No messages target. Those files are part of libkdepim.pot.
diff --git a/libkpimidentities/identity.cpp b/libkpimidentities/identity.cpp
new file mode 100644
index 000000000..204e997e7
--- /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;
+}
diff --git a/libkpimidentities/identity.h b/libkpimidentities/identity.h
new file mode 100644
index 000000000..6b06e9a9d
--- /dev/null
+++ b/libkpimidentities/identity.h
@@ -0,0 +1,319 @@
+/* -*- mode: C++; c-file-style: "gnu" -*-
+ * User identity information
+ *
+ * Author: Stefan Taferner <taferner@kde.org>
+ * This code is under GPL
+ */
+#ifndef kpim_identity_h
+#define kpim_identity_h
+
+#include <kleo/enum.h>
+
+#include <kdepimmacros.h>
+
+#include <qstring.h>
+#include <qcstring.h>
+#include <qstringlist.h>
+
+class KProcess;
+namespace KPIM {
+ class Identity;
+ class Signature;
+}
+class KConfigBase;
+class IdentityList;
+class QDataStream;
+
+namespace KPIM {
+
+/**
+ * @short abstraction of a signature (aka "footer").
+ * @author Marc Mutz <mutz@kde.org>
+ */
+class KDE_EXPORT Signature {
+ friend class Identity;
+
+ friend QDataStream & KPIM::operator<<( QDataStream & stream, const Signature & sig );
+ friend QDataStream & KPIM::operator>>( QDataStream & stream, Signature & sig );
+
+public:
+ /** Type of signature (ie. way to obtain the signature text) */
+ enum Type { Disabled = 0, Inlined = 1, FromFile = 2, FromCommand = 3 };
+
+ /** Used for comparison */
+ bool operator==( const Signature & other ) const;
+
+ /** Constructor for disabled signature */
+ Signature();
+ /** Constructor for inline text */
+ Signature( const QString & text );
+ /** Constructor for text from a file or from output of a command */
+ Signature( const QString & url, bool isExecutable );
+
+ /** @return the raw signature text as entered resp. read from file. */
+ QString rawText( bool * ok=0 ) const;
+
+ /** @return the signature text with a "-- " separator added, if
+ necessary. */
+ QString withSeparator( bool * ok=0 ) const;
+
+ /** Set the signature text and mark this signature as being of
+ "inline text" type. */
+ void setText( const QString & text ) { mText = text; }
+ QString text() const { return mText; }
+
+ /** Set the signature URL and mark this signature as being of
+ "from file" resp. "from output of command" type. */
+ void setUrl( const QString & url, bool isExecutable=false );
+ QString url() const { return mUrl; }
+
+ /// @return the type of signature (ie. way to obtain the signature text)
+ Type type() const { return mType; }
+ void setType( Type type ) { mType = type; }
+
+protected:
+ void writeConfig( KConfigBase * config ) const;
+ void readConfig( const KConfigBase * config );
+
+private:
+ QString textFromFile( bool * ok ) const;
+ QString textFromCommand( bool * ok ) const;
+
+private:
+ QString mUrl;
+ QString mText;
+ Type mType;
+};
+
+/** User identity information */
+class KDE_EXPORT Identity
+{
+ // only the identity manager should be able to construct and
+ // destruct us, but then we get into problems with using
+ // QValueList<Identity> and especially qHeapSort().
+ friend class IdentityManager;
+
+ friend QDataStream & operator<<( QDataStream & stream, const KPIM::Identity & ident );
+ friend QDataStream & operator>>( QDataStream & stream, KPIM::Identity & ident );
+
+public:
+ typedef QValueList<Identity> List;
+
+ /** used for comparison */
+ bool operator==( const Identity & other ) const;
+
+ bool operator!=( const Identity & other ) const {
+ return !operator==( other );
+ }
+
+ /** used for sorting */
+ bool operator<( const Identity & other ) const {
+ if ( isDefault() ) return true;
+ if ( other.isDefault() ) return false;
+ return identityName() < other.identityName();
+ }
+ bool operator>( const Identity & other ) const {
+ if ( isDefault() ) return false;
+ if ( other.isDefault() ) return true;
+ return identityName() > other.identityName();
+ }
+ bool operator<=( const Identity & other ) const {
+ return !operator>( other );
+ }
+ bool operator>=( const Identity & other ) const {
+ return !operator<( other );
+ }
+
+ /** Constructor */
+ explicit Identity( const QString & id=QString::null,
+ const QString & realName=QString::null,
+ const QString & emailAddr=QString::null,
+ const QString & organization=QString::null,
+ const QString & replyToAddress=QString::null );
+
+ /** Destructor */
+ ~Identity();
+
+protected:
+ /** Read configuration from config. Group must be preset (or use
+ KConfigGroup). Called from IdentityManager. */
+ void readConfig( const KConfigBase * );
+
+ /** Write configuration to config. Group must be preset (or use
+ KConfigGroup). Called from IdentityManager. */
+ void writeConfig( KConfigBase * ) const;
+
+public:
+ /** Tests if there are enough values set to allow mailing */
+ bool mailingAllowed() const;
+
+ /** Identity/nickname for this collection */
+ QString identityName() const { return mIdentity; }
+ void setIdentityName( const QString & name );
+
+ /** @return whether this identity is the default identity */
+ bool isDefault() const { return mIsDefault; }
+
+ /// Unique Object Identifier for this identity
+ uint uoid() const { return mUoid; }
+
+protected:
+ /** Set whether this identity is the default identity. Since this
+ affects all other identites, too (most notably, the old default
+ identity), only the IdentityManager can change this.
+ You should use
+ <pre>
+ kmkernel->identityManager()->setAsDefault( name_of_default )
+ </pre>
+ instead.
+ **/
+ void setIsDefault( bool flag );
+
+ void setUoid( uint aUoid ) { mUoid = aUoid; }
+
+public:
+ /** Full name of the user */
+ QString fullName() const { return mFullName; }
+ void setFullName(const QString&);
+
+ /** The user's organization (optional) */
+ QString organization() const { return mOrganization; }
+ void setOrganization(const QString&);
+
+ KDE_DEPRECATED QCString pgpIdentity() const { return pgpEncryptionKey(); }
+ KDE_DEPRECATED void setPgpIdentity( const QCString & key ) {
+ setPGPEncryptionKey( key );
+ setPGPSigningKey( key );
+ }
+
+ /** The user's OpenPGP encryption key */
+ QCString pgpEncryptionKey() const { return mPGPEncryptionKey; }
+ void setPGPEncryptionKey( const QCString & key );
+
+ /** The user's OpenPGP signing key */
+ QCString pgpSigningKey() const { return mPGPSigningKey; }
+ void setPGPSigningKey( const QCString & key );
+
+ /** The user's S/MIME encryption key */
+ QCString smimeEncryptionKey() const { return mSMIMEEncryptionKey; }
+ void setSMIMEEncryptionKey( const QCString & key );
+
+ /** The user's S/MIME signing key */
+ QCString smimeSigningKey() const { return mSMIMESigningKey; }
+ void setSMIMESigningKey( const QCString & key );
+
+ Kleo::CryptoMessageFormat preferredCryptoMessageFormat() const { return mPreferredCryptoMessageFormat; }
+ void setPreferredCryptoMessageFormat( Kleo::CryptoMessageFormat format ) { mPreferredCryptoMessageFormat = format; }
+
+ /** email address (without the user name - only name\@host) */
+ QString emailAddr() const { return mEmailAddr; }
+ void setEmailAddr(const QString&);
+
+ /** vCard to attach to outgoing emails */
+ QString vCardFile() const { return mVCardFile; }
+ void setVCardFile(const QString&);
+
+ /** email address in the format "username <name@host>" suitable
+ for the "From:" field of email messages. */
+ QString fullEmailAddr() const;
+
+ /** email address for the ReplyTo: field */
+ QString replyToAddr() const { return mReplyToAddr; }
+ void setReplyToAddr(const QString&);
+
+ /** email addresses for the BCC: field */
+ QString bcc() const { return mBcc; }
+ void setBcc(const QString& aBcc) { mBcc = aBcc; }
+
+ void setSignature( const Signature & sig ) { mSignature = sig; }
+ Signature & signature() /* _not_ const! */ { return mSignature; }
+ const Signature & signature() const { return mSignature; }
+
+protected:
+ /** @return true if the signature is read from the output of a command */
+ bool signatureIsCommand() const { return mSignature.type() == Signature::FromCommand; }
+ /** @return true if the signature is read from a text file */
+ bool signatureIsPlainFile() const { return mSignature.type() == Signature::FromFile; }
+ /** @return true if the signature was specified directly */
+ bool signatureIsInline() const { return mSignature.type() == Signature::Inlined; }
+
+ /** name of the signature file (with path) */
+ QString signatureFile() const { return mSignature.url(); }
+ void setSignatureFile(const QString&);
+
+ /** inline signature */
+ QString signatureInlineText() const { return mSignature.text();}
+ void setSignatureInlineText(const QString&);
+
+ /** Inline or signature from a file */
+ bool useSignatureFile() const { return signatureIsPlainFile() || signatureIsCommand(); }
+
+public:
+ /** Returns the signature. This method also takes care of special
+ signature files that are shell scripts and handles them
+ correct. So use this method to rectreive the contents of the
+ signature file. If @p prompt is false, no errors will be displayed
+ (useful for retries). */
+ QString signatureText( bool * ok=0) const;
+
+ /** The transport that is set for this identity. Used to link a
+ transport with an identity. */
+ QString transport() const { return mTransport; }
+ void setTransport(const QString&);
+
+ /** The folder where sent messages from this identity will be
+ stored by default. */
+ QString fcc() const { return mFcc; }
+ void setFcc(const QString&);
+
+ /** The folder where draft messages from this identity will be
+ stored by default. */
+ QString drafts() const { return mDrafts; }
+ void setDrafts(const QString&);
+
+ /** The folder where template messages from this identity will be
+ stored by default. */
+ QString templates() const { return mTemplates; }
+ void setTemplates( const QString& );
+
+ /** dictionary which should be used for spell checking */
+ QString dictionary() const { return mDictionary; }
+ void setDictionary( const QString& );
+
+ /** a X-Face header for this identity */
+ QString xface() const { return mXFace; }
+ void setXFace( const QString& );
+ bool isXFaceEnabled() const { return mXFaceEnabled; }
+ void setXFaceEnabled( const bool );
+
+ static const Identity& null();
+ bool isNull() const;
+protected:
+ // if you add new members, make sure they have an operator= (or the
+ // compiler can synthesize one) and amend Identity::operator==,
+ // isNull(), readConfig() and writeConfig() as well as operator<<
+ // and operator>> accordingly:
+ uint mUoid;
+ QString mIdentity, mFullName, mEmailAddr, mOrganization;
+ QString mReplyToAddr;
+ QString mBcc;
+ QString mVCardFile;
+ QCString mPGPEncryptionKey, mPGPSigningKey, mSMIMEEncryptionKey, mSMIMESigningKey;
+ QString mFcc, mDrafts, mTemplates, mTransport;
+ QString mDictionary;
+ QString mXFace;
+ bool mXFaceEnabled;
+ Signature mSignature;
+ bool mIsDefault;
+ Kleo::CryptoMessageFormat mPreferredCryptoMessageFormat;
+};
+
+KDE_EXPORT QDataStream & operator<<( QDataStream & stream, const KPIM::Signature & sig );
+KDE_EXPORT QDataStream & operator>>( QDataStream & stream, KPIM::Signature & sig );
+
+KDE_EXPORT QDataStream & operator<<( QDataStream & stream, const KPIM::Identity & ident );
+KDE_EXPORT QDataStream & operator>>( QDataStream & stream, KPIM::Identity & ident );
+
+} // namespace KPIM
+
+#endif /*kpim_identity_h*/
diff --git a/libkpimidentities/identitycombo.cpp b/libkpimidentities/identitycombo.cpp
new file mode 100644
index 000000000..a7b9cd3ab
--- /dev/null
+++ b/libkpimidentities/identitycombo.cpp
@@ -0,0 +1,129 @@
+/* -*- c++ -*-
+ identitycombo.cpp
+
+ This file is part of KMail, the KDE mail client.
+ Copyright (c) 2002 Marc Mutz <mutz@kde.org>
+
+ KMail is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License, version 2, as
+ published by the Free Software Foundation.
+
+ KMail 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
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "identitycombo.h"
+#include "identity.h"
+#include "identitymanager.h"
+
+#include <klocale.h>
+
+#include <assert.h>
+
+using namespace KPIM;
+
+IdentityCombo::IdentityCombo( IdentityManager* manager, QWidget * parent, const char * name )
+ : QComboBox( false, parent, name ), mIdentityManager( manager )
+{
+ reloadCombo();
+ reloadUoidList();
+ connect( this, SIGNAL(activated(int)), SLOT(slotEmitChanged(int)) );
+ connect( manager, SIGNAL(changed()),
+ SLOT(slotIdentityManagerChanged()) );
+}
+
+QString IdentityCombo::currentIdentityName() const {
+ return mIdentityManager->identities()[ currentItem() ];
+}
+
+uint IdentityCombo::currentIdentity() const {
+ return mUoidList[ currentItem() ];
+}
+
+void IdentityCombo::setCurrentIdentity( const Identity & identity ) {
+ setCurrentIdentity( identity.uoid() );
+}
+
+void IdentityCombo::setCurrentIdentity( const QString & name ) {
+ int idx = mIdentityManager->identities().findIndex( name );
+ if ( idx < 0 ) return;
+ if ( idx == currentItem() ) return;
+
+ blockSignals( true ); // just in case Qt gets fixed to emit activated() here
+ setCurrentItem( idx );
+ blockSignals( false );
+
+ slotEmitChanged( idx );
+}
+
+void IdentityCombo::setCurrentIdentity( uint uoid ) {
+ int idx = mUoidList.findIndex( uoid );
+ if ( idx < 0 ) return;
+ if ( idx == currentItem() ) return;
+
+ blockSignals( true ); // just in case Qt gets fixed to emit activated() here
+ setCurrentItem( idx );
+ blockSignals( false );
+
+ slotEmitChanged( idx );
+}
+
+void IdentityCombo::reloadCombo() {
+ QStringList identities = mIdentityManager->identities();
+ // the IM should prevent this from happening:
+ assert( !identities.isEmpty() );
+ identities.first() = i18n("%1 (Default)").arg( identities.first() );
+ clear();
+ insertStringList( identities );
+}
+
+void IdentityCombo::reloadUoidList() {
+ mUoidList.clear();
+ IdentityManager::ConstIterator it;
+ for ( it = mIdentityManager->begin() ; it != mIdentityManager->end() ; ++it )
+ mUoidList << (*it).uoid();
+}
+
+void IdentityCombo::slotIdentityManagerChanged() {
+ uint oldIdentity = mUoidList[ currentItem() ];
+
+ reloadUoidList();
+ int idx = mUoidList.findIndex( oldIdentity );
+
+ blockSignals( true );
+ reloadCombo();
+ setCurrentItem( idx < 0 ? 0 : idx );
+ blockSignals( false );
+
+ if ( idx < 0 )
+ // apparently our oldIdentity got deleted:
+ slotEmitChanged( currentItem() );
+}
+
+void IdentityCombo::slotEmitChanged( int idx ) {
+ emit identityChanged( mIdentityManager->identities()[idx] );
+ emit identityChanged( mUoidList[idx] );
+}
+
+#include "identitycombo.moc"
diff --git a/libkpimidentities/identitycombo.h b/libkpimidentities/identitycombo.h
new file mode 100644
index 000000000..193b81d04
--- /dev/null
+++ b/libkpimidentities/identitycombo.h
@@ -0,0 +1,99 @@
+/* -*- c++ -*-
+ identitycombo.h
+
+ This file is part of KMail, the KDE mail client.
+ Copyright (c) 2002 Marc Mutz <mutz@kde.org>
+
+ KMail is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License, version 2, as
+ published by the Free Software Foundation.
+
+ KMail 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
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifndef _KPIM_IDENTITYCOMBO_H_
+#define _KPIM_IDENTITYCOMBO_H_
+
+#include <qcombobox.h>
+#include <qvaluelist.h>
+#include <kdepimmacros.h>
+
+class QString;
+
+namespace KPIM {
+
+class IdentityManager;
+class Identity;
+
+/**
+ * @short A combo box that always shows the up-to-date identity list.
+ * @author Marc Mutz <mutz@kde.org>
+ **/
+
+class KDE_EXPORT IdentityCombo : public QComboBox {
+ Q_OBJECT
+public:
+ IdentityCombo( IdentityManager* manager, QWidget * parent=0, const char * name=0 );
+
+ QString currentIdentityName() const;
+ uint currentIdentity() const;
+ void setCurrentIdentity( const QString & identityName );
+ void setCurrentIdentity( const Identity & identity );
+ void setCurrentIdentity( uint uoid );
+
+signals:
+ /** @deprecated
+ * @em Really emitted whenever the current identity changes. Either
+ * by user intervention or on setCurrentIdentity() or if the
+ * current identity disappears.
+ **/
+ void identityChanged( const QString & identityName );
+
+ /** @em Really emitted whenever the current identity changes. Either
+ * by user intervention or on setCurrentIdentity() or if the
+ * current identity disappears.
+ *
+ * You might also want to listen to IdentityManager::changed,
+ * IdentityManager::deleted and IdentityManager::added.
+ **/
+ void identityChanged( uint uoid );
+
+public slots:
+ /** Connected to IdentityManager::changed(). Reloads the list
+ * of identities.
+ **/
+ void slotIdentityManagerChanged();
+
+protected slots:
+ void slotEmitChanged(int);
+
+protected:
+ void reloadCombo();
+ void reloadUoidList();
+
+protected:
+ QValueList<uint> mUoidList;
+ IdentityManager* mIdentityManager;
+};
+
+} // namespace
+
+#endif // _KPIM_IDENTITYCOMBO_H_
diff --git a/libkpimidentities/identitymanager.cpp b/libkpimidentities/identitymanager.cpp
new file mode 100644
index 000000000..00f3eae45
--- /dev/null
+++ b/libkpimidentities/identitymanager.cpp
@@ -0,0 +1,518 @@
+/* -*- mode: C++; c-file-style: "gnu" -*-
+ identitymanager.cpp
+
+ This file is part of KMail, the KDE mail client.
+ Copyright (c) 2002 Marc Mutz <mutz@kde.org>
+
+ KMail is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License, version 2, as
+ published by the Free Software Foundation.
+
+ KMail 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
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+// config keys:
+static const char configKeyDefaultIdentity[] = "Default Identity";
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "identitymanager.h"
+
+#include "identity.h" // for IdentityList::{export,import}Data
+#include <libemailfunctions/email.h> // for static helper functions
+
+#include <kemailsettings.h> // for IdentityEntry::fromControlCenter()
+#include <kapplication.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kuser.h>
+#include <dcopclient.h>
+
+#include <qregexp.h>
+
+#include <assert.h>
+
+using namespace KPIM;
+
+static QCString newDCOPObjectName()
+{
+ static int s_count = 0;
+ QCString name( "KPIM::IdentityManager" );
+ if ( s_count++ ) {
+ name += '-';
+ name += QCString().setNum( s_count );
+ }
+ return name;
+}
+
+IdentityManager::IdentityManager( bool readonly, QObject * parent, const char * name )
+ : ConfigManager( parent, name ), DCOPObject( newDCOPObjectName() )
+{
+ mReadOnly = readonly;
+ mConfig = new KConfig( "emailidentities", readonly );
+ readConfig(mConfig);
+ if ( mIdentities.isEmpty() ) {
+ kdDebug(5006) << "emailidentities is empty -> convert from kmailrc" << endl;
+ // No emailidentities file, or an empty one due to broken conversion (kconf_update bug in kdelibs <= 3.2.2)
+ // => convert it, i.e. read settings from kmailrc
+ KConfig kmailConf( "kmailrc", true );
+ readConfig( &kmailConf );
+ }
+ // we need at least a default identity:
+ if ( mIdentities.isEmpty() ) {
+ kdDebug( 5006 ) << "IdentityManager: No identity found. Creating default." << endl;
+ createDefaultIdentity();
+ commit();
+ }
+ // Migration: people without settings in kemailsettings should get some
+ if ( KEMailSettings().getSetting( KEMailSettings::EmailAddress ).isEmpty() ) {
+ writeConfig();
+ }
+
+ // The emitter is always called KPIM::IdentityManager even if we are not
+ if ( !connectDCOPSignal( 0, "KPIM::IdentityManager", "identitiesChanged(QCString,QCString)",
+ "slotIdentitiesChanged(QCString,QCString)", false ) )
+ kdError(5650) << "IdentityManager: connection to identitiesChanged failed" << endl;
+}
+
+IdentityManager::~IdentityManager()
+{
+ kdWarning( hasPendingChanges(), 5006 )
+ << "IdentityManager: There were uncommitted changes!" << endl;
+ delete mConfig;
+}
+
+void IdentityManager::commit()
+{
+ // early out:
+ if ( !hasPendingChanges() || mReadOnly ) return;
+
+ QValueList<uint> seenUOIDs;
+ for ( QValueList<Identity>::ConstIterator it = mIdentities.begin() ;
+ it != mIdentities.end() ; ++it )
+ seenUOIDs << (*it).uoid();
+
+ QValueList<uint> changedUOIDs;
+ // find added and changed identities:
+ for ( QValueList<Identity>::ConstIterator it = mShadowIdentities.begin() ;
+ it != mShadowIdentities.end() ; ++it ) {
+ QValueList<uint>::Iterator uoid = seenUOIDs.find( (*it).uoid() );
+ if ( uoid != seenUOIDs.end() ) {
+ const Identity & orig = identityForUoid( *uoid ); // look it up in mIdentities
+ if ( *it != orig ) {
+ // changed identity
+ kdDebug( 5006 ) << "emitting changed() for identity " << *uoid << endl;
+ emit changed( *it );
+ changedUOIDs << *uoid;
+ }
+ seenUOIDs.remove( uoid );
+ } else {
+ // new identity
+ kdDebug( 5006 ) << "emitting added() for identity " << (*it).uoid() << endl;
+ emit added( *it );
+ }
+ }
+
+ // what's left are deleted identities:
+ for ( QValueList<uint>::ConstIterator it = seenUOIDs.begin() ;
+ it != seenUOIDs.end() ; ++it ) {
+ kdDebug( 5006 ) << "emitting deleted() for identity " << (*it) << endl;
+ emit deleted( *it );
+ }
+
+ mIdentities = mShadowIdentities;
+ writeConfig();
+
+ // now that mIdentities has all the new info, we can emit the added/changed
+ // signals that ship a uoid. This is because the slots might use identityForUoid(uoid)...
+ for ( QValueList<uint>::ConstIterator it = changedUOIDs.begin() ;
+ it != changedUOIDs.end() ; ++it )
+ emit changed( *it );
+
+ emit ConfigManager::changed(); // normal signal
+
+ // DCOP signal for other IdentityManager instances
+ // The emitter is always set to KPIM::IdentityManager, so that the connect works
+ // This is why we can't use k_dcop_signals here, but need to use emitDCOPSignal
+ QByteArray data; QDataStream arg( data, IO_WriteOnly );
+ arg << kapp->dcopClient()->appId();
+ arg << DCOPObject::objId(); // the real objId, for checking in slotIdentitiesChanged
+ kapp->dcopClient()->emitDCOPSignal( "KPIM::IdentityManager", "identitiesChanged(QCString,QCString)", data );
+}
+
+void IdentityManager::rollback()
+{
+ mShadowIdentities = mIdentities;
+}
+
+bool IdentityManager::hasPendingChanges() const
+{
+ return mIdentities != mShadowIdentities;
+}
+
+QStringList IdentityManager::identities() const
+{
+ QStringList result;
+ for ( ConstIterator it = mIdentities.begin() ;
+ it != mIdentities.end() ; ++it )
+ result << (*it).identityName();
+ return result;
+}
+
+QStringList IdentityManager::shadowIdentities() const
+{
+ QStringList result;
+ for ( ConstIterator it = mShadowIdentities.begin() ;
+ it != mShadowIdentities.end() ; ++it )
+ result << (*it).identityName();
+ return result;
+}
+
+void IdentityManager::sort() {
+ qHeapSort( mShadowIdentities );
+}
+
+void IdentityManager::writeConfig() const {
+ QStringList identities = groupList(mConfig);
+ for ( QStringList::Iterator group = identities.begin() ;
+ group != identities.end() ; ++group )
+ mConfig->deleteGroup( *group );
+ int i = 0;
+ for ( ConstIterator it = mIdentities.begin() ;
+ it != mIdentities.end() ; ++it, ++i ) {
+ KConfigGroup cg( mConfig, QString::fromLatin1("Identity #%1").arg(i) );
+ (*it).writeConfig( &cg );
+ if ( (*it).isDefault() ) {
+ // remember which one is default:
+ KConfigGroup general( mConfig, "General" );
+ general.writeEntry( configKeyDefaultIdentity, (*it).uoid() );
+
+ // Also write the default identity to emailsettings
+ KEMailSettings es;
+ es.setSetting( KEMailSettings::RealName, (*it).fullName() );
+ es.setSetting( KEMailSettings::EmailAddress, (*it).emailAddr() );
+ es.setSetting( KEMailSettings::Organization, (*it).organization() );
+ es.setSetting( KEMailSettings::ReplyToAddress, (*it).replyToAddr() );
+ }
+ }
+ mConfig->sync();
+
+}
+
+void IdentityManager::readConfig(KConfigBase* config) {
+ mIdentities.clear();
+
+ QStringList identities = groupList(config);
+ if ( identities.isEmpty() ) return; // nothing to be done...
+
+ KConfigGroup general( config, "General" );
+ uint defaultIdentity = general.readUnsignedNumEntry( configKeyDefaultIdentity );
+ bool haveDefault = false;
+
+ for ( QStringList::Iterator group = identities.begin() ;
+ group != identities.end() ; ++group ) {
+ KConfigGroup configGroup( config, *group );
+ mIdentities << Identity();
+ mIdentities.last().readConfig( &configGroup );
+ if ( !haveDefault && mIdentities.last().uoid() == defaultIdentity ) {
+ haveDefault = true;
+ mIdentities.last().setIsDefault( true );
+ }
+ }
+ if ( !haveDefault ) {
+ kdWarning( 5006 ) << "IdentityManager: There was no default identity. Marking first one as default." << endl;
+ mIdentities.first().setIsDefault( true );
+ }
+ qHeapSort( mIdentities );
+
+ mShadowIdentities = mIdentities;
+}
+
+QStringList IdentityManager::groupList(KConfigBase* config) const {
+ return config->groupList().grep( QRegExp("^Identity #\\d+$") );
+}
+
+IdentityManager::ConstIterator IdentityManager::begin() const {
+ return mIdentities.begin();
+}
+
+IdentityManager::ConstIterator IdentityManager::end() const {
+ return mIdentities.end();
+}
+
+IdentityManager::Iterator IdentityManager::modifyBegin() {
+ return mShadowIdentities.begin();
+}
+
+IdentityManager::Iterator IdentityManager::modifyEnd() {
+ return mShadowIdentities.end();
+}
+
+const Identity & IdentityManager::identityForName( const QString & name ) const
+{
+ kdWarning( 5006 )
+ << "deprecated method IdentityManager::identityForName() called!" << endl;
+ for ( ConstIterator it = begin() ; it != end() ; ++it )
+ if ( (*it).identityName() == name ) return (*it);
+ return Identity::null();
+}
+
+const Identity & IdentityManager::identityForUoid( uint uoid ) const {
+ for ( ConstIterator it = begin() ; it != end() ; ++it )
+ if ( (*it).uoid() == uoid ) return (*it);
+ return Identity::null();
+}
+
+const Identity & IdentityManager::identityForNameOrDefault( const QString & name ) const
+{
+ const Identity & ident = identityForName( name );
+ if ( ident.isNull() )
+ return defaultIdentity();
+ else
+ return ident;
+}
+
+const Identity & IdentityManager::identityForUoidOrDefault( uint uoid ) const
+{
+ const Identity & ident = identityForUoid( uoid );
+ if ( ident.isNull() )
+ return defaultIdentity();
+ else
+ return ident;
+}
+
+const Identity & IdentityManager::identityForAddress( const QString & addresses ) const
+{
+ QStringList addressList = KPIM::splitEmailAddrList( addresses );
+ for ( ConstIterator it = begin() ; it != end() ; ++it ) {
+ for( QStringList::ConstIterator addrIt = addressList.begin();
+ addrIt != addressList.end(); ++addrIt ) {
+ // I use QString::utf8() instead of QString::latin1() because I want
+ // a QCString and not a char*. It doesn't matter because emailAddr()
+ // returns a 7-bit string.
+ if( (*it).emailAddr().lower() ==
+ KPIM::getEmailAddress( *addrIt ).lower() ) {
+ return (*it);
+ }
+ }
+ }
+ return Identity::null();
+}
+
+bool IdentityManager::thatIsMe( const QString & addressList ) const {
+ return !identityForAddress( addressList ).isNull();
+}
+
+Identity & IdentityManager::modifyIdentityForName( const QString & name )
+{
+ for ( Iterator it = modifyBegin() ; it != modifyEnd() ; ++it )
+ if ( (*it).identityName() == name ) return (*it);
+ kdWarning( 5006 ) << "IdentityManager::identityForName() used as newFromScratch() replacement!"
+ << "\n name == \"" << name << "\"" << endl;
+ return newFromScratch( name );
+}
+
+Identity & IdentityManager::modifyIdentityForUoid( uint uoid )
+{
+ for ( Iterator it = modifyBegin() ; it != modifyEnd() ; ++it )
+ if ( (*it).uoid() == uoid ) return (*it);
+ kdWarning( 5006 ) << "IdentityManager::identityForUoid() used as newFromScratch() replacement!"
+ << "\n uoid == \"" << uoid << "\"" << endl;
+ return newFromScratch( i18n("Unnamed") );
+}
+
+const Identity & IdentityManager::defaultIdentity() const {
+ for ( ConstIterator it = begin() ; it != end() ; ++it )
+ if ( (*it).isDefault() ) return (*it);
+ (mIdentities.isEmpty() ? kdFatal( 5006 ) : kdWarning( 5006 ) )
+ << "IdentityManager: No default identity found!" << endl;
+ return *begin();
+}
+
+bool IdentityManager::setAsDefault( const QString & name ) {
+ // First, check if the identity actually exists:
+ QStringList names = shadowIdentities();
+ if ( names.find( name ) == names.end() ) return false;
+ // Then, change the default as requested:
+ for ( Iterator it = modifyBegin() ; it != modifyEnd() ; ++it )
+ (*it).setIsDefault( (*it).identityName() == name );
+ // and re-sort:
+ sort();
+ return true;
+}
+
+bool IdentityManager::setAsDefault( uint uoid ) {
+ // First, check if the identity actually exists:
+ bool found = false;
+ for ( ConstIterator it = mShadowIdentities.begin() ;
+ it != mShadowIdentities.end() ; ++it )
+ if ( (*it).uoid() == uoid ) {
+ found = true;
+ break;
+ }
+ if ( !found ) return false;
+
+ // Then, change the default as requested:
+ for ( Iterator it = modifyBegin() ; it != modifyEnd() ; ++it )
+ (*it).setIsDefault( (*it).uoid() == uoid );
+ // and re-sort:
+ sort();
+ return true;
+}
+
+bool IdentityManager::removeIdentity( const QString & name ) {
+ for ( Iterator it = modifyBegin() ; it != modifyEnd() ; ++it )
+ if ( (*it).identityName() == name ) {
+ bool removedWasDefault = (*it).isDefault();
+ mShadowIdentities.remove( it );
+ if ( removedWasDefault )
+ mShadowIdentities.first().setIsDefault( true );
+ return true;
+ }
+ return false;
+}
+
+Identity & IdentityManager::newFromScratch( const QString & name ) {
+ return newFromExisting( Identity( name ) );
+}
+
+Identity & IdentityManager::newFromControlCenter( const QString & name ) {
+ KEMailSettings es;
+ es.setProfile( es.defaultProfileName() );
+
+ return newFromExisting( Identity( name,
+ es.getSetting( KEMailSettings::RealName ),
+ es.getSetting( KEMailSettings::EmailAddress ),
+ es.getSetting( KEMailSettings::Organization ),
+ es.getSetting( KEMailSettings::ReplyToAddress )
+ ) );
+}
+
+Identity & IdentityManager::newFromExisting( const Identity & other,
+ const QString & name ) {
+ mShadowIdentities << other;
+ Identity & result = mShadowIdentities.last();
+ result.setIsDefault( false ); // we don't want two default identities!
+ result.setUoid( newUoid() ); // we don't want two identies w/ same UOID
+ if ( !name.isNull() )
+ result.setIdentityName( name );
+ return result;
+}
+
+void IdentityManager::createDefaultIdentity() {
+ QString fullName, emailAddress;
+ bool done = false;
+
+ // Check if the application has any settings
+ createDefaultIdentity( fullName, emailAddress );
+
+ // If not, then use the kcontrol settings
+ if ( fullName.isEmpty() && emailAddress.isEmpty() ) {
+ KEMailSettings emailSettings;
+ fullName = emailSettings.getSetting( KEMailSettings::RealName );
+ emailAddress = emailSettings.getSetting( KEMailSettings::EmailAddress );
+
+ if ( !fullName.isEmpty() && !emailAddress.isEmpty() ) {
+ newFromControlCenter( i18n("Default") );
+ done = true;
+ } else {
+ // If KEmailSettings doesn't have name and address, generate something from KUser
+ KUser user;
+ if ( fullName.isEmpty() )
+ fullName = user.fullName();
+ if ( emailAddress.isEmpty() ) {
+ emailAddress = user.loginName();
+ if ( !emailAddress.isEmpty() ) {
+ KConfigGroup general( mConfig, "General" );
+ QString defaultdomain = general.readEntry( "Default domain" );
+ if( !defaultdomain.isEmpty() ) {
+ emailAddress += '@' + defaultdomain;
+ }
+ else {
+ emailAddress = QString::null;
+ }
+ }
+ }
+ }
+ }
+
+ if ( !done )
+ mShadowIdentities << Identity( i18n("Default"), fullName, emailAddress );
+
+ mShadowIdentities.last().setIsDefault( true );
+ mShadowIdentities.last().setUoid( newUoid() );
+ if ( mReadOnly ) // commit won't do it in readonly mode
+ mIdentities = mShadowIdentities;
+}
+
+int IdentityManager::newUoid()
+{
+ int uoid;
+
+ // determine the UOIDs of all saved identities
+ QValueList<uint> usedUOIDs;
+ for ( QValueList<Identity>::ConstIterator it = mIdentities.begin() ;
+ it != mIdentities.end() ; ++it )
+ usedUOIDs << (*it).uoid();
+
+ if ( hasPendingChanges() ) {
+ // add UOIDs of all shadow identities. Yes, we will add a lot of duplicate
+ // UOIDs, but avoiding duplicate UOIDs isn't worth the effort.
+ for ( QValueList<Identity>::ConstIterator it = mShadowIdentities.begin() ;
+ it != mShadowIdentities.end() ; ++it ) {
+ usedUOIDs << (*it).uoid();
+ }
+ }
+
+ usedUOIDs << 0; // no UOID must be 0 because this value always refers to the
+ // default identity
+
+ do {
+ uoid = kapp->random();
+ } while ( usedUOIDs.find( uoid ) != usedUOIDs.end() );
+
+ return uoid;
+}
+
+QStringList KPIM::IdentityManager::allEmails() const
+{
+ QStringList lst;
+ for ( ConstIterator it = begin() ; it != end() ; ++it ) {
+ lst << (*it).emailAddr();
+ }
+ return lst;
+}
+
+void KPIM::IdentityManager::slotIdentitiesChanged( QCString appId, QCString objId )
+{
+ // From standalone kmail to standalone korganizer, the appId will differ
+ // From kontact the appId will match, so we need to test the objId
+ if ( kapp->dcopClient()->appId() != appId || DCOPObject::objId() != objId ) {
+ mConfig->reparseConfiguration();
+ Q_ASSERT( !hasPendingChanges() );
+ readConfig( mConfig );
+ }
+}
+
+#include "identitymanager.moc"
diff --git a/libkpimidentities/identitymanager.h b/libkpimidentities/identitymanager.h
new file mode 100644
index 000000000..b07ba7434
--- /dev/null
+++ b/libkpimidentities/identitymanager.h
@@ -0,0 +1,242 @@
+/* -*- c++ -*-
+ identitymanager.h
+
+ This file is part of KMail, the KDE mail client.
+ Copyright (c) 2002 Marc Mutz <mutz@kde.org>
+
+ KMail is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License, version 2, as
+ published by the Free Software Foundation.
+
+ KMail 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
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+#ifndef _KPIM_IDENTITYMANAGER_H_
+#define _KPIM_IDENTITYMANAGER_H_
+
+#include <libkdepim/configmanager.h>
+
+#include <qvaluelist.h>
+#include <dcopobject.h>
+#include <kdepimmacros.h>
+
+class KConfigBase;
+class KConfig;
+class KMKernel;
+class QStringList;
+class KMIdentity;
+
+namespace KPIM {
+
+class Identity;
+/**
+ * @short Manages the list of identities.
+ * @author Marc Mutz <mutz@kde.org>
+ **/
+#define IdentityManager KDE_EXPORT IdentityManager
+class IdentityManager : public ConfigManager, public DCOPObject
+#undef IdentityManager
+{
+ Q_OBJECT
+ K_DCOP
+
+public:
+ /**
+ * Create an identity manager, which loads the emailidentities file
+ * to create identities.
+ * @param readonly if true, no changes can be made to the identity manager
+ * This means in particular that if there is no identity configured,
+ * the default identity created here will not be saved.
+ */
+ IdentityManager( bool readonly = false, QObject * parent=0, const char * name=0 );
+ virtual ~IdentityManager();
+
+public:
+ typedef QValueList<Identity>::Iterator Iterator;
+ typedef QValueList<Identity>::ConstIterator ConstIterator;
+
+ /** Commit changes to disk and emit changed() if necessary. */
+ void commit();
+ /** Re-read the config from disk and forget changes. */
+ void rollback();
+
+ /** Check whether there are any unsaved changes. */
+ bool hasPendingChanges() const;
+
+ /** @return the list of identities */
+ QStringList identities() const;
+
+ /** Convenience method.
+
+ @return the list of (shadow) identities, ie. the ones currently
+ under configuration.
+ */
+ QStringList shadowIdentities() const;
+
+ /** Sort the identities by name (the default is always first). This
+ operates on the @em shadow list, so you need to @ref commit for
+ the changes to take effect.
+ **/
+ void sort();
+
+ /** @return an identity whose address matches any in @p addresses
+ or @ref Identity::null if no such identity exists.
+ **/
+ const Identity & identityForAddress( const QString & addresses ) const;
+
+ /** @return true if @p addressList contains any of our addresses,
+ false otherwise.
+ @see #identityForAddress
+ **/
+ bool thatIsMe( const QString & addressList ) const;
+
+ /** @deprecated
+ @return the identity named @p identityName or @ref
+ Identity::null if not found.
+ **/
+ const Identity & identityForName( const QString & identityName ) const;
+
+ /** @return the identity with Unique Object Identifier (UOID) @p
+ uoid or @ref Identity::null if not found.
+ **/
+ const Identity & identityForUoid( uint uoid ) const;
+
+ /** @deprecated
+ Convenience method.
+
+ @return the identity named @p identityName or the default
+ identity if not found.
+ **/
+ const Identity & identityForNameOrDefault( const QString & identityName ) const;
+
+ /** Convenience menthod.
+
+ @return the identity with Unique Object Identifier (UOID) @p
+ uoid or the default identity if not found.
+ **/
+ const Identity & identityForUoidOrDefault( uint uoid ) const;
+
+ /** @return the default identity */
+ const Identity & defaultIdentity() const;
+
+ /** @deprecated
+ Sets the identity named @p identityName to be the new default
+ identity. As usual, use @ref commit to make this permanent.
+
+ @return false if an identity named @p identityName was not found
+ **/
+ bool setAsDefault( const QString & identityName );
+
+ /** Sets the identity with Unique Object Identifier (UOID) @p uoid
+ to be new the default identity. As usual, use @ref commit to
+ make this permanent.
+
+ @return false if an identity with UOID @p uoid was not found
+ **/
+ bool setAsDefault( uint uoid );
+
+ /** @return the identity named @p identityName. This method returns a
+ reference to the identity that can be modified. To let others
+ see this change, use @ref commit.
+ **/
+ Identity & modifyIdentityForName( const QString & identityName );
+
+ /** @return the identity with Unique Object Identifier (UOID) @p uoid.
+ This method returns a reference to the identity that can
+ be modified. To let others see this change, use @ref commit.
+ **/
+ Identity & modifyIdentityForUoid( uint uoid );
+
+ /** Removes the identity with name @p identityName */
+ bool removeIdentity( const QString & identityName );
+
+ ConstIterator begin() const;
+ ConstIterator end() const;
+ /// Iterator used by the configuration dialog, which works on a separate list
+ /// of identities, for modification. Changes are made effective by commit().
+ Iterator modifyBegin();
+ Iterator modifyEnd();
+
+ Identity & newFromScratch( const QString & name );
+ Identity & newFromControlCenter( const QString & name );
+ Identity & newFromExisting( const Identity & other,
+ const QString & name=QString::null );
+
+ /** Returns the list of all email addresses (only name@host) from all identities */
+ QStringList allEmails() const;
+
+signals:
+ /** Emitted whenever the identity with Unique Object Identifier
+ (UOID) @p uoid changed. Useful for more fine-grained change
+ notifications than what is possible with the standard @ref
+ changed() signal. */
+ void changed( uint uoid );
+ /** Emitted whenever the identity @p ident changed. Useful for more
+ fine-grained change notifications than what is possible with the
+ standard @ref changed() signal. */
+ void changed( const KPIM::Identity & ident );
+ /** Emitted on @ref commit() for each deleted identity. At the time
+ this signal is emitted, the identity does still exist and can be
+ retrieved by @ref identityForUoid() if needed */
+ void deleted( uint uoid );
+ /** Emitted on @ref commit() for each new identity */
+ void added( const KPIM::Identity & ident );
+
+protected:
+ /**
+ * This is called when no identity has been defined, so we need to create a default one
+ * The parameters are filled with some default values from KUser,
+ * but reimplementations of this method can give them another value.
+ */
+ virtual void createDefaultIdentity( QString& /*fullName*/, QString& /*emailAddress*/ ) {}
+
+protected slots:
+ void slotRollback() { rollback(); };
+
+protected:
+ /** The list that will be seen by everyone */
+ QValueList<Identity> mIdentities;
+ /** The list that will be seen by the config dialog */
+ QValueList<Identity> mShadowIdentities;
+
+//k_dcop_signals:
+// void identitiesChanged( QCString appId, QCString objId );
+
+k_dcop:
+ // Connected to the DCOP signal
+ void slotIdentitiesChanged( QCString appId, QCString objId );
+
+private:
+ void writeConfig() const;
+ void readConfig(KConfigBase* config);
+ QStringList groupList(KConfigBase* config) const;
+ void createDefaultIdentity();
+
+ // returns a new Unique Object Identifier
+ int newUoid();
+
+private:
+ KConfig* mConfig;
+ bool mReadOnly;
+};
+
+} // namespace
+
+#endif // _KMAIL_IDENTITYMANAGER_H_