33 #include <config-kleopatra.h>
45 #include <kleo/stl_util.h>
46 #include <kleo/importfromkeyserverjob.h>
47 #include <kleo/keylistjob.h>
48 #include <kleo/cryptobackendfactory.h>
49 #include <kleo/cryptobackend.h>
50 #include <kleo/cryptoconfig.h>
52 #include <gpgme++/key.h>
53 #include <gpgme++/keylistresult.h>
54 #include <gpgme++/importresult.h>
57 #include <KMessageBox>
64 #include <boost/bind.hpp>
65 #include <boost/shared_ptr.hpp>
73 using namespace Kleo::Commands;
74 using namespace Kleo::Dialogs;
75 using namespace GpgME;
76 using namespace boost;
79 friend class ::Kleo::Commands::LookupCertificatesCommand;
89 void slotSearchTextChanged(
const QString & str );
90 void slotNextKey(
const Key & key ) {
91 keyListing.keys.push_back( key );
93 void slotKeyListResult(
const KeyListResult & result );
94 void slotImportRequested(
const std::vector<Key> & keys );
95 void slotDetailsRequested(
const Key & key );
96 void slotSaveAsRequested(
const std::vector<Key> & keys );
97 void slotDialogRejected() {
103 void showError(
QWidget * parent,
const KeyListResult & result );
104 void showResult(
QWidget * parent,
const KeyListResult & result );
106 KeyListJob * createKeyListJob( GpgME::Protocol proto )
const {
107 const CryptoBackend::Protocol *
const cbp = CryptoBackendFactory::instance()->protocol( proto );
108 return cbp ? cbp->keyListJob(
true ) : 0 ;
110 ImportFromKeyserverJob * createImportJob( GpgME::Protocol proto )
const {
111 const CryptoBackend::Protocol *
const cbp = CryptoBackendFactory::instance()->protocol( proto );
112 return cbp ? cbp->importFromKeyserverJob() : 0 ;
114 void startKeyListJob( GpgME::Protocol proto,
const QString & str );
115 bool checkConfig()
const;
117 QWidget * dialogOrParentWidgetOrView()
const {
if ( dialog )
return dialog;
else return parentWidgetOrView(); }
120 QPointer<LookupCertificatesDialog> dialog;
121 struct KeyListingVariables {
122 QPointer<KeyListJob> cms, openpgp;
123 KeyListResult result;
124 std::vector<Key> keys;
126 void reset() { *
this = KeyListingVariables(); }
131 LookupCertificatesCommand::Private * LookupCertificatesCommand::d_func() {
return static_cast<Private*
>(
d.get() ); }
132 const LookupCertificatesCommand::Private * LookupCertificatesCommand::d_func()
const {
return static_cast<const Private*
>(
d.get() ); }
144 LookupCertificatesCommand::Private::~Private() {
159 d->fingerPrint = fingerPrint;
168 void LookupCertificatesCommand::Private::init() {
175 void LookupCertificatesCommand::doStart() {
177 if ( !
d->checkConfig() ) {
187 if ( !
d->fingerPrint.isEmpty() ) {
188 if ( !
d->fingerPrint.startsWith( QLatin1String(
"0x") ) )
189 d->fingerPrint = QLatin1String(
"0x") +
d->fingerPrint;
190 d->dialog->setSearchText(
d->fingerPrint );
192 d->slotSearchTextChanged(
d->fingerPrint );
195 d->dialog->setPassive(
false );
200 void LookupCertificatesCommand::Private::createDialog() {
204 applyWindowID( dialog );
205 dialog->setAttribute( Qt::WA_DeleteOnClose );
206 connect( dialog, SIGNAL(searchTextChanged(QString)),
207 q, SLOT(slotSearchTextChanged(QString)) );
208 connect( dialog, SIGNAL(saveAsRequested(std::vector<GpgME::Key>)),
209 q, SLOT(slotSaveAsRequested(std::vector<GpgME::Key>)) );
210 connect( dialog, SIGNAL(importRequested(std::vector<GpgME::Key>)),
211 q, SLOT(slotImportRequested(std::vector<GpgME::Key>)) );
212 connect( dialog, SIGNAL(detailsRequested(GpgME::Key)),
213 q, SLOT(slotDetailsRequested(GpgME::Key)) );
214 connect( dialog, SIGNAL(rejected()),
215 q, SLOT(slotDialogRejected()) );
218 void LookupCertificatesCommand::Private::slotSearchTextChanged(
const QString & str ) {
222 dialog->setPassive(
true );
223 dialog->setCertificates( std::vector<Key>() );
226 const QRegExp rx( QLatin1String(
"(?:0x|0X)?[0-9a-fA-F]{6,}" ) );
227 if ( rx.exactMatch( str ) )
228 information( str.startsWith( QLatin1String(
"0x" ), Qt::CaseInsensitive )
229 ? i18n(
"<p>You seem to be searching for a fingerPrint or a key-id.</p>"
230 "<p>Different keyservers expect different ways to search for these. "
231 "Some require a \"0x\" prefix, while others require there be no such prefix.</p>"
232 "<p>If your search does not yield any results, try removing the 0x prefix from your search.</p>")
233 : i18n(
"<p>You seem to be searching for a fingerPrint or a key-id.</p>"
234 "<p>Different keyservers expect different ways to search for these. "
235 "Some require a \"0x\" prefix, while others require there be no such prefix.</p>"
236 "<p>If your search does not yield any results, try adding the 0x prefix to your search.</p>"),
237 i18n(
"Hex-String Search"),
238 QLatin1String(
"lookup-certificates-warn-0x-prefix" ) );
240 startKeyListJob(
CMS, str );
241 startKeyListJob(
OpenPGP, str );
245 void LookupCertificatesCommand::Private::startKeyListJob( GpgME::Protocol proto,
const QString & str ) {
246 KeyListJob *
const klj = createKeyListJob( proto );
249 connect( klj, SIGNAL(result(GpgME::KeyListResult)),
250 q, SLOT(slotKeyListResult(GpgME::KeyListResult)) );
251 connect( klj, SIGNAL(nextKey(GpgME::Key)),
252 q, SLOT(slotNextKey(GpgME::Key)) );
253 if (
const Error err = klj->start( QStringList( str ) ) )
254 keyListing.result.mergeWith( KeyListResult( err ) );
257 keyListing.cms = klj;
259 keyListing.openpgp = klj;
262 void LookupCertificatesCommand::Private::slotKeyListResult(
const KeyListResult & r ) {
264 if (
q->sender() == keyListing.cms )
266 else if (
q->sender() == keyListing.openpgp )
267 keyListing.openpgp = 0;
269 kDebug() <<
"unknown sender()" <<
q->sender();
271 keyListing.result.mergeWith( r );
272 if ( keyListing.cms || keyListing.openpgp )
275 if ( keyListing.result.error() && !keyListing.result.error().isCanceled() )
276 showError( dialog, keyListing.result );
278 if ( keyListing.result.isTruncated() )
279 showResult( dialog, keyListing.result );
282 dialog->setPassive(
false );
283 dialog->setCertificates( keyListing.keys );
292 void LookupCertificatesCommand::Private::slotImportRequested(
const std::vector<Key> & keys ) {
295 assert( !keys.empty() );
296 assert( kdtools::none_of( keys, mem_fn( &Key::isNull ) ) );
298 std::vector<Key> pgp, cms;
299 pgp.reserve( keys.size() );
300 cms.reserve( keys.size() );
301 kdtools::separate_if( keys.begin(), keys.end(),
302 std::back_inserter( pgp ),
303 std::back_inserter( cms ),
304 boost::bind( &Key::protocol, _1 ) ==
OpenPGP );
306 setWaitForMoreJobs(
true );
309 i18nc(
"@title %1:\"OpenPGP\" or \"CMS\"",
310 "%1 Certificate Server",
313 startImport(
CMS, cms,
314 i18nc(
"@title %1:\"OpenPGP\" or \"CMS\"",
315 "%1 Certificate Server",
317 setWaitForMoreJobs(
false );
321 void LookupCertificatesCommand::Private::slotSaveAsRequested(
const std::vector<Key> & keys ) {
323 kDebug() <<
"not implemented";
326 void LookupCertificatesCommand::Private::slotDetailsRequested(
const Key & key ) {
332 void LookupCertificatesCommand::doCancel() {
334 if (
QDialog *
const dlg =
d->dialog ) {
341 if ( !result.error() )
343 KMessageBox::information( parent, i18nc(
"@info",
344 "Failed to search on certificate server. The error returned was:\n%1",
345 QString::fromLocal8Bit( result.error().asString() ) ) );
348 void LookupCertificatesCommand::Private::showResult(
QWidget * parent,
const KeyListResult & result ) {
349 if ( result.isTruncated() )
350 KMessageBox::information( parent,
352 "<para>The query result has been truncated.</para>"
353 "<para>Either the local or a remote limit on "
354 "the maximum number of returned hits has "
355 "been exceeded.</para>"
356 "<para>You can try to increase the local limit "
357 "in the configuration dialog, but if one "
358 "of the configured servers is the limiting "
359 "factor, you have to refine your search.</para>"),
360 i18nc(
"@title",
"Result Truncated"),
361 QLatin1String(
"lookup-certificates-truncated-result") );
365 const Kleo::CryptoConfig *
const config = Kleo::CryptoBackendFactory::instance()->config();
368 const Kleo::CryptoConfigEntry *
const entry = config->entry( QLatin1String(
"gpg"), QLatin1String(
"Keyserver"), QLatin1String(
"keyserver") );
369 return entry && !entry->stringValue().isEmpty();
374 const Kleo::CryptoConfig *
const config = Kleo::CryptoBackendFactory::instance()->config();
377 const Kleo::CryptoConfigEntry * entry = config->entry( QLatin1String(
"dirmngr"), QLatin1String(
"LDAP"), QLatin1String(
"LDAP Server") );
378 bool entriesExist = entry && !entry->urlValueList().empty();
379 entry = config->entry( QLatin1String(
"gpgsm"), QLatin1String(
"Configuration"), QLatin1String(
"keyserver") );
380 entriesExist |= entry && !entry->stringValueList().empty();
385 bool LookupCertificatesCommand::Private::checkConfig()
const {
388 information( i18nc(
"@info",
389 "<para>You do not have any directory servers configured.</para>"
390 "<para>You need to configure at least one directory server to "
391 "search on one.</para>"
392 "<para>You can configure directory servers here: "
393 "<interface>Settings->Configure Kleopatra</interface>.</para>"),
394 i18nc(
"@title",
"No Directory Servers Configured") );
401 #include "moc_lookupcertificatescommand.cpp"
void showError(QWidget *parent, const GpgME::Error &error, const QString &id=QString())
kdtools::pimpl_ptr< Private > d
LookupCertificatesCommand(QAbstractItemView *view, KeyListController *parent)
static bool haveX509DirectoryServerConfigured()
~LookupCertificatesCommand()
void setParentWidget(QWidget *widget)
static bool haveOpenPGPKeyserverConfigured()