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
48namespace Kpgp {
49
50Module *Module::kpgpObject = 0L;
51static KStaticDeleter<Module> kpgpod;
52
53Module::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
71Module::~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
83void
84Module::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
107void
108Module::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
120void
121Module::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
139void
140Module::setUser(const KeyID& keyID)
141{
142 if (pgpUser != keyID) {
143 pgpUser = keyID;
144 wipePassPhrase();
145 }
146}
147
148const KeyID
149Module::user(void) const
150{
151 return pgpUser;
152}
153
154
155void
156Module::setEncryptToSelf(bool flag)
157{
158 flagEncryptToSelf = flag;
159}
160
161bool
162Module::encryptToSelf(void) const
163{
164 return flagEncryptToSelf;
165}
166
167
168void
169Module::setStorePassPhrase(bool flag)
170{
171 storePass = flag;
172}
173
174bool
175Module::storePassPhrase(void) const
176{
177 return storePass;
178}
179
180int
181Module::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
227void
228Module::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
239bool
240Module::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
260bool
261Module::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
300Kpgp::Result
301Module::clearsign( Block& block,
302 const KeyID& keyId, const TQCString& charset )
303{
304 return encrypt( block, TQStringList(), keyId, true, charset );
305}
306
307Kpgp::Result
308Module::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
450int
451Module::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
481Kpgp::Result
482Module::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
617int
618Module::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
675bool
676Module::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
691const KeyList
692Module::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
706const KeyList
707Module::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
721Key*
722Module::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
734Key*
735Module::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
746Key*
747Module::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
759Validity
760Module::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
774Validity
775Module::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
792bool
793Module::isTrusted( const KeyID& keyID )
794{
795 return ( keyTrust( keyID ) >= KPGP_VALIDITY_MARGINAL );
796}
797
798Key*
799Module::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
824TQCString
825Module::getAsciiPublicKey(const KeyID& keyID)
826{
827 if (0 == pgp) assignPGPBase();
828
829 return pgp->getAsciiPublicKey(keyID);
830}
831
832
833bool 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
853bool
854Module::changePassPhrase()
855{
856 //FIXME...
857 KMessageBox::information(0,i18n("This feature is\nstill missing"));
858 return FALSE;
859}
860
861void
862Module::clear(const bool erasePassPhrase)
863{
864 if(erasePassPhrase)
865 wipePassPhrase(true);
866}
867
868const TQString
869Module::lastErrorMsg(void) const
870{
871 return errMsg;
872}
873
874bool
875Module::havePGP(void) const
876{
877 return havePgp;
878}
879
880void
881Module::setShowCipherText(const bool flag)
882{
883 showEncryptionResult = flag;
884}
885
886bool
887Module::showCipherText(void) const
888{
889 return showEncryptionResult;
890}
891
892KeyID
893Module::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
911KeyID
912Module::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
947KeyIDList
948Module::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
985Module *
986Module::getKpgp()
987{
988 if (!kpgpObject)
989 {
990 kpgpObject = new Module();
991 }
992 return kpgpObject;
993}
994
995
996TDEConfig *
997Module::getConfig()
998{
999 return getKpgp()->config;
1000}
1001
1002
1003bool
1004Module::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
1086bool
1087Module::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
1146KeyIDList
1147Module::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
1304bool
1305Module::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
1380void
1381Module::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
1461TQString
1462Module::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
1492void
1493Module::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
1535void
1536Module::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
1578KeyID
1579Module::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
1601KeyIDList
1602Module::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
1625KeyID
1626Module::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
1653KeyIDList
1654Module::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
1681KeyIDList
1682Module::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
1696void
1697Module::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
1716void
1717Module::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
1741void
1742Module::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
1761EncryptPref
1762Module::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
1773void
1774Module::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