00001
00002
00003
00004 #ifdef HAVE_CONFIG_H
00005 #include <config.h>
00006 #endif
00007
00008 #include "kmidentity.h"
00009 #include "kfileio.h"
00010 #include "kmkernel.h"
00011
00012 #include <kdebug.h>
00013 #include <klocale.h>
00014 #include <kmessagebox.h>
00015 #include <kprocess.h>
00016 #include <kconfig.h>
00017
00018 #include <qfileinfo.h>
00019
00020 #include <sys/types.h>
00021 #include <stdlib.h>
00022 #include <stdio.h>
00023 #include <errno.h>
00024 #include <assert.h>
00025
00026 Signature::Signature()
00027 : mType( Disabled )
00028 {
00029
00030 }
00031
00032 Signature::Signature( const QString & text )
00033 : mText( text ),
00034 mType( Inlined )
00035 {
00036
00037 }
00038
00039 Signature::Signature( const QString & url, bool isExecutable )
00040 : mUrl( url ),
00041 mType( isExecutable ? FromCommand : FromFile )
00042 {
00043 }
00044
00045 bool Signature::operator==( const Signature & other ) const {
00046 if ( mType != other.mType ) return false;
00047 switch ( mType ) {
00048 case Inlined: return mText == other.mText;
00049 case FromFile:
00050 case FromCommand: return mUrl == other.mUrl;
00051 default:
00052 case Disabled: return true;
00053 }
00054 }
00055
00056 QString Signature::rawText( bool * ok ) const
00057 {
00058 switch ( mType ) {
00059 case Disabled:
00060 if ( ok ) *ok = true;
00061 return QString::null;
00062 case Inlined:
00063 if ( ok ) *ok = true;
00064 return mText;
00065 case FromFile:
00066 return textFromFile( ok );
00067 case FromCommand:
00068 return textFromCommand( ok );
00069 };
00070 kdFatal( 5006 ) << "Signature::type() returned unknown value!" << endl;
00071 return QString::null;
00072 }
00073
00074 QString Signature::textFromCommand( bool * ok ) const
00075 {
00076 assert( mType == FromCommand );
00077
00078
00079 if ( mUrl.isEmpty() ) {
00080 if ( ok ) *ok = true;
00081 return QString::null;
00082 }
00083
00084
00085 KProcess proc;
00086 proc.setUseShell(true);
00087 proc << mUrl;
00088
00089
00090 QObject::connect( &proc, SIGNAL(receivedStdout(KProcess*,char*,int)),
00091 kmkernel, SLOT(slotCollectStdOut(KProcess*,char*,int)) );
00092
00093
00094 int rc = 0;
00095 if ( !proc.start( KProcess::Block, KProcess::Stdout ) )
00096 rc = -1;
00097 else
00098 rc = ( proc.normalExit() ) ? proc.exitStatus() : -1 ;
00099
00100
00101 QByteArray output = kmkernel->getCollectedStdOut( &proc );
00102
00103
00104 if ( rc != 0 ) {
00105 if ( ok ) *ok = false;
00106 QString wmsg = i18n("<qt>Failed to execute signature script<br><b>%1</b>:<br>%2</qt>")
00107 .arg( mUrl ).arg( strerror(rc) );
00108 KMessageBox::error(0, wmsg);
00109 return QString::null;
00110 }
00111
00112
00113 if ( ok ) *ok = true;
00114
00115 return QString::fromLocal8Bit( output.data(), output.size() );
00116 }
00117
00118 QString Signature::textFromFile( bool * ok ) const
00119 {
00120 assert( mType == FromFile );
00121
00122
00123 if ( !KURL(mUrl).isLocalFile() && !(QFileInfo(mUrl).isRelative()
00124 && QFileInfo(mUrl).exists()) ) {
00125 kdDebug( 5006 ) << "Signature::textFromFile: non-local URLs are unsupported" << endl;
00126 if ( ok ) *ok = false;
00127 return QString::null;
00128 }
00129 if ( ok ) *ok = true;
00130
00131 return QString::fromLocal8Bit( kFileToString( mUrl, false ) );
00132 }
00133
00134 QString Signature::withSeparator( bool * ok ) const
00135 {
00136 bool internalOK = false;
00137 QString signature = rawText( &internalOK );
00138 if ( !internalOK ) {
00139 if ( ok ) *ok = false;
00140 return QString::null;
00141 }
00142 if ( ok ) *ok = true;
00143 if ( signature.isEmpty() ) return signature;
00144 if ( signature.startsWith( QString::fromLatin1("-- \n") ) )
00145
00146 return QString::fromLatin1("\n") += signature;
00147 else if ( signature.find( QString::fromLatin1("\n-- \n") ) != -1 )
00148
00149
00150 return signature;
00151 else
00152
00153 return QString::fromLatin1("\n-- \n") + signature;
00154 }
00155
00156
00157 void Signature::setUrl( const QString & url, bool isExecutable )
00158 {
00159 mUrl = url;
00160 mType = isExecutable ? FromCommand : FromFile ;
00161 }
00162
00163
00164 static const char sigTypeKey[] = "Signature Type";
00165 static const char sigTypeInlineValue[] = "inline";
00166 static const char sigTypeFileValue[] = "file";
00167 static const char sigTypeCommandValue[] = "command";
00168 static const char sigTypeDisabledValue[] = "disabled";
00169 static const char sigTextKey[] = "Inline Signature";
00170 static const char sigFileKey[] = "Signature File";
00171 static const char sigCommandKey[] = "Signature Command";
00172
00173 void Signature::readConfig( const KConfigBase * config )
00174 {
00175 QString sigType = config->readEntry( sigTypeKey );
00176 if ( sigType == sigTypeInlineValue ) {
00177 mType = Inlined;
00178 mText = config->readEntry( sigTextKey );
00179 } else if ( sigType == sigTypeFileValue ) {
00180 mType = FromFile;
00181 mUrl = config->readPathEntry( sigFileKey );
00182 } else if ( sigType == sigTypeCommandValue ) {
00183 mType = FromCommand;
00184 mUrl = config->readPathEntry( sigCommandKey );
00185 } else {
00186 mType = Disabled;
00187 }
00188 }
00189
00190 void Signature::writeConfig( KConfigBase * config ) const
00191 {
00192 switch ( mType ) {
00193 case Inlined:
00194 config->writeEntry( sigTypeKey, sigTypeInlineValue );
00195 config->writeEntry( sigTextKey, mText );
00196 break;
00197 case FromFile:
00198 config->writeEntry( sigTypeKey, sigTypeFileValue );
00199 config->writePathEntry( sigFileKey, mUrl );
00200 break;
00201 case FromCommand:
00202 config->writeEntry( sigTypeKey, sigTypeCommandValue );
00203 config->writePathEntry( sigCommandKey, mUrl );
00204 break;
00205 case Disabled:
00206 config->writeEntry( sigTypeKey, sigTypeDisabledValue );
00207 default: ;
00208 }
00209 }
00210
00211 QDataStream & operator<<( QDataStream & stream, const Signature & sig ) {
00212 return stream << static_cast<Q_UINT8>(sig.mType)
00213 << sig.mUrl
00214 << sig.mText;
00215 }
00216
00217 QDataStream & operator>>( QDataStream & stream, Signature & sig ) {
00218 Q_UINT8 s;
00219 stream >> s
00220 >> sig.mUrl
00221 >> sig.mText;
00222 sig.mType = static_cast<Signature::Type>(s);
00223 return stream;
00224 }
00225
00226 KMIdentity KMIdentity::null;
00227
00228 bool KMIdentity::isNull() const {
00229 return mIdentity.isNull() && mFullName.isNull() && mEmailAddr.isNull() &&
00230 mOrganization.isNull() && mReplyToAddr.isNull() && mBcc.isNull() &&
00231 mVCardFile.isNull() &&
00232 mPgpIdentity.isNull() && mFcc.isNull() && mDrafts.isNull() &&
00233 mTransport.isNull() && mDictionary.isNull() &&
00234 mSignature.type() == Signature::Disabled;
00235 }
00236
00237 bool KMIdentity::operator==( const KMIdentity & other ) const {
00238 return mUoid == other.mUoid &&
00239 mIdentity == other.mIdentity && mFullName == other.mFullName &&
00240 mEmailAddr == other.mEmailAddr && mOrganization == other.mOrganization &&
00241 mReplyToAddr == other.mReplyToAddr && mBcc == other.mBcc &&
00242 mVCardFile == other.mVCardFile &&
00243 mPgpIdentity == other.mPgpIdentity && mFcc == other.mFcc &&
00244 mDrafts == other.mDrafts && mTransport == other.mTransport &&
00245 mDictionary == other.mDictionary && mSignature == other.mSignature;
00246 }
00247
00248 KMIdentity::KMIdentity( const QString & id, const QString & fullName,
00249 const QString & emailAddr, const QString & organization,
00250 const QString & replyToAddr )
00251 : mUoid( 0 ), mIdentity( id ), mFullName( fullName ),
00252 mEmailAddr( emailAddr ), mOrganization( organization ),
00253 mReplyToAddr( replyToAddr ), mIsDefault( false )
00254 {
00255
00256 }
00257
00258 KMIdentity::~KMIdentity()
00259 {
00260 }
00261
00262
00263 void KMIdentity::readConfig( const KConfigBase * config )
00264 {
00265 mUoid = config->readUnsignedNumEntry("uoid",0);
00266
00267 mIdentity = config->readEntry("Identity");
00268 mFullName = config->readEntry("Name");
00269 mEmailAddr = config->readEntry("Email Address");
00270 mVCardFile = config->readPathEntry("VCardFile");
00271 mOrganization = config->readEntry("Organization");
00272 mPgpIdentity = config->readEntry("Default PGP Key").local8Bit();
00273 mReplyToAddr = config->readEntry("Reply-To Address");
00274 mBcc = config->readEntry("Bcc");
00275 mFcc = config->readEntry("Fcc", "sent-mail");
00276 if( mFcc.isEmpty() )
00277 mFcc = "sent-mail";
00278 mDrafts = config->readEntry("Drafts", "drafts");
00279 if( mDrafts.isEmpty() )
00280 mDrafts = "drafts";
00281 mTransport = config->readEntry("Transport");
00282 mDictionary = config->readEntry( "Dictionary" );
00283
00284 mSignature.readConfig( config );
00285 kdDebug(5006) << "KMIdentity::readConfig(): UOID = " << mUoid
00286 << " for identity named \"" << mIdentity << "\"" << endl;
00287 }
00288
00289
00290 void KMIdentity::writeConfig( KConfigBase * config ) const
00291 {
00292 config->writeEntry("uoid", mUoid);
00293
00294 config->writeEntry("Identity", mIdentity);
00295 config->writeEntry("Name", mFullName);
00296 config->writeEntry("Organization", mOrganization);
00297 config->writeEntry("Default PGP Key", mPgpIdentity.data());
00298 config->writeEntry("Email Address", mEmailAddr);
00299 config->writeEntry("Reply-To Address", mReplyToAddr);
00300 config->writeEntry("Bcc", mBcc);
00301 config->writePathEntry("VCardFile", mVCardFile);
00302 config->writeEntry("Transport", mTransport);
00303 config->writeEntry("Fcc", mFcc);
00304 config->writeEntry("Drafts", mDrafts);
00305 config->writeEntry( "Dictionary", mDictionary );
00306
00307 mSignature.writeConfig( config );
00308 }
00309
00310 QDataStream & operator<<( QDataStream & stream, const KMIdentity & i ) {
00311 return stream << static_cast<Q_UINT32>(i.uoid())
00312 << i.identityName()
00313 << i.fullName()
00314 << i.organization()
00315 << i.pgpIdentity()
00316 << i.emailAddr()
00317 << i.replyToAddr()
00318 << i.bcc()
00319 << i.vCardFile()
00320 << i.transport()
00321 << i.fcc()
00322 << i.drafts()
00323 << i.mSignature
00324 << i.dictionary();
00325 }
00326
00327 QDataStream & operator>>( QDataStream & stream, KMIdentity & i ) {
00328 #if 1 // why doesn't it work like for Q_UINT8 above???
00329 Q_UINT32 uoid;
00330 stream >> uoid;
00331 i.mUoid = uoid;
00332 return stream
00333 #else
00334 return stream >> (Q_UINT32)i.mUoid
00335 #endif
00336 >> i.mIdentity
00337 >> i.mFullName
00338 >> i.mOrganization
00339 >> i.mPgpIdentity
00340 >> i.mEmailAddr
00341 >> i.mReplyToAddr
00342 >> i.mBcc
00343 >> i.mVCardFile
00344 >> i.mTransport
00345 >> i.mFcc
00346 >> i.mDrafts
00347 >> i.mSignature
00348 >> i.mDictionary;
00349 }
00350
00351
00352 bool KMIdentity::mailingAllowed() const
00353 {
00354 return !mEmailAddr.isEmpty();
00355 }
00356
00357
00358 void KMIdentity::setIsDefault( bool flag ) {
00359 mIsDefault = flag;
00360 }
00361
00362 void KMIdentity::setIdentityName( const QString & name ) {
00363 mIdentity = name;
00364 }
00365
00366 void KMIdentity::setFullName(const QString &str)
00367 {
00368 mFullName = str;
00369 }
00370
00371
00372
00373 void KMIdentity::setOrganization(const QString &str)
00374 {
00375 mOrganization = str;
00376 }
00377
00378
00379
00380 void KMIdentity::setPgpIdentity(const QCString &str)
00381 {
00382 mPgpIdentity = str;
00383 }
00384
00385
00386
00387 void KMIdentity::setEmailAddr(const QString &str)
00388 {
00389 mEmailAddr = str;
00390 }
00391
00392
00393
00394 void KMIdentity::setVCardFile(const QString &str)
00395 {
00396 mVCardFile = str;
00397 }
00398
00399
00400
00401 QString KMIdentity::fullEmailAddr(void) const
00402 {
00403 if (mFullName.isEmpty()) return mEmailAddr;
00404
00405 const QString specials("()<>@,.;:[]");
00406
00407 QString result;
00408
00409
00410 bool needsQuotes=false;
00411 for (unsigned int i=0; i < mFullName.length(); i++) {
00412 if ( specials.contains( mFullName[i] ) )
00413 needsQuotes = true;
00414 else if ( mFullName[i] == '\\' || mFullName[i] == '"' ) {
00415 needsQuotes = true;
00416 result += '\\';
00417 }
00418 result += mFullName[i];
00419 }
00420
00421 if (needsQuotes) {
00422 result.insert(0,'"');
00423 result += '"';
00424 }
00425
00426 result += " <" + mEmailAddr + '>';
00427
00428 return result;
00429 }
00430
00431
00432 void KMIdentity::setReplyToAddr(const QString& str)
00433 {
00434 mReplyToAddr = str;
00435 }
00436
00437
00438
00439 void KMIdentity::setSignatureFile(const QString &str)
00440 {
00441 mSignature.setUrl( str, signatureIsCommand() );
00442 }
00443
00444
00445
00446 void KMIdentity::setSignatureInlineText(const QString &str )
00447 {
00448 mSignature.setText( str );
00449 }
00450
00451
00452
00453 void KMIdentity::setTransport(const QString &str)
00454 {
00455 mTransport = str;
00456 }
00457
00458
00459 void KMIdentity::setFcc(const QString &str)
00460 {
00461 mFcc = str;
00462 }
00463
00464
00465 void KMIdentity::setDrafts(const QString &str)
00466 {
00467 mDrafts = str;
00468 }
00469
00470
00471
00472 void KMIdentity::setDictionary( const QString &str )
00473 {
00474 mDictionary = str;
00475 }
00476
00477
00478
00479 QString KMIdentity::signatureText( bool * ok ) const
00480 {
00481 bool internalOK = false;
00482 QString signatureText = mSignature.withSeparator( &internalOK );
00483 if ( internalOK ) {
00484 if ( ok ) *ok=true;
00485 return signatureText;
00486 }
00487
00488
00489
00490
00491 if ( ok ) *ok = false;
00492 return QString::null;
00493
00494 #if 0 // ### FIXME: error handling
00495 if (mSignatureFile.endsWith("|"))
00496 {
00497 }
00498 else
00499 {
00500 }
00501 #endif
00502
00503 return QString::null;
00504 }