From 53d7a92a0da13b671f4fbe3a8d58ad9dcd5af235 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Tue, 1 Nov 2022 23:12:42 +0300 Subject: [PATCH 01/13] added import of configs in .ovpn format - on the "OpenVPN Settings" page, such a config will be displayed as raw text --- client/settings.cpp | 7 + client/settings.h | 2 + .../ui/pages_logic/ServerContainersLogic.cpp | 3 +- client/ui/pages_logic/StartPageLogic.cpp | 69 +- client/ui/pages_logic/StartPageLogic.h | 1 + .../ui/pages_logic/protocols/CloakLogic.cpp | 2 +- client/ui/pages_logic/protocols/CloakLogic.h | 2 +- .../ui/pages_logic/protocols/OpenVpnLogic.cpp | 12 +- .../ui/pages_logic/protocols/OpenVpnLogic.h | 5 +- .../protocols/OtherProtocolsLogic.cpp | 2 +- .../protocols/OtherProtocolsLogic.h | 2 +- .../protocols/PageProtocolLogicBase.h | 2 +- .../protocols/ShadowSocksLogic.cpp | 2 +- .../pages_logic/protocols/ShadowSocksLogic.h | 2 +- .../qml/Pages/Protocols/PageProtoOpenVPN.qml | 639 +++++++++--------- 15 files changed, 430 insertions(+), 322 deletions(-) diff --git a/client/settings.cpp b/client/settings.cpp index 6e470a33..ccef9e40 100644 --- a/client/settings.cpp +++ b/client/settings.cpp @@ -312,3 +312,10 @@ ServerCredentials Settings::serverCredentials(int index) const return credentials; } + +bool Settings::isThirdPartyConfig(int serverIndex) const +{ + if (serverIndex < 0) return false; + const QJsonObject &s = server(serverIndex); + return s.value("isThirdPartyConfig").toBool(); +} diff --git a/client/settings.h b/client/settings.h index c78b9a79..56b28c18 100644 --- a/client/settings.h +++ b/client/settings.h @@ -113,6 +113,8 @@ public: QByteArray backupAppConfig() const { return m_settings.backupAppConfig(); } bool restoreAppConfig(const QByteArray &cfg) { return m_settings.restoreAppConfig(cfg); } + bool isThirdPartyConfig(int serverIndex) const; + private: SecureQSettings m_settings; diff --git a/client/ui/pages_logic/ServerContainersLogic.cpp b/client/ui/pages_logic/ServerContainersLogic.cpp index 27f865b5..ba873eb2 100644 --- a/client/ui/pages_logic/ServerContainersLogic.cpp +++ b/client/ui/pages_logic/ServerContainersLogic.cpp @@ -38,7 +38,8 @@ void ServerContainersLogic::onPushButtonProtoSettingsClicked(DockerContainer c, uiLogic()->selectedDockerContainer = c; uiLogic()->protocolLogic(p)->updateProtocolPage(m_settings->protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, p), uiLogic()->selectedDockerContainer, - m_settings->haveAuthData(uiLogic()->selectedServerIndex)); + m_settings->haveAuthData(uiLogic()->selectedServerIndex), + m_settings->isThirdPartyConfig(uiLogic()->selectedServerIndex)); emit uiLogic()->goToProtocolPage(p); } diff --git a/client/ui/pages_logic/StartPageLogic.cpp b/client/ui/pages_logic/StartPageLogic.cpp index 1e28d6cd..6a6333e9 100644 --- a/client/ui/pages_logic/StartPageLogic.cpp +++ b/client/ui/pages_logic/StartPageLogic.cpp @@ -15,6 +15,25 @@ #include "platforms/android/android_controller.h" #endif +namespace { +QString checkConfigFormat(const QString &config) +{ + const QString openVpnConfigPatternCli = "client"; + const QString openVpnConfigPatternProto1 = "proto tcp"; + const QString openVpnConfigPatternProto2 = "proto udp"; + const QString openVpnConfigPatternDriver1 = "dev tun"; + const QString openVpnConfigPatternDriver2 = "dev tap"; + + if (config.contains(openVpnConfigPatternCli) && + (config.contains(openVpnConfigPatternProto1) || config.contains(openVpnConfigPatternProto2)) && + (config.contains(openVpnConfigPatternDriver1) || config.contains(openVpnConfigPatternDriver2))) { + return "OpenVpn"; + } + return "Amnezia"; +} + +} + StartPageLogic::StartPageLogic(UiLogic *logic, QObject *parent): PageLogicBase(logic, parent), m_pushButtonConnectEnabled{true}, @@ -136,7 +155,7 @@ void StartPageLogic::onPushButtonImport() void StartPageLogic::onPushButtonImportOpenFile() { QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open profile"), - QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.vpn"); + QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.vpn *.ovpn"); if (fileName.isEmpty()) return; @@ -144,7 +163,12 @@ void StartPageLogic::onPushButtonImportOpenFile() file.open(QIODevice::ReadOnly); QByteArray data = file.readAll(); - importConnectionFromCode(QString(data)); + auto configFormat = checkConfigFormat(QString(data)); + if (configFormat == "OpenVpn") { + importConnectionFromOpenVpnConfig(QString(data)); + } else { + importConnectionFromCode(QString(data)); + } } bool StartPageLogic::importConnection(const QJsonObject &profile) @@ -214,3 +238,44 @@ bool StartPageLogic::importConnectionFromQr(const QByteArray &data) return false; } + +bool StartPageLogic::importConnectionFromOpenVpnConfig(const QString &config) +{ + QJsonObject openVpnConfig; + openVpnConfig[config_key::config] = config; + + QJsonObject lastConfig; + lastConfig[config_key::last_config] = QString(QJsonDocument(openVpnConfig).toJson()); + + QJsonObject containers; + containers.insert(config_key::container, QJsonValue("amnezia-openvpn")); + containers.insert("openvpn", QJsonValue(lastConfig)); + + QJsonArray arr; + arr.push_back(containers); + + QJsonObject o; + o[config_key::containers] = arr; + o[config_key::defaultContainer] = "amnezia-openvpn"; + o[config_key::description] = "OpenVpn server"; + + + const static QRegularExpression dnsRegExp("dhcp-option DNS \\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b"); + QRegularExpressionMatchIterator dnsMatch = dnsRegExp.globalMatch(config); + if (dnsMatch.hasNext()) { + o[config_key::dns1] = dnsMatch.next().captured(0).split(" ").at(2); + } + if (dnsMatch.hasNext()) { + o[config_key::dns2] = dnsMatch.next().captured(0).split(" ").at(2); + } + + const static QRegularExpression hostNameRegExp("remote \\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b"); + QRegularExpressionMatch hostNameMatch = hostNameRegExp.match(config); + if (hostNameMatch.hasMatch()) { + o[config_key::hostName] = hostNameMatch.captured(0).split(" ").at(1); + } + + o["isThirdPartyConfig"] = true; + + return importConnection(o); +} diff --git a/client/ui/pages_logic/StartPageLogic.h b/client/ui/pages_logic/StartPageLogic.h index 24bdc53f..830c9100 100644 --- a/client/ui/pages_logic/StartPageLogic.h +++ b/client/ui/pages_logic/StartPageLogic.h @@ -32,6 +32,7 @@ public: bool importConnection(const QJsonObject &profile); bool importConnectionFromCode(QString code); bool importConnectionFromQr(const QByteArray &data); + bool importConnectionFromOpenVpnConfig(const QString &config); public: explicit StartPageLogic(UiLogic *uiLogic, QObject *parent = nullptr); diff --git a/client/ui/pages_logic/protocols/CloakLogic.cpp b/client/ui/pages_logic/protocols/CloakLogic.cpp index 59019990..9faa5996 100644 --- a/client/ui/pages_logic/protocols/CloakLogic.cpp +++ b/client/ui/pages_logic/protocols/CloakLogic.cpp @@ -23,7 +23,7 @@ CloakLogic::CloakLogic(UiLogic *logic, QObject *parent): } -void CloakLogic::updateProtocolPage(const QJsonObject &ckConfig, DockerContainer container, bool haveAuthData) +void CloakLogic::updateProtocolPage(const QJsonObject &ckConfig, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig) { set_pageEnabled(haveAuthData); set_pushButtonSaveVisible(haveAuthData); diff --git a/client/ui/pages_logic/protocols/CloakLogic.h b/client/ui/pages_logic/protocols/CloakLogic.h index d88252c8..8d4450fb 100644 --- a/client/ui/pages_logic/protocols/CloakLogic.h +++ b/client/ui/pages_logic/protocols/CloakLogic.h @@ -28,7 +28,7 @@ public: explicit CloakLogic(UiLogic *uiLogic, QObject *parent = nullptr); ~CloakLogic() = default; - void updateProtocolPage (const QJsonObject &ckConfig, DockerContainer container, bool haveAuthData) override; + void updateProtocolPage(const QJsonObject &ckConfig, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig) override; QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override; private: diff --git a/client/ui/pages_logic/protocols/OpenVpnLogic.cpp b/client/ui/pages_logic/protocols/OpenVpnLogic.cpp index 91f21151..7d726670 100644 --- a/client/ui/pages_logic/protocols/OpenVpnLogic.cpp +++ b/client/ui/pages_logic/protocols/OpenVpnLogic.cpp @@ -35,7 +35,7 @@ OpenVpnLogic::OpenVpnLogic(UiLogic *logic, QObject *parent): } -void OpenVpnLogic::updateProtocolPage(const QJsonObject &openvpnConfig, DockerContainer container, bool haveAuthData) +void OpenVpnLogic::updateProtocolPage(const QJsonObject &openvpnConfig, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig) { qDebug() << "OpenVpnLogic::updateProtocolPage"; set_pageEnabled(haveAuthData); @@ -87,6 +87,16 @@ void OpenVpnLogic::updateProtocolPage(const QJsonObject &openvpnConfig, DockerCo toString(protocols::openvpn::defaultPort)); set_lineEditPortEnabled(container == DockerContainer::OpenVpn); + + auto lastConfig = openvpnConfig.value(config_key::last_config).toString(); + auto lastConfigJson = QJsonDocument::fromJson(lastConfig.toUtf8()).object(); + QStringList lines = lastConfigJson.value(config_key::config).toString().replace("\r", "").split("\n"); + for (const QString &l: lines) { + m_openVpnLastConfigText.append(l + "\n"); + } + + emit openVpnLastConfigTextChanged(m_openVpnLastConfigText); + set_isThirdPartyConfig(isThirdPartyConfig); } void OpenVpnLogic::onPushButtonProtoOpenVpnSaveClicked() diff --git a/client/ui/pages_logic/protocols/OpenVpnLogic.h b/client/ui/pages_logic/protocols/OpenVpnLogic.h index 23c2dd4d..76c481e6 100644 --- a/client/ui/pages_logic/protocols/OpenVpnLogic.h +++ b/client/ui/pages_logic/protocols/OpenVpnLogic.h @@ -35,6 +35,9 @@ class OpenVpnLogic : public PageProtocolLogicBase AUTO_PROPERTY(int, progressBarResetValue) AUTO_PROPERTY(int, progressBarResetMaximium) + AUTO_PROPERTY(QString, openVpnLastConfigText) + AUTO_PROPERTY(bool, isThirdPartyConfig) + public: Q_INVOKABLE void onPushButtonProtoOpenVpnSaveClicked(); @@ -42,7 +45,7 @@ public: explicit OpenVpnLogic(UiLogic *uiLogic, QObject *parent = nullptr); ~OpenVpnLogic() = default; - void updateProtocolPage(const QJsonObject &openvpnConfig, DockerContainer container, bool haveAuthData) override; + void updateProtocolPage(const QJsonObject &openvpnConfig, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig) override; QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override; private: diff --git a/client/ui/pages_logic/protocols/OtherProtocolsLogic.cpp b/client/ui/pages_logic/protocols/OtherProtocolsLogic.cpp index 50b17a46..e10956a4 100644 --- a/client/ui/pages_logic/protocols/OtherProtocolsLogic.cpp +++ b/client/ui/pages_logic/protocols/OtherProtocolsLogic.cpp @@ -36,7 +36,7 @@ OtherProtocolsLogic::~OtherProtocolsLogic() #endif } -void OtherProtocolsLogic::updateProtocolPage(const QJsonObject &config, DockerContainer container, bool haveAuthData) +void OtherProtocolsLogic::updateProtocolPage(const QJsonObject &config, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig) { set_labelTftpUserNameText(config.value(config_key::userName).toString()); set_labelTftpPasswordText(config.value(config_key::password).toString(protocols::sftp::defaultUserName)); diff --git a/client/ui/pages_logic/protocols/OtherProtocolsLogic.h b/client/ui/pages_logic/protocols/OtherProtocolsLogic.h index 508c2914..e4d3c6ab 100644 --- a/client/ui/pages_logic/protocols/OtherProtocolsLogic.h +++ b/client/ui/pages_logic/protocols/OtherProtocolsLogic.h @@ -27,7 +27,7 @@ public: explicit OtherProtocolsLogic(UiLogic *uiLogic, QObject *parent = nullptr); ~OtherProtocolsLogic(); - void updateProtocolPage(const QJsonObject &config, DockerContainer container, bool haveAuthData) override; + void updateProtocolPage(const QJsonObject &config, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig) override; //QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override; private: diff --git a/client/ui/pages_logic/protocols/PageProtocolLogicBase.h b/client/ui/pages_logic/protocols/PageProtocolLogicBase.h index ab66f8a9..75e0ac2e 100644 --- a/client/ui/pages_logic/protocols/PageProtocolLogicBase.h +++ b/client/ui/pages_logic/protocols/PageProtocolLogicBase.h @@ -17,7 +17,7 @@ public: explicit PageProtocolLogicBase(UiLogic *uiLogic, QObject *parent = nullptr); ~PageProtocolLogicBase() = default; - virtual void updateProtocolPage(const QJsonObject &config, DockerContainer container, bool haveAuthData) {} + virtual void updateProtocolPage(const QJsonObject &config, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig) {} virtual QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) { return QJsonObject(); } }; diff --git a/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp b/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp index 1d5da936..e23f0bf8 100644 --- a/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp +++ b/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp @@ -21,7 +21,7 @@ ShadowSocksLogic::ShadowSocksLogic(UiLogic *logic, QObject *parent): } -void ShadowSocksLogic::updateProtocolPage(const QJsonObject &ssConfig, DockerContainer container, bool haveAuthData) +void ShadowSocksLogic::updateProtocolPage(const QJsonObject &ssConfig, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig) { set_pageEnabled(haveAuthData); set_pushButtonSaveVisible(haveAuthData); diff --git a/client/ui/pages_logic/protocols/ShadowSocksLogic.h b/client/ui/pages_logic/protocols/ShadowSocksLogic.h index 4e566825..6d2fbd1b 100644 --- a/client/ui/pages_logic/protocols/ShadowSocksLogic.h +++ b/client/ui/pages_logic/protocols/ShadowSocksLogic.h @@ -26,7 +26,7 @@ public: explicit ShadowSocksLogic(UiLogic *uiLogic, QObject *parent = nullptr); ~ShadowSocksLogic() = default; - void updateProtocolPage(const QJsonObject &ssConfig, DockerContainer container, bool haveAuthData) override; + void updateProtocolPage(const QJsonObject &ssConfig, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig) override; QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override; private: diff --git a/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml b/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml index 9c00172c..5722c68b 100644 --- a/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml +++ b/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml @@ -36,370 +36,389 @@ PageProtocolBase { ColumnLayout { id: content - enabled: logic.pageEnabled anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right - - LabelType { - id: lb_subnet - height: 21 - text: qsTr("VPN Addresses Subnet") - } - TextFieldType { - id: tf_subnet - - implicitWidth: parent.width - height: 31 - text: logic.lineEditSubnetText - onEditingFinished: { - logic.lineEditSubnetText = text - } - } - - // - LabelType { - id: lb_proto - Layout.topMargin: 20 - height: 21 - text: qsTr("Network protocol") - } - Rectangle { - id: rect_proto - implicitWidth: root.width - 60 - height: 71 - border.width: 1 - border.color: "lightgray" - radius: 2 - RadioButtonType { - x: 10 - y: 40 - width: 171 - height: 19 - text: qsTr("TCP") - enabled: logic.radioButtonTcpEnabled - checked: logic.radioButtonTcpChecked - onCheckedChanged: { - UiLogic.radioButtonTcpChecked = checked - } - } - RadioButtonType { - x: 10 - y: 10 - width: 171 - height: 19 - text: qsTr("UDP") - checked: logic.radioButtonUdpChecked - onCheckedChanged: { - logic.radioButtonUdpChecked = checked - } - enabled: logic.radioButtonUdpEnabled - } - } - - // - RowLayout { - Layout.topMargin: 10 - Layout.fillWidth: true + ColumnLayout { + visible: !logic.isThirdPartyConfig + enabled: logic.pageEnabled LabelType { - id: lb_port - height: 31 - text: qsTr("Port") - Layout.preferredWidth: root.width / 2 - 10 + id: lb_subnet + height: 21 + text: qsTr("VPN Addresses Subnet") } TextFieldType { - id: tf_port + id: tf_subnet + + implicitWidth: parent.width + height: 31 + text: logic.lineEditSubnetText + onEditingFinished: { + logic.lineEditSubnetText = text + } + } + + // + LabelType { + id: lb_proto + Layout.topMargin: 20 + height: 21 + text: qsTr("Network protocol") + } + Rectangle { + id: rect_proto + implicitWidth: root.width - 60 + height: 71 + border.width: 1 + border.color: "lightgray" + radius: 2 + RadioButtonType { + x: 10 + y: 40 + width: 171 + height: 19 + text: qsTr("TCP") + enabled: logic.radioButtonTcpEnabled + checked: logic.radioButtonTcpChecked + onCheckedChanged: { + UiLogic.radioButtonTcpChecked = checked + } + } + RadioButtonType { + x: 10 + y: 10 + width: 171 + height: 19 + text: qsTr("UDP") + checked: logic.radioButtonUdpChecked + onCheckedChanged: { + logic.radioButtonUdpChecked = checked + } + enabled: logic.radioButtonUdpEnabled + } + } + + // + RowLayout { + Layout.topMargin: 10 Layout.fillWidth: true + LabelType { + id: lb_port + height: 31 + text: qsTr("Port") + Layout.preferredWidth: root.width / 2 - 10 + } + TextFieldType { + id: tf_port + Layout.fillWidth: true + + height: 31 + text: logic.lineEditPortText + onEditingFinished: { + logic.lineEditPortText = text + } + enabled: logic.lineEditPortEnabled + } + } + + + + // + CheckBoxType { + id: check_auto_enc + + implicitWidth: parent.width + height: 21 + text: qsTr("Auto-negotiate encryption") + checked: logic.checkBoxAutoEncryptionChecked + onCheckedChanged: { + logic.checkBoxAutoEncryptionChecked = checked + } + onClicked: { + logic.checkBoxAutoEncryptionClicked() + } + } + + // + LabelType { + id: lb_cipher + height: 21 + text: qsTr("Cipher") + } + + ComboBoxType { + id: cb_cipher + implicitWidth: parent.width height: 31 - text: logic.lineEditPortText - onEditingFinished: { - logic.lineEditPortText = text - } - enabled: logic.lineEditPortEnabled - } - } - - - - // - CheckBoxType { - id: check_auto_enc - - implicitWidth: parent.width - height: 21 - text: qsTr("Auto-negotiate encryption") - checked: logic.checkBoxAutoEncryptionChecked - onCheckedChanged: { - logic.checkBoxAutoEncryptionChecked = checked - } - onClicked: { - logic.checkBoxAutoEncryptionClicked() - } - } - - // - LabelType { - id: lb_cipher - height: 21 - text: qsTr("Cipher") - } - - ComboBoxType { - id: cb_cipher - implicitWidth: parent.width - - height: 31 - model: [ - qsTr("AES-256-GCM"), - qsTr("AES-192-GCM"), - qsTr("AES-128-GCM"), - qsTr("AES-256-CBC"), - qsTr("AES-192-CBC"), - qsTr("AES-128-CBC"), - qsTr("ChaCha20-Poly1305"), - qsTr("ARIA-256-CBC"), - qsTr("CAMELLIA-256-CBC"), - qsTr("none") - ] - currentIndex: { - for (let i = 0; i < model.length; ++i) { - if (logic.comboBoxVpnCipherText === model[i]) { - return i + model: [ + qsTr("AES-256-GCM"), + qsTr("AES-192-GCM"), + qsTr("AES-128-GCM"), + qsTr("AES-256-CBC"), + qsTr("AES-192-CBC"), + qsTr("AES-128-CBC"), + qsTr("ChaCha20-Poly1305"), + qsTr("ARIA-256-CBC"), + qsTr("CAMELLIA-256-CBC"), + qsTr("none") + ] + currentIndex: { + for (let i = 0; i < model.length; ++i) { + if (logic.comboBoxVpnCipherText === model[i]) { + return i + } } + return -1 } - return -1 + onCurrentTextChanged: { + logic.comboBoxVpnCipherText = currentText + } + enabled: !check_auto_enc.checked } - onCurrentTextChanged: { - logic.comboBoxVpnCipherText = currentText - } - enabled: !check_auto_enc.checked - } - // - LabelType { - id: lb_hash - height: 21 - Layout.topMargin: 20 - text: qsTr("Hash") - } - ComboBoxType { - id: cb_hash - height: 31 - implicitWidth: parent.width - model: [ - qsTr("SHA512"), - qsTr("SHA384"), - qsTr("SHA256"), - qsTr("SHA3-512"), - qsTr("SHA3-384"), - qsTr("SHA3-256"), - qsTr("whirlpool"), - qsTr("BLAKE2b512"), - qsTr("BLAKE2s256"), - qsTr("SHA1") - ] - currentIndex: { - for (let i = 0; i < model.length; ++i) { - if (logic.comboBoxVpnHashText === model[i]) { - return i + // + LabelType { + id: lb_hash + height: 21 + Layout.topMargin: 20 + text: qsTr("Hash") + } + ComboBoxType { + id: cb_hash + height: 31 + implicitWidth: parent.width + model: [ + qsTr("SHA512"), + qsTr("SHA384"), + qsTr("SHA256"), + qsTr("SHA3-512"), + qsTr("SHA3-384"), + qsTr("SHA3-256"), + qsTr("whirlpool"), + qsTr("BLAKE2b512"), + qsTr("BLAKE2s256"), + qsTr("SHA1") + ] + currentIndex: { + for (let i = 0; i < model.length; ++i) { + if (logic.comboBoxVpnHashText === model[i]) { + return i + } } + return -1 } - return -1 - } - onCurrentTextChanged: { - logic.comboBoxVpnHashText = currentText - } - enabled: !check_auto_enc.checked - } - - CheckBoxType { - id: check_tls - implicitWidth: parent.width - Layout.topMargin: 20 - height: 21 - text: qsTr("Enable TLS auth") - checked: logic.checkBoxTlsAuthChecked - onCheckedChanged: { - logic.checkBoxTlsAuthChecked = checked + onCurrentTextChanged: { + logic.comboBoxVpnHashText = currentText + } + enabled: !check_auto_enc.checked } - } + CheckBoxType { + id: check_tls + implicitWidth: parent.width + Layout.topMargin: 20 + height: 21 + text: qsTr("Enable TLS auth") + checked: logic.checkBoxTlsAuthChecked + onCheckedChanged: { + logic.checkBoxTlsAuthChecked = checked + } - CheckBoxType { - id: check_block_dns - implicitWidth: parent.width - height: 21 - text: qsTr("Block DNS requests outside of VPN") - checked: logic.checkBoxBlockDnsChecked - onCheckedChanged: { - logic.checkBoxBlockDnsChecked = checked - } - } - - - BasicButtonType { - id: pb_client_config - - implicitWidth: parent.width - height: 21 - text: qsTr("Additional client config commands →") - background: Item { - anchors.fill: parent } - contentItem: Text { - anchors.fill: parent - font.family: "Lato" - font.styleName: "normal" - font.pixelSize: 16 - color: "#15CDCB"; - text: pb_client_config.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter + CheckBoxType { + id: check_block_dns + implicitWidth: parent.width + height: 21 + text: qsTr("Block DNS requests outside of VPN") + checked: logic.checkBoxBlockDnsChecked + onCheckedChanged: { + logic.checkBoxBlockDnsChecked = checked + } } - antialiasing: true - checkable: true - checked: StartPageLogic.pushButtonConnectKeyChecked - } - Rectangle { - id: rect_client_conf - implicitWidth: root.width - 60 - height: 101 - border.width: 1 - border.color: "lightgray" - radius: 2 - visible: pb_client_config.checked - ScrollView { - anchors.fill: parent - TextArea { - id: te_client_config + BasicButtonType { + id: pb_client_config + + implicitWidth: parent.width + height: 21 + text: qsTr("Additional client config commands →") + background: Item { + anchors.fill: parent + } + + contentItem: Text { + anchors.fill: parent font.family: "Lato" font.styleName: "normal" font.pixelSize: 16 - color: "#181922" - text: logic.textAreaAdditionalClientConfig - onEditingFinished: { - logic.textAreaAdditionalClientConfig = text + color: "#15CDCB"; + text: pb_client_config.text + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + antialiasing: true + checkable: true + checked: StartPageLogic.pushButtonConnectKeyChecked + } + + Rectangle { + id: rect_client_conf + implicitWidth: root.width - 60 + height: 101 + border.width: 1 + border.color: "lightgray" + radius: 2 + visible: pb_client_config.checked + + ScrollView { + anchors.fill: parent + TextArea { + id: te_client_config + font.family: "Lato" + font.styleName: "normal" + font.pixelSize: 16 + color: "#181922" + text: logic.textAreaAdditionalClientConfig + onEditingFinished: { + logic.textAreaAdditionalClientConfig = text + } } } + + } - } + BasicButtonType { + id: pb_server_config + implicitWidth: parent.width + height: 21 + text: qsTr("Additional server config commands →") + background: Item { + anchors.fill: parent + } - BasicButtonType { - id: pb_server_config - - implicitWidth: parent.width - height: 21 - text: qsTr("Additional server config commands →") - background: Item { - anchors.fill: parent - } - - contentItem: Text { - anchors.fill: parent - font.family: "Lato" - font.styleName: "normal" - font.pixelSize: 16 - color: "#15CDCB"; - text: pb_server_config.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - } - antialiasing: true - checkable: true - checked: StartPageLogic.pushButtonConnectKeyChecked - } - - Rectangle { - id: rect_server_conf - implicitWidth: root.width - 60 - height: 101 - border.width: 1 - border.color: "lightgray" - radius: 2 - visible: pb_server_config.checked - - ScrollView { - anchors.fill: parent - TextArea { - id: te_server_config + contentItem: Text { + anchors.fill: parent font.family: "Lato" font.styleName: "normal" font.pixelSize: 16 - color: "#181922" - text: logic.textAreaAdditionalServerConfig - onEditingFinished: { - logic.textAreaAdditionalServerConfig = text - } + color: "#15CDCB"; + text: pb_server_config.text + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter } + antialiasing: true + checkable: true + checked: StartPageLogic.pushButtonConnectKeyChecked } + Rectangle { + id: rect_server_conf + implicitWidth: root.width - 60 + height: 101 + border.width: 1 + border.color: "lightgray" + radius: 2 + visible: pb_server_config.checked - } + ScrollView { + anchors.fill: parent + TextArea { + id: te_server_config + font.family: "Lato" + font.styleName: "normal" + font.pixelSize: 16 + color: "#181922" + text: logic.textAreaAdditionalServerConfig + onEditingFinished: { + logic.textAreaAdditionalServerConfig = text + } + } + } - LabelType { - id: label_proto_openvpn_info - height: 41 - visible: logic.labelProtoOpenVpnInfoVisible - text: logic.labelProtoOpenVpnInfoText - } + } - Rectangle { - id: it_save - implicitWidth: parent.width - Layout.topMargin: 20 - height: 40 + LabelType { + id: label_proto_openvpn_info - BlueButtonType { - id: pb_save - z: 1 + height: 41 + visible: logic.labelProtoOpenVpnInfoVisible + text: logic.labelProtoOpenVpnInfoText + } + + Rectangle { + id: it_save + implicitWidth: parent.width + Layout.topMargin: 20 height: 40 - text: qsTr("Save and restart VPN") - width: parent.width - visible: logic.pushButtonSaveVisible - onClicked: { - logic.onPushButtonProtoOpenVpnSaveClicked() - } - } - ProgressBar { - id: progress_save - anchors.fill: pb_save - from: 0 - to: logic.progressBarResetMaximium - value: logic.progressBarResetValue - visible: logic.progressBarResetVisible - background: Rectangle { - implicitWidth: parent.width - implicitHeight: parent.height - color: "#100A44" - radius: 4 - } - - contentItem: Item { - implicitWidth: parent.width - implicitHeight: parent.height - Rectangle { - width: progress_save.visualPosition * parent.width - height: parent.height - radius: 4 - color: Qt.rgba(255, 255, 255, 0.15); + BlueButtonType { + id: pb_save + z: 1 + height: 40 + text: qsTr("Save and restart VPN") + width: parent.width + visible: logic.pushButtonSaveVisible + onClicked: { + logic.onPushButtonProtoOpenVpnSaveClicked() } } + + ProgressBar { + id: progress_save + anchors.fill: pb_save + from: 0 + to: logic.progressBarResetMaximium + value: logic.progressBarResetValue + visible: logic.progressBarResetVisible + background: Rectangle { + implicitWidth: parent.width + implicitHeight: parent.height + color: "#100A44" + radius: 4 + } + + contentItem: Item { + implicitWidth: parent.width + implicitHeight: parent.height + Rectangle { + width: progress_save.visualPosition * parent.width + height: parent.height + radius: 4 + color: Qt.rgba(255, 255, 255, 0.15); + } + } + } + } } - } + ColumnLayout { + visible: logic.isThirdPartyConfig + TextAreaType { + id: ta_config + Layout.topMargin: 5 + Layout.bottomMargin: 20 + Layout.fillWidth: true + Layout.leftMargin: 1 + Layout.rightMargin: 1 + Layout.preferredHeight: fl.height - 70 + flickableDirection: Flickable.AutoFlickIfNeeded + + textArea.readOnly: true + textArea.text: logic.openVpnLastConfigText + } + } + } } } From 1a443076644d51988d8a3fdc09a32ae820e90287 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Tue, 1 Nov 2022 23:24:58 +0300 Subject: [PATCH 02/13] added protocol_defs for new config keywords --- client/protocols/protocols_defs.h | 5 +++++ client/settings.cpp | 2 +- client/ui/pages_logic/StartPageLogic.cpp | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/client/protocols/protocols_defs.h b/client/protocols/protocols_defs.h index c158822d..9e121f56 100644 --- a/client/protocols/protocols_defs.h +++ b/client/protocols/protocols_defs.h @@ -58,6 +58,11 @@ constexpr char additional_server_config[] = "additional_server_config"; // proto config keys constexpr char last_config[] = "last_config"; + +constexpr char is_third_party_config[] = "is_third_party_config"; + +constexpr char openvpn[] = "openvpn"; + } namespace protocols { diff --git a/client/settings.cpp b/client/settings.cpp index ccef9e40..8202eb27 100644 --- a/client/settings.cpp +++ b/client/settings.cpp @@ -317,5 +317,5 @@ bool Settings::isThirdPartyConfig(int serverIndex) const { if (serverIndex < 0) return false; const QJsonObject &s = server(serverIndex); - return s.value("isThirdPartyConfig").toBool(); + return s.value(config_key::is_third_party_config).toBool(); } diff --git a/client/ui/pages_logic/StartPageLogic.cpp b/client/ui/pages_logic/StartPageLogic.cpp index 6a6333e9..897caaaf 100644 --- a/client/ui/pages_logic/StartPageLogic.cpp +++ b/client/ui/pages_logic/StartPageLogic.cpp @@ -249,7 +249,7 @@ bool StartPageLogic::importConnectionFromOpenVpnConfig(const QString &config) QJsonObject containers; containers.insert(config_key::container, QJsonValue("amnezia-openvpn")); - containers.insert("openvpn", QJsonValue(lastConfig)); + containers.insert(config_key::openvpn, QJsonValue(lastConfig)); QJsonArray arr; arr.push_back(containers); @@ -275,7 +275,7 @@ bool StartPageLogic::importConnectionFromOpenVpnConfig(const QString &config) o[config_key::hostName] = hostNameMatch.captured(0).split(" ").at(1); } - o["isThirdPartyConfig"] = true; + o[config_key::is_third_party_config] = true; return importConnection(o); } From 99a6cd82b2a01fecc984ae776682b0a0733adac4 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Thu, 3 Nov 2022 23:39:58 +0300 Subject: [PATCH 03/13] added import of configs in wireguard format --- client/protocols/protocols_defs.h | 1 + client/ui/pages_logic/StartPageLogic.cpp | 47 ++++++++++++++++++- client/ui/pages_logic/StartPageLogic.h | 1 + .../qml/Pages/Protocols/PageProtoOpenVPN.qml | 1 + 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/client/protocols/protocols_defs.h b/client/protocols/protocols_defs.h index 9e121f56..462c7c51 100644 --- a/client/protocols/protocols_defs.h +++ b/client/protocols/protocols_defs.h @@ -62,6 +62,7 @@ constexpr char last_config[] = "last_config"; constexpr char is_third_party_config[] = "is_third_party_config"; constexpr char openvpn[] = "openvpn"; +constexpr char wireguard[] = "wireguard"; } diff --git a/client/ui/pages_logic/StartPageLogic.cpp b/client/ui/pages_logic/StartPageLogic.cpp index 897caaaf..47b893bc 100644 --- a/client/ui/pages_logic/StartPageLogic.cpp +++ b/client/ui/pages_logic/StartPageLogic.cpp @@ -24,11 +24,16 @@ QString checkConfigFormat(const QString &config) const QString openVpnConfigPatternDriver1 = "dev tun"; const QString openVpnConfigPatternDriver2 = "dev tap"; + const QString wireguardConfigPatternSectionInterface = "[Interface]"; + const QString wireguardConfigPatternSectionPeer = "[Peer]"; + if (config.contains(openVpnConfigPatternCli) && (config.contains(openVpnConfigPatternProto1) || config.contains(openVpnConfigPatternProto2)) && (config.contains(openVpnConfigPatternDriver1) || config.contains(openVpnConfigPatternDriver2))) { return "OpenVpn"; - } + } else if (config.contains(wireguardConfigPatternSectionInterface) && + config.contains(wireguardConfigPatternSectionPeer)) + return "Wireguard"; return "Amnezia"; } @@ -155,7 +160,7 @@ void StartPageLogic::onPushButtonImport() void StartPageLogic::onPushButtonImportOpenFile() { QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open profile"), - QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.vpn *.ovpn"); + QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.vpn *.ovpn *.conf"); if (fileName.isEmpty()) return; @@ -166,6 +171,8 @@ void StartPageLogic::onPushButtonImportOpenFile() auto configFormat = checkConfigFormat(QString(data)); if (configFormat == "OpenVpn") { importConnectionFromOpenVpnConfig(QString(data)); + } else if (configFormat == "Wireguard") { + importConnectionFromWireguardConfig(QString(data)); } else { importConnectionFromCode(QString(data)); } @@ -279,3 +286,39 @@ bool StartPageLogic::importConnectionFromOpenVpnConfig(const QString &config) return importConnection(o); } + +bool StartPageLogic::importConnectionFromWireguardConfig(const QString &config) +{ + QJsonObject lastConfig; + lastConfig[config_key::config] = config; + + const static QRegularExpression hostNameAndPortRegExp("Endpoint = (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b):([0-9]*)"); + QRegularExpressionMatch hostNameAndPortMatch = hostNameAndPortRegExp.match(config); + QString hostName; + QString port; + if (hostNameAndPortMatch.hasMatch()) { + hostName = hostNameAndPortMatch.captured(1); + port = hostNameAndPortMatch.captured(2); + } + + + QJsonObject wireguardConfig; + wireguardConfig[config_key::last_config] = lastConfig; + wireguardConfig[config_key::port] = port; + wireguardConfig[config_key::transport_proto] = "udp"; + + QJsonObject containers; + containers.insert(config_key::container, QJsonValue("amnezia-wireguard")); + containers.insert(config_key::wireguard, QJsonValue(wireguardConfig)); + + QJsonArray arr; + arr.push_back(containers); + + QJsonObject o; + o[config_key::containers] = arr; + o[config_key::defaultContainer] = "amnezia-wireguard"; + o[config_key::description] = "Wireguard server"; + o[config_key::hostName] = hostName; + + return importConnection(o); +} diff --git a/client/ui/pages_logic/StartPageLogic.h b/client/ui/pages_logic/StartPageLogic.h index 830c9100..d5e72edc 100644 --- a/client/ui/pages_logic/StartPageLogic.h +++ b/client/ui/pages_logic/StartPageLogic.h @@ -33,6 +33,7 @@ public: bool importConnectionFromCode(QString code); bool importConnectionFromQr(const QByteArray &data); bool importConnectionFromOpenVpnConfig(const QString &config); + bool importConnectionFromWireguardConfig(const QString &config); public: explicit StartPageLogic(UiLogic *uiLogic, QObject *parent = nullptr); diff --git a/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml b/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml index 5722c68b..3ca79bdc 100644 --- a/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml +++ b/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml @@ -43,6 +43,7 @@ PageProtocolBase { ColumnLayout { visible: !logic.isThirdPartyConfig enabled: logic.pageEnabled + LabelType { id: lb_subnet height: 21 From 6941b7463e1b5878438a1136496e429c44d24611 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Fri, 4 Nov 2022 23:31:39 +0300 Subject: [PATCH 04/13] added display of wireguard configs, such a config will be displayed as raw text --- client/client.pro | 2 + client/protocols/protocols_defs.h | 2 +- client/resources.qrc | 1 + client/settings.cpp | 2 +- client/ui/pages_logic/StartPageLogic.cpp | 24 +++++--- .../ui/pages_logic/protocols/OpenVpnLogic.cpp | 5 +- .../pages_logic/protocols/WireGuardLogic.cpp | 30 ++++++++++ .../ui/pages_logic/protocols/WireGuardLogic.h | 26 ++++++++ .../Pages/Protocols/PageProtoWireGuard.qml | 60 +++++++++++++++++++ client/ui/uilogic.cpp | 4 +- 10 files changed, 142 insertions(+), 14 deletions(-) create mode 100644 client/ui/pages_logic/protocols/WireGuardLogic.cpp create mode 100644 client/ui/pages_logic/protocols/WireGuardLogic.h create mode 100644 client/ui/qml/Pages/Protocols/PageProtoWireGuard.qml diff --git a/client/client.pro b/client/client.pro index bf9db7ed..032fe5d3 100644 --- a/client/client.pro +++ b/client/client.pro @@ -74,6 +74,7 @@ HEADERS += \ ui/pages_logic/protocols/OtherProtocolsLogic.h \ ui/pages_logic/protocols/PageProtocolLogicBase.h \ ui/pages_logic/protocols/ShadowSocksLogic.h \ + ui/pages_logic/protocols/WireGuardLogic.h \ ui/property_helper.h \ ui/models/servers_model.h \ ui/uilogic.h \ @@ -136,6 +137,7 @@ SOURCES += \ ui/pages_logic/protocols/PageProtocolLogicBase.cpp \ ui/pages_logic/protocols/ShadowSocksLogic.cpp \ ui/models/servers_model.cpp \ + ui/pages_logic/protocols/WireGuardLogic.cpp \ ui/uilogic.cpp \ ui/qautostart.cpp \ ui/models/sites_model.cpp \ diff --git a/client/protocols/protocols_defs.h b/client/protocols/protocols_defs.h index 462c7c51..c5f15d5b 100644 --- a/client/protocols/protocols_defs.h +++ b/client/protocols/protocols_defs.h @@ -59,7 +59,7 @@ constexpr char additional_server_config[] = "additional_server_config"; // proto config keys constexpr char last_config[] = "last_config"; -constexpr char is_third_party_config[] = "is_third_party_config"; +constexpr char isThirdPartyConfig[] = "isThirdPartyConfig"; constexpr char openvpn[] = "openvpn"; constexpr char wireguard[] = "wireguard"; diff --git a/client/resources.qrc b/client/resources.qrc index a7e67e39..47d10f7c 100644 --- a/client/resources.qrc +++ b/client/resources.qrc @@ -160,5 +160,6 @@ ui/qml/Pages/PageQrDecoderIos.qml server_scripts/website_tor/Dockerfile ui/qml/Pages/PageViewConfig.qml + ui/qml/Pages/Protocols/PageProtoWireGuard.qml diff --git a/client/settings.cpp b/client/settings.cpp index 8202eb27..fc3a5825 100644 --- a/client/settings.cpp +++ b/client/settings.cpp @@ -317,5 +317,5 @@ bool Settings::isThirdPartyConfig(int serverIndex) const { if (serverIndex < 0) return false; const QJsonObject &s = server(serverIndex); - return s.value(config_key::is_third_party_config).toBool(); + return s.value(config_key::isThirdPartyConfig).toBool(); } diff --git a/client/ui/pages_logic/StartPageLogic.cpp b/client/ui/pages_logic/StartPageLogic.cpp index 47b893bc..37b557e0 100644 --- a/client/ui/pages_logic/StartPageLogic.cpp +++ b/client/ui/pages_logic/StartPageLogic.cpp @@ -267,22 +267,22 @@ bool StartPageLogic::importConnectionFromOpenVpnConfig(const QString &config) o[config_key::description] = "OpenVpn server"; - const static QRegularExpression dnsRegExp("dhcp-option DNS \\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b"); + const static QRegularExpression dnsRegExp("dhcp-option DNS (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)"); QRegularExpressionMatchIterator dnsMatch = dnsRegExp.globalMatch(config); if (dnsMatch.hasNext()) { - o[config_key::dns1] = dnsMatch.next().captured(0).split(" ").at(2); + o[config_key::dns1] = dnsMatch.next().captured(1); } if (dnsMatch.hasNext()) { - o[config_key::dns2] = dnsMatch.next().captured(0).split(" ").at(2); + o[config_key::dns2] = dnsMatch.next().captured(1); } - const static QRegularExpression hostNameRegExp("remote \\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b"); + const static QRegularExpression hostNameRegExp("remote (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)"); QRegularExpressionMatch hostNameMatch = hostNameRegExp.match(config); if (hostNameMatch.hasMatch()) { - o[config_key::hostName] = hostNameMatch.captured(0).split(" ").at(1); + o[config_key::hostName] = hostNameMatch.captured(1); } - o[config_key::is_third_party_config] = true; + o[config_key::isThirdPartyConfig] = true; return importConnection(o); } @@ -301,9 +301,8 @@ bool StartPageLogic::importConnectionFromWireguardConfig(const QString &config) port = hostNameAndPortMatch.captured(2); } - QJsonObject wireguardConfig; - wireguardConfig[config_key::last_config] = lastConfig; + wireguardConfig[config_key::last_config] = QString(QJsonDocument(lastConfig).toJson());; wireguardConfig[config_key::port] = port; wireguardConfig[config_key::transport_proto] = "udp"; @@ -318,7 +317,16 @@ bool StartPageLogic::importConnectionFromWireguardConfig(const QString &config) o[config_key::containers] = arr; o[config_key::defaultContainer] = "amnezia-wireguard"; o[config_key::description] = "Wireguard server"; + + const static QRegularExpression dnsRegExp("DNS = (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b).*(\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)"); + QRegularExpressionMatch dnsMatch = dnsRegExp.match(config); + if (dnsMatch.hasMatch()) { + o[config_key::dns1] = dnsMatch.captured(1); + o[config_key::dns2] = dnsMatch.captured(2); + } + o[config_key::hostName] = hostName; + o[config_key::isThirdPartyConfig] = true; return importConnection(o); } diff --git a/client/ui/pages_logic/protocols/OpenVpnLogic.cpp b/client/ui/pages_logic/protocols/OpenVpnLogic.cpp index 7d726670..fbbf1c86 100644 --- a/client/ui/pages_logic/protocols/OpenVpnLogic.cpp +++ b/client/ui/pages_logic/protocols/OpenVpnLogic.cpp @@ -91,11 +91,12 @@ void OpenVpnLogic::updateProtocolPage(const QJsonObject &openvpnConfig, DockerCo auto lastConfig = openvpnConfig.value(config_key::last_config).toString(); auto lastConfigJson = QJsonDocument::fromJson(lastConfig.toUtf8()).object(); QStringList lines = lastConfigJson.value(config_key::config).toString().replace("\r", "").split("\n"); + QString openVpnLastConfigText; for (const QString &l: lines) { - m_openVpnLastConfigText.append(l + "\n"); + openVpnLastConfigText.append(l + "\n"); } - emit openVpnLastConfigTextChanged(m_openVpnLastConfigText); + set_openVpnLastConfigText(m_openVpnLastConfigText); set_isThirdPartyConfig(isThirdPartyConfig); } diff --git a/client/ui/pages_logic/protocols/WireGuardLogic.cpp b/client/ui/pages_logic/protocols/WireGuardLogic.cpp new file mode 100644 index 00000000..d4c18df6 --- /dev/null +++ b/client/ui/pages_logic/protocols/WireGuardLogic.cpp @@ -0,0 +1,30 @@ +#include "WireGuardLogic.h" +#include "core/servercontroller.h" +#include +#include "../../uilogic.h" + +using namespace amnezia; +using namespace PageEnumNS; + +WireGuardLogic::WireGuardLogic(UiLogic *logic, QObject *parent): + PageProtocolLogicBase(logic, parent) +{ + +} + +void WireGuardLogic::updateProtocolPage(const QJsonObject &wireGuardConfig, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig) +{ + qDebug() << "WireGuardLogic::updateProtocolPage"; + + auto lastConfigJsonDoc = QJsonDocument::fromJson(wireGuardConfig.value(config_key::last_config).toString().toUtf8()); + auto lastConfigJson = lastConfigJsonDoc.object(); + + QString wireGuardLastConfigText; + QStringList lines = lastConfigJson.value(config_key::config).toString().replace("\r", "").split("\n"); + for (const QString &l: lines) { + wireGuardLastConfigText.append(l + "\n"); + } + + set_wireGuardLastConfigText(wireGuardLastConfigText); + set_isThirdPartyConfig(isThirdPartyConfig); +} diff --git a/client/ui/pages_logic/protocols/WireGuardLogic.h b/client/ui/pages_logic/protocols/WireGuardLogic.h new file mode 100644 index 00000000..19e9f90d --- /dev/null +++ b/client/ui/pages_logic/protocols/WireGuardLogic.h @@ -0,0 +1,26 @@ +#ifndef WIREGUARDLOGIC_H +#define WIREGUARDLOGIC_H + +#include "PageProtocolLogicBase.h" + +class UiLogic; + +class WireGuardLogic : public PageProtocolLogicBase +{ + Q_OBJECT + + AUTO_PROPERTY(QString, wireGuardLastConfigText) + AUTO_PROPERTY(bool, isThirdPartyConfig) + +public: + explicit WireGuardLogic(UiLogic *uiLogic, QObject *parent = nullptr); + ~WireGuardLogic() = default; + + void updateProtocolPage(const QJsonObject &wireGuardConfig, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig) override; + +private: + UiLogic *m_uiLogic; + +}; + +#endif // WIREGUARDLOGIC_H diff --git a/client/ui/qml/Pages/Protocols/PageProtoWireGuard.qml b/client/ui/qml/Pages/Protocols/PageProtoWireGuard.qml new file mode 100644 index 00000000..e4dde50e --- /dev/null +++ b/client/ui/qml/Pages/Protocols/PageProtoWireGuard.qml @@ -0,0 +1,60 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.15 +import ProtocolEnum 1.0 +import "../" +import "../../Controls" +import "../../Config" + +PageProtocolBase { + id: root + protocol: ProtocolEnum.WireGuard + logic: UiLogic.protocolLogic(protocol) + + BackButton { + id: back + } + Caption { + id: caption + text: qsTr("WireGuard Settings") + } + + Flickable { + id: fl + width: root.width + anchors.top: caption.bottom + anchors.topMargin: 20 + anchors.bottom: parent.bottom + anchors.bottomMargin: 20 + anchors.left: root.left + anchors.leftMargin: 30 + anchors.right: root.right + anchors.rightMargin: 30 + + contentHeight: content.height + clip: true + + ColumnLayout { + id: content + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + + TextAreaType { + id: ta_config + + Layout.topMargin: 5 + Layout.bottomMargin: 20 + Layout.fillWidth: true + Layout.leftMargin: 1 + Layout.rightMargin: 1 + Layout.preferredHeight: fl.height - 70 + flickableDirection: Flickable.AutoFlickIfNeeded + + textArea.readOnly: true + textArea.text: logic.wireGuardLastConfigText + } + } + } + +} diff --git a/client/ui/uilogic.cpp b/client/ui/uilogic.cpp index e1468da7..81492023 100644 --- a/client/ui/uilogic.cpp +++ b/client/ui/uilogic.cpp @@ -71,7 +71,7 @@ #include "pages_logic/protocols/OpenVpnLogic.h" #include "pages_logic/protocols/ShadowSocksLogic.h" #include "pages_logic/protocols/OtherProtocolsLogic.h" - +#include "pages_logic/protocols/WireGuardLogic.h" using namespace amnezia; using namespace PageEnumNS; @@ -94,7 +94,7 @@ UiLogic::UiLogic(std::shared_ptr settings, std::shared_ptrinsert(Proto::WireGuard, new WireguardLogic(this)); + m_protocolLogicMap.insert(Proto::WireGuard, new WireGuardLogic(this)); m_protocolLogicMap.insert(Proto::Dns, new OtherProtocolsLogic(this)); m_protocolLogicMap.insert(Proto::Sftp, new OtherProtocolsLogic(this)); From 7270e701d4a4f8518e8a00781d68faf81a669835 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Sat, 5 Nov 2022 19:40:51 +0300 Subject: [PATCH 05/13] hostname is now added to the server name for imported openvpn and wireguard configs --- client/ui/pages_logic/StartPageLogic.cpp | 38 +++++++++++++++--------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/client/ui/pages_logic/StartPageLogic.cpp b/client/ui/pages_logic/StartPageLogic.cpp index 37b557e0..67f83918 100644 --- a/client/ui/pages_logic/StartPageLogic.cpp +++ b/client/ui/pages_logic/StartPageLogic.cpp @@ -16,7 +16,13 @@ #endif namespace { -QString checkConfigFormat(const QString &config) +enum class ConfigTypes { + Amnezia, + OpenVpn, + WireGuard +}; + +ConfigTypes checkConfigFormat(const QString &config) { const QString openVpnConfigPatternCli = "client"; const QString openVpnConfigPatternProto1 = "proto tcp"; @@ -30,11 +36,11 @@ QString checkConfigFormat(const QString &config) if (config.contains(openVpnConfigPatternCli) && (config.contains(openVpnConfigPatternProto1) || config.contains(openVpnConfigPatternProto2)) && (config.contains(openVpnConfigPatternDriver1) || config.contains(openVpnConfigPatternDriver2))) { - return "OpenVpn"; + return ConfigTypes::OpenVpn; } else if (config.contains(wireguardConfigPatternSectionInterface) && config.contains(wireguardConfigPatternSectionPeer)) - return "Wireguard"; - return "Amnezia"; + return ConfigTypes::WireGuard; + return ConfigTypes::Amnezia; } } @@ -169,9 +175,9 @@ void StartPageLogic::onPushButtonImportOpenFile() QByteArray data = file.readAll(); auto configFormat = checkConfigFormat(QString(data)); - if (configFormat == "OpenVpn") { + if (configFormat == ConfigTypes::OpenVpn) { importConnectionFromOpenVpnConfig(QString(data)); - } else if (configFormat == "Wireguard") { + } else if (configFormat == ConfigTypes::WireGuard) { importConnectionFromWireguardConfig(QString(data)); } else { importConnectionFromCode(QString(data)); @@ -261,10 +267,17 @@ bool StartPageLogic::importConnectionFromOpenVpnConfig(const QString &config) QJsonArray arr; arr.push_back(containers); + QString hostName; + const static QRegularExpression hostNameRegExp("remote (.*) [0-9]*"); + QRegularExpressionMatch hostNameMatch = hostNameRegExp.match(config); + if (hostNameMatch.hasMatch()) { + hostName = hostNameMatch.captured(1); + } + QJsonObject o; o[config_key::containers] = arr; o[config_key::defaultContainer] = "amnezia-openvpn"; - o[config_key::description] = "OpenVpn server"; + o[config_key::description] = QString("OpenVpn server %1").arg(hostName); const static QRegularExpression dnsRegExp("dhcp-option DNS (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)"); @@ -276,11 +289,7 @@ bool StartPageLogic::importConnectionFromOpenVpnConfig(const QString &config) o[config_key::dns2] = dnsMatch.next().captured(1); } - const static QRegularExpression hostNameRegExp("remote (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)"); - QRegularExpressionMatch hostNameMatch = hostNameRegExp.match(config); - if (hostNameMatch.hasMatch()) { - o[config_key::hostName] = hostNameMatch.captured(1); - } + o[config_key::hostName] = hostName; o[config_key::isThirdPartyConfig] = true; @@ -292,7 +301,7 @@ bool StartPageLogic::importConnectionFromWireguardConfig(const QString &config) QJsonObject lastConfig; lastConfig[config_key::config] = config; - const static QRegularExpression hostNameAndPortRegExp("Endpoint = (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b):([0-9]*)"); + const static QRegularExpression hostNameAndPortRegExp("Endpoint = (.*):([0-9]*)"); QRegularExpressionMatch hostNameAndPortMatch = hostNameAndPortRegExp.match(config); QString hostName; QString port; @@ -316,7 +325,7 @@ bool StartPageLogic::importConnectionFromWireguardConfig(const QString &config) QJsonObject o; o[config_key::containers] = arr; o[config_key::defaultContainer] = "amnezia-wireguard"; - o[config_key::description] = "Wireguard server"; + o[config_key::description] = QString("Wireguard server %1").arg(hostName); const static QRegularExpression dnsRegExp("DNS = (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b).*(\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)"); QRegularExpressionMatch dnsMatch = dnsRegExp.match(config); @@ -326,6 +335,7 @@ bool StartPageLogic::importConnectionFromWireguardConfig(const QString &config) } o[config_key::hostName] = hostName; + o[config_key::isThirdPartyConfig] = true; return importConnection(o); From 9222877306f5b71293072db715512049762f1750 Mon Sep 17 00:00:00 2001 From: Hamza ARBI Date: Sat, 17 Dec 2022 12:06:19 +0100 Subject: [PATCH 06/13] Show Scrollbars whenever the scroll is not obvious --- client/ui/qml/Pages/PageAppSetting.qml | 7 ++++++- client/ui/qml/Pages/PageServerList.qml | 8 ++++++-- client/ui/qml/Pages/PageShareConnection.qml | 1 + 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/client/ui/qml/Pages/PageAppSetting.qml b/client/ui/qml/Pages/PageAppSetting.qml index 7e8d415a..1b0f05c0 100644 --- a/client/ui/qml/Pages/PageAppSetting.qml +++ b/client/ui/qml/Pages/PageAppSetting.qml @@ -29,7 +29,7 @@ PageBase { anchors.left: root.left anchors.leftMargin: 30 anchors.right: root.right - anchors.rightMargin: 30 + anchors.rightMargin: 15 contentHeight: content.height clip: true @@ -40,6 +40,7 @@ PageBase { anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right + anchors.rightMargin: 15 CheckBoxType { visible: !GC.isMobile() @@ -161,6 +162,10 @@ PageBase { } } } + + ScrollBar.vertical: ScrollBar { + policy: fl.height > content.height? ScrollBar.AlwaysOff : ScrollBar.AlwaysOn + } } Logo { diff --git a/client/ui/qml/Pages/PageServerList.qml b/client/ui/qml/Pages/PageServerList.qml index de6f90ab..7791cc05 100644 --- a/client/ui/qml/Pages/PageServerList.qml +++ b/client/ui/qml/Pages/PageServerList.qml @@ -38,7 +38,7 @@ PageBase { x: 20 anchors.top: caption.bottom anchors.topMargin: 15 - width: parent.width + width: parent.width - 30 anchors.bottom: parent.bottom anchors.bottomMargin: 20 model: ServerListLogic.serverListModel @@ -49,7 +49,7 @@ PageBase { clip: true delegate: Item { height: 60 - width: root.width - 40 + width: listWidget_servers.width - 15 MouseArea { id: ms anchors.fill: parent @@ -174,5 +174,9 @@ PageBase { } } } + + ScrollBar.vertical: ScrollBar { + policy: ScrollBar.AlwaysOn + } } } diff --git a/client/ui/qml/Pages/PageShareConnection.qml b/client/ui/qml/Pages/PageShareConnection.qml index 9bd84bdd..b643a7ee 100644 --- a/client/ui/qml/Pages/PageShareConnection.qml +++ b/client/ui/qml/Pages/PageShareConnection.qml @@ -34,6 +34,7 @@ PageBase { anchors.top: caption.bottom anchors.bottom: root.bottom contentHeight: col.height + boundsBehavior: Flickable.StopAtBounds Column { id: col From c6bb33fa84282085e0a7937e9fbe13b585366137 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Sat, 17 Dec 2022 21:00:48 +0300 Subject: [PATCH 07/13] added display of "pure" config if it was imported in native format - changed the method of passing the isThirdPartyConfig parameter to page logic - removed adding hostname to the server name when importing configs in native format - fixed display of the "$proto settings" button when clicking on the protocol on the "Installed services" page --- client/settings.cpp | 7 --- client/settings.h | 2 - .../ui/pages_logic/ServerContainersLogic.cpp | 3 +- client/ui/pages_logic/StartPageLogic.cpp | 12 ++-- client/ui/pages_logic/ViewConfigLogic.cpp | 58 ++++++++++++------- .../ui/pages_logic/protocols/CloakLogic.cpp | 2 +- client/ui/pages_logic/protocols/CloakLogic.h | 2 +- .../ui/pages_logic/protocols/OpenVpnLogic.cpp | 6 +- .../ui/pages_logic/protocols/OpenVpnLogic.h | 2 +- .../protocols/OtherProtocolsLogic.cpp | 2 +- .../protocols/OtherProtocolsLogic.h | 2 +- .../protocols/PageProtocolLogicBase.h | 2 +- .../protocols/ShadowSocksLogic.cpp | 2 +- .../pages_logic/protocols/ShadowSocksLogic.h | 2 +- .../pages_logic/protocols/WireGuardLogic.cpp | 4 +- .../ui/pages_logic/protocols/WireGuardLogic.h | 2 +- client/ui/qml/Pages/PageServerContainers.qml | 1 + 17 files changed, 58 insertions(+), 53 deletions(-) diff --git a/client/settings.cpp b/client/settings.cpp index fc3a5825..6e470a33 100644 --- a/client/settings.cpp +++ b/client/settings.cpp @@ -312,10 +312,3 @@ ServerCredentials Settings::serverCredentials(int index) const return credentials; } - -bool Settings::isThirdPartyConfig(int serverIndex) const -{ - if (serverIndex < 0) return false; - const QJsonObject &s = server(serverIndex); - return s.value(config_key::isThirdPartyConfig).toBool(); -} diff --git a/client/settings.h b/client/settings.h index 56b28c18..c78b9a79 100644 --- a/client/settings.h +++ b/client/settings.h @@ -113,8 +113,6 @@ public: QByteArray backupAppConfig() const { return m_settings.backupAppConfig(); } bool restoreAppConfig(const QByteArray &cfg) { return m_settings.restoreAppConfig(cfg); } - bool isThirdPartyConfig(int serverIndex) const; - private: SecureQSettings m_settings; diff --git a/client/ui/pages_logic/ServerContainersLogic.cpp b/client/ui/pages_logic/ServerContainersLogic.cpp index ba873eb2..27f865b5 100644 --- a/client/ui/pages_logic/ServerContainersLogic.cpp +++ b/client/ui/pages_logic/ServerContainersLogic.cpp @@ -38,8 +38,7 @@ void ServerContainersLogic::onPushButtonProtoSettingsClicked(DockerContainer c, uiLogic()->selectedDockerContainer = c; uiLogic()->protocolLogic(p)->updateProtocolPage(m_settings->protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, p), uiLogic()->selectedDockerContainer, - m_settings->haveAuthData(uiLogic()->selectedServerIndex), - m_settings->isThirdPartyConfig(uiLogic()->selectedServerIndex)); + m_settings->haveAuthData(uiLogic()->selectedServerIndex)); emit uiLogic()->goToProtocolPage(p); } diff --git a/client/ui/pages_logic/StartPageLogic.cpp b/client/ui/pages_logic/StartPageLogic.cpp index 2a738fcf..09ebde9d 100644 --- a/client/ui/pages_logic/StartPageLogic.cpp +++ b/client/ui/pages_logic/StartPageLogic.cpp @@ -250,6 +250,7 @@ bool StartPageLogic::importConnectionFromOpenVpnConfig(const QString &config) QJsonObject lastConfig; lastConfig[config_key::last_config] = QString(QJsonDocument(openVpnConfig).toJson()); + lastConfig[config_key::isThirdPartyConfig] = true; QJsonObject containers; containers.insert(config_key::container, QJsonValue("amnezia-openvpn")); @@ -268,7 +269,7 @@ bool StartPageLogic::importConnectionFromOpenVpnConfig(const QString &config) QJsonObject o; o[config_key::containers] = arr; o[config_key::defaultContainer] = "amnezia-openvpn"; - o[config_key::description] = QString("OpenVpn server %1").arg(hostName); + o[config_key::description] = QString("OpenVpn server"); const static QRegularExpression dnsRegExp("dhcp-option DNS (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)"); @@ -282,8 +283,6 @@ bool StartPageLogic::importConnectionFromOpenVpnConfig(const QString &config) o[config_key::hostName] = hostName; - o[config_key::isThirdPartyConfig] = true; - return importConnection(o); } @@ -302,7 +301,8 @@ bool StartPageLogic::importConnectionFromWireguardConfig(const QString &config) } QJsonObject wireguardConfig; - wireguardConfig[config_key::last_config] = QString(QJsonDocument(lastConfig).toJson());; + wireguardConfig[config_key::last_config] = QString(QJsonDocument(lastConfig).toJson()); + wireguardConfig[config_key::isThirdPartyConfig] = true; wireguardConfig[config_key::port] = port; wireguardConfig[config_key::transport_proto] = "udp"; @@ -316,7 +316,7 @@ bool StartPageLogic::importConnectionFromWireguardConfig(const QString &config) QJsonObject o; o[config_key::containers] = arr; o[config_key::defaultContainer] = "amnezia-wireguard"; - o[config_key::description] = QString("Wireguard server %1").arg(hostName); + o[config_key::description] = QString("Wireguard server"); const static QRegularExpression dnsRegExp("DNS = (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b).*(\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)"); QRegularExpressionMatch dnsMatch = dnsRegExp.match(config); @@ -327,7 +327,5 @@ bool StartPageLogic::importConnectionFromWireguardConfig(const QString &config) o[config_key::hostName] = hostName; - o[config_key::isThirdPartyConfig] = true; - return importConnection(o); } diff --git a/client/ui/pages_logic/ViewConfigLogic.cpp b/client/ui/pages_logic/ViewConfigLogic.cpp index 1dfe9abe..9ccd9d3e 100644 --- a/client/ui/pages_logic/ViewConfigLogic.cpp +++ b/client/ui/pages_logic/ViewConfigLogic.cpp @@ -13,6 +13,8 @@ void ViewConfigLogic::onUpdatePage() { set_configText(QJsonDocument(configJson()).toJson()); + auto s = configJson()[config_key::isThirdPartyConfig].toBool(); + m_openVpnLastConfigs = m_openVpnMalStrings = "