33 #include <config-kleopatra.h>
40 #include "smimevalidationpreferences.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>
61 #include <KLocalizedString>
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>
80 using namespace GpgME;
81 using namespace boost;
82 using namespace KMime::Types;
84 static const unsigned int hours2ms = 1000 * 60 * 60;
96 struct is_string_empty : std::unary_function<const char*,bool> {
97 bool operator()(
const char * s )
const {
return !s || !*s; }
102 class KeyCache::Private {
103 friend class ::Kleo::KeyCache;
106 explicit Private(
KeyCache * qq ) :
q( qq ) {
107 connect( &m_autoKeyListingTimer, SIGNAL(timeout()),
q, SLOT(startKeyListing()) );
108 updateAutoKeyListingTimer();
111 template <
template <
template <
typename U>
class Op>
class Comp>
112 std::vector<Key>::const_iterator find( const std::vector<Key> & keys, const char * key ) const {
113 const std::vector<Key>::const_iterator it =
114 std::lower_bound( keys.begin(), keys.end(), key, Comp<std::less>() );
115 if ( it == keys.end() || Comp<std::equal_to>()( *it, key ) )
121 template <
template <
template <
typename U>
class Op>
class Comp>
122 std::vector<Subkey>::const_iterator find( const std::vector<Subkey> & keys, const char * key ) const {
123 const std::vector<Subkey>::const_iterator it =
124 std::lower_bound( keys.begin(), keys.end(), key, Comp<std::less>() );
125 if ( it == keys.end() || Comp<std::equal_to>()( *it, key ) )
131 std::vector<Key>::const_iterator find_fpr(
const char * fpr )
const {
132 return find<_detail::ByFingerprint>( by.fpr, fpr );
135 std::pair< std::vector< std::pair<std::string,Key> >::const_iterator,
136 std::vector< std::pair<std::string,Key> >::const_iterator >
137 find_email(
const char *
email )
const {
138 return std::equal_range( by.email.begin(), by.email.end(),
139 email, ByEMail<std::less>() );
142 std::vector<Key> find_mailbox(
const Mailbox & mb,
bool sign )
const;
144 std::vector<Subkey>::const_iterator find_subkeyid(
const char * subkeyid )
const {
145 return find<_detail::ByKeyID>( by.subkeyid, subkeyid );
148 std::vector<Key>::const_iterator find_keyid(
const char * keyid )
const {
149 return find<_detail::ByKeyID>( by.keyid, keyid );
152 std::vector<Key>::const_iterator find_shortkeyid(
const char * shortkeyid )
const {
153 return find<_detail::ByShortKeyID>( by.shortkeyid, shortkeyid );
157 std::vector<Key>::const_iterator,
158 std::vector<Key>::const_iterator
159 > find_subjects(
const char * chain_id )
const {
160 return std::equal_range( by.chainid.begin(), by.chainid.end(),
161 chain_id, _detail::ByChainID<std::less>() );
164 void refreshJobDone(
const KeyListResult & result );
167 void updateAutoKeyListingTimer() {
168 setAutoKeyListingInterval(
hours2ms * SMimeValidationPreferences().refreshInterval() );
170 void setAutoKeyListingInterval(
int ms ) {
171 m_autoKeyListingTimer.stop();
172 m_autoKeyListingTimer.setInterval( ms );
174 m_autoKeyListingTimer.start();
179 std::vector<shared_ptr<FileSystemWatcher> > m_fsWatchers;
180 QTimer m_autoKeyListingTimer;
183 std::vector<Key> fpr, keyid, shortkeyid, chainid;
184 std::vector< std::pair<std::string,Key> >
email;
185 std::vector<Subkey> subkeyid;
191 return mutableInstance();
195 static weak_ptr<KeyCache>
self;
198 }
catch (
const bad_weak_ptr & ) {
206 :
QObject(),
d( new Private( this ) )
216 i->setEnabled( enable );
221 if ( d->m_refreshJob )
224 d->updateAutoKeyListingTimer();
228 connect( d->m_refreshJob, SIGNAL(done(GpgME::KeyListResult)),
this, SLOT(refreshJobDone(GpgME::KeyListResult)) );
229 d->m_refreshJob->start();
234 if ( !d->m_refreshJob )
236 d->m_refreshJob->cancel();
243 d->m_fsWatchers.push_back( watcher );
249 watcher->setEnabled( d->m_refreshJob == 0 );
252 void KeyCache::Private::refreshJobDone(
const KeyListResult& result )
254 emit
q->keyListingDone( result );
255 q->enableFileSystemWatcher(
true );
259 const std::vector<Key>::const_iterator it = d->find_fpr( fpr );
260 if ( it == d->by.fpr.end() ) {
261 static const Key null;
269 std::vector<std::string> sorted;
270 sorted.reserve( fprs.size() );
271 std::remove_copy_if( fprs.begin(), fprs.end(), std::back_inserter( sorted ),
272 boost::bind( is_string_empty(), boost::bind( &std::string::c_str, _1 ) ) );
274 std::sort( sorted.begin(), sorted.end(), _detail::ByFingerprint<std::less>() );
276 std::vector<Key> result;
277 kdtools::set_intersection( d->by.fpr.begin(), d->by.fpr.end(),
278 sorted.begin(), sorted.end(),
279 std::back_inserter( result ),
280 _detail::ByFingerprint<std::less>() );
286 std::vector< std::pair<std::string,Key> >::const_iterator,
287 std::vector< std::pair<std::string,Key> >::const_iterator
288 > pair = d->find_email( email );
289 std::vector<Key> result;
290 result.reserve( std::distance( pair.first, pair.second ) );
291 std::transform( pair.first, pair.second,
292 std::back_inserter( result ),
293 boost::bind( &std::pair<std::string,Key>::second, _1 ) );
302 const std::vector<Key>::const_iterator it = d->find_shortkeyid(
id );
303 if ( it != d->by.shortkeyid.end() )
305 static const Key null;
312 const std::vector<Key>::const_iterator it = d->find_fpr(
id );
313 if ( it != d->by.fpr.end() )
317 const std::vector<Key>::const_iterator it = d->find_keyid(
id );
318 if ( it != d->by.keyid.end() )
321 static const Key null;
327 std::vector<std::string> keyids;
328 std::remove_copy_if( ids.begin(), ids.end(), std::back_inserter( keyids ),
329 boost::bind( is_string_empty(), boost::bind( &std::string::c_str, _1 ) ) );
332 std::sort( keyids.begin(), keyids.end(), _detail::ByFingerprint<std::less>() );
334 std::vector<Key> result;
335 result.reserve( keyids.size() );
337 kdtools::set_intersection( d->by.fpr.begin(), d->by.fpr.end(),
338 keyids.begin(), keyids.end(),
339 std::back_inserter( result ),
340 _detail::ByFingerprint<std::less>() );
341 if ( result.size() < keyids.size() ) {
344 kdtools::set_intersection( d->by.keyid.begin(), d->by.keyid.end(),
345 keyids.begin(), keyids.end(),
346 std::back_inserter( result ),
347 _detail::ByKeyID<std::less>() );
350 std::sort( result.begin(), result.end(), _detail::ByFingerprint<std::less>() );
351 result.erase( std::unique( result.begin(), result.end(), _detail::ByFingerprint<std::equal_to>() ), result.end() );
361 std::vector<std::string> sorted;
362 sorted.reserve( ids.size() );
363 std::remove_copy_if( ids.begin(), ids.end(), std::back_inserter( sorted ),
364 boost::bind( is_string_empty(), boost::bind( &std::string::c_str, _1 ) ) );
366 std::sort( sorted.begin(), sorted.end(), _detail::ByKeyID<std::less>() );
368 std::vector<Subkey> result;
369 kdtools::set_intersection( d->by.subkeyid.begin(), d->by.subkeyid.end(),
370 sorted.begin(), sorted.end(),
371 std::back_inserter( result ),
372 _detail::ByKeyID<std::less>() );
377 std::vector<std::string> keyids;
378 Q_FOREACH(
const DecryptionResult::Recipient & r, res.recipients() )
379 if (
const char * kid = r.keyID() )
380 keyids.push_back( kid );
382 std::vector<Key> result;
383 result.reserve( subkeys.size() );
384 std::transform( subkeys.begin(), subkeys.end(), std::back_inserter( result ), boost::bind( &Subkey::parent, _1 ) );
386 std::sort( result.begin(), result.end(), _detail::ByFingerprint<std::less>() );
387 result.erase( std::unique( result.begin(), result.end(), _detail::ByFingerprint<std::equal_to>() ), result.end() );
392 std::vector<std::string> fprs;
393 Q_FOREACH(
const Signature & s, res.signatures() )
394 if (
const char * fpr = s.fingerprint() )
395 fprs.push_back( fpr );
400 return d->find_mailbox( mb,
true );
404 return d->find_mailbox( mb,
false );
408 #define DO( op, meth, meth2 ) if ( op key.meth() ) {} else { qDebug( "rejecting for signing: %s: %s", #meth2, key.primaryFingerprint() ); return false; }
409 #define ACCEPT( meth ) DO( !!, meth, !meth )
410 #define REJECT( meth ) DO( !, meth, meth )
411 struct ready_for_signing : std::unary_function<Key,bool> {
412 bool operator()(
const Key & key )
const {
422 return key.hasSecret() &&
423 key.canReallySign() && !key.isRevoked() && !key.isExpired() && !key.isDisabled() && !key.isInvalid() ;
429 struct ready_for_encryption : std::unary_function<Key,bool> {
430 #define DO( op, meth, meth2 ) if ( op key.meth() ) {} else { qDebug( "rejecting for encrypting: %s: %s", #meth2, key.primaryFingerprint() ); return false; }
431 bool operator()(
const Key & key )
const {
441 key.canEncrypt() && !key.isRevoked() && !key.isExpired() && !key.isDisabled() && !key.isInvalid() ;
450 std::vector<Key> KeyCache::Private::find_mailbox(
const Mailbox & mb,
bool sign )
const {
451 const QString email = mb.addrSpec().asString();
453 return std::vector<Key>();
456 std::vector< std::pair<std::string,Key> >::const_iterator,
457 std::vector< std::pair<std::string,Key> >::const_iterator
460 std::vector<Key> result;
461 result.
reserve( std::distance( pair.first, pair.second ) );
463 kdtools::copy_2nd_if( pair.first, pair.second,
464 std::back_inserter( result ),
465 ready_for_signing() );
467 kdtools::copy_2nd_if( pair.first, pair.second,
468 std::back_inserter( result ),
469 ready_for_encryption() );
474 return findSubjects( std::vector<Key>( 1, key ), options );
478 return findSubjects( keys.begin(), keys.end(), options );
481 std::vector<Key>
KeyCache::findSubjects( std::vector<Key>::const_iterator first, std::vector<Key>::const_iterator last, Options options )
const {
484 return std::vector<Key>();
486 std::vector<Key> result;
487 while ( first != last ) {
489 std::vector<Key>::const_iterator,
490 std::vector<Key>::const_iterator
491 > pair = d->find_subjects( first->primaryFingerprint() );
492 result.insert( result.end(), pair.first, pair.second );
496 std::sort( result.begin(), result.end(), _detail::ByFingerprint<std::less>() );
497 result.erase( std::unique( result.begin(), result.end(), _detail::ByFingerprint<std::equal_to>() ), result.end() );
500 const std::vector<Key> furtherSubjects =
findSubjects( result, options );
501 std::vector<Key> combined;
502 combined.reserve( result.size() + furtherSubjects.size() );
503 std::merge( result.begin(), result.end(),
504 furtherSubjects.begin(), furtherSubjects.end(),
505 std::back_inserter( combined ),
506 _detail::ByFingerprint<std::less>() );
507 combined.erase( std::unique( combined.begin(), combined.end(), _detail::ByFingerprint<std::equal_to>() ), combined.end() );
508 result.swap( combined );
519 return std::vector<Key>();
521 std::vector<Key> result;
523 result.push_back( key );
530 if ( issuer.isNull() )
533 result.push_back( issuer );
535 if ( !( options & RecursiveSearch ) )
538 while ( !result.back().isNull() && !result.back().isRoot() )
541 if ( result.back().isNull() )
548 return findIssuers( keys.begin(), keys.end(), options );
551 std::vector<Key>
KeyCache::findIssuers( std::vector<Key>::const_iterator first, std::vector<Key>::const_iterator last, Options options )
const {
554 return std::vector<Key>();
557 std::vector<const char *> chainIDs;
558 chainIDs.reserve( last - first );
559 std::transform( boost::make_filter_iterator( !boost::bind( &Key::isRoot, _1 ), first, last ),
560 boost::make_filter_iterator( !boost::bind( &Key::isRoot, _1 ), last, last ),
561 std::back_inserter( chainIDs ),
562 boost::bind( &Key::chainID, _1 ) );
563 std::sort( chainIDs.begin(), chainIDs.end(), _detail::ByFingerprint<std::less>() );
565 const std::vector<const char*>::iterator lastUniqueChainID = std::unique( chainIDs.begin(), chainIDs.end(), _detail::ByFingerprint<std::less>() );
567 std::vector<Key> result;
568 result.reserve( lastUniqueChainID - chainIDs.begin() );
570 kdtools::set_intersection( d->by.fpr.begin(), d->by.fpr.end(),
571 chainIDs.begin(), lastUniqueChainID,
572 std::back_inserter( result ),
573 _detail::ByFingerprint<std::less>() );
576 const unsigned int rs = result.size();
577 result.insert( result.end(), first, last );
578 std::inplace_merge( result.begin(), result.begin() + rs, result.end(),
579 _detail::ByFingerprint<std::less>() );
582 if ( !( options & RecursiveSearch ) )
585 const std::vector<Key> l2result =
findIssuers( result, options & ~IncludeSubject );
587 const unsigned long result_size = result.size();
588 result.insert( result.end(), l2result.begin(), l2result.end() );
589 std::inplace_merge( result.begin(), result.begin() + result_size, result.end(),
590 _detail::ByFingerprint<std::less>() );
598 if ( email[0] ==
'<' && email[email.size()-1] ==
'>' )
599 return email.substr( 1, email.size() - 2 );
604 static std::vector<std::string>
emails(
const Key & key ) {
605 std::vector<std::string>
emails;
606 Q_FOREACH(
const UserID & uid, key.userIDs() ) {
609 emails.push_back( e );
611 std::sort( emails.begin(), emails.end(), ByEMail<std::less>() );
612 emails.erase( std::unique( emails.begin(), emails.end(), ByEMail<std::equal_to>() ), emails.end() );
620 const char * fpr = key.primaryFingerprint();
627 const std::pair<std::vector<Key>::iterator,std::vector<Key>::iterator> range
628 = std::equal_range( d->by.fpr.begin(), d->by.fpr.end(), fpr,
629 _detail::ByFingerprint<std::less>() );
630 d->by.fpr.erase( range.first, range.second );
633 if (
const char * keyid = key.keyID() ) {
634 const std::pair<std::vector<Key>::iterator,std::vector<Key>::iterator> range
635 = std::equal_range( d->by.keyid.begin(), d->by.keyid.end(), keyid,
636 _detail::ByKeyID<std::less>() );
637 const std::vector<Key>::iterator it
638 = std::remove_if( begin( range ), end( range ), boost::bind( _detail::ByFingerprint<std::equal_to>(), fpr, _1 ) );
639 d->by.keyid.erase( it, end( range ) );
642 if (
const char * shortkeyid = key.shortKeyID() ) {
643 const std::pair<std::vector<Key>::iterator,std::vector<Key>::iterator> range
644 = std::equal_range( d->by.shortkeyid.begin(), d->by.shortkeyid.end(), shortkeyid,
645 _detail::ByShortKeyID<std::less>() );
646 const std::vector<Key>::iterator it
647 = std::remove_if( begin( range ), end( range ), boost::bind( _detail::ByFingerprint<std::equal_to>(), fpr, _1 ) );
648 d->by.shortkeyid.erase( it, end( range ) );
651 if (
const char * chainid = key.chainID() ) {
652 const std::pair<std::vector<Key>::iterator,std::vector<Key>::iterator> range
653 = std::equal_range( d->by.chainid.begin(), d->by.chainid.end(), chainid,
654 _detail::ByChainID<std::less>() );
655 const std::pair< std::vector<Key>::iterator, std::vector<Key>::iterator > range2
656 = std::equal_range( begin( range ), end( range ), fpr, _detail::ByFingerprint<std::less>() );
657 d->by.chainid.erase( begin( range2 ), end( range2 ) );
662 const std::pair<std::vector<std::pair<std::string,Key> >::iterator,std::vector<std::pair<std::string,Key> >::iterator> range
663 = std::equal_range( d->by.email.begin(), d->by.email.end(),
email, ByEMail<std::less>() );
664 const std::vector< std::pair<std::string,Key> >::iterator it
665 = 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 );
666 d->by.email.erase( it, end( range ) );
669 Q_FOREACH(
const Subkey & subkey, key.subkeys() ) {
670 if (
const char * keyid = subkey.keyID() ) {
671 const std::pair<std::vector<Subkey>::iterator,std::vector<Subkey>::iterator> range
672 = std::equal_range( d->by.subkeyid.begin(), d->by.subkeyid.end(), keyid,
673 _detail::ByKeyID<std::less>() );
674 const std::pair< std::vector<Subkey>::iterator, std::vector<Subkey>::iterator > range2
675 = std::equal_range( begin( range ), end( range ), fpr, _detail::ByKeyID<std::less>() );
676 d->by.subkeyid.erase( begin( range2 ), end( range2 ) );
682 Q_FOREACH(
const Key & key, keys )
686 const std::vector<GpgME::Key> &
KeyCache::keys()
const
693 std::vector<Key> keys = this->
keys();
694 keys.erase( std::remove_if( keys.begin(), keys.end(), !boost::bind( &Key::hasSecret, _1 ) ), keys.end() );
705 insert( std::vector<Key>( 1, key ) );
711 template <
template <
typename T>
class Op>
class T1,
712 template <template <typename T> class Op> class T2
713 > struct lexicographically {
714 typedef bool result_type;
716 template <
typename U,
typename V>
717 bool operator()(
const U & lhs,
const V & rhs )
const {
719 T1<std::less>()( lhs, rhs ) ||
720 ( T1<std::equal_to>()( lhs, rhs ) &&
721 T2<std::less>()( lhs, rhs ) )
731 std::vector<Key> sorted;
732 sorted.reserve( keys.size() );
733 std::remove_copy_if( keys.begin(), keys.end(),
734 std::back_inserter( sorted ),
735 boost::bind( is_string_empty(), boost::bind( &Key::primaryFingerprint, _1 ) ) );
737 Q_FOREACH(
const Key & key, sorted )
741 std::sort( sorted.begin(), sorted.end(), _detail::ByFingerprint<std::less>() );
744 std::vector<Key> by_fpr;
745 by_fpr.reserve( sorted.size() + d->by.fpr.size() );
746 std::merge( sorted.begin(), sorted.end(),
747 d->by.fpr.begin(), d->by.fpr.end(),
748 std::back_inserter( by_fpr ),
749 _detail::ByFingerprint<std::less>() );
752 std::vector< std::pair<std::
string,Key> > pairs;
753 pairs.reserve( sorted.size() );
754 Q_FOREACH( const Key & key, sorted ) {
757 pairs.push_back( std::make_pair( e, key ) );
759 std::sort( pairs.begin(), pairs.end(), ByEMail<std::less>() );
762 std::vector< std::pair<std::
string,Key> > by_email;
763 by_email.reserve( pairs.size() + d->by.email.size() );
764 std::merge( pairs.begin(), pairs.end(),
765 d->by.email.begin(), d->by.email.end(),
766 std::back_inserter( by_email ),
767 ByEMail<std::less>() );
770 std::stable_sort( sorted.begin(), sorted.end(), _detail::ByChainID<std::less>() );
773 std::vector<Key> by_chainid;
774 by_chainid.reserve( sorted.size() + d->by.chainid.size() );
775 std::merge( boost::make_filter_iterator( !boost::bind( &Key::isRoot, _1 ), sorted.begin(), sorted.end() ),
776 boost::make_filter_iterator( !boost::bind( &Key::isRoot, _1 ), sorted.end(), sorted.end() ),
777 d->by.chainid.begin(), d->by.chainid.end(),
778 std::back_inserter( by_chainid ),
779 lexicographically<_detail::ByChainID,_detail::ByFingerprint>() );
782 std::sort( sorted.begin(), sorted.end(), _detail::ByKeyID<std::less>() );
785 std::vector<Key> by_keyid;
786 by_keyid.reserve( sorted.size() + d->by.keyid.size() );
787 std::merge( sorted.begin(), sorted.end(),
788 d->by.keyid.begin(), d->by.keyid.end(),
789 std::back_inserter( by_keyid ),
790 _detail::ByKeyID<std::less>() );
793 std::sort( sorted.begin(), sorted.end(), _detail::ByShortKeyID<std::less>() );
796 std::vector<Key> by_shortkeyid;
797 by_shortkeyid.reserve( sorted.size() + d->by.shortkeyid.size() );
798 std::merge( sorted.begin(), sorted.end(),
799 d->by.shortkeyid.begin(), d->by.shortkeyid.end(),
800 std::back_inserter( by_shortkeyid ),
801 _detail::ByShortKeyID<std::less>() );
804 std::vector<Subkey> subkeys;
805 subkeys.reserve( sorted.size() );
806 Q_FOREACH( const Key & key, sorted )
807 Q_FOREACH( const Subkey & subkey, key.subkeys() )
808 subkeys.push_back( subkey );
811 std::sort( subkeys.begin(), subkeys.end(), _detail::ByKeyID<std::less>() );
814 std::vector<Subkey> by_subkeyid;
815 by_email.reserve( subkeys.size() + d->by.subkeyid.size() );
816 std::merge( subkeys.begin(), subkeys.end(),
817 d->by.subkeyid.begin(), d->by.subkeyid.end(),
818 std::back_inserter( by_subkeyid ),
819 _detail::ByKeyID<std::less>() );
822 by_fpr.swap( d->by.fpr );
823 by_keyid.swap( d->by.keyid );
824 by_shortkeyid.swap( d->by.shortkeyid );
825 by_email.swap( d->by.email );
826 by_subkeyid.swap( d->by.subkeyid );
827 by_chainid.swap( d->by.chainid );
829 Q_FOREACH( const Key & key, sorted )
836 d->by = Private::By();
847 RefreshKeysJob *
const q;
849 Private(
KeyCache * cache, RefreshKeysJob * qq );
852 void listAllKeysJobDone(
const KeyListResult & res,
const std::vector<Key> & nextKeys ) {
853 std::vector<Key>
keys;
854 keys.reserve( m_keys.size() + nextKeys.size() );
855 if ( m_keys.empty() )
858 std::merge( m_keys.begin(), m_keys.end(),
859 nextKeys.begin(), nextKeys.end(),
860 std::back_inserter( keys ),
861 _detail::ByFingerprint<std::less>() );
865 void emitDone(
const KeyListResult & result );
866 void updateKeyCache();
870 std::vector<Key> m_keys;
871 KeyListResult m_mergedResult;
874 void jobDone(
const KeyListResult & res );
877 KeyCache::RefreshKeysJob::Private::Private(
KeyCache * cache, RefreshKeysJob * qq ) :
q( qq ), m_cache( cache ), m_jobsPending( 0 )
882 void KeyCache::RefreshKeysJob::Private::jobDone(
const KeyListResult & result )
884 QObject*
const sender =
q->sender();
887 assert( m_jobsPending > 0 );
889 m_mergedResult.mergeWith( result );
890 if ( m_jobsPending > 0 )
893 emitDone( m_mergedResult );
896 void KeyCache::RefreshKeysJob::Private::emitDone(
const KeyListResult & res )
919 void KeyCache::RefreshKeysJob::Private::doStart()
921 assert( m_jobsPending == 0 );
922 m_mergedResult.mergeWith( KeyListResult(
startKeyListing(
"openpgp" ) ) );
923 m_mergedResult.mergeWith( KeyListResult(
startKeyListing(
"smime" ) ) );
925 if ( m_jobsPending != 0 )
928 const bool hasError = m_mergedResult.error() || m_mergedResult.error().isCanceled();
929 emitDone( hasError ? m_mergedResult : KeyListResult( Error( GPG_ERR_UNSUPPORTED_OPERATION ) ) );
932 void KeyCache::RefreshKeysJob::Private::updateKeyCache()
934 std::vector<Key> cachedKeys = m_cache->keys();
935 std::sort( cachedKeys.begin(), cachedKeys.end(), _detail::ByFingerprint<std::less>() );
936 std::vector<Key> keysToRemove;
937 std::set_difference( cachedKeys.begin(), cachedKeys.end(),
938 m_keys.begin(), m_keys.end(),
939 std::back_inserter( keysToRemove ),
940 _detail::ByFingerprint<std::less>() );
941 m_cache->remove( keysToRemove );
942 m_cache->refresh( m_keys );
945 Error KeyCache::RefreshKeysJob::Private::startKeyListing(
const char* backend )
947 const Kleo::CryptoBackend::Protocol *
const protocol = Kleo::CryptoBackendFactory::instance()->protocol( backend );
950 Kleo::ListAllKeysJob *
const job = protocol->listAllKeysJob(
false,
true );
953 connect( job, SIGNAL(result(GpgME::KeyListResult,std::vector<GpgME::Key>)),
954 q, SLOT(listAllKeysJobDone(GpgME::KeyListResult,std::vector<GpgME::Key>)) );
956 const QString label = protocol == Kleo::CryptoBackendFactory::instance()->smime()
957 ? i18n(
"Listing X.509 certificates")
958 : i18n(
"Listing OpenPGP certificates") ;
962 job, SLOT(slotCancel()) );
964 const Error error = job->start(
true );
966 if ( !error && !error.isCanceled() )
971 #include "moc_keycache_p.cpp"
972 #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)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
std::vector< GpgME::Key > findSubjects(const GpgME::Key &key, Options option=RecursiveSearch) const
void startKeyListing(GpgME::Protocol proto=GpgME::UnknownProtocol)
const char * constData() const
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
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
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()
QByteArray toUtf8() const