From 33809bf988deb55bb5a2a2d5373a111bebe69a79 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Tue, 5 Jun 2018 23:21:38 +0200 Subject: [PATCH] improve connect page and translation handling even more --- libmea-core/discovery/discoverydevice.cpp | 1 + libmea-core/discovery/upnpdiscovery.cpp | 7 +- libmea-core/nymeaconnection.cpp | 16 ++-- libmea-core/nymeaconnection.h | 5 +- mea/ui/ConnectPage.qml | 99 ++++++++++++----------- 5 files changed, 70 insertions(+), 58 deletions(-) diff --git a/libmea-core/discovery/discoverydevice.cpp b/libmea-core/discovery/discoverydevice.cpp index 000fac6e..38f8e3be 100644 --- a/libmea-core/discovery/discoverydevice.cpp +++ b/libmea-core/discovery/discoverydevice.cpp @@ -91,6 +91,7 @@ QString DiscoveryDevice::toUrl(int portConfigIndex) PortConfig *pc = m_portConfigs->get(portConfigIndex); if (!pc) { qWarning() << "No portconfig for index" << portConfigIndex; + return QString(); } QString ret = pc->protocol() == PortConfig::ProtocolNymeaRpc ? "nymea" : "ws"; ret += pc->sslEnabled() ? "s" : ""; diff --git a/libmea-core/discovery/upnpdiscovery.cpp b/libmea-core/discovery/upnpdiscovery.cpp index 46c4845e..4f1da6e2 100644 --- a/libmea-core/discovery/upnpdiscovery.cpp +++ b/libmea-core/discovery/upnpdiscovery.cpp @@ -102,7 +102,7 @@ void UpnpDiscovery::writeDiscoveryPacket() "MX:2\r\n" "ST: ssdp:all\r\n\r\n"); - qDebug() << "sending discovery package"; +// qDebug() << "sending discovery package"; foreach (QUdpSocket* socket, m_sockets) { quint64 ret = socket->writeDatagram(ssdpSearchMessage, QHostAddress("239.255.255.250"), 1900); if (ret != ssdpSearchMessage.length()) { @@ -151,7 +151,6 @@ void UpnpDiscovery::readData() if (key.contains("Server") || key.contains("SERVER")) { if (value.contains("nymea")) { - qDebug() << " --> " << key << value; isNymea = true; } } @@ -162,10 +161,6 @@ void UpnpDiscovery::readData() } } - if (isNymea) { - qDebug() << "Found nymea device:" << location; - } - if (!m_foundDevices.contains(location) && isNymea) { m_foundDevices.append(location); qDebug() << "Getting server data from:" << location; diff --git a/libmea-core/nymeaconnection.cpp b/libmea-core/nymeaconnection.cpp index a1026438..551ff2cf 100644 --- a/libmea-core/nymeaconnection.cpp +++ b/libmea-core/nymeaconnection.cpp @@ -43,13 +43,19 @@ void NymeaConnection::disconnect() m_currentInterface->disconnect(); } -void NymeaConnection::acceptCertificate(const QByteArray &fingerprint) +void NymeaConnection::acceptCertificate(const QString &url, const QByteArray &fingerprint) { QSettings settings; settings.beginGroup("acceptedCertificates"); - settings.setValue(m_currentUrl.toString(), fingerprint); + settings.setValue(QUrl(url).host(), fingerprint); settings.endGroup(); - connect(m_currentUrl.toString()); +} + +bool NymeaConnection::isTrusted(const QString &url) +{ + QSettings settings; + settings.beginGroup("acceptedCertificates"); + return settings.contains(QUrl(url).host()); } bool NymeaConnection::connected() @@ -90,7 +96,7 @@ void NymeaConnection::onSslErrors(const QList &errors) QSettings settings; settings.beginGroup("acceptedCertificates"); - QByteArray storedFingerPrint = settings.value(m_currentUrl.toString()).toByteArray(); + QByteArray storedFingerPrint = settings.value(m_currentUrl.host()).toByteArray(); settings.endGroup(); QByteArray certificateFingerprint; @@ -115,7 +121,7 @@ void NymeaConnection::onSslErrors(const QList &errors) // info << tr("Name Qualifier:")<< error.certificate().issuerInfo(QSslCertificate::DistinguishedNameQualifier); // info << tr("Email:")<< error.certificate().issuerInfo(QSslCertificate::EmailAddress); - emit verifyConnectionCertificate(info, certificateFingerprint); + emit verifyConnectionCertificate(m_currentUrl.toString(), info, certificateFingerprint); } } else { // Reject the connection on all other errors... diff --git a/libmea-core/nymeaconnection.h b/libmea-core/nymeaconnection.h index 3e37f0c3..abdc0aa8 100644 --- a/libmea-core/nymeaconnection.h +++ b/libmea-core/nymeaconnection.h @@ -21,7 +21,8 @@ public: Q_INVOKABLE void connect(const QString &url); Q_INVOKABLE void disconnect(); - Q_INVOKABLE void acceptCertificate(const QByteArray &fingerprint); + Q_INVOKABLE void acceptCertificate(const QString &url, const QByteArray &fingerprint); + Q_INVOKABLE bool isTrusted(const QString &url); bool connected(); @@ -31,7 +32,7 @@ public: void sendData(const QByteArray &data); signals: - void verifyConnectionCertificate(const QStringList &issuerInfo, const QByteArray &fingerprint); + void verifyConnectionCertificate(const QString &url, const QStringList &issuerInfo, const QByteArray &fingerprint); void connectedChanged(bool connected); void connectionError(); void dataAvailable(const QByteArray &data); diff --git a/mea/ui/ConnectPage.qml b/mea/ui/ConnectPage.qml index 7c6ea5e8..d3f1ffa2 100644 --- a/mea/ui/ConnectPage.qml +++ b/mea/ui/ConnectPage.qml @@ -24,7 +24,7 @@ Page { target: Engine.connection onVerifyConnectionCertificate: { print("verify cert!") - var popup = certDialogComponent.createObject(app, {issuerInfo: issuerInfo, fingerprint: fingerprint}); + var popup = certDialogComponent.createObject(app, {url: url, issuerInfo: issuerInfo, fingerprint: fingerprint}); popup.open(); } onConnectionError: { @@ -118,41 +118,12 @@ Page { clip: true delegate: SwipeDelegate { + id: discoveryDeviceDelegate width: parent.width height: app.delegateHeight objectName: "discoveryDelegate" + index - contentItem: RowLayout { - ColumnLayout { - Layout.fillWidth: true - Label { - text: model.name - Layout.fillWidth: true - elide: Text.ElideRight - } - Label { - text: model.hostAddress - font.pixelSize: app.smallFont - } - } - ColorIcon { - Layout.fillHeight: true - Layout.preferredWidth: height - name: "../images/network-secure.svg" - visible: { - var discoveryDevice = discovery.discoveryModel.get(index); - for (var i = 0; i < discoveryDevice.portConfigs.count; i++) { - if (discoveryDevice.portConfigs.get(i).sslEnabled) { - return true; - } - } - return false; - } - } - } - - onClicked: { - var discoveryDevice = discovery.discoveryModel.get(index); - print("discoveryDevice:", discoveryDevice.name, discoveryDevice.uuid, discoveryDevice.hostAddress) + property var discoveryDevice: discovery.discoveryModel.get(index) + property string defaultPortConfigIndex: { var usedConfigIndex = 0; for (var i = 1; i < discoveryDevice.portConfigs.count; i++) { var oldConfig = discoveryDevice.portConfigs.get(usedConfigIndex); @@ -172,7 +143,36 @@ Page { usedConfigIndex = i; } } - Engine.connection.connect(discoveryDevice.toUrl(usedConfigIndex)) + return usedConfigIndex + } + + contentItem: RowLayout { + ColumnLayout { + Layout.fillWidth: true + Label { + text: model.name + Layout.fillWidth: true + elide: Text.ElideRight + } + Label { + text: model.hostAddress + font.pixelSize: app.smallFont + } + } + ColorIcon { + Layout.fillHeight: true + Layout.preferredWidth: height + property bool hasSecurePort: discoveryDeviceDelegate.discoveryDevice.portConfigs.get(discoveryDeviceDelegate.defaultPortConfigIndex).sslEnabled + property bool isTrusted: Engine.connection.isTrusted(discoveryDeviceDelegate.discoveryDevice.toUrl(discoveryDeviceDelegate.defaultPortConfigIndex)) + visible: hasSecurePort + name: "../images/network-secure.svg" + color: isTrusted ? app.guhAccent : keyColor + + } + } + + onClicked: { + Engine.connection.connect(discoveryDevice.toUrl(defaultPortConfigIndex)) pageStack.push(connectingPage) } @@ -191,7 +191,6 @@ Page { popup.open() } } - } Column { @@ -373,9 +372,12 @@ Page { y: (parent.height - height) / 2 standardButtons: Dialog.Yes | Dialog.No + property string url property var fingerprint property var issuerInfo + readonly property bool hasOldFingerprint: Engine.connection.isTrusted(url) + ColumnLayout { id: certLayout anchors.fill: parent @@ -387,16 +389,16 @@ Page { ColorIcon { Layout.preferredHeight: app.iconSize * 2 Layout.preferredWidth: height - name: "../images/dialog-warning-symbolic.svg" - color: app.guhAccent + name: certDialog.hasOldFingerprint ? "../images/lock-broken.svg" : "../images/info.svg" + color: certDialog.hasOldFingerprint ? "red" : app.guhAccent } Label { id: titleLabel Layout.fillWidth: true wrapMode: Text.WordWrap - text: qsTr("Warning") - color: app.guhAccent + text: certDialog.hasOldFingerprint ? qsTr("Warning") : qsTr("Hi there!") + color: certDialog.hasOldFingerprint ? "red" : app.guhAccent font.pixelSize: app.largeFont } } @@ -404,13 +406,13 @@ Page { Label { Layout.fillWidth: true wrapMode: Text.WordWrap - text: qsTr("The authenticity of this %1 box cannot be verified.").arg(app.systemName) + text: certDialog.hasOldFingerprint ? qsTr("The certificate of this %1 box has changed!").arg(app.systemName) : qsTr("It seems this is the first time you connect to this %1 box.").arg(app.systemName) } Label { Layout.fillWidth: true wrapMode: Text.WordWrap - text: qsTr("If this is the first time you connect to this box, this is expected. Once you trust a box, you should never see this message again for that one. If you see this message multiple times for the same box, something suspicious is going on!") + text: certDialog.hasOldFingerprint ? qsTr("Did you change the box's configuration? Verify if this information is correct.") : qsTr("This is the box's certificate. Once you trust it, an encrypted connection will be established.") } ThinDivider {} @@ -423,6 +425,10 @@ Page { contentHeight: certGridLayout.implicitHeight clip: true + ScrollBar.vertical: ScrollBar { + policy: contentHeight > height ? ScrollBar.AlwaysOn : ScrollBar.AsNeeded + } + GridLayout { id: certGridLayout columns: 2 @@ -452,14 +458,15 @@ Page { Label { Layout.fillWidth: true wrapMode: Text.WordWrap - text: qsTr("Do you want to trust this device?") + text: certDialog.hasOldFingerprint ? qsTr("Do you want to connect nevertheless?") : qsTr("Do you want to trust this device?") font.bold: true } } onAccepted: { - Engine.connection.acceptCertificate(certDialog.fingerprint) + Engine.connection.acceptCertificate(certDialog.url, certDialog.fingerprint) + Engine.connection.connect(certDialog.url) } } } @@ -576,8 +583,10 @@ Page { ColorIcon { Layout.preferredHeight: app.iconSize Layout.preferredWidth: height - name: model.sslEnabled ? "../images/network-secure.svg" : "../images/lock-broken.svg" - color: model.sslEnabled ? app.guhAccent : "red" + visible: model.sslEnabled + name: "../images/network-secure.svg" + property bool isTrusted: Engine.connection.isTrusted(dialog.discoveryDevice.toUrl(index)) + color: isTrusted ? app.guhAccent : keyColor } } onClicked: {