From 89972b872782698c48d9c919c5766240f0a81d41 Mon Sep 17 00:00:00 2001 From: Lauris Kaplinski Date: Thu, 21 May 2026 13:56:47 +0300 Subject: [PATCH 1/2] Return configuration error if keyserver is not known --- client/CDocSupport.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/client/CDocSupport.cpp b/client/CDocSupport.cpp index 47a4419d1..e49a4db0f 100644 --- a/client/CDocSupport.cpp +++ b/client/CDocSupport.cpp @@ -188,26 +188,33 @@ checkConnection() std::string DDConfiguration::getValue(std::string_view domain, std::string_view param) const { - std::string def = Settings::CDOC2_DEFAULT_KEYSERVER; if (param == libcdoc::Configuration::KEYSERVER_SEND_URL) { #ifdef CONFIG_URL QJsonObject list = Application::confValue(QLatin1String("CDOC2-CONF")).toObject(); + if (list.isEmpty()) return {}; QJsonObject data = list.value(QLatin1String(domain.data(), domain.size())).toObject(); - QString url = data.value(QLatin1String("POST")).toString(Settings::CDOC2_POST); + if (data.isEmpty()) return {}; + QString url = data.value(QLatin1String("POST")).toString(); return url.toStdString(); #else - QString url = Settings::CDOC2_POST; - return url.toStdString(); + if (domain == Settings::CDOC2_DEFAULT_KEYSERVER) { + QString url = Settings::CDOC2_POST; + return url.toStdString(); + } #endif } else if (param == libcdoc::Configuration::KEYSERVER_FETCH_URL) { #ifdef CONFIG_URL QJsonObject list = Application::confValue(QLatin1String("CDOC2-CONF")).toObject(); + if (list.isEmpty()) return {}; QJsonObject data = list.value(QLatin1String(domain.data(), domain.size())).toObject(); - QString url = data.value(QLatin1String("FETCH")).toString(Settings::CDOC2_GET); + if (data.isEmpty()) return {}; + QString url = data.value(QLatin1String("FETCH")).toString(); return url.toStdString(); #else - QString url = Settings::CDOC2_GET; - return url.toStdString(); + if (domain == Settings::CDOC2_DEFAULT_KEYSERVER) { + QString url = Settings::CDOC2_GET; + return url.toStdString(); + } #endif } return {}; From 735e56fca55e88111ee6a059a7d94254630e3a3e Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Tue, 25 Aug 2026 09:53:24 +0300 Subject: [PATCH 2/2] Harden WarningDialog text handling IB-9051 Signed-off-by: Raul Metsma --- client/Application.cpp | 8 ++++---- client/CryptoDoc.cpp | 2 +- client/DigiDoc.cpp | 6 +++--- client/dialogs/AddRecipients.cpp | 4 ++-- client/dialogs/MobileProgress.cpp | 12 ++++++++---- client/dialogs/SettingsDialog.cpp | 4 ++-- client/dialogs/SmartIDProgress.cpp | 16 ++++++++++------ client/dialogs/WarningDialog.cpp | 16 ++++++++++++++++ client/dialogs/WarningDialog.h | 1 + client/dialogs/WarningDialog.ui | 16 +++++++++++----- client/widgets/FileList.cpp | 2 +- client/widgets/VerifyCert.cpp | 12 ++++++------ 12 files changed, 65 insertions(+), 34 deletions(-) diff --git a/client/Application.cpp b/client/Application.cpp index 66b4107d5..94976ff0b 100644 --- a/client/Application.cpp +++ b/client/Application.cpp @@ -199,7 +199,7 @@ class DigidocConf final: public digidoc::XmlConfCurrent dispatchToMain([] { WarningDialog::create() ->withTitle(Application::tr("The renewal of Trust Service status List has failed")) - ->withText(Application::tr( + ->withRichText(Application::tr( "Trust Service status List is used for digital signature validation. " "Please check your internet connection and make sure you have the latest ID-software version " "installed. An expired Trust Service List (TSL) will be used for signature validation. " @@ -372,7 +372,7 @@ Application::Application( int &argc, char **argv ) { dlg = WarningDialog::create() ->withTitle(tr("This version of ID-software on your computer is unsupported")) - ->withText(tr("DigiDoc4 Client cannot be used until you update ID-software. " + ->withRichText(tr("DigiDoc4 Client cannot be used until you update ID-software. " "Install new ID-software from www.id.ee. " "macOS users can download the latest ID-software version from the " "Mac App Store.")); @@ -382,7 +382,7 @@ Application::Application( int &argc, char **argv ) { dlg = WarningDialog::create() ->withTitle(tr("Your ID-software has expired")) - ->withText(tr("To download the latest software version, go to the " + ->withRichText(tr("To download the latest software version, go to the " "id.ee website. " "macOS users can download the latest ID-software version from the " "Mac App Store.")); @@ -392,7 +392,7 @@ Application::Application( int &argc, char **argv ) { auto *dlg = WarningDialog::create(activeWindow()) ->withTitle(tr("An ID-software update has been found")) - ->withText(tr("To download the update, go to the " + ->withRichText(tr("To download the update, go to the " "id.ee website. " "macOS users can download the update from the " "Mac App Store.")); diff --git a/client/CryptoDoc.cpp b/client/CryptoDoc.cpp index a285cbaa9..16f39862f 100644 --- a/client/CryptoDoc.cpp +++ b/client/CryptoDoc.cpp @@ -122,7 +122,7 @@ bool CDocumentModel::addFile(const QString &file, const QString &mime) { WarningDialog::create() ->withTitle(DocumentModel::tr("Failed to add file")) - ->withText(tr("Added file(s) exceeds the maximum size limit of the container (∼120MB). " + ->withRichText(tr("Added file(s) exceeds the maximum size limit of the container (∼120MB). " "Read more about it")) ->open(); return false; diff --git a/client/DigiDoc.cpp b/client/DigiDoc.cpp index 8409b55b4..3b50da02d 100644 --- a/client/DigiDoc.cpp +++ b/client/DigiDoc.cpp @@ -64,7 +64,7 @@ struct ServiceConfirmation final: public ContainerOpenCB return dispatchToMain([this] { return WarningDialog::create(parent) ->withTitle(DigiDoc::tr("Send document to SiVa")) - ->withText(DigiDoc::tr( + ->withRichText(DigiDoc::tr( "This type of signed document will be transmitted to the " "Digital Signature Validation Service SiVa to verify the validity of the digital signature. " "Read more information about transmitted data to Digital Signature Validation service from " @@ -735,14 +735,14 @@ void DigiDoc::setLastError(const QString &title, const Exception &e) case Exception::CertificateUnknown: dlg->withText(tr("Certificate status unknown")); break; case Exception::OCSPTimeSlot: - dlg->withText(tr("Please check your computer time. Additional information")); break; + dlg->withRichText(tr("Please check your computer time. Additional information")); break; case Exception::OCSPRequestUnauthorized: dlg->withText(tr("You have not granted IP-based access. " "Check your validity confirmation service access settings.")); break; case Exception::TSForbidden: dlg->withText(tr("Check your Time-Stamping service access settings.")); break; case Exception::TSTooManyRequests: - dlg->withText(tr("The limit for digital signatures per month has been reached for this IP address. " + dlg->withRichText(tr("The limit for digital signatures per month has been reached for this IP address. " "Additional information")); break; case Exception::PINCanceled: dlg->deleteLater(); diff --git a/client/dialogs/AddRecipients.cpp b/client/dialogs/AddRecipients.cpp index d49c5b38b..55f14fcff 100644 --- a/client/dialogs/AddRecipients.cpp +++ b/client/dialogs/AddRecipients.cpp @@ -264,7 +264,7 @@ void AddRecipients::addRecipientToRightPane(Item *item, bool update) ->open(); return; } - auto *dlg = WarningDialog::create(this)->withText(tr( + auto *dlg = WarningDialog::create(this)->withRichText(tr( "Are you sure that you want use certificate for encrypting, which expired on %1?
" "When decrypter has updated certificates then decrypting is impossible.") .arg(expiryDate.toString(QStringLiteral("dd.MM.yyyy hh:mm:ss")))) @@ -403,7 +403,7 @@ void AddRecipients::showResult(const QList &result, int resultC else if(--multiSearch <= 0 && ui->leftPane->items.isEmpty()) WarningDialog::create(this) ->withTitle(tr("Person or company does not own a valid certificate")) - ->withText(tr("It is necessary to have a valid certificate for encryption.
" + ->withRichText(tr("It is necessary to have a valid certificate for encryption.
" "Read more about it.")) ->open(); QApplication::restoreOverrideCursor(); diff --git a/client/dialogs/MobileProgress.cpp b/client/dialogs/MobileProgress.cpp index d78131636..2938728d2 100644 --- a/client/dialogs/MobileProgress.cpp +++ b/client/dialogs/MobileProgress.cpp @@ -100,12 +100,16 @@ background-color: #007aff; d->manager->setParent(d); QObject::connect(d->manager, &QNetworkAccessManager::finished, d, [=, this](QNetworkReply *reply) { QScopedPointer scope(reply); - auto returnError = [=, this](const QString &err, const QString &details = {}) { + auto returnError = [=, this](const QString &err, const QString &details = {}, bool richText = false) { qCWarning(MIDLog) << err; d->statusTimer->stop(); d->hide(); - auto *dlg = WarningDialog::create(d->parentWidget())->withText(err)->withDetails(details) - ->withTitle(QCoreApplication::translate("DigiDoc", "Failed to sign container")); + auto *dlg = WarningDialog::create(d->parentWidget()); + if(richText) + dlg->withRichText(err); + else + dlg->withText(err); + dlg->withDetails(details)->withTitle(QCoreApplication::translate("DigiDoc", "Failed to sign container")); QObject::connect(dlg, &WarningDialog::finished, &d->l, &QEventLoop::exit); dlg->open(); }; @@ -137,7 +141,7 @@ background-color: #007aff; return returnError(tr("Failed to send request. The number of unsuccesful request from this IP address has been exceeded. Please try again later.")); case 429: return returnError(tr("The limit for %1 digital signatures per month has been reached. " - "Additional information").arg(tr("mobile-ID"))); + "Additional information").arg(tr("mobile-ID")), {}, true); case 580: return returnError(tr("Failed to send request. A valid session is associated with this personal code. " "It is not possible to start a new signing before the current session expires. Please try again later.")); diff --git a/client/dialogs/SettingsDialog.cpp b/client/dialogs/SettingsDialog.cpp index dff6252c5..4f52a6b38 100644 --- a/client/dialogs/SettingsDialog.cpp +++ b/client/dialogs/SettingsDialog.cpp @@ -304,12 +304,12 @@ SettingsDialog::SettingsDialog(int page, QWidget *parent) #ifdef Q_OS_MACOS WarningDialog::create(this) ->withTitle(tr("Restart DigiDoc4 Client to activate logging")) - ->withText(tr("Read more here.")) + ->withRichText(tr("Read more here.")) ->open(); #else auto *dlg = WarningDialog::create(this) ->withTitle(tr("Restart DigiDoc4 Client to activate logging")) - ->withText(tr("Read more here. Restart now?")) + ->withRichText(tr("Read more here. Restart now?")) ->setCancelText(WarningDialog::NO) ->addButton(WarningDialog::YES, QMessageBox::Yes); connect(dlg, &WarningDialog::finished, qApp, [](int result) { diff --git a/client/dialogs/SmartIDProgress.cpp b/client/dialogs/SmartIDProgress.cpp index 97afb60fd..edaa49db6 100644 --- a/client/dialogs/SmartIDProgress.cpp +++ b/client/dialogs/SmartIDProgress.cpp @@ -112,14 +112,18 @@ background-color: #007aff; d->manager->setParent(d); QNetworkAccessManager::connect(d->manager, &QNetworkAccessManager::finished, d, [&, this](QNetworkReply *reply){ QScopedPointer scope(reply); - auto returnError = [=, this](const QString &err, const QString &details = {}) { + auto returnError = [=, this](const QString &err, const QString &details = {}, bool richText = false) { qCWarning(SIDLog) << err; d->statusTimer->stop(); delete d->timer; d->timer = nullptr; d->hide(); - auto *dlg = WarningDialog::create(d->parentWidget())->withText(err)->withDetails(details) - ->withTitle(QCoreApplication::translate("DigiDoc", "Failed to sign container")); + auto *dlg = WarningDialog::create(d->parentWidget()); + if(richText) + dlg->withRichText(err); + else + dlg->withText(err); + dlg->withDetails(details)->withTitle(QCoreApplication::translate("DigiDoc", "Failed to sign container")); QObject::connect(dlg, &WarningDialog::finished, &d->l, &QEventLoop::exit); dlg->open(); }; @@ -147,17 +151,17 @@ background-color: #007aff; { case 403: return returnError(tr("Check your %1 service access settings. " - "Additional information").arg(tr("Smart-ID"))); + "Additional information").arg(tr("Smart-ID")), {}, true); case 409: return returnError(tr("Failed to send request. The number of unsuccesful request from this IP address has been exceeded. Please try again later.")); case 429: return returnError(tr("The limit for %1 digital signatures per month has been reached. " - "Additional information").arg(tr("Smart-ID"))); + "Additional information").arg(tr("Smart-ID")), {}, true); case 471: return returnError(tr("Your Smart-ID certificate level must be qualified to sign documents in DigiDoc4 Client.")); case 480: return returnError(tr("Your signing software needs an upgrade. Please update your ID software, which you can get from " - "www.id.ee. Additional info is available ID-helpline (+372) 666 8888.")); + "www.id.ee. Additional info is available ID-helpline (+372) 666 8888."), {}, true); case 580: return returnError(tr("Failed to send request. A valid session is associated with this personal code. " "It is not possible to start a new signing before the current session expires. Please try again later.")); diff --git a/client/dialogs/WarningDialog.cpp b/client/dialogs/WarningDialog.cpp index 0ec547e96..fc49f8dfa 100644 --- a/client/dialogs/WarningDialog.cpp +++ b/client/dialogs/WarningDialog.cpp @@ -153,12 +153,25 @@ WarningDialog* WarningDialog::create(QWidget *parent) WarningDialog* WarningDialog::withText(const QString &text) { + ui->text->setTextFormat(Qt::PlainText); + ui->text->setOpenExternalLinks(false); + ui->text->setTextInteractionFlags(Qt::TextSelectableByMouse|Qt::TextSelectableByKeyboard); + ui->text->setText(text); + ui->text->setHidden(text.isEmpty()); + return this; +} +WarningDialog* WarningDialog::withRichText(const QString &text) +{ + ui->text->setTextFormat(Qt::RichText); + ui->text->setOpenExternalLinks(true); + ui->text->setTextInteractionFlags(Qt::TextBrowserInteraction); ui->text->setText(text); ui->text->setHidden(text.isEmpty()); return this; } WarningDialog* WarningDialog::withTitle(const QString &title) { + ui->title->setTextFormat(Qt::PlainText); ui->title->setText(title); ui->title->setHidden(title.isEmpty()); return this; @@ -166,6 +179,9 @@ WarningDialog* WarningDialog::withTitle(const QString &title) WarningDialog* WarningDialog::withDetails(const QString &details) { + ui->details->setTextFormat(Qt::PlainText); + ui->details->setOpenExternalLinks(false); + ui->details->setTextInteractionFlags(Qt::TextSelectableByMouse|Qt::TextSelectableByKeyboard); ui->details->setText(details); ui->details->hide(); ui->showDetails->setHidden(details.isEmpty()); diff --git a/client/dialogs/WarningDialog.h b/client/dialogs/WarningDialog.h index 3169c0fb2..042db53ce 100644 --- a/client/dialogs/WarningDialog.h +++ b/client/dialogs/WarningDialog.h @@ -48,6 +48,7 @@ class WarningDialog final: public QDialog WarningDialog *resetCancelStyle(bool warning); WarningDialog *withTitle(const QString &text); WarningDialog *withText(const QString &text); + WarningDialog *withRichText(const QString &text); WarningDialog *withDetails(const QString &details); static WarningDialog *create(QWidget *parent = {}); diff --git a/client/dialogs/WarningDialog.ui b/client/dialogs/WarningDialog.ui index eecd215a5..dbeb49013 100644 --- a/client/dialogs/WarningDialog.ui +++ b/client/dialogs/WarningDialog.ui @@ -88,6 +88,9 @@ background-color: #E1C1C6; Qt::AlignCenter + + Qt::PlainText + @@ -99,16 +102,16 @@ background-color: #E1C1C6; Qt::TabFocus - Qt::RichText + Qt::PlainText true - true + false - Qt::TextBrowserInteraction + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse @@ -153,14 +156,17 @@ margin: 0px 15px 0px 15px; Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + Qt::PlainText + true - true + false - Qt::TextBrowserInteraction + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse diff --git a/client/widgets/FileList.cpp b/client/widgets/FileList.cpp index eb78a6dd2..d6fc80673 100644 --- a/client/widgets/FileList.cpp +++ b/client/widgets/FileList.cpp @@ -166,7 +166,7 @@ void FileList::saveAll() } b = WarningDialog::create(this) ->withTitle(FileDialog::tr("Failed to save files")) - ->withText(tr("%1 already exists.
Do you want replace it?").arg(dest)) + ->withRichText(tr("%1 already exists.
Do you want replace it?").arg(dest.toHtmlEscaped())) ->setCancelText(WarningDialog::Cancel) ->addButton(WarningDialog::YES, QMessageBox::Yes) ->addButton(WarningDialog::NO, QMessageBox::No) diff --git a/client/widgets/VerifyCert.cpp b/client/widgets/VerifyCert.cpp index 29b95ff94..4090d83bc 100644 --- a/client/widgets/VerifyCert.cpp +++ b/client/widgets/VerifyCert.cpp @@ -64,24 +64,24 @@ VerifyCert::VerifyCert(QWidget *parent) case SslCertificate::Revoked: if(SslCertificate::CertType::TempelType == c.type()) dlg->withTitle(tr("Certificate is not valid")) - ->withText(tr("A valid certificate is required for electronic use. ") + readMore); + ->withRichText(tr("A valid certificate is required for electronic use. ") + readMore); else if(c.keyUsage().contains(SslCertificate::NonRepudiation)) dlg->withTitle(tr("Your ID-card signing certificate is not valid")) - ->withText(tr("You need valid certificates to use your ID-card electronically. ") + readMore); + ->withRichText(tr("You need valid certificates to use your ID-card electronically. ") + readMore); else dlg->withTitle(tr("Your ID-card authentication certificate is not valid")) - ->withText(tr("You need valid certificates to use your ID-card electronically. ") + readMore); + ->withRichText(tr("You need valid certificates to use your ID-card electronically. ") + readMore); break; case SslCertificate::Unknown: if(SslCertificate::CertType::TempelType == c.type()) dlg->withTitle(tr("Certificate status is unknown")) - ->withText(tr("A valid certificate is required for electronic use. ") + readMore); + ->withRichText(tr("A valid certificate is required for electronic use. ") + readMore); else if(c.keyUsage().contains(SslCertificate::NonRepudiation)) dlg->withTitle(tr("Your ID-card signing certificate status is unknown")) - ->withText(tr("You need valid certificates to use your ID-card electronically. ") + readMore); + ->withRichText(tr("You need valid certificates to use your ID-card electronically. ") + readMore); else dlg->withTitle(tr("Your ID-card authentication certificate status is unknown")) - ->withText(tr("You need valid certificates to use your ID-card electronically. ") + readMore); + ->withRichText(tr("You need valid certificates to use your ID-card electronically. ") + readMore); break; default: dlg->withTitle(tr("Certificate status check failed"))