File indexing completed on 2024-06-23 05:14:04
0001 /* SPDX-FileCopyrightText: 2017 Intevation GmbH 0002 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "exportdialog.h" 0007 0008 #include "kleopatra_debug.h" 0009 0010 #include "view/waitwidget.h" 0011 0012 #include <QDialogButtonBox> 0013 #include <QPushButton> 0014 #include <QTextEdit> 0015 #include <QVBoxLayout> 0016 0017 #include <gpgme++/key.h> 0018 0019 #include <QGpgME/ExportJob> 0020 #include <QGpgME/Protocol> 0021 0022 #include <KConfigGroup> 0023 #include <KLocalizedString> 0024 #include <KSharedConfig> 0025 0026 #include <Libkleo/Formatting> 0027 0028 using namespace Kleo; 0029 0030 class ExportWidget::Private 0031 { 0032 public: 0033 Private(ExportWidget *qq) 0034 : q(qq) 0035 { 0036 } 0037 0038 void setupUi(); 0039 0040 GpgME::Key key; 0041 GpgME::Subkey subkey; 0042 QTextEdit *textEdit; 0043 WaitWidget *waitWidget; 0044 unsigned int flags; 0045 0046 private: 0047 ExportWidget *const q; 0048 }; 0049 0050 void ExportWidget::Private::setupUi() 0051 { 0052 auto vlay = new QVBoxLayout(q); 0053 vlay->setContentsMargins(0, 0, 0, 0); 0054 0055 textEdit = new QTextEdit; 0056 textEdit->setVisible(false); 0057 textEdit->setReadOnly(true); 0058 0059 auto fixedFont = QFont(QStringLiteral("Monospace")); 0060 fixedFont.setStyleHint(QFont::TypeWriter); 0061 0062 textEdit->setFont(fixedFont); 0063 textEdit->setReadOnly(true); 0064 vlay->addWidget(textEdit); 0065 0066 waitWidget = new WaitWidget; 0067 waitWidget->setText(i18n("Exporting ...")); 0068 vlay->addWidget(waitWidget); 0069 } 0070 0071 ExportWidget::ExportWidget(QWidget *parent) 0072 : QWidget(parent) 0073 , d(new Private(this)) 0074 { 0075 d->setupUi(); 0076 } 0077 0078 ExportWidget::~ExportWidget() 0079 { 0080 } 0081 0082 static QString injectComments(const GpgME::Key &key, const QByteArray &data) 0083 { 0084 QString ret = QString::fromUtf8(data); 0085 0086 if (key.protocol() != GpgME::OpenPGP) { 0087 return ret; 0088 } 0089 0090 auto overView = Formatting::toolTip(key, 0091 Formatting::Fingerprint | Formatting::UserIDs | Formatting::Issuer | Formatting::Subject | Formatting::ExpiryDates 0092 | Formatting::CertificateType | Formatting::CertificateUsage); 0093 0094 // Fixup the HTML coming from the toolTip for our own format. 0095 overView.remove(QLatin1StringView("<tr><th>")); 0096 overView.replace(QLatin1StringView("</th><td>"), QLatin1String("\t")); 0097 overView.replace(QLatin1StringView("</td></tr>"), QLatin1String("\n")); 0098 overView.remove(QLatin1StringView("<table border=\"0\">")); 0099 overView.remove(QLatin1StringView("\n</table>")); 0100 overView.replace(QLatin1StringView("<"), QLatin1String("<")); 0101 overView.replace(QLatin1StringView(">"), QLatin1String(">")); 0102 0103 auto overViewLines = overView.split(QLatin1Char('\n')); 0104 0105 // Format comments so that they fit for RFC 4880 0106 auto comments = QStringLiteral("Comment: "); 0107 comments += overViewLines.join(QLatin1StringView("\nComment: ")) + QLatin1Char('\n'); 0108 0109 ret.insert(37 /* -----BEGIN PGP PUBLIC KEY BLOCK-----\n */, comments); 0110 0111 return ret; 0112 } 0113 0114 void ExportWidget::exportResult(const GpgME::Error &err, const QByteArray &data) 0115 { 0116 d->waitWidget->setVisible(false); 0117 d->textEdit->setVisible(true); 0118 0119 if (err) { 0120 /* Should not happen. But well,.. */ 0121 d->textEdit->setText(i18nc("%1 is error message", "Failed to export: '%1'", Formatting::errorAsString(err))); 0122 } 0123 0124 if (!d->flags) { 0125 d->textEdit->setText(injectComments(d->key, data)); 0126 } else { 0127 d->textEdit->setText(QString::fromUtf8(data)); 0128 } 0129 } 0130 0131 void ExportWidget::setKey(const GpgME::Subkey &key, unsigned int flags) 0132 { 0133 d->waitWidget->setVisible(true); 0134 d->textEdit->setVisible(false); 0135 d->key = key.parent(); 0136 d->subkey = key; 0137 d->flags = flags; 0138 0139 auto protocol = d->key.protocol() == GpgME::CMS ? QGpgME::smime() : QGpgME::openpgp(); 0140 0141 auto job = protocol->publicKeyExportJob(true); 0142 0143 connect(job, &QGpgME::ExportJob::result, this, &ExportWidget::exportResult); 0144 0145 job->setExportFlags(flags); 0146 job->start(QStringList() << QLatin1StringView(key.fingerprint()) + QLatin1Char('!')); 0147 } 0148 0149 void ExportWidget::setKey(const GpgME::Key &key, unsigned int flags) 0150 { 0151 d->waitWidget->setVisible(true); 0152 d->textEdit->setVisible(false); 0153 d->key = key; 0154 d->flags = flags; 0155 0156 auto protocol = key.protocol() == GpgME::CMS ? QGpgME::smime() : QGpgME::openpgp(); 0157 0158 auto job = protocol->publicKeyExportJob(true); 0159 0160 connect(job, &QGpgME::ExportJob::result, this, &ExportWidget::exportResult); 0161 0162 job->setExportFlags(flags); 0163 job->start(QStringList() << QLatin1StringView(key.primaryFingerprint())); 0164 } 0165 0166 GpgME::Key ExportWidget::key() const 0167 { 0168 return d->key; 0169 } 0170 0171 ExportDialog::ExportDialog(QWidget *parent) 0172 : QDialog(parent) 0173 , mWidget(new ExportWidget(this)) 0174 { 0175 KConfigGroup dialog(KSharedConfig::openStateConfig(), QStringLiteral("ExportDialog")); 0176 const auto size = dialog.readEntry("Size", QSize(600, 800)); 0177 if (size.isValid()) { 0178 resize(size); 0179 } 0180 setWindowTitle(i18nc("@title:window", "Export")); 0181 0182 auto l = new QVBoxLayout(this); 0183 l->addWidget(mWidget); 0184 0185 auto bbox = new QDialogButtonBox(this); 0186 auto btn = bbox->addButton(QDialogButtonBox::Close); 0187 connect(btn, &QPushButton::pressed, this, &QDialog::accept); 0188 l->addWidget(bbox); 0189 } 0190 0191 ExportDialog::~ExportDialog() 0192 { 0193 KConfigGroup dialog(KSharedConfig::openStateConfig(), QStringLiteral("ExportDialog")); 0194 dialog.writeEntry("Size", size()); 0195 dialog.sync(); 0196 } 0197 0198 void ExportDialog::setKey(const GpgME::Key &key, unsigned int flags) 0199 { 0200 mWidget->setKey(key, flags); 0201 } 0202 0203 void ExportDialog::setKey(const GpgME::Subkey &key, unsigned int flags) 0204 { 0205 mWidget->setKey(key, flags); 0206 } 0207 0208 GpgME::Key ExportDialog::key() const 0209 { 0210 return mWidget->key(); 0211 } 0212 0213 #include "moc_exportdialog.cpp"