33 #include <config-kleopatra.h>
45 #include <kleo/stl_util.h>
46 #include <kleo/cryptobackendfactory.h>
48 #include <kleo/keylistjob.h>
49 #include <kleo/listallkeysjob.h>
51 #include <gpgme++/error.h>
52 #include <gpgme++/key.h>
53 #include <gpgme++/decryptionresult.h>
54 #include <gpgme++/verificationresult.h>
55 #include <gpgme++/keylistresult.h>
57 #include <gpg-error.h>
59 #include <kmime/kmime_header_parsing.h>
64 #include <QStringList>
67 #include <boost/bind.hpp>
68 #include <boost/mem_fn.hpp>
69 #include <boost/range.hpp>
70 #include <boost/weak_ptr.hpp>
71 #include <boost/iterator/filter_iterator.hpp>
79 using namespace GpgME;
80 using namespace boost;
81 using namespace KMime::Types;
83 static const unsigned int hours2ms = 1000 * 60 * 60;
95 struct is_string_empty : std::unary_function<const char*,bool> {
96 bool operator()(
const char * s )
const {
return !s || !*s; }
101 class KeyCache::Private {
102 friend class ::Kleo::KeyCache;
105 explicit Private(
KeyCache * qq ) :
q( qq ) {
106 connect( &m_autoKeyListingTimer, SIGNAL(timeout()),
q, SLOT(startKeyListing()) );
107 updateAutoKeyListingTimer();
110 template <
template <
template <
typename U>
class Op>
class Comp>
111 std::vector<Key>::const_iterator find( const std::vector<Key> & keys, const char * key ) const {
112 const std::vector<Key>::const_iterator it =
113 std::lower_bound( keys.begin(), keys.end(), key, Comp<std::less>() );
114 if ( it == keys.end() || Comp<std::equal_to>()( *it, key ) )
120 template <
template <
template <
typename U>
class Op>
class Comp>
121 std::vector<Subkey>::const_iterator find( const std::vector<Subkey> & keys, const char * key ) const {
122 const std::vector<Subkey>::const_iterator it =
123 std::lower_bound( keys.begin(), keys.end(), key, Comp<std::less>() );
124 if ( it == keys.end() || Comp<std::equal_to>()( *it, key ) )
130 std::vector<Key>::const_iterator find_fpr(
const char * fpr )
const {
131 return find<_detail::ByFingerprint>( by.fpr, fpr );
134 std::pair< std::vector< std::pair<std::string,Key> >::const_iterator,
135 std::vector< std::pair<std::string,Key> >::const_iterator >
136 find_email(
const char *
email )
const {
137 return std::equal_range( by.email.begin(), by.email.end(),
138 email, ByEMail<std::less>() );
141 std::vector<Key> find_mailbox(
const Mailbox & mb,
bool sign )
const;
143 std::vector<Subkey>::const_iterator find_subkeyid(
const char * subkeyid )
const {
144 return find<_detail::ByKeyID>( by.subkeyid, subkeyid );
147 std::vector<Key>::const_iterator find_keyid(
const char * keyid )
const {
148 return find<_detail::ByKeyID>( by.keyid, keyid );
151 std::vector<Key>::const_iterator find_shortkeyid(
const char * shortkeyid )
const {
152 return find<_detail::ByShortKeyID>( by.shortkeyid, shortkeyid );
156 std::vector<Key>::const_iterator,
157 std::vector<Key>::const_iterator
158 > find_subjects(
const char * chain_id )
const {
159 return std::equal_range( by.chainid.begin(), by.chainid.end(),
160 chain_id, _detail::ByChainID<std::less>() );
163 void refreshJobDone(
const KeyListResult & result );
166 void updateAutoKeyListingTimer() {
169 void setAutoKeyListingInterval(
int ms ) {
170 m_autoKeyListingTimer.stop();
171 m_autoKeyListingTimer.setInterval( ms );
173 m_autoKeyListingTimer.start();
177 QPointer<RefreshKeysJob> m_refreshJob;
178 std::vector<shared_ptr<FileSystemWatcher> > m_fsWatchers;
179 QTimer m_autoKeyListingTimer;
182 std::vector<Key> fpr, keyid, shortkeyid, chainid;
183 std::vector< std::pair<std::string,Key> >
email;
184 std::vector<Subkey> subkeyid;
190 return mutableInstance();
194 static weak_ptr<KeyCache>
self;
197 }
catch (
const bad_weak_ptr & ) {
205 : QObject(),
d( new Private( this ) )
215 i->setEnabled( enable );
220 if ( d->m_refreshJob )
223 d->updateAutoKeyListingTimer();
227 connect( d->m_refreshJob, SIGNAL(done(GpgME::KeyListResult)),
this, SLOT(refreshJobDone(GpgME::KeyListResult)) );
228 d->m_refreshJob->start();
233 if ( !d->m_refreshJob )
235 d->m_refreshJob->cancel();
242 d->m_fsWatchers.push_back( watcher );
243 connect( watcher.get(), SIGNAL(directoryChanged(QString)),
245 connect( watcher.get(), SIGNAL(fileChanged(QString)),
248 watcher->setEnabled( d->m_refreshJob == 0 );
251 void KeyCache::Private::refreshJobDone(
const KeyListResult& result )
253 emit
q->keyListingDone( result );
254 q->enableFileSystemWatcher(
true );
258 const std::vector<Key>::const_iterator it = d->find_fpr( fpr );
259 if ( it == d->by.fpr.end() ) {
260 static const Key null;
268 std::vector<std::string> sorted;
269 sorted.reserve( fprs.size() );
270 std::remove_copy_if( fprs.begin(), fprs.end(), std::back_inserter( sorted ),
271 boost::bind( is_string_empty(), boost::bind( &std::string::c_str, _1 ) ) );
273 std::sort( sorted.begin(), sorted.end(), _detail::ByFingerprint<std::less>() );
275 std::vector<Key> result;
276 kdtools::set_intersection( d->by.fpr.begin(), d->by.fpr.end(),
277 sorted.begin(), sorted.end(),
278 std::back_inserter( result ),
279 _detail::ByFingerprint<std::less>() );
285 std::vector< std::pair<std::string,Key> >::const_iterator,
286 std::vector< std::pair<std::string,Key> >::const_iterator
287 > pair = d->find_email( email );
288 std::vector<Key> result;
289 result.reserve( std::distance( pair.first, pair.second ) );
290 std::transform( pair.first, pair.second,
291 std::back_inserter( result ),
292 boost::bind( &std::pair<std::string,Key>::second, _1 ) );
301 const std::vector<Key>::const_iterator it = d->find_shortkeyid(
id );
302 if ( it != d->by.shortkeyid.end() )
304 static const Key null;
311 const std::vector<Key>::const_iterator it = d->find_fpr(
id );
312 if ( it != d->by.fpr.end() )
316 const std::vector<Key>::const_iterator it = d->find_keyid(
id );
317 if ( it != d->by.keyid.end() )
320 static const Key null;
326 std::vector<std::string> keyids;
327 std::remove_copy_if( ids.begin(), ids.end(), std::back_inserter( keyids ),
328 boost::bind( is_string_empty(), boost::bind( &std::string::c_str, _1 ) ) );
331 std::sort( keyids.begin(), keyids.end(), _detail::ByFingerprint<std::less>() );
333 std::vector<Key> result;
334 result.reserve( keyids.size() );
336 kdtools::set_intersection( d->by.fpr.begin(), d->by.fpr.end(),
337 keyids.begin(), keyids.end(),
338 std::back_inserter( result ),
339 _detail::ByFingerprint<std::less>() );
340 if ( result.size() < keyids.size() ) {
343 kdtools::set_intersection( d->by.keyid.begin(), d->by.keyid.end(),
344 keyids.begin(), keyids.end(),
345 std::back_inserter( result ),
346 _detail::ByKeyID<std::less>() );
349 std::sort( result.begin(), result.end(), _detail::ByFingerprint<std::less>() );
350 result.erase( std::unique( result.begin(), result.end(), _detail::ByFingerprint<std::equal_to>() ), result.end() );
360 std::vector<std::string> sorted;
361 sorted.reserve( ids.size() );
362 std::remove_copy_if( ids.begin(), ids.end(), std::back_inserter( sorted ),
363 boost::bind( is_string_empty(), boost::bind( &std::string::c_str, _1 ) ) );
365 std::sort( sorted.begin(), sorted.end(), _detail::ByKeyID<std::less>() );
367 std::vector<Subkey> result;
368 kdtools::set_intersection( d->by.subkeyid.begin(), d->by.subkeyid.end(),
369 sorted.begin(), sorted.end(),
370 std::back_inserter( result ),
371 _detail::ByKeyID<std::less>() );
376 std::vector<std::string> keyids;
377 Q_FOREACH(
const DecryptionResult::Recipient & r, res.recipients() )
378 if (
const char * kid = r.keyID() )
379 keyids.push_back( kid );
381 std::vector<Key> result;
382 result.reserve( subkeys.size() );
383 std::transform( subkeys.begin(), subkeys.end(), std::back_inserter( result ), boost::bind( &Subkey::parent, _1 ) );
385 std::sort( result.begin(), result.end(), _detail::ByFingerprint<std::less>() );
386 result.erase( std::unique( result.begin(), result.end(), _detail::ByFingerprint<std::equal_to>() ), result.end() );
391 std::vector<std::string> fprs;
392 Q_FOREACH(
const Signature & s, res.signatures() )
393 if (
const char * fpr = s.fingerprint() )
394 fprs.push_back( fpr );
399 return d->find_mailbox( mb,
true );
403 return d->find_mailbox( mb,
false );
407 #define DO( op, meth, meth2 ) if ( op key.meth() ) {} else { qDebug( "rejecting for signing: %s: %s", #meth2, key.primaryFingerprint() ); return false; }
408 #define ACCEPT( meth ) DO( !!, meth, !meth )
409 #define REJECT( meth ) DO( !, meth, meth )
410 struct ready_for_signing : std::unary_function<Key,bool> {
411 bool operator()(
const Key & key )
const {
421 return key.hasSecret() &&
422 key.canReallySign() && !key.isRevoked() && !key.isExpired() && !key.isDisabled() && !key.isInvalid() ;
428 struct ready_for_encryption : std::unary_function<Key,bool> {
429 #define DO( op, meth, meth2 ) if ( op key.meth() ) {} else { qDebug( "rejecting for encrypting: %s: %s", #meth2, key.primaryFingerprint() ); return false; }
430 bool operator()(
const Key & key )
const {
440 key.canEncrypt() && !key.isRevoked() && !key.isExpired() && !key.isDisabled() && !key.isInvalid() ;
449 std::vector<Key> KeyCache::Private::find_mailbox(
const Mailbox & mb,
bool sign )
const {
450 const QString email = mb.addrSpec().asString();
451 if ( email.isEmpty() )
452 return std::vector<Key>();
455 std::vector< std::pair<std::string,Key> >::const_iterator,
456 std::vector< std::pair<std::string,Key> >::const_iterator
457 > pair = find_email( email.toUtf8().constData() );
459 std::vector<Key> result;
460 result.reserve( std::distance( pair.first, pair.second ) );
462 kdtools::copy_2nd_if( pair.first, pair.second,
463 std::back_inserter( result ),
464 ready_for_signing() );
466 kdtools::copy_2nd_if( pair.first, pair.second,
467 std::back_inserter( result ),
468 ready_for_encryption() );
473 return findSubjects( std::vector<Key>( 1, key ), options );
477 return findSubjects( keys.begin(), keys.end(), options );
480 std::vector<Key>
KeyCache::findSubjects( std::vector<Key>::const_iterator first, std::vector<Key>::const_iterator last, Options options )
const {
483 return std::vector<Key>();
485 std::vector<Key> result;
486 while ( first != last ) {
488 std::vector<Key>::const_iterator,
489 std::vector<Key>::const_iterator
490 > pair = d->find_subjects( first->primaryFingerprint() );
491 result.insert( result.end(), pair.first, pair.second );
495 std::sort( result.begin(), result.end(), _detail::ByFingerprint<std::less>() );
496 result.erase( std::unique( result.begin(), result.end(), _detail::ByFingerprint<std::equal_to>() ), result.end() );
499 const std::vector<Key> furtherSubjects =
findSubjects( result, options );
500 std::vector<Key> combined;
501 combined.reserve( result.size() + furtherSubjects.size() );
502 std::merge( result.begin(), result.end(),
503 furtherSubjects.begin(), furtherSubjects.end(),
504 std::back_inserter( combined ),
505 _detail::ByFingerprint<std::less>() );
506 combined.erase( std::unique( combined.begin(), combined.end(), _detail::ByFingerprint<std::equal_to>() ), combined.end() );
507 result.swap( combined );
518 return std::vector<Key>();
520 std::vector<Key> result;
522 result.push_back( key );
529 if ( issuer.isNull() )
532 result.push_back( issuer );
534 if ( !( options & RecursiveSearch ) )
537 while ( !result.back().isNull() && !result.back().isRoot() )
540 if ( result.back().isNull() )
547 return findIssuers( keys.begin(), keys.end(), options );
550 std::vector<Key>
KeyCache::findIssuers( std::vector<Key>::const_iterator first, std::vector<Key>::const_iterator last, Options options )
const {
553 return std::vector<Key>();
556 std::vector<const char *> chainIDs;
557 chainIDs.reserve( last - first );
558 std::transform( boost::make_filter_iterator( !boost::bind( &Key::isRoot, _1 ), first, last ),
559 boost::make_filter_iterator( !boost::bind( &Key::isRoot, _1 ), last, last ),
560 std::back_inserter( chainIDs ),
561 boost::bind( &Key::chainID, _1 ) );
562 std::sort( chainIDs.begin(), chainIDs.end(), _detail::ByFingerprint<std::less>() );
564 const std::vector<const char*>::iterator lastUniqueChainID = std::unique( chainIDs.begin(), chainIDs.end(), _detail::ByFingerprint<std::less>() );
566 std::vector<Key> result;
567 result.reserve( lastUniqueChainID - chainIDs.begin() );
569 kdtools::set_intersection( d->by.fpr.begin(), d->by.fpr.end(),
570 chainIDs.begin(), lastUniqueChainID,
571 std::back_inserter( result ),
572 _detail::ByFingerprint<std::less>() );
575 const unsigned int rs = result.size();
576 result.insert( result.end(), first, last );
577 std::inplace_merge( result.begin(), result.begin() + rs, result.end(),
578 _detail::ByFingerprint<std::less>() );
581 if ( !( options & RecursiveSearch ) )
584 const std::vector<Key> l2result =
findIssuers( result, options & ~IncludeSubject );
586 const unsigned long result_size = result.size();
587 result.insert( result.end(), l2result.begin(), l2result.end() );
588 std::inplace_merge( result.begin(), result.begin() + result_size, result.end(),
589 _detail::ByFingerprint<std::less>() );
596 return DN( uid.id() )[QLatin1String(
"EMAIL")].trimmed().toUtf8().constData();
597 if ( email[0] ==
'<' && email[email.size()-1] ==
'>' )
598 return email.substr( 1, email.size() - 2 );
603 static std::vector<std::string>
emails(
const Key & key ) {
604 std::vector<std::string>
emails;
605 Q_FOREACH(
const UserID & uid, key.userIDs() ) {
608 emails.push_back( e );
610 std::sort( emails.begin(), emails.end(), ByEMail<std::less>() );
611 emails.erase( std::unique( emails.begin(), emails.end(), ByEMail<std::equal_to>() ), emails.end() );
619 const char * fpr = key.primaryFingerprint();
626 const std::pair<std::vector<Key>::iterator,std::vector<Key>::iterator> range
627 = std::equal_range( d->by.fpr.begin(), d->by.fpr.end(), fpr,
628 _detail::ByFingerprint<std::less>() );
629 d->by.fpr.erase( range.first, range.second );
632 if (
const char * keyid = key.keyID() ) {
633 const std::pair<std::vector<Key>::iterator,std::vector<Key>::iterator> range
634 = std::equal_range( d->by.keyid.begin(), d->by.keyid.end(), keyid,
635 _detail::ByKeyID<std::less>() );
636 const std::vector<Key>::iterator it
637 = std::remove_if( begin( range ), end( range ), boost::bind( _detail::ByFingerprint<std::equal_to>(), fpr, _1 ) );
638 d->by.keyid.erase( it, end( range ) );
641 if (
const char * shortkeyid = key.shortKeyID() ) {
642 const std::pair<std::vector<Key>::iterator,std::vector<Key>::iterator> range
643 = std::equal_range( d->by.shortkeyid.begin(), d->by.shortkeyid.end(), shortkeyid,
644 _detail::ByShortKeyID<std::less>() );
645 const std::vector<Key>::iterator it
646 = std::remove_if( begin( range ), end( range ), boost::bind( _detail::ByFingerprint<std::equal_to>(), fpr, _1 ) );
647 d->by.shortkeyid.erase( it, end( range ) );
650 if (
const char * chainid = key.chainID() ) {
651 const std::pair<std::vector<Key>::iterator,std::vector<Key>::iterator> range
652 = std::equal_range( d->by.chainid.begin(), d->by.chainid.end(), chainid,
653 _detail::ByChainID<std::less>() );
654 const std::pair< std::vector<Key>::iterator, std::vector<Key>::iterator > range2
655 = std::equal_range( begin( range ), end( range ), fpr, _detail::ByFingerprint<std::less>() );
656 d->by.chainid.erase( begin( range2 ), end( range2 ) );
661 const std::pair<std::vector<std::pair<std::string,Key> >::iterator,std::vector<std::pair<std::string,Key> >::iterator> range
662 = std::equal_range( d->by.email.begin(), d->by.email.end(),
email, ByEMail<std::less>() );
663 const std::vector< std::pair<std::string,Key> >::iterator it
664 = std::remove_if( begin( range ), end( range ), boost::bind( qstricmp, fpr, boost::bind( &Key::primaryFingerprint, boost::bind( &std::pair<std::string,Key>::second,_1 ) ) ) == 0 );
665 d->by.email.erase( it, end( range ) );
668 Q_FOREACH(
const Subkey & subkey, key.subkeys() ) {
669 if (
const char * keyid = subkey.keyID() ) {
670 const std::pair<std::vector<Subkey>::iterator,std::vector<Subkey>::iterator> range
671 = std::equal_range( d->by.subkeyid.begin(), d->by.subkeyid.end(), keyid,
672 _detail::ByKeyID<std::less>() );
673 const std::pair< std::vector<Subkey>::iterator, std::vector<Subkey>::iterator > range2
674 = std::equal_range( begin( range ), end( range ), fpr, _detail::ByKeyID<std::less>() );
675 d->by.subkeyid.erase( begin( range2 ), end( range2 ) );
681 Q_FOREACH(
const Key & key, keys )
685 const std::vector<GpgME::Key> &
KeyCache::keys()
const
692 std::vector<Key> keys = this->
keys();
693 keys.erase( std::remove_if( keys.begin(), keys.end(), !boost::bind( &Key::hasSecret, _1 ) ), keys.end() );
704 insert( std::vector<Key>( 1, key ) );
710 template <
template <
typename T>
class Op>
class T1,
711 template <template <typename T> class Op> class T2
712 > struct lexicographically {
713 typedef bool result_type;
715 template <
typename U,
typename V>
716 bool operator()(
const U & lhs,
const V & rhs )
const {
718 T1<std::less>()( lhs, rhs ) ||
719 ( T1<std::equal_to>()( lhs, rhs ) &&
720 T2<std::less>()( lhs, rhs ) )
730 std::vector<Key> sorted;
731 sorted.reserve( keys.size() );
732 std::remove_copy_if( keys.begin(), keys.end(),
733 std::back_inserter( sorted ),
734 boost::bind( is_string_empty(), boost::bind( &Key::primaryFingerprint, _1 ) ) );
736 Q_FOREACH(
const Key & key, sorted )
740 std::sort( sorted.begin(), sorted.end(), _detail::ByFingerprint<std::less>() );
743 std::vector<Key> by_fpr;
744 by_fpr.reserve( sorted.size() + d->by.fpr.size() );
745 std::merge( sorted.begin(), sorted.end(),
746 d->by.fpr.begin(), d->by.fpr.end(),
747 std::back_inserter( by_fpr ),
748 _detail::ByFingerprint<std::less>() );
751 std::vector< std::pair<std::
string,Key> > pairs;
752 pairs.reserve( sorted.size() );
753 Q_FOREACH( const Key & key, sorted ) {
756 pairs.push_back( std::make_pair( e, key ) );
758 std::sort( pairs.begin(), pairs.end(), ByEMail<std::less>() );
761 std::vector< std::pair<std::
string,Key> > by_email;
762 by_email.reserve( pairs.size() + d->by.email.size() );
763 std::merge( pairs.begin(), pairs.end(),
764 d->by.email.begin(), d->by.email.end(),
765 std::back_inserter( by_email ),
766 ByEMail<std::less>() );
769 std::stable_sort( sorted.begin(), sorted.end(), _detail::ByChainID<std::less>() );
772 std::vector<Key> by_chainid;
773 by_chainid.reserve( sorted.size() + d->by.chainid.size() );
774 std::merge( boost::make_filter_iterator( !boost::bind( &Key::isRoot, _1 ), sorted.begin(), sorted.end() ),
775 boost::make_filter_iterator( !boost::bind( &Key::isRoot, _1 ), sorted.end(), sorted.end() ),
776 d->by.chainid.begin(), d->by.chainid.end(),
777 std::back_inserter( by_chainid ),
778 lexicographically<_detail::ByChainID,_detail::ByFingerprint>() );
781 std::sort( sorted.begin(), sorted.end(), _detail::ByKeyID<std::less>() );
784 std::vector<Key> by_keyid;
785 by_keyid.reserve( sorted.size() + d->by.keyid.size() );
786 std::merge( sorted.begin(), sorted.end(),
787 d->by.keyid.begin(), d->by.keyid.end(),
788 std::back_inserter( by_keyid ),
789 _detail::ByKeyID<std::less>() );
792 std::sort( sorted.begin(), sorted.end(), _detail::ByShortKeyID<std::less>() );
795 std::vector<Key> by_shortkeyid;
796 by_shortkeyid.reserve( sorted.size() + d->by.shortkeyid.size() );
797 std::merge( sorted.begin(), sorted.end(),
798 d->by.shortkeyid.begin(), d->by.shortkeyid.end(),
799 std::back_inserter( by_shortkeyid ),
800 _detail::ByShortKeyID<std::less>() );
803 std::vector<Subkey> subkeys;
804 subkeys.reserve( sorted.size() );
805 Q_FOREACH( const Key & key, sorted )
806 Q_FOREACH( const Subkey & subkey, key.subkeys() )
807 subkeys.push_back( subkey );
810 std::sort( subkeys.begin(), subkeys.end(), _detail::ByKeyID<std::less>() );
813 std::vector<Subkey> by_subkeyid;
814 by_email.reserve( subkeys.size() + d->by.subkeyid.size() );
815 std::merge( subkeys.begin(), subkeys.end(),
816 d->by.subkeyid.begin(), d->by.subkeyid.end(),
817 std::back_inserter( by_subkeyid ),
818 _detail::ByKeyID<std::less>() );
821 by_fpr.swap( d->by.fpr );
822 by_keyid.swap( d->by.keyid );
823 by_shortkeyid.swap( d->by.shortkeyid );
824 by_email.swap( d->by.email );
825 by_subkeyid.swap( d->by.subkeyid );
826 by_chainid.swap( d->by.chainid );
828 Q_FOREACH( const Key & key, sorted )
835 d->by = Private::By();
846 RefreshKeysJob *
const q;
848 Private(
KeyCache * cache, RefreshKeysJob * qq );
851 void listAllKeysJobDone(
const KeyListResult & res,
const std::vector<Key> & nextKeys ) {
852 std::vector<Key>
keys;
853 keys.reserve( m_keys.size() + nextKeys.size() );
854 if ( m_keys.empty() )
857 std::merge( m_keys.begin(), m_keys.end(),
858 nextKeys.begin(), nextKeys.end(),
859 std::back_inserter( keys ),
860 _detail::ByFingerprint<std::less>() );
864 void emitDone(
const KeyListResult & result );
865 void updateKeyCache();
869 std::vector<Key> m_keys;
870 KeyListResult m_mergedResult;
873 void jobDone(
const KeyListResult & res );
876 KeyCache::RefreshKeysJob::Private::Private(
KeyCache * cache, RefreshKeysJob * qq ) :
q( qq ), m_cache( cache ), m_jobsPending( 0 )
881 void KeyCache::RefreshKeysJob::Private::jobDone(
const KeyListResult & result )
883 QObject*
const sender =
q->sender();
885 sender->disconnect(
q );
886 assert( m_jobsPending > 0 );
888 m_mergedResult.mergeWith( result );
889 if ( m_jobsPending > 0 )
892 emitDone( m_mergedResult );
895 void KeyCache::RefreshKeysJob::Private::emitDone(
const KeyListResult & res )
910 QTimer::singleShot( 0,
this, SLOT(doStart()) );
918 void KeyCache::RefreshKeysJob::Private::doStart()
920 assert( m_jobsPending == 0 );
921 m_mergedResult.mergeWith( KeyListResult(
startKeyListing(
"openpgp" ) ) );
922 m_mergedResult.mergeWith( KeyListResult(
startKeyListing(
"smime" ) ) );
924 if ( m_jobsPending != 0 )
927 const bool hasError = m_mergedResult.error() || m_mergedResult.error().isCanceled();
928 emitDone( hasError ? m_mergedResult : KeyListResult( Error( GPG_ERR_UNSUPPORTED_OPERATION ) ) );
931 void KeyCache::RefreshKeysJob::Private::updateKeyCache()
933 std::vector<Key> cachedKeys = m_cache->keys();
934 std::sort( cachedKeys.begin(), cachedKeys.end(), _detail::ByFingerprint<std::less>() );
935 std::vector<Key> keysToRemove;
936 std::set_difference( cachedKeys.begin(), cachedKeys.end(),
937 m_keys.begin(), m_keys.end(),
938 std::back_inserter( keysToRemove ),
939 _detail::ByFingerprint<std::less>() );
940 m_cache->remove( keysToRemove );
941 m_cache->refresh( m_keys );
944 Error KeyCache::RefreshKeysJob::Private::startKeyListing(
const char* backend )
946 const Kleo::CryptoBackend::Protocol *
const protocol = Kleo::CryptoBackendFactory::instance()->protocol( backend );
949 Kleo::ListAllKeysJob *
const job = protocol->listAllKeysJob(
false,
true );
952 connect( job, SIGNAL(result(GpgME::KeyListResult,std::vector<GpgME::Key>)),
953 q, SLOT(listAllKeysJobDone(GpgME::KeyListResult,std::vector<GpgME::Key>)) );
955 const QString label = protocol == Kleo::CryptoBackendFactory::instance()->smime()
956 ? i18n(
"Listing X.509 certificates")
957 : i18n(
"Listing OpenPGP certificates") ;
960 connect(
q, SIGNAL(canceled()),
961 job, SLOT(slotCancel()) );
963 const Error error = job->start(
true );
965 if ( !error && !error.isCanceled() )
970 #include "moc_keycache_p.cpp"
971 #include "moc_keycache.cpp"
std::vector< GpgME::Key > findSigners(const GpgME::VerificationResult &result) const
static const unsigned int hours2ms
static const unsigned int LIKELY_CHAIN_DEPTH
void insert(const GpgME::Key &key)
void addFileSystemWatcher(const boost::shared_ptr< FileSystemWatcher > &watcher)
static std::string email(const UserID &uid)
const GpgME::Key & findByKeyIDOrFingerprint(const char *id) const
void added(const GpgME::Key &key)
std::vector< GpgME::Key > findIssuers(const GpgME::Key &key, Options options=RecursiveSearch) const
#define make_comparator_str(Name, expr)
void refresh(const std::vector< GpgME::Key > &keys)
static std::vector< std::string > emails(const Key &key)
std::vector< GpgME::Key > findSubjects(const GpgME::Key &key, Options option=RecursiveSearch) const
void startKeyListing(GpgME::Protocol proto=GpgME::UnknownProtocol)
std::vector< GpgME::Key > findSigningKeysByMailbox(const KMime::Types::Mailbox &mb) const
std::vector< GpgME::Key > findRecipients(const GpgME::DecryptionResult &result) const
std::vector< GpgME::Key > secretKeys() const
RefreshKeysJob(KeyCache *cache, QObject *parent=0)
std::vector< GpgME::Key > findByEMailAddress(const char *email) const
const GpgME::Key & findByFingerprint(const char *fpr) const
const GpgME::Key & findByShortKeyID(const char *id) const
void remove(const GpgME::Key &key)
void aboutToRemove(const GpgME::Key &key)
static ReaderStatus * self
void enableFileSystemWatcher(bool enable)
void reload(GpgME::Protocol proto=GpgME::UnknownProtocol)
static boost::shared_ptr< const KeyCache > instance()
void keysMayHaveChanged()
std::vector< GpgME::Key > findEncryptionKeysByMailbox(const KMime::Types::Mailbox &mb) const
const std::vector< GpgME::Key > & keys() const
KPIM::ProgressItem * createForJob(Kleo::Job *job, const QString &label)
std::vector< GpgME::Subkey > findSubkeysByKeyID(const std::vector< std::string > &ids) const
static boost::shared_ptr< KeyCache > mutableInstance()