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 + } + } + } } }