Page MenuHome GnuPG

No OneTemporary

diff --git a/client/setupdialogs.cpp b/client/setupdialogs.cpp
index c16ee58..11187cb 100644
--- a/client/setupdialogs.cpp
+++ b/client/setupdialogs.cpp
@@ -1,384 +1,387 @@
// SPDX-FileCopyrightText: 2026 g10 code Gmbh
// SPDX-Contributor: Carl Schwan <carl.schwan@gnupg.com>
// SPDX-Contributor: Thomas Friedrichsmeier <thomas.friedrichsmeier@gnupg.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "setupdialogs.h"
#include "config.h"
#include "connectioncontroller.h"
#include "gpgolweb_version.h"
#include "rootcagenerator/controller.h"
#include "websocketclient.h"
#include <KAssistantDialog>
#include <KLocalizedString>
#include <KTitleWidget>
#include <QApplication>
#include <QButtonGroup>
#include <QClipboard>
#include <QDialog>
#include <QDialogButtonBox>
+#include <QDir>
#include <QDesktopServices>
#include <QFile>
#include <QGroupBox>
#include <QLabel>
#include <QPushButton>
#include <QRadioButton>
#include <QSaveFile>
+#include <QSettings>
#include <QToolTip>
#include <QVBoxLayout>
#include "ui_confpageproxyoptions.h"
#include "ui_confpagetlscertificate.h"
using namespace Qt::StringLiterals;
PairingDialog::PairingDialog(QWidget *parent)
: QDialog(parent)
{
setWindowTitle(i18n("Pairing mode active"));
auto l = new QVBoxLayout(this);
auto lab = new QLabel(i18n("<p>Copy and paste the code shown below into the input field shown at the top of the Add-In:</p>"));
lab->setWordWrap(true);
l->addWidget(lab);
m_pairingTokenLabel = new QLabel(i18nc("status message", "<p align='center'><b>Obtaining token...</b></p>"));
l->addWidget(m_pairingTokenLabel);
auto bb = new QDialogButtonBox;
auto endButton = bb->addButton(i18nc("@button", "End pairing mode"), QDialogButtonBox::RejectRole);
connect(endButton, &QAbstractButton::clicked, this, &QDialog::reject);
m_copyButton = bb->addButton(i18nc("@button", "Copy code to clipboard"), QDialogButtonBox::ActionRole);
m_copyButton->setEnabled(false);
l->addWidget(bb);
setFixedSize(sizeHint());
connect(&WebsocketClient::self(), &WebsocketClient::pairingStatusChanged, this, &PairingDialog::pairingStatusChanged);
WebsocketClient::self().enterPairingMode();
}
void PairingDialog::pairingStatusChanged(const QString& token, bool pairingActive) {
if (!pairingActive) {
reject();
return;
}
m_pairingTokenLabel->setText(QString(u"<p align='center'><b>%1</b></p>").arg(token));
m_copyButton->setEnabled(true);
connect(m_copyButton, &QAbstractButton::clicked, [this, token]() {
qApp->clipboard()->setText(token);
});
}
class GenerateCertificateWidget : public QWidget {
Q_OBJECT
public:
GenerateCertificateWidget(bool assistant, QWidget *parent)
: QWidget(parent)
, m_controller(nullptr)
, m_installed(false)
, m_dialog(nullptr)
{
auto hbox = new QHBoxLayout(this);
hbox->setContentsMargins(0, 0, 0, 0);
m_label = new QLabel();
hbox->addWidget(m_label);
m_generateButton = new QPushButton();
m_generateButton->setVisible(!assistant);
if (!assistant) {
connect(m_generateButton, &QPushButton::clicked, this, [this]() {
KAssistantDialog dialog;
addAssistantPages(&dialog);
startGenerate();
dialog.exec();
});
}
hbox->addWidget(m_generateButton);
updateStatus();
}
void addAssistantPages(KAssistantDialog *dialog) {
m_dialog = dialog;
auto genPage = new QWidget();
auto vbox = new QVBoxLayout(genPage);
m_genProgress = new QPlainTextEdit();
vbox->addWidget(m_genProgress);
m_genDoneLabel = new QLabel();
vbox->addWidget(m_genDoneLabel);
m_genPageItem = new KPageWidgetItem(genPage);
m_genPageItem->setHeader(i18n("Generating TLS certificate"));
m_dialog->addPage(m_genPageItem);
auto installPage = new QWidget();
vbox = new QVBoxLayout(installPage);
m_installProgress = new QPlainTextEdit();
vbox->addWidget(m_installProgress);
m_installDoneLabel = new QLabel();
vbox->addWidget(m_installDoneLabel);
m_installPageItem = new KPageWidgetItem(installPage);
m_installPageItem->setHeader(i18n("Installing certificate"));
m_dialog->addPage(m_installPageItem);
connect(dialog, &KPageDialog::currentPageChanged, this,
[this](KPageWidgetItem *current, KPageWidgetItem *) {
if (current == m_genPageItem) {
startGenerate();
} else if (current == m_installPageItem) {
if (!m_installed) {
m_controller->install();
}
}
});
}
void updateStatus() {
if (Config::self()->isLocalServer()) {
setVisible(true);
if (Controller::certificateAlreadyGenerated()) {
m_label->setText(i18n("A TLS certificate has already been generated."));
m_generateButton->setText(i18n("Re-generate certificate"));
m_generateButton->setFixedSize(m_generateButton->minimumSizeHint());
//m_generateButton->setToolTip(i18n("Re-generates and installs a TLS certificate for a secure connection to the local proxy server. It is not usually necessary to repeat this step."));
} else {
m_label->setText(i18n("A TLS certificate is needed for the secure connection to the proxy."));
m_generateButton->setText(i18n("Generate and install certificate"));
if (m_dialog) {
m_label->setText(i18n("A TLS certificate is needed for the secure connection to the proxy. This will be generated in the next step."));
}
}
} else {
setVisible(false);
}
if (m_dialog) {
m_dialog->setAppropriate(m_genPageItem, Config::self()->isLocalServer() && !Controller::certificateAlreadyGenerated());
m_dialog->setAppropriate(m_installPageItem, Config::self()->isLocalServer() && !Controller::certificateAlreadyGenerated());
}
}
private:
QLabel *m_label;
QPushButton *m_generateButton;
QPlainTextEdit *m_genProgress, *m_installProgress;
QLabel *m_genDoneLabel, *m_installDoneLabel;
KPageWidgetItem *m_genPageItem, *m_installPageItem;
KAssistantDialog *m_dialog;
QPointer<Controller> m_controller; // it's a KJob and will auto-delete
bool m_installed;
void startGenerate() {
if (m_controller || m_installed) {
return;
}
m_dialog->setValid(m_genPageItem, false);
m_dialog->setValid(m_installPageItem, false);
m_controller = new Controller(this);
m_dialog->setValid(m_genPageItem, false);
connect(m_controller, &Controller::generationDone, this, [this]() {
m_genDoneLabel->setText(i18nc("@info", "Successfully generated certificate with fingerprint %1", m_controller->rootFingerprint()));
m_dialog->setValid(m_genPageItem, true);
});
connect(m_controller, &Controller::debutOutput, this, [this](const QString &output) {
m_genProgress->appendPlainText(output);
m_installProgress->appendPlainText(output);
});
connect(m_controller, &Controller::result, this, [this](KJob *) {
if (m_controller->error()) {
m_genProgress->appendPlainText(m_controller->errorText());
m_installProgress->appendPlainText(m_controller->errorText());
return;
}
m_label->setText(i18nc("@info", "Installed certificate with fingerprint: %1", m_controller->rootFingerprint()));
m_dialog->setValid(m_installPageItem, true);
m_installed = true;
});
m_controller->start();
}
};
void DialogController::doDialog(const QList<PageID> &pageIds, const bool assistant) {
KPageDialog *dialog = assistant ? new KAssistantDialog() : new KPageDialog();
if (pageIds.contains(PageProxy)) {
auto widget = new QWidget();
auto vbox = new QVBoxLayout(widget);
auto item = new KPageWidgetItem(widget, i18n("Proxy"));
item->setHeader(i18nc("@title", "Configure Proxy"));
dialog->addPage(item);
auto label = new QLabel(i18n("Choose your configuration for the proxy component:"));
vbox->addWidget(label);
label = new QLabel(i18n("Note: Changes to this setting only take effect after uploading the adjusted manifest file to Outlook on the next page!"));
auto font = label->font();
font.setItalic(true);
label->setFont(font);
label->setWordWrap(true);
vbox->addWidget(label);
auto certcontrol = new GenerateCertificateWidget(assistant, nullptr);
if (assistant) {
certcontrol->addAssistantPages(static_cast<KAssistantDialog*>(dialog));
}
auto grp = new QButtonGroup(widget);
auto localOption = new QRadioButton(i18n("Run a local proxy on this machine"));
localOption->setChecked(Config::self()->isLocalServer());
auto remoteOption = new QRadioButton(i18n("Use proxy from a remote server (EXPERIMENTAL)"));
remoteOption->setChecked(!Config::self()->isLocalServer());
grp->addButton(localOption);
vbox->addWidget(localOption);
grp->addButton(remoteOption);
vbox->addWidget(remoteOption);
auto hbox = new QHBoxLayout();
auto remoteLabel = new QLabel(i18n("Remote proxy server"));
hbox->addWidget(remoteLabel);
auto remoteServer = new QLineEdit();
remoteServer->setPlaceholderText(u"internal.company.com"_s);
remoteServer->setClearButtonEnabled(true);
hbox->addWidget(remoteServer);
vbox->addLayout(hbox);
QObject::connect(remoteOption, &QRadioButton::toggled, dialog, [remoteLabel, remoteServer, certcontrol](bool checked) {
Config::self()->setIsLocalServer(!checked);
Config::self()->save();
remoteLabel->setEnabled(!Config::self()->isLocalServer());
remoteServer->setEnabled(!Config::self()->isLocalServer());
certcontrol->updateStatus();
});
QObject::connect(remoteServer, &QLineEdit::textChanged, dialog, [remoteServer]() {
Config::self()->setRemoteAddress(QUrl::fromUserInput(remoteServer->text()));
Config::self()->save();
});
vbox->addWidget(certcontrol);
vbox->addStretch();
}
if (pageIds.contains(PageInstallAddin)) {
auto widget = new QWidget();
auto vbox = new QVBoxLayout(widget);
auto item = new KPageWidgetItem(widget);
item->setHeader(i18nc("@title", "Install Outlook Add-In"));
dialog->addPage(item);
auto label = new QLabel(i18n("<p>Before the first use, the add-in has to be activated in Outlook:</p>"
"<ol><li>Go to the <a href=\"%1\">Outlook Extension Manager</a> (you may be prompted to log in).<li>"
"<li><a href=\"%2\">Click here</a> to copy the manifest file name to your clipboard.</li>"
"<li>In Outlook, register this via <tt>My Add-Ins -> Custom Add-Ins -> Add a custom Add-In</tt></li>"
"<li>Click on any E-Mail, and activate the add-in by clicking on the GnuPG icon shown about the email header.</li>"
"<li>When prompted for a pairing code, <a href=\"%3\">click here to enter pairing mode</a>.</li></ol></p>",
u"https://outlook.office.com/mail/jsmvvmdeeplink/?path=/options/manageapps&amp;bO=4"_s,
u"copy"_s, u"pairing"_s));
label->setWordWrap(true);
QObject::connect(label, &QLabel::linkActivated, dialog, [label, dialog](const QString &url) {
if (url == u"copy"_s) {
QFile file(u":/gpgol-client/manifest.xml.in"_s);
if (!file.open(QIODeviceBase::ReadOnly)) {
Q_ASSERT(false);
return;
}
QByteArray manifest = file.readAll();
manifest.replace("%HOST%", ConnectionController::serverDomain().toUtf8());
manifest.replace("%VERSION%", GPGOLWEB_VERSION_STRING);
const auto saveFilePath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + u"/gpgol-web-manifest.xml"_s;
QSaveFile saveFile(saveFilePath);
if (!saveFile.open(QIODeviceBase::WriteOnly)) {
Q_ASSERT(false);
return;
}
saveFile.write(manifest);
saveFile.commit();
QGuiApplication::clipboard()->setText(saveFilePath);
QToolTip::showText(label->mapToGlobal(QPoint(10, 10)), i18n("Copied to clipboard."), label, QRect(), 2000);
} else if (url == u"pairing"_s) {
PairingDialog d(dialog);
d.exec();
WebsocketClient::self().quitPairingMode();
} else {
QDesktopServices::openUrl(QUrl(url));
}
});
vbox->addWidget(label);
auto title = new KTitleWidget();
title->setText(i18n("Troubleshooting"));
vbox->addWidget(title);
label = new QLabel(i18n("<p>If the extension is not connected:</p><ul>"
"<li>Test for problems with the TLS-certificate installation, by opening this <a href=\"%1\">test page</a>.</li>"
"<li>Sometimes the add-in icon is not immediately visible in the task-bar. Make sure to click on an existing message in Outlook. "
"You may also have to click on the \"Apps\" icon. From there, you should be allowed to \"pin\" the icon for easier access.</li>"
"<li>If you have just added the manifest, it may be necessary to reload.</li>"
"<li>If your account is organization managed, your administrator may have to allow usage of the GPGOL/Web add-in, manually.</li>"
"</ul></p>", u"https://"_s + ConnectionController::serverDomain() + u"/test"_s));
label->setWordWrap(true);
label->setOpenExternalLinks(true);
vbox->addWidget(label);
}
if (pageIds.contains(PageSettings)) {
auto widget = new QWidget();
auto vbox = new QVBoxLayout(widget);
auto featuresbox = new QGroupBox(i18n("Optional features"));
auto boxlayout = new QVBoxLayout(featuresbox);
auto reencrypt = new QCheckBox(i18n("Reencrypt email folders with new keys"), featuresbox);
reencrypt->setChecked(Config::self()->reencrypt());
QObject::connect(reencrypt, &QCheckBox::checkStateChanged, dialog, [](Qt::CheckState state) {
Config::self()->setReencrypt(state == Qt::Checked);
Config::self()->save();
});
boxlayout->addWidget(reencrypt);
vbox->addWidget(featuresbox);
auto startupbox = new QGroupBox(i18n("Startup behavior"));
boxlayout = new QVBoxLayout(startupbox);
- #ifdef Q_OS_WIN
+
+#ifdef Q_OS_WIN
auto autoStartBox = new QCheckBox(i18n("Start GPGOL/Web automatically"));
// We intentionally don't use our own config for this: If users disable autostart via
// the Windows settings menu, we want to respect that, too.
{
QSettings winreg(u"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"_s, QSettings::NativeFormat);
- autostartBox->setChecked(!winreg.value(QCoreApplication::applicationName()).toString().isEmpty());
+ autoStartBox->setChecked(!winreg.value(QCoreApplication::applicationName()).toString().isEmpty());
}
- connect(autostartBox, &QCheckBox::checkStateChanged, this, [this](Qt::CheckState state) {
+ QObject::connect(autoStartBox, &QCheckBox::checkStateChanged, dialog, [](Qt::CheckState state) {
QSettings winreg(u"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"_s, QSettings::NativeFormat);
if (state) {
winreg.setValue(QCoreApplication::applicationName(),
QDir::toNativeSeparators(QCoreApplication::applicationFilePath()));
} else {
winreg.remove(QCoreApplication::applicationName());
}
});
boxlayout->addWidget(autoStartBox);
#endif
auto showOnStartup = new QCheckBox(i18n("Show status dialog when starting"));
showOnStartup->setChecked(Config::self()->showLauncher());
QObject::connect(showOnStartup, &QCheckBox::checkStateChanged, dialog, [](Qt::CheckState state) {
Config::self()->setShowLauncher(state == Qt::Checked);
Config::self()->save();
});
boxlayout->addWidget(showOnStartup);
vbox->addWidget(startupbox);
vbox->addStretch();
auto item = new KPageWidgetItem(widget);
item->setHeader(i18nc("@title", "Options"));
dialog->addPage(item);
}
dialog->exec();
}
void DialogController::doFirstTimeAssistant()
{
doDialog(QList{PageProxy, PageInstallAddin, PageSettings}, true);
}
#include "setupdialogs.moc"

File Metadata

Mime Type
text/x-diff
Expires
Thu, Feb 26, 7:10 PM (16 h, 31 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
a8/54/373654eadbef48e34788425d5493

Event Timeline