Fix assert when Mail-Followup-To contains two emails, as Ossi's Mutt does
[kdepim.git] / libkpgp / kpgp.cpp
blob0f3e24efc89bc32a1afbcfdc3b36e12d1cf7184c
1 /* -*- mode: C++; c-file-style: "gnu" -*-
2 kpgp.cpp
4 Copyright (C) 2001,2002 the KPGP authors
5 See file AUTHORS.kpgp for details
7 This file is part of KPGP, the KDE PGP/GnuPG support library.
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.
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
19 #include "kpgp.h"
20 #include "kpgpbase.h"
21 #include "kpgpui.h"
23 #include <kdebug.h>
24 #include <klocale.h>
25 #include <kmessagebox.h>
26 #include <kconfigbase.h>
27 #include <kconfiggroup.h>
28 #include <kconfig.h>
29 #include <kde_file.h>
31 #include <QLabel>
32 #include <QCursor>
33 #include <QApplication>
34 #include <QByteArray>
35 #include <QFileInfo>
37 #include <algorithm>
39 #include <stdio.h>
40 #include <time.h>
41 #include <stdlib.h>
42 #include <assert.h>
43 #include <stdarg.h>
44 #include <fcntl.h>
45 #include <unistd.h>
46 #include <string.h>
47 #include <signal.h>
48 #include <sys/socket.h>
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <sys/wait.h>
53 #ifdef ERROR
54 #undef ERROR
55 #endif
57 namespace Kpgp {
59 struct ModuleStatic {
60 ModuleStatic() : kpgpObject( 0 ) {}
61 ~ModuleStatic() { delete kpgpObject; }
62 Module* kpgpObject;
65 K_GLOBAL_STATIC( ModuleStatic, s_module )
67 Module::Module()
68 : mPublicKeys(),
69 mPublicKeysCached(false),
70 mSecretKeys(),
71 mSecretKeysCached(false),
72 passphrase(0), passphrase_buffer_len(0), havePassPhrase(false)
74 pgp = 0;
76 config = new KConfig("kpgprc");
78 init();
81 Module::~Module()
83 writeAddressData();
85 if (!s_module.isDestroyed() && s_module->kpgpObject == this)
86 s_module->kpgpObject = 0;
87 clear(true);
88 delete config;
89 delete pgp;
92 // ----------------- public methods -------------------------
94 void
95 Module::init()
97 wipePassPhrase();
99 // read kpgp config file entries
100 readConfig();
102 // read the email address -> { encryption keys, encryption preference }
103 // associations
104 readAddressData();
106 // do we have a pgp executable
107 checkForPGP();
109 // create the Base object later when it is
110 // needed to avoid the costly check done for
111 // the autodetection of PGP 2/6
112 //assignPGPBase();
113 delete pgp;
114 pgp=0;
117 void
118 Module::readConfig()
120 KConfigGroup grp(config, QString());
121 storePass = grp.readEntry("storePass", false);
122 showEncryptionResult = grp.readEntry("showEncryptionResult", true);
123 mShowKeyApprovalDlg = grp.readEntry( "showKeysForApproval", true );
124 // We have no config GUI for this key anymore, and the KPGP backend isn't ported,
125 // so let's just use Auto all the time. See #92619.
126 ///pgpType = (Module::PGPType) config->readEntry("pgpType", tAuto);
127 pgpType = tAuto;
128 flagEncryptToSelf = grp.readEntry("encryptToSelf", true);
131 void
132 Module::writeConfig(bool sync)
134 KConfigGroup grp(config, QString());
135 grp.writeEntry("storePass", storePass);
136 grp.writeEntry("showEncryptionResult", showEncryptionResult);
137 grp.writeEntry( "showKeysForApproval", mShowKeyApprovalDlg );
138 //config->writeEntry("pgpType", (int) pgpType);
139 grp.writeEntry("encryptToSelf", flagEncryptToSelf);
141 if(sync)
142 config->sync();
144 /// ### Why is the pgp object deleted? This is only necessary if the
145 /// PGP type was changed in the config dialog.
146 delete pgp;
147 pgp = 0;
150 void
151 Module::setUser(const KeyID& keyID)
153 if (pgpUser != keyID) {
154 pgpUser = keyID;
155 wipePassPhrase();
159 const KeyID
160 Module::user(void) const
162 return pgpUser;
166 void
167 Module::setEncryptToSelf(bool flag)
169 flagEncryptToSelf = flag;
172 bool
173 Module::encryptToSelf(void) const
175 return flagEncryptToSelf;
179 void
180 Module::setStorePassPhrase(bool flag)
182 storePass = flag;
185 bool
186 Module::storePassPhrase(void) const
188 return storePass;
192 Module::prepare( bool needPassPhrase, Block* block )
194 if (0 == pgp) assignPGPBase();
196 if(!havePgp)
198 errMsg = i18n("Could not find PGP executable.\n"
199 "Please check your PATH is set correctly.");
200 return 0;
203 if( block && ( block->status() & NO_SEC_KEY ) )
204 return 0;
206 if(needPassPhrase && !havePassPhrase) {
207 if( ( tGPG == pgpType ) && ( 0 != getenv("GPG_AGENT_INFO") ) ) {
208 // the user uses gpg-agent which asks itself for the passphrase
209 kDebug( 5326 ) <<"user uses gpg-agent -> don't ask for passphrase";
210 // set dummy passphrase (because else signing doesn't work -> FIXME)
211 setPassPhrase( "dummy" );
213 else {
214 QString ID;
215 if( block )
216 ID = block->requiredUserId();
217 PassphraseDialog passdlg(0, i18n("OpenPGP Security Check"), ID);
218 #ifndef QT_NO_CURSOR
219 QApplication::setOverrideCursor( QCursor(Qt::ArrowCursor) );
220 #endif
221 int passdlgResult = passdlg.exec();
222 #ifndef QT_NO_CURSOR
223 QApplication::restoreOverrideCursor();
224 #endif
225 if (passdlgResult == QDialog::Accepted) {
226 if (!setPassPhrase(passdlg.passphrase())) {
227 if ( passdlg.passphrase().length() >= 1024)
228 errMsg = i18n("Passphrase is too long, it must contain fewer than 1024 characters.");
229 else
230 errMsg = i18n("Out of memory.");
231 return 0;
233 } else {
234 wipePassPhrase();
235 return -1;
239 return 1;
242 void
243 Module::wipePassPhrase(bool freeMem)
245 if ( passphrase ) {
246 if ( passphrase_buffer_len )
247 memset( passphrase, 0x00, passphrase_buffer_len );
248 else {
249 kDebug( 5326 ) <<"wipePassPhrase: passphrase && !passphrase_buffer_len ???";
250 passphrase = 0;
253 if ( freeMem && passphrase ) {
254 free( passphrase );
255 passphrase = 0;
256 passphrase_buffer_len = 0;
258 havePassPhrase = false;
261 bool
262 Module::verify( Block& block )
264 int retval;
266 if (0 == pgp) assignPGPBase();
268 // everything ready
269 if( !prepare( false, &block ) )
270 return false;
271 // ok now try to verify the message.
272 retval = pgp->verify( block );
274 if(retval & Kpgp::ERROR)
276 errMsg = pgp->lastErrorMessage();
277 return false;
279 return true;
282 bool
283 Module::decrypt( Block& block )
285 int retval;
287 if (0 == pgp) assignPGPBase();
289 do {
290 // loop as long as the user enters a wrong passphrase and doesn't abort
291 // everything ready
292 if( prepare( true, &block ) != 1 )
293 return false;
294 // ok now try to decrypt the message.
295 retval = pgp->decrypt( block, passphrase );
296 // loop on bad passphrase
297 if( retval & BADPHRASE ) {
298 wipePassPhrase();
299 #ifndef QT_NO_CURSOR
300 QApplication::setOverrideCursor( QCursor(Qt::ArrowCursor) );
301 #endif
302 int ret = KMessageBox::warningContinueCancel(0,
303 i18n("You just entered an invalid passphrase.\n"
304 "Do you want to try again, or "
305 "cancel and view the message undecrypted?"),
306 i18n("PGP Warning"), KGuiItem(i18n("&Retry")));
307 #ifndef QT_NO_CURSOR
308 QApplication::restoreOverrideCursor();
309 #endif
310 if ( ret == KMessageBox::Cancel ) break;
311 } else
312 break;
313 } while ( true );
315 // erase the passphrase if we do not want to keep it
316 cleanupPass();
318 if(retval & Kpgp::ERROR)
320 errMsg = pgp->lastErrorMessage();
321 return false;
323 return true;
326 Kpgp::Result
327 Module::clearsign( Block& block,
328 const KeyID& keyId, const QByteArray& charset )
330 return encrypt( block, QStringList(), keyId, true, charset );
333 Kpgp::Result
334 Module::encrypt( Block& block,
335 const QStringList& receivers, const KeyID& keyId,
336 bool sign, const QByteArray& charset )
338 KeyIDList encryptionKeyIds; // list of keys which are used for encryption
339 int status = 0;
340 errMsg = "";
342 if( 0 == pgp ) assignPGPBase();
344 setUser( keyId );
346 if( !receivers.empty() ) {
347 Kpgp::Result result = getEncryptionKeys( encryptionKeyIds, receivers,
348 keyId );
349 if( Kpgp::Ok != result ) {
350 return result;
354 status = doEncSign( block, encryptionKeyIds, sign );
356 if( status & CANCEL )
357 return Kpgp::Canceled;
359 // check for bad passphrase
360 while( status & BADPHRASE ) {
361 wipePassPhrase();
362 QString str = i18n("You entered an invalid passphrase.\n"
363 "Do you want to try again, continue and leave the "
364 "message unsigned, or cancel sending the message?");
365 #ifndef QT_NO_CURSOR
366 QApplication::setOverrideCursor( QCursor(Qt::ArrowCursor) );
367 #endif
368 int ret = KMessageBox::warningYesNoCancel( 0, str,
369 i18n("PGP Warning"),
370 KGuiItem(i18n("&Retry")),
371 KGuiItem(i18n("Send &Unsigned")) );
372 #ifndef QT_NO_CURSOR
373 QApplication::restoreOverrideCursor();
374 #endif
375 if( ret == KMessageBox::Cancel ) {
376 return Kpgp::Canceled;
378 if( ret == KMessageBox::No ) {
379 // the user selected "Send unsigned"
380 if( encryptionKeyIds.isEmpty() ) {
381 block.reset();
382 return Kpgp::Ok;
384 else {
385 sign = false;
388 // ok let's try once again...
389 status = doEncSign( block, encryptionKeyIds, sign );
392 // did signing fail?
393 if( status & ERR_SIGNING ) {
394 QString str = i18nc("%1 = 'signing failed' error message",
395 "%1\nDo you want to send the message unsigned, "
396 "or cancel sending the message?",
397 pgp->lastErrorMessage() );
398 #ifndef QT_NO_CURSOR
399 QApplication::setOverrideCursor( QCursor(Qt::ArrowCursor) );
400 #endif
401 int ret = KMessageBox::warningContinueCancel( 0, str,
402 i18n("PGP Warning"),
403 KGuiItem(i18n("Send &Unsigned")) );
404 #ifndef QT_NO_CURSOR
405 QApplication::restoreOverrideCursor();
406 #endif
407 if( ret == KMessageBox::Cancel ) {
408 return Kpgp::Canceled;
410 sign = false;
411 status = doEncSign( block, encryptionKeyIds, sign );
414 // check for bad keys
415 if( status & BADKEYS ) {
416 QString str = i18nc("%1 = 'bad keys' error message",
417 "%1\nDo you want to encrypt anyway, leave the "
418 "message as-is, or cancel sending the message?",
419 pgp->lastErrorMessage() );
421 #ifndef QT_NO_CURSOR
422 QApplication::setOverrideCursor( QCursor(Qt::ArrowCursor) );
423 #endif
424 int ret = KMessageBox::warningYesNoCancel( 0, str,
425 i18n("PGP Warning"),
426 KGuiItem(i18n("Send &Encrypted")),
427 KGuiItem(i18n("Send &Unencrypted")) );
428 #ifndef QT_NO_CURSOR
429 QApplication::restoreOverrideCursor();
430 #endif
431 if( ret == KMessageBox::Cancel ) {
432 return Kpgp::Canceled;
434 if( ret == KMessageBox::No ) {
435 // the user selected "Send unencrypted"
436 if( sign ) {
437 doEncSign( block, KeyIDList(), sign );
439 else {
440 block.reset();
442 return Kpgp::Ok;
446 if( status & MISSINGKEY ) {
447 QString str = i18nc("%1 = 'missing keys' error message",
448 "%1\nDo you want to leave the message as-is, "
449 "or cancel sending the message?",
450 pgp->lastErrorMessage() );
451 #ifndef QT_NO_CURSOR
452 QApplication::setOverrideCursor( QCursor(Qt::ArrowCursor) );
453 #endif
454 int ret = KMessageBox::warningContinueCancel( 0, str,
455 i18n("PGP Warning"),
456 KGuiItem(i18n("&Send As-Is")) );
457 #ifndef QT_NO_CURSOR
458 QApplication::restoreOverrideCursor();
459 #endif
460 if( ret == KMessageBox::Cancel ) {
461 return Kpgp::Canceled;
463 block.reset();
464 return Kpgp::Ok;
467 if( status & Kpgp::ERROR ) {
468 // show error dialog
469 errMsg = i18n( "The following error occurred:\n%1" ,
470 pgp->lastErrorMessage() );
471 QString details = i18n( "This is the error message of %1:\n%2" ,
472 ( pgpType == tGPG ) ? "GnuPG" : "PGP" ,
473 block.error().data() );
474 #ifndef QT_NO_CURSOR
475 QApplication::setOverrideCursor( QCursor(Qt::ArrowCursor) );
476 #endif
477 KMessageBox::detailedSorry( 0, errMsg, details );
478 #ifndef QT_NO_CURSOR
479 QApplication::restoreOverrideCursor();
480 #endif
481 return Kpgp::Failure;
484 if( showCipherText() ) {
485 // show cipher text dialog
486 CipherTextDialog *cipherTextDlg = new CipherTextDialog( block.text(), charset );
487 #ifndef QT_NO_CURSOR
488 QApplication::setOverrideCursor( QCursor(Qt::ArrowCursor) );
489 #endif
490 bool result = ( cipherTextDlg->exec() == QDialog::Accepted );
491 #ifndef QT_NO_CURSOR
492 QApplication::restoreOverrideCursor();
493 #endif
494 delete cipherTextDlg;
495 return result == QDialog::Accepted ? Kpgp::Ok : Kpgp::Canceled;
497 return Kpgp::Ok;
501 Module::doEncSign( Block& block,
502 const KeyIDList& recipientKeyIds, bool sign )
504 int retval = 0;
506 if( 0 == pgp ) assignPGPBase();
508 // to avoid error messages in case pgp is not installed
509 if( !havePgp ) return OK;
511 if( sign ) {
512 int result = prepare( true, &block );
513 switch( result ) {
514 case -1:
515 return CANCEL;
516 case 0:
517 return Kpgp::ERROR;
519 retval = pgp->encsign( block, recipientKeyIds, passphrase );
521 else {
522 if( !prepare( false, &block ) ) return Kpgp::ERROR;
523 retval = pgp->encrypt( block, recipientKeyIds );
525 // erase the passphrase if we do not want to keep it
526 cleanupPass();
528 return retval;
531 Kpgp::Result
532 Module::getEncryptionKeys( KeyIDList& encryptionKeyIds,
533 const QStringList& recipients,
534 const KeyID& keyId )
536 if( recipients.empty() ) {
537 encryptionKeyIds.clear();
538 return Kpgp::Ok;
541 // list of lists of encryption keys (one list per recipient + one list
542 // for the sender)
543 QVector<KeyIDList> recipientKeyIds( recipients.count() + 1 );
544 // add the sender's encryption key(s) to the list of recipient key IDs
545 if( encryptToSelf() ) {
546 recipientKeyIds[0] = KeyIDList( keyId );
548 else {
549 recipientKeyIds[0] = KeyIDList();
551 bool showKeysForApproval = false;
552 int i = 1;
553 for( QStringList::ConstIterator it = recipients.constBegin();
554 it != recipients.constEnd(); ++it, ++i ) {
555 EncryptPref encrPref = encryptionPreference( *it );
556 if( ( encrPref == UnknownEncryptPref ) || ( encrPref == NeverEncrypt ) )
557 showKeysForApproval = true;
559 KeyIDList keyIds = getEncryptionKeys( *it );
560 if( keyIds.isEmpty() ) {
561 showKeysForApproval = true;
563 recipientKeyIds[i] = keyIds;
566 kDebug( 5326 ) <<"recipientKeyIds = (";
567 QVector<KeyIDList>::const_iterator kit;
568 for( kit = recipientKeyIds.constBegin(); kit != recipientKeyIds.constEnd(); ++kit ) {
569 kDebug( 5326 ) <<"( 0x" << (*kit).toStringList().join(", 0x" )
570 << " ),\n";
572 kDebug( 5326 ) <<")";
574 if( showKeysForApproval || mShowKeyApprovalDlg ) {
575 // #### FIXME: Until we support encryption with untrusted keys only
576 // #### trusted keys are allowed
577 unsigned int allowedKeys = PublicKeys | EncryptionKeys | ValidKeys | TrustedKeys;
578 #if 0
579 // ### reenable this code when we support encryption with untrusted keys
580 if( pgpType != tGPG ) {
581 // usage of untrusted keys is only possible with GnuPG
582 allowedKeys |= TrustedKeys;
584 #endif
585 // show the recipients <-> key relation
586 KeyApprovalDialog dlg( recipients, recipientKeyIds, allowedKeys );
588 #ifndef QT_NO_CURSOR
589 QApplication::setOverrideCursor( QCursor(Qt::ArrowCursor) );
590 #endif
591 int ret = dlg.exec();
593 if( ret == QDialog::Rejected ) {
594 #ifndef QT_NO_CURSOR
595 QApplication::restoreOverrideCursor();
596 #endif
597 return Kpgp::Canceled;
600 recipientKeyIds = dlg.keys();
601 #ifndef QT_NO_CURSOR
602 QApplication::restoreOverrideCursor();
603 #endif
606 // flatten the list of lists of key IDs and count empty key ID lists
607 int emptyListCount = 0;
608 for( QVector<KeyIDList>::const_iterator it = recipientKeyIds.constBegin();
609 it != recipientKeyIds.constEnd(); ++it ) {
610 if( (*it).isEmpty() ) {
611 // only count empty key ID lists for the recipients
612 if( it != recipientKeyIds.constBegin() ) {
613 emptyListCount++;
616 else {
617 for( KeyIDList::ConstIterator kit = (*it).constBegin();
618 kit != (*it).constEnd(); kit++ ) {
619 encryptionKeyIds.append( *kit );
624 // FIXME-AFTER-KDE-3.1: Show warning if message won't be encrypted to self
626 // show a warning if the user didn't select an encryption key for
627 // some of the recipients
628 if( recipientKeyIds.size() == emptyListCount + 1 ) { // (+1 because of the sender's key)
629 QString str = ( recipients.count() == 1 )
630 ? i18n("You did not select an encryption key for the "
631 "recipient of this message; therefore, the message "
632 "will not be encrypted.")
633 : i18n("You did not select an encryption key for any of the "
634 "recipients of this message; therefore, the message "
635 "will not be encrypted.");
636 #ifndef QT_NO_CURSOR
637 QApplication::setOverrideCursor( QCursor(Qt::ArrowCursor) );
638 #endif
639 int ret = KMessageBox::warningContinueCancel( 0, str,
640 i18n("PGP Warning"),
641 KGuiItem(i18n("Send &Unencrypted")) );
642 #ifndef QT_NO_CURSOR
643 QApplication::restoreOverrideCursor();
644 #endif
645 if( ret == KMessageBox::Cancel ) {
646 return Kpgp::Canceled;
648 else
649 encryptionKeyIds.clear();
651 else if( emptyListCount > 0 ) {
652 QString str = ( emptyListCount == 1 )
653 ? i18n("You did not select an encryption key for one of "
654 "the recipients; this person will not be able to "
655 "decrypt the message if you encrypt it.")
656 : i18n("You did not select encryption keys for some of "
657 "the recipients; these persons will not be able to "
658 "decrypt the message if you encrypt it." );
659 #ifndef QT_NO_CURSOR
660 QApplication::setOverrideCursor( QCursor(Qt::ArrowCursor) );
661 #endif
662 int ret = KMessageBox::warningYesNoCancel( 0, str,
663 i18n("PGP Warning"),
664 KGuiItem(i18n("Send &Encrypted")),
665 KGuiItem(i18n("Send &Unencrypted")) );
666 #ifndef QT_NO_CURSOR
667 QApplication::restoreOverrideCursor();
668 #endif
669 if( ret == KMessageBox::Cancel ) {
670 return Kpgp::Canceled;
672 else if( ret == KMessageBox::No ) {
673 // the user selected "Send unencrypted"
674 encryptionKeyIds.clear();
678 return Kpgp::Ok;
682 Module::encryptionPossible( const QStringList& recipients )
684 if( 0 == pgp ) assignPGPBase();
686 if( !usePGP() )
687 return 0;
689 if( recipients.empty() )
690 return 0;
692 int noKey = 0, never = 0, unknown = 0, always = 0, aip = 0, ask = 0,
693 askwp = 0;
694 for( QStringList::ConstIterator it = recipients.constBegin();
695 it != recipients.constEnd(); ++it) {
696 if( haveTrustedEncryptionKey( *it ) ) {
697 EncryptPref encrPref = encryptionPreference( *it );
698 switch( encrPref ) {
699 case NeverEncrypt:
700 never++;
701 break;
702 case UnknownEncryptPref:
703 unknown++;
704 break;
705 case AlwaysEncrypt:
706 always++;
707 break;
708 case AlwaysEncryptIfPossible:
709 aip++;
710 break;
711 case AlwaysAskForEncryption:
712 ask++;
713 break;
714 case AskWheneverPossible:
715 askwp++;
716 break;
719 else {
720 noKey++;
724 if( ( always+aip > 0 ) && ( never+unknown+ask+askwp+noKey == 0 ) ) {
725 return 1; // encryption possible and desired
728 if( ( unknown+ask+askwp > 0 ) && ( never+noKey == 0 ) ) {
729 return 2; // encryption possible, but user has to be asked
732 if( ( never+noKey > 0 ) && ( always+ask == 0 ) ) {
733 return 0; // encryption isn't possible or desired
736 return -1; // we can't decide it automatically
739 bool
740 Module::signKey(const KeyID& keyId)
742 if (0 == pgp) assignPGPBase();
744 if( prepare( true ) != 1 )
745 return false;
746 if(pgp->signKey(keyId, passphrase) & Kpgp::ERROR)
748 errMsg = pgp->lastErrorMessage();
749 return false;
751 return true;
755 const KeyList
756 Module::publicKeys()
758 if (0 == pgp) assignPGPBase();
760 if (!prepare()) return KeyList();
762 if( !mPublicKeysCached ) {
763 readPublicKeys();
766 return mPublicKeys;
770 const KeyList
771 Module::secretKeys()
773 if (0 == pgp) assignPGPBase();
775 if (!prepare()) return KeyList();
777 if( !mSecretKeysCached ) {
778 readSecretKeys();
781 return mSecretKeys;
785 Key*
786 Module::publicKey(const KeyID& keyID)
788 readPublicKeys();
790 foreach ( Key* key, mPublicKeys ) {
791 if( keyID == key->primaryKeyID() ||
792 keyID == key->primaryFingerprint() )
793 return key;
796 return 0;
799 Key*
800 Module::publicKey( const QString& userID )
802 readPublicKeys();
804 foreach ( Key* key, mPublicKeys ) {
805 if( key->matchesUserID( userID ) )
806 return key;
809 return 0;
812 Key*
813 Module::secretKey(const KeyID& keyID)
815 readSecretKeys();
817 foreach ( Key* key, mSecretKeys ) {
818 if( keyID == key->primaryKeyID() ||
819 keyID == key->primaryFingerprint() )
820 return key;
823 return 0;
826 Validity
827 Module::keyTrust( const KeyID& keyID )
829 Key *key = publicKey( keyID );
831 if( ( 0 == key ) || ( key->keyTrust() == KPGP_VALIDITY_UNKNOWN ) )
832 { // (re)check the key if it's unknown or if its trust is unknown
833 key = rereadKey( keyID, true );
834 if( key == 0 )
835 return KPGP_VALIDITY_UNKNOWN;
838 return key->keyTrust();
841 Validity
842 Module::keyTrust( const QString& userID )
844 Key *key = publicKey( userID );
846 if( key == 0 )
847 return KPGP_VALIDITY_UNKNOWN;
849 if( key->keyTrust() == KPGP_VALIDITY_UNKNOWN )
851 key = rereadKey( key->primaryKeyID(), true );
852 if( key == 0 )
853 return KPGP_VALIDITY_UNKNOWN;
856 return key->keyTrust();
859 bool
860 Module::isTrusted( const KeyID& keyID )
862 return ( keyTrust( keyID ) >= KPGP_VALIDITY_MARGINAL );
865 Key*
866 Module::rereadKey( const KeyID& keyID, const bool readTrust /* = true */ )
868 if( 0 == pgp ) assignPGPBase();
870 // search the old key data in the key list
871 Key* oldKey = publicKey( keyID );
873 Key* newKey = pgp->readPublicKey( keyID, readTrust, oldKey );
875 if( ( 0 == oldKey ) && ( 0 != newKey ) )
877 KeyList::Iterator it = std::lower_bound( mPublicKeys.begin(), mPublicKeys.end(), newKey, KeyCompare );
878 mPublicKeys.insert( it, newKey );
879 kDebug( 5326 ) <<"New public key 0x" << newKey->primaryKeyID() <<" ("
880 << newKey->primaryUserID() << ").\n";
882 else if( ( 0 != oldKey ) && ( 0 == newKey ) )
883 { // the key has been deleted in the meantime
884 kDebug( 5326 ) <<"Public key 0x" << oldKey->primaryKeyID() <<" ("
885 << oldKey->primaryUserID() << ") will be removed.\n";
886 mPublicKeys.removeAll( oldKey );
889 return newKey;
892 QByteArray
893 Module::getAsciiPublicKey(const KeyID& keyID)
895 if (0 == pgp) assignPGPBase();
897 return pgp->getAsciiPublicKey(keyID);
901 bool Module::setPassPhrase(const QString& aPass)
903 // null out old buffer before we touch the new string. So in case
904 // aPass isn't properly null-terminated, we don't leak secret data.
905 wipePassPhrase();
907 if (!aPass.isNull())
909 size_t newlen = aPass.length();
910 if ( newlen >= 1024 ) {
911 // rediculously long passphrase.
912 // Maybe someone wants to trick us in malloc()'ing
913 // huge buffers...
914 return false;
916 if ( passphrase_buffer_len < newlen + 1 ) {
917 // too little space in current buffer:
918 // allocate a larger one.
919 if ( passphrase )
920 free( passphrase );
921 passphrase_buffer_len = (newlen + 1 + 15) & ~0xF; // make it a multiple of 16.
922 passphrase = (char*)malloc( passphrase_buffer_len );
923 if (!passphrase) {
924 passphrase_buffer_len = 0;
925 return false;
928 memcpy( passphrase, aPass.toLocal8Bit().data(), newlen + 1 );
929 havePassPhrase = true;
931 return true;
934 bool
935 Module::changePassPhrase()
937 //FIXME...
938 KMessageBox::information(0,i18n("This feature is\nstill missing"));
939 return false;
942 void
943 Module::clear(const bool erasePassPhrase)
945 if(erasePassPhrase)
946 wipePassPhrase(true);
949 const QString
950 Module::lastErrorMsg(void) const
952 return errMsg;
955 bool
956 Module::havePGP(void) const
958 return havePgp;
961 void
962 Module::setShowCipherText(const bool flag)
964 showEncryptionResult = flag;
967 bool
968 Module::showCipherText(void) const
970 return showEncryptionResult;
973 KeyID
974 Module::selectSecretKey( const QString& title,
975 const QString& text,
976 const KeyID& keyId )
978 if( 0 == pgp ) {
979 assignPGPBase();
982 if( usePGP() ) {
983 return selectKey( secretKeys(), title, text, keyId, SecretKeys );
985 else {
986 KMessageBox::sorry( 0, i18n("You either do not have GnuPG/PGP installed "
987 "or you chose not to use GnuPG/PGP.") );
988 return KeyID();
992 KeyID
993 Module::selectPublicKey( const QString& title,
994 const QString& text /*QString() */,
995 const KeyID& oldKeyId /* = KeyID() */,
996 const QString& address /*QString() */,
997 const unsigned int allowedKeys /* = AllKeys */ )
999 if( 0 == pgp ) {
1000 assignPGPBase();
1003 if( usePGP() ) {
1004 KeyID keyId;
1006 if( address.isEmpty() ) {
1007 keyId = selectKey( publicKeys(), title, text, oldKeyId, allowedKeys );
1009 else {
1010 bool rememberChoice;
1011 keyId = selectKey( rememberChoice, publicKeys(), title, text, oldKeyId,
1012 allowedKeys );
1013 if( !keyId.isEmpty() && rememberChoice ) {
1014 setKeysForAddress( address, KeyIDList( keyId ) );
1018 return keyId;
1020 else {
1021 KMessageBox::sorry( 0, i18n("You either do not have GnuPG/PGP installed "
1022 "or you chose not to use GnuPG/PGP.") );
1023 return KeyID();
1028 KeyIDList
1029 Module::selectPublicKeys( const QString& title,
1030 const QString& text /* = QString() */,
1031 const KeyIDList& oldKeyIds /* = KeyIDList() */,
1032 const QString& address /*= QString() */,
1033 const unsigned int allowedKeys /* = AllKeys */ )
1035 if( 0 == pgp ) {
1036 assignPGPBase();
1039 if( usePGP() ) {
1040 KeyIDList keyIds;
1042 if( address.isEmpty() ) {
1043 keyIds = selectKeys( publicKeys(), title, text, oldKeyIds, allowedKeys );
1045 else {
1046 bool rememberChoice;
1047 keyIds = selectKeys( rememberChoice, publicKeys(), title, text,
1048 oldKeyIds, allowedKeys );
1049 if( !keyIds.isEmpty() && rememberChoice ) {
1050 setKeysForAddress( address, keyIds );
1054 return keyIds;
1056 else {
1057 KMessageBox::sorry( 0, i18n("You either do not have GnuPG/PGP installed "
1058 "or you chose not to use GnuPG/PGP.") );
1059 return KeyIDList();
1064 // -- static member functions ----------------------------------------------
1066 Module *
1067 Module::getKpgp()
1069 if (!s_module->kpgpObject)
1071 s_module->kpgpObject = new Module();
1073 return s_module->kpgpObject;
1077 KConfig *
1078 Module::getConfig()
1080 return getKpgp()->config;
1084 bool
1085 Module::prepareMessageForDecryption( const QByteArray& msg,
1086 QList<Block>& pgpBlocks,
1087 QList<QByteArray>& nonPgpBlocks )
1089 BlockType pgpBlock = NoPgpBlock;
1090 int start = -1; // start of the current PGP block
1091 int lastEnd = -1; // end of the last PGP block
1093 pgpBlocks.clear();
1094 nonPgpBlocks.clear();
1096 if( msg.isEmpty() )
1098 nonPgpBlocks.append( "" );
1099 return false;
1102 if( !strncmp( msg.data(), "-----BEGIN PGP ", 15 ) )
1103 start = 0;
1104 else
1106 start = msg.indexOf( "\n-----BEGIN PGP" ) + 1;
1107 if( start == 0 )
1109 nonPgpBlocks.append( msg );
1110 return false; // message doesn't contain an OpenPGP block
1114 while( start != -1 )
1116 int nextEnd, nextStart;
1118 // is the PGP block a clearsigned block?
1119 if( !strncmp( msg.data() + start + 15, "SIGNED", 6 ) )
1120 pgpBlock = ClearsignedBlock;
1121 else
1122 pgpBlock = UnknownBlock;
1124 nextEnd = msg.indexOf( "\n-----END PGP", start + 15 );
1125 if( nextEnd == -1 )
1127 nonPgpBlocks.append( msg.mid( lastEnd+1 ) );
1128 break;
1130 nextStart = msg.indexOf( "\n-----BEGIN PGP", start + 15 );
1132 if( ( nextStart == -1 ) || ( nextEnd < nextStart ) ||
1133 ( pgpBlock == ClearsignedBlock ) )
1134 { // most likely we found a PGP block (but we don't check if it's valid)
1135 // store the preceding non-PGP block
1136 nonPgpBlocks.append( msg.mid( lastEnd+1, start-lastEnd-1 ) );
1137 lastEnd = msg.indexOf( "\n", nextEnd + 14 );
1138 if( lastEnd == -1 )
1140 pgpBlocks.append( Block( msg.mid( start ) ) );
1141 nonPgpBlocks.append( "" );
1142 break;
1144 else
1146 pgpBlocks.append( Block( msg.mid( start, lastEnd+1-start ) ) );
1147 if( ( nextStart != -1 ) && ( nextEnd > nextStart ) )
1148 nextStart = msg.indexOf( "\n-----BEGIN PGP", lastEnd+1 );
1152 start = nextStart;
1153 if( start == -1 )
1154 nonPgpBlocks.append( msg.mid( lastEnd+1 ) );
1155 else
1156 start++; // move start behind the '\n'
1159 return ( !pgpBlocks.isEmpty() );
1163 // --------------------- private functions -------------------
1165 bool
1166 Module::haveTrustedEncryptionKey( const QString& person )
1168 if( 0 == pgp ) assignPGPBase();
1170 if( !usePGP() ) return false;
1172 readPublicKeys();
1174 QString address = canonicalAddress( person ).toLower();
1176 // First look for this person's address in the address data dictionary
1177 KeyIDList keyIds = keysForAddress( address );
1178 if( !keyIds.isEmpty() ) {
1179 // Check if at least one of the keys is a trusted and valid encryption key
1180 for( KeyIDList::ConstIterator it = keyIds.constBegin();
1181 it != keyIds.constEnd(); ++it ) {
1182 keyTrust( *it ); // this is called to make sure that the trust info
1183 // for this key is read
1184 Key *key = publicKey( *it );
1185 if( key && ( key->isValidEncryptionKey() ) &&
1186 ( key->keyTrust() >= KPGP_VALIDITY_MARGINAL ) )
1187 return true;
1191 // Now search the public keys for matching keys
1192 KeyList::Iterator it = mPublicKeys.begin();
1194 // search a key which matches the complete address
1195 for(; it != mPublicKeys.end(); ++it ) {
1196 // search case insensitively in the list of userIDs of this key
1197 if( (*it)->matchesUserID( person, false ) ) {
1198 keyTrust( (*it)->primaryKeyID() ); // this is called to make sure that
1199 // the trust info for this key is read
1200 if( ( (*it)->isValidEncryptionKey() ) &&
1201 ( (*it)->keyTrust() >= KPGP_VALIDITY_MARGINAL ) ) {
1202 return true;
1207 // if no key matches the complete address look for a key which matches
1208 // the canonical mail address
1209 for( it = mPublicKeys.begin(); it != mPublicKeys.end(); ++it ) {
1210 // search case insensitively in the list of userIDs of this key
1211 if( (*it)->matchesUserID( address, false ) ) {
1212 keyTrust( (*it)->primaryKeyID() ); // this is called to make sure that
1213 // the trust info for this key is read
1214 if( ( (*it)->isValidEncryptionKey() ) &&
1215 ( (*it)->keyTrust() >= KPGP_VALIDITY_MARGINAL ) ) {
1216 return true;
1221 // no trusted encryption key was found for the given person
1222 return false;
1225 KeyIDList
1226 Module::getEncryptionKeys( const QString& person )
1228 if( 0 == pgp ) assignPGPBase();
1230 if( !usePGP() ) return KeyIDList();
1232 readPublicKeys();
1234 QString address = canonicalAddress( person ).toLower();
1236 // #### FIXME: Until we support encryption with untrusted keys only
1237 // #### trusted keys are allowed
1238 unsigned int allowedKeys = PublicKeys | EncryptionKeys | ValidKeys | TrustedKeys;
1239 #if 0
1240 // ### reenable this code when we support encryption with untrusted keys
1241 if( pgpType != tGPG ) {
1242 // usage of untrusted keys is only possible with GnuPG
1243 allowedKeys |= TrustedKeys;
1245 #endif
1247 // First look for this person's address in the address->key dictionary
1248 KeyIDList keyIds = keysForAddress( address );
1249 if( !keyIds.isEmpty() ) {
1250 kDebug( 5326 ) <<"Using encryption keys 0x"
1251 << keyIds.toStringList().join( ", 0x" )
1252 << "for" << person;
1253 // Check if all of the keys are a trusted and valid encryption keys
1254 bool keysOk = true;
1255 for( KeyIDList::ConstIterator it = keyIds.constBegin();
1256 it != keyIds.constEnd(); ++it ) {
1257 keyTrust( *it ); // this is called to make sure that the trust info
1258 // for this key is read
1259 Key *key = publicKey( *it );
1260 if( !( key && ( key->isValidEncryptionKey() ) &&
1261 ( key->keyTrust() >= KPGP_VALIDITY_MARGINAL ) ) )
1262 keysOk = false;
1264 if( keysOk ) {
1265 return keyIds;
1267 else {
1268 bool rememberChoice;
1269 keyIds = selectKeys( rememberChoice, mPublicKeys,
1270 i18n("Encryption Key Selection"),
1271 i18nc("if in your language something like "
1272 "'key(s)' isn't possible please "
1273 "use the plural in the translation",
1274 "There is a problem with the "
1275 "encryption key(s) for \"%1\".\n\n"
1276 "Please re-select the key(s) which should "
1277 "be used for this recipient."
1278 , person),
1279 keyIds,
1280 allowedKeys );
1281 if( !keyIds.isEmpty() ) {
1282 if( rememberChoice ) {
1283 setKeysForAddress( person, keyIds );
1285 return keyIds;
1290 // Now search all public keys for matching keys
1291 KeyList::Iterator it = mPublicKeys.begin();
1292 KeyList matchingKeys;
1294 // search all keys which match the complete address
1295 kDebug( 5326 ) <<"Looking for keys matching" << person <<" ...";
1296 for( ; it != mPublicKeys.end(); ++it ) {
1297 // search case insensitively in the list of userIDs of this key
1298 if( (*it)->matchesUserID( person, false ) ) {
1299 keyTrust( (*it)->primaryKeyID() ); // this is called to make sure that
1300 // the trust info for this key is read
1301 if( ( (*it)->isValidEncryptionKey() ) &&
1302 ( (*it)->keyTrust() >= KPGP_VALIDITY_MARGINAL ) ) {
1303 kDebug( 5326 ) <<"Matching trusted key found:"
1304 << (*it)->primaryKeyID();
1305 matchingKeys.append( *it );
1310 // if no keys match the complete address look for keys which match
1311 // the canonical mail address
1312 kDebug( 5326 ) <<"Looking for keys matching" << address <<" ...";
1313 if( matchingKeys.isEmpty() ) {
1314 for ( it = mPublicKeys.begin(); it != mPublicKeys.end(); ++it ) {
1315 // search case insensitively in the list of userIDs of this key
1316 if( (*it)->matchesUserID( address, false ) ) {
1317 keyTrust( (*it)->primaryKeyID() ); // this is called to make sure that
1318 // the trust info for this key is read
1319 if( ( (*it)->isValidEncryptionKey() ) &&
1320 ( (*it)->keyTrust() >= KPGP_VALIDITY_MARGINAL ) ) {
1321 kDebug( 5326 ) <<"Matching trusted key found:"
1322 << (*it)->primaryKeyID();
1323 matchingKeys.append( *it );
1329 // no match until now, let the user choose the key
1330 if( matchingKeys.isEmpty() ) {
1331 // FIXME: let user get the key from keyserver
1332 bool rememberChoice;
1333 KeyIDList keyIds = selectKeys( rememberChoice, mPublicKeys,
1334 i18n("Encryption Key Selection"),
1335 i18nc("if in your language something like "
1336 "'key(s)' isn't possible please "
1337 "use the plural in the translation",
1338 "No valid and trusted OpenPGP key was "
1339 "found for \"%1\".\n\n"
1340 "Select the key(s) which should "
1341 "be used for this recipient."
1342 , person),
1343 KeyIDList(),
1344 allowedKeys );
1345 if( !keyIds.isEmpty() ) {
1346 if( rememberChoice ) {
1347 setKeysForAddress( person, keyIds );
1349 return keyIds;
1352 // only one key matches
1353 else if( matchingKeys.count() == 1 ) {
1354 return KeyIDList( matchingKeys.first()->primaryKeyID() );
1356 // more than one key matches; let the user choose the key(s)
1357 else {
1358 bool rememberChoice;
1359 KeyIDList keyIds = selectKeys( rememberChoice, matchingKeys,
1360 i18n("Encryption Key Selection"),
1361 i18nc("if in your language something like "
1362 "'key(s)' isn't possible please "
1363 "use the plural in the translation",
1364 "More than one key matches \"%1\".\n\n"
1365 "Select the key(s) which should "
1366 "be used for this recipient."
1367 , person),
1368 KeyIDList(),
1369 allowedKeys );
1370 if( !keyIds.isEmpty() ) {
1371 if( rememberChoice ) {
1372 setKeysForAddress( person, keyIds );
1374 return keyIds;
1378 return KeyIDList();
1381 // check if pgp 2.6.x or 5.0 is installed
1382 // kpgp will prefer to user pgp 5.0
1383 bool
1384 Module::checkForPGP(void)
1386 // get path
1387 QString path;
1388 QStringList pSearchPaths;
1390 havePgp=false;
1392 path = QString::fromLocal8Bit( getenv("PATH") );
1393 pSearchPaths = path.split( KPATH_SEPARATOR, QString::SkipEmptyParts );
1395 haveGpg=false;
1396 // lets try gpg
1398 foreach( const QString& curPath, pSearchPaths )
1400 path = curPath;
1401 path += "/gpg";
1402 if ( QFileInfo(path).isExecutable() )
1404 kDebug( 5326 ) <<"Kpgp: gpg found";
1405 havePgp=true;
1406 haveGpg=true;
1407 break;
1411 // search for pgp5.0
1412 havePGP5=false;
1413 foreach( const QString& curPath, pSearchPaths )
1415 path = curPath;
1416 path += "/pgpe";
1417 if ( QFileInfo(path).isExecutable() )
1419 kDebug( 5326 ) <<"Kpgp: pgp 5 found";
1420 havePgp=true;
1421 havePGP5=true;
1422 break;
1426 // lets try pgp2.6.x
1427 if (!havePgp) {
1428 foreach( const QString& curPath, pSearchPaths )
1430 path = curPath;
1431 path += "/pgp";
1432 if ( QFileInfo(path).isExecutable() )
1434 kDebug( 5326 ) <<"Kpgp: pgp 2 or 6 found";
1435 havePgp=true;
1436 break;
1441 if (!havePgp)
1443 kDebug( 5326 ) <<"Kpgp: no pgp found";
1446 return havePgp;
1449 void
1450 Module::assignPGPBase(void)
1452 if (pgp)
1453 delete pgp;
1455 if(havePgp)
1457 switch (pgpType)
1459 case tGPG:
1460 kDebug( 5326 ) <<"Kpgp: assign pgp - gpg";
1461 pgp = new BaseG();
1462 break;
1464 case tPGP2:
1465 kDebug( 5326 ) <<"Kpgp: assign pgp - pgp 2";
1466 pgp = new Base2();
1467 break;
1469 case tPGP5:
1470 kDebug( 5326 ) <<"Kpgp: assign pgp - pgp 5";
1471 pgp = new Base5();
1472 break;
1474 case tPGP6:
1475 kDebug( 5326 ) <<"Kpgp: assign pgp - pgp 6";
1476 pgp = new Base6();
1477 break;
1479 case tOff:
1480 // dummy handler
1481 kDebug( 5326 ) <<"Kpgp: pgpBase is dummy";
1482 pgp = new Base();
1483 break;
1485 case tAuto:
1486 kDebug( 5326 ) <<"Kpgp: assign pgp - auto";
1487 // fall through
1488 default:
1489 kDebug( 5326 ) <<"Kpgp: assign pgp - default";
1490 if (haveGpg)
1492 kDebug( 5326 ) <<"Kpgp: pgpBase is gpg";
1493 pgp = new BaseG();
1494 pgpType = tGPG;
1496 else if(havePGP5)
1498 kDebug( 5326 ) <<"Kpgp: pgpBase is pgp 5";
1499 pgp = new Base5();
1500 pgpType = tPGP5;
1502 else
1504 Base6 *pgp_v6 = new Base6();
1505 if (!pgp_v6->isVersion6())
1507 kDebug( 5326 ) <<"Kpgp: pgpBase is pgp 2";
1508 delete pgp_v6;
1509 pgp = new Base2();
1510 pgpType = tPGP2;
1512 else
1514 kDebug( 5326 ) <<"Kpgp: pgpBase is pgp 6";
1515 pgp = pgp_v6;
1516 pgpType = tPGP6;
1519 } // switch
1521 else
1523 // dummy handler
1524 kDebug( 5326 ) <<"Kpgp: pgpBase is dummy";
1525 pgp = new Base();
1526 pgpType = tOff;
1530 QString
1531 Module::canonicalAddress( const QString& _adress )
1533 int index,index2;
1535 QString address = _adress.simplified();
1536 address = address.trimmed();
1538 // just leave pure e-mail address.
1539 if((index = address.indexOf("<")) != -1)
1540 if((index2 = address.indexOf("@",index+1)) != -1)
1541 if((index2 = address.indexOf(">",index2+1)) != -1)
1542 return address.mid(index,index2-index+1);
1544 if((index = address.indexOf("@")) == -1)
1546 // local address
1547 //char hostname[1024];
1548 //gethostname(hostname,1024);
1549 //return "<" + address + "@" + hostname + ">";
1550 return '<' + address + "@localdomain>";
1552 else
1554 int index1 = address.lastIndexOf(" ",index);
1555 int index2 = address.indexOf(" ",index);
1556 if(index2 == -1) index2 = address.length();
1557 return '<' + address.mid(index1+1 ,index2-index1-1) + '>';
1561 void
1562 Module::readPublicKeys( bool reread )
1564 if( 0 == pgp ) assignPGPBase();
1566 if( !usePGP() )
1568 qDeleteAll( mPublicKeys );
1569 mPublicKeys.clear();
1570 mPublicKeysCached = false;
1571 return;
1574 if( !mPublicKeysCached || reread )
1576 if( mPublicKeys.isEmpty() )
1578 mPublicKeys = pgp->publicKeys();
1580 else
1582 KeyList newPublicKeyList = pgp->publicKeys();
1584 // merge the trust info from the old key list into the new key list
1585 // FIXME: This is currently O(K^2) where K = #keys. As the key lists
1586 // are sorted this can be done in O(K).
1587 for( KeyList::Iterator it = newPublicKeyList.begin(); it != newPublicKeyList.end(); ++it )
1589 Key* oldKey = publicKey( (*it)->primaryKeyID() );
1590 if( oldKey )
1592 (*it)->cloneKeyTrust( oldKey );
1596 qDeleteAll( mPublicKeys );
1597 mPublicKeys = newPublicKeyList;
1600 mPublicKeysCached = true;
1604 void
1605 Module::readSecretKeys( bool reread )
1607 if( 0 == pgp ) assignPGPBase();
1609 if( !usePGP() )
1611 qDeleteAll( mSecretKeys );
1612 mSecretKeys.clear();
1613 mSecretKeysCached = false;
1614 return;
1617 if( mSecretKeys.isEmpty() || reread )
1619 if( mSecretKeys.isEmpty() )
1621 mSecretKeys = pgp->secretKeys();
1623 else
1625 KeyList newSecretKeyList = pgp->secretKeys();
1627 // merge the trust info from the old key list into the new key list
1628 // FIXME: This is currently O(K^2) where K = #keys. As the key lists
1629 // are sorted this can be done in O(K).
1630 for( KeyList::Iterator it = newSecretKeyList.begin(); it != newSecretKeyList.end(); ++it )
1632 Key* oldKey = secretKey( (*it)->primaryKeyID() );
1633 if( oldKey )
1635 (*it)->cloneKeyTrust( oldKey );
1639 qDeleteAll( mSecretKeys );
1640 mSecretKeys = newSecretKeyList;
1643 mSecretKeysCached = true;
1647 KeyID
1648 Module::selectKey( const KeyList& keys,
1649 const QString& title,
1650 const QString& text /*=QString() */ ,
1651 const KeyID& keyId /* = KeyID() */ ,
1652 const unsigned int allowedKeys /* = AllKeys */ )
1654 KeyID retval = KeyID();
1656 #ifndef QT_NO_TREEWIDGET
1657 KeySelectionDialog dlg( keys, title, text, KeyIDList( keyId ), false,
1658 allowedKeys, false );
1660 #ifndef QT_NO_CURSOR
1661 QApplication::setOverrideCursor( QCursor(Qt::ArrowCursor) );
1662 #endif
1663 bool rej = ( dlg.exec() == QDialog::Rejected );
1664 #ifndef QT_NO_CURSOR
1665 QApplication::restoreOverrideCursor();
1666 #endif
1668 if( !rej ) {
1669 retval = dlg.key();
1671 #endif
1673 return retval;
1676 KeyIDList
1677 Module::selectKeys( const KeyList& keys,
1678 const QString& title,
1679 const QString& text /*=QString() */ ,
1680 const KeyIDList& keyIds /* = KeyIDList() */ ,
1681 const unsigned int allowedKeys /* = AllKeys */ )
1683 KeyIDList retval = KeyIDList();
1685 #ifndef QT_NO_TREEWIDGET
1686 KeySelectionDialog dlg( keys, title, text, keyIds, false, allowedKeys,
1687 true );
1689 #ifndef QT_NO_CURSOR
1690 QApplication::setOverrideCursor( QCursor(Qt::ArrowCursor) );
1691 #endif
1692 bool rej = ( dlg.exec() == QDialog::Rejected );
1693 #ifndef QT_NO_CURSOR
1694 QApplication::restoreOverrideCursor();
1695 #endif
1697 if( !rej ) {
1698 retval = dlg.keys();
1700 #endif
1702 return retval;
1706 KeyID
1707 Module::selectKey( bool& rememberChoice,
1708 const KeyList& keys,
1709 const QString& title,
1710 const QString& text /*=QString() */ ,
1711 const KeyID& keyId /* = KeyID() */ ,
1712 const unsigned int allowedKeys /* = AllKeys */ )
1714 KeyID retval = KeyID();
1716 #ifndef QT_NO_TREEWIDGET
1717 KeySelectionDialog dlg( keys, title, text, KeyIDList( keyId ), false,
1718 allowedKeys, false );
1720 #ifndef QT_NO_CURSOR
1721 QApplication::setOverrideCursor( QCursor(Qt::ArrowCursor) );
1722 #endif
1723 bool rej = ( dlg.exec() == QDialog::Rejected );
1724 #ifndef QT_NO_CURSOR
1725 QApplication::restoreOverrideCursor();
1726 #endif
1728 if( !rej ) {
1729 retval = dlg.key();
1730 rememberChoice = dlg.rememberSelection();
1732 else {
1733 rememberChoice = false;
1735 #endif
1737 return retval;
1740 KeyIDList
1741 Module::selectKeys( bool& rememberChoice,
1742 const KeyList& keys,
1743 const QString& title,
1744 const QString& text /*=QString() */ ,
1745 const KeyIDList& keyIds /* = KeyIDList() */ ,
1746 const unsigned int allowedKeys /* = AllKeys */ )
1748 KeyIDList retval = KeyIDList();
1750 #ifndef QT_NO_TREEWIDGET
1751 KeySelectionDialog dlg( keys, title, text, keyIds, true, allowedKeys,
1752 true );
1754 #ifndef QT_NO_CURSOR
1755 QApplication::setOverrideCursor( QCursor(Qt::ArrowCursor) );
1756 #endif
1757 bool rej = ( dlg.exec() == QDialog::Rejected );
1758 #ifndef QT_NO_CURSOR
1759 QApplication::restoreOverrideCursor();
1760 #endif
1762 if( !rej ) {
1763 retval = dlg.keys();
1764 rememberChoice = dlg.rememberSelection();
1766 else {
1767 rememberChoice = false;
1769 #endif
1771 return retval;
1774 KeyIDList
1775 Module::keysForAddress( const QString& address )
1777 if( address.isEmpty() ) {
1778 return KeyIDList();
1780 QString addr = canonicalAddress( address ).toLower();
1781 if( addressDataDict.contains( addr ) ) {
1782 return addressDataDict[addr].keyIds;
1784 else {
1785 return KeyIDList();
1789 void
1790 Module::setKeysForAddress( const QString& address, const KeyIDList& keyIds )
1792 if( address.isEmpty() ) {
1793 return;
1795 QString addr = canonicalAddress( address ).toLower();
1796 if( addressDataDict.contains( addr ) ) {
1797 addressDataDict[addr].keyIds = keyIds;
1799 else {
1800 AddressData data;
1801 data.encrPref = UnknownEncryptPref;
1802 data.keyIds = keyIds;
1803 addressDataDict.insert( addr, data );
1806 //writeAddressData();
1809 void
1810 Module::readAddressData()
1812 QString address;
1813 AddressData data;
1815 KConfigGroup general( config, "General" );
1816 int num = general.readEntry( "addressEntries", 0 );
1818 addressDataDict.clear();
1819 for( int i=1; i<=num; i++ ) {
1820 KConfigGroup addrGroup( config, QString("Address #%1").arg(i) );
1821 address = addrGroup.readEntry( "Address" );
1822 data.keyIds = KeyIDList::fromStringList( addrGroup.readEntry( "Key IDs" , QStringList() ) );
1823 data.encrPref = (EncryptPref) addrGroup.readEntry( "EncryptionPreference",
1824 int(UnknownEncryptPref ));
1825 // kDebug( 5326 ) <<"Read address" << i <<":" << address
1826 // << "\nKey IDs: 0x" << data.keyIds.toStringList().join(", 0x")
1827 // << "\nEncryption preference:" << data.encrPref;
1828 if ( !address.isEmpty() ) {
1829 addressDataDict.insert( address, data );
1834 void
1835 Module::writeAddressData()
1837 KConfigGroup general( config, "General" );
1838 general.writeEntry( "addressEntries", addressDataDict.count() );
1840 int i;
1841 AddressDataDict::Iterator it;
1842 for ( i=1, it = addressDataDict.begin();
1843 it != addressDataDict.end();
1844 ++it, i++ ) {
1845 KConfigGroup addrGroup( config, QString("Address #%1").arg(i));
1846 addrGroup.writeEntry( "Address", it.key() );
1847 addrGroup.writeEntry( "Key IDs", it.value().keyIds.toStringList() );
1848 addrGroup.writeEntry( "EncryptionPreference", (int)it.value().encrPref );
1851 config->sync();
1854 EncryptPref
1855 Module::encryptionPreference( const QString& address )
1857 QString addr = canonicalAddress( address ).toLower();
1858 if( addressDataDict.contains( addr ) ) {
1859 return addressDataDict[addr].encrPref;
1861 else {
1862 return UnknownEncryptPref;
1866 void
1867 Module::setEncryptionPreference( const QString& address,
1868 const EncryptPref pref )
1870 if( address.isEmpty() ) {
1871 return;
1873 QString addr = canonicalAddress( address ).toLower();
1874 if( addressDataDict.contains( addr ) ) {
1875 addressDataDict[addr].encrPref = pref;
1877 else {
1878 AddressData data;
1879 data.encrPref = pref;
1880 addressDataDict.insert( addr, data );
1884 } // namespace Kpgp