From f3beb1624c24012c246d17a40c4e10c1c6b3b5b5 Mon Sep 17 00:00:00 2001 From: Thomas Vanbesien Date: Tue, 31 Mar 2026 17:44:35 +0200 Subject: Add passphrase-protected private key support Wire up QOpcUaClient::passwordForPrivateKeyRequired to a QML dialog, mirroring the existing certificate trust flow (local QEventLoop + 30s timeout). --- src/OpcUaClient.cpp | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'src/OpcUaClient.cpp') diff --git a/src/OpcUaClient.cpp b/src/OpcUaClient.cpp index a319f29..d212ab2 100644 --- a/src/OpcUaClient.cpp +++ b/src/OpcUaClient.cpp @@ -90,6 +90,8 @@ OpcUaClient::setupClient () &OpcUaClient::handleFindServersFinished); connect (m_client, &QOpcUaClient::errorChanged, this, &OpcUaClient::handleClientError); + connect (m_client, &QOpcUaClient::passwordForPrivateKeyRequired, this, + &OpcUaClient::handlePasswordRequired); } /* ====================================== @@ -326,6 +328,41 @@ OpcUaClient::handleConnectError (QOpcUaErrorState *errorState) } } +void +OpcUaClient::provideKeyPassword (const QString &password) +{ + m_keyPassword = password; + if (m_keyPassLoop) + m_keyPassLoop->quit (); +} + +void +OpcUaClient::cancelKeyPassword () +{ + m_keyPassword.clear (); + if (m_keyPassLoop) + m_keyPassLoop->quit (); +} + +void +OpcUaClient::handlePasswordRequired (QString keyFilePath, QString *password, + bool previousTryWasInvalid) +{ + // passwordForPrivateKeyRequired uses BlockingQueuedConnection — the backend + // thread is blocked waiting for us to return. Spin a local event loop so + // QML can show a dialog and call provideKeyPassword() / cancelKeyPassword(). + m_keyPassword.clear (); + emit privateKeyPasswordRequired (keyFilePath, previousTryWasInvalid); + + QEventLoop loop; + m_keyPassLoop = &loop; + QTimer::singleShot (30000, &loop, &QEventLoop::quit); + loop.exec (); + m_keyPassLoop = nullptr; + + *password = m_keyPassword; +} + void OpcUaClient::handleClientError (QOpcUaClient::ClientError error) { -- cgit v1.2.3