You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
489 lines
12 KiB
489 lines
12 KiB
// kmidentity.cpp |
|
|
|
#include "kmidentity.h" |
|
#include "kfileio.h" |
|
#include "kmkernel.h" |
|
|
|
#include <kdebug.h> |
|
#include <klocale.h> |
|
#include <kmessagebox.h> |
|
#include <kprocess.h> |
|
#include <kconfig.h> |
|
|
|
#include <qfileinfo.h> |
|
|
|
#include <pwd.h> |
|
#include <sys/types.h> |
|
#include <unistd.h> |
|
#include <stdlib.h> |
|
#include <stdio.h> |
|
#include <errno.h> |
|
#include <assert.h> |
|
|
|
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: |
|
KProcess proc; |
|
proc.setUseShell(true); |
|
proc << mUrl; |
|
|
|
// let the kernel collect the output for us: |
|
QObject::connect( &proc, SIGNAL(receivedStdout(KProcess*,char*,int)), |
|
kernel, SLOT(slotCollectStdOut(KProcess*,char*,int)) ); |
|
|
|
// run the process: |
|
int rc = 0; |
|
if ( !proc.start( KProcess::Block, KProcess::Stdout ) ) |
|
rc = -1; |
|
else |
|
rc = ( proc.normalExit() ) ? proc.exitStatus() : -1 ; |
|
|
|
// get output: |
|
QByteArray output = kernel->getCollectedStdOut( &proc ); |
|
|
|
// 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; |
|
// ### 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 ) ); |
|
} |
|
|
|
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; |
|
mText = config->readEntry( sigTextKey ); |
|
} else if ( sigType == sigTypeFileValue ) { |
|
mType = FromFile; |
|
mUrl = config->readEntry( sigFileKey ); |
|
} else if ( sigType == sigTypeCommandValue ) { |
|
mType = FromCommand; |
|
mUrl = config->readEntry( sigCommandKey ); |
|
} else { |
|
mType = Disabled; |
|
} |
|
} |
|
|
|
void Signature::writeConfig( KConfigBase * config ) const |
|
{ |
|
switch ( mType ) { |
|
case Inlined: |
|
config->writeEntry( sigTypeKey, sigTypeInlineValue ); |
|
config->writeEntry( sigTextKey, mText ); |
|
break; |
|
case FromFile: |
|
config->writeEntry( sigTypeKey, sigTypeFileValue ); |
|
config->writeEntry( sigFileKey, mUrl ); |
|
break; |
|
case FromCommand: |
|
config->writeEntry( sigTypeKey, sigTypeCommandValue ); |
|
config->writeEntry( sigCommandKey, mUrl ); |
|
break; |
|
case Disabled: |
|
config->writeEntry( sigTypeKey, sigTypeDisabledValue ); |
|
default: ; |
|
} |
|
} |
|
|
|
QDataStream & operator<<( QDataStream & stream, const Signature & sig ) { |
|
return stream << static_cast<Q_UINT8>(sig.mType) |
|
<< sig.mUrl |
|
<< sig.mText; |
|
} |
|
|
|
QDataStream & operator>>( QDataStream & stream, Signature & sig ) { |
|
Q_UINT8 s; |
|
stream >> s |
|
>> sig.mUrl |
|
>> sig.mText; |
|
sig.mType = static_cast<Signature::Type>(s); |
|
return stream; |
|
} |
|
|
|
KMIdentity KMIdentity::null; |
|
|
|
bool KMIdentity::isNull() const { |
|
return mIdentity.isNull() && mFullName.isNull() && mEmailAddr.isNull() && |
|
mOrganization.isNull() && mReplyToAddr.isNull() && mBcc.isNull() && |
|
mVCardFile.isNull() && |
|
mPgpIdentity.isNull() && mFcc.isNull() && mDrafts.isNull() && |
|
mTransport.isNull() && mSignature.type() == Signature::Disabled; |
|
} |
|
|
|
bool KMIdentity::operator==( const KMIdentity & other ) const { |
|
return mUoid == other.mUoid && |
|
mIdentity == other.mIdentity && mFullName == other.mFullName && |
|
mEmailAddr == other.mEmailAddr && mOrganization == other.mOrganization && |
|
mReplyToAddr == other.mReplyToAddr && mBcc == other.mBcc && |
|
mVCardFile == other.mVCardFile && |
|
mPgpIdentity == other.mPgpIdentity && mFcc == other.mFcc && |
|
mDrafts == other.mDrafts && mTransport == other.mTransport && |
|
mSignature == other.mSignature; |
|
} |
|
|
|
KMIdentity::KMIdentity( 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 ), mIsDefault( false ) |
|
{ |
|
|
|
} |
|
|
|
KMIdentity::~KMIdentity() |
|
{ |
|
} |
|
|
|
|
|
void KMIdentity::readConfig( const KConfigBase * config ) |
|
{ |
|
mUoid = config->readUnsignedNumEntry("uoid",0); |
|
|
|
mIdentity = config->readEntry("Identity"); |
|
mFullName = config->readEntry("Name"); |
|
mEmailAddr = config->readEntry("Email Address"); |
|
mVCardFile = config->readEntry("VCardFile"); |
|
mOrganization = config->readEntry("Organization"); |
|
mPgpIdentity = config->readEntry("Default PGP Key").local8Bit(); |
|
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"; |
|
mTransport = config->readEntry("Transport"); |
|
|
|
mSignature.readConfig( config ); |
|
kdDebug(5006) << "KMIdentity::readConfig(): UOID = " << mUoid |
|
<< " for identity named \"" << mIdentity << "\"" << endl; |
|
} |
|
|
|
|
|
void KMIdentity::writeConfig( KConfigBase * config ) const |
|
{ |
|
config->writeEntry("uoid", mUoid); |
|
|
|
config->writeEntry("Identity", mIdentity); |
|
config->writeEntry("Name", mFullName); |
|
config->writeEntry("Organization", mOrganization); |
|
config->writeEntry("Default PGP Key", mPgpIdentity.data()); |
|
config->writeEntry("Email Address", mEmailAddr); |
|
config->writeEntry("Reply-To Address", mReplyToAddr); |
|
config->writeEntry("Bcc", mBcc); |
|
config->writeEntry("VCardFile", mVCardFile); |
|
config->writeEntry("Transport", mTransport); |
|
config->writeEntry("Fcc", mFcc); |
|
config->writeEntry("Drafts", mDrafts); |
|
|
|
mSignature.writeConfig( config ); |
|
} |
|
|
|
QDataStream & operator<<( QDataStream & stream, const KMIdentity & i ) { |
|
return stream << static_cast<Q_UINT32>(i.uoid()) |
|
<< i.identityName() |
|
<< i.fullName() |
|
<< i.organization() |
|
<< i.pgpIdentity() |
|
<< i.emailAddr() |
|
<< i.replyToAddr() |
|
<< i.bcc() |
|
<< i.vCardFile() |
|
<< i.transport() |
|
<< i.fcc() |
|
<< i.drafts() |
|
<< i.mSignature; |
|
} |
|
|
|
QDataStream & operator>>( QDataStream & stream, KMIdentity & i ) { |
|
#if 1 // why doesn't it work like for Q_UINT8 above??? |
|
Q_UINT32 uoid; |
|
stream >> uoid; |
|
i.mUoid = uoid; |
|
return stream |
|
#else |
|
return stream >> (Q_UINT32)i.mUoid |
|
#endif |
|
>> i.mIdentity |
|
>> i.mFullName |
|
>> i.mOrganization |
|
>> i.mPgpIdentity |
|
>> i.mEmailAddr |
|
>> i.mReplyToAddr |
|
>> i.mBcc |
|
>> i.mVCardFile |
|
>> i.mTransport |
|
>> i.mFcc |
|
>> i.mDrafts |
|
>> i.mSignature; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMIdentity::mailingAllowed() const |
|
{ |
|
return !mEmailAddr.isEmpty(); |
|
} |
|
|
|
|
|
void KMIdentity::setIsDefault( bool flag ) { |
|
mIsDefault = flag; |
|
} |
|
|
|
void KMIdentity::setIdentityName( const QString & name ) { |
|
mIdentity = name; |
|
} |
|
|
|
void KMIdentity::setFullName(const QString &str) |
|
{ |
|
mFullName = str; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMIdentity::setOrganization(const QString &str) |
|
{ |
|
mOrganization = str; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMIdentity::setPgpIdentity(const QCString &str) |
|
{ |
|
mPgpIdentity = str; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMIdentity::setEmailAddr(const QString &str) |
|
{ |
|
mEmailAddr = str; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMIdentity::setVCardFile(const QString &str) |
|
{ |
|
mVCardFile = str; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
QString KMIdentity::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 KMIdentity::setReplyToAddr(const QString& str) |
|
{ |
|
mReplyToAddr = str; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMIdentity::setSignatureFile(const QString &str) |
|
{ |
|
mSignature.setUrl( str, signatureIsCommand() ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMIdentity::setSignatureInlineText(const QString &str ) |
|
{ |
|
mSignature.setText( str ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMIdentity::setTransport(const QString &str) |
|
{ |
|
mTransport = str; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMIdentity::setFcc(const QString &str) |
|
{ |
|
mFcc = str; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMIdentity::setDrafts(const QString &str) |
|
{ |
|
mDrafts = str; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
QString KMIdentity::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; |
|
}
|
|
|