added import of configs in .ovpn format
- on the "OpenVPN Settings" page, such a config will be displayed as raw text
This commit is contained in:
parent
b62d0697be
commit
53d7a92a0d
15 changed files with 430 additions and 322 deletions
|
@ -312,3 +312,10 @@ ServerCredentials Settings::serverCredentials(int index) const
|
||||||
|
|
||||||
return credentials;
|
return credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Settings::isThirdPartyConfig(int serverIndex) const
|
||||||
|
{
|
||||||
|
if (serverIndex < 0) return false;
|
||||||
|
const QJsonObject &s = server(serverIndex);
|
||||||
|
return s.value("isThirdPartyConfig").toBool();
|
||||||
|
}
|
||||||
|
|
|
@ -113,6 +113,8 @@ public:
|
||||||
QByteArray backupAppConfig() const { return m_settings.backupAppConfig(); }
|
QByteArray backupAppConfig() const { return m_settings.backupAppConfig(); }
|
||||||
bool restoreAppConfig(const QByteArray &cfg) { return m_settings.restoreAppConfig(cfg); }
|
bool restoreAppConfig(const QByteArray &cfg) { return m_settings.restoreAppConfig(cfg); }
|
||||||
|
|
||||||
|
bool isThirdPartyConfig(int serverIndex) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SecureQSettings m_settings;
|
SecureQSettings m_settings;
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,8 @@ void ServerContainersLogic::onPushButtonProtoSettingsClicked(DockerContainer c,
|
||||||
uiLogic()->selectedDockerContainer = c;
|
uiLogic()->selectedDockerContainer = c;
|
||||||
uiLogic()->protocolLogic(p)->updateProtocolPage(m_settings->protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, p),
|
uiLogic()->protocolLogic(p)->updateProtocolPage(m_settings->protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, p),
|
||||||
uiLogic()->selectedDockerContainer,
|
uiLogic()->selectedDockerContainer,
|
||||||
m_settings->haveAuthData(uiLogic()->selectedServerIndex));
|
m_settings->haveAuthData(uiLogic()->selectedServerIndex),
|
||||||
|
m_settings->isThirdPartyConfig(uiLogic()->selectedServerIndex));
|
||||||
|
|
||||||
emit uiLogic()->goToProtocolPage(p);
|
emit uiLogic()->goToProtocolPage(p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,25 @@
|
||||||
#include "platforms/android/android_controller.h"
|
#include "platforms/android/android_controller.h"
|
||||||
#endif
|
#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):
|
StartPageLogic::StartPageLogic(UiLogic *logic, QObject *parent):
|
||||||
PageLogicBase(logic, parent),
|
PageLogicBase(logic, parent),
|
||||||
m_pushButtonConnectEnabled{true},
|
m_pushButtonConnectEnabled{true},
|
||||||
|
@ -136,7 +155,7 @@ void StartPageLogic::onPushButtonImport()
|
||||||
void StartPageLogic::onPushButtonImportOpenFile()
|
void StartPageLogic::onPushButtonImportOpenFile()
|
||||||
{
|
{
|
||||||
QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open profile"),
|
QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open profile"),
|
||||||
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.vpn");
|
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.vpn *.ovpn");
|
||||||
|
|
||||||
if (fileName.isEmpty()) return;
|
if (fileName.isEmpty()) return;
|
||||||
|
|
||||||
|
@ -144,7 +163,12 @@ void StartPageLogic::onPushButtonImportOpenFile()
|
||||||
file.open(QIODevice::ReadOnly);
|
file.open(QIODevice::ReadOnly);
|
||||||
QByteArray data = file.readAll();
|
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)
|
bool StartPageLogic::importConnection(const QJsonObject &profile)
|
||||||
|
@ -214,3 +238,44 @@ bool StartPageLogic::importConnectionFromQr(const QByteArray &data)
|
||||||
|
|
||||||
return false;
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ public:
|
||||||
bool importConnection(const QJsonObject &profile);
|
bool importConnection(const QJsonObject &profile);
|
||||||
bool importConnectionFromCode(QString code);
|
bool importConnectionFromCode(QString code);
|
||||||
bool importConnectionFromQr(const QByteArray &data);
|
bool importConnectionFromQr(const QByteArray &data);
|
||||||
|
bool importConnectionFromOpenVpnConfig(const QString &config);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit StartPageLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
explicit StartPageLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
||||||
|
|
|
@ -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_pageEnabled(haveAuthData);
|
||||||
set_pushButtonSaveVisible(haveAuthData);
|
set_pushButtonSaveVisible(haveAuthData);
|
||||||
|
|
|
@ -28,7 +28,7 @@ public:
|
||||||
explicit CloakLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
explicit CloakLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
||||||
~CloakLogic() = default;
|
~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;
|
QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -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";
|
qDebug() << "OpenVpnLogic::updateProtocolPage";
|
||||||
set_pageEnabled(haveAuthData);
|
set_pageEnabled(haveAuthData);
|
||||||
|
@ -87,6 +87,16 @@ void OpenVpnLogic::updateProtocolPage(const QJsonObject &openvpnConfig, DockerCo
|
||||||
toString(protocols::openvpn::defaultPort));
|
toString(protocols::openvpn::defaultPort));
|
||||||
|
|
||||||
set_lineEditPortEnabled(container == DockerContainer::OpenVpn);
|
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()
|
void OpenVpnLogic::onPushButtonProtoOpenVpnSaveClicked()
|
||||||
|
|
|
@ -35,6 +35,9 @@ class OpenVpnLogic : public PageProtocolLogicBase
|
||||||
AUTO_PROPERTY(int, progressBarResetValue)
|
AUTO_PROPERTY(int, progressBarResetValue)
|
||||||
AUTO_PROPERTY(int, progressBarResetMaximium)
|
AUTO_PROPERTY(int, progressBarResetMaximium)
|
||||||
|
|
||||||
|
AUTO_PROPERTY(QString, openVpnLastConfigText)
|
||||||
|
AUTO_PROPERTY(bool, isThirdPartyConfig)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Q_INVOKABLE void onPushButtonProtoOpenVpnSaveClicked();
|
Q_INVOKABLE void onPushButtonProtoOpenVpnSaveClicked();
|
||||||
|
|
||||||
|
@ -42,7 +45,7 @@ public:
|
||||||
explicit OpenVpnLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
explicit OpenVpnLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
||||||
~OpenVpnLogic() = default;
|
~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;
|
QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -36,7 +36,7 @@ OtherProtocolsLogic::~OtherProtocolsLogic()
|
||||||
#endif
|
#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_labelTftpUserNameText(config.value(config_key::userName).toString());
|
||||||
set_labelTftpPasswordText(config.value(config_key::password).toString(protocols::sftp::defaultUserName));
|
set_labelTftpPasswordText(config.value(config_key::password).toString(protocols::sftp::defaultUserName));
|
||||||
|
|
|
@ -27,7 +27,7 @@ public:
|
||||||
explicit OtherProtocolsLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
explicit OtherProtocolsLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
||||||
~OtherProtocolsLogic();
|
~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;
|
//QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -17,7 +17,7 @@ public:
|
||||||
explicit PageProtocolLogicBase(UiLogic *uiLogic, QObject *parent = nullptr);
|
explicit PageProtocolLogicBase(UiLogic *uiLogic, QObject *parent = nullptr);
|
||||||
~PageProtocolLogicBase() = default;
|
~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(); }
|
virtual QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) { return QJsonObject(); }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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_pageEnabled(haveAuthData);
|
||||||
set_pushButtonSaveVisible(haveAuthData);
|
set_pushButtonSaveVisible(haveAuthData);
|
||||||
|
|
|
@ -26,7 +26,7 @@ public:
|
||||||
explicit ShadowSocksLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
explicit ShadowSocksLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
||||||
~ShadowSocksLogic() = default;
|
~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;
|
QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -36,370 +36,389 @@ PageProtocolBase {
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: content
|
id: content
|
||||||
enabled: logic.pageEnabled
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
LabelType {
|
visible: !logic.isThirdPartyConfig
|
||||||
id: lb_subnet
|
enabled: logic.pageEnabled
|
||||||
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
|
|
||||||
LabelType {
|
LabelType {
|
||||||
id: lb_port
|
id: lb_subnet
|
||||||
height: 31
|
height: 21
|
||||||
text: qsTr("Port")
|
text: qsTr("VPN Addresses Subnet")
|
||||||
Layout.preferredWidth: root.width / 2 - 10
|
|
||||||
}
|
}
|
||||||
TextFieldType {
|
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
|
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
|
height: 31
|
||||||
text: logic.lineEditPortText
|
model: [
|
||||||
onEditingFinished: {
|
qsTr("AES-256-GCM"),
|
||||||
logic.lineEditPortText = text
|
qsTr("AES-192-GCM"),
|
||||||
}
|
qsTr("AES-128-GCM"),
|
||||||
enabled: logic.lineEditPortEnabled
|
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")
|
||||||
CheckBoxType {
|
]
|
||||||
id: check_auto_enc
|
currentIndex: {
|
||||||
|
for (let i = 0; i < model.length; ++i) {
|
||||||
implicitWidth: parent.width
|
if (logic.comboBoxVpnCipherText === model[i]) {
|
||||||
height: 21
|
return i
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
return -1
|
||||||
}
|
}
|
||||||
return -1
|
onCurrentTextChanged: {
|
||||||
|
logic.comboBoxVpnCipherText = currentText
|
||||||
|
}
|
||||||
|
enabled: !check_auto_enc.checked
|
||||||
}
|
}
|
||||||
onCurrentTextChanged: {
|
|
||||||
logic.comboBoxVpnCipherText = currentText
|
|
||||||
}
|
|
||||||
enabled: !check_auto_enc.checked
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
LabelType {
|
LabelType {
|
||||||
id: lb_hash
|
id: lb_hash
|
||||||
height: 21
|
height: 21
|
||||||
Layout.topMargin: 20
|
Layout.topMargin: 20
|
||||||
text: qsTr("Hash")
|
text: qsTr("Hash")
|
||||||
}
|
}
|
||||||
ComboBoxType {
|
ComboBoxType {
|
||||||
id: cb_hash
|
id: cb_hash
|
||||||
height: 31
|
height: 31
|
||||||
implicitWidth: parent.width
|
implicitWidth: parent.width
|
||||||
model: [
|
model: [
|
||||||
qsTr("SHA512"),
|
qsTr("SHA512"),
|
||||||
qsTr("SHA384"),
|
qsTr("SHA384"),
|
||||||
qsTr("SHA256"),
|
qsTr("SHA256"),
|
||||||
qsTr("SHA3-512"),
|
qsTr("SHA3-512"),
|
||||||
qsTr("SHA3-384"),
|
qsTr("SHA3-384"),
|
||||||
qsTr("SHA3-256"),
|
qsTr("SHA3-256"),
|
||||||
qsTr("whirlpool"),
|
qsTr("whirlpool"),
|
||||||
qsTr("BLAKE2b512"),
|
qsTr("BLAKE2b512"),
|
||||||
qsTr("BLAKE2s256"),
|
qsTr("BLAKE2s256"),
|
||||||
qsTr("SHA1")
|
qsTr("SHA1")
|
||||||
]
|
]
|
||||||
currentIndex: {
|
currentIndex: {
|
||||||
for (let i = 0; i < model.length; ++i) {
|
for (let i = 0; i < model.length; ++i) {
|
||||||
if (logic.comboBoxVpnHashText === model[i]) {
|
if (logic.comboBoxVpnHashText === model[i]) {
|
||||||
return i
|
return i
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return -1
|
||||||
}
|
}
|
||||||
return -1
|
onCurrentTextChanged: {
|
||||||
}
|
logic.comboBoxVpnHashText = currentText
|
||||||
onCurrentTextChanged: {
|
}
|
||||||
logic.comboBoxVpnHashText = currentText
|
enabled: !check_auto_enc.checked
|
||||||
}
|
|
||||||
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_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 {
|
CheckBoxType {
|
||||||
anchors.fill: parent
|
id: check_block_dns
|
||||||
font.family: "Lato"
|
implicitWidth: parent.width
|
||||||
font.styleName: "normal"
|
height: 21
|
||||||
font.pixelSize: 16
|
text: qsTr("Block DNS requests outside of VPN")
|
||||||
color: "#15CDCB";
|
checked: logic.checkBoxBlockDnsChecked
|
||||||
text: pb_client_config.text
|
onCheckedChanged: {
|
||||||
horizontalAlignment: Text.AlignLeft
|
logic.checkBoxBlockDnsChecked = checked
|
||||||
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 {
|
BasicButtonType {
|
||||||
anchors.fill: parent
|
id: pb_client_config
|
||||||
TextArea {
|
|
||||||
id: te_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.family: "Lato"
|
||||||
font.styleName: "normal"
|
font.styleName: "normal"
|
||||||
font.pixelSize: 16
|
font.pixelSize: 16
|
||||||
color: "#181922"
|
color: "#15CDCB";
|
||||||
text: logic.textAreaAdditionalClientConfig
|
text: pb_client_config.text
|
||||||
onEditingFinished: {
|
horizontalAlignment: Text.AlignLeft
|
||||||
logic.textAreaAdditionalClientConfig = text
|
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 {
|
contentItem: Text {
|
||||||
id: pb_server_config
|
anchors.fill: parent
|
||||||
|
|
||||||
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
|
|
||||||
font.family: "Lato"
|
font.family: "Lato"
|
||||||
font.styleName: "normal"
|
font.styleName: "normal"
|
||||||
font.pixelSize: 16
|
font.pixelSize: 16
|
||||||
color: "#181922"
|
color: "#15CDCB";
|
||||||
text: logic.textAreaAdditionalServerConfig
|
text: pb_server_config.text
|
||||||
onEditingFinished: {
|
horizontalAlignment: Text.AlignLeft
|
||||||
logic.textAreaAdditionalServerConfig = text
|
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 {
|
LabelType {
|
||||||
id: it_save
|
id: label_proto_openvpn_info
|
||||||
implicitWidth: parent.width
|
|
||||||
Layout.topMargin: 20
|
|
||||||
height: 40
|
|
||||||
|
|
||||||
BlueButtonType {
|
height: 41
|
||||||
id: pb_save
|
visible: logic.labelProtoOpenVpnInfoVisible
|
||||||
z: 1
|
text: logic.labelProtoOpenVpnInfoText
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: it_save
|
||||||
|
implicitWidth: parent.width
|
||||||
|
Layout.topMargin: 20
|
||||||
height: 40
|
height: 40
|
||||||
text: qsTr("Save and restart VPN")
|
|
||||||
width: parent.width
|
|
||||||
visible: logic.pushButtonSaveVisible
|
|
||||||
onClicked: {
|
|
||||||
logic.onPushButtonProtoOpenVpnSaveClicked()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressBar {
|
BlueButtonType {
|
||||||
id: progress_save
|
id: pb_save
|
||||||
anchors.fill: pb_save
|
z: 1
|
||||||
from: 0
|
height: 40
|
||||||
to: logic.progressBarResetMaximium
|
text: qsTr("Save and restart VPN")
|
||||||
value: logic.progressBarResetValue
|
width: parent.width
|
||||||
visible: logic.progressBarResetVisible
|
visible: logic.pushButtonSaveVisible
|
||||||
background: Rectangle {
|
onClicked: {
|
||||||
implicitWidth: parent.width
|
logic.onPushButtonProtoOpenVpnSaveClicked()
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue