diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a928697d1..9a4b998a7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,365 +1,367 @@ add_subdirectory(icons) include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) if (NOT DISABLE_KWATCHGNUPG) add_subdirectory(kwatchgnupg) endif() add_subdirectory(libkleopatraclient) add_subdirectory(conf) add_subdirectory(kconf_update) if(WIN32) set(_kleopatra_extra_uiserver_SRCS uiserver/uiserver_win.cpp) set(_kleopatra_extra_SRCS utils/gnupg-registry.c selftest/registrycheck.cpp utils/windowsprocessdevice.cpp ) else() set(_kleopatra_extra_uiserver_SRCS uiserver/uiserver_unix.cpp) set(_kleopatra_extra_SRCS) endif() set(_kleopatra_uiserver_SRCS uiserver/sessiondata.cpp uiserver/uiserver.cpp ${_kleopatra_extra_uiserver_SRCS} uiserver/assuanserverconnection.cpp uiserver/echocommand.cpp uiserver/decryptverifycommandemailbase.cpp uiserver/decryptverifycommandfilesbase.cpp uiserver/signcommand.cpp uiserver/signencryptfilescommand.cpp uiserver/prepencryptcommand.cpp uiserver/prepsigncommand.cpp uiserver/encryptcommand.cpp uiserver/selectcertificatecommand.cpp uiserver/importfilescommand.cpp uiserver/createchecksumscommand.cpp uiserver/verifychecksumscommand.cpp selftest/uiservercheck.cpp ) if(ASSUAN2_FOUND) include_directories(${ASSUAN2_INCLUDES}) set(_kleopatra_uiserver_extra_libs ${ASSUAN2_LIBRARIES}) else() include_directories(${ASSUAN_INCLUDES}) if(WIN32) set(_kleopatra_uiserver_extra_libs ${ASSUAN_VANILLA_LIBRARIES}) else() set(_kleopatra_uiserver_extra_libs ${ASSUAN_PTHREAD_LIBRARIES}) endif() endif() if(HAVE_GPG_ERR_SOURCE_KLEO) add_definitions(-DGPG_ERR_SOURCE_DEFAULT=GPG_ERR_SOURCE_KLEO) else() add_definitions(-DGPG_ERR_SOURCE_DEFAULT=GPG_ERR_SOURCE_USER_1) endif() ki18n_wrap_ui(_kleopatra_uiserver_SRCS crypto/gui/signingcertificateselectionwidget.ui) if("${Gpgmepp_VERSION}" VERSION_GREATER_EQUAL "1.14.1") set(_kleopatra_deviceinfowatcher_files smartcard/deviceinfowatcher.cpp ) else() set(_kleopatra_deviceinfowatcher_files) endif() set(_kleopatra_SRCS utils/gui-helper.cpp utils/filedialog.cpp utils/kdpipeiodevice.cpp utils/headerview.cpp utils/scrollarea.cpp utils/dragqueen.cpp utils/multivalidator.cpp utils/systemtrayicon.cpp utils/hex.cpp utils/path-helper.cpp utils/input.cpp utils/output.cpp utils/validation.cpp utils/wsastarter.cpp utils/iodevicelogger.cpp utils/log.cpp utils/action_data.cpp utils/types.cpp utils/archivedefinition.cpp utils/auditlog.cpp utils/clipboardmenu.cpp utils/kuniqueservice.cpp utils/remarks.cpp utils/writecertassuantransaction.cpp selftest/selftest.cpp selftest/enginecheck.cpp selftest/gpgconfcheck.cpp selftest/gpgagentcheck.cpp selftest/libkleopatrarccheck.cpp ${_kleopatra_extra_SRCS} view/keylistcontroller.cpp view/keytreeview.cpp view/searchbar.cpp view/smartcardwidget.cpp view/padwidget.cpp view/pgpcardwidget.cpp view/pivcardwidget.cpp view/netkeywidget.cpp view/nullpinwidget.cpp view/tabwidget.cpp view/keycacheoverlay.cpp view/waitwidget.cpp view/welcomewidget.cpp dialogs/certificateselectiondialog.cpp dialogs/certifywidget.cpp dialogs/expirydialog.cpp dialogs/lookupcertificatesdialog.cpp dialogs/ownertrustdialog.cpp dialogs/selftestdialog.cpp dialogs/certifycertificatedialog.cpp dialogs/revokecertificationwidget.cpp dialogs/revokecertificationdialog.cpp dialogs/adduseriddialog.cpp dialogs/addemaildialog.cpp dialogs/exportcertificatesdialog.cpp dialogs/deletecertificatesdialog.cpp dialogs/setinitialpindialog.cpp dialogs/certificatedetailswidget.cpp dialogs/trustchainwidget.cpp dialogs/weboftrustwidget.cpp dialogs/weboftrustdialog.cpp dialogs/exportdialog.cpp dialogs/subkeyswidget.cpp dialogs/gencardkeydialog.cpp dialogs/updatenotification.cpp dialogs/pivcardapplicationadministrationkeyinputdialog.cpp + dialogs/certificatedetailsinputwidget.cpp + dialogs/createcsrforcardkeydialog.cpp crypto/controller.cpp crypto/certificateresolver.cpp crypto/sender.cpp crypto/recipient.cpp crypto/task.cpp crypto/taskcollection.cpp crypto/decryptverifytask.cpp crypto/decryptverifyemailcontroller.cpp crypto/decryptverifyfilescontroller.cpp crypto/autodecryptverifyfilescontroller.cpp crypto/encryptemailtask.cpp crypto/encryptemailcontroller.cpp crypto/newsignencryptemailcontroller.cpp crypto/signencrypttask.cpp crypto/signencryptfilescontroller.cpp crypto/signemailtask.cpp crypto/signemailcontroller.cpp crypto/createchecksumscontroller.cpp crypto/verifychecksumscontroller.cpp crypto/gui/wizard.cpp crypto/gui/wizardpage.cpp crypto/gui/certificateselectionline.cpp crypto/gui/certificatelineedit.cpp crypto/gui/signingcertificateselectionwidget.cpp crypto/gui/signingcertificateselectiondialog.cpp crypto/gui/resultitemwidget.cpp crypto/gui/resultlistwidget.cpp crypto/gui/resultpage.cpp crypto/gui/newresultpage.cpp crypto/gui/signencryptfileswizard.cpp crypto/gui/signencryptemailconflictdialog.cpp crypto/gui/decryptverifyoperationwidget.cpp crypto/gui/decryptverifyfileswizard.cpp crypto/gui/decryptverifyfilesdialog.cpp crypto/gui/objectspage.cpp crypto/gui/resolverecipientspage.cpp crypto/gui/signerresolvepage.cpp crypto/gui/encryptemailwizard.cpp crypto/gui/signemailwizard.cpp crypto/gui/signencryptwidget.cpp crypto/gui/signencryptwizard.cpp crypto/gui/unknownrecipientwidget.cpp crypto/gui/verifychecksumsdialog.cpp commands/command.cpp commands/gnupgprocesscommand.cpp commands/detailscommand.cpp commands/exportcertificatecommand.cpp commands/importcertificatescommand.cpp commands/importcertificatefromfilecommand.cpp commands/importcertificatefromclipboardcommand.cpp commands/importcertificatefromdatacommand.cpp commands/lookupcertificatescommand.cpp commands/reloadkeyscommand.cpp commands/refreshx509certscommand.cpp commands/refreshopenpgpcertscommand.cpp commands/deletecertificatescommand.cpp commands/decryptverifyfilescommand.cpp commands/signencryptfilescommand.cpp commands/signencryptfoldercommand.cpp commands/encryptclipboardcommand.cpp commands/signclipboardcommand.cpp commands/decryptverifyclipboardcommand.cpp commands/clearcrlcachecommand.cpp commands/dumpcrlcachecommand.cpp commands/dumpcertificatecommand.cpp commands/importcrlcommand.cpp commands/changeexpirycommand.cpp commands/changeownertrustcommand.cpp commands/changeroottrustcommand.cpp commands/changepassphrasecommand.cpp commands/certifycertificatecommand.cpp commands/revokecertificationcommand.cpp commands/selftestcommand.cpp commands/exportsecretkeycommand.cpp commands/exportopenpgpcertstoservercommand.cpp commands/adduseridcommand.cpp commands/newcertificatecommand.cpp commands/setinitialpincommand.cpp commands/learncardkeyscommand.cpp commands/checksumcreatefilescommand.cpp commands/checksumverifyfilescommand.cpp commands/exportpaperkeycommand.cpp commands/importpaperkeycommand.cpp commands/genrevokecommand.cpp commands/keytocardcommand.cpp commands/cardcommand.cpp commands/pivgeneratecardkeycommand.cpp commands/changepincommand.cpp commands/authenticatepivcardapplicationcommand.cpp commands/setpivcardapplicationadministrationkeycommand.cpp commands/certificatetopivcardcommand.cpp commands/importcertificatefrompivcardcommand.cpp commands/createopenpgpkeyfromcardkeyscommand.cpp ${_kleopatra_uiserver_files} conf/configuredialog.cpp newcertificatewizard/listwidget.cpp newcertificatewizard/newcertificatewizard.cpp smartcard/readerstatus.cpp smartcard/card.cpp smartcard/openpgpcard.cpp smartcard/netkeycard.cpp smartcard/pivcard.cpp smartcard/keypairinfo.cpp smartcard/utils.cpp ${_kleopatra_deviceinfowatcher_files} aboutdata.cpp systrayicon.cpp kleopatraapplication.cpp mainwindow.cpp main.cpp ) if(WIN32) configure_file (versioninfo.rc.in versioninfo.rc) set(_kleopatra_SRCS ${CMAKE_CURRENT_BINARY_DIR}/versioninfo.rc ${_kleopatra_SRCS}) endif() if(HAVE_KCMUTILS) set (_kleopatra_extra_libs KF5::KCMUtils) else() set (_kleopatra_SRCS conf/kleopageconfigdialog.cpp ${_kleopatra_SRCS}) endif() ecm_qt_declare_logging_category(_kleopatra_SRCS HEADER kleopatra_debug.h IDENTIFIER KLEOPATRA_LOG CATEGORY_NAME org.kde.pim.kleopatra DESCRIPTION "kleopatra (kleopatra)" OLD_CATEGORY_NAMES log_kleopatra EXPORT KLEOPATRA ) if(KLEO_MODEL_TEST) add_definitions(-DKLEO_MODEL_TEST) set(_kleopatra_SRCS ${_kleopatra_SRCS} models/modeltest.cpp) endif() ki18n_wrap_ui(_kleopatra_SRCS dialogs/expirydialog.ui dialogs/lookupcertificatesdialog.ui dialogs/ownertrustdialog.ui dialogs/selectchecklevelwidget.ui dialogs/selftestdialog.ui dialogs/adduseriddialog.ui dialogs/setinitialpindialog.ui dialogs/certificatedetailswidget.ui dialogs/trustchainwidget.ui dialogs/subkeyswidget.ui newcertificatewizard/listwidget.ui newcertificatewizard/chooseprotocolpage.ui newcertificatewizard/enterdetailspage.ui newcertificatewizard/overviewpage.ui newcertificatewizard/keycreationpage.ui newcertificatewizard/resultpage.ui newcertificatewizard/advancedsettingsdialog.ui ) kconfig_add_kcfg_files(_kleopatra_SRCS kcfg/tooltippreferences.kcfgc kcfg/emailoperationspreferences.kcfgc kcfg/fileoperationspreferences.kcfgc kcfg/smimevalidationpreferences.kcfgc ) file(GLOB ICONS_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/icons/*-apps-kleopatra.png") ecm_add_app_icon(_kleopatra_SRCS ICONS ${ICONS_SRCS}) qt5_add_resources(_kleopatra_SRCS kleopatra.qrc) add_executable(kleopatra_bin ${_kleopatra_SRCS} ${_kleopatra_uiserver_SRCS}) set_target_properties(kleopatra_bin PROPERTIES OUTPUT_NAME kleopatra) target_link_libraries(kleopatra_bin Gpgmepp QGpgme ${_kleopatra_extra_libs} KF5::Libkleo KF5::Mime KF5::I18n KF5::XmlGui KF5::IconThemes KF5::WindowSystem KF5::CoreAddons KF5::ItemModels KF5::Crash Qt5::Network Qt5::PrintSupport # Printing secret keys ${_kleopatra_uiserver_extra_libs} ${_kleopatra_dbusaddons_libs} kleopatraclientcore ) install(TARGETS kleopatra_bin ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install( PROGRAMS data/org.kde.kleopatra.desktop data/kleopatra_import.desktop DESTINATION ${KDE_INSTALL_APPDIR} ) install(FILES data/org.kde.kleopatra.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) install( FILES data/kleopatra_signencryptfiles.desktop data/kleopatra_signencryptfolders.desktop data/kleopatra_decryptverifyfiles.desktop data/kleopatra_decryptverifyfolders.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} ) diff --git a/src/dialogs/certificatedetailsinputwidget.cpp b/src/dialogs/certificatedetailsinputwidget.cpp new file mode 100644 index 000000000..74a747c6f --- /dev/null +++ b/src/dialogs/certificatedetailsinputwidget.cpp @@ -0,0 +1,348 @@ +/* -*- mode: c++; c-basic-offset:4 -*- + dialogs/certificatedetailsinputwidget.cpp + + This file is part of Kleopatra, the KDE keymanager + SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB + + SPDX-FileCopyrightText: 2020 g10 Code GmbH + SPDX-FileContributor: Ingo Klöcker + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#include "certificatedetailsinputwidget.h" + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "kleopatra_debug.h" + +using namespace Kleo; +using namespace Kleo::Dialogs; + +namespace +{ + struct Line { + QString attr; + QString label; + QString regex; + QLineEdit *edit; + bool required; + }; + + QString attributeFromKey(QString key) + { + return key.remove(QLatin1Char('!')); + } + + QString attributeLabel(const QString &attr) + { + if (attr.isEmpty()) { + return QString(); + } + const QString label = DNAttributeMapper::instance()->name2label(attr); + if (!label.isEmpty()) { + return i18nc("Format string for the labels in the \"Your Personal Data\" page", + "%1 (%2)", label, attr); + } else { + return attr; + } + } + + QLineEdit * addRow(QGridLayout *l, const QString &label, const QString &preset, QValidator *validator, bool readonly, bool required) + { + Q_ASSERT(l); + + QLabel *lb = new QLabel(l->parentWidget()); + lb->setText(i18nc("interpunctation for labels", "%1:", label)); + + QLineEdit *le = new QLineEdit(l->parentWidget()); + le->setText(preset); + delete le->validator(); + if (validator) { + if (!validator->parent()) { + validator->setParent(le); + } + le->setValidator(validator); + } + le->setReadOnly(readonly && le->hasAcceptableInput()); + + QLabel *reqLB = new QLabel(l->parentWidget()); + reqLB->setText(required ? i18n("(required)") : i18n("(optional)")); + + const int row = l->rowCount(); + l->addWidget(lb, row, 0); + l->addWidget(le, row, 1); + l->addWidget(reqLB, row, 2); + return le; + } + + bool hasIntermediateInput(const QLineEdit *le) + { + QString text = le->text(); + int pos = le->cursorPosition(); + const QValidator *const v = le->validator(); + return v && v->validate(text, pos) == QValidator::Intermediate; + } + + QString requirementsAreMet(const QVector &lines) + { + for (const Line &line : lines) { + const QLineEdit *le = line.edit; + if (!le) { + continue; + } + qCDebug(KLEOPATRA_LOG) << "requirementsAreMet(): checking \"" << line.attr << "\" against \"" << le->text() << "\":"; + if (le->text().trimmed().isEmpty()) { + if (line.required) { + if (line.regex.isEmpty()) { + return xi18nc("@info", "%1 is required, but empty.", line.label); + } else { + return xi18nc("@info", "%1 is required, but empty." + "Local Admin rule: %2", line.label, line.regex); + } + } + } else if (hasIntermediateInput(le)) { + if (line.regex.isEmpty()) { + return xi18nc("@info", "%1 is incomplete.", line.label); + } else { + return xi18nc("@info", "%1 is incomplete." + "Local Admin rule: %2", line.label, line.regex); + } + } else if (!le->hasAcceptableInput()) { + if (line.regex.isEmpty()) { + return xi18nc("@info", "%1 is invalid.", line.label); + } else { + return xi18nc("@info", "%1 is invalid." + "Local Admin rule: %2", line.label, line.regex); + } + } + } + return QString(); + } +} + +class CertificateDetailsInputWidget::Private +{ + friend class ::Kleo::Dialogs::CertificateDetailsInputWidget; + CertificateDetailsInputWidget *const q; + + struct { + QGridLayout *gridLayout; + QVector lines; + QLineEdit *dn; + QLabel *error; + } ui; + +public: + Private(CertificateDetailsInputWidget *qq) + : q(qq) + { + auto mainLayout = new QVBoxLayout(q); + + ui.gridLayout = new QGridLayout(); + mainLayout->addLayout(ui.gridLayout); + + mainLayout->addStretch(1); + + ui.dn = new QLineEdit(); + ui.dn->setFrame(false); + ui.dn->setAlignment(Qt::AlignCenter); + ui.dn->setReadOnly(true); + mainLayout->addWidget(ui.dn); + + ui.error = new QLabel(); + { + QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(ui.error->sizePolicy().hasHeightForWidth()); + ui.error->setSizePolicy(sizePolicy); + } + { + QPalette palette; + QBrush brush(QColor(255, 0, 0, 255)); + brush.setStyle(Qt::SolidPattern); + palette.setBrush(QPalette::Active, QPalette::WindowText, brush); + palette.setBrush(QPalette::Inactive, QPalette::WindowText, brush); + QBrush brush1(QColor(114, 114, 114, 255)); + brush1.setStyle(Qt::SolidPattern); + palette.setBrush(QPalette::Disabled, QPalette::WindowText, brush1); + ui.error->setPalette(palette); + } + ui.error->setTextFormat(Qt::RichText); + // set error label to have a fixed height of two lines: + ui.error->setText(QStringLiteral("2
1")); + ui.error->setFixedHeight(ui.error->minimumSizeHint().height()); + ui.error->clear(); + mainLayout->addWidget(ui.error); + + createForm(); + fixTabOrder(); + } + + ~Private() + { + } + + void createForm() + { + const KEMailSettings emailSettings; + const KConfigGroup config(KSharedConfig::openConfig(), "CertificateCreationWizard"); + + QStringList attrOrder = config.readEntry("DNAttributeOrder", QStringList()); + if (attrOrder.empty()) { + attrOrder << QStringLiteral("CN!") + << QStringLiteral("EMAIL!") + << QStringLiteral("L") + << QStringLiteral("OU") + << QStringLiteral("O!") + << QStringLiteral("C!"); + } + + for (const QString &rawKey : attrOrder) { + const QString key = rawKey.trimmed().toUpper(); + const QString attr = attributeFromKey(key); + if (attr.isEmpty()) { + continue; + } + const QString defaultPreset = (attr == QLatin1String("CN")) ? emailSettings.getSetting(KEMailSettings::RealName) : + (attr == QLatin1String("EMAIL")) ? emailSettings.getSetting(KEMailSettings::EmailAddress) : + QString(); + const QString preset = config.readEntry(attr, defaultPreset); + const bool required = key.endsWith(QLatin1Char('!')); + const bool readonly = config.isEntryImmutable(attr); + const QString label = config.readEntry(attr + QLatin1String("_label"), + attributeLabel(attr)); + const QString regex = config.readEntry(attr + QLatin1String("_regex")); + + QValidator *validator = nullptr; + if (attr == QLatin1String("EMAIL")) { + validator = regex.isEmpty() ? Validation::email() : Validation::email(QRegExp(regex)); + } else if (!regex.isEmpty()) { + validator = new QRegExpValidator(QRegExp(regex), nullptr); + } + + QLineEdit *le = addRow(ui.gridLayout, label, preset, validator, readonly, required); + + const Line line = { attr, label, regex, le, required }; + ui.lines.push_back(line); + + if (attr != QLatin1String("EMAIL")) { + connect(le, &QLineEdit::textChanged, [this] () { updateDN(); }); + } + connect(le, &QLineEdit::textChanged, [this] () { checkRequirements(); }); + } + } + + void fixTabOrder() + { + QVector widgets; + widgets.reserve(ui.lines.size() + 1); + for ( const Line &line : ui.lines ) { + widgets.push_back(line.edit); + } + widgets.push_back(ui.dn); + kdtools::for_each_adjacent_pair(widgets.begin(), widgets.end(), &QWidget::setTabOrder); + } + + void updateDN() + { + ui.dn->setText(cmsDN()); + } + + QString cmsDN() const + { + DN dn; + for ( const Line &line : ui.lines ) { + const QString text = line.edit->text().trimmed(); + if (text.isEmpty()) { + continue; + } + QString attr = attributeFromKey(line.attr); + if (attr == QLatin1String("EMAIL")) { + continue; + } + if (const char *const oid = oidForAttributeName(attr)) { + attr = QString::fromUtf8(oid); + } + dn.append(DN::Attribute(attr, text)); + } + return dn.dn(); + } + + void checkRequirements() + { + const QString error = requirementsAreMet(ui.lines); + ui.error->setText(error); + Q_EMIT q->validityChanged(error.isEmpty()); + } + + QLineEdit * attributeWidget(const QString &attribute) + { + for ( const Line &line : ui.lines ) { + if (attributeFromKey(line.attr) == attribute) { + return line.edit; + } + } + qCWarning(KLEOPATRA_LOG) << "CertificateDetailsInputWidget: No widget for attribute" << attribute; + return nullptr; + } + + void setAttributeValue(const QString &attribute, const QString &value) + { + QLineEdit *w = attributeWidget(attribute); + if (w) { + w->setText(value); + } + } + + QString attributeValue(const QString &attribute) + { + const QLineEdit *w = attributeWidget(attribute); + return w ? w->text().trimmed() : QString(); + } +}; + +CertificateDetailsInputWidget::CertificateDetailsInputWidget(QWidget *parent) + : QWidget(parent) + , d(new Private(this)) +{ +} + +CertificateDetailsInputWidget::~CertificateDetailsInputWidget() +{ +} + +void CertificateDetailsInputWidget::setName(const QString &name) +{ + d->setAttributeValue(QStringLiteral("CN"), name); +} + +void CertificateDetailsInputWidget::setEmail(const QString &email) +{ + d->setAttributeValue(QStringLiteral("EMAIL"), email); +} + +QString CertificateDetailsInputWidget::email() const +{ + return d->attributeValue(QStringLiteral("EMAIL")); +} + +QString CertificateDetailsInputWidget::dn() const +{ + return d->ui.dn->text(); +} diff --git a/src/dialogs/certificatedetailsinputwidget.h b/src/dialogs/certificatedetailsinputwidget.h new file mode 100644 index 000000000..91559de64 --- /dev/null +++ b/src/dialogs/certificatedetailsinputwidget.h @@ -0,0 +1,46 @@ +/* -*- mode: c++; c-basic-offset:4 -*- + dialogs/certificatedetailsinputwidget.h + + This file is part of Kleopatra, the KDE keymanager + SPDX-FileCopyrightText: 2020 g10 Code GmbH + SPDX-FileContributor: Ingo Klöcker + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#ifndef __KLEOPATRA_DIALOGS_CERTIFICATEDETAILSINPUTWIDGET_H__ +#define __KLEOPATRA_DIALOGS_CERTIFICATEDETAILSINPUTWIDGET_H__ + +#include + +namespace Kleo +{ +namespace Dialogs +{ + +class CertificateDetailsInputWidget : public QWidget +{ + Q_OBJECT +public: + explicit CertificateDetailsInputWidget(QWidget *parent = nullptr); + ~CertificateDetailsInputWidget() override; + + void setName(const QString &name); + + void setEmail(const QString &email); + QString email() const; + + QString dn() const; + +Q_SIGNALS: + void validityChanged(bool valid); + +private: + class Private; + const std::unique_ptr d; +}; + +} +} + +#endif // __KLEOPATRA_DIALOGS_CERTIFICATEDETAILSINPUTWIDGET_H__ diff --git a/src/dialogs/createcsrforcardkeydialog.cpp b/src/dialogs/createcsrforcardkeydialog.cpp new file mode 100644 index 000000000..41d7087b7 --- /dev/null +++ b/src/dialogs/createcsrforcardkeydialog.cpp @@ -0,0 +1,114 @@ +/* -*- mode: c++; c-basic-offset:4 -*- + dialogs/createcsrforcardkeydialog.h + + This file is part of Kleopatra, the KDE keymanager + SPDX-FileCopyrightText: 2020 g10 Code GmbH + SPDX-FileContributor: Ingo Klöcker + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#include "createcsrforcardkeydialog.h" + +#include "certificatedetailsinputwidget.h" + +#include +#include + +#include +#include +#include + +using namespace Kleo; +using namespace Kleo::Dialogs; + +class CreateCSRForCardKeyDialog::Private +{ + friend class ::Kleo::Dialogs::CreateCSRForCardKeyDialog; + CreateCSRForCardKeyDialog *const q; + + struct { + CertificateDetailsInputWidget *detailsWidget = nullptr; + QDialogButtonBox *buttonBox = nullptr; + } ui; + +public: + Private(CreateCSRForCardKeyDialog *qq) + : q(qq) + { + auto mainLayout = new QVBoxLayout(q); + + ui.detailsWidget = new CertificateDetailsInputWidget(); + connect(ui.detailsWidget, &CertificateDetailsInputWidget::validityChanged, + q, [this] (bool valid) { onValidityChanged(valid); }); + + ui.buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(ui.buttonBox, &QDialogButtonBox::accepted, q, &QDialog::accept); + connect(ui.buttonBox, &QDialogButtonBox::rejected, q, &QDialog::reject); + + mainLayout->addWidget(ui.detailsWidget); + mainLayout->addWidget(ui.buttonBox); + + // increase default width by 50 % to get more space for line edits + const QSize sizeHint = q->sizeHint(); + const QSize defaultSize = QSize(sizeHint.width() * 15 / 10, sizeHint.height()); + restoreGeometry(defaultSize); + } + + ~Private() + { + saveGeometry(); + } + + void onValidityChanged(bool valid) + { + ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(valid); + } + +private: + void saveGeometry() + { + KConfigGroup cfgGroup(KSharedConfig::openConfig(), "CreateCSRForCardKeyDialog"); + cfgGroup.writeEntry("Size", q->size()); + cfgGroup.sync(); + } + + void restoreGeometry(const QSize &defaultSize) + { + KConfigGroup cfgGroup(KSharedConfig::openConfig(), "CreateCSRForCardKeyDialog"); + const QSize size = cfgGroup.readEntry("Size", defaultSize); + if (size.isValid()) { + q->resize(size); + } + } +}; + +CreateCSRForCardKeyDialog::CreateCSRForCardKeyDialog(QWidget *parent) + : QDialog(parent) + , d(new Private(this)) +{ +} + +CreateCSRForCardKeyDialog::~CreateCSRForCardKeyDialog() +{ +} + +void CreateCSRForCardKeyDialog::setName(const QString &name) +{ + d->ui.detailsWidget->setName(name); +} + +void CreateCSRForCardKeyDialog::setEmail(const QString &email) +{ + d->ui.detailsWidget->setEmail(email); +} + +QString CreateCSRForCardKeyDialog::email() const +{ + return d->ui.detailsWidget->email(); +} + +QString CreateCSRForCardKeyDialog::dn() const +{ + return d->ui.detailsWidget->dn(); +} diff --git a/src/dialogs/createcsrforcardkeydialog.h b/src/dialogs/createcsrforcardkeydialog.h new file mode 100644 index 000000000..be11aabfb --- /dev/null +++ b/src/dialogs/createcsrforcardkeydialog.h @@ -0,0 +1,43 @@ +/* -*- mode: c++; c-basic-offset:4 -*- + dialogs/createcsrforcardkeydialog.h + + This file is part of Kleopatra, the KDE keymanager + SPDX-FileCopyrightText: 2020 g10 Code GmbH + SPDX-FileContributor: Ingo Klöcker + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#ifndef __KLEOPATRA_DIALOGS_CREATECSRFORCARDKEYDIALOG_H__ +#define __KLEOPATRA_DIALOGS_CREATECSRFORCARDKEYDIALOG_H__ + +#include + +namespace Kleo +{ +namespace Dialogs +{ + +class CreateCSRForCardKeyDialog : public QDialog +{ + Q_OBJECT +public: + explicit CreateCSRForCardKeyDialog(QWidget *parent = nullptr); + ~CreateCSRForCardKeyDialog() override; + + void setName(const QString &name); + + void setEmail(const QString &email); + QString email() const; + + QString dn() const; + +private: + class Private; + const std::unique_ptr d; +}; + +} +} + +#endif // __KLEOPATRA_DIALOGS_CREATECSRFORCARDKEYDIALOG_H__