libkpgp

kpgp.cpp
1 /*
2  kpgp.cpp
3 
4  Copyright (C) 2001,2002 the KPGP authors
5  See file AUTHORS.kpgp for details
6 
7  This file is part of KPGP, the KDE PGP/GnuPG support library.
8 
9  KPGP is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software Foundation,
16  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include <stdio.h>
20 #include <time.h>
21 #include <stdlib.h>
22 #include <assert.h>
23 #include <stdarg.h>
24 #include <fcntl.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <sys/socket.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <sys/wait.h>
31 #include <signal.h>
32 
33 #include <tqlabel.h>
34 #include <tqcursor.h>
35 #include <tqapplication.h>
36 
37 #include <kdebug.h>
38 #include <tdelocale.h>
39 #include <tdemessagebox.h>
40 #include <tdeconfigbase.h>
41 #include <tdeconfig.h>
42 #include <kstaticdeleter.h>
43 
44 #include "kpgpbase.h"
45 #include "kpgpui.h"
46 #include "kpgp.h"
47 
48 namespace Kpgp {
49 
50 Module *Module::kpgpObject = 0L;
51 static KStaticDeleter<Module> kpgpod;
52 
53 Module::Module()
54  : mPublicKeys(),
55  mPublicKeysCached(false),
56  mSecretKeys(),
57  mSecretKeysCached(false),
58  passphrase(TQString::null), havePassPhrase(false)
59 {
60  if (!kpgpObject) {
61  kdDebug(5100) << "creating new pgp object" << endl;
62  }
63  kpgpObject=kpgpod.setObject(Module::kpgpObject, this);
64  pgp = 0;
65 
66  config = new TDEConfig("kpgprc");
67 
68  init();
69 }
70 
71 Module::~Module()
72 {
73  writeAddressData();
74 
75  if (kpgpObject == this) kpgpObject = kpgpod.setObject( Module::kpgpObject, 0, false );
76  clear(TRUE);
77  delete config;
78  delete pgp;
79 }
80 
81 // ----------------- public methods -------------------------
82 
83 void
84 Module::init()
85 {
86  wipePassPhrase();
87 
88  // read kpgp config file entries
89  readConfig();
90 
91  // read the email address -> { encryption keys, encryption preference }
92  // associations
93  readAddressData();
94 
95  // do we have a pgp executable
96  checkForPGP();
97 
98  // create the Base object later when it is
99  // needed to avoid the costly check done for
100  // the autodetection of PGP 2/6
101  //assignPGPBase();
102  delete pgp;
103  pgp=0;
104 }
105 
106 
107 void
108 Module::readConfig()
109 {
110  storePass = config->readBoolEntry("storePass", false);
111  showEncryptionResult = config->readBoolEntry("showEncryptionResult", true);
112  mShowKeyApprovalDlg = config->readBoolEntry( "showKeysForApproval", true );
113  // We have no config GUI for this key anymore, and the KPGP backend isn't ported,
114  // so let's just use Auto all the time. See #92619.
116  pgpType = tAuto;
117  flagEncryptToSelf = config->readBoolEntry("encryptToSelf", true);
118 }
119 
120 void
121 Module::writeConfig(bool sync)
122 {
123  config->writeEntry("storePass", storePass);
124  config->writeEntry("showEncryptionResult", showEncryptionResult);
125  config->writeEntry( "showKeysForApproval", mShowKeyApprovalDlg );
126  //config->writeEntry("pgpType", (int) pgpType);
127  config->writeEntry("encryptToSelf", flagEncryptToSelf);
128 
129  if(sync)
130  config->sync();
131 
134  delete pgp;
135  pgp = 0;
136 }
137 
138 
139 void
140 Module::setUser(const KeyID& keyID)
141 {
142  if (pgpUser != keyID) {
143  pgpUser = keyID;
144  wipePassPhrase();
145  }
146 }
147 
148 const KeyID
149 Module::user(void) const
150 {
151  return pgpUser;
152 }
153 
154 
155 void
156 Module::setEncryptToSelf(bool flag)
157 {
158  flagEncryptToSelf = flag;
159 }
160 
161 bool
162 Module::encryptToSelf(void) const
163 {
164  return flagEncryptToSelf;
165 }
166 
167 
168 void
169 Module::setStorePassPhrase(bool flag)
170 {
171  storePass = flag;
172 }
173 
174 bool
175 Module::storePassPhrase(void) const
176 {
177  return storePass;
178 }
179 
180 int
181 Module::prepare( bool needPassPhrase, Block* block )
182 {
183  if (0 == pgp) assignPGPBase();
184 
185  if(!havePgp)
186  {
187  errMsg = i18n("Could not find PGP executable.\n"
188  "Please check your PATH is set correctly.");
189  return 0;
190  }
191 
192  if( block && ( block->status() & NO_SEC_KEY ) )
193  return 0;
194 
195  if(needPassPhrase && !havePassPhrase) {
196  if( ( tGPG == pgpType ) && ( 0 != getenv("GPG_AGENT_INFO") ) ) {
197  // the user uses gpg-agent which asks itself for the passphrase
198  kdDebug(5100) << "user uses gpg-agent -> don't ask for passphrase\n";
199  // set dummy passphrase (because else signing doesn't work -> FIXME)
200  setPassPhrase( "dummy" );
201  }
202  else {
203  TQString ID;
204  if( block )
205  ID = block->requiredUserId();
206  PassphraseDialog passdlg(0, i18n("OpenPGP Security Check"), true, ID);
207  TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
208  int passdlgResult = passdlg.exec();
209  TQApplication::restoreOverrideCursor();
210  if (passdlgResult == TQDialog::Accepted) {
211  if (!setPassPhrase(passdlg.passphrase())) {
212  if (passdlg.passphrase().length() >= 1024)
213  errMsg = i18n("Passphrase is too long, it must contain fewer than 1024 characters.");
214  else
215  errMsg = i18n("Out of memory.");
216  return 0;
217  }
218  } else {
219  wipePassPhrase();
220  return -1;
221  }
222  }
223  }
224  return 1;
225 }
226 
227 void
228 Module::wipePassPhrase(bool freeMem)
229 {
230  if (!passphrase.isEmpty()) {
231  passphrase.fill(' ');
232  }
233  if (freeMem) {
234  passphrase.truncate(0);
235  }
236  havePassPhrase = false;
237 }
238 
239 bool
240 Module::verify( Block& block )
241 {
242  int retval;
243 
244  if (0 == pgp) assignPGPBase();
245 
246  // everything ready
247  if( !prepare( false, &block ) )
248  return false;
249  // ok now try to verify the message.
250  retval = pgp->verify( block );
251 
252  if(retval & ERROR)
253  {
254  errMsg = pgp->lastErrorMessage();
255  return false;
256  }
257  return true;
258 }
259 
260 bool
261 Module::decrypt( Block& block )
262 {
263  int retval;
264 
265  if (0 == pgp) assignPGPBase();
266 
267  do {
268  // loop as long as the user enters a wrong passphrase and doesn't abort
269  // everything ready
270  if( prepare( true, &block ) != 1 )
271  return FALSE;
272  // ok now try to decrypt the message.
273  retval = pgp->decrypt( block, passphrase );
274  // loop on bad passphrase
275  if( retval & BADPHRASE ) {
276  wipePassPhrase();
277  TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
278  int ret = KMessageBox::warningContinueCancel(0,
279  i18n("You just entered an invalid passphrase.\n"
280  "Do you want to try again, or "
281  "cancel and view the message undecrypted?"),
282  i18n("PGP Warning"), i18n("&Retry"));
283  TQApplication::restoreOverrideCursor();
284  if ( ret == KMessageBox::Cancel ) break;
285  } else
286  break;
287  } while ( true );
288 
289  // erase the passphrase if we do not want to keep it
290  cleanupPass();
291 
292  if(retval & ERROR)
293  {
294  errMsg = pgp->lastErrorMessage();
295  return false;
296  }
297  return true;
298 }
299 
300 Kpgp::Result
301 Module::clearsign( Block& block,
302  const KeyID& keyId, const TQCString& charset )
303 {
304  return encrypt( block, TQStringList(), keyId, true, charset );
305 }
306 
307 Kpgp::Result
308 Module::encrypt( Block& block,
309  const TQStringList& receivers, const KeyID& keyId,
310  bool sign, const TQCString& charset )
311 {
312  KeyIDList encryptionKeyIds; // list of keys which are used for encryption
313  int status = 0;
314  errMsg = "";
315 
316  if( 0 == pgp ) assignPGPBase();
317 
318  setUser( keyId );
319 
320  if( !receivers.empty() ) {
321  Kpgp::Result result = getEncryptionKeys( encryptionKeyIds, receivers,
322  keyId );
323  if( Kpgp::Ok != result ) {
324  return result;
325  }
326  }
327 
328  status = doEncSign( block, encryptionKeyIds, sign );
329 
330  if( status & CANCEL )
331  return Kpgp::Canceled;
332 
333  // check for bad passphrase
334  while( status & BADPHRASE ) {
335  wipePassPhrase();
336  TQString str = i18n("You entered an invalid passphrase.\n"
337  "Do you want to try again, continue and leave the "
338  "message unsigned, or cancel sending the message?");
339  TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
340  int ret = KMessageBox::warningYesNoCancel( 0, str,
341  i18n("PGP Warning"),
342  i18n("&Retry"),
343  i18n("Send &Unsigned") );
344  TQApplication::restoreOverrideCursor();
345  if( ret == KMessageBox::Cancel ) {
346  return Kpgp::Canceled;
347  }
348  if( ret == KMessageBox::No ) {
349  // the user selected "Send unsigned"
350  if( encryptionKeyIds.isEmpty() ) {
351  block.reset();
352  return Kpgp::Ok;
353  }
354  else {
355  sign = false;
356  }
357  }
358  // ok let's try once again...
359  status = doEncSign( block, encryptionKeyIds, sign );
360  }
361 
362  // did signing fail?
363  if( status & ERR_SIGNING ) {
364  TQString str = i18n("%1 = 'signing failed' error message",
365  "%1\nDo you want to send the message unsigned, "
366  "or cancel sending the message?")
367  .arg( pgp->lastErrorMessage() );
368  TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
369  int ret = KMessageBox::warningContinueCancel( 0, str,
370  i18n("PGP Warning"),
371  i18n("Send &Unsigned") );
372  TQApplication::restoreOverrideCursor();
373  if( ret == KMessageBox::Cancel ) {
374  return Kpgp::Canceled;
375  }
376  sign = false;
377  status = doEncSign( block, encryptionKeyIds, sign );
378  }
379 
380  // check for bad keys
381  if( status & BADKEYS ) {
382  TQString str = i18n("%1 = 'bad keys' error message",
383  "%1\nDo you want to encrypt anyway, leave the "
384  "message as-is, or cancel sending the message?")
385  .arg( pgp->lastErrorMessage() );
386 
387  TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
388  int ret = KMessageBox::warningYesNoCancel( 0, str,
389  i18n("PGP Warning"),
390  i18n("Send &Encrypted"),
391  i18n("Send &Unencrypted") );
392  TQApplication::restoreOverrideCursor();
393  if( ret == KMessageBox::Cancel ) {
394  return Kpgp::Canceled;
395  }
396  if( ret == KMessageBox::No ) {
397  // the user selected "Send unencrypted"
398  if( sign ) {
399  doEncSign( block, KeyIDList(), sign );
400  }
401  else {
402  block.reset();
403  }
404  return Kpgp::Ok;
405  }
406  }
407 
408  if( status & MISSINGKEY ) {
409  TQString str = i18n("%1 = 'missing keys' error message",
410  "%1\nDo you want to leave the message as-is, "
411  "or cancel sending the message?")
412  .arg( pgp->lastErrorMessage() );
413  TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
414  int ret = KMessageBox::warningContinueCancel( 0, str,
415  i18n("PGP Warning"),
416  i18n("&Send As-Is") );
417  TQApplication::restoreOverrideCursor();
418  if( ret == KMessageBox::Cancel ) {
419  return Kpgp::Canceled;
420  }
421  block.reset();
422  return Kpgp::Ok;
423  }
424 
425  if( status & ERROR ) {
426  // show error dialog
427  errMsg = i18n( "The following error occurred:\n%1" )
428  .arg( pgp->lastErrorMessage() );
429  TQString details = i18n( "This is the error message of %1:\n%2" )
430  .arg( ( pgpType == tGPG ) ? "GnuPG" : "PGP" )
431  .arg( block.error().data() );
432  TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
433  KMessageBox::detailedSorry( 0, errMsg, details );
434  TQApplication::restoreOverrideCursor();
435  return Kpgp::Failure;
436  }
437 
438  if( showCipherText() ) {
439  // show cipher text dialog
440  CipherTextDialog *cipherTextDlg = new CipherTextDialog( block.text(), charset );
441  TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
442  bool result = ( cipherTextDlg->exec() == TQDialog::Accepted );
443  TQApplication::restoreOverrideCursor();
444  delete cipherTextDlg;
445  return result == TQDialog::Accepted ? Kpgp::Ok : Kpgp::Canceled;
446  }
447  return Kpgp::Ok;
448 }
449 
450 int
451 Module::doEncSign( Block& block,
452  const KeyIDList& recipientKeyIds, bool sign )
453 {
454  int retval = 0;
455 
456  if( 0 == pgp ) assignPGPBase();
457 
458  // to avoid error messages in case pgp is not installed
459  if( !havePgp ) return OK;
460 
461  if( sign ) {
462  int result = prepare( true, &block );
463  switch( result ) {
464  case -1:
465  return CANCEL;
466  case 0:
467  return ERROR;
468  }
469  retval = pgp->encsign( block, recipientKeyIds, passphrase );
470  }
471  else {
472  if( !prepare( false, &block ) ) return ERROR;
473  retval = pgp->encrypt( block, recipientKeyIds );
474  }
475  // erase the passphrase if we do not want to keep it
476  cleanupPass();
477 
478  return retval;
479 }
480 
481 Kpgp::Result
482 Module::getEncryptionKeys( KeyIDList& encryptionKeyIds,
483  const TQStringList& recipients,
484  const KeyID& keyId )
485 {
486  if( recipients.empty() ) {
487  encryptionKeyIds.clear();
488  return Kpgp::Ok;
489  }
490 
491  // list of lists of encryption keys (one list per recipient + one list
492  // for the sender)
493  TQValueVector<KeyIDList> recipientKeyIds( recipients.count() + 1 );
494  // add the sender's encryption key(s) to the list of recipient key IDs
495  if( encryptToSelf() ) {
496  recipientKeyIds[0] = KeyIDList( keyId );
497  }
498  else {
499  recipientKeyIds[0] = KeyIDList();
500  }
501  bool showKeysForApproval = false;
502  int i = 1;
503  for( TQStringList::ConstIterator it = recipients.begin();
504  it != recipients.end(); ++it, ++i ) {
505  EncryptPref encrPref = encryptionPreference( *it );
506  if( ( encrPref == UnknownEncryptPref ) || ( encrPref == NeverEncrypt ) )
507  showKeysForApproval = true;
508 
509  KeyIDList keyIds = getEncryptionKeys( *it );
510  if( keyIds.isEmpty() ) {
511  showKeysForApproval = true;
512  }
513  recipientKeyIds[i] = keyIds;
514  }
515 
516  kdDebug(5100) << "recipientKeyIds = (\n";
517  TQValueVector<KeyIDList>::const_iterator kit;
518  for( kit = recipientKeyIds.begin(); kit != recipientKeyIds.end(); ++kit ) {
519  kdDebug(5100) << "( 0x" << (*kit).toStringList().join( ", 0x" )
520  << " ),\n";
521  }
522  kdDebug(5100) << ")\n";
523 
524  if( showKeysForApproval || mShowKeyApprovalDlg ) {
525  // #### FIXME: Until we support encryption with untrusted keys only
526  // #### trusted keys are allowed
527  unsigned int allowedKeys = PublicKeys | EncryptionKeys | ValidKeys | TrustedKeys;
528 #if 0
529  // ### reenable this code when we support encryption with untrusted keys
530  if( pgpType != tGPG ) {
531  // usage of untrusted keys is only possible with GnuPG
532  allowedKeys |= TrustedKeys;
533  }
534 #endif
535  // show the recipients <-> key relation
536  KeyApprovalDialog dlg( recipients, recipientKeyIds, allowedKeys );
537 
538  TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
539  int ret = dlg.exec();
540 
541  if( ret == TQDialog::Rejected ) {
542  TQApplication::restoreOverrideCursor();
543  return Kpgp::Canceled;
544  }
545 
546  recipientKeyIds = dlg.keys();
547  TQApplication::restoreOverrideCursor();
548  }
549 
550  // flatten the list of lists of key IDs and count empty key ID lists
551  unsigned int emptyListCount = 0;
552  for( TQValueVector<KeyIDList>::const_iterator it = recipientKeyIds.begin();
553  it != recipientKeyIds.end(); ++it ) {
554  if( (*it).isEmpty() ) {
555  // only count empty key ID lists for the recipients
556  if( it != recipientKeyIds.begin() ) {
557  emptyListCount++;
558  }
559  }
560  else {
561  for( KeyIDList::ConstIterator kit = (*it).begin();
562  kit != (*it).end(); kit++ ) {
563  encryptionKeyIds.append( *kit );
564  }
565  }
566  }
567 
568  // FIXME-AFTER-KDE-3.1: Show warning if message won't be encrypted to self
569 
570  // show a warning if the user didn't select an encryption key for
571  // some of the recipients
572  if( recipientKeyIds.size() == emptyListCount + 1 ) { // (+1 because of the sender's key)
573  TQString str = ( recipients.count() == 1 )
574  ? i18n("You did not select an encryption key for the "
575  "recipient of this message; therefore, the message "
576  "will not be encrypted.")
577  : i18n("You did not select an encryption key for any of the "
578  "recipients of this message; therefore, the message "
579  "will not be encrypted.");
580  TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
581  int ret = KMessageBox::warningContinueCancel( 0, str,
582  i18n("PGP Warning"),
583  i18n("Send &Unencrypted") );
584  TQApplication::restoreOverrideCursor();
585  if( ret == KMessageBox::Cancel ) {
586  return Kpgp::Canceled;
587  }
588  else
589  encryptionKeyIds.clear();
590  }
591  else if( emptyListCount > 0 ) {
592  TQString str = ( emptyListCount == 1 )
593  ? i18n("You did not select an encryption key for one of "
594  "the recipients; this person will not be able to "
595  "decrypt the message if you encrypt it.")
596  : i18n("You did not select encryption keys for some of "
597  "the recipients; these persons will not be able to "
598  "decrypt the message if you encrypt it." );
599  TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
600  int ret = KMessageBox::warningYesNoCancel( 0, str,
601  i18n("PGP Warning"),
602  i18n("Send &Encrypted"),
603  i18n("Send &Unencrypted") );
604  TQApplication::restoreOverrideCursor();
605  if( ret == KMessageBox::Cancel ) {
606  return Kpgp::Canceled;
607  }
608  else if( ret == KMessageBox::No ) {
609  // the user selected "Send unencrypted"
610  encryptionKeyIds.clear();
611  }
612  }
613 
614  return Kpgp::Ok;
615 }
616 
617 int
618 Module::encryptionPossible( const TQStringList& recipients )
619 {
620  if( 0 == pgp ) assignPGPBase();
621 
622  if( !usePGP() )
623  return 0;
624 
625  if( recipients.empty() )
626  return 0;
627 
628  int noKey = 0, never = 0, unknown = 0, always = 0, aip = 0, ask = 0,
629  askwp = 0;
630  for( TQStringList::ConstIterator it = recipients.begin();
631  it != recipients.end(); ++it) {
632  if( haveTrustedEncryptionKey( *it ) ) {
633  EncryptPref encrPref = encryptionPreference( *it );
634  switch( encrPref ) {
635  case NeverEncrypt:
636  never++;
637  break;
638  case UnknownEncryptPref:
639  unknown++;
640  break;
641  case AlwaysEncrypt:
642  always++;
643  break;
644  case AlwaysEncryptIfPossible:
645  aip++;
646  break;
647  case AlwaysAskForEncryption:
648  ask++;
649  break;
650  case AskWheneverPossible:
651  askwp++;
652  break;
653  }
654  }
655  else {
656  noKey++;
657  }
658  }
659 
660  if( ( always+aip > 0 ) && ( never+unknown+ask+askwp+noKey == 0 ) ) {
661  return 1; // encryption possible and desired
662  }
663 
664  if( ( unknown+ask+askwp > 0 ) && ( never+noKey == 0 ) ) {
665  return 2; // encryption possible, but user has to be asked
666  }
667 
668  if( ( never+noKey > 0 ) && ( always+ask == 0 ) ) {
669  return 0; // encryption isn't possible or desired
670  }
671 
672  return -1; // we can't decide it automatically
673 }
674 
675 bool
676 Module::signKey(const KeyID& keyId)
677 {
678  if (0 == pgp) assignPGPBase();
679 
680  if( prepare( true ) != 1 )
681  return FALSE;
682  if(pgp->signKey(keyId, passphrase) & ERROR)
683  {
684  errMsg = pgp->lastErrorMessage();
685  return false;
686  }
687  return true;
688 }
689 
690 
691 const KeyList
692 Module::publicKeys()
693 {
694  if (0 == pgp) assignPGPBase();
695 
696  if (!prepare()) return KeyList();
697 
698  if( !mPublicKeysCached ) {
699  readPublicKeys();
700  }
701 
702  return mPublicKeys;
703 }
704 
705 
706 const KeyList
707 Module::secretKeys()
708 {
709  if (0 == pgp) assignPGPBase();
710 
711  if (!prepare()) return KeyList();
712 
713  if( !mSecretKeysCached ) {
714  readSecretKeys();
715  }
716 
717  return mSecretKeys;
718 }
719 
720 
721 Key*
722 Module::publicKey(const KeyID& keyID)
723 {
724  readPublicKeys();
725 
726  for( KeyListIterator it( mPublicKeys ); (*it); ++it )
727  if( keyID == (*it)->primaryKeyID() ||
728  keyID == (*it)->primaryFingerprint() )
729  return (*it);
730 
731  return 0;
732 }
733 
734 Key*
735 Module::publicKey( const TQString& userID )
736 {
737  readPublicKeys();
738 
739  for( KeyListIterator it( mPublicKeys ); (*it); ++it )
740  if( (*it)->matchesUserID( userID ) )
741  return (*it);
742 
743  return 0;
744 }
745 
746 Key*
747 Module::secretKey(const KeyID& keyID)
748 {
749  readSecretKeys();
750 
751  for( KeyListIterator it( mSecretKeys ); (*it); ++it )
752  if( keyID == (*it)->primaryKeyID() ||
753  keyID == (*it)->primaryFingerprint() )
754  return (*it);
755 
756  return 0;
757 }
758 
759 Validity
760 Module::keyTrust( const KeyID& keyID )
761 {
762  Key *key = publicKey( keyID );
763 
764  if( ( 0 == key ) || ( key->keyTrust() == KPGP_VALIDITY_UNKNOWN ) )
765  { // (re)check the key if it's unknown or if its trust is unknown
766  key = rereadKey( keyID, true );
767  if( key == 0 )
768  return KPGP_VALIDITY_UNKNOWN;
769  }
770 
771  return key->keyTrust();
772 }
773 
774 Validity
775 Module::keyTrust( const TQString& userID )
776 {
777  Key *key = publicKey( userID );
778 
779  if( key == 0 )
780  return KPGP_VALIDITY_UNKNOWN;
781 
782  if( key->keyTrust() == KPGP_VALIDITY_UNKNOWN )
783  {
784  key = rereadKey( key->primaryKeyID(), true );
785  if( key == 0 )
786  return KPGP_VALIDITY_UNKNOWN;
787  }
788 
789  return key->keyTrust();
790 }
791 
792 bool
793 Module::isTrusted( const KeyID& keyID )
794 {
795  return ( keyTrust( keyID ) >= KPGP_VALIDITY_MARGINAL );
796 }
797 
798 Key*
799 Module::rereadKey( const KeyID& keyID, const bool readTrust /* = true */ )
800 {
801  if( 0 == pgp ) assignPGPBase();
802 
803  // search the old key data in the key list
804  Key* oldKey = publicKey( keyID );
805 
806  Key* newKey = pgp->readPublicKey( keyID, readTrust, oldKey );
807 
808  if( ( 0 == oldKey ) && ( 0 != newKey ) )
809  {
810  mPublicKeys.inSort( newKey );
811  kdDebug(5100) << "New public key 0x" << newKey->primaryKeyID() << " ("
812  << newKey->primaryUserID() << ").\n";
813  }
814  else if( ( 0 != oldKey ) && ( 0 == newKey ) )
815  { // the key has been deleted in the meantime
816  kdDebug(5100) << "Public key 0x" << oldKey->primaryKeyID() << " ("
817  << oldKey->primaryUserID() << ") will be removed.\n";
818  mPublicKeys.removeRef( oldKey );
819  }
820 
821  return newKey;
822 }
823 
824 TQCString
825 Module::getAsciiPublicKey(const KeyID& keyID)
826 {
827  if (0 == pgp) assignPGPBase();
828 
829  return pgp->getAsciiPublicKey(keyID);
830 }
831 
832 
833 bool Module::setPassPhrase(const TQString &aPass)
834 {
835  // null out old buffer before we touch the new string. So in case
836  // aPass isn't properly null-terminated, we don't leak secret data.
837  wipePassPhrase();
838 
839  if (!aPass.isEmpty())
840  {
841  if (aPass.length() >= 1024) {
842  // rediculously long passphrase.
843  // Maybe someone wants to trick us in malloc()'ing
844  // huge buffers...
845  return false;
846  }
847  passphrase = aPass;
848  havePassPhrase = true;
849  }
850  return true;
851 }
852 
853 bool
854 Module::changePassPhrase()
855 {
856  //FIXME...
857  KMessageBox::information(0,i18n("This feature is\nstill missing"));
858  return FALSE;
859 }
860 
861 void
862 Module::clear(const bool erasePassPhrase)
863 {
864  if(erasePassPhrase)
865  wipePassPhrase(true);
866 }
867 
868 const TQString
869 Module::lastErrorMsg(void) const
870 {
871  return errMsg;
872 }
873 
874 bool
875 Module::havePGP(void) const
876 {
877  return havePgp;
878 }
879 
880 void
881 Module::setShowCipherText(const bool flag)
882 {
883  showEncryptionResult = flag;
884 }
885 
886 bool
887 Module::showCipherText(void) const
888 {
889  return showEncryptionResult;
890 }
891 
892 KeyID
893 Module::selectSecretKey( const TQString& title,
894  const TQString& text,
895  const KeyID& keyId )
896 {
897  if( 0 == pgp ) {
898  assignPGPBase();
899  }
900 
901  if( usePGP() ) {
902  return selectKey( secretKeys(), title, text, keyId, SecretKeys );
903  }
904  else {
905  KMessageBox::sorry( 0, i18n("You either do not have GnuPG/PGP installed "
906  "or you chose not to use GnuPG/PGP.") );
907  return KeyID();
908  }
909 }
910 
911 KeyID
912 Module::selectPublicKey( const TQString& title,
913  const TQString& text /* = TQString() */,
914  const KeyID& oldKeyId /* = KeyID() */,
915  const TQString& address /* = TQString() */,
916  const unsigned int allowedKeys /* = AllKeys */ )
917 {
918  if( 0 == pgp ) {
919  assignPGPBase();
920  }
921 
922  if( usePGP() ) {
923  KeyID keyId;
924 
925  if( address.isEmpty() ) {
926  keyId = selectKey( publicKeys(), title, text, oldKeyId, allowedKeys );
927  }
928  else {
929  bool rememberChoice;
930  keyId = selectKey( rememberChoice, publicKeys(), title, text, oldKeyId,
931  allowedKeys );
932  if( !keyId.isEmpty() && rememberChoice ) {
933  setKeysForAddress( address, KeyIDList( keyId ) );
934  }
935  }
936 
937  return keyId;
938  }
939  else {
940  KMessageBox::sorry( 0, i18n("You either do not have GnuPG/PGP installed "
941  "or you chose not to use GnuPG/PGP.") );
942  return KeyID();
943  }
944 }
945 
946 
947 KeyIDList
948 Module::selectPublicKeys( const TQString& title,
949  const TQString& text /* = TQString() */,
950  const KeyIDList& oldKeyIds /* = KeyIDList() */,
951  const TQString& address /* = TQString() */,
952  const unsigned int allowedKeys /* = AllKeys */ )
953 {
954  if( 0 == pgp ) {
955  assignPGPBase();
956  }
957 
958  if( usePGP() ) {
959  KeyIDList keyIds;
960 
961  if( address.isEmpty() ) {
962  keyIds = selectKeys( publicKeys(), title, text, oldKeyIds, allowedKeys );
963  }
964  else {
965  bool rememberChoice;
966  keyIds = selectKeys( rememberChoice, publicKeys(), title, text,
967  oldKeyIds, allowedKeys );
968  if( !keyIds.isEmpty() && rememberChoice ) {
969  setKeysForAddress( address, keyIds );
970  }
971  }
972 
973  return keyIds;
974  }
975  else {
976  KMessageBox::sorry( 0, i18n("You either do not have GnuPG/PGP installed "
977  "or you chose not to use GnuPG/PGP.") );
978  return KeyIDList();
979  }
980 }
981 
982 
983 // -- static member functions ----------------------------------------------
984 
985 Module *
986 Module::getKpgp()
987 {
988  if (!kpgpObject)
989  {
990  kpgpObject = new Module();
991  }
992  return kpgpObject;
993 }
994 
995 
996 TDEConfig *
997 Module::getConfig()
998 {
999  return getKpgp()->config;
1000 }
1001 
1002 
1003 bool
1004 Module::prepareMessageForDecryption( const TQCString& msg,
1005  TQPtrList<Block>& pgpBlocks,
1006  TQStrList& nonPgpBlocks )
1007 {
1008  BlockType pgpBlock = NoPgpBlock;
1009  int start = -1; // start of the current PGP block
1010  int lastEnd = -1; // end of the last PGP block
1011 
1012  pgpBlocks.setAutoDelete( true );
1013  pgpBlocks.clear();
1014  nonPgpBlocks.setAutoDelete( true );
1015  nonPgpBlocks.clear();
1016 
1017  if( msg.isEmpty() )
1018  {
1019  nonPgpBlocks.append( "" );
1020  return false;
1021  }
1022 
1023  if( !strncmp( msg.data(), "-----BEGIN PGP ", 15 ) )
1024  start = 0;
1025  else
1026  {
1027  start = msg.find( "\n-----BEGIN PGP" ) + 1;
1028  if( start == 0 )
1029  {
1030  nonPgpBlocks.append( msg );
1031  return false; // message doesn't contain an OpenPGP block
1032  }
1033  }
1034 
1035  while( start != -1 )
1036  {
1037  int nextEnd, nextStart;
1038 
1039  // is the PGP block a clearsigned block?
1040  if( !strncmp( msg.data() + start + 15, "SIGNED", 6 ) )
1041  pgpBlock = ClearsignedBlock;
1042  else
1043  pgpBlock = UnknownBlock;
1044 
1045  nextEnd = msg.find( "\n-----END PGP", start + 15 );
1046  if( nextEnd == -1 )
1047  {
1048  nonPgpBlocks.append( msg.mid( lastEnd+1 ) );
1049  break;
1050  }
1051  nextStart = msg.find( "\n-----BEGIN PGP", start + 15 );
1052 
1053  if( ( nextStart == -1 ) || ( nextEnd < nextStart ) ||
1054  ( pgpBlock == ClearsignedBlock ) )
1055  { // most likely we found a PGP block (but we don't check if it's valid)
1056  // store the preceding non-PGP block
1057  nonPgpBlocks.append( msg.mid( lastEnd+1, start-lastEnd-1 ) );
1058  lastEnd = msg.find( "\n", nextEnd + 14 );
1059  if( lastEnd == -1 )
1060  {
1061  pgpBlocks.append( new Block( msg.mid( start ) ) );
1062  nonPgpBlocks.append( "" );
1063  break;
1064  }
1065  else
1066  {
1067  pgpBlocks.append( new Block( msg.mid( start, lastEnd+1-start ) ) );
1068  if( ( nextStart != -1 ) && ( nextEnd > nextStart ) )
1069  nextStart = msg.find( "\n-----BEGIN PGP", lastEnd+1 );
1070  }
1071  }
1072 
1073  start = nextStart;
1074  if( start == -1 )
1075  nonPgpBlocks.append( msg.mid( lastEnd+1 ) );
1076  else
1077  start++; // move start behind the '\n'
1078  }
1079 
1080  return ( !pgpBlocks.isEmpty() );
1081 }
1082 
1083 
1084 // --------------------- private functions -------------------
1085 
1086 bool
1087 Module::haveTrustedEncryptionKey( const TQString& person )
1088 {
1089  if( 0 == pgp ) assignPGPBase();
1090 
1091  if( !usePGP() ) return false;
1092 
1093  readPublicKeys();
1094 
1095  TQString address = canonicalAddress( person ).lower();
1096 
1097  // First look for this person's address in the address data dictionary
1098  KeyIDList keyIds = keysForAddress( address );
1099  if( !keyIds.isEmpty() ) {
1100  // Check if at least one of the keys is a trusted and valid encryption key
1101  for( KeyIDList::ConstIterator it = keyIds.begin();
1102  it != keyIds.end(); ++it ) {
1103  keyTrust( *it ); // this is called to make sure that the trust info
1104  // for this key is read
1105  Key *key = publicKey( *it );
1106  if( key && ( key->isValidEncryptionKey() ) &&
1107  ( key->keyTrust() >= KPGP_VALIDITY_MARGINAL ) )
1108  return true;
1109  }
1110  }
1111 
1112  // Now search the public keys for matching keys
1113  KeyListIterator it( mPublicKeys );
1114 
1115  // search a key which matches the complete address
1116  for( it.toFirst(); (*it); ++it ) {
1117  // search case insensitively in the list of userIDs of this key
1118  if( (*it)->matchesUserID( person, false ) ) {
1119  keyTrust( (*it)->primaryKeyID() ); // this is called to make sure that
1120  // the trust info for this key is read
1121  if( ( (*it)->isValidEncryptionKey() ) &&
1122  ( (*it)->keyTrust() >= KPGP_VALIDITY_MARGINAL ) ) {
1123  return true;
1124  }
1125  }
1126  }
1127 
1128  // if no key matches the complete address look for a key which matches
1129  // the canonical mail address
1130  for( it.toFirst(); (*it); ++it ) {
1131  // search case insensitively in the list of userIDs of this key
1132  if( (*it)->matchesUserID( address, false ) ) {
1133  keyTrust( (*it)->primaryKeyID() ); // this is called to make sure that
1134  // the trust info for this key is read
1135  if( ( (*it)->isValidEncryptionKey() ) &&
1136  ( (*it)->keyTrust() >= KPGP_VALIDITY_MARGINAL ) ) {
1137  return true;
1138  }
1139  }
1140  }
1141 
1142  // no trusted encryption key was found for the given person
1143  return false;
1144 }
1145 
1146 KeyIDList
1147 Module::getEncryptionKeys( const TQString& person )
1148 {
1149  if( 0 == pgp ) assignPGPBase();
1150 
1151  if( !usePGP() ) return KeyIDList();
1152 
1153  readPublicKeys();
1154 
1155  TQString address = canonicalAddress( person ).lower();
1156 
1157  // #### FIXME: Until we support encryption with untrusted keys only
1158  // #### trusted keys are allowed
1159  unsigned int allowedKeys = PublicKeys | EncryptionKeys | ValidKeys | TrustedKeys;
1160 #if 0
1161  // ### reenable this code when we support encryption with untrusted keys
1162  if( pgpType != tGPG ) {
1163  // usage of untrusted keys is only possible with GnuPG
1164  allowedKeys |= TrustedKeys;
1165  }
1166 #endif
1167 
1168  // First look for this person's address in the address->key dictionary
1169  KeyIDList keyIds = keysForAddress( address );
1170  if( !keyIds.isEmpty() ) {
1171  kdDebug(5100) << "Using encryption keys 0x"
1172  << keyIds.toStringList().join( ", 0x" )
1173  << " for " << person << endl;
1174  // Check if all of the keys are a trusted and valid encryption keys
1175  bool keysOk = true;
1176  for( KeyIDList::ConstIterator it = keyIds.begin();
1177  it != keyIds.end(); ++it ) {
1178  keyTrust( *it ); // this is called to make sure that the trust info
1179  // for this key is read
1180  Key *key = publicKey( *it );
1181  if( !( key && ( key->isValidEncryptionKey() ) &&
1182  ( key->keyTrust() >= KPGP_VALIDITY_MARGINAL ) ) )
1183  keysOk = false;
1184  }
1185  if( keysOk ) {
1186  return keyIds;
1187  }
1188  else {
1189  bool rememberChoice;
1190  keyIds = selectKeys( rememberChoice, mPublicKeys,
1191  i18n("Encryption Key Selection"),
1192  i18n("if in your language something like "
1193  "'key(s)' isn't possible please "
1194  "use the plural in the translation",
1195  "There is a problem with the "
1196  "encryption key(s) for \"%1\".\n\n"
1197  "Please re-select the key(s) which should "
1198  "be used for this recipient."
1199  ).arg(person),
1200  keyIds,
1201  allowedKeys );
1202  if( !keyIds.isEmpty() ) {
1203  if( rememberChoice ) {
1204  setKeysForAddress( person, keyIds );
1205  }
1206  return keyIds;
1207  }
1208  }
1209  }
1210 
1211  // Now search all public keys for matching keys
1212  KeyListIterator it( mPublicKeys );
1213  KeyList matchingKeys;
1214 
1215  // search all keys which match the complete address
1216  kdDebug(5100) << "Looking for keys matching " << person << " ...\n";
1217  for( it.toFirst(); (*it); ++it ) {
1218  // search case insensitively in the list of userIDs of this key
1219  if( (*it)->matchesUserID( person, false ) ) {
1220  keyTrust( (*it)->primaryKeyID() ); // this is called to make sure that
1221  // the trust info for this key is read
1222  if( ( (*it)->isValidEncryptionKey() ) &&
1223  ( (*it)->keyTrust() >= KPGP_VALIDITY_MARGINAL ) ) {
1224  kdDebug(5100) << "Matching trusted key found: "
1225  << (*it)->primaryKeyID() << endl;
1226  matchingKeys.append( *it );
1227  }
1228  }
1229  }
1230 
1231  // if no keys match the complete address look for keys which match
1232  // the canonical mail address
1233  kdDebug(5100) << "Looking for keys matching " << address << " ...\n";
1234  if( matchingKeys.isEmpty() ) {
1235  for ( it.toFirst(); (*it); ++it ) {
1236  // search case insensitively in the list of userIDs of this key
1237  if( (*it)->matchesUserID( address, false ) ) {
1238  keyTrust( (*it)->primaryKeyID() ); // this is called to make sure that
1239  // the trust info for this key is read
1240  if( ( (*it)->isValidEncryptionKey() ) &&
1241  ( (*it)->keyTrust() >= KPGP_VALIDITY_MARGINAL ) ) {
1242  kdDebug(5100) << "Matching trusted key found: "
1243  << (*it)->primaryKeyID() << endl;
1244  matchingKeys.append( *it );
1245  }
1246  }
1247  }
1248  }
1249 
1250  // no match until now, let the user choose the key
1251  if( matchingKeys.isEmpty() ) {
1252  // FIXME: let user get the key from keyserver
1253  bool rememberChoice;
1254  KeyIDList keyIds = selectKeys( rememberChoice, mPublicKeys,
1255  i18n("Encryption Key Selection"),
1256  i18n("if in your language something like "
1257  "'key(s)' isn't possible please "
1258  "use the plural in the translation",
1259  "No valid and trusted OpenPGP key was "
1260  "found for \"%1\".\n\n"
1261  "Select the key(s) which should "
1262  "be used for this recipient."
1263  ).arg(person),
1264  KeyIDList(),
1265  allowedKeys );
1266  if( !keyIds.isEmpty() ) {
1267  if( rememberChoice ) {
1268  setKeysForAddress( person, keyIds );
1269  }
1270  return keyIds;
1271  }
1272  }
1273  // only one key matches
1274  else if( matchingKeys.count() == 1 ) {
1275  return KeyIDList( matchingKeys.getFirst()->primaryKeyID() );
1276  }
1277  // more than one key matches; let the user choose the key(s)
1278  else {
1279  bool rememberChoice;
1280  KeyIDList keyIds = selectKeys( rememberChoice, matchingKeys,
1281  i18n("Encryption Key Selection"),
1282  i18n("if in your language something like "
1283  "'key(s)' isn't possible please "
1284  "use the plural in the translation",
1285  "More than one key matches \"%1\".\n\n"
1286  "Select the key(s) which should "
1287  "be used for this recipient."
1288  ).arg(person),
1289  KeyIDList(),
1290  allowedKeys );
1291  if( !keyIds.isEmpty() ) {
1292  if( rememberChoice ) {
1293  setKeysForAddress( person, keyIds );
1294  }
1295  return keyIds;
1296  }
1297  }
1298 
1299  return KeyIDList();
1300 }
1301 
1302 // check if pgp 2.6.x or 5.0 is installed
1303 // kpgp will prefer to user pgp 5.0
1304 bool
1305 Module::checkForPGP(void)
1306 {
1307  // get path
1308  TQCString path;
1309  TQStrList pSearchPaths;
1310  int index = 0;
1311  int lastindex = -1;
1312 
1313  havePgp=FALSE;
1314 
1315  path = getenv("PATH");
1316  while((index = path.find(":",lastindex+1)) != -1)
1317  {
1318  pSearchPaths.append(path.mid(lastindex+1,index-lastindex-1));
1319  lastindex = index;
1320  }
1321  if(lastindex != (int)path.length() - 1)
1322  pSearchPaths.append( path.mid(lastindex+1,path.length()-lastindex) );
1323 
1324  TQStrListIterator it(pSearchPaths);
1325 
1326  haveGpg=FALSE;
1327  // lets try gpg
1328 
1329  for ( it.toFirst() ; it.current() ; ++it )
1330  {
1331  path = (*it);
1332  path += "/gpg";
1333  if ( !access( path, X_OK ) )
1334  {
1335  kdDebug(5100) << "Kpgp: gpg found" << endl;
1336  havePgp=TRUE;
1337  haveGpg=TRUE;
1338  break;
1339  }
1340  }
1341 
1342  // search for pgp5.0
1343  havePGP5=FALSE;
1344  for ( it.toFirst() ; it.current() ; ++it )
1345  {
1346  path = (*it);
1347  path += "/pgpe";
1348  if ( !access( path, X_OK ) )
1349  {
1350  kdDebug(5100) << "Kpgp: pgp 5 found" << endl;
1351  havePgp=TRUE;
1352  havePGP5=TRUE;
1353  break;
1354  }
1355  }
1356 
1357  // lets try pgp2.6.x
1358  if (!havePgp) {
1359  for ( it.toFirst() ; it.current() ; ++it )
1360  {
1361  path = it.current();
1362  path += "/pgp";
1363  if ( !access( path, X_OK ) )
1364  {
1365  kdDebug(5100) << "Kpgp: pgp 2 or 6 found" << endl;
1366  havePgp=TRUE;
1367  break;
1368  }
1369  }
1370  }
1371 
1372  if (!havePgp)
1373  {
1374  kdDebug(5100) << "Kpgp: no pgp found" << endl;
1375  }
1376 
1377  return havePgp;
1378 }
1379 
1380 void
1381 Module::assignPGPBase(void)
1382 {
1383  if (pgp)
1384  delete pgp;
1385 
1386  if(havePgp)
1387  {
1388  switch (pgpType)
1389  {
1390  case tGPG:
1391  kdDebug(5100) << "Kpgp: assign pgp - gpg" << endl;
1392  pgp = new BaseG();
1393  break;
1394 
1395  case tPGP2:
1396  kdDebug(5100) << "Kpgp: assign pgp - pgp 2" << endl;
1397  pgp = new Base2();
1398  break;
1399 
1400  case tPGP5:
1401  kdDebug(5100) << "Kpgp: assign pgp - pgp 5" << endl;
1402  pgp = new Base5();
1403  break;
1404 
1405  case tPGP6:
1406  kdDebug(5100) << "Kpgp: assign pgp - pgp 6" << endl;
1407  pgp = new Base6();
1408  break;
1409 
1410  case tOff:
1411  // dummy handler
1412  kdDebug(5100) << "Kpgp: pgpBase is dummy " << endl;
1413  pgp = new Base();
1414  break;
1415 
1416  case tAuto:
1417  kdDebug(5100) << "Kpgp: assign pgp - auto" << endl;
1418  // fall through
1419  default:
1420  kdDebug(5100) << "Kpgp: assign pgp - default" << endl;
1421  if (haveGpg)
1422  {
1423  kdDebug(5100) << "Kpgp: pgpBase is gpg " << endl;
1424  pgp = new BaseG();
1425  pgpType = tGPG;
1426  }
1427  else if(havePGP5)
1428  {
1429  kdDebug(5100) << "Kpgp: pgpBase is pgp 5" << endl;
1430  pgp = new Base5();
1431  pgpType = tPGP5;
1432  }
1433  else
1434  {
1435  Base6 *pgp_v6 = new Base6();
1436  if (!pgp_v6->isVersion6())
1437  {
1438  kdDebug(5100) << "Kpgp: pgpBase is pgp 2 " << endl;
1439  delete pgp_v6;
1440  pgp = new Base2();
1441  pgpType = tPGP2;
1442  }
1443  else
1444  {
1445  kdDebug(5100) << "Kpgp: pgpBase is pgp 6 " << endl;
1446  pgp = pgp_v6;
1447  pgpType = tPGP6;
1448  }
1449  }
1450  } // switch
1451  }
1452  else
1453  {
1454  // dummy handler
1455  kdDebug(5100) << "Kpgp: pgpBase is dummy " << endl;
1456  pgp = new Base();
1457  pgpType = tOff;
1458  }
1459 }
1460 
1461 TQString
1462 Module::canonicalAddress( const TQString& _adress )
1463 {
1464  int index,index2;
1465 
1466  TQString address = _adress.simplifyWhiteSpace();
1467  address = address.stripWhiteSpace();
1468 
1469  // just leave pure e-mail address.
1470  if((index = address.find("<")) != -1)
1471  if((index2 = address.find("@",index+1)) != -1)
1472  if((index2 = address.find(">",index2+1)) != -1)
1473  return address.mid(index,index2-index+1);
1474 
1475  if((index = address.find("@")) == -1)
1476  {
1477  // local address
1478  //char hostname[1024];
1479  //gethostname(hostname,1024);
1480  //return "<" + address + "@" + hostname + ">";
1481  return "<" + address + "@localdomain>";
1482  }
1483  else
1484  {
1485  int index1 = address.findRev(" ",index);
1486  int index2 = address.find(" ",index);
1487  if(index2 == -1) index2 = address.length();
1488  return "<" + address.mid(index1+1 ,index2-index1-1) + ">";
1489  }
1490 }
1491 
1492 void
1493 Module::readPublicKeys( bool reread )
1494 {
1495  if( 0 == pgp ) assignPGPBase();
1496 
1497  if( !usePGP() )
1498  {
1499  mPublicKeys.clear();
1500  mPublicKeysCached = false;
1501  return;
1502  }
1503 
1504  if( !mPublicKeysCached || reread )
1505  {
1506  if( mPublicKeys.isEmpty() )
1507  {
1508  mPublicKeys = pgp->publicKeys();
1509  }
1510  else
1511  {
1512  KeyList newPublicKeyList = pgp->publicKeys();
1513 
1514  // merge the trust info from the old key list into the new key list
1515  // FIXME: This is currently O(K^2) where K = #keys. As the key lists
1516  // are sorted this can be done in O(K).
1517  KeyListIterator it( newPublicKeyList );
1518  for( it.toFirst(); (*it); ++it )
1519  {
1520  Key* oldKey = publicKey( (*it)->primaryKeyID() );
1521  if( oldKey )
1522  {
1523  (*it)->cloneKeyTrust( oldKey );
1524  }
1525  }
1526 
1527  mPublicKeys = newPublicKeyList;
1528  }
1529 
1530  mPublicKeysCached = true;
1531  mPublicKeys.setAutoDelete( true );
1532  }
1533 }
1534 
1535 void
1536 Module::readSecretKeys( bool reread )
1537 {
1538  if( 0 == pgp ) assignPGPBase();
1539 
1540  if( !usePGP() )
1541  {
1542  mSecretKeys.clear();
1543  mSecretKeysCached = false;
1544  return;
1545  }
1546 
1547  if( mSecretKeys.isEmpty() || reread )
1548  {
1549  if( mSecretKeys.isEmpty() )
1550  {
1551  mSecretKeys = pgp->secretKeys();
1552  }
1553  else
1554  {
1555  KeyList newSecretKeyList = pgp->secretKeys();
1556 
1557  // merge the trust info from the old key list into the new key list
1558  // FIXME: This is currently O(K^2) where K = #keys. As the key lists
1559  // are sorted this can be done in O(K).
1560  KeyListIterator it( newSecretKeyList );
1561  for( it.toFirst(); (*it); ++it )
1562  {
1563  Key* oldKey = secretKey( (*it)->primaryKeyID() );
1564  if( oldKey )
1565  {
1566  (*it)->cloneKeyTrust( oldKey );
1567  }
1568  }
1569 
1570  mSecretKeys = newSecretKeyList;
1571  }
1572 
1573  mSecretKeysCached = true;
1574  mSecretKeys.setAutoDelete( true );
1575  }
1576 }
1577 
1578 KeyID
1579 Module::selectKey( const KeyList& keys,
1580  const TQString& title,
1581  const TQString& text /* = TQString() */ ,
1582  const KeyID& keyId /* = KeyID() */ ,
1583  const unsigned int allowedKeys /* = AllKeys */ )
1584 {
1585  KeyID retval = KeyID();
1586 
1587  KeySelectionDialog dlg( keys, title, text, KeyIDList( keyId ), false,
1588  allowedKeys, false );
1589 
1590  TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
1591  bool rej = ( dlg.exec() == TQDialog::Rejected );
1592  TQApplication::restoreOverrideCursor();
1593 
1594  if( !rej ) {
1595  retval = dlg.key();
1596  }
1597 
1598  return retval;
1599 }
1600 
1601 KeyIDList
1602 Module::selectKeys( const KeyList& keys,
1603  const TQString& title,
1604  const TQString& text /* = TQString() */ ,
1605  const KeyIDList& keyIds /* = KeyIDList() */ ,
1606  const unsigned int allowedKeys /* = AllKeys */ )
1607 {
1608  KeyIDList retval = KeyIDList();
1609 
1610  KeySelectionDialog dlg( keys, title, text, keyIds, false, allowedKeys,
1611  true );
1612 
1613  TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
1614  bool rej = ( dlg.exec() == TQDialog::Rejected );
1615  TQApplication::restoreOverrideCursor();
1616 
1617  if( !rej ) {
1618  retval = dlg.keys();
1619  }
1620 
1621  return retval;
1622 }
1623 
1624 
1625 KeyID
1626 Module::selectKey( bool& rememberChoice,
1627  const KeyList& keys,
1628  const TQString& title,
1629  const TQString& text /* = TQString() */ ,
1630  const KeyID& keyId /* = KeyID() */ ,
1631  const unsigned int allowedKeys /* = AllKeys */ )
1632 {
1633  KeyID retval = KeyID();
1634 
1635  KeySelectionDialog dlg( keys, title, text, KeyIDList( keyId ), false,
1636  allowedKeys, false );
1637 
1638  TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
1639  bool rej = ( dlg.exec() == TQDialog::Rejected );
1640  TQApplication::restoreOverrideCursor();
1641 
1642  if( !rej ) {
1643  retval = dlg.key();
1644  rememberChoice = dlg.rememberSelection();
1645  }
1646  else {
1647  rememberChoice = false;
1648  }
1649 
1650  return retval;
1651 }
1652 
1653 KeyIDList
1654 Module::selectKeys( bool& rememberChoice,
1655  const KeyList& keys,
1656  const TQString& title,
1657  const TQString& text /* = TQString() */ ,
1658  const KeyIDList& keyIds /* = KeyIDList() */ ,
1659  const unsigned int allowedKeys /* = AllKeys */ )
1660 {
1661  KeyIDList retval = KeyIDList();
1662 
1663  KeySelectionDialog dlg( keys, title, text, keyIds, true, allowedKeys,
1664  true );
1665 
1666  TQApplication::setOverrideCursor( TQCursor(TQCursor::ArrowCursor) );
1667  bool rej = ( dlg.exec() == TQDialog::Rejected );
1668  TQApplication::restoreOverrideCursor();
1669 
1670  if( !rej ) {
1671  retval = dlg.keys();
1672  rememberChoice = dlg.rememberSelection();
1673  }
1674  else {
1675  rememberChoice = false;
1676  }
1677 
1678  return retval;
1679 }
1680 
1681 KeyIDList
1682 Module::keysForAddress( const TQString& address )
1683 {
1684  if( address.isEmpty() ) {
1685  return KeyIDList();
1686  }
1687  TQString addr = canonicalAddress( address ).lower();
1688  if( addressDataDict.contains( addr ) ) {
1689  return addressDataDict[addr].keyIds;
1690  }
1691  else {
1692  return KeyIDList();
1693  }
1694 }
1695 
1696 void
1697 Module::setKeysForAddress( const TQString& address, const KeyIDList& keyIds )
1698 {
1699  if( address.isEmpty() ) {
1700  return;
1701  }
1702  TQString addr = canonicalAddress( address ).lower();
1703  if( addressDataDict.contains( addr ) ) {
1704  addressDataDict[addr].keyIds = keyIds;
1705  }
1706  else {
1707  AddressData data;
1708  data.encrPref = UnknownEncryptPref;
1709  data.keyIds = keyIds;
1710  addressDataDict.insert( addr, data );
1711  }
1712 
1713  //writeAddressData();
1714 }
1715 
1716 void
1717 Module::readAddressData()
1718 {
1719  TQString address;
1720  AddressData data;
1721 
1722  TDEConfigGroup general( config, "General" );
1723  int num = general.readNumEntry( "addressEntries", 0 );
1724 
1725  addressDataDict.clear();
1726  for( int i=1; i<=num; i++ ) {
1727  TDEConfigGroup addrGroup( config, TQString("Address #%1").arg(i).local8Bit() );
1728  address = addrGroup.readEntry( "Address" );
1729  data.keyIds = KeyIDList::fromStringList( addrGroup.readListEntry( "Key IDs" ) );
1730  data.encrPref = (EncryptPref) addrGroup.readNumEntry( "EncryptionPreference",
1731  UnknownEncryptPref );
1732 // kdDebug(5100) << "Read address " << i << ": " << address
1733 // << "\nKey IDs: 0x" << data.keyIds.toStringList().join(", 0x")
1734 // << "\nEncryption preference: " << data.encrPref << endl;
1735  if ( !address.isEmpty() ) {
1736  addressDataDict.insert( address, data );
1737  }
1738  }
1739 }
1740 
1741 void
1742 Module::writeAddressData()
1743 {
1744  TDEConfigGroup general( config, "General" );
1745  general.writeEntry( "addressEntries", addressDataDict.count() );
1746 
1747  int i;
1748  AddressDataDict::Iterator it;
1749  for ( i=1, it = addressDataDict.begin();
1750  it != addressDataDict.end();
1751  ++it, i++ ) {
1752  TDEConfigGroup addrGroup( config, TQString("Address #%1").arg(i).local8Bit() );
1753  addrGroup.writeEntry( "Address", it.key() );
1754  addrGroup.writeEntry( "Key IDs", it.data().keyIds.toStringList() );
1755  addrGroup.writeEntry( "EncryptionPreference", it.data().encrPref );
1756  }
1757 
1758  config->sync();
1759 }
1760 
1761 EncryptPref
1762 Module::encryptionPreference( const TQString& address )
1763 {
1764  TQString addr = canonicalAddress( address ).lower();
1765  if( addressDataDict.contains( addr ) ) {
1766  return addressDataDict[addr].encrPref;
1767  }
1768  else {
1769  return UnknownEncryptPref;
1770  }
1771 }
1772 
1773 void
1774 Module::setEncryptionPreference( const TQString& address,
1775  const EncryptPref pref )
1776 {
1777  if( address.isEmpty() ) {
1778  return;
1779  }
1780  TQString addr = canonicalAddress( address ).lower();
1781  if( addressDataDict.contains( addr ) ) {
1782  addressDataDict[addr].encrPref = pref;
1783  }
1784  else {
1785  AddressData data;
1786  data.encrPref = pref;
1787  addressDataDict.insert( addr, data );
1788  }
1789 }
1790 
1791 } // namespace Kpgp