libkpgp

kpgp.cpp
00001 /*  -*- mode: C++; c-file-style: "gnu" -*-
00002     kpgp.cpp
00003 
00004     Copyright (C) 2001,2002 the KPGP authors
00005     See file AUTHORS.kpgp for details
00006 
00007     This file is part of KPGP, the KDE PGP/GnuPG support library.
00008 
00009     KPGP is free software; you can redistribute it and/or modify
00010     it under the terms of the GNU General Public License as published by
00011     the Free Software Foundation; either version 2 of the License, or
00012     (at your option) any later version.
00013 
00014     You should have received a copy of the GNU General Public License
00015     along with this program; if not, write to the Free Software Foundation,
00016     Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
00017  */
00018 
00019 #include <stdio.h>
00020 #include <time.h>
00021 #include <stdlib.h>
00022 #include <assert.h>
00023 #include <stdarg.h>
00024 #include <fcntl.h>
00025 #include <unistd.h>
00026 #include <string.h>
00027 #include <sys/socket.h>
00028 #include <sys/types.h>
00029 #include <sys/stat.h>
00030 #include <sys/wait.h>
00031 #include <signal.h>
00032 
00033 #include <tqlabel.h>
00034 #include <tqcursor.h>
00035 #include <tqapplication.h>
00036 
00037 #include <kdebug.h>
00038 #include <tdelocale.h>
00039 #include <tdemessagebox.h>
00040 #include <tdeconfigbase.h>
00041 #include <tdeconfig.h>
00042 #include <kstaticdeleter.h>
00043 
00044 #include "kpgpbase.h"
00045 #include "kpgpui.h"
00046 #include "kpgp.h"
00047 
00048 namespace Kpgp {
00049 
00050 Module *Module::kpgpObject = 0L;
00051 static KStaticDeleter<Module> kpgpod;
00052 
00053 Module::Module()
00054   : mPublicKeys(),
00055     mPublicKeysCached(false),
00056     mSecretKeys(),
00057     mSecretKeysCached(false),
00058     passphrase(TQString::null), havePassPhrase(false)
00059 {
00060   if (!kpgpObject) {
00061     kdDebug(5100) << "creating new pgp object" << endl;
00062   }
00063   kpgpObject=kpgpod.setObject(Module::kpgpObject, this);
00064   pgp = 0;
00065 
00066   config = new TDEConfig("kpgprc");
00067 
00068   init();
00069 }
00070 
00071 Module::~Module()
00072 {
00073   writeAddressData();
00074 
00075   if (kpgpObject == this) kpgpObject = kpgpod.setObject( Module::kpgpObject, 0, false );
00076   clear(TRUE);
00077   delete config;
00078   delete pgp;
00079 }
00080 
00081 // ----------------- public methods -------------------------
00082 
00083 void
00084 Module::init()
00085 {
00086   wipePassPhrase();
00087 
00088   // read kpgp config file entries
00089   readConfig();
00090 
00091   // read the email address -> { encryption keys, encryption preference }
00092   // associations
00093   readAddressData();
00094 
00095   // do we have a pgp executable
00096   checkForPGP();
00097 
00098   // create the Base object later when it is
00099   // needed to avoid the costly check done for
00100   // the autodetection of PGP 2/6
00101   //assignPGPBase();
00102   delete pgp;
00103   pgp=0;
00104 }
00105 
00106 
00107 void
00108 Module::readConfig()
00109 {
00110   storePass = config->readBoolEntry("storePass", false);
00111   showEncryptionResult = config->readBoolEntry("showEncryptionResult", true);
00112   mShowKeyApprovalDlg = config->readBoolEntry( "showKeysForApproval", true );
00113   // We have no config GUI for this key anymore, and the KPGP backend isn't ported,
00114   // so let's just use Auto all the time.  See #92619.
00116   pgpType = tAuto;
00117   flagEncryptToSelf = config->readBoolEntry("encryptToSelf", true);
00118 }
00119 
00120 void
00121 Module::writeConfig(bool sync)
00122 {
00123   config->writeEntry("storePass", storePass);
00124   config->writeEntry("showEncryptionResult", showEncryptionResult);
00125   config->writeEntry( "showKeysForApproval", mShowKeyApprovalDlg );
00126   //config->writeEntry("pgpType", (int) pgpType);
00127   config->writeEntry("encryptToSelf", flagEncryptToSelf);
00128 
00129   if(sync)
00130     config->sync();
00131 
00134   delete pgp;
00135   pgp = 0;
00136 }
00137 
00138 
00139 void
00140 Module::setUser(const KeyID& keyID)
00141 {
00142   if (pgpUser != keyID) {
00143     pgpUser = keyID;
00144     wipePassPhrase();
00145   }
00146 }
00147 
00148 const KeyID
00149 Module::user(void) const
00150 {
00151   return pgpUser;
00152 }
00153 
00154 
00155 void
00156 Module::setEncryptToSelf(bool flag)
00157 {
00158   flagEncryptToSelf = flag;
00159 }
00160 
00161 bool
00162 Module::encryptToSelf(void) const
00163 {
00164   return flagEncryptToSelf;
00165 }
00166 
00167 
00168 void
00169 Module::setStorePassPhrase(bool flag)
00170 {
00171   storePass = flag;
00172 }
00173 
00174 bool
00175 Module::storePassPhrase(void) const
00176 {
00177   return storePass;
00178 }
00179 
00180 int
00181 Module::prepare( bool needPassPhrase, Block* block )
00182 {
00183   if (0 == pgp) assignPGPBase();
00184 
00185   if(!havePgp)
00186   {
00187     errMsg = i18n("Could not find PGP executable.\n"
00188                "Please check your PATH is set correctly.");
00189     return 0;
00190   }
00191 
00192   if( block && ( block->status() & NO_SEC_KEY ) )
00193     return 0;
00194 
00195   if(needPassPhrase && !havePassPhrase) {
00196     if( ( tGPG == pgpType ) && ( 0 != getenv("GPG_AGENT_INFO") ) ) {
00197       // the user uses gpg-agent which asks itself for the passphrase
00198       kdDebug(5100) << "user uses gpg-agent -> don't ask for passphrase\n";
00199       // set dummy passphrase (because else signing doesn't work -> FIXME)
00200       setPassPhrase( "dummy" );
00201     }
00202     else {
00203       TQString ID;
00204       if( block )
00205         ID = block->requiredUserId();
00206       PassphraseDialog passdlg(0, i18n("OpenPGP Security Check"), true, ID);
00207       TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
00208       int passdlgResult = passdlg.exec();
00209       TQApplication::restoreOverrideCursor();
00210       if (passdlgResult == TQDialog::Accepted) {
00211         if (!setPassPhrase(passdlg.passphrase())) {
00212           if (passdlg.passphrase().length() >= 1024)
00213              errMsg = i18n("Passphrase is too long, it must contain fewer than 1024 characters.");
00214           else
00215              errMsg = i18n("Out of memory.");
00216     return 0;
00217         }
00218       } else {
00219         wipePassPhrase();
00220         return -1;
00221       }
00222     }
00223   }
00224   return 1;
00225 }
00226 
00227 void
00228 Module::wipePassPhrase(bool freeMem)
00229 {
00230   if (!passphrase.isEmpty()) {
00231     passphrase.fill(' ');
00232   }
00233   if (freeMem) {
00234     passphrase.truncate(0);
00235   }
00236   havePassPhrase = false;
00237 }
00238 
00239 bool
00240 Module::verify( Block& block )
00241 {
00242   int retval;
00243 
00244   if (0 == pgp) assignPGPBase();
00245 
00246   // everything ready
00247   if( !prepare( false, &block ) )
00248     return false;
00249   // ok now try to verify the message.
00250   retval = pgp->verify( block );
00251 
00252   if(retval & ERROR)
00253   {
00254     errMsg = pgp->lastErrorMessage();
00255     return false;
00256   }
00257   return true;
00258 }
00259 
00260 bool
00261 Module::decrypt( Block& block )
00262 {
00263   int retval;
00264 
00265   if (0 == pgp) assignPGPBase();
00266 
00267   do {
00268     // loop as long as the user enters a wrong passphrase and doesn't abort
00269     // everything ready
00270     if( prepare( true, &block ) != 1 )
00271       return FALSE;
00272     // ok now try to decrypt the message.
00273     retval = pgp->decrypt( block, passphrase );
00274     // loop on bad passphrase
00275     if( retval & BADPHRASE ) {
00276       wipePassPhrase();
00277       TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
00278       int ret = KMessageBox::warningContinueCancel(0,
00279          i18n("You just entered an invalid passphrase.\n"
00280           "Do you want to try again, or "
00281           "cancel and view the message undecrypted?"),
00282          i18n("PGP Warning"), i18n("&Retry"));
00283       TQApplication::restoreOverrideCursor();
00284       if ( ret == KMessageBox::Cancel ) break;
00285     } else
00286       break;
00287   } while ( true );
00288 
00289   // erase the passphrase if we do not want to keep it
00290   cleanupPass();
00291 
00292   if(retval & ERROR)
00293   {
00294     errMsg = pgp->lastErrorMessage();
00295     return false;
00296   }
00297   return true;
00298 }
00299 
00300 Kpgp::Result
00301 Module::clearsign( Block& block,
00302                    const KeyID& keyId, const TQCString& charset )
00303 {
00304   return encrypt( block, TQStringList(), keyId, true, charset );
00305 }
00306 
00307 Kpgp::Result
00308 Module::encrypt( Block& block,
00309                  const TQStringList& receivers, const KeyID& keyId,
00310                  bool sign, const TQCString& charset )
00311 {
00312   KeyIDList encryptionKeyIds; // list of keys which are used for encryption
00313   int status = 0;
00314   errMsg = "";
00315 
00316   if( 0 == pgp ) assignPGPBase();
00317 
00318   setUser( keyId );
00319 
00320   if( !receivers.empty() ) {
00321     Kpgp::Result result = getEncryptionKeys( encryptionKeyIds, receivers,
00322                                              keyId );
00323     if( Kpgp::Ok != result ) {
00324       return result;
00325     }
00326   }
00327 
00328   status = doEncSign( block, encryptionKeyIds, sign );
00329 
00330   if( status & CANCEL )
00331     return Kpgp::Canceled;
00332 
00333   // check for bad passphrase
00334   while( status & BADPHRASE ) {
00335     wipePassPhrase();
00336     TQString str = i18n("You entered an invalid passphrase.\n"
00337                        "Do you want to try again, continue and leave the "
00338                        "message unsigned, or cancel sending the message?");
00339     TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
00340     int ret = KMessageBox::warningYesNoCancel( 0, str,
00341                                                i18n("PGP Warning"),
00342                                                i18n("&Retry"),
00343                                                i18n("Send &Unsigned") );
00344     TQApplication::restoreOverrideCursor();
00345     if( ret == KMessageBox::Cancel ) {
00346       return Kpgp::Canceled;
00347     }
00348     if( ret == KMessageBox::No ) {
00349       // the user selected "Send unsigned"
00350       if( encryptionKeyIds.isEmpty() ) {
00351         block.reset();
00352         return Kpgp::Ok;
00353       }
00354       else {
00355         sign = false;
00356       }
00357     }
00358     // ok let's try once again...
00359     status = doEncSign( block, encryptionKeyIds, sign );
00360   }
00361 
00362   // did signing fail?
00363   if( status & ERR_SIGNING ) {
00364     TQString str = i18n("%1 = 'signing failed' error message",
00365                        "%1\nDo you want to send the message unsigned, "
00366                        "or cancel sending the message?")
00367                   .arg( pgp->lastErrorMessage() );
00368     TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
00369     int ret = KMessageBox::warningContinueCancel( 0, str,
00370                                                   i18n("PGP Warning"),
00371                                                   i18n("Send &Unsigned") );
00372     TQApplication::restoreOverrideCursor();
00373     if( ret == KMessageBox::Cancel ) {
00374       return Kpgp::Canceled;
00375     }
00376     sign = false;
00377     status = doEncSign( block, encryptionKeyIds, sign );
00378   }
00379 
00380   // check for bad keys
00381   if( status & BADKEYS ) {
00382     TQString str = i18n("%1 = 'bad keys' error message",
00383                        "%1\nDo you want to encrypt anyway, leave the "
00384                        "message as-is, or cancel sending the message?")
00385                   .arg( pgp->lastErrorMessage() );
00386 
00387     TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
00388     int ret = KMessageBox::warningYesNoCancel( 0, str,
00389                                                i18n("PGP Warning"),
00390                                                i18n("Send &Encrypted"),
00391                                                i18n("Send &Unencrypted") );
00392     TQApplication::restoreOverrideCursor();
00393     if( ret == KMessageBox::Cancel ) {
00394       return Kpgp::Canceled;
00395     }
00396     if( ret == KMessageBox::No ) {
00397       // the user selected "Send unencrypted"
00398       if( sign ) {
00399         doEncSign( block, KeyIDList(), sign );
00400       }
00401       else {
00402         block.reset();
00403       }
00404       return Kpgp::Ok;
00405     }
00406   }
00407 
00408   if( status & MISSINGKEY ) {
00409     TQString str = i18n("%1 = 'missing keys' error message",
00410                        "%1\nDo you want to leave the message as-is, "
00411                        "or cancel sending the message?")
00412                   .arg( pgp->lastErrorMessage() );
00413     TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
00414     int ret = KMessageBox::warningContinueCancel( 0, str,
00415                                                   i18n("PGP Warning"),
00416                                                   i18n("&Send As-Is") );
00417     TQApplication::restoreOverrideCursor();
00418     if( ret == KMessageBox::Cancel ) {
00419       return Kpgp::Canceled;
00420     }
00421     block.reset();
00422     return Kpgp::Ok;
00423   }
00424 
00425   if( status & ERROR ) {
00426     // show error dialog
00427     errMsg = i18n( "The following error occurred:\n%1" )
00428              .arg( pgp->lastErrorMessage() );
00429     TQString details = i18n( "This is the error message of %1:\n%2" )
00430                       .arg( ( pgpType == tGPG ) ? "GnuPG" : "PGP" )
00431                       .arg( block.error().data() );
00432     TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
00433     KMessageBox::detailedSorry( 0, errMsg, details );
00434     TQApplication::restoreOverrideCursor();
00435     return Kpgp::Failure;
00436   }
00437 
00438   if( showCipherText() ) {
00439     // show cipher text dialog
00440     CipherTextDialog *cipherTextDlg = new CipherTextDialog( block.text(), charset );
00441     TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
00442     bool result = ( cipherTextDlg->exec() == TQDialog::Accepted );
00443     TQApplication::restoreOverrideCursor();
00444     delete cipherTextDlg;
00445     return result == TQDialog::Accepted ? Kpgp::Ok : Kpgp::Canceled;
00446   }
00447   return Kpgp::Ok;
00448 }
00449 
00450 int
00451 Module::doEncSign( Block& block,
00452                    const KeyIDList& recipientKeyIds, bool sign )
00453 {
00454   int retval = 0;
00455 
00456   if( 0 == pgp ) assignPGPBase();
00457 
00458   // to avoid error messages in case pgp is not installed
00459   if( !havePgp ) return OK;
00460 
00461   if( sign ) {
00462     int result = prepare( true, &block );
00463     switch( result ) {
00464       case -1:
00465         return CANCEL;
00466       case 0:
00467         return ERROR;
00468     }
00469     retval = pgp->encsign( block, recipientKeyIds, passphrase );
00470   }
00471   else {
00472     if( !prepare( false, &block ) ) return ERROR;
00473     retval = pgp->encrypt( block, recipientKeyIds );
00474   }
00475   // erase the passphrase if we do not want to keep it
00476   cleanupPass();
00477 
00478   return retval;
00479 }
00480 
00481 Kpgp::Result
00482 Module::getEncryptionKeys( KeyIDList& encryptionKeyIds,
00483                            const TQStringList& recipients,
00484                            const KeyID& keyId )
00485 {
00486   if( recipients.empty() ) {
00487     encryptionKeyIds.clear();
00488     return Kpgp::Ok;
00489   }
00490 
00491   // list of lists of encryption keys (one list per recipient + one list
00492   // for the sender)
00493   TQValueVector<KeyIDList> recipientKeyIds( recipients.count() + 1 );
00494   // add the sender's encryption key(s) to the list of recipient key IDs
00495   if( encryptToSelf() ) {
00496     recipientKeyIds[0] = KeyIDList( keyId );
00497   }
00498   else {
00499     recipientKeyIds[0] = KeyIDList();
00500   }
00501   bool showKeysForApproval = false;
00502   int i = 1;
00503   for( TQStringList::ConstIterator it = recipients.begin();
00504        it != recipients.end(); ++it, ++i ) {
00505     EncryptPref encrPref = encryptionPreference( *it );
00506     if( ( encrPref == UnknownEncryptPref ) || ( encrPref == NeverEncrypt ) )
00507       showKeysForApproval = true;
00508 
00509     KeyIDList keyIds = getEncryptionKeys( *it );
00510     if( keyIds.isEmpty() ) {
00511       showKeysForApproval = true;
00512     }
00513     recipientKeyIds[i] = keyIds;
00514   }
00515 
00516   kdDebug(5100) << "recipientKeyIds = (\n";
00517   TQValueVector<KeyIDList>::const_iterator kit;
00518   for( kit = recipientKeyIds.begin(); kit != recipientKeyIds.end(); ++kit ) {
00519     kdDebug(5100) << "( 0x" << (*kit).toStringList().join( ", 0x" )
00520                   << " ),\n";
00521   }
00522   kdDebug(5100) << ")\n";
00523 
00524   if( showKeysForApproval || mShowKeyApprovalDlg ) {
00525     // #### FIXME: Until we support encryption with untrusted keys only
00526     // ####        trusted keys are allowed
00527     unsigned int allowedKeys = PublicKeys | EncryptionKeys | ValidKeys | TrustedKeys;
00528 #if 0
00529     // ### reenable this code when we support encryption with untrusted keys
00530     if( pgpType != tGPG ) {
00531       // usage of untrusted keys is only possible with GnuPG
00532       allowedKeys |= TrustedKeys;
00533     }
00534 #endif
00535     // show the recipients <-> key relation
00536     KeyApprovalDialog dlg( recipients, recipientKeyIds, allowedKeys );
00537 
00538     TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
00539     int ret = dlg.exec();
00540 
00541     if( ret == TQDialog::Rejected ) {
00542         TQApplication::restoreOverrideCursor();
00543         return Kpgp::Canceled;
00544     }
00545 
00546     recipientKeyIds = dlg.keys();
00547     TQApplication::restoreOverrideCursor();
00548   }
00549 
00550   // flatten the list of lists of key IDs and count empty key ID lists
00551   unsigned int emptyListCount = 0;
00552   for( TQValueVector<KeyIDList>::const_iterator it = recipientKeyIds.begin();
00553        it != recipientKeyIds.end(); ++it ) {
00554     if( (*it).isEmpty() ) {
00555       // only count empty key ID lists for the recipients
00556       if( it != recipientKeyIds.begin() ) {
00557         emptyListCount++;
00558       }
00559     }
00560     else {
00561       for( KeyIDList::ConstIterator kit = (*it).begin();
00562            kit != (*it).end(); kit++ ) {
00563         encryptionKeyIds.append( *kit );
00564       }
00565     }
00566   }
00567 
00568   // FIXME-AFTER-KDE-3.1: Show warning if message won't be encrypted to self
00569 
00570   // show a warning if the user didn't select an encryption key for
00571   // some of the recipients
00572   if( recipientKeyIds.size() == emptyListCount + 1 ) { // (+1 because of the sender's key)
00573     TQString str = ( recipients.count() == 1 )
00574                   ? i18n("You did not select an encryption key for the "
00575                          "recipient of this message; therefore, the message "
00576                          "will not be encrypted.")
00577                   : i18n("You did not select an encryption key for any of the "
00578                          "recipients of this message; therefore, the message "
00579                          "will not be encrypted.");
00580     TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
00581     int ret = KMessageBox::warningContinueCancel( 0, str,
00582                                                   i18n("PGP Warning"),
00583                                                   i18n("Send &Unencrypted") );
00584     TQApplication::restoreOverrideCursor();
00585     if( ret == KMessageBox::Cancel ) {
00586       return Kpgp::Canceled;
00587     }
00588     else
00589       encryptionKeyIds.clear();
00590   }
00591   else if( emptyListCount > 0 ) {
00592     TQString str = ( emptyListCount == 1 )
00593                   ? i18n("You did not select an encryption key for one of "
00594                          "the recipients; this person will not be able to "
00595                          "decrypt the message if you encrypt it.")
00596                   : i18n("You did not select encryption keys for some of "
00597                          "the recipients; these persons will not be able to "
00598                          "decrypt the message if you encrypt it." );
00599     TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
00600     int ret = KMessageBox::warningYesNoCancel( 0, str,
00601                                                i18n("PGP Warning"),
00602                                                i18n("Send &Encrypted"),
00603                                                i18n("Send &Unencrypted") );
00604     TQApplication::restoreOverrideCursor();
00605     if( ret == KMessageBox::Cancel ) {
00606       return Kpgp::Canceled;
00607     }
00608     else if( ret == KMessageBox::No ) {
00609       // the user selected "Send unencrypted"
00610       encryptionKeyIds.clear();
00611     }
00612   }
00613 
00614   return Kpgp::Ok;
00615 }
00616 
00617 int
00618 Module::encryptionPossible( const TQStringList& recipients )
00619 {
00620   if( 0 == pgp ) assignPGPBase();
00621 
00622   if( !usePGP() )
00623     return 0;
00624 
00625   if( recipients.empty() )
00626     return 0;
00627 
00628   int noKey = 0, never = 0, unknown = 0, always = 0, aip = 0, ask = 0,
00629       askwp = 0;
00630   for( TQStringList::ConstIterator it = recipients.begin();
00631        it != recipients.end(); ++it) {
00632     if( haveTrustedEncryptionKey( *it ) ) {
00633       EncryptPref encrPref = encryptionPreference( *it );
00634       switch( encrPref ) {
00635         case NeverEncrypt:
00636           never++;
00637           break;
00638         case UnknownEncryptPref:
00639           unknown++;
00640           break;
00641         case AlwaysEncrypt:
00642           always++;
00643           break;
00644         case AlwaysEncryptIfPossible:
00645           aip++;
00646           break;
00647         case AlwaysAskForEncryption:
00648           ask++;
00649           break;
00650         case AskWheneverPossible:
00651           askwp++;
00652           break;
00653       }
00654     }
00655     else {
00656       noKey++;
00657     }
00658   }
00659 
00660   if( ( always+aip > 0 ) && ( never+unknown+ask+askwp+noKey == 0 ) ) {
00661     return 1; // encryption possible and desired
00662   }
00663 
00664   if( ( unknown+ask+askwp > 0 ) && ( never+noKey == 0 ) ) {
00665     return 2; // encryption possible, but user has to be asked
00666   }
00667 
00668   if( ( never+noKey > 0 ) && ( always+ask == 0 ) ) {
00669     return 0; // encryption isn't possible or desired
00670   }
00671 
00672   return -1; // we can't decide it automatically
00673 }
00674 
00675 bool
00676 Module::signKey(const KeyID& keyId)
00677 {
00678   if (0 == pgp) assignPGPBase();
00679 
00680   if( prepare( true ) != 1 )
00681     return FALSE;
00682   if(pgp->signKey(keyId, passphrase) & ERROR)
00683   {
00684     errMsg = pgp->lastErrorMessage();
00685     return false;
00686   }
00687   return true;
00688 }
00689 
00690 
00691 const KeyList
00692 Module::publicKeys()
00693 {
00694   if (0 == pgp) assignPGPBase();
00695 
00696   if (!prepare()) return KeyList();
00697 
00698   if( !mPublicKeysCached ) {
00699     readPublicKeys();
00700   }
00701 
00702   return mPublicKeys;
00703 }
00704 
00705 
00706 const KeyList
00707 Module::secretKeys()
00708 {
00709   if (0 == pgp) assignPGPBase();
00710 
00711   if (!prepare()) return KeyList();
00712 
00713   if( !mSecretKeysCached ) {
00714     readSecretKeys();
00715   }
00716 
00717   return mSecretKeys;
00718 }
00719 
00720 
00721 Key*
00722 Module::publicKey(const KeyID& keyID)
00723 {
00724   readPublicKeys();
00725 
00726   for( KeyListIterator it( mPublicKeys ); (*it); ++it )
00727     if( keyID == (*it)->primaryKeyID() ||
00728     keyID == (*it)->primaryFingerprint() )
00729       return (*it);
00730 
00731   return 0;
00732 }
00733 
00734 Key*
00735 Module::publicKey( const TQString& userID )
00736 {
00737   readPublicKeys();
00738 
00739   for( KeyListIterator it( mPublicKeys ); (*it); ++it )
00740     if( (*it)->matchesUserID( userID ) )
00741       return (*it);
00742 
00743   return 0;
00744 }
00745 
00746 Key*
00747 Module::secretKey(const KeyID& keyID)
00748 {
00749   readSecretKeys();
00750 
00751   for( KeyListIterator it( mSecretKeys ); (*it); ++it )
00752     if( keyID == (*it)->primaryKeyID() ||
00753     keyID == (*it)->primaryFingerprint() )
00754       return (*it);
00755 
00756   return 0;
00757 }
00758 
00759 Validity
00760 Module::keyTrust( const KeyID& keyID )
00761 {
00762   Key *key = publicKey( keyID );
00763 
00764   if( ( 0 == key ) || ( key->keyTrust() == KPGP_VALIDITY_UNKNOWN ) )
00765   { // (re)check the key if it's unknown or if its trust is unknown
00766     key = rereadKey( keyID, true );
00767     if( key == 0 )
00768       return KPGP_VALIDITY_UNKNOWN;
00769   }
00770 
00771   return key->keyTrust();
00772 }
00773 
00774 Validity
00775 Module::keyTrust( const TQString& userID )
00776 {
00777   Key *key = publicKey( userID );
00778 
00779   if( key == 0 )
00780     return KPGP_VALIDITY_UNKNOWN;
00781 
00782   if( key->keyTrust() == KPGP_VALIDITY_UNKNOWN )
00783   {
00784     key = rereadKey( key->primaryKeyID(), true );
00785     if( key == 0 )
00786       return KPGP_VALIDITY_UNKNOWN;
00787   }
00788 
00789   return key->keyTrust();
00790 }
00791 
00792 bool
00793 Module::isTrusted( const KeyID& keyID )
00794 {
00795   return ( keyTrust( keyID ) >= KPGP_VALIDITY_MARGINAL );
00796 }
00797 
00798 Key*
00799 Module::rereadKey( const KeyID& keyID, const bool readTrust /* = true */ )
00800 {
00801   if( 0 == pgp ) assignPGPBase();
00802 
00803   // search the old key data in the key list
00804   Key* oldKey = publicKey( keyID );
00805 
00806   Key* newKey = pgp->readPublicKey( keyID, readTrust, oldKey );
00807 
00808   if( ( 0 == oldKey ) && ( 0 != newKey ) )
00809   {
00810     mPublicKeys.inSort( newKey );
00811     kdDebug(5100) << "New public key 0x" << newKey->primaryKeyID() << " ("
00812                   << newKey->primaryUserID() << ").\n";
00813   }
00814   else if( ( 0 != oldKey ) && ( 0 == newKey ) )
00815   { // the key has been deleted in the meantime
00816     kdDebug(5100) << "Public key 0x" << oldKey->primaryKeyID() << " ("
00817                   << oldKey->primaryUserID() << ") will be removed.\n";
00818     mPublicKeys.removeRef( oldKey );
00819   }
00820 
00821   return newKey;
00822 }
00823 
00824 TQCString
00825 Module::getAsciiPublicKey(const KeyID& keyID)
00826 {
00827   if (0 == pgp) assignPGPBase();
00828 
00829   return pgp->getAsciiPublicKey(keyID);
00830 }
00831 
00832 
00833 bool Module::setPassPhrase(const TQString &aPass)
00834 {
00835   // null out old buffer before we touch the new string.  So in case
00836   // aPass isn't properly null-terminated, we don't leak secret data.
00837   wipePassPhrase();
00838 
00839   if (!aPass.isEmpty())
00840   {
00841     if (aPass.length() >= 1024) {
00842       // rediculously long passphrase.
00843       // Maybe someone wants to trick us in malloc()'ing
00844       // huge buffers...
00845       return false;
00846     }
00847     passphrase = aPass;
00848     havePassPhrase = true;
00849   }
00850   return true;
00851 }
00852 
00853 bool
00854 Module::changePassPhrase()
00855 {
00856   //FIXME...
00857   KMessageBox::information(0,i18n("This feature is\nstill missing"));
00858   return FALSE;
00859 }
00860 
00861 void
00862 Module::clear(const bool erasePassPhrase)
00863 {
00864   if(erasePassPhrase)
00865     wipePassPhrase(true);
00866 }
00867 
00868 const TQString
00869 Module::lastErrorMsg(void) const
00870 {
00871   return errMsg;
00872 }
00873 
00874 bool
00875 Module::havePGP(void) const
00876 {
00877   return havePgp;
00878 }
00879 
00880 void
00881 Module::setShowCipherText(const bool flag)
00882 {
00883   showEncryptionResult = flag;
00884 }
00885 
00886 bool
00887 Module::showCipherText(void) const
00888 {
00889   return showEncryptionResult;
00890 }
00891 
00892 KeyID
00893 Module::selectSecretKey( const TQString& title,
00894                          const TQString& text,
00895                          const KeyID& keyId )
00896 {
00897   if( 0 == pgp ) {
00898     assignPGPBase();
00899   }
00900 
00901   if( usePGP() ) {
00902     return selectKey( secretKeys(), title, text, keyId, SecretKeys );
00903   }
00904   else {
00905     KMessageBox::sorry( 0, i18n("You either do not have GnuPG/PGP installed "
00906                                 "or you chose not to use GnuPG/PGP.") );
00907     return KeyID();
00908   }
00909 }
00910 
00911 KeyID
00912 Module::selectPublicKey( const TQString& title,
00913                          const TQString& text /* = TQString() */,
00914                          const KeyID& oldKeyId /* = KeyID() */,
00915                          const TQString& address /* = TQString() */,
00916                          const unsigned int allowedKeys /* = AllKeys */ )
00917 {
00918   if( 0 == pgp ) {
00919     assignPGPBase();
00920   }
00921 
00922   if( usePGP() ) {
00923     KeyID keyId;
00924 
00925     if( address.isEmpty() ) {
00926       keyId = selectKey( publicKeys(), title, text, oldKeyId, allowedKeys );
00927     }
00928     else {
00929       bool rememberChoice;
00930       keyId = selectKey( rememberChoice, publicKeys(), title, text, oldKeyId,
00931                          allowedKeys );
00932       if( !keyId.isEmpty() && rememberChoice ) {
00933         setKeysForAddress( address, KeyIDList( keyId ) );
00934       }
00935     }
00936 
00937     return keyId;
00938   }
00939   else {
00940     KMessageBox::sorry( 0, i18n("You either do not have GnuPG/PGP installed "
00941                                 "or you chose not to use GnuPG/PGP.") );
00942     return KeyID();
00943   }
00944 }
00945 
00946 
00947 KeyIDList
00948 Module::selectPublicKeys( const TQString& title,
00949                           const TQString& text /* = TQString() */,
00950                           const KeyIDList& oldKeyIds /* = KeyIDList() */,
00951                           const TQString& address /* = TQString() */,
00952                           const unsigned int allowedKeys /* = AllKeys */ )
00953 {
00954   if( 0 == pgp ) {
00955     assignPGPBase();
00956   }
00957 
00958   if( usePGP() ) {
00959     KeyIDList keyIds;
00960 
00961     if( address.isEmpty() ) {
00962       keyIds = selectKeys( publicKeys(), title, text, oldKeyIds, allowedKeys );
00963     }
00964     else {
00965       bool rememberChoice;
00966       keyIds = selectKeys( rememberChoice, publicKeys(), title, text,
00967                            oldKeyIds, allowedKeys );
00968       if( !keyIds.isEmpty() && rememberChoice ) {
00969         setKeysForAddress( address, keyIds );
00970       }
00971     }
00972 
00973     return keyIds;
00974   }
00975   else {
00976     KMessageBox::sorry( 0, i18n("You either do not have GnuPG/PGP installed "
00977                                 "or you chose not to use GnuPG/PGP.") );
00978     return KeyIDList();
00979   }
00980 }
00981 
00982 
00983 // -- static member functions ----------------------------------------------
00984 
00985 Module *
00986 Module::getKpgp()
00987 {
00988   if (!kpgpObject)
00989   {
00990     kpgpObject = new Module();
00991   }
00992   return kpgpObject;
00993 }
00994 
00995 
00996 TDEConfig *
00997 Module::getConfig()
00998 {
00999   return getKpgp()->config;
01000 }
01001 
01002 
01003 bool
01004 Module::prepareMessageForDecryption( const TQCString& msg,
01005                                      TQPtrList<Block>& pgpBlocks,
01006                                      TQStrList& nonPgpBlocks )
01007 {
01008   BlockType pgpBlock = NoPgpBlock;
01009   int start = -1;   // start of the current PGP block
01010   int lastEnd = -1; // end of the last PGP block
01011 
01012   pgpBlocks.setAutoDelete( true );
01013   pgpBlocks.clear();
01014   nonPgpBlocks.setAutoDelete( true );
01015   nonPgpBlocks.clear();
01016 
01017   if( msg.isEmpty() )
01018   {
01019     nonPgpBlocks.append( "" );
01020     return false;
01021   }
01022 
01023   if( !strncmp( msg.data(), "-----BEGIN PGP ", 15 ) )
01024     start = 0;
01025   else
01026   {
01027     start = msg.find( "\n-----BEGIN PGP" ) + 1;
01028     if( start == 0 )
01029     {
01030       nonPgpBlocks.append( msg );
01031       return false; // message doesn't contain an OpenPGP block
01032     }
01033   }
01034 
01035   while( start != -1 )
01036   {
01037     int nextEnd, nextStart;
01038 
01039     // is the PGP block a clearsigned block?
01040     if( !strncmp( msg.data() + start + 15, "SIGNED", 6 ) )
01041       pgpBlock = ClearsignedBlock;
01042     else
01043       pgpBlock = UnknownBlock;
01044 
01045     nextEnd = msg.find( "\n-----END PGP", start + 15 );
01046     if( nextEnd == -1 )
01047     {
01048       nonPgpBlocks.append( msg.mid( lastEnd+1 ) );
01049       break;
01050     }
01051     nextStart = msg.find( "\n-----BEGIN PGP", start + 15 );
01052 
01053     if( ( nextStart == -1 ) || ( nextEnd < nextStart ) ||
01054         ( pgpBlock == ClearsignedBlock ) )
01055     { // most likely we found a PGP block (but we don't check if it's valid)
01056       // store the preceding non-PGP block
01057       nonPgpBlocks.append( msg.mid( lastEnd+1, start-lastEnd-1 ) );
01058       lastEnd = msg.find( "\n", nextEnd + 14 );
01059       if( lastEnd == -1 )
01060       {
01061         pgpBlocks.append( new Block( msg.mid( start ) ) );
01062         nonPgpBlocks.append( "" );
01063         break;
01064       }
01065       else
01066       {
01067         pgpBlocks.append( new Block( msg.mid( start, lastEnd+1-start ) ) );
01068         if( ( nextStart != -1 ) && ( nextEnd > nextStart ) )
01069           nextStart = msg.find( "\n-----BEGIN PGP", lastEnd+1 );
01070       }
01071     }
01072 
01073     start = nextStart;
01074     if( start == -1 )
01075       nonPgpBlocks.append( msg.mid( lastEnd+1 ) );
01076     else
01077       start++; // move start behind the '\n'
01078   }
01079 
01080   return ( !pgpBlocks.isEmpty() );
01081 }
01082 
01083 
01084 // --------------------- private functions -------------------
01085 
01086 bool
01087 Module::haveTrustedEncryptionKey( const TQString& person )
01088 {
01089   if( 0 == pgp ) assignPGPBase();
01090 
01091   if( !usePGP() ) return false;
01092 
01093   readPublicKeys();
01094 
01095   TQString address = canonicalAddress( person ).lower();
01096 
01097   // First look for this person's address in the address data dictionary
01098   KeyIDList keyIds = keysForAddress( address );
01099   if( !keyIds.isEmpty() ) {
01100     // Check if at least one of the keys is a trusted and valid encryption key
01101     for( KeyIDList::ConstIterator it = keyIds.begin();
01102          it != keyIds.end(); ++it ) {
01103       keyTrust( *it ); // this is called to make sure that the trust info
01104                        // for this key is read
01105       Key *key = publicKey( *it );
01106       if( key && ( key->isValidEncryptionKey() ) &&
01107           ( key->keyTrust() >= KPGP_VALIDITY_MARGINAL ) )
01108         return true;
01109     }
01110   }
01111 
01112   // Now search the public keys for matching keys
01113   KeyListIterator it( mPublicKeys );
01114 
01115   // search a key which matches the complete address
01116   for( it.toFirst(); (*it); ++it ) {
01117     // search case insensitively in the list of userIDs of this key
01118     if( (*it)->matchesUserID( person, false ) ) {
01119       keyTrust( (*it)->primaryKeyID() ); // this is called to make sure that
01120                                          // the trust info for this key is read
01121       if( ( (*it)->isValidEncryptionKey() ) &&
01122           ( (*it)->keyTrust() >= KPGP_VALIDITY_MARGINAL ) ) {
01123         return true;
01124       }
01125     }
01126   }
01127 
01128   // if no key matches the complete address look for a key which matches
01129   // the canonical mail address
01130   for( it.toFirst(); (*it); ++it ) {
01131     // search case insensitively in the list of userIDs of this key
01132     if( (*it)->matchesUserID( address, false ) ) {
01133       keyTrust( (*it)->primaryKeyID() ); // this is called to make sure that
01134                                          // the trust info for this key is read
01135       if( ( (*it)->isValidEncryptionKey() ) &&
01136           ( (*it)->keyTrust() >= KPGP_VALIDITY_MARGINAL ) ) {
01137         return true;
01138       }
01139     }
01140   }
01141 
01142   // no trusted encryption key was found for the given person
01143   return false;
01144 }
01145 
01146 KeyIDList
01147 Module::getEncryptionKeys( const TQString& person )
01148 {
01149   if( 0 == pgp ) assignPGPBase();
01150 
01151   if( !usePGP() ) return KeyIDList();
01152 
01153   readPublicKeys();
01154 
01155   TQString address = canonicalAddress( person ).lower();
01156 
01157   // #### FIXME: Until we support encryption with untrusted keys only
01158   // ####        trusted keys are allowed
01159   unsigned int allowedKeys = PublicKeys | EncryptionKeys | ValidKeys | TrustedKeys;
01160 #if 0
01161   // ### reenable this code when we support encryption with untrusted keys
01162   if( pgpType != tGPG ) {
01163     // usage of untrusted keys is only possible with GnuPG
01164     allowedKeys |= TrustedKeys;
01165   }
01166 #endif
01167 
01168   // First look for this person's address in the address->key dictionary
01169   KeyIDList keyIds = keysForAddress( address );
01170   if( !keyIds.isEmpty() ) {
01171     kdDebug(5100) << "Using encryption keys 0x"
01172                   << keyIds.toStringList().join( ", 0x" )
01173                   << " for " << person << endl;
01174     // Check if all of the keys are a trusted and valid encryption keys
01175     bool keysOk = true;
01176     for( KeyIDList::ConstIterator it = keyIds.begin();
01177          it != keyIds.end(); ++it ) {
01178       keyTrust( *it ); // this is called to make sure that the trust info
01179                        // for this key is read
01180       Key *key = publicKey( *it );
01181       if( !( key && ( key->isValidEncryptionKey() ) &&
01182              ( key->keyTrust() >= KPGP_VALIDITY_MARGINAL ) ) )
01183         keysOk = false;
01184     }
01185     if( keysOk ) {
01186       return keyIds;
01187     }
01188     else {
01189       bool rememberChoice;
01190       keyIds = selectKeys( rememberChoice, mPublicKeys,
01191                            i18n("Encryption Key Selection"),
01192                            i18n("if in your language something like "
01193                                 "'key(s)' isn't possible please "
01194                                 "use the plural in the translation",
01195                                 "There is a problem with the "
01196                                 "encryption key(s) for \"%1\".\n\n"
01197                                 "Please re-select the key(s) which should "
01198                                 "be used for this recipient."
01199                                 ).arg(person),
01200                            keyIds,
01201                            allowedKeys );
01202       if( !keyIds.isEmpty() ) {
01203         if( rememberChoice ) {
01204           setKeysForAddress( person, keyIds );
01205         }
01206         return keyIds;
01207       }
01208     }
01209   }
01210 
01211   // Now search all public keys for matching keys
01212   KeyListIterator it( mPublicKeys );
01213   KeyList matchingKeys;
01214 
01215   // search all keys which match the complete address
01216   kdDebug(5100) << "Looking for keys matching " << person << " ...\n";
01217   for( it.toFirst(); (*it); ++it ) {
01218     // search case insensitively in the list of userIDs of this key
01219     if( (*it)->matchesUserID( person, false ) ) {
01220       keyTrust( (*it)->primaryKeyID() ); // this is called to make sure that
01221                                          // the trust info for this key is read
01222       if( ( (*it)->isValidEncryptionKey() ) &&
01223           ( (*it)->keyTrust() >= KPGP_VALIDITY_MARGINAL ) ) {
01224         kdDebug(5100) << "Matching trusted key found: "
01225                       << (*it)->primaryKeyID() << endl;
01226         matchingKeys.append( *it );
01227       }
01228     }
01229   }
01230 
01231   // if no keys match the complete address look for keys which match
01232   // the canonical mail address
01233   kdDebug(5100) << "Looking for keys matching " << address << " ...\n";
01234   if( matchingKeys.isEmpty() ) {
01235     for ( it.toFirst(); (*it); ++it ) {
01236       // search case insensitively in the list of userIDs of this key
01237       if( (*it)->matchesUserID( address, false ) ) {
01238         keyTrust( (*it)->primaryKeyID() ); // this is called to make sure that
01239                                            // the trust info for this key is read
01240         if( ( (*it)->isValidEncryptionKey() ) &&
01241             ( (*it)->keyTrust() >= KPGP_VALIDITY_MARGINAL ) ) {
01242           kdDebug(5100) << "Matching trusted key found: "
01243                         << (*it)->primaryKeyID() << endl;
01244           matchingKeys.append( *it );
01245         }
01246       }
01247     }
01248   }
01249 
01250   // no match until now, let the user choose the key
01251   if( matchingKeys.isEmpty() ) {
01252     // FIXME: let user get the key from keyserver
01253     bool rememberChoice;
01254     KeyIDList keyIds = selectKeys( rememberChoice, mPublicKeys,
01255                                    i18n("Encryption Key Selection"),
01256                                    i18n("if in your language something like "
01257                                         "'key(s)' isn't possible please "
01258                                         "use the plural in the translation",
01259                                         "No valid and trusted OpenPGP key was "
01260                                         "found for \"%1\".\n\n"
01261                                         "Select the key(s) which should "
01262                                         "be used for this recipient."
01263                                         ).arg(person),
01264                                    KeyIDList(),
01265                                    allowedKeys );
01266     if( !keyIds.isEmpty() ) {
01267       if( rememberChoice ) {
01268         setKeysForAddress( person, keyIds );
01269       }
01270       return keyIds;
01271     }
01272   }
01273   // only one key matches
01274   else if( matchingKeys.count() == 1 ) {
01275     return KeyIDList( matchingKeys.getFirst()->primaryKeyID() );
01276   }
01277   // more than one key matches; let the user choose the key(s)
01278   else {
01279     bool rememberChoice;
01280     KeyIDList keyIds = selectKeys( rememberChoice, matchingKeys,
01281                                    i18n("Encryption Key Selection"),
01282                                    i18n("if in your language something like "
01283                                         "'key(s)' isn't possible please "
01284                                         "use the plural in the translation",
01285                                         "More than one key matches \"%1\".\n\n"
01286                                         "Select the key(s) which should "
01287                                         "be used for this recipient."
01288                                         ).arg(person),
01289                                    KeyIDList(),
01290                                    allowedKeys );
01291     if( !keyIds.isEmpty() ) {
01292       if( rememberChoice ) {
01293         setKeysForAddress( person, keyIds );
01294       }
01295       return keyIds;
01296     }
01297   }
01298 
01299   return KeyIDList();
01300 }
01301 
01302 // check if pgp 2.6.x or 5.0 is installed
01303 // kpgp will prefer to user pgp 5.0
01304 bool
01305 Module::checkForPGP(void)
01306 {
01307   // get path
01308   TQCString path;
01309   TQStrList pSearchPaths;
01310   int index = 0;
01311   int lastindex = -1;
01312 
01313   havePgp=FALSE;
01314 
01315   path = getenv("PATH");
01316   while((index = path.find(":",lastindex+1)) != -1)
01317   {
01318     pSearchPaths.append(path.mid(lastindex+1,index-lastindex-1));
01319     lastindex = index;
01320   }
01321   if(lastindex != (int)path.length() - 1)
01322     pSearchPaths.append( path.mid(lastindex+1,path.length()-lastindex) );
01323 
01324   TQStrListIterator it(pSearchPaths);
01325 
01326   haveGpg=FALSE;
01327   // lets try gpg
01328 
01329   for ( it.toFirst() ; it.current() ; ++it )
01330   {
01331     path = (*it);
01332     path += "/gpg";
01333     if ( !access( path, X_OK ) )
01334     {
01335       kdDebug(5100) << "Kpgp: gpg found" << endl;
01336       havePgp=TRUE;
01337       haveGpg=TRUE;
01338       break;
01339     }
01340   }
01341 
01342   // search for pgp5.0
01343   havePGP5=FALSE;
01344   for ( it.toFirst() ; it.current() ; ++it )
01345   {
01346     path = (*it);
01347     path += "/pgpe";
01348     if ( !access( path, X_OK ) )
01349     {
01350       kdDebug(5100) << "Kpgp: pgp 5 found" << endl;
01351       havePgp=TRUE;
01352       havePGP5=TRUE;
01353       break;
01354     }
01355   }
01356 
01357   // lets try pgp2.6.x
01358   if (!havePgp) {
01359     for ( it.toFirst() ; it.current() ; ++it )
01360     {
01361       path = it.current();
01362       path += "/pgp";
01363       if ( !access( path, X_OK ) )
01364       {
01365     kdDebug(5100) << "Kpgp: pgp 2 or 6 found" << endl;
01366     havePgp=TRUE;
01367     break;
01368       }
01369     }
01370   }
01371 
01372   if (!havePgp)
01373   {
01374     kdDebug(5100) << "Kpgp: no pgp found" << endl;
01375   }
01376 
01377   return havePgp;
01378 }
01379 
01380 void
01381 Module::assignPGPBase(void)
01382 {
01383   if (pgp)
01384     delete pgp;
01385 
01386   if(havePgp)
01387   {
01388     switch (pgpType)
01389     {
01390       case tGPG:
01391         kdDebug(5100) << "Kpgp: assign pgp - gpg" << endl;
01392         pgp = new BaseG();
01393         break;
01394 
01395       case tPGP2:
01396         kdDebug(5100) << "Kpgp: assign pgp - pgp 2" << endl;
01397         pgp = new Base2();
01398         break;
01399 
01400       case tPGP5:
01401         kdDebug(5100) << "Kpgp: assign pgp - pgp 5" << endl;
01402         pgp = new Base5();
01403         break;
01404 
01405       case tPGP6:
01406         kdDebug(5100) << "Kpgp: assign pgp - pgp 6" << endl;
01407         pgp = new Base6();
01408         break;
01409 
01410       case tOff:
01411         // dummy handler
01412         kdDebug(5100) << "Kpgp: pgpBase is dummy " << endl;
01413         pgp = new Base();
01414         break;
01415 
01416       case tAuto:
01417         kdDebug(5100) << "Kpgp: assign pgp - auto" << endl;
01418         // fall through
01419       default:
01420         kdDebug(5100) << "Kpgp: assign pgp - default" << endl;
01421         if (haveGpg)
01422         {
01423           kdDebug(5100) << "Kpgp: pgpBase is gpg " << endl;
01424           pgp = new BaseG();
01425           pgpType = tGPG;
01426         }
01427         else if(havePGP5)
01428         {
01429           kdDebug(5100) << "Kpgp: pgpBase is pgp 5" << endl;
01430           pgp = new Base5();
01431           pgpType = tPGP5;
01432         }
01433         else
01434         {
01435           Base6 *pgp_v6 = new Base6();
01436           if (!pgp_v6->isVersion6())
01437           {
01438             kdDebug(5100) << "Kpgp: pgpBase is pgp 2 " << endl;
01439             delete pgp_v6;
01440             pgp = new Base2();
01441             pgpType = tPGP2;
01442           }
01443           else
01444           {
01445             kdDebug(5100) << "Kpgp: pgpBase is pgp 6 " << endl;
01446             pgp = pgp_v6;
01447             pgpType = tPGP6;
01448           }
01449         }
01450     } // switch
01451   }
01452   else
01453   {
01454     // dummy handler
01455     kdDebug(5100) << "Kpgp: pgpBase is dummy " << endl;
01456     pgp = new Base();
01457     pgpType = tOff;
01458   }
01459 }
01460 
01461 TQString
01462 Module::canonicalAddress( const TQString& _adress )
01463 {
01464   int index,index2;
01465 
01466   TQString address = _adress.simplifyWhiteSpace();
01467   address = address.stripWhiteSpace();
01468 
01469   // just leave pure e-mail address.
01470   if((index = address.find("<")) != -1)
01471     if((index2 = address.find("@",index+1)) != -1)
01472       if((index2 = address.find(">",index2+1)) != -1)
01473     return address.mid(index,index2-index+1);
01474 
01475   if((index = address.find("@")) == -1)
01476   {
01477     // local address
01478     //char hostname[1024];
01479     //gethostname(hostname,1024);
01480     //return "<" + address + "@" + hostname + ">";
01481     return "<" + address + "@localdomain>";
01482   }
01483   else
01484   {
01485     int index1 = address.findRev(" ",index);
01486     int index2 = address.find(" ",index);
01487     if(index2 == -1) index2 = address.length();
01488     return "<" + address.mid(index1+1 ,index2-index1-1) + ">";
01489   }
01490 }
01491 
01492 void
01493 Module::readPublicKeys( bool reread )
01494 {
01495   if( 0 == pgp ) assignPGPBase();
01496 
01497   if( !usePGP() )
01498   {
01499     mPublicKeys.clear();
01500     mPublicKeysCached = false;
01501     return;
01502   }
01503 
01504   if( !mPublicKeysCached || reread )
01505   {
01506     if( mPublicKeys.isEmpty() )
01507     {
01508       mPublicKeys = pgp->publicKeys();
01509     }
01510     else
01511     {
01512       KeyList newPublicKeyList = pgp->publicKeys();
01513 
01514       // merge the trust info from the old key list into the new key list
01515       // FIXME: This is currently O(K^2) where K = #keys. As the key lists
01516       //        are sorted this can be done in O(K).
01517       KeyListIterator it( newPublicKeyList );
01518       for( it.toFirst(); (*it); ++it )
01519       {
01520         Key* oldKey = publicKey( (*it)->primaryKeyID() );
01521         if( oldKey )
01522         {
01523           (*it)->cloneKeyTrust( oldKey );
01524         }
01525       }
01526 
01527       mPublicKeys = newPublicKeyList;
01528     }
01529 
01530     mPublicKeysCached = true;
01531     mPublicKeys.setAutoDelete( true );
01532   }
01533 }
01534 
01535 void
01536 Module::readSecretKeys( bool reread )
01537 {
01538   if( 0 == pgp ) assignPGPBase();
01539 
01540   if( !usePGP() )
01541   {
01542     mSecretKeys.clear();
01543     mSecretKeysCached = false;
01544     return;
01545   }
01546 
01547   if( mSecretKeys.isEmpty() || reread )
01548   {
01549     if( mSecretKeys.isEmpty() )
01550     {
01551       mSecretKeys = pgp->secretKeys();
01552     }
01553     else
01554     {
01555       KeyList newSecretKeyList = pgp->secretKeys();
01556 
01557       // merge the trust info from the old key list into the new key list
01558       // FIXME: This is currently O(K^2) where K = #keys. As the key lists
01559       //        are sorted this can be done in O(K).
01560       KeyListIterator it( newSecretKeyList );
01561       for( it.toFirst(); (*it); ++it )
01562       {
01563         Key* oldKey = secretKey( (*it)->primaryKeyID() );
01564         if( oldKey )
01565         {
01566           (*it)->cloneKeyTrust( oldKey );
01567         }
01568       }
01569 
01570       mSecretKeys = newSecretKeyList;
01571     }
01572 
01573     mSecretKeysCached = true;
01574     mSecretKeys.setAutoDelete( true );
01575   }
01576 }
01577 
01578 KeyID
01579 Module::selectKey( const KeyList& keys,
01580                    const TQString& title,
01581                    const TQString& text /* = TQString() */ ,
01582                    const KeyID& keyId /* = KeyID() */ ,
01583                    const unsigned int allowedKeys /* = AllKeys */ )
01584 {
01585   KeyID retval = KeyID();
01586 
01587   KeySelectionDialog dlg( keys, title, text, KeyIDList( keyId ), false,
01588                           allowedKeys, false );
01589 
01590   TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
01591   bool rej = ( dlg.exec() == TQDialog::Rejected );
01592   TQApplication::restoreOverrideCursor();
01593 
01594   if( !rej ) {
01595     retval = dlg.key();
01596   }
01597 
01598   return retval;
01599 }
01600 
01601 KeyIDList
01602 Module::selectKeys( const KeyList& keys,
01603                     const TQString& title,
01604                     const TQString& text /* = TQString() */ ,
01605                     const KeyIDList& keyIds /* = KeyIDList() */ ,
01606                     const unsigned int allowedKeys /* = AllKeys */ )
01607 {
01608   KeyIDList retval = KeyIDList();
01609 
01610   KeySelectionDialog dlg( keys, title, text, keyIds, false, allowedKeys,
01611                           true );
01612 
01613   TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
01614   bool rej = ( dlg.exec() == TQDialog::Rejected );
01615   TQApplication::restoreOverrideCursor();
01616 
01617   if( !rej ) {
01618     retval = dlg.keys();
01619   }
01620 
01621   return retval;
01622 }
01623 
01624 
01625 KeyID
01626 Module::selectKey( bool& rememberChoice,
01627                    const KeyList& keys,
01628                    const TQString& title,
01629                    const TQString& text /* = TQString() */ ,
01630                    const KeyID& keyId /* = KeyID() */ ,
01631                    const unsigned int allowedKeys /* = AllKeys */ )
01632 {
01633   KeyID retval = KeyID();
01634 
01635   KeySelectionDialog dlg( keys, title, text, KeyIDList( keyId ), false,
01636                           allowedKeys, false );
01637 
01638   TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
01639   bool rej = ( dlg.exec() == TQDialog::Rejected );
01640   TQApplication::restoreOverrideCursor();
01641 
01642   if( !rej ) {
01643     retval = dlg.key();
01644     rememberChoice = dlg.rememberSelection();
01645   }
01646   else {
01647     rememberChoice = false;
01648   }
01649 
01650   return retval;
01651 }
01652 
01653 KeyIDList
01654 Module::selectKeys( bool& rememberChoice,
01655                     const KeyList& keys,
01656                     const TQString& title,
01657                     const TQString& text /* = TQString() */ ,
01658                     const KeyIDList& keyIds /* = KeyIDList() */ ,
01659                     const unsigned int allowedKeys /* = AllKeys */ )
01660 {
01661   KeyIDList retval = KeyIDList();
01662 
01663   KeySelectionDialog dlg( keys, title, text, keyIds, true, allowedKeys,
01664                           true );
01665 
01666   TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
01667   bool rej = ( dlg.exec() == TQDialog::Rejected );
01668   TQApplication::restoreOverrideCursor();
01669 
01670   if( !rej ) {
01671     retval = dlg.keys();
01672     rememberChoice = dlg.rememberSelection();
01673   }
01674   else {
01675     rememberChoice = false;
01676   }
01677 
01678   return retval;
01679 }
01680 
01681 KeyIDList
01682 Module::keysForAddress( const TQString& address )
01683 {
01684   if( address.isEmpty() ) {
01685     return KeyIDList();
01686   }
01687   TQString addr = canonicalAddress( address ).lower();
01688   if( addressDataDict.contains( addr ) ) {
01689     return addressDataDict[addr].keyIds;
01690   }
01691   else {
01692     return KeyIDList();
01693   }
01694 }
01695 
01696 void
01697 Module::setKeysForAddress( const TQString& address, const KeyIDList& keyIds )
01698 {
01699   if( address.isEmpty() ) {
01700     return;
01701   }
01702   TQString addr = canonicalAddress( address ).lower();
01703   if( addressDataDict.contains( addr ) ) {
01704     addressDataDict[addr].keyIds = keyIds;
01705   }
01706   else {
01707     AddressData data;
01708     data.encrPref = UnknownEncryptPref;
01709     data.keyIds = keyIds;
01710     addressDataDict.insert( addr, data );
01711   }
01712 
01713   //writeAddressData();
01714 }
01715 
01716 void
01717 Module::readAddressData()
01718 {
01719   TQString address;
01720   AddressData data;
01721 
01722   TDEConfigGroup general( config, "General" );
01723   int num = general.readNumEntry( "addressEntries", 0 );
01724 
01725   addressDataDict.clear();
01726   for( int i=1; i<=num; i++ ) {
01727     TDEConfigGroup addrGroup( config, TQString("Address #%1").arg(i).local8Bit() );
01728     address = addrGroup.readEntry( "Address" );
01729     data.keyIds = KeyIDList::fromStringList( addrGroup.readListEntry( "Key IDs" ) );
01730     data.encrPref = (EncryptPref) addrGroup.readNumEntry( "EncryptionPreference",
01731                                                           UnknownEncryptPref );
01732 //     kdDebug(5100) << "Read address " << i << ": " << address
01733 //                   << "\nKey IDs: 0x" << data.keyIds.toStringList().join(", 0x")
01734 //                   << "\nEncryption preference: " << data.encrPref << endl;
01735     if ( !address.isEmpty() ) {
01736       addressDataDict.insert( address, data );
01737     }
01738   }
01739 }
01740 
01741 void
01742 Module::writeAddressData()
01743 {
01744   TDEConfigGroup general( config, "General" );
01745   general.writeEntry( "addressEntries", addressDataDict.count() );
01746 
01747   int i;
01748   AddressDataDict::Iterator it;
01749   for ( i=1, it = addressDataDict.begin();
01750         it != addressDataDict.end();
01751         ++it, i++ ) {
01752     TDEConfigGroup addrGroup( config, TQString("Address #%1").arg(i).local8Bit() );
01753     addrGroup.writeEntry( "Address", it.key() );
01754     addrGroup.writeEntry( "Key IDs", it.data().keyIds.toStringList() );
01755     addrGroup.writeEntry( "EncryptionPreference", it.data().encrPref );
01756   }
01757 
01758   config->sync();
01759 }
01760 
01761 EncryptPref
01762 Module::encryptionPreference( const TQString& address )
01763 {
01764   TQString addr = canonicalAddress( address ).lower();
01765   if( addressDataDict.contains( addr ) ) {
01766     return addressDataDict[addr].encrPref;
01767   }
01768   else {
01769     return UnknownEncryptPref;
01770   }
01771 }
01772 
01773 void
01774 Module::setEncryptionPreference( const TQString& address,
01775                                  const EncryptPref pref )
01776 {
01777   if( address.isEmpty() ) {
01778     return;
01779   }
01780   TQString addr = canonicalAddress( address ).lower();
01781   if( addressDataDict.contains( addr ) ) {
01782     addressDataDict[addr].encrPref = pref;
01783   }
01784   else {
01785     AddressData data;
01786     data.encrPref = pref;
01787     addressDataDict.insert( addr, data );
01788   }
01789 }
01790 
01791 } // namespace Kpgp