libkpgp

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