libkpimidentities

identity.cpp

00001 // -*- mode: C++; c-file-style: "gnu" -*-
00002 // kmidentity.cpp
00003 // License: GPL
00004 
00005 #ifdef HAVE_CONFIG_H
00006 #include <config.h>
00007 #endif
00008 
00009 #include "identity.h"
00010 
00011 #include <libkdepim/kfileio.h>
00012 #include <libkdepim/collectingprocess.h>
00013 
00014 #include <kdebug.h>
00015 #include <klocale.h>
00016 #include <kmessagebox.h>
00017 #include <kconfig.h>
00018 #include <kurl.h>
00019 
00020 #include <qfileinfo.h>
00021 
00022 #include <sys/types.h>
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <errno.h>
00026 #include <assert.h>
00027 
00028 using namespace KPIM;
00029 
00030 
00031 Signature::Signature()
00032   : mType( Disabled )
00033 {
00034 
00035 }
00036 
00037 Signature::Signature( const QString & text )
00038   : mText( text ),
00039     mType( Inlined )
00040 {
00041 
00042 }
00043 
00044 Signature::Signature( const QString & url, bool isExecutable )
00045   : mUrl( url ),
00046     mType( isExecutable ? FromCommand : FromFile )
00047 {
00048 }
00049 
00050 bool Signature::operator==( const Signature & other ) const {
00051   if ( mType != other.mType ) return false;
00052   switch ( mType ) {
00053   case Inlined: return mText == other.mText;
00054   case FromFile:
00055   case FromCommand: return mUrl == other.mUrl;
00056   default:
00057   case Disabled: return true;
00058   }
00059 }
00060 
00061 QString Signature::rawText( bool * ok ) const
00062 {
00063   switch ( mType ) {
00064   case Disabled:
00065     if ( ok ) *ok = true;
00066     return QString::null;
00067   case Inlined:
00068     if ( ok ) *ok = true;
00069     return mText;
00070   case FromFile:
00071     return textFromFile( ok );
00072   case FromCommand:
00073     return textFromCommand( ok );
00074   };
00075   kdFatal( 5006 ) << "Signature::type() returned unknown value!" << endl;
00076   return QString::null; // make compiler happy
00077 }
00078 
00079 QString Signature::textFromCommand( bool * ok ) const
00080 {
00081   assert( mType == FromCommand );
00082 
00083   // handle pathological cases:
00084   if ( mUrl.isEmpty() ) {
00085     if ( ok ) *ok = true;
00086     return QString::null;
00087   }
00088 
00089   // create a shell process:
00090   CollectingProcess proc;
00091   proc.setUseShell(true);
00092   proc << mUrl;
00093 
00094   // run the process:
00095   int rc = 0;
00096   if ( !proc.start( KProcess::Block, KProcess::Stdout ) )
00097     rc = -1;
00098   else
00099     rc = ( proc.normalExit() ) ? proc.exitStatus() : -1 ;
00100 
00101   // handle errors, if any:
00102   if ( rc != 0 ) {
00103     if ( ok ) *ok = false;
00104     QString wmsg = i18n("<qt>Failed to execute signature script<br><b>%1</b>:<br>%2</qt>")
00105       .arg( mUrl ).arg( strerror(rc) );
00106     KMessageBox::error(0, wmsg);
00107     return QString::null;
00108   }
00109 
00110   // no errors:
00111   if ( ok ) *ok = true;
00112 
00113   // get output:
00114   QByteArray output = proc.collectedStdout();
00115 
00116   // ### hmm, should we allow other encodings, too?
00117   return QString::fromLocal8Bit( output.data(), output.size() );
00118 }
00119 
00120 QString Signature::textFromFile( bool * ok ) const
00121 {
00122   assert( mType == FromFile );
00123 
00124   // ### FIXME: Use KIO::NetAccess to download non-local files!
00125   if ( !KURL(mUrl).isLocalFile() && !(QFileInfo(mUrl).isRelative()
00126                                       && QFileInfo(mUrl).exists()) ) {
00127     kdDebug( 5006 ) << "Signature::textFromFile: non-local URLs are unsupported" << endl;
00128     if ( ok ) *ok = false;
00129     return QString::null;
00130   }
00131   if ( ok ) *ok = true;
00132   // ### hmm, should we allow other encodings, too?
00133   return QString::fromLocal8Bit( kFileToString( mUrl, false ) );
00134 }
00135 
00136 QString Signature::withSeparator( bool * ok ) const
00137 {
00138   bool internalOK = false;
00139   QString signature = rawText( &internalOK );
00140   if ( !internalOK ) {
00141     if ( ok ) *ok = false;
00142     return QString::null;
00143   }
00144   if ( ok ) *ok = true;
00145   if ( signature.isEmpty() ) return signature; // don't add a separator in this case
00146   if ( signature.startsWith( QString::fromLatin1("-- \n") ) )
00147     // already have signature separator at start of sig:
00148     return QString::fromLatin1("\n") += signature;
00149   else if ( signature.find( QString::fromLatin1("\n-- \n") ) != -1 )
00150     // already have signature separator inside sig; don't prepend '\n'
00151     // to improve abusing signatures as templates:
00152     return signature;
00153   else
00154     // need to prepend one:
00155     return QString::fromLatin1("\n-- \n") + signature;
00156 }
00157 
00158 
00159 void Signature::setUrl( const QString & url, bool isExecutable )
00160 {
00161   mUrl = url;
00162   mType = isExecutable ? FromCommand : FromFile ;
00163 }
00164 
00165 // config keys and values:
00166 static const char sigTypeKey[] = "Signature Type";
00167 static const char sigTypeInlineValue[] = "inline";
00168 static const char sigTypeFileValue[] = "file";
00169 static const char sigTypeCommandValue[] = "command";
00170 static const char sigTypeDisabledValue[] = "disabled";
00171 static const char sigTextKey[] = "Inline Signature";
00172 static const char sigFileKey[] = "Signature File";
00173 static const char sigCommandKey[] = "Signature Command";
00174 
00175 void Signature::readConfig( const KConfigBase * config )
00176 {
00177   QString sigType = config->readEntry( sigTypeKey );
00178   if ( sigType == sigTypeInlineValue ) {
00179     mType = Inlined;
00180     mText = config->readEntry( sigTextKey );
00181   } else if ( sigType == sigTypeFileValue ) {
00182     mType = FromFile;
00183     mUrl = config->readPathEntry( sigFileKey );
00184   } else if ( sigType == sigTypeCommandValue ) {
00185     mType = FromCommand;
00186     mUrl = config->readPathEntry( sigCommandKey );
00187   } else {
00188     mType = Disabled;
00189   }
00190 }
00191 
00192 void Signature::writeConfig( KConfigBase * config ) const
00193 {
00194   switch ( mType ) {
00195   case Inlined:
00196     config->writeEntry( sigTypeKey, sigTypeInlineValue );
00197     config->writeEntry( sigTextKey, mText );
00198     break;
00199   case FromFile:
00200     config->writeEntry( sigTypeKey, sigTypeFileValue );
00201     config->writePathEntry( sigFileKey, mUrl );
00202     break;
00203   case FromCommand:
00204     config->writeEntry( sigTypeKey, sigTypeCommandValue );
00205     config->writePathEntry( sigCommandKey, mUrl );
00206     break;
00207   case Disabled:
00208     config->writeEntry( sigTypeKey, sigTypeDisabledValue );
00209   default: ;
00210   }
00211 }
00212 
00213 QDataStream & KPIM::operator<<( QDataStream & stream, const KPIM::Signature & sig ) {
00214   return stream << static_cast<Q_UINT8>(sig.mType)
00215         << sig.mUrl
00216         << sig.mText;
00217 }
00218 
00219 QDataStream & KPIM::operator>>( QDataStream & stream, KPIM::Signature & sig ) {
00220     Q_UINT8 s;
00221     stream >> s
00222            >> sig.mUrl
00223            >> sig.mText;
00224     sig.mType = static_cast<Signature::Type>(s);
00225     return stream;
00226 }
00227 
00228 // ### should use a kstaticdeleter?
00229 static Identity* identityNull = 0;
00230 const Identity& Identity::null()
00231 {
00232     if ( !identityNull )
00233         identityNull = new Identity;
00234     return *identityNull;
00235 }
00236 
00237 bool Identity::isNull() const {
00238   return mIdentity.isEmpty() && mFullName.isEmpty() && mEmailAddr.isEmpty() &&
00239     mOrganization.isEmpty() && mReplyToAddr.isEmpty() && mBcc.isEmpty() &&
00240     mVCardFile.isEmpty() &&
00241     mFcc.isEmpty() && mDrafts.isEmpty() &&
00242     mPGPEncryptionKey.isEmpty() && mPGPSigningKey.isEmpty() &&
00243     mSMIMEEncryptionKey.isEmpty() && mSMIMESigningKey.isEmpty() &&
00244     mTransport.isEmpty() && mDictionary.isEmpty() &&
00245     mPreferredCryptoMessageFormat == Kleo::AutoFormat &&
00246     mSignature.type() == Signature::Disabled &&
00247     mXFace.isEmpty();
00248 }
00249 
00250 bool Identity::operator==( const Identity & other ) const {
00251   bool same = mUoid == other.mUoid &&
00252       mIdentity == other.mIdentity && mFullName == other.mFullName &&
00253       mEmailAddr == other.mEmailAddr && mOrganization == other.mOrganization &&
00254       mReplyToAddr == other.mReplyToAddr && mBcc == other.mBcc &&
00255       mVCardFile == other.mVCardFile &&
00256       mFcc == other.mFcc &&
00257       mPGPEncryptionKey == other.mPGPEncryptionKey &&
00258       mPGPSigningKey == other.mPGPSigningKey &&
00259       mSMIMEEncryptionKey == other.mSMIMEEncryptionKey &&
00260       mSMIMESigningKey == other.mSMIMESigningKey &&
00261       mPreferredCryptoMessageFormat == other.mPreferredCryptoMessageFormat &&
00262       mDrafts == other.mDrafts && mTransport == other.mTransport &&
00263       mDictionary == other.mDictionary && mSignature == other.mSignature &&
00264       mXFace == other.mXFace && mXFaceEnabled == other.mXFaceEnabled;
00265 
00266 #if 0
00267   if ( same )
00268     return true;
00269   if ( mUoid != other.mUoid ) kdDebug() << "mUoid differs : " << mUoid << " != " << other.mUoid << endl;
00270   if ( mIdentity != other.mIdentity ) kdDebug() << "mIdentity differs : " << mIdentity << " != " << other.mIdentity << endl;
00271   if ( mFullName != other.mFullName ) kdDebug() << "mFullName differs : " << mFullName << " != " << other.mFullName << endl;
00272   if ( mEmailAddr != other.mEmailAddr ) kdDebug() << "mEmailAddr differs : " << mEmailAddr << " != " << other.mEmailAddr << endl;
00273   if ( mOrganization != other.mOrganization ) kdDebug() << "mOrganization differs : " << mOrganization << " != " << other.mOrganization << endl;
00274   if ( mReplyToAddr != other.mReplyToAddr ) kdDebug() << "mReplyToAddr differs : " << mReplyToAddr << " != " << other.mReplyToAddr << endl;
00275   if ( mBcc != other.mBcc ) kdDebug() << "mBcc differs : " << mBcc << " != " << other.mBcc << endl;
00276   if ( mVCardFile != other.mVCardFile ) kdDebug() << "mVCardFile differs : " << mVCardFile << " != " << other.mVCardFile << endl;
00277   if ( mFcc != other.mFcc ) kdDebug() << "mFcc differs : " << mFcc << " != " << other.mFcc << endl;
00278   if ( mPGPEncryptionKey != other.mPGPEncryptionKey ) kdDebug() << "mPGPEncryptionKey differs : " << mPGPEncryptionKey << " != " << other.mPGPEncryptionKey << endl;
00279   if ( mPGPSigningKey != other.mPGPSigningKey ) kdDebug() << "mPGPSigningKey differs : " << mPGPSigningKey << " != " << other.mPGPSigningKey << endl;
00280   if ( mSMIMEEncryptionKey != other.mSMIMEEncryptionKey ) kdDebug() << "mSMIMEEncryptionKey differs : '" << mSMIMEEncryptionKey << "' != '" << other.mSMIMEEncryptionKey << "'" << endl;
00281   if ( mSMIMESigningKey != other.mSMIMESigningKey ) kdDebug() << "mSMIMESigningKey differs : " << mSMIMESigningKey << " != " << other.mSMIMESigningKey << endl;
00282   if ( mPreferredCryptoMessageFormat != other.mPreferredCryptoMessageFormat ) kdDebug() << "mPreferredCryptoMessageFormat differs : " << mPreferredCryptoMessageFormat << " != " << other.mPreferredCryptoMessageFormat << endl;
00283   if ( mDrafts != other.mDrafts ) kdDebug() << "mDrafts differs : " << mDrafts << " != " << other.mDrafts << endl;
00284   if ( mTransport != other.mTransport ) kdDebug() << "mTransport differs : " << mTransport << " != " << other.mTransport << endl;
00285   if ( mDictionary != other.mDictionary ) kdDebug() << "mDictionary differs : " << mDictionary << " != " << other.mDictionary << endl;
00286   if ( ! ( mSignature == other.mSignature ) ) kdDebug() << "mSignature differs" << endl;
00287 #endif
00288   return same;
00289 }
00290 
00291 Identity::Identity( const QString & id, const QString & fullName,
00292             const QString & emailAddr, const QString & organization,
00293             const QString & replyToAddr )
00294   : mUoid( 0 ), mIdentity( id ), mFullName( fullName ),
00295     mEmailAddr( emailAddr ), mOrganization( organization ),
00296     mReplyToAddr( replyToAddr ),
00297     // Using "" instead of null to make operator==() not fail
00298     // (readConfig returns "")
00299     mBcc( "" ), mVCardFile( "" ), mPGPEncryptionKey( "" ), mPGPSigningKey( "" ),
00300     mSMIMEEncryptionKey( "" ), mSMIMESigningKey( "" ), mFcc( "" ), mDrafts( "" ), mTransport( "" ),
00301     mDictionary( "" ),
00302     mXFace( "" ), mXFaceEnabled( false ),
00303     mIsDefault( false ),
00304     mPreferredCryptoMessageFormat( Kleo::AutoFormat )
00305 {
00306 }
00307 
00308 Identity::~Identity()
00309 {
00310 }
00311 
00312 
00313 void Identity::readConfig( const KConfigBase * config )
00314 {
00315   mUoid = config->readUnsignedNumEntry("uoid",0);
00316 
00317   mIdentity = config->readEntry("Identity");
00318   mFullName = config->readEntry("Name");
00319   mEmailAddr = config->readEntry("Email Address");
00320   mVCardFile = config->readPathEntry("VCardFile");
00321   mOrganization = config->readEntry("Organization");
00322   mPGPSigningKey = config->readEntry("PGP Signing Key").latin1();
00323   mPGPEncryptionKey = config->readEntry("PGP Encryption Key").latin1();
00324   mSMIMESigningKey = config->readEntry("SMIME Signing Key").latin1();
00325   mSMIMEEncryptionKey = config->readEntry("SMIME Encryption Key").latin1();
00326   mPreferredCryptoMessageFormat = Kleo::stringToCryptoMessageFormat( config->readEntry("Preferred Crypto Message Format", "none" ) );
00327   mReplyToAddr = config->readEntry("Reply-To Address");
00328   mBcc = config->readEntry("Bcc");
00329   mFcc = config->readEntry("Fcc", "sent-mail");
00330   if( mFcc.isEmpty() )
00331     mFcc = "sent-mail";
00332   mDrafts = config->readEntry("Drafts", "drafts");
00333   if( mDrafts.isEmpty() )
00334     mDrafts = "drafts";
00335   mTransport = config->readEntry("Transport");
00336   mDictionary = config->readEntry( "Dictionary" );
00337   mXFace = config->readEntry( "X-Face" );
00338   mXFaceEnabled = config->readBoolEntry( "X-FaceEnabled", false );
00339 
00340   mSignature.readConfig( config );
00341   kdDebug(5006) << "Identity::readConfig(): UOID = " << mUoid
00342         << " for identity named \"" << mIdentity << "\"" << endl;
00343 }
00344 
00345 
00346 void Identity::writeConfig( KConfigBase * config ) const
00347 {
00348   config->writeEntry("uoid", mUoid);
00349 
00350   config->writeEntry("Identity", mIdentity);
00351   config->writeEntry("Name", mFullName);
00352   config->writeEntry("Organization", mOrganization);
00353   config->writeEntry("PGP Signing Key", mPGPSigningKey.data());
00354   config->writeEntry("PGP Encryption Key", mPGPEncryptionKey.data());
00355   config->writeEntry("SMIME Signing Key", mSMIMESigningKey.data());
00356   config->writeEntry("SMIME Encryption Key", mSMIMEEncryptionKey.data());
00357   config->writeEntry("Preferred Crypto Message Format", Kleo::cryptoMessageFormatToString( mPreferredCryptoMessageFormat ) );
00358   config->writeEntry("Email Address", mEmailAddr);
00359   config->writeEntry("Reply-To Address", mReplyToAddr);
00360   config->writeEntry("Bcc", mBcc);
00361   config->writePathEntry("VCardFile", mVCardFile);
00362   config->writeEntry("Transport", mTransport);
00363   config->writeEntry("Fcc", mFcc);
00364   config->writeEntry("Drafts", mDrafts);
00365   config->writeEntry( "Dictionary", mDictionary );
00366   config->writeEntry( "X-Face", mXFace );
00367   config->writeEntry( "X-FaceEnabled", mXFaceEnabled );
00368 
00369   mSignature.writeConfig( config );
00370 }
00371 
00372 QDataStream & KPIM::operator<<( QDataStream & stream, const KPIM::Identity & i ) {
00373   return stream << static_cast<Q_UINT32>(i.uoid())
00374         << i.identityName()
00375         << i.fullName()
00376         << i.organization()
00377         << i.pgpSigningKey()
00378         << i.pgpEncryptionKey()
00379         << i.smimeSigningKey()
00380         << i.smimeEncryptionKey()
00381         << i.emailAddr()
00382         << i.replyToAddr()
00383         << i.bcc()
00384         << i.vCardFile()
00385         << i.transport()
00386         << i.fcc()
00387         << i.drafts()
00388         << i.mSignature
00389                 << i.dictionary()
00390                 << i.xface()
00391         << QString( Kleo::cryptoMessageFormatToString( i.mPreferredCryptoMessageFormat ) );
00392 }
00393 
00394 QDataStream & KPIM::operator>>( QDataStream & stream, KPIM::Identity & i ) {
00395   Q_UINT32 uoid;
00396   QString format;
00397   stream        >> uoid
00398         >> i.mIdentity
00399         >> i.mFullName
00400         >> i.mOrganization
00401         >> i.mPGPSigningKey
00402         >> i.mPGPEncryptionKey
00403         >> i.mSMIMESigningKey
00404         >> i.mSMIMEEncryptionKey
00405         >> i.mEmailAddr
00406         >> i.mReplyToAddr
00407         >> i.mBcc
00408         >> i.mVCardFile
00409         >> i.mTransport
00410         >> i.mFcc
00411         >> i.mDrafts
00412         >> i.mSignature
00413                 >> i.mDictionary
00414                 >> i.mXFace
00415         >> format;
00416   i.mUoid = uoid;
00417   i.mPreferredCryptoMessageFormat = Kleo::stringToCryptoMessageFormat( format.latin1() );
00418 
00419   return stream;
00420 }
00421 
00422 //-----------------------------------------------------------------------------
00423 bool Identity::mailingAllowed() const
00424 {
00425   return !mEmailAddr.isEmpty();
00426 }
00427 
00428 
00429 void Identity::setIsDefault( bool flag ) {
00430   mIsDefault = flag;
00431 }
00432 
00433 void Identity::setIdentityName( const QString & name ) {
00434   mIdentity = name;
00435 }
00436 
00437 void Identity::setFullName(const QString &str)
00438 {
00439   mFullName = str;
00440 }
00441 
00442 
00443 //-----------------------------------------------------------------------------
00444 void Identity::setOrganization(const QString &str)
00445 {
00446   mOrganization = str;
00447 }
00448 
00449 void Identity::setPGPSigningKey(const QCString &str)
00450 {
00451   mPGPSigningKey = str;
00452   if ( mPGPSigningKey.isNull() )
00453     mPGPSigningKey = "";
00454 }
00455 
00456 void Identity::setPGPEncryptionKey(const QCString &str)
00457 {
00458   mPGPEncryptionKey = str;
00459   if ( mPGPEncryptionKey.isNull() )
00460     mPGPEncryptionKey = "";
00461 }
00462 
00463 void Identity::setSMIMESigningKey(const QCString &str)
00464 {
00465   mSMIMESigningKey = str;
00466   if ( mSMIMESigningKey.isNull() )
00467     mSMIMESigningKey = "";
00468 }
00469 
00470 void Identity::setSMIMEEncryptionKey(const QCString &str)
00471 {
00472   mSMIMEEncryptionKey = str;
00473   if ( mSMIMEEncryptionKey.isNull() )
00474     mSMIMEEncryptionKey = "";
00475 }
00476 
00477 //-----------------------------------------------------------------------------
00478 void Identity::setEmailAddr(const QString &str)
00479 {
00480   mEmailAddr = str;
00481 }
00482 
00483 
00484 //-----------------------------------------------------------------------------
00485 void Identity::setVCardFile(const QString &str)
00486 {
00487   mVCardFile = str;
00488 }
00489 
00490 
00491 //-----------------------------------------------------------------------------
00492 QString Identity::fullEmailAddr(void) const
00493 {
00494   if (mFullName.isEmpty()) return mEmailAddr;
00495 
00496   const QString specials("()<>@,.;:[]");
00497 
00498   QString result;
00499 
00500   // add DQUOTE's if necessary:
00501   bool needsQuotes=false;
00502   for (unsigned int i=0; i < mFullName.length(); i++) {
00503     if ( specials.contains( mFullName[i] ) )
00504       needsQuotes = true;
00505     else if ( mFullName[i] == '\\' || mFullName[i] == '"' ) {
00506       needsQuotes = true;
00507       result += '\\';
00508     }
00509     result += mFullName[i];
00510   }
00511 
00512   if (needsQuotes) {
00513     result.insert(0,'"');
00514     result += '"';
00515   }
00516 
00517   result += " <" + mEmailAddr + '>';
00518 
00519   return result;
00520 }
00521 
00522 //-----------------------------------------------------------------------------
00523 void Identity::setReplyToAddr(const QString& str)
00524 {
00525   mReplyToAddr = str;
00526 }
00527 
00528 
00529 //-----------------------------------------------------------------------------
00530 void Identity::setSignatureFile(const QString &str)
00531 {
00532   mSignature.setUrl( str, signatureIsCommand() );
00533 }
00534 
00535 
00536 //-----------------------------------------------------------------------------
00537 void Identity::setSignatureInlineText(const QString &str )
00538 {
00539   mSignature.setText( str );
00540 }
00541 
00542 
00543 //-----------------------------------------------------------------------------
00544 void Identity::setTransport(const QString &str)
00545 {
00546   mTransport = str;
00547   if ( mTransport.isNull() )
00548     mTransport = "";
00549 }
00550 
00551 //-----------------------------------------------------------------------------
00552 void Identity::setFcc(const QString &str)
00553 {
00554   mFcc = str;
00555   if ( mFcc.isNull() )
00556     mFcc = "";
00557 }
00558 
00559 //-----------------------------------------------------------------------------
00560 void Identity::setDrafts(const QString &str)
00561 {
00562   mDrafts = str;
00563   if ( mDrafts.isNull() )
00564     mDrafts = "";
00565 }
00566 
00567 
00568 //-----------------------------------------------------------------------------
00569 void Identity::setDictionary( const QString &str )
00570 {
00571   mDictionary = str;
00572   if ( mDictionary.isNull() )
00573     mDictionary = "";
00574 }
00575 
00576 
00577 //-----------------------------------------------------------------------------
00578 void Identity::setXFace( const QString &str )
00579 {
00580   mXFace = str;
00581   mXFace.remove( " " );
00582   mXFace.remove( "\n" );
00583   mXFace.remove( "\r" );
00584 }
00585 
00586 
00587 //-----------------------------------------------------------------------------
00588 void Identity::setXFaceEnabled( const bool on )
00589 {
00590   mXFaceEnabled = on;
00591 }
00592 
00593 
00594 //-----------------------------------------------------------------------------
00595 QString Identity::signatureText( bool * ok ) const
00596 {
00597   bool internalOK = false;
00598   QString signatureText = mSignature.withSeparator( &internalOK );
00599   if ( internalOK ) {
00600     if ( ok ) *ok=true;
00601     return signatureText;
00602   }
00603 
00604   // OK, here comes the funny part. The call to
00605   // Signature::withSeparator() failed, so we should probably fix the
00606   // cause:
00607   if ( ok ) *ok = false;
00608   return QString::null;
00609 
00610 #if 0 // ### FIXME: error handling
00611   if (mSignatureFile.endsWith("|"))
00612   {
00613   }
00614   else
00615   {
00616   }
00617 #endif
00618 
00619   return QString::null;
00620 }
KDE Home | KDE Accessibility Home | Description of Access Keys