File indexing completed on 2024-06-23 05:14:14
0001 /* -*- mode: c++; c-basic-offset:4 -*- 0002 uiserver/selectcertificatecommand.cpp 0003 0004 This file is part of Kleopatra, the KDE keymanager 0005 SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include <config-kleopatra.h> 0011 0012 #include "selectcertificatecommand.h" 0013 0014 #include <dialogs/certificateselectiondialog.h> 0015 0016 #include <Libkleo/KeyCache> 0017 #include <Libkleo/KleoException> 0018 #include <Libkleo/Stl_Util> 0019 0020 #include <gpgme++/key.h> 0021 0022 #include <gpg-error.h> 0023 0024 #include "kleopatra_debug.h" 0025 #include <KLocalizedString> 0026 0027 #include <QByteArray> 0028 #include <QPointer> 0029 0030 #include <algorithm> 0031 #include <string> 0032 0033 using namespace Kleo; 0034 using namespace Kleo::Dialogs; 0035 using namespace GpgME; 0036 0037 class SelectCertificateCommand::Private 0038 { 0039 friend class ::Kleo::SelectCertificateCommand; 0040 SelectCertificateCommand *const q; 0041 0042 public: 0043 Private(SelectCertificateCommand *qq) 0044 : q(qq) 0045 , dialog() 0046 { 0047 } 0048 0049 private: 0050 void slotDialogAccepted(); 0051 void slotDialogRejected(); 0052 void slotSelectedCertificates(int, const QByteArray &); 0053 0054 private: 0055 void ensureDialogCreated() 0056 { 0057 if (dialog) { 0058 return; 0059 } 0060 dialog = new CertificateSelectionDialog; 0061 q->applyWindowID(dialog); 0062 dialog->setAttribute(Qt::WA_DeleteOnClose); 0063 // dialog->setWindowTitle( i18nc( "@title", "Certificate Selection" ) ); 0064 connect(dialog, SIGNAL(accepted()), q, SLOT(slotDialogAccepted())); 0065 connect(dialog, SIGNAL(rejected()), q, SLOT(slotDialogRejected())); 0066 } 0067 void ensureDialogShown() 0068 { 0069 ensureDialogCreated(); 0070 if (dialog->isVisible()) { 0071 dialog->raise(); 0072 } else { 0073 dialog->show(); 0074 } 0075 } 0076 0077 private: 0078 QPointer<CertificateSelectionDialog> dialog; 0079 }; 0080 0081 SelectCertificateCommand::SelectCertificateCommand() 0082 : QObject() 0083 , AssuanCommandMixin<SelectCertificateCommand>() 0084 , d(new Private(this)) 0085 { 0086 } 0087 0088 SelectCertificateCommand::~SelectCertificateCommand() 0089 { 0090 } 0091 0092 static const struct { 0093 const char *name; 0094 CertificateSelectionDialog::Option option; 0095 } option_table[] = { 0096 {"multi", CertificateSelectionDialog::MultiSelection}, 0097 {"sign-only", CertificateSelectionDialog::SignOnly}, 0098 {"encrypt-only", CertificateSelectionDialog::EncryptOnly}, 0099 {"openpgp-only", CertificateSelectionDialog::OpenPGPFormat}, 0100 {"x509-only", CertificateSelectionDialog::CMSFormat}, 0101 {"secret-only", CertificateSelectionDialog::SecretKeys}, 0102 }; 0103 0104 int SelectCertificateCommand::doStart() 0105 { 0106 d->ensureDialogCreated(); 0107 0108 CertificateSelectionDialog::Options opts; 0109 for (unsigned int i = 0; i < sizeof option_table / sizeof *option_table; ++i) { 0110 if (hasOption(option_table[i].name)) { 0111 opts |= option_table[i].option; 0112 } 0113 } 0114 if ((opts & CertificateSelectionDialog::AnyCertificate) == 0) { 0115 // neither sign-only nor encrypt-only => any usage 0116 opts |= CertificateSelectionDialog::AnyCertificate; 0117 } 0118 if ((opts & CertificateSelectionDialog::AnyFormat) == 0) { 0119 // neither openpgp-only nor x509-only => any protocol 0120 opts |= CertificateSelectionDialog::AnyFormat; 0121 } 0122 d->dialog->setOptions(opts); 0123 0124 if (const int err = inquire("SELECTED_CERTIFICATES", this, SLOT(slotSelectedCertificates(int, QByteArray)))) { 0125 return err; 0126 } 0127 0128 d->ensureDialogShown(); 0129 0130 return 0; 0131 } 0132 0133 void SelectCertificateCommand::Private::slotSelectedCertificates(int err, const QByteArray &data) 0134 { 0135 qCDebug(KLEOPATRA_LOG) << err << ", " << data.constData(); 0136 if (err) { 0137 return; 0138 } 0139 const auto split = data.split('\n'); 0140 std::vector<std::string> fprs; 0141 fprs.reserve(split.size()); 0142 std::transform(split.cbegin(), split.cend(), std::back_inserter(fprs), std::mem_fn(&QByteArray::constData)); 0143 const std::vector<Key> keys = KeyCache::instance()->findByKeyIDOrFingerprint(fprs); 0144 for (const Key &key : keys) { 0145 qCDebug(KLEOPATRA_LOG) << "found key " << key.userID(0).id(); 0146 } 0147 if (dialog) { 0148 dialog->selectCertificates(keys); 0149 } else { 0150 qCWarning(KLEOPATRA_LOG) << "dialog == NULL in slotSelectedCertificates"; 0151 } 0152 } 0153 0154 void SelectCertificateCommand::doCanceled() 0155 { 0156 if (d->dialog) { 0157 d->dialog->close(); 0158 } 0159 } 0160 0161 void SelectCertificateCommand::Private::slotDialogAccepted() 0162 { 0163 try { 0164 QByteArray data; 0165 const auto selectedCertificates(dialog->selectedCertificates()); 0166 for (const Key &key : selectedCertificates) { 0167 data += key.primaryFingerprint(); 0168 data += '\n'; 0169 } 0170 q->sendData(data); 0171 q->done(); 0172 } catch (const Exception &e) { 0173 q->done(e.error(), e.message()); 0174 } catch (const std::exception &e) { 0175 q->done(makeError(GPG_ERR_UNEXPECTED), 0176 i18n("Caught unexpected exception in SelectCertificateCommand::Private::slotDialogAccepted: %1", QString::fromLocal8Bit(e.what()))); 0177 } catch (...) { 0178 q->done(makeError(GPG_ERR_UNEXPECTED), i18n("Caught unknown exception in SelectCertificateCommand::Private::slotDialogAccepted")); 0179 } 0180 } 0181 0182 void SelectCertificateCommand::Private::slotDialogRejected() 0183 { 0184 dialog = nullptr; 0185 q->done(makeError(GPG_ERR_CANCELED)); 0186 } 0187 0188 #include "moc_selectcertificatecommand.cpp"