Merge branch 'dev' into ios_main
This commit is contained in:
commit
fd9d54d2dd
98 changed files with 3280 additions and 2062 deletions
|
@ -597,7 +597,7 @@ CQR_Encode::~CQR_Encode()
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CQR_Encode::EncodeData
|
||||
|
||||
bool CQR_Encode::EncodeData(int nLevel, int nVersion, bool bAutoExtent, int nMaskingNo, char* lpsSource, int ncSource)
|
||||
bool CQR_Encode::EncodeData(int nLevel, int nVersion, bool bAutoExtent, int nMaskingNo, const char* lpsSource, int ncSource)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
|
@ -746,7 +746,7 @@ bool CQR_Encode::EncodeData(int nLevel, int nVersion, bool bAutoExtent, int nMas
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CQR_Encode::GetEncodeVersion
|
||||
|
||||
int CQR_Encode::GetEncodeVersion(int nVersion, char* lpsSource, int ncLength)
|
||||
int CQR_Encode::GetEncodeVersion(int nVersion, const char* lpsSource, int ncLength)
|
||||
{
|
||||
int nVerGroup = nVersion >= 27 ? QR_VRESION_L : (nVersion >= 10 ? QR_VRESION_M : QR_VRESION_S);
|
||||
int i, j;
|
||||
|
@ -788,7 +788,7 @@ int CQR_Encode::GetEncodeVersion(int nVersion, char* lpsSource, int ncLength)
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CQR_Encode::EncodeSourceData
|
||||
bool CQR_Encode::EncodeSourceData(char* lpsSource, int ncLength, int nVerGroup)
|
||||
bool CQR_Encode::EncodeSourceData(const char* lpsSource, int ncLength, int nVerGroup)
|
||||
{
|
||||
memset(m_nBlockLength, 0, sizeof(m_nBlockLength));
|
||||
|
||||
|
|
|
@ -92,11 +92,11 @@ private:
|
|||
unsigned char m_byRSWork[MAX_CODEBLOCK];
|
||||
|
||||
public:
|
||||
bool EncodeData(int nLevel, int nVersion, bool bAutoExtent, int nMaskingNo, char* lpsSource, int ncSource = 0);
|
||||
bool EncodeData(int nLevel, int nVersion, bool bAutoExtent, int nMaskingNo, const char* lpsSource, int ncSource = 0);
|
||||
|
||||
private:
|
||||
int GetEncodeVersion(int nVersion, char* lpsSource, int ncLength);
|
||||
bool EncodeSourceData(char* lpsSource, int ncLength, int nVerGroup);
|
||||
int GetEncodeVersion(int nVersion, const char* lpsSource, int ncLength);
|
||||
bool EncodeSourceData(const char* lpsSource, int ncLength, int nVerGroup);
|
||||
|
||||
int GetBitLength(unsigned char nMode, int ncData, int nVerGroup);
|
||||
|
||||
|
|
|
@ -106,6 +106,8 @@ android {
|
|||
resConfig "en"
|
||||
minSdkVersion = 24
|
||||
targetSdkVersion = 30
|
||||
versionCode 2 // Change to a higher number
|
||||
versionName "2.0.1" // Change to a higher number
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
|
|
@ -287,48 +287,74 @@ class VPNService : android.net.VpnService() {
|
|||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Wireguard [Config] from a [json] string -
|
||||
* The [json] will be created in AndroidVpnProtocol.cpp
|
||||
*/
|
||||
private fun buildWireugardConfig(obj: JSONObject): Config {
|
||||
val confBuilder = Config.Builder()
|
||||
val jServer = obj.getJSONObject("server")
|
||||
val peerBuilder = Peer.Builder()
|
||||
val ep =
|
||||
InetEndpoint.parse(jServer.getString("ipv4AddrIn") + ":" + jServer.getString("port"))
|
||||
peerBuilder.setEndpoint(ep)
|
||||
peerBuilder.setPublicKey(Key.fromBase64(jServer.getString("publicKey")))
|
||||
|
||||
val jAllowedIPList = obj.getJSONArray("allowedIPs")
|
||||
if (jAllowedIPList.length() == 0) {
|
||||
val internet = InetNetwork.parse("0.0.0.0/0") // aka The whole internet.
|
||||
peerBuilder.addAllowedIp(internet)
|
||||
} else {
|
||||
(0 until jAllowedIPList.length()).toList().forEach {
|
||||
val network = InetNetwork.parse(jAllowedIPList.getString(it))
|
||||
peerBuilder.addAllowedIp(network)
|
||||
private fun parseConfigData(data: String): Map<String, Map<String, String>> {
|
||||
val parseData = mutableMapOf<String, Map<String, String>>()
|
||||
var currentSection: Pair<String, MutableMap<String, String>>? = null
|
||||
data.lines().forEach { line ->
|
||||
if (line.isNotEmpty()) {
|
||||
if (line.startsWith('[')) {
|
||||
currentSection?.let {
|
||||
parseData.put(it.first, it.second)
|
||||
}
|
||||
currentSection = line.substring(1, line.indexOfLast { it == ']' }) to mutableMapOf()
|
||||
} else {
|
||||
val parameter = line.split("=", limit = 2)
|
||||
currentSection!!.second.put(parameter.first().trim(), parameter.last().trim())
|
||||
}
|
||||
}
|
||||
|
||||
confBuilder.addPeer(peerBuilder.build())
|
||||
|
||||
val privateKey = obj.getJSONObject("keys").getString("privateKey")
|
||||
val jDevice = obj.getJSONObject("device")
|
||||
|
||||
val ifaceBuilder = Interface.Builder()
|
||||
ifaceBuilder.parsePrivateKey(privateKey)
|
||||
ifaceBuilder.addAddress(InetNetwork.parse(jDevice.getString("ipv4Address")))
|
||||
ifaceBuilder.addAddress(InetNetwork.parse(jDevice.getString("ipv6Address")))
|
||||
ifaceBuilder.addDnsServer(InetNetwork.parse(obj.getString("dns")).address)
|
||||
val jExcludedApplication = obj.getJSONArray("excludedApps")
|
||||
(0 until jExcludedApplication.length()).toList().forEach {
|
||||
val appName = jExcludedApplication.get(it).toString()
|
||||
ifaceBuilder.excludeApplication(appName)
|
||||
}
|
||||
confBuilder.setInterface(ifaceBuilder.build())
|
||||
return confBuilder.build()
|
||||
}
|
||||
currentSection?.let {
|
||||
parseData.put(it.first, it.second)
|
||||
}
|
||||
return parseData
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Wireguard [Config] from a [json] string -
|
||||
* The [json] will be created in AndroidVpnProtocol.cpp
|
||||
*/
|
||||
private fun buildWireugardConfig(obj: JSONObject): Config {
|
||||
val confBuilder = Config.Builder()
|
||||
val wireguardConfigData = obj.getJSONObject("wireguard_config_data")
|
||||
val config = parseConfigData(wireguardConfigData.getString("config"))
|
||||
val peerBuilder = Peer.Builder()
|
||||
val peerConfig = config["Peer"]!!
|
||||
peerBuilder.setPublicKey(Key.fromBase64(peerConfig["PublicKey"]))
|
||||
peerConfig["PresharedKey"]?.let {
|
||||
peerBuilder.setPreSharedKey(Key.fromBase64(it))
|
||||
}
|
||||
val allowedIPList = peerConfig["AllowedIPs"]?.split(",") ?: emptyList()
|
||||
if (allowedIPList.isEmpty()) {
|
||||
val internet = InetNetwork.parse("0.0.0.0/0") // aka The whole internet.
|
||||
peerBuilder.addAllowedIp(internet)
|
||||
} else {
|
||||
allowedIPList.forEach {
|
||||
val network = InetNetwork.parse(it.trim())
|
||||
peerBuilder.addAllowedIp(network)
|
||||
}
|
||||
}
|
||||
peerBuilder.setEndpoint(InetEndpoint.parse(peerConfig["Endpoint"]))
|
||||
peerConfig["PersistentKeepalive"]?.let {
|
||||
peerBuilder.setPersistentKeepalive(it.toInt())
|
||||
}
|
||||
confBuilder.addPeer(peerBuilder.build())
|
||||
|
||||
val ifaceBuilder = Interface.Builder()
|
||||
val ifaceConfig = config["Interface"]!!
|
||||
ifaceBuilder.parsePrivateKey(ifaceConfig["PrivateKey"])
|
||||
ifaceBuilder.addAddress(InetNetwork.parse(ifaceConfig["Address"]))
|
||||
ifaceConfig["DNS"]!!.split(",").forEach {
|
||||
ifaceBuilder.addDnsServer(InetNetwork.parse(it.trim()).address)
|
||||
}
|
||||
/*val jExcludedApplication = obj.getJSONArray("excludedApps")
|
||||
(0 until jExcludedApplication.length()).toList().forEach {
|
||||
val appName = jExcludedApplication.get(it).toString()
|
||||
ifaceBuilder.excludeApplication(appName)
|
||||
}*/
|
||||
confBuilder.setInterface(ifaceBuilder.build())
|
||||
|
||||
return confBuilder.build()
|
||||
}
|
||||
|
||||
fun getVpnConfig(): JSONObject {
|
||||
return mConfig!!
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <QDebug>
|
||||
#include <QTemporaryFile>
|
||||
#include <QJsonDocument>
|
||||
#include <QUuid>
|
||||
|
||||
#include "sftpdefs.h"
|
||||
|
||||
|
@ -21,6 +22,7 @@ Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const Se
|
|||
connData.host = credentials.hostName;
|
||||
connData.clientId = Utils::getRandomString(16);
|
||||
connData.password = Utils::getRandomString(16);
|
||||
connData.password = "";
|
||||
|
||||
QString certFileName = "/opt/amnezia/ikev2/clients/" + connData.clientId + ".p12";
|
||||
|
||||
|
@ -41,8 +43,11 @@ Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const Se
|
|||
.arg(certFileName);
|
||||
e = ServerController::runContainerScript(credentials, container, scriptExportCert);
|
||||
|
||||
connData.cert = ServerController::getTextFileFromContainer(container, credentials, certFileName, &e);
|
||||
qDebug() << "Ikev2Configurator::ConnectionData cert size:" << connData.cert.size();
|
||||
connData.clientCert = ServerController::getTextFileFromContainer(container, credentials, certFileName, &e);
|
||||
connData.caCert = ServerController::getTextFileFromContainer(container, credentials, "/etc/ipsec.d/ca_cert_base64.p12", &e);
|
||||
|
||||
qDebug() << "Ikev2Configurator::ConnectionData client cert size:" << connData.clientCert.size();
|
||||
qDebug() << "Ikev2Configurator::ConnectionData ca cert size:" << connData.caCert.size();
|
||||
|
||||
return connData;
|
||||
}
|
||||
|
@ -50,17 +55,62 @@ Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const Se
|
|||
QString Ikev2Configurator::genIkev2Config(const ServerCredentials &credentials,
|
||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
{
|
||||
Q_UNUSED(containerConfig)
|
||||
|
||||
ConnectionData connData = prepareIkev2Config(credentials, container, errorCode);
|
||||
if (errorCode && *errorCode) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return genIkev2Config(connData);
|
||||
}
|
||||
|
||||
QString Ikev2Configurator::genIkev2Config(const ConnectionData &connData)
|
||||
{
|
||||
QJsonObject config;
|
||||
config[config_key::hostName] = connData.host;
|
||||
config[config_key::userName] = connData.clientId;
|
||||
config[config_key::cert] = QString(connData.cert.toBase64());
|
||||
config[config_key::cert] = QString(connData.clientCert.toBase64());
|
||||
config[config_key::password] = connData.password;
|
||||
|
||||
return QJsonDocument(config).toJson();
|
||||
}
|
||||
|
||||
QString Ikev2Configurator::genMobileConfig(const ConnectionData &connData)
|
||||
{
|
||||
QFile file(":/server_scripts/ipsec/mobileconfig.plist");
|
||||
file.open(QIODevice::ReadOnly);
|
||||
QString config = QString(file.readAll());
|
||||
|
||||
config.replace("$CLIENT_NAME", connData.clientId);
|
||||
config.replace("$UUID1", QUuid::createUuid().toString());
|
||||
config.replace("$SERVER_ADDR", connData.host);
|
||||
|
||||
QString subStr("$(UUID_GEN)");
|
||||
while (config.indexOf(subStr) > 0) {
|
||||
config.replace(config.indexOf(subStr), subStr.size(), QUuid::createUuid().toString());
|
||||
}
|
||||
|
||||
config.replace("$P12_BASE64", connData.clientCert.toBase64());
|
||||
config.replace("$CA_BASE64", connData.caCert.toBase64());
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
QString Ikev2Configurator::genStrongSwanConfig(const ConnectionData &connData)
|
||||
{
|
||||
QFile file(":/server_scripts/ipsec/strongswan.profile");
|
||||
file.open(QIODevice::ReadOnly);
|
||||
QString config = QString(file.readAll());
|
||||
|
||||
config.replace("$CLIENT_NAME", connData.clientId);
|
||||
config.replace("$UUID", QUuid::createUuid().toString());
|
||||
config.replace("$SERVER_ADDR", connData.host);
|
||||
|
||||
QByteArray cert = connData.clientCert.toBase64();
|
||||
cert.replace("\r", "").replace("\n", "");
|
||||
config.replace("$P12_BASE64", cert);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@ class Ikev2Configurator
|
|||
public:
|
||||
|
||||
struct ConnectionData {
|
||||
QByteArray cert; // p12 client cert
|
||||
QByteArray clientCert; // p12 client cert
|
||||
QByteArray caCert; // p12 server cert
|
||||
QString clientId;
|
||||
QString password; // certificate password
|
||||
QString host; // host ip
|
||||
|
@ -21,8 +22,10 @@ public:
|
|||
static QString genIkev2Config(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
|
||||
static QString genIkev2Config(const ConnectionData &connData);
|
||||
static QString genMobileConfig(const ConnectionData &connData);
|
||||
static QString genStrongSwanConfig(const ConnectionData &connData);
|
||||
|
||||
private:
|
||||
static ConnectionData prepareIkev2Config(const ServerCredentials &credentials,
|
||||
DockerContainer container, ErrorCode *errorCode = nullptr);
|
||||
};
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
#include <QDebug>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/pem.h>
|
||||
|
||||
#include "sftpdefs.h"
|
||||
|
||||
#include "core/server_defs.h"
|
||||
|
@ -13,72 +18,34 @@
|
|||
#include "core/scripts_registry.h"
|
||||
#include "utils.h"
|
||||
|
||||
QProcessEnvironment WireguardConfigurator::prepareEnv()
|
||||
{
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
QString pathEnvVar = env.value("PATH");
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
pathEnvVar.clear();
|
||||
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\wireguard;");
|
||||
#else
|
||||
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "/Contents/MacOS");
|
||||
#endif
|
||||
|
||||
env.insert("PATH", pathEnvVar);
|
||||
qDebug().noquote() << "ENV PATH" << pathEnvVar;
|
||||
return env;
|
||||
}
|
||||
|
||||
WireguardConfigurator::ConnectionData WireguardConfigurator::genClientKeys()
|
||||
{
|
||||
// TODO review
|
||||
constexpr size_t EDDSA_KEY_LENGTH = 32;
|
||||
|
||||
ConnectionData connData;
|
||||
|
||||
QString program;
|
||||
#ifdef Q_OS_WIN
|
||||
program = QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\wireguard\\wg.exe";
|
||||
#else
|
||||
program = QDir::toNativeSeparators(QApplication::applicationDirPath()) + "/Contents/MacOS/wg";
|
||||
#endif
|
||||
unsigned char buff[EDDSA_KEY_LENGTH];
|
||||
int ret = RAND_priv_bytes(buff, EDDSA_KEY_LENGTH);
|
||||
if (ret <=0) return connData;
|
||||
|
||||
#ifndef Q_OS_IOS
|
||||
EVP_PKEY * pKey = EVP_PKEY_new();
|
||||
q_check_ptr(pKey);
|
||||
pKey = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL, &buff[0], EDDSA_KEY_LENGTH);
|
||||
|
||||
// Priv
|
||||
{
|
||||
QProcess p;
|
||||
p.setProcessEnvironment(prepareEnv());
|
||||
p.setProcessChannelMode(QProcess::MergedChannels);
|
||||
p.setProgram(program);
|
||||
|
||||
p.setArguments(QStringList() << "genkey");
|
||||
size_t keySize = EDDSA_KEY_LENGTH;
|
||||
|
||||
p.start();
|
||||
p.waitForFinished();
|
||||
// save private key
|
||||
unsigned char priv[EDDSA_KEY_LENGTH];
|
||||
EVP_PKEY_get_raw_private_key(pKey, priv, &keySize);
|
||||
connData.clientPrivKey = QByteArray::fromRawData((char*)priv, keySize).toBase64();
|
||||
|
||||
connData.clientPrivKey = QString(p.readAll());
|
||||
connData.clientPrivKey.replace("\r", "");
|
||||
connData.clientPrivKey.replace("\n", "");
|
||||
}
|
||||
// save public key
|
||||
unsigned char pub[EDDSA_KEY_LENGTH];
|
||||
EVP_PKEY_get_raw_public_key(pKey, pub, &keySize);
|
||||
connData.clientPubKey = QByteArray::fromRawData((char*)pub, keySize).toBase64();
|
||||
|
||||
// Pub
|
||||
{
|
||||
QProcess p;
|
||||
p.setProcessEnvironment(prepareEnv());
|
||||
p.setProcessChannelMode(QProcess::MergedChannels);
|
||||
p.setProgram(program);
|
||||
|
||||
p.setArguments(QStringList() << "pubkey");
|
||||
|
||||
p.start();
|
||||
p.write(connData.clientPrivKey.toUtf8());
|
||||
p.closeWriteChannel();
|
||||
p.waitForFinished();
|
||||
|
||||
connData.clientPubKey = QString(p.readAll());
|
||||
connData.clientPubKey.replace("\r", "");
|
||||
connData.clientPubKey.replace("\n", "");
|
||||
}
|
||||
#endif
|
||||
return connData;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,8 +28,6 @@ public:
|
|||
|
||||
|
||||
private:
|
||||
static QProcessEnvironment prepareEnv();
|
||||
|
||||
static ConnectionData prepareWireguardConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, ErrorCode *errorCode = nullptr);
|
||||
|
||||
|
|
|
@ -43,11 +43,14 @@ QVector<amnezia::Protocol> ContainerProps::protocolsForContainer(amnezia::Docker
|
|||
return { Protocol::OpenVpn, Protocol::ShadowSocks, Protocol::Cloak };
|
||||
|
||||
case DockerContainer::Ipsec:
|
||||
return { Protocol::Ikev2, Protocol::L2tp };
|
||||
return { Protocol::Ikev2 /*, Protocol::L2tp */};
|
||||
|
||||
case DockerContainer::Dns:
|
||||
return { };
|
||||
|
||||
case DockerContainer::Sftp:
|
||||
return { Protocol::Sftp};
|
||||
|
||||
default:
|
||||
return { defaultProtocol(container) };
|
||||
}
|
||||
|
@ -72,11 +75,11 @@ QMap<DockerContainer, QString> ContainerProps::containerHumanNames()
|
|||
{DockerContainer::ShadowSocks, "OpenVpn over ShadowSocks"},
|
||||
{DockerContainer::Cloak, "OpenVpn over Cloak"},
|
||||
{DockerContainer::WireGuard, "WireGuard"},
|
||||
{DockerContainer::Ipsec, QObject::tr("IPsec container")},
|
||||
{DockerContainer::Ipsec, QObject::tr("IPsec")},
|
||||
|
||||
{DockerContainer::TorWebSite, QObject::tr("Web site in TOR network")},
|
||||
{DockerContainer::Dns, QObject::tr("DNS Service")},
|
||||
{DockerContainer::FileShare, QObject::tr("SMB file sharing service")},
|
||||
//{DockerContainer::FileShare, QObject::tr("SMB file sharing service")},
|
||||
{DockerContainer::Sftp, QObject::tr("Sftp file sharing service")}
|
||||
};
|
||||
}
|
||||
|
@ -93,7 +96,7 @@ QMap<DockerContainer, QString> ContainerProps::containerDescriptions()
|
|||
|
||||
{DockerContainer::TorWebSite, QObject::tr("Web site in TOR network")},
|
||||
{DockerContainer::Dns, QObject::tr("DNS Service")},
|
||||
{DockerContainer::FileShare, QObject::tr("SMB file sharing service - is Window file sharing protocol")},
|
||||
//{DockerContainer::FileShare, QObject::tr("SMB file sharing service - is Window file sharing protocol")},
|
||||
{DockerContainer::Sftp, QObject::tr("Sftp file sharing service - is secure FTP service")}
|
||||
};
|
||||
}
|
||||
|
@ -109,7 +112,7 @@ amnezia::ServiceType ContainerProps::containerService(DockerContainer c)
|
|||
case DockerContainer::Ipsec : return ServiceType::Vpn;
|
||||
case DockerContainer::TorWebSite : return ServiceType::Other;
|
||||
case DockerContainer::Dns : return ServiceType::Other;
|
||||
case DockerContainer::FileShare : return ServiceType::Other;
|
||||
//case DockerContainer::FileShare : return ServiceType::Other;
|
||||
case DockerContainer::Sftp : return ServiceType::Other;
|
||||
default: return ServiceType::Other;
|
||||
}
|
||||
|
@ -127,8 +130,9 @@ Protocol ContainerProps::defaultProtocol(DockerContainer c)
|
|||
|
||||
case DockerContainer::TorWebSite : return Protocol::TorWebSite;
|
||||
case DockerContainer::Dns : return Protocol::Dns;
|
||||
case DockerContainer::FileShare : return Protocol::FileShare;
|
||||
//case DockerContainer::FileShare : return Protocol::FileShare;
|
||||
case DockerContainer::Sftp : return Protocol::Sftp;
|
||||
default: return Protocol::Any;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ enum DockerContainer {
|
|||
//non-vpn
|
||||
TorWebSite,
|
||||
Dns,
|
||||
FileShare,
|
||||
//FileShare,
|
||||
Sftp
|
||||
};
|
||||
Q_ENUM_NS(DockerContainer)
|
||||
|
|
|
@ -1,38 +1,83 @@
|
|||
#include "ipcclient.h"
|
||||
#include <QRemoteObjectNode>
|
||||
|
||||
IpcClient &IpcClient::Instance()
|
||||
IpcClient *IpcClient::m_instance = nullptr;
|
||||
|
||||
IpcClient::IpcClient(QObject *parent) : QObject(parent)
|
||||
{
|
||||
static IpcClient s;
|
||||
return s;
|
||||
|
||||
}
|
||||
|
||||
bool IpcClient::init()
|
||||
IpcClient::~IpcClient()
|
||||
{
|
||||
Instance().m_localSocket->waitForConnected();
|
||||
if (m_localSocket) m_localSocket->close();
|
||||
}
|
||||
|
||||
if (!Instance().m_ipcClient) {
|
||||
bool IpcClient::isSocketConnected() const
|
||||
{
|
||||
return m_isSocketConnected;
|
||||
}
|
||||
|
||||
IpcClient *IpcClient::Instance()
|
||||
{
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
QSharedPointer<IpcInterfaceReplica> IpcClient::Interface()
|
||||
{
|
||||
if (!Instance()) return nullptr;
|
||||
return Instance()->m_ipcClient;
|
||||
}
|
||||
|
||||
bool IpcClient::init(IpcClient *instance)
|
||||
{
|
||||
m_instance = instance;
|
||||
|
||||
Instance()->m_localSocket = new QLocalSocket(Instance());
|
||||
connect(Instance()->m_localSocket.data(), &QLocalSocket::connected, &Instance()->m_ClientNode, []() {
|
||||
Instance()->m_ClientNode.addClientSideConnection(Instance()->m_localSocket.data());
|
||||
|
||||
Instance()->m_ipcClient.reset(Instance()->m_ClientNode.acquire<IpcInterfaceReplica>());
|
||||
Instance()->m_ipcClient->waitForSource(1000);
|
||||
|
||||
if (!Instance()->m_ipcClient->isReplicaValid()) {
|
||||
qWarning() << "IpcClient replica is not connected!";
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
connect(Instance()->m_localSocket, &QLocalSocket::disconnected, [instance](){
|
||||
instance->m_isSocketConnected = false;
|
||||
});
|
||||
|
||||
Instance()->m_localSocket->connectToServer(amnezia::getIpcServiceUrl());
|
||||
|
||||
Instance()->m_localSocket->waitForConnected();
|
||||
|
||||
if (!Instance()->m_ipcClient) {
|
||||
qDebug() << "IpcClient::init failed";
|
||||
return false;
|
||||
}
|
||||
return Instance().m_ipcClient->isReplicaValid();
|
||||
qDebug() << "IpcClient::init succeed";
|
||||
|
||||
return Instance()->m_ipcClient->isReplicaValid();
|
||||
}
|
||||
|
||||
QSharedPointer<IpcProcessInterfaceReplica> IpcClient::CreatePrivilegedProcess()
|
||||
{
|
||||
#ifndef Q_OS_IOS
|
||||
if (! Instance().m_ipcClient || ! Instance().m_ipcClient->isReplicaValid()) {
|
||||
if (! Instance()->m_ipcClient || ! Instance()->m_ipcClient->isReplicaValid()) {
|
||||
qWarning() << "IpcClient::createPrivilegedProcess : IpcClient IpcClient replica is not valid";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QRemoteObjectPendingReply<int> futureResult = Instance().m_ipcClient->createPrivilegedProcess();
|
||||
QRemoteObjectPendingReply<int> futureResult = Instance()->m_ipcClient->createPrivilegedProcess();
|
||||
futureResult.waitForFinished(1000);
|
||||
|
||||
int pid = futureResult.returnValue();
|
||||
|
||||
auto pd = QSharedPointer<ProcessDescriptor>(new ProcessDescriptor());
|
||||
Instance().m_processNodes.insert(pid, pd);
|
||||
Instance()->m_processNodes.insert(pid, pd);
|
||||
|
||||
pd->localSocket.reset(new QLocalSocket(pd->replicaNode.data()));
|
||||
|
||||
|
@ -65,19 +110,4 @@ QSharedPointer<IpcProcessInterfaceReplica> IpcClient::CreatePrivilegedProcess()
|
|||
#endif
|
||||
}
|
||||
|
||||
IpcClient::IpcClient(QObject *parent) : QObject(parent)
|
||||
{
|
||||
m_localSocket.reset(new QLocalSocket(this));
|
||||
connect(m_localSocket.data(), &QLocalSocket::connected, &m_ClientNode, [this]() {
|
||||
m_ClientNode.addClientSideConnection(m_localSocket.data());
|
||||
|
||||
m_ipcClient.reset(m_ClientNode.acquire<IpcInterfaceReplica>());
|
||||
m_ipcClient->waitForSource(1000);
|
||||
|
||||
if (!m_ipcClient->isReplicaValid()) {
|
||||
qWarning() << "IpcClient replica is not connected!";
|
||||
}
|
||||
|
||||
});
|
||||
m_localSocket->connectToServer(amnezia::getIpcServiceUrl());
|
||||
}
|
||||
|
|
|
@ -19,19 +19,23 @@ class IpcClient : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static IpcClient &Instance();
|
||||
static bool init();
|
||||
static QSharedPointer<IpcInterfaceReplica> Interface() { return Instance().m_ipcClient; }
|
||||
explicit IpcClient(QObject *parent = nullptr);
|
||||
|
||||
static IpcClient *Instance();
|
||||
static bool init(IpcClient *instance);
|
||||
static QSharedPointer<IpcInterfaceReplica> Interface();
|
||||
static QSharedPointer<IpcProcessInterfaceReplica> CreatePrivilegedProcess();
|
||||
|
||||
bool isSocketConnected() const;
|
||||
|
||||
signals:
|
||||
|
||||
private:
|
||||
explicit IpcClient(QObject *parent = nullptr);
|
||||
~IpcClient() override;
|
||||
|
||||
QRemoteObjectNode m_ClientNode;
|
||||
QSharedPointer<IpcInterfaceReplica> m_ipcClient;
|
||||
QSharedPointer<QLocalSocket> m_localSocket;
|
||||
QPointer<QLocalSocket> m_localSocket;
|
||||
|
||||
struct ProcessDescriptor {
|
||||
ProcessDescriptor () {
|
||||
|
@ -45,6 +49,9 @@ private:
|
|||
};
|
||||
|
||||
QMap<int, QSharedPointer<ProcessDescriptor>> m_processNodes;
|
||||
bool m_isSocketConnected {false};
|
||||
|
||||
static IpcClient *m_instance;
|
||||
};
|
||||
|
||||
#endif // IPCCLIENT_H
|
||||
|
|
|
@ -15,7 +15,7 @@ QString amnezia::scriptFolder(amnezia::DockerContainer container)
|
|||
|
||||
case DockerContainer::TorWebSite: return QLatin1String("website_tor");
|
||||
case DockerContainer::Dns: return QLatin1String("dns");
|
||||
case DockerContainer::FileShare: return QLatin1String("file_share");
|
||||
//case DockerContainer::FileShare: return QLatin1String("file_share");
|
||||
case DockerContainer::Sftp: return QLatin1String("sftp");
|
||||
default: return "";
|
||||
}
|
||||
|
|
|
@ -24,6 +24,12 @@
|
|||
|
||||
using namespace QSsh;
|
||||
|
||||
Settings &ServerController::m_settings()
|
||||
{
|
||||
static Settings s;
|
||||
return s;
|
||||
}
|
||||
|
||||
ErrorCode ServerController::runScript(const ServerCredentials &credentials, QString script,
|
||||
const std::function<void(const QString &, QSharedPointer<SshRemoteProcess>)> &cbReadStdOut,
|
||||
const std::function<void(const QString &, QSharedPointer<SshRemoteProcess>)> &cbReadStdErr)
|
||||
|
@ -127,16 +133,22 @@ ErrorCode ServerController::runContainerScript(const ServerCredentials &credenti
|
|||
const std::function<void (const QString &, QSharedPointer<QSsh::SshRemoteProcess>)> &cbReadStdErr)
|
||||
{
|
||||
QString fileName = "/opt/amnezia/" + Utils::getRandomString(16) + ".sh";
|
||||
ErrorCode e = uploadTextFileToContainer(container, credentials, script, fileName);
|
||||
|
||||
QString mkdir = "sudo docker exec -i $CONTAINER_NAME mkdir -p /opt/amnezia/";
|
||||
ErrorCode e = runScript(credentials,
|
||||
replaceVars(mkdir, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
|
||||
if (e) return e;
|
||||
|
||||
e = uploadTextFileToContainer(container, credentials, script, fileName);
|
||||
if (e) return e;
|
||||
|
||||
QString runner = QString("sudo docker exec -i $CONTAINER_NAME bash %1 ").arg(fileName);
|
||||
e = runScript(credentials,
|
||||
replaceVars(runner, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
|
||||
|
||||
// QString remover = QString("sudo docker exec -i $CONTAINER_NAME rm %1 ").arg(fileName);
|
||||
// runScript(credentials,
|
||||
// replaceVars(remover, genVarsForScript(credentials, container)));
|
||||
QString remover = QString("sudo docker exec -i $CONTAINER_NAME rm %1 ").arg(fileName);
|
||||
runScript(credentials,
|
||||
replaceVars(remover, genVarsForScript(credentials, container)));
|
||||
|
||||
return e;
|
||||
}
|
||||
|
@ -672,6 +684,8 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
|
|||
|
||||
vars.append({{"$IPSEC_VPN_C2C_TRAFFIC", "no"}});
|
||||
|
||||
vars.append({{"$PRIMARY_SERVER_DNS", m_settings().primaryDns()}});
|
||||
vars.append({{"$SECONDARY_SERVER_DNS", m_settings().secondaryDns()}});
|
||||
|
||||
|
||||
// Sftp vars
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include "sshconnection.h"
|
||||
#include "sshremoteprocess.h"
|
||||
#include "defs.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include "containers/containers_defs.h"
|
||||
|
||||
#include "sftpdefs.h"
|
||||
|
@ -75,6 +77,7 @@ private:
|
|||
static ErrorCode configureContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config);
|
||||
static ErrorCode startupContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject());
|
||||
|
||||
static Settings &m_settings();
|
||||
};
|
||||
|
||||
#endif // SERVERCONTROLLER_H
|
||||
|
|
BIN
client/images/animation.gif
Normal file
BIN
client/images/animation.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 MiB |
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.3 KiB |
BIN
client/images/connected.png
Normal file
BIN
client/images/connected.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
client/images/disconnected.png
Normal file
BIN
client/images/disconnected.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
|
@ -116,6 +116,9 @@ int main(int argc, char *argv[])
|
|||
|
||||
app.setQuitOnLastWindowClosed(false);
|
||||
|
||||
qRegisterMetaType<VpnProtocol::ConnectionState>("VpnProtocol::ConnectionState");
|
||||
qRegisterMetaType<ServerCredentials>("ServerCredentials");
|
||||
|
||||
qRegisterMetaType<DockerContainer>("DockerContainer");
|
||||
qRegisterMetaType<TransportProto>("TransportProto");
|
||||
qRegisterMetaType<Protocol>("Protocol");
|
||||
|
@ -127,12 +130,14 @@ int main(int argc, char *argv[])
|
|||
|
||||
UiLogic *uiLogic = new UiLogic;
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QQmlApplicationEngine *engine = new QQmlApplicationEngine;
|
||||
|
||||
declareQmlPageEnum();
|
||||
declareQmlProtocolEnum();
|
||||
declareQmlContainerEnum();
|
||||
|
||||
qmlRegisterType<PageType>("PageType", 1, 0, "PageType");
|
||||
|
||||
QScopedPointer<ContainerProps> containerProps(new ContainerProps);
|
||||
qmlRegisterSingletonInstance("ContainerProps", 1, 0, "ContainerProps", containerProps.get());
|
||||
|
||||
|
@ -140,29 +145,41 @@ int main(int argc, char *argv[])
|
|||
qmlRegisterSingletonInstance("ProtocolProps", 1, 0, "ProtocolProps", protocolProps.get());
|
||||
|
||||
const QUrl url(QStringLiteral("qrc:/ui/qml/main.qml"));
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
|
||||
QObject::connect(engine, &QQmlApplicationEngine::objectCreated,
|
||||
&app, [url](QObject *obj, const QUrl &objUrl) {
|
||||
if (!obj && url == objUrl)
|
||||
QCoreApplication::exit(-1);
|
||||
}, Qt::QueuedConnection);
|
||||
|
||||
engine.rootContext()->setContextProperty("UiLogic", uiLogic);
|
||||
engine->rootContext()->setContextProperty("UiLogic", uiLogic);
|
||||
|
||||
engine.rootContext()->setContextProperty("AppSettingsLogic", uiLogic->appSettingsLogic());
|
||||
engine.rootContext()->setContextProperty("GeneralSettingsLogic", uiLogic->generalSettingsLogic());
|
||||
engine.rootContext()->setContextProperty("NetworkSettingsLogic", uiLogic->networkSettingsLogic());
|
||||
engine.rootContext()->setContextProperty("ServerConfiguringProgressLogic", uiLogic->serverConfiguringProgressLogic());
|
||||
engine.rootContext()->setContextProperty("NewServerProtocolsLogic", uiLogic->newServerProtocolsLogic());
|
||||
engine.rootContext()->setContextProperty("ServerListLogic", uiLogic->serverListLogic());
|
||||
engine.rootContext()->setContextProperty("ServerSettingsLogic", uiLogic->serverSettingsLogic());
|
||||
engine.rootContext()->setContextProperty("ServerContainersLogic", uiLogic->serverVpnProtocolsLogic());
|
||||
engine.rootContext()->setContextProperty("ShareConnectionLogic", uiLogic->shareConnectionLogic());
|
||||
engine.rootContext()->setContextProperty("SitesLogic", uiLogic->sitesLogic());
|
||||
engine.rootContext()->setContextProperty("StartPageLogic", uiLogic->startPageLogic());
|
||||
engine.rootContext()->setContextProperty("VpnLogic", uiLogic->vpnLogic());
|
||||
engine.rootContext()->setContextProperty("WizardLogic", uiLogic->wizardLogic());
|
||||
engine->rootContext()->setContextProperty("AppSettingsLogic", uiLogic->appSettingsLogic());
|
||||
engine->rootContext()->setContextProperty("GeneralSettingsLogic", uiLogic->generalSettingsLogic());
|
||||
engine->rootContext()->setContextProperty("NetworkSettingsLogic", uiLogic->networkSettingsLogic());
|
||||
engine->rootContext()->setContextProperty("ServerConfiguringProgressLogic", uiLogic->serverConfiguringProgressLogic());
|
||||
engine->rootContext()->setContextProperty("NewServerProtocolsLogic", uiLogic->newServerProtocolsLogic());
|
||||
engine->rootContext()->setContextProperty("ServerListLogic", uiLogic->serverListLogic());
|
||||
engine->rootContext()->setContextProperty("ServerSettingsLogic", uiLogic->serverSettingsLogic());
|
||||
engine->rootContext()->setContextProperty("ServerContainersLogic", uiLogic->serverVpnProtocolsLogic());
|
||||
engine->rootContext()->setContextProperty("ShareConnectionLogic", uiLogic->shareConnectionLogic());
|
||||
engine->rootContext()->setContextProperty("SitesLogic", uiLogic->sitesLogic());
|
||||
engine->rootContext()->setContextProperty("StartPageLogic", uiLogic->startPageLogic());
|
||||
engine->rootContext()->setContextProperty("VpnLogic", uiLogic->vpnLogic());
|
||||
engine->rootContext()->setContextProperty("WizardLogic", uiLogic->wizardLogic());
|
||||
|
||||
engine.load(url);
|
||||
engine->load(url);
|
||||
|
||||
QObject::connect(&app, &QCoreApplication::aboutToQuit, uiLogic, [&engine, uiLogic](){
|
||||
QObject::disconnect(engine, 0,0,0);
|
||||
delete engine;
|
||||
|
||||
QObject::disconnect(uiLogic, 0,0,0);
|
||||
delete uiLogic;
|
||||
});
|
||||
|
||||
if (engine->rootObjects().size() > 0) {
|
||||
uiLogic->setQmlRoot(engine->rootObjects().at(0));
|
||||
}
|
||||
|
||||
// TODO - fix
|
||||
//#ifdef Q_OS_WIN
|
||||
|
|
|
@ -1,18 +1,29 @@
|
|||
#include <QCoreApplication>
|
||||
#include <QFileInfo>
|
||||
#include <QProcess>
|
||||
#include <QRegularExpression>
|
||||
#include <QTcpSocket>
|
||||
//#include <QRegularExpression>
|
||||
//#include <QTcpSocket>
|
||||
#include <QThread>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "debug.h"
|
||||
#include "ikev2_vpn_protocol.h"
|
||||
#include "utils.h"
|
||||
|
||||
static Ikev2Protocol* self = nullptr;
|
||||
static std::mutex rasDialFuncMutex;
|
||||
|
||||
extern "C" {
|
||||
static void WINAPI RasDialFuncCallback(UINT unMsg,
|
||||
RASCONNSTATE rasconnstate,
|
||||
DWORD dwError );
|
||||
}
|
||||
|
||||
Ikev2Protocol::Ikev2Protocol(const QJsonObject &configuration, QObject* parent) :
|
||||
VpnProtocol(configuration, parent)
|
||||
{
|
||||
self = this;
|
||||
//m_configFile.setFileTemplate(QDir::tempPath() + QDir::separator() + serviceName() + ".conf");
|
||||
readIkev2Configuration(configuration);
|
||||
}
|
||||
|
@ -20,34 +31,214 @@ Ikev2Protocol::Ikev2Protocol(const QJsonObject &configuration, QObject* parent)
|
|||
Ikev2Protocol::~Ikev2Protocol()
|
||||
{
|
||||
qDebug() << "IpsecProtocol::~IpsecProtocol()";
|
||||
#ifdef Q_OS_WIN
|
||||
disconnect_vpn();
|
||||
#endif
|
||||
Ikev2Protocol::stop();
|
||||
QThread::msleep(200);
|
||||
}
|
||||
|
||||
void Ikev2Protocol::stop()
|
||||
{
|
||||
setConnectionState(VpnProtocol::Disconnecting);
|
||||
#ifdef Q_OS_WINDOWS
|
||||
{
|
||||
setConnectionState(Disconnecting);
|
||||
|
||||
auto disconnectProcess = new QProcess;
|
||||
|
||||
disconnectProcess->setProgram("rasdial");
|
||||
QString arguments = QString("\"%1\" /disconnect")
|
||||
.arg(tunnelName());
|
||||
disconnectProcess->setNativeArguments(arguments);
|
||||
|
||||
// connect(connectProcess, &QProcess::readyRead, [connectProcess]() {
|
||||
// qDebug().noquote() << "connectProcess readyRead" << connectProcess->readAll();
|
||||
// });
|
||||
|
||||
disconnectProcess->start();
|
||||
disconnectProcess->waitForFinished(5000);
|
||||
setConnectionState(Disconnected);
|
||||
if (! disconnect_vpn() ){
|
||||
qDebug()<<"We don't disconnect";
|
||||
setConnectionState(VpnProtocol::Error);
|
||||
}
|
||||
else {
|
||||
setConnectionState(VpnProtocol::Disconnected);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Ikev2Protocol::newConnectionStateEventReceived(UINT unMsg, tagRASCONNSTATE rasconnstate, DWORD dwError)
|
||||
{
|
||||
Q_UNUSED(unMsg);
|
||||
qDebug()<<"Recive the new event "<<static_cast<int>(rasconnstate);
|
||||
switch (rasconnstate)
|
||||
{
|
||||
case RASCS_OpenPort:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
setConnectionState(Preparing);
|
||||
//printf ("RASCS_OpenPort = %d\n", _connection_state);
|
||||
//printf ("Opening port...\n");
|
||||
break;
|
||||
case RASCS_PortOpened:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
setConnectionState(Preparing);
|
||||
//printf ("RASCS_PortOpened = %d\n", _connection_state);
|
||||
//printf ("Port opened.\n");
|
||||
break;
|
||||
case RASCS_ConnectDevice:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
setConnectionState(Preparing);
|
||||
//printf ("RASCS_ConnectDevice = %d\n", _connection_state);
|
||||
//printf ("Connecting device...\n");
|
||||
break;
|
||||
case RASCS_DeviceConnected:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
setConnectionState(Preparing);
|
||||
//printf ("RASCS_DeviceConnected = %d\n", _connection_state);
|
||||
//printf ("Device connected.\n");
|
||||
break;
|
||||
case RASCS_AllDevicesConnected:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
setConnectionState(Preparing);
|
||||
//printf ("RASCS_AllDevicesConnected = %d\n", _connection_state);
|
||||
//printf ("All devices connected.\n");
|
||||
break;
|
||||
case RASCS_Authenticate:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
setConnectionState(Preparing);
|
||||
//printf ("RASCS_Authenticate = %d\n", _connection_state);
|
||||
// printf ("Authenticating...\n");
|
||||
break;
|
||||
case RASCS_AuthNotify:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
if (dwError != 0) {
|
||||
qDebug() << "have error" << dwError;
|
||||
setConnectionState(Disconnected);
|
||||
} else {
|
||||
qDebug() << "RASCS_AuthNotify but no error" << dwError;
|
||||
}
|
||||
//printf ("RASCS_AuthNotify = %d\n", _connection_state);
|
||||
// printf ("Authentication notify.\n");
|
||||
break;
|
||||
case RASCS_AuthRetry:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
setConnectionState(Preparing);
|
||||
//printf ("RASCS_AuthRetry = %d\n", _connection_state);
|
||||
//printf ("Retrying authentication...\n");
|
||||
break;
|
||||
case RASCS_AuthCallback:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_AuthCallback = %d\n", _connection_state);
|
||||
//printf ("Authentication callback...\n");
|
||||
break;
|
||||
case RASCS_AuthChangePassword:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
// printf ("RASCS_AuthChangePassword = %d\n", _connection_state);
|
||||
//printf ("Change password...\n");
|
||||
break;
|
||||
case RASCS_AuthProject:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_AuthProject = %d\n", _connection_state);
|
||||
//printf ("Projection phase started...\n");
|
||||
break;
|
||||
case RASCS_AuthLinkSpeed:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_AuthLinkSpeed = %d\n", _connection_state);
|
||||
//printf ("Negoting speed...\n");
|
||||
break;
|
||||
case RASCS_AuthAck:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_AuthAck = %d\n", _connection_state);
|
||||
//printf ("Authentication acknowledge...\n");
|
||||
break;
|
||||
case RASCS_ReAuthenticate:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_ReAuthenticate = %d\n", _connection_state);
|
||||
//printf ("Retrying Authentication...\n");
|
||||
break;
|
||||
case RASCS_Authenticated:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_Authenticated = %d\n", _connection_state);
|
||||
//printf ("Authentication complete.\n");
|
||||
break;
|
||||
case RASCS_PrepareForCallback:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_PrepareForCallback = %d\n", _connection_state);
|
||||
//printf ("Preparing for callback...\n");
|
||||
break;
|
||||
case RASCS_WaitForModemReset:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_WaitForModemReset = %d\n", _connection_state);
|
||||
// printf ("Waiting for modem reset...\n");
|
||||
break;
|
||||
case RASCS_WaitForCallback:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_WaitForCallback = %d\n", _connection_state);
|
||||
//printf ("Waiting for callback...\n");
|
||||
break;
|
||||
case RASCS_Projected:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_Projected = %d\n", _connection_state);
|
||||
//printf ("Projection completed.\n");
|
||||
break;
|
||||
#if (WINVER >= 0x400)
|
||||
case RASCS_StartAuthentication: // Windows 95 only
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_StartAuthentication = %d\n", _connection_state);
|
||||
//printf ("Starting authentication...\n");
|
||||
|
||||
break;
|
||||
case RASCS_CallbackComplete: // Windows 95 only
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_CallbackComplete = %d\n", rasconnstate);
|
||||
//printf ("Callback complete.\n");
|
||||
break;
|
||||
case RASCS_LogonNetwork: // Windows 95 only
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_LogonNetwork = %d\n", _connection_state);
|
||||
//printf ("Login to the network.\n");
|
||||
break;
|
||||
#endif
|
||||
case RASCS_SubEntryConnected:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_SubEntryConnected = %d\n", _connection_state);
|
||||
//printf ("Subentry connected.\n");
|
||||
break;
|
||||
case RASCS_SubEntryDisconnected:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_SubEntryDisconnected = %d\n", _connection_state);
|
||||
//printf ("Subentry disconnected.\n");
|
||||
break;
|
||||
//PAUSED STATES:
|
||||
case RASCS_Interactive:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_Interactive = %d\n", _connection_state);
|
||||
//printf ("In Paused state: Interactive mode.\n");
|
||||
break;
|
||||
case RASCS_RetryAuthentication:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_RetryAuthentication = %d\n", _connection_state);
|
||||
//printf ("In Paused state: Retry Authentication...\n");
|
||||
break;
|
||||
case RASCS_CallbackSetByCaller:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_CallbackSetByCaller = %d\n", _connection_state);
|
||||
//printf ("In Paused state: Callback set by Caller.\n");
|
||||
break;
|
||||
case RASCS_PasswordExpired:
|
||||
setConnectionState(Error);
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_PasswordExpired = %d\n", _connection_state);
|
||||
//printf ("In Paused state: Password has expired...\n");
|
||||
break;
|
||||
|
||||
case RASCS_Connected: // = RASCS_DONE:
|
||||
setConnectionState(Connected);
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_Connected = %d\n", _connection_state);
|
||||
//printf ("Connection completed.\n");
|
||||
//SetEvent(gEvent_handle);
|
||||
break;
|
||||
case RASCS_Disconnected:
|
||||
setConnectionState(Disconnected);
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("RASCS_Disconnected = %d\n", _connection_state);
|
||||
//printf ("Disconnecting...\n");
|
||||
break;
|
||||
default:
|
||||
qDebug()<<__FUNCTION__ << __LINE__;
|
||||
//printf ("Unknown Status = %d\n", _connection_state);
|
||||
//printf ("What are you going to do about it?\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Ikev2Protocol::readIkev2Configuration(const QJsonObject &configuration)
|
||||
{
|
||||
m_config = configuration.value(ProtocolProps::key_proto_config_data(Protocol::Ikev2)).toObject();
|
||||
|
@ -57,7 +248,7 @@ ErrorCode Ikev2Protocol::start()
|
|||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
QByteArray cert = QByteArray::fromBase64(m_config[config_key::cert].toString().toUtf8());
|
||||
setConnectionState(ConnectionState::Connecting);
|
||||
setConnectionState(Connecting);
|
||||
|
||||
QTemporaryFile certFile;
|
||||
certFile.setAutoRemove(false);
|
||||
|
@ -65,7 +256,6 @@ ErrorCode Ikev2Protocol::start()
|
|||
certFile.write(cert);
|
||||
certFile.close();
|
||||
|
||||
|
||||
{
|
||||
auto certInstallProcess = IpcClient::CreatePrivilegedProcess();
|
||||
|
||||
|
@ -87,64 +277,71 @@ ErrorCode Ikev2Protocol::start()
|
|||
});
|
||||
certInstallProcess->setArguments(arguments);
|
||||
|
||||
// qDebug() << arguments.join(" ");
|
||||
// connect(certInstallProcess.data(), &IpcProcessInterfaceReplica::errorOccurred, [certInstallProcess](QProcess::ProcessError error) {
|
||||
// qDebug() << "IpcProcessInterfaceReplica errorOccurred" << error;
|
||||
// });
|
||||
// qDebug() << arguments.join(" ");
|
||||
// connect(certInstallProcess.data(), &IpcProcessInterfaceReplica::errorOccurred, [certInstallProcess](QProcess::ProcessError error) {
|
||||
// qDebug() << "IpcProcessInterfaceReplica errorOccurred" << error;
|
||||
// });
|
||||
|
||||
// connect(certInstallProcess.data(), &IpcProcessInterfaceReplica::stateChanged, [certInstallProcess](QProcess::ProcessState newState) {
|
||||
// qDebug() << "IpcProcessInterfaceReplica stateChanged" << newState;
|
||||
// });
|
||||
// connect(certInstallProcess.data(), &IpcProcessInterfaceReplica::stateChanged, [certInstallProcess](QProcess::ProcessState newState) {
|
||||
// qDebug() << "IpcProcessInterfaceReplica stateChanged" << newState;
|
||||
// });
|
||||
|
||||
// connect(certInstallProcess.data(), &IpcProcessInterfaceReplica::readyRead, [certInstallProcess]() {
|
||||
// auto req = certInstallProcess->readAll();
|
||||
// req.waitForFinished();
|
||||
// qDebug() << "IpcProcessInterfaceReplica readyRead" << req.returnValue();
|
||||
// });
|
||||
// connect(certInstallProcess.data(), &IpcProcessInterfaceReplica::readyRead, [certInstallProcess]() {
|
||||
// auto req = certInstallProcess->readAll();
|
||||
// req.waitForFinished();
|
||||
// qDebug() << "IpcProcessInterfaceReplica readyRead" << req.returnValue();
|
||||
// });
|
||||
|
||||
|
||||
certInstallProcess->start();
|
||||
}
|
||||
|
||||
// /*
|
||||
{
|
||||
auto adapterRemoveProcess = new QProcess;
|
||||
// auto adapterRemoveProcess = new QProcess;
|
||||
|
||||
adapterRemoveProcess->setProgram("powershell");
|
||||
QString arguments = QString("-command \"Remove-VpnConnection -Name '%1' -Force\"").arg(tunnelName());
|
||||
adapterRemoveProcess->setNativeArguments(arguments);
|
||||
// adapterRemoveProcess->setProgram("powershell");
|
||||
// QString arguments = QString("-command \"Remove-VpnConnection -Name '%1' -Force\"").arg(tunnelName());
|
||||
// adapterRemoveProcess->setNativeArguments(arguments);
|
||||
|
||||
adapterRemoveProcess->start();
|
||||
adapterRemoveProcess->waitForFinished(5000);
|
||||
// adapterRemoveProcess->start();
|
||||
// adapterRemoveProcess->waitForFinished(5000);
|
||||
if ( disconnect_vpn()){
|
||||
qDebug()<<"VPN was disconnected";
|
||||
}
|
||||
if ( delete_vpn_connection (tunnelName())){
|
||||
qDebug()<<"VPN was deleted";
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto adapterInstallProcess = new QProcess;
|
||||
{
|
||||
if ( !create_new_vpn(tunnelName(), m_config[config_key::hostName].toString())){
|
||||
qDebug() <<"Can't create the VPN connect";
|
||||
}
|
||||
}
|
||||
// auto adapterInstallProcess = new QProcess;
|
||||
|
||||
adapterInstallProcess->setProgram("powershell");
|
||||
QString arguments = QString("-command \"Add-VpnConnection "
|
||||
"-ServerAddress '%1' "
|
||||
"-Name '%2' "
|
||||
"-TunnelType IKEv2 "
|
||||
"-AuthenticationMethod MachineCertificate "
|
||||
"-EncryptionLevel Required "
|
||||
"-PassThru\"")
|
||||
.arg(m_config[config_key::hostName].toString())
|
||||
.arg(tunnelName());
|
||||
adapterInstallProcess->setNativeArguments(arguments);
|
||||
// connect(adapterInstallProcess, &QProcess::readyRead, [adapterInstallProcess]() {
|
||||
// qDebug().noquote() << "adapterInstallProcess readyRead" << adapterInstallProcess->readAll();
|
||||
// });
|
||||
|
||||
adapterInstallProcess->start();
|
||||
adapterInstallProcess->waitForFinished(5000);
|
||||
// adapterInstallProcess->setProgram("powershell");
|
||||
// QString arguments = QString("-command \"Add-VpnConnection "
|
||||
// "-ServerAddress '%1' "
|
||||
// "-Name '%2' "
|
||||
// "-TunnelType IKEv2 "
|
||||
// "-AuthenticationMethod MachineCertificate "
|
||||
// "-EncryptionLevel Required "
|
||||
// "-PassThru\"")
|
||||
// .arg(m_config[config_key::hostName].toString())
|
||||
// .arg(tunnelName());
|
||||
// adapterInstallProcess->setNativeArguments(arguments);
|
||||
// adapterInstallProcess->start();
|
||||
// adapterInstallProcess->waitForFinished(5000);
|
||||
}
|
||||
|
||||
{
|
||||
auto adapterConfigProcess = new QProcess;
|
||||
|
||||
adapterConfigProcess->setProgram("powershell");
|
||||
QString arguments = QString("-command \"Set-VpnConnectionIPsecConfiguration\ "
|
||||
"-ConnectionName '%1'\ "
|
||||
QString arguments = QString("-command \"Set-VpnConnectionIPsecConfiguration\" "
|
||||
"-ConnectionName '%1' "
|
||||
"-AuthenticationTransformConstants GCMAES128 "
|
||||
"-CipherTransformConstants GCMAES128 "
|
||||
"-EncryptionMethod AES256 "
|
||||
|
@ -152,67 +349,98 @@ ErrorCode Ikev2Protocol::start()
|
|||
"-PfsGroup None "
|
||||
"-DHGroup Group14 "
|
||||
"-PassThru -Force\"")
|
||||
.arg(tunnelName());
|
||||
.arg(tunnelName());
|
||||
adapterConfigProcess->setNativeArguments(arguments);
|
||||
|
||||
// connect(adapterConfigProcess, &QProcess::readyRead, [adapterConfigProcess]() {
|
||||
// qDebug().noquote() << "adapterConfigProcess readyRead" << adapterConfigProcess->readAll();
|
||||
// });
|
||||
// connect(adapterConfigProcess, &QProcess::readyRead, [adapterConfigProcess]() {
|
||||
// qDebug().noquote() << "adapterConfigProcess readyRead" << adapterConfigProcess->readAll();
|
||||
// });
|
||||
|
||||
adapterConfigProcess->start();
|
||||
adapterConfigProcess->waitForFinished(5000);
|
||||
}
|
||||
|
||||
//*/
|
||||
{
|
||||
// char buf[RASBUFFER]= {0};
|
||||
// DWORD err = 0;
|
||||
// RASDIALPARAMSA *param = (RASDIALPARAMSA *)buf;
|
||||
// param->dwSize = 1064;
|
||||
// strcpy(param->szEntryName, tunnelName().toStdString().c_str());
|
||||
// err = RasDialA(NULL, NULL, param, 0, (LPVOID)rasCallback, &g_h);
|
||||
// qDebug() << "Ikev2Protocol::start() ret" << err;
|
||||
|
||||
|
||||
auto connectProcess = new QProcess;
|
||||
|
||||
connectProcess->setProgram("rasdial");
|
||||
QString arguments = QString("\"%1\"")
|
||||
.arg(tunnelName());
|
||||
connectProcess->setNativeArguments(arguments);
|
||||
|
||||
connect(connectProcess, &QProcess::readyRead, [connectProcess]() {
|
||||
qDebug().noquote() << "connectProcess readyRead" << connectProcess->readAll();
|
||||
});
|
||||
|
||||
connectProcess->start();
|
||||
connectProcess->waitForFinished(5000);
|
||||
}
|
||||
|
||||
setConnectionState(Connected);
|
||||
return ErrorCode::NoError;
|
||||
|
||||
#endif
|
||||
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
DWORD CALLBACK rasCallback(UINT msg, RASCONNSTATE rascs, DWORD err)
|
||||
{
|
||||
if(err != 0) {
|
||||
printf("Error: %d\n", err);
|
||||
fflush(stdout);
|
||||
//g_done = 1;
|
||||
return 0; // stop the connection.
|
||||
} else {
|
||||
//printf("%s\n", rasState(rascs));
|
||||
fflush(stdout);
|
||||
if(rascs == RASCS_Connected) {
|
||||
printf("Success: Connected\n");
|
||||
fflush(stdout);
|
||||
//g_done = 1;
|
||||
if (!connect_to_vpn(tunnelName())) {
|
||||
qDebug()<<"We can't connect to VPN";
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
//setConnectionState(Connecting);
|
||||
return ErrorCode::NoError;
|
||||
#else
|
||||
return ErrorCode::NoError;
|
||||
#endif
|
||||
|
||||
}
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
#ifdef Q_OS_WINDOWS
|
||||
bool Ikev2Protocol::create_new_vpn(const QString & vpn_name,
|
||||
const QString & serv_addr){
|
||||
|
||||
if ( RasValidateEntryName(nullptr, vpn_name.toStdWString().c_str()) != ERROR_SUCCESS)
|
||||
return false;
|
||||
DWORD size = 0;
|
||||
::RasGetEntryProperties(nullptr, L"", nullptr, &size, nullptr, nullptr);
|
||||
LPRASENTRY pras = static_cast<LPRASENTRY>(malloc(size));
|
||||
memset(pras, 0, size);
|
||||
pras->dwSize = size;
|
||||
pras->dwType = RASET_Vpn;
|
||||
pras->dwRedialCount = 1;
|
||||
pras->dwRedialPause = 60;
|
||||
pras->dwfNetProtocols = RASNP_Ip|RASNP_Ipv6;
|
||||
pras->dwEncryptionType = ET_RequireMax;
|
||||
wcscpy_s(pras->szLocalPhoneNumber, serv_addr.toStdWString().c_str());
|
||||
wcscpy_s(pras->szDeviceType, RASDT_Vpn);
|
||||
pras->dwfOptions = RASEO_RemoteDefaultGateway;
|
||||
pras->dwfOptions |= RASEO_RequireDataEncryption;
|
||||
pras->dwfOptions2 |= RASEO2_RequireMachineCertificates;
|
||||
pras->dwVpnStrategy = VS_Ikev2Only;
|
||||
const auto nRet = ::RasSetEntryProperties(nullptr, vpn_name.toStdWString().c_str(), pras, pras->dwSize, NULL, 0);
|
||||
free(pras);
|
||||
if (nRet == ERROR_SUCCESS)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
bool Ikev2Protocol::delete_vpn_connection(const QString &vpn_name){
|
||||
|
||||
if ( RasDeleteEntry(nullptr, vpn_name.toStdWString().c_str()) == ERROR_SUCCESS){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
bool Ikev2Protocol::connect_to_vpn(const QString & vpn_name){
|
||||
RASDIALPARAMS RasDialParams;
|
||||
memset(&RasDialParams, 0x0, sizeof(RASDIALPARAMS));
|
||||
RasDialParams.dwSize = sizeof(RASDIALPARAMS);
|
||||
wcscpy_s(RasDialParams.szEntryName, vpn_name.toStdWString().c_str());
|
||||
auto ret = RasDial(NULL, NULL, &RasDialParams, 0,
|
||||
&RasDialFuncCallback,
|
||||
&hRasConn);
|
||||
if (ret == ERROR_SUCCESS){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
bool Ikev2Protocol::disconnect_vpn(){
|
||||
if ( hRasConn != nullptr ){
|
||||
if ( RasHangUp(hRasConn) != ERROR_SUCCESS)
|
||||
return false;
|
||||
}
|
||||
QThread::msleep(3000);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WINAPI RasDialFuncCallback(UINT unMsg,
|
||||
RASCONNSTATE rasconnstate,
|
||||
DWORD dwError ){
|
||||
std::lock_guard<std::mutex> guard(rasDialFuncMutex);
|
||||
if (self) {
|
||||
self->newConnectionStateEventReceived(unMsg, rasconnstate, dwError);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,20 +11,26 @@
|
|||
#include "core/ipcclient.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <ras.h>
|
||||
#include <Ras.h>
|
||||
#include <raserror.h>
|
||||
#include <shlwapi.h>
|
||||
|
||||
#include <wincrypt.h>
|
||||
|
||||
#pragma comment(lib, "shlwapi.lib")
|
||||
#pragma comment(lib, "rasapi32.lib")
|
||||
#pragma comment(lib, "Crypt32.lib")
|
||||
|
||||
#define RASBUFFER 0x1000
|
||||
#define RASMAXENUM 0x100
|
||||
#endif
|
||||
|
||||
class Ikev2Protocol : public VpnProtocol
|
||||
|
@ -40,17 +46,32 @@ public:
|
|||
|
||||
static QString tunnelName() { return "AmneziaVPN IKEv2"; }
|
||||
|
||||
public:
|
||||
void newConnectionStateEventReceived(UINT unMsg,
|
||||
RASCONNSTATE rasconnstate,
|
||||
DWORD dwError);
|
||||
|
||||
private:
|
||||
void readIkev2Configuration(const QJsonObject &configuration);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
//certificates variables
|
||||
|
||||
#endif
|
||||
private:
|
||||
QJsonObject m_config;
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
HRASCONN g_h;
|
||||
int g_done = 0;
|
||||
//RAS functions and parametrs
|
||||
HRASCONN hRasConn{nullptr};
|
||||
bool create_new_vpn(const QString & vpn_name,
|
||||
const QString & serv_addr);
|
||||
bool delete_vpn_connection(const QString &vpn_name);
|
||||
|
||||
bool connect_to_vpn(const QString & vpn_name);
|
||||
bool disconnect_vpn();
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
|
|
@ -73,6 +73,9 @@ QMap<amnezia::Protocol, QString> ProtocolProps::protocolHumanNames()
|
|||
{Protocol::ShadowSocks, "ShadowSocks"},
|
||||
{Protocol::Cloak, "Cloak"},
|
||||
{Protocol::WireGuard, "WireGuard"},
|
||||
{Protocol::Ikev2, "IKEv2"},
|
||||
{Protocol::L2tp, "L2TP"},
|
||||
|
||||
{Protocol::TorWebSite, "Web site in TOR network"},
|
||||
{Protocol::Dns, "DNS Service"},
|
||||
{Protocol::FileShare, "File Sharing Service"},
|
||||
|
|
|
@ -51,7 +51,7 @@ void WireguardProtocol::stop()
|
|||
m_wireguardStopProcess->setProgram(wireguardExecPath());
|
||||
|
||||
|
||||
QStringList arguments({"/uninstalltunnelservice", serviceName(), });
|
||||
QStringList arguments({"--remove", configPath()});
|
||||
m_wireguardStopProcess->setArguments(arguments);
|
||||
|
||||
qDebug() << arguments.join(" ");
|
||||
|
@ -114,7 +114,7 @@ void WireguardProtocol::updateRouteGateway(QString line)
|
|||
QString WireguardProtocol::wireguardExecPath() const
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
return Utils::executable("wireguard/wireguard", true);
|
||||
return Utils::executable("wireguard/wireguard-service", true);
|
||||
#elif defined Q_OS_LINUX
|
||||
return Utils::usrExecutable("wg");
|
||||
#else
|
||||
|
@ -163,7 +163,7 @@ ErrorCode WireguardProtocol::start()
|
|||
m_wireguardStartProcess->setProgram(wireguardExecPath());
|
||||
|
||||
|
||||
QStringList arguments({"/installtunnelservice", configPath(), });
|
||||
QStringList arguments({"--add", configPath()});
|
||||
m_wireguardStartProcess->setArguments(arguments);
|
||||
|
||||
qDebug() << arguments.join(" ");
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
<file>images/tray/default.png</file>
|
||||
<file>images/tray/error.png</file>
|
||||
<file>images/arrow_left.png</file>
|
||||
<file>images/connect_button_connected.png</file>
|
||||
<file>images/connect_button_disconnected.png</file>
|
||||
<file>fonts/Lato-Black.ttf</file>
|
||||
<file>fonts/Lato-BlackItalic.ttf</file>
|
||||
<file>fonts/Lato-Bold.ttf</file>
|
||||
|
@ -126,5 +124,22 @@
|
|||
<file>server_scripts/ipsec/Dockerfile</file>
|
||||
<file>server_scripts/ipsec/run_container.sh</file>
|
||||
<file>server_scripts/ipsec/start.sh</file>
|
||||
<file>ui/qml/Pages/Share/PageShareProtoCloak.qml</file>
|
||||
<file>ui/qml/Pages/Share/PageShareProtocolBase.qml</file>
|
||||
<file>ui/qml/Pages/Share/PageShareProtoOpenVPN.qml</file>
|
||||
<file>ui/qml/Pages/Share/PageShareProtoSftp.qml</file>
|
||||
<file>ui/qml/Pages/Share/PageShareProtoShadowSocks.qml</file>
|
||||
<file>ui/qml/Pages/Share/PageShareProtoTorWebSite.qml</file>
|
||||
<file>ui/qml/Controls/TextAreaType.qml</file>
|
||||
<file>ui/qml/Controls/ContextMenu.qml</file>
|
||||
<file>ui/qml/Pages/Share/PageShareProtoAmnezia.qml</file>
|
||||
<file>ui/qml/Controls/ShareConnectionButtonCopyType.qml</file>
|
||||
<file>ui/qml/Pages/Share/PageShareProtoWireGuard.qml</file>
|
||||
<file>server_scripts/ipsec/mobileconfig.plist</file>
|
||||
<file>ui/qml/Pages/Share/PageShareProtoIkev2.qml</file>
|
||||
<file>server_scripts/ipsec/strongswan.profile</file>
|
||||
<file>images/animation.gif</file>
|
||||
<file>images/connected.png</file>
|
||||
<file>images/disconnected.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -1 +1 @@
|
|||
sudo docker build -t $CONTAINER_NAME $DOCKERFILE_FOLDER
|
||||
sudo docker build -t $CONTAINER_NAME $DOCKERFILE_FOLDER --build-arg SERVER_ARCH=$(uname -m)
|
||||
|
|
|
@ -120,8 +120,8 @@ proxyarp
|
|||
lcp-echo-failure 4
|
||||
lcp-echo-interval 30
|
||||
connect-delay 5000
|
||||
ms-dns $PRIMARY_DNS
|
||||
ms-dns $SECONDARY_DNS
|
||||
ms-dns $PRIMARY_SERVER_DNS
|
||||
ms-dns $SECONDARY_SERVER_DNS
|
||||
EOF
|
||||
|
||||
|
||||
|
@ -222,6 +222,8 @@ certutil -z <(head -c 1024 /dev/urandom) \
|
|||
--extKeyUsage serverAuth \
|
||||
--extSAN "ip:$SERVER_IP_ADDRESS,dns:$SERVER_IP_ADDRESS"
|
||||
|
||||
certutil -L -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" -a | grep -v CERTIFICATE > /etc/ipsec.d/ca_cert_base64.p12
|
||||
|
||||
cat > /etc/ipsec.d/ikev2.conf <<EOF
|
||||
conn ikev2-cp
|
||||
left=%defaultroute
|
||||
|
@ -248,7 +250,7 @@ conn ikev2-cp
|
|||
ikelifetime=24h
|
||||
salifetime=24h
|
||||
encapsulation=yes
|
||||
modecfgdns=$PRIMARY_DNS,$SECONDARY_DNS
|
||||
modecfgdns=$PRIMARY_SERVER_DNS,$SECONDARY_SERVER_DNS
|
||||
EOF
|
||||
|
||||
ipsec auto --add ikev2-cp
|
||||
|
|
145
client/server_scripts/ipsec/mobileconfig.plist
Normal file
145
client/server_scripts/ipsec/mobileconfig.plist
Normal file
|
@ -0,0 +1,145 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PayloadContent</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IKEv2</key>
|
||||
<dict>
|
||||
<key>AuthenticationMethod</key>
|
||||
<string>Certificate</string>
|
||||
<key>ChildSecurityAssociationParameters</key>
|
||||
<dict>
|
||||
<key>DiffieHellmanGroup</key>
|
||||
<integer>14</integer>
|
||||
<key>EncryptionAlgorithm</key>
|
||||
<string>AES-128-GCM</string>
|
||||
<key>LifeTimeInMinutes</key>
|
||||
<integer>1410</integer>
|
||||
</dict>
|
||||
<key>DeadPeerDetectionRate</key>
|
||||
<string>Medium</string>
|
||||
<key>DisableRedirect</key>
|
||||
<true/>
|
||||
<key>EnableCertificateRevocationCheck</key>
|
||||
<integer>0</integer>
|
||||
<key>EnablePFS</key>
|
||||
<integer>0</integer>
|
||||
<key>IKESecurityAssociationParameters</key>
|
||||
<dict>
|
||||
<key>DiffieHellmanGroup</key>
|
||||
<integer>14</integer>
|
||||
<key>EncryptionAlgorithm</key>
|
||||
<string>AES-256</string>
|
||||
<key>IntegrityAlgorithm</key>
|
||||
<string>SHA2-256</string>
|
||||
<key>LifeTimeInMinutes</key>
|
||||
<integer>1410</integer>
|
||||
</dict>
|
||||
<key>LocalIdentifier</key>
|
||||
<string>$CLIENT_NAME</string>
|
||||
<key>PayloadCertificateUUID</key>
|
||||
<string>$UUID1</string>
|
||||
<key>OnDemandEnabled</key>
|
||||
<integer>0</integer>
|
||||
<key>OnDemandRules</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>Action</key>
|
||||
<string>Connect</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>RemoteAddress</key>
|
||||
<string>$SERVER_ADDR</string>
|
||||
<key>RemoteIdentifier</key>
|
||||
<string>$SERVER_ADDR</string>
|
||||
<key>UseConfigurationAttributeInternalIPSubnet</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>IPv4</key>
|
||||
<dict>
|
||||
<key>OverridePrimary</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<key>PayloadDescription</key>
|
||||
<string>Configures VPN settings</string>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>VPN</string>
|
||||
<key>PayloadOrganization</key>
|
||||
<string>IKEv2 VPN</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>com.apple.vpn.managed.$(UUID_GEN)</string>
|
||||
<key>PayloadType</key>
|
||||
<string>com.apple.vpn.managed</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>$(UUID_GEN)</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
<key>Proxies</key>
|
||||
<dict>
|
||||
<key>HTTPEnable</key>
|
||||
<integer>0</integer>
|
||||
<key>HTTPSEnable</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>UserDefinedName</key>
|
||||
<string>$SERVER_ADDR</string>
|
||||
<key>VPNType</key>
|
||||
<string>IKEv2</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>PayloadCertificateFileName</key>
|
||||
<string>$CLIENT_NAME</string>
|
||||
<key>PayloadContent</key>
|
||||
<data>
|
||||
$P12_BASE64
|
||||
</data>
|
||||
<key>PayloadDescription</key>
|
||||
<string>Adds a PKCS#12-formatted certificate</string>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>$CLIENT_NAME</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>com.apple.security.pkcs12.$(UUID_GEN)</string>
|
||||
<key>PayloadType</key>
|
||||
<string>com.apple.security.pkcs12</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>$UUID1</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>PayloadContent</key>
|
||||
<data>
|
||||
$CA_BASE64
|
||||
</data>
|
||||
<key>PayloadCertificateFileName</key>
|
||||
<string>ikev2vpnca</string>
|
||||
<key>PayloadDescription</key>
|
||||
<string>Adds a CA root certificate</string>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>Certificate Authority (CA)</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>com.apple.security.root.$(UUID_GEN)</string>
|
||||
<key>PayloadType</key>
|
||||
<string>com.apple.security.root</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>$(UUID_GEN)</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</array>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>IKEv2 VPN ($SERVER_ADDR)</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>com.apple.vpn.managed.$(UUID_GEN)</string>
|
||||
<key>PayloadRemovalDisallowed</key>
|
||||
<false/>
|
||||
<key>PayloadType</key>
|
||||
<string>Configuration</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>$(UUID_GEN)</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</plist>
|
14
client/server_scripts/ipsec/strongswan.profile
Normal file
14
client/server_scripts/ipsec/strongswan.profile
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"uuid": "$UUID",
|
||||
"name": "IKEv2 VPN ($SERVER_ADDR)",
|
||||
"type": "ikev2-cert",
|
||||
"remote": {
|
||||
"addr": "$SERVER_ADDR"
|
||||
},
|
||||
"local": {
|
||||
"p12": "$P12_BASE64",
|
||||
"rsa-pss": "true"
|
||||
},
|
||||
"ike-proposal": "aes256-sha256-modp2048",
|
||||
"esp-proposal": "aes128gcm16"
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
FROM alpine:latest
|
||||
|
||||
LABEL maintainer="AmneziaVPN"
|
||||
|
||||
ARG SS_RELEASE="v1.11.2"
|
||||
ARG SERVER_ARCH
|
||||
|
||||
#Install required packages
|
||||
RUN apk add --no-cache curl openvpn easy-rsa bash netcat-openbsd dumb-init rng-tools xz
|
||||
RUN apk --update upgrade --no-cache
|
||||
|
@ -13,9 +15,9 @@ RUN mkdir -p /opt/amnezia
|
|||
RUN echo -e "#!/bin/bash\ntail -f /dev/null" > /opt/amnezia/start.sh
|
||||
RUN chmod a+x /opt/amnezia/start.sh
|
||||
|
||||
RUN curl -L https://github.com/shadowsocks/shadowsocks-rust/releases/download/v1.10.9/shadowsocks-v1.10.9.x86_64-unknown-linux-musl.tar.xz > /usr/bin/ss.tar.xz
|
||||
RUN tar -Jxvf /usr/bin/ss.tar.xz -C /usr/bin/
|
||||
RUN chmod a+x /usr/bin/ssserver
|
||||
RUN curl -L https://github.com/shadowsocks/shadowsocks-rust/releases/download/${SS_RELEASE}/shadowsocks-${SS_RELEASE}.${SERVER_ARCH}-unknown-linux-musl.tar.xz > /usr/bin/ss.tar.xz;\
|
||||
tar -Jxvf /usr/bin/ss.tar.xz -C /usr/bin/;\
|
||||
chmod a+x /usr/bin/ssserver;
|
||||
|
||||
# Tune network
|
||||
RUN echo -e " \n\
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
# Run container
|
||||
sudo docker stop amnezia-tor
|
||||
sudo docker rm amnezia-tor
|
||||
sudo docker run -d -p 80:80 --restart always --name $CONTAINER_NAME tutum/wordpress
|
||||
sudo docker run -d --link $CONTAINER_NAME --name amnezia-tor goldy/tor-hidden-service
|
||||
sudo docker exec -i amnezia-tor apk add bash
|
||||
|
|
|
@ -24,7 +24,7 @@ QHash<int, QByteArray> ProtocolsModel::roleNames() const {
|
|||
QVariant ProtocolsModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() < 0
|
||||
|| index.row() >= ContainerProps::allContainers().size()) {
|
||||
|| index.row() >= ProtocolProps::allProtocols().size()) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,19 @@
|
|||
#include <QObject>
|
||||
#include <QQmlEngine>
|
||||
|
||||
class PageType : public QObject
|
||||
{
|
||||
Q_GADGET
|
||||
|
||||
public:
|
||||
enum Type {
|
||||
Basic,
|
||||
Proto,
|
||||
ShareProto
|
||||
};
|
||||
Q_ENUM(Type)
|
||||
};
|
||||
|
||||
namespace PageEnumNS
|
||||
{
|
||||
Q_NAMESPACE
|
||||
|
@ -11,7 +24,7 @@ enum class Page {Start = 0, NewServer, NewServerProtocols, Vpn,
|
|||
Wizard, WizardLow, WizardMedium, WizardHigh, WizardVpnMode, ServerConfiguringProgress,
|
||||
GeneralSettings, AppSettings, NetworkSettings, ServerSettings,
|
||||
ServerContainers, ServersList, ShareConnection, Sites,
|
||||
ProtocolSettings};
|
||||
ProtocolSettings, ProtocolShare};
|
||||
Q_ENUM_NS(Page)
|
||||
|
||||
static void declareQmlPageEnum() {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "ShareConnectionLogic.h"
|
||||
|
||||
#include "../uilogic.h"
|
||||
#include "../models/protocols_model.h"
|
||||
|
||||
GeneralSettingsLogic::GeneralSettingsLogic(UiLogic *logic, QObject *parent):
|
||||
PageLogicBase(logic, parent)
|
||||
|
@ -11,13 +12,18 @@ GeneralSettingsLogic::GeneralSettingsLogic(UiLogic *logic, QObject *parent):
|
|||
|
||||
void GeneralSettingsLogic::onUpdatePage()
|
||||
{
|
||||
uiLogic()->selectedServerIndex = m_settings.defaultServerIndex();
|
||||
uiLogic()->selectedDockerContainer = m_settings.defaultContainer(m_settings.defaultServerIndex());
|
||||
|
||||
set_pushButtonGeneralSettingsShareConnectionEnable(m_settings.haveAuthData(m_settings.defaultServerIndex()));
|
||||
}
|
||||
|
||||
void GeneralSettingsLogic::onPushButtonGeneralSettingsServerSettingsClicked()
|
||||
{
|
||||
uiLogic()->selectedServerIndex = m_settings.defaultServerIndex();
|
||||
uiLogic()->goToPage(Page::ServerSettings);
|
||||
uiLogic()->selectedDockerContainer = m_settings.defaultContainer(m_settings.defaultServerIndex());
|
||||
|
||||
emit uiLogic()->goToPage(Page::ServerSettings);
|
||||
}
|
||||
|
||||
void GeneralSettingsLogic::onPushButtonGeneralSettingsShareConnectionClicked()
|
||||
|
@ -25,6 +31,9 @@ void GeneralSettingsLogic::onPushButtonGeneralSettingsShareConnectionClicked()
|
|||
uiLogic()->selectedServerIndex = m_settings.defaultServerIndex();
|
||||
uiLogic()->selectedDockerContainer = m_settings.defaultContainer(uiLogic()->selectedServerIndex);
|
||||
|
||||
uiLogic()->shareConnectionLogic()->updateSharingPage(uiLogic()->selectedServerIndex, m_settings.serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer);
|
||||
uiLogic()->goToPage(Page::ShareConnection);
|
||||
qobject_cast<ProtocolsModel *>(uiLogic()->protocolsModel())->setSelectedServerIndex(uiLogic()->selectedServerIndex);
|
||||
qobject_cast<ProtocolsModel *>(uiLogic()->protocolsModel())->setSelectedDockerContainer(uiLogic()->selectedDockerContainer);
|
||||
|
||||
uiLogic()->shareConnectionLogic()->updateSharingPage(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer);
|
||||
emit uiLogic()->goToPage(Page::ShareConnection);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,11 @@ ServerConfiguringProgressLogic::ServerConfiguringProgressLogic(UiLogic *logic, Q
|
|||
|
||||
}
|
||||
|
||||
void ServerConfiguringProgressLogic::onUpdatePage()
|
||||
{
|
||||
set_progressBarValue(0);
|
||||
}
|
||||
|
||||
|
||||
ErrorCode ServerConfiguringProgressLogic::doInstallAction(const std::function<ErrorCode()> &action)
|
||||
{
|
||||
|
|
|
@ -22,6 +22,7 @@ public:
|
|||
explicit ServerConfiguringProgressLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
||||
~ServerConfiguringProgressLogic() = default;
|
||||
|
||||
void onUpdatePage() override;
|
||||
ErrorCode doInstallAction(const std::function<ErrorCode()> &action);
|
||||
|
||||
private:
|
||||
|
|
|
@ -43,12 +43,12 @@ void ServerContainersLogic::onPushButtonProtoSettingsClicked(DockerContainer c,
|
|||
void ServerContainersLogic::onPushButtonDefaultClicked(DockerContainer c)
|
||||
{
|
||||
m_settings.setDefaultContainer(uiLogic()->selectedServerIndex, c);
|
||||
onUpdatePage();
|
||||
uiLogic()->onUpdateAllPages();
|
||||
}
|
||||
|
||||
void ServerContainersLogic::onPushButtonShareClicked(DockerContainer c)
|
||||
{
|
||||
uiLogic()->shareConnectionLogic()->updateSharingPage(uiLogic()->selectedServerIndex, m_settings.serverCredentials(uiLogic()->selectedServerIndex), c);
|
||||
uiLogic()->shareConnectionLogic()->updateSharingPage(uiLogic()->selectedServerIndex, c);
|
||||
emit uiLogic()->goToPage(Page::ShareConnection);
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ void ServerContainersLogic::onPushButtonRemoveClicked(DockerContainer container)
|
|||
if (c.isEmpty()) m_settings.setDefaultContainer(uiLogic()->selectedServerIndex, DockerContainer::None);
|
||||
else m_settings.setDefaultContainer(uiLogic()->selectedServerIndex, c.keys().first());
|
||||
}
|
||||
onUpdatePage();
|
||||
uiLogic()->onUpdateAllPages();
|
||||
}
|
||||
|
||||
void ServerContainersLogic::onPushButtonContinueClicked(DockerContainer c, int port, TransportProto tp)
|
||||
|
@ -85,6 +85,6 @@ void ServerContainersLogic::onPushButtonContinueClicked(DockerContainer c, int p
|
|||
}
|
||||
}
|
||||
|
||||
onUpdatePage();
|
||||
uiLogic()->onUpdateAllPages();
|
||||
emit uiLogic()->closePage();
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ ServerListLogic::ServerListLogic(UiLogic *logic, QObject *parent):
|
|||
void ServerListLogic::onServerListPushbuttonDefaultClicked(int index)
|
||||
{
|
||||
m_settings.setDefaultServer(index);
|
||||
onUpdatePage();
|
||||
uiLogic()->onUpdateAllPages();
|
||||
}
|
||||
|
||||
void ServerListLogic::onServerListPushbuttonSettingsClicked(int index)
|
||||
|
|
|
@ -37,7 +37,7 @@ void ServerSettingsLogic::onUpdatePage()
|
|||
.arg(port));
|
||||
set_lineEditDescriptionText(server.value(config_key::description).toString());
|
||||
QString selectedContainerName = m_settings.defaultContainerName(uiLogic()->selectedServerIndex);
|
||||
set_labelCurrentVpnProtocolText(tr("Protocol: ") + selectedContainerName);
|
||||
set_labelCurrentVpnProtocolText(tr("Service: ") + selectedContainerName);
|
||||
}
|
||||
|
||||
void ServerSettingsLogic::onPushButtonClearServer()
|
||||
|
@ -90,8 +90,7 @@ void ServerSettingsLogic::onPushButtonForgetServer()
|
|||
|
||||
|
||||
uiLogic()->selectedServerIndex = -1;
|
||||
|
||||
uiLogic()->serverListLogic()->onUpdatePage();
|
||||
uiLogic()->onUpdateAllPages();
|
||||
|
||||
if (m_settings.serversCount() == 0) {
|
||||
uiLogic()->setStartPage(Page::Start);
|
||||
|
@ -121,11 +120,11 @@ void ServerSettingsLogic::onLineEditDescriptionEditingFinished()
|
|||
QJsonObject server = m_settings.server(uiLogic()->selectedServerIndex);
|
||||
server.insert(config_key::description, newText);
|
||||
m_settings.editServer(uiLogic()->selectedServerIndex, server);
|
||||
uiLogic()->serverListLogic()->onUpdatePage();
|
||||
uiLogic()->onUpdateAllPages();
|
||||
}
|
||||
|
||||
void ServerSettingsLogic::onPushButtonShareFullClicked()
|
||||
{
|
||||
uiLogic()->shareConnectionLogic()->updateSharingPage(uiLogic()->selectedServerIndex, m_settings.serverCredentials(uiLogic()->selectedServerIndex), DockerContainer::None);
|
||||
uiLogic()->goToPage(Page::ShareConnection);
|
||||
uiLogic()->shareConnectionLogic()->updateSharingPage(uiLogic()->selectedServerIndex, DockerContainer::None);
|
||||
emit uiLogic()->goToShareProtocolPage(Protocol::Any);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <QTimer>
|
||||
#include <QSaveFile>
|
||||
#include <QStandardPaths>
|
||||
#include <QImage>
|
||||
|
||||
#include "ShareConnectionLogic.h"
|
||||
|
||||
|
@ -12,6 +13,8 @@
|
|||
#include "configurators/vpn_configurator.h"
|
||||
#include "configurators/openvpn_configurator.h"
|
||||
#include "configurators/shadowsocks_configurator.h"
|
||||
#include "configurators/wireguard_configurator.h"
|
||||
#include "configurators/ikev2_configurator.h"
|
||||
#include "configurators/ssh_configurator.h"
|
||||
|
||||
#include "defines.h"
|
||||
|
@ -21,333 +24,226 @@
|
|||
|
||||
ShareConnectionLogic::ShareConnectionLogic(UiLogic *logic, QObject *parent):
|
||||
PageLogicBase(logic, parent),
|
||||
m_pageShareAmneziaVisible{true},
|
||||
m_pageShareOpenVpnVisible{true},
|
||||
m_pageShareShadowSocksVisible{true},
|
||||
m_pageShareCloakVisible{true},
|
||||
m_pageShareFullAccessVisible{true},
|
||||
m_textEditShareOpenVpnCodeText{},
|
||||
m_pushButtonShareOpenVpnCopyEnabled{false},
|
||||
m_pushButtonShareOpenVpnSaveEnabled{false},
|
||||
m_toolBoxShareConnectionCurrentIndex{-1},
|
||||
m_pushButtonShareShadowSocksCopyEnabled{false},
|
||||
m_lineEditShareShadowSocksStringText{},
|
||||
m_labelShareShadowSocksQrCodeText{},
|
||||
m_labelShareShadowSocksServerText{},
|
||||
m_labelShareShadowSocksPortText{},
|
||||
m_labelShareShadowSocksMethodText{},
|
||||
m_labelShareShadowSocksPasswordText{},
|
||||
m_plainTextEditShareCloakText{},
|
||||
m_pushButtonShareCloakCopyEnabled{false},
|
||||
m_textEditShareFullCodeText{},
|
||||
m_textEditShareAmneziaCodeText{},
|
||||
m_pushButtonShareFullCopyText{tr("Copy")},
|
||||
m_pushButtonShareAmneziaCopyText{tr("Copy")},
|
||||
m_pushButtonShareOpenVpnCopyText{tr("Copy")},
|
||||
m_pushButtonShareShadowSocksCopyText{tr("Copy")},
|
||||
m_pushButtonShareCloakCopyText{tr("Copy")},
|
||||
m_pushButtonShareAmneziaGenerateEnabled{true},
|
||||
m_pushButtonShareAmneziaCopyEnabled{true},
|
||||
m_pushButtonShareAmneziaGenerateText{tr("Generate config")},
|
||||
m_pushButtonShareOpenVpnGenerateEnabled{true},
|
||||
m_pushButtonShareOpenVpnGenerateText{tr("Generate config")}
|
||||
m_shareShadowSocksQrCodeText{},
|
||||
m_textEditShareCloakText{},
|
||||
m_textEditShareAmneziaCodeText{}
|
||||
{
|
||||
// TODO consider move to Component.onCompleted
|
||||
updateSharingPage(uiLogic()->selectedServerIndex, m_settings.serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer);
|
||||
}
|
||||
|
||||
|
||||
void ShareConnectionLogic::onPushButtonShareFullCopyClicked()
|
||||
void ShareConnectionLogic::onUpdatePage()
|
||||
{
|
||||
QGuiApplication::clipboard()->setText(textEditShareFullCodeText());
|
||||
set_pushButtonShareFullCopyText(tr("Copied"));
|
||||
set_textEditShareAmneziaCodeText(tr(""));
|
||||
set_shareAmneziaQrCodeText("");
|
||||
|
||||
QTimer::singleShot(3000, this, [this]() {
|
||||
set_pushButtonShareFullCopyText(tr("Copy"));
|
||||
});
|
||||
}
|
||||
set_textEditShareOpenVpnCodeText("");
|
||||
|
||||
void ShareConnectionLogic::onPushButtonShareFullSaveClicked()
|
||||
{
|
||||
if (textEditShareFullCodeText().isEmpty()) return;
|
||||
set_shareShadowSocksQrCodeText("");
|
||||
set_textEditShareShadowSocksText("");
|
||||
set_lineEditShareShadowSocksStringText("");
|
||||
|
||||
QString fileName = QFileDialog::getSaveFileName(nullptr, tr("Save AmneziaVPN config"),
|
||||
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.amnezia");
|
||||
QSaveFile save(fileName);
|
||||
save.open(QIODevice::WriteOnly);
|
||||
save.write(textEditShareFullCodeText().toUtf8());
|
||||
save.commit();
|
||||
}
|
||||
set_textEditShareCloakText("");
|
||||
|
||||
void ShareConnectionLogic::onPushButtonShareAmneziaCopyClicked()
|
||||
{
|
||||
if (textEditShareAmneziaCodeText().isEmpty()) return;
|
||||
set_textEditShareWireGuardCodeText("");
|
||||
set_shareWireGuardQrCodeText("");
|
||||
|
||||
QGuiApplication::clipboard()->setText(textEditShareAmneziaCodeText());
|
||||
set_pushButtonShareAmneziaCopyText(tr("Copied"));
|
||||
|
||||
QTimer::singleShot(3000, this, [this]() {
|
||||
set_pushButtonShareAmneziaCopyText(tr("Copy"));
|
||||
});
|
||||
}
|
||||
|
||||
void ShareConnectionLogic::onPushButtonShareAmneziaSaveClicked()
|
||||
{
|
||||
if (textEditShareAmneziaCodeText().isEmpty()) return;
|
||||
|
||||
QString fileName = QFileDialog::getSaveFileName(nullptr, tr("Save AmneziaVPN config"),
|
||||
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.amnezia");
|
||||
QSaveFile save(fileName);
|
||||
save.open(QIODevice::WriteOnly);
|
||||
save.write(textEditShareAmneziaCodeText().toUtf8());
|
||||
save.commit();
|
||||
}
|
||||
|
||||
void ShareConnectionLogic::onPushButtonShareOpenVpnCopyClicked()
|
||||
{
|
||||
QGuiApplication::clipboard()->setText(textEditShareOpenVpnCodeText());
|
||||
set_pushButtonShareOpenVpnCopyText(tr("Copied"));
|
||||
|
||||
QTimer::singleShot(3000, this, [this]() {
|
||||
set_pushButtonShareOpenVpnCopyText(tr("Copy"));
|
||||
});
|
||||
}
|
||||
|
||||
void ShareConnectionLogic::onPushButtonShareShadowSocksCopyClicked()
|
||||
{
|
||||
QGuiApplication::clipboard()->setText(lineEditShareShadowSocksStringText());
|
||||
set_pushButtonShareShadowSocksCopyText(tr("Copied"));
|
||||
|
||||
QTimer::singleShot(3000, this, [this]() {
|
||||
set_pushButtonShareShadowSocksCopyText(tr("Copy"));
|
||||
});
|
||||
}
|
||||
|
||||
void ShareConnectionLogic::onPushButtonShareCloakCopyClicked()
|
||||
{
|
||||
QGuiApplication::clipboard()->setText(plainTextEditShareCloakText());
|
||||
set_pushButtonShareCloakCopyText(tr("Copied"));
|
||||
|
||||
QTimer::singleShot(3000, this, [this]() {
|
||||
set_pushButtonShareCloakCopyText(tr("Copy"));
|
||||
});
|
||||
set_textEditShareIkev2CertText("");
|
||||
set_textEditShareIkev2MobileConfigText("");
|
||||
set_textEditShareIkev2StrongSwanConfigText("");
|
||||
}
|
||||
|
||||
void ShareConnectionLogic::onPushButtonShareAmneziaGenerateClicked()
|
||||
{
|
||||
set_pushButtonShareAmneziaGenerateEnabled(false);
|
||||
set_pushButtonShareAmneziaCopyEnabled(false);
|
||||
set_pushButtonShareAmneziaGenerateText(tr("Generating..."));
|
||||
qApp->processEvents();
|
||||
set_textEditShareAmneziaCodeText("");
|
||||
set_shareAmneziaQrCodeText("");
|
||||
|
||||
ServerCredentials credentials = m_settings.serverCredentials(uiLogic()->selectedServerIndex);
|
||||
QJsonObject containerConfig = m_settings.containerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer);
|
||||
containerConfig.insert(config_key::container, ContainerProps::containerToString(uiLogic()->selectedDockerContainer));
|
||||
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
for (Protocol p: ContainerProps::protocolsForContainer(uiLogic()->selectedDockerContainer)) {
|
||||
QJsonObject protoConfig = m_settings.protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, p);
|
||||
|
||||
QString cfg = VpnConfigurator::genVpnProtocolConfig(credentials, uiLogic()->selectedDockerContainer, containerConfig, p, &e);
|
||||
if (e) {
|
||||
cfg = "Error generating config";
|
||||
break;
|
||||
}
|
||||
protoConfig.insert(config_key::last_config, cfg);
|
||||
|
||||
containerConfig.insert(ProtocolProps::protoToString(p), protoConfig);
|
||||
}
|
||||
|
||||
QByteArray ba;
|
||||
if (!e) {
|
||||
QJsonObject serverConfig = m_settings.server(uiLogic()->selectedServerIndex);
|
||||
serverConfig.remove(config_key::userName);
|
||||
serverConfig.remove(config_key::password);
|
||||
serverConfig.remove(config_key::port);
|
||||
serverConfig.insert(config_key::containers, QJsonArray {containerConfig});
|
||||
serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(uiLogic()->selectedDockerContainer));
|
||||
|
||||
|
||||
ba = QJsonDocument(serverConfig).toJson().toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||
set_textEditShareAmneziaCodeText(QString("vpn://%1").arg(QString(ba)));
|
||||
QJsonObject serverConfig;
|
||||
// Full access
|
||||
if (shareFullAccess()) {
|
||||
serverConfig = m_settings.server(uiLogic()->selectedServerIndex);
|
||||
}
|
||||
// Container share
|
||||
else {
|
||||
set_textEditShareAmneziaCodeText(tr("Error while generating connection profile"));
|
||||
ServerCredentials credentials = m_settings.serverCredentials(uiLogic()->selectedServerIndex);
|
||||
QJsonObject containerConfig = m_settings.containerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer);
|
||||
containerConfig.insert(config_key::container, ContainerProps::containerToString(uiLogic()->selectedDockerContainer));
|
||||
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
for (Protocol p: ContainerProps::protocolsForContainer(uiLogic()->selectedDockerContainer)) {
|
||||
QJsonObject protoConfig = m_settings.protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, p);
|
||||
|
||||
QString cfg = VpnConfigurator::genVpnProtocolConfig(credentials, uiLogic()->selectedDockerContainer, containerConfig, p, &e);
|
||||
if (e) {
|
||||
cfg = "Error generating config";
|
||||
break;
|
||||
}
|
||||
protoConfig.insert(config_key::last_config, cfg);
|
||||
containerConfig.insert(ProtocolProps::protoToString(p), protoConfig);
|
||||
}
|
||||
|
||||
QByteArray ba;
|
||||
if (!e) {
|
||||
serverConfig = m_settings.server(uiLogic()->selectedServerIndex);
|
||||
serverConfig.remove(config_key::userName);
|
||||
serverConfig.remove(config_key::password);
|
||||
serverConfig.remove(config_key::port);
|
||||
serverConfig.insert(config_key::containers, QJsonArray {containerConfig});
|
||||
serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(uiLogic()->selectedDockerContainer));
|
||||
}
|
||||
else {
|
||||
set_textEditShareAmneziaCodeText(tr("Error while generating connection profile"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
set_pushButtonShareAmneziaGenerateEnabled(true);
|
||||
set_pushButtonShareAmneziaCopyEnabled(true);
|
||||
set_pushButtonShareAmneziaGenerateText(tr("Generate config"));
|
||||
QByteArray ba = QJsonDocument(serverConfig).toBinaryData();
|
||||
ba = qCompress(ba, 8);
|
||||
QString code = QString("vpn://%1").arg(QString(ba.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals)));
|
||||
set_textEditShareAmneziaCodeText(code);
|
||||
|
||||
if (ba.size() < 2900) {
|
||||
QImage qr = updateQRCodeImage(ba.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals));
|
||||
set_shareAmneziaQrCodeText(imageToBase64(qr));
|
||||
}
|
||||
}
|
||||
|
||||
void ShareConnectionLogic::onPushButtonShareOpenVpnGenerateClicked()
|
||||
{
|
||||
set_pushButtonShareOpenVpnGenerateEnabled(false);
|
||||
set_pushButtonShareOpenVpnCopyEnabled(false);
|
||||
set_pushButtonShareOpenVpnSaveEnabled(false);
|
||||
set_pushButtonShareOpenVpnGenerateText(tr("Generating..."));
|
||||
|
||||
ServerCredentials credentials = m_settings.serverCredentials(uiLogic()->selectedServerIndex);
|
||||
const QJsonObject &containerConfig = m_settings.containerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer);
|
||||
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
QString cfg = OpenVpnConfigurator::genOpenVpnConfig(credentials, uiLogic()->selectedDockerContainer, containerConfig, &e);
|
||||
cfg = OpenVpnConfigurator::processConfigWithExportSettings(cfg);
|
||||
cfg = VpnConfigurator::processConfigWithExportSettings(uiLogic()->selectedDockerContainer, Protocol::OpenVpn, cfg);
|
||||
|
||||
set_textEditShareOpenVpnCodeText(QJsonDocument::fromJson(cfg.toUtf8()).object()[config_key::config].toString());
|
||||
|
||||
set_pushButtonShareOpenVpnGenerateEnabled(true);
|
||||
set_pushButtonShareOpenVpnCopyEnabled(true);
|
||||
set_pushButtonShareOpenVpnSaveEnabled(true);
|
||||
set_pushButtonShareOpenVpnGenerateText(tr("Generate config"));
|
||||
}
|
||||
|
||||
void ShareConnectionLogic::onPushButtonShareOpenVpnSaveClicked()
|
||||
void ShareConnectionLogic::onPushButtonShareShadowSocksGenerateClicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getSaveFileName(nullptr, tr("Save OpenVPN config"),
|
||||
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.ovpn");
|
||||
int serverIndex = uiLogic()->selectedServerIndex;
|
||||
DockerContainer container = uiLogic()->selectedDockerContainer;
|
||||
ServerCredentials credentials = m_settings.serverCredentials(serverIndex);
|
||||
|
||||
QSaveFile save(fileName);
|
||||
save.open(QIODevice::WriteOnly);
|
||||
save.write(textEditShareOpenVpnCodeText().toUtf8());
|
||||
save.commit();
|
||||
QJsonObject protoConfig = m_settings.protocolConfig(serverIndex, container, Protocol::ShadowSocks);
|
||||
QString cfg = protoConfig.value(config_key::last_config).toString();
|
||||
|
||||
if (cfg.isEmpty()) {
|
||||
const QJsonObject &containerConfig = m_settings.containerConfig(serverIndex, container);
|
||||
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
cfg = ShadowSocksConfigurator::genShadowSocksConfig(credentials, container, containerConfig, &e);
|
||||
}
|
||||
|
||||
QJsonObject ssConfig = QJsonDocument::fromJson(cfg.toUtf8()).object();
|
||||
|
||||
QString ssString = QString("%1:%2@%3:%4")
|
||||
.arg(ssConfig.value("method").toString())
|
||||
.arg(ssConfig.value("password").toString())
|
||||
.arg(ssConfig.value("server").toString())
|
||||
.arg(ssConfig.value("server_port").toString());
|
||||
|
||||
ssString = "ss://" + ssString.toUtf8().toBase64();
|
||||
set_lineEditShareShadowSocksStringText(ssString);
|
||||
|
||||
QImage qr = updateQRCodeImage(ssString.toUtf8());
|
||||
set_shareShadowSocksQrCodeText(imageToBase64(qr));
|
||||
|
||||
QString humanString = QString("Server: %3\n"
|
||||
"Port: %4\n"
|
||||
"Encryption: %1\n"
|
||||
"Password: %2")
|
||||
.arg(ssConfig.value("method").toString())
|
||||
.arg(ssConfig.value("password").toString())
|
||||
.arg(ssConfig.value("server").toString())
|
||||
.arg(ssConfig.value("server_port").toString());
|
||||
|
||||
set_textEditShareShadowSocksText(humanString);
|
||||
}
|
||||
|
||||
|
||||
void ShareConnectionLogic::updateSharingPage(int serverIndex, const ServerCredentials &credentials,
|
||||
DockerContainer container)
|
||||
void ShareConnectionLogic::onPushButtonShareCloakGenerateClicked()
|
||||
{
|
||||
uiLogic()->selectedDockerContainer = container;
|
||||
uiLogic()->selectedServerIndex = serverIndex;
|
||||
int serverIndex = uiLogic()->selectedServerIndex;
|
||||
DockerContainer container = uiLogic()->selectedDockerContainer;
|
||||
ServerCredentials credentials = m_settings.serverCredentials(serverIndex);
|
||||
|
||||
QJsonObject protoConfig = m_settings.protocolConfig(serverIndex, container, Protocol::Cloak);
|
||||
QString cfg = protoConfig.value(config_key::last_config).toString();
|
||||
|
||||
if (cfg.isEmpty()) {
|
||||
const QJsonObject &containerConfig = m_settings.containerConfig(serverIndex, container);
|
||||
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
cfg = CloakConfigurator::genCloakConfig(credentials, container, containerConfig, &e);
|
||||
}
|
||||
|
||||
QJsonObject cloakConfig = QJsonDocument::fromJson(cfg.toUtf8()).object();
|
||||
cloakConfig.remove(config_key::transport_proto);
|
||||
cloakConfig.insert("ProxyMethod", "shadowsocks");
|
||||
|
||||
set_textEditShareCloakText(QJsonDocument(cloakConfig).toJson());
|
||||
}
|
||||
|
||||
void ShareConnectionLogic::onPushButtonShareWireGuardGenerateClicked()
|
||||
{
|
||||
int serverIndex = uiLogic()->selectedServerIndex;
|
||||
DockerContainer container = uiLogic()->selectedDockerContainer;
|
||||
ServerCredentials credentials = m_settings.serverCredentials(serverIndex);
|
||||
|
||||
const QJsonObject &containerConfig = m_settings.containerConfig(serverIndex, container);
|
||||
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
QString cfg = WireguardConfigurator::genWireguardConfig(credentials, container, containerConfig, &e);
|
||||
cfg = VpnConfigurator::processConfigWithExportSettings(container, Protocol::WireGuard, cfg);
|
||||
cfg = QJsonDocument::fromJson(cfg.toUtf8()).object()[config_key::config].toString();
|
||||
|
||||
set_textEditShareWireGuardCodeText(cfg);
|
||||
|
||||
QImage qr = updateQRCodeImage(cfg.toUtf8());
|
||||
set_shareWireGuardQrCodeText(imageToBase64(qr));
|
||||
}
|
||||
|
||||
void ShareConnectionLogic::onPushButtonShareIkev2GenerateClicked()
|
||||
{
|
||||
int serverIndex = uiLogic()->selectedServerIndex;
|
||||
DockerContainer container = uiLogic()->selectedDockerContainer;
|
||||
ServerCredentials credentials = m_settings.serverCredentials(serverIndex);
|
||||
|
||||
//const QJsonObject &containerConfig = m_settings.containerConfig(serverIndex, container);
|
||||
|
||||
set_pageShareAmneziaVisible(false);
|
||||
set_pageShareOpenVpnVisible(false);
|
||||
set_pageShareShadowSocksVisible(false);
|
||||
set_pageShareCloakVisible(false);
|
||||
set_pageShareFullAccessVisible(false);
|
||||
Ikev2Configurator::ConnectionData connData = Ikev2Configurator::prepareIkev2Config(credentials, container);
|
||||
|
||||
enum currentWidget {
|
||||
full_access = 0,
|
||||
share_amezia,
|
||||
share_openvpn,
|
||||
share_shadowshock,
|
||||
share_cloak
|
||||
};
|
||||
QString cfg = Ikev2Configurator::genIkev2Config(connData);
|
||||
cfg = VpnConfigurator::processConfigWithExportSettings(container, Protocol::Ikev2, cfg);
|
||||
cfg = QJsonDocument::fromJson(cfg.toUtf8()).object()[config_key::cert].toString();
|
||||
|
||||
if (container == DockerContainer::OpenVpn) {
|
||||
set_pageShareAmneziaVisible(true);
|
||||
set_pageShareOpenVpnVisible(true);
|
||||
set_textEditShareIkev2CertText(cfg);
|
||||
|
||||
QString cfg = tr("Press Generate config");
|
||||
set_textEditShareOpenVpnCodeText(cfg);
|
||||
set_pushButtonShareOpenVpnCopyEnabled(false);
|
||||
set_pushButtonShareOpenVpnSaveEnabled(false);
|
||||
QString mobileCfg = Ikev2Configurator::genMobileConfig(connData);
|
||||
set_textEditShareIkev2MobileConfigText(mobileCfg);
|
||||
|
||||
set_toolBoxShareConnectionCurrentIndex(share_openvpn);
|
||||
}
|
||||
QString strongSwanCfg = Ikev2Configurator::genStrongSwanConfig(connData);
|
||||
set_textEditShareIkev2StrongSwanConfigText(strongSwanCfg);
|
||||
|
||||
if (container == DockerContainer::ShadowSocks ||
|
||||
container == DockerContainer::Cloak) {
|
||||
set_pageShareAmneziaVisible(true);
|
||||
set_pageShareShadowSocksVisible(true);
|
||||
|
||||
QJsonObject protoConfig = m_settings.protocolConfig(serverIndex, container, Protocol::ShadowSocks);
|
||||
QString cfg = protoConfig.value(config_key::last_config).toString();
|
||||
|
||||
if (cfg.isEmpty()) {
|
||||
const QJsonObject &containerConfig = m_settings.containerConfig(serverIndex, container);
|
||||
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
cfg = ShadowSocksConfigurator::genShadowSocksConfig(credentials, container, containerConfig, &e);
|
||||
|
||||
set_pushButtonShareShadowSocksCopyEnabled(true);
|
||||
}
|
||||
|
||||
QJsonObject ssConfig = QJsonDocument::fromJson(cfg.toUtf8()).object();
|
||||
|
||||
QString ssString = QString("%1:%2@%3:%4")
|
||||
.arg(ssConfig.value("method").toString())
|
||||
.arg(ssConfig.value("password").toString())
|
||||
.arg(ssConfig.value("server").toString())
|
||||
.arg(ssConfig.value("server_port").toString());
|
||||
|
||||
ssString = "ss://" + ssString.toUtf8().toBase64();
|
||||
set_lineEditShareShadowSocksStringText(ssString);
|
||||
updateQRCodeImage(ssString, [this](const QString& labelText) ->void {
|
||||
set_labelShareShadowSocksQrCodeText(labelText);
|
||||
});
|
||||
|
||||
set_labelShareShadowSocksServerText(ssConfig.value("server").toString());
|
||||
set_labelShareShadowSocksPortText(ssConfig.value("server_port").toString());
|
||||
set_labelShareShadowSocksMethodText(ssConfig.value("method").toString());
|
||||
set_labelShareShadowSocksPasswordText(ssConfig.value("password").toString());
|
||||
|
||||
set_toolBoxShareConnectionCurrentIndex(share_shadowshock);
|
||||
}
|
||||
|
||||
if (container == DockerContainer::Cloak) {
|
||||
//ui->toolBox_share_connection->addItem(ui->page_share_amnezia, tr(" Share for Amnezia client"));
|
||||
set_pageShareCloakVisible(true);
|
||||
set_plainTextEditShareCloakText(QString(""));
|
||||
|
||||
QJsonObject protoConfig = m_settings.protocolConfig(serverIndex, container, Protocol::Cloak);
|
||||
QString cfg = protoConfig.value(config_key::last_config).toString();
|
||||
|
||||
if (cfg.isEmpty()) {
|
||||
const QJsonObject &containerConfig = m_settings.containerConfig(serverIndex, container);
|
||||
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
cfg = CloakConfigurator::genCloakConfig(credentials, container, containerConfig, &e);
|
||||
|
||||
set_pushButtonShareCloakCopyEnabled(true);
|
||||
}
|
||||
|
||||
QJsonObject cloakConfig = QJsonDocument::fromJson(cfg.toUtf8()).object();
|
||||
cloakConfig.remove(config_key::transport_proto);
|
||||
cloakConfig.insert("ProxyMethod", "shadowsocks");
|
||||
|
||||
set_plainTextEditShareCloakText(QJsonDocument(cloakConfig).toJson());
|
||||
}
|
||||
|
||||
// Full access
|
||||
if (container == DockerContainer::None) {
|
||||
set_pageShareFullAccessVisible(true);
|
||||
|
||||
const QJsonObject &server = m_settings.server(uiLogic()->selectedServerIndex);
|
||||
|
||||
QByteArray ba = QJsonDocument(server).toJson().toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||
|
||||
set_textEditShareFullCodeText(QString("vpn://%1").arg(QString(ba)));
|
||||
set_toolBoxShareConnectionCurrentIndex(full_access);
|
||||
}
|
||||
|
||||
//ui->toolBox_share_connection->addItem(ui->page_share_amnezia, tr(" Share for Amnezia client"));
|
||||
|
||||
// Amnezia sharing
|
||||
// QJsonObject exportContainer;
|
||||
// for (Protocol p: protocolsForContainer(container)) {
|
||||
// QJsonObject protocolConfig = containerConfig.value(ProtocolProps::protoToString(p)).toObject();
|
||||
// protocolConfig.remove(config_key::last_config);
|
||||
// exportContainer.insert(ProtocolProps::protoToString(p), protocolConfig);
|
||||
// }
|
||||
// exportContainer.insert(config_key::container, containerToString(container));
|
||||
|
||||
// ui->textEdit_share_amnezia_code->setPlainText(QJsonDocument(exportContainer).toJson());
|
||||
|
||||
set_textEditShareAmneziaCodeText(tr(""));
|
||||
}
|
||||
|
||||
|
||||
void ShareConnectionLogic::updateQRCodeImage(const QString &text, const std::function<void(const QString&)>& set_labelFunc)
|
||||
void ShareConnectionLogic::updateSharingPage(int serverIndex, DockerContainer container)
|
||||
{
|
||||
uiLogic()->selectedDockerContainer = container;
|
||||
uiLogic()->selectedServerIndex = serverIndex;
|
||||
set_shareFullAccess(container == DockerContainer::None);
|
||||
}
|
||||
|
||||
QImage ShareConnectionLogic::updateQRCodeImage(const QByteArray &data)
|
||||
{
|
||||
int levelIndex = 1;
|
||||
int versionIndex = 0;
|
||||
bool bExtent = true;
|
||||
int maskIndex = -1;
|
||||
|
||||
m_qrEncode.EncodeData( levelIndex, versionIndex, bExtent, maskIndex, text.toUtf8().data() );
|
||||
m_qrEncode.EncodeData( levelIndex, versionIndex, bExtent, maskIndex, data.data() );
|
||||
|
||||
int qrImageSize = m_qrEncode.m_nSymbleSize;
|
||||
|
||||
|
@ -361,10 +257,14 @@ void ShareConnectionLogic::updateQRCodeImage(const QString &text, const std::fun
|
|||
if ( m_qrEncode.m_byModuleData[i][j] )
|
||||
encodeImage.setPixel( i + QR_MARGIN, j + QR_MARGIN, 0 );
|
||||
|
||||
QByteArray byteArray;
|
||||
QBuffer buffer(&byteArray);
|
||||
encodeImage.save(&buffer, "PNG"); // writes the image in PNG format inside the buffer
|
||||
QString iconBase64 = QString::fromLatin1(byteArray.toBase64().data());
|
||||
|
||||
set_labelFunc(iconBase64);
|
||||
return encodeImage;
|
||||
}
|
||||
|
||||
QString ShareConnectionLogic::imageToBase64(const QImage &image)
|
||||
{
|
||||
QByteArray ba;
|
||||
QBuffer bu(&ba);
|
||||
bu.open(QIODevice::WriteOnly);
|
||||
image.save(&bu, "PNG");
|
||||
return "data:image/png;base64," + QString::fromLatin1(ba.toBase64().data());
|
||||
}
|
||||
|
|
|
@ -11,56 +11,43 @@ class ShareConnectionLogic: public PageLogicBase
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AUTO_PROPERTY(bool, pageShareAmneziaVisible)
|
||||
AUTO_PROPERTY(bool, pageShareOpenVpnVisible)
|
||||
AUTO_PROPERTY(bool, pageShareShadowSocksVisible)
|
||||
AUTO_PROPERTY(bool, pageShareCloakVisible)
|
||||
AUTO_PROPERTY(bool, pageShareFullAccessVisible)
|
||||
AUTO_PROPERTY(QString, textEditShareOpenVpnCodeText)
|
||||
AUTO_PROPERTY(bool, pushButtonShareOpenVpnCopyEnabled)
|
||||
AUTO_PROPERTY(bool, pushButtonShareOpenVpnSaveEnabled)
|
||||
AUTO_PROPERTY(int, toolBoxShareConnectionCurrentIndex)
|
||||
AUTO_PROPERTY(bool, pushButtonShareShadowSocksCopyEnabled)
|
||||
AUTO_PROPERTY(QString, lineEditShareShadowSocksStringText)
|
||||
AUTO_PROPERTY(QString, labelShareShadowSocksQrCodeText)
|
||||
AUTO_PROPERTY(QString, labelShareShadowSocksServerText)
|
||||
AUTO_PROPERTY(QString, labelShareShadowSocksPortText)
|
||||
AUTO_PROPERTY(QString, labelShareShadowSocksMethodText)
|
||||
AUTO_PROPERTY(QString, labelShareShadowSocksPasswordText)
|
||||
AUTO_PROPERTY(QString, plainTextEditShareCloakText)
|
||||
AUTO_PROPERTY(bool, pushButtonShareCloakCopyEnabled)
|
||||
AUTO_PROPERTY(QString, textEditShareFullCodeText)
|
||||
AUTO_PROPERTY(bool, shareFullAccess)
|
||||
|
||||
AUTO_PROPERTY(QString, textEditShareAmneziaCodeText)
|
||||
AUTO_PROPERTY(QString, pushButtonShareFullCopyText)
|
||||
AUTO_PROPERTY(QString, pushButtonShareAmneziaCopyText)
|
||||
AUTO_PROPERTY(QString, pushButtonShareOpenVpnCopyText)
|
||||
AUTO_PROPERTY(QString, pushButtonShareShadowSocksCopyText)
|
||||
AUTO_PROPERTY(QString, pushButtonShareCloakCopyText)
|
||||
AUTO_PROPERTY(bool, pushButtonShareAmneziaGenerateEnabled)
|
||||
AUTO_PROPERTY(bool, pushButtonShareAmneziaCopyEnabled)
|
||||
AUTO_PROPERTY(QString, pushButtonShareAmneziaGenerateText)
|
||||
AUTO_PROPERTY(bool, pushButtonShareOpenVpnGenerateEnabled)
|
||||
AUTO_PROPERTY(QString, pushButtonShareOpenVpnGenerateText)
|
||||
AUTO_PROPERTY(QString, shareAmneziaQrCodeText)
|
||||
|
||||
AUTO_PROPERTY(QString, textEditShareOpenVpnCodeText)
|
||||
|
||||
AUTO_PROPERTY(QString, textEditShareShadowSocksText)
|
||||
AUTO_PROPERTY(QString, lineEditShareShadowSocksStringText)
|
||||
AUTO_PROPERTY(QString, shareShadowSocksQrCodeText)
|
||||
|
||||
AUTO_PROPERTY(QString, textEditShareCloakText)
|
||||
|
||||
AUTO_PROPERTY(QString, textEditShareWireGuardCodeText)
|
||||
AUTO_PROPERTY(QString, shareWireGuardQrCodeText)
|
||||
|
||||
AUTO_PROPERTY(QString, textEditShareIkev2CertText)
|
||||
AUTO_PROPERTY(QString, textEditShareIkev2MobileConfigText)
|
||||
AUTO_PROPERTY(QString, textEditShareIkev2StrongSwanConfigText)
|
||||
|
||||
public:
|
||||
Q_INVOKABLE void onPushButtonShareFullCopyClicked();
|
||||
Q_INVOKABLE void onPushButtonShareFullSaveClicked();
|
||||
Q_INVOKABLE void onPushButtonShareAmneziaCopyClicked();
|
||||
Q_INVOKABLE void onPushButtonShareAmneziaSaveClicked();
|
||||
Q_INVOKABLE void onPushButtonShareOpenVpnCopyClicked();
|
||||
Q_INVOKABLE void onPushButtonShareShadowSocksCopyClicked();
|
||||
Q_INVOKABLE void onPushButtonShareCloakCopyClicked();
|
||||
Q_INVOKABLE void onPushButtonShareAmneziaGenerateClicked();
|
||||
Q_INVOKABLE void onPushButtonShareOpenVpnGenerateClicked();
|
||||
Q_INVOKABLE void onPushButtonShareOpenVpnSaveClicked();
|
||||
Q_INVOKABLE void onPushButtonShareShadowSocksGenerateClicked();
|
||||
Q_INVOKABLE void onPushButtonShareCloakGenerateClicked();
|
||||
Q_INVOKABLE void onPushButtonShareWireGuardGenerateClicked();
|
||||
Q_INVOKABLE void onPushButtonShareIkev2GenerateClicked();
|
||||
|
||||
Q_INVOKABLE virtual void onUpdatePage() override;
|
||||
|
||||
public:
|
||||
explicit ShareConnectionLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
||||
~ShareConnectionLogic() = default;
|
||||
|
||||
void updateSharingPage(int serverIndex, const ServerCredentials &credentials,
|
||||
DockerContainer container);
|
||||
void updateQRCodeImage(const QString &text, const std::function<void(const QString&)>& setLabelFunc);
|
||||
void updateSharingPage(int serverIndex, DockerContainer container);
|
||||
QImage updateQRCodeImage(const QByteArray &data);
|
||||
QString imageToBase64(const QImage &image);
|
||||
|
||||
private:
|
||||
CQR_Encode m_qrEncode;
|
||||
|
|
|
@ -22,7 +22,7 @@ SitesLogic::SitesLogic(UiLogic *logic, QObject *parent):
|
|||
sitesModels.insert(Settings::VpnAllExceptSites, new SitesModel(Settings::VpnAllExceptSites));
|
||||
}
|
||||
|
||||
void SitesLogic::updateSitesPage()
|
||||
void SitesLogic::onUpdatePage()
|
||||
{
|
||||
Settings::RouteMode m = m_settings.routeMode();
|
||||
if (m == Settings::VpnAllSites) return;
|
||||
|
@ -71,7 +71,7 @@ void SitesLogic::onPushButtonAddCustomSitesClicked()
|
|||
uiLogic()->m_vpnConnection->flushDns();
|
||||
}
|
||||
|
||||
updateSitesPage();
|
||||
onUpdatePage();
|
||||
};
|
||||
|
||||
const auto &cbResolv = [this, cbProcess](const QHostInfo &hostInfo){
|
||||
|
@ -93,7 +93,7 @@ void SitesLogic::onPushButtonAddCustomSitesClicked()
|
|||
}
|
||||
else {
|
||||
cbProcess(newSite, "");
|
||||
updateSitesPage();
|
||||
onUpdatePage();
|
||||
QHostInfo::lookupHost(newSite, this, cbResolv);
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ void SitesLogic::onPushButtonSitesDeleteClicked(int row)
|
|||
uiLogic()->m_vpnConnection->flushDns();
|
||||
}
|
||||
|
||||
updateSitesPage();
|
||||
onUpdatePage();
|
||||
}
|
||||
|
||||
void SitesLogic::onPushButtonSitesImportClicked(const QString& fileName)
|
||||
|
@ -153,6 +153,6 @@ void SitesLogic::onPushButtonSitesImportClicked(const QString& fileName)
|
|||
uiLogic()->m_vpnConnection->addRoutes(QStringList() << ips);
|
||||
uiLogic()->m_vpnConnection->flushDns();
|
||||
|
||||
updateSitesPage();
|
||||
onUpdatePage();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ class SitesLogic : public PageLogicBase
|
|||
AUTO_PROPERTY(QString, lineEditSitesAddCustomText)
|
||||
|
||||
public:
|
||||
Q_INVOKABLE void updateSitesPage();
|
||||
Q_INVOKABLE void onUpdatePage() override;
|
||||
|
||||
Q_INVOKABLE void onPushButtonAddCustomSitesClicked();
|
||||
Q_INVOKABLE void onPushButtonSitesDeleteClicked(int row);
|
||||
|
|
|
@ -35,6 +35,8 @@ void StartPageLogic::onUpdatePage()
|
|||
set_pushButtonConnectVisible(true);
|
||||
|
||||
set_pushButtonConnectKeyChecked(false);
|
||||
|
||||
set_pushButtonBackFromStartVisible(uiLogic()->pagesStackDepth() > 0);
|
||||
}
|
||||
|
||||
void StartPageLogic::onPushButtonConnect()
|
||||
|
|
|
@ -24,6 +24,9 @@ VpnLogic::VpnLogic(UiLogic *logic, QObject *parent):
|
|||
connect(uiLogic()->m_vpnConnection, &VpnConnection::connectionStateChanged, this, &VpnLogic::onConnectionStateChanged);
|
||||
connect(uiLogic()->m_vpnConnection, &VpnConnection::vpnProtocolError, this, &VpnLogic::onVpnProtocolError);
|
||||
|
||||
connect(this, &VpnLogic::connectToVpn, uiLogic()->m_vpnConnection, &VpnConnection::connectToVpn, Qt::QueuedConnection);
|
||||
connect(this, &VpnLogic::disconnectFromVpn, uiLogic()->m_vpnConnection, &VpnConnection::disconnectFromVpn, Qt::QueuedConnection);
|
||||
|
||||
if (m_settings.isAutoConnect() && m_settings.defaultServerIndex() >= 0) {
|
||||
QTimer::singleShot(1000, this, [this](){
|
||||
set_pushButtonConnectEnabled(false);
|
||||
|
@ -33,13 +36,22 @@ VpnLogic::VpnLogic(UiLogic *logic, QObject *parent):
|
|||
}
|
||||
|
||||
|
||||
void VpnLogic::updateVpnPage()
|
||||
void VpnLogic::onUpdatePage()
|
||||
{
|
||||
Settings::RouteMode mode = m_settings.routeMode();
|
||||
set_radioButtonVpnModeAllSitesChecked(mode == Settings::VpnAllSites);
|
||||
set_radioButtonVpnModeForwardSitesChecked(mode == Settings::VpnOnlyForwardSites);
|
||||
set_radioButtonVpnModeExceptSitesChecked(mode == Settings::VpnAllExceptSites);
|
||||
set_pushButtonVpnAddSiteEnabled(mode != Settings::VpnAllSites);
|
||||
|
||||
const QJsonObject &server = uiLogic()->m_settings.defaultServer();
|
||||
QString serverString = QString("%2 (%3)")
|
||||
.arg(server.value(config_key::description).toString())
|
||||
.arg(server.value(config_key::hostName).toString());
|
||||
set_labelCurrentServer(serverString);
|
||||
|
||||
QString selectedContainerName = m_settings.defaultContainerName(m_settings.defaultServerIndex());
|
||||
set_labelCurrentService(selectedContainerName);
|
||||
}
|
||||
|
||||
|
||||
|
@ -76,6 +88,7 @@ void VpnLogic::onConnectionStateChanged(VpnProtocol::ConnectionState state)
|
|||
|
||||
bool pbConnectEnabled = false;
|
||||
bool rbModeEnabled = false;
|
||||
bool pbConnectVisible = false;
|
||||
set_labelStateText(VpnProtocol::textConnectionState(state));
|
||||
|
||||
uiLogic()->setTrayState(state);
|
||||
|
@ -85,39 +98,48 @@ void VpnLogic::onConnectionStateChanged(VpnProtocol::ConnectionState state)
|
|||
onBytesChanged(0,0);
|
||||
set_pushButtonConnectChecked(false);
|
||||
pbConnectEnabled = true;
|
||||
pbConnectVisible = true;
|
||||
rbModeEnabled = true;
|
||||
break;
|
||||
case VpnProtocol::Preparing:
|
||||
pbConnectEnabled = false;
|
||||
pbConnectVisible = false;
|
||||
rbModeEnabled = false;
|
||||
break;
|
||||
case VpnProtocol::Connecting:
|
||||
pbConnectEnabled = false;
|
||||
pbConnectVisible = false;
|
||||
rbModeEnabled = false;
|
||||
break;
|
||||
case VpnProtocol::Connected:
|
||||
pbConnectEnabled = true;
|
||||
pbConnectVisible = true;
|
||||
rbModeEnabled = false;
|
||||
break;
|
||||
case VpnProtocol::Disconnecting:
|
||||
pbConnectEnabled = false;
|
||||
pbConnectVisible = false;
|
||||
rbModeEnabled = false;
|
||||
break;
|
||||
case VpnProtocol::Reconnecting:
|
||||
pbConnectEnabled = true;
|
||||
pbConnectVisible = false;
|
||||
rbModeEnabled = false;
|
||||
break;
|
||||
case VpnProtocol::Error:
|
||||
set_pushButtonConnectEnabled(false);
|
||||
pbConnectEnabled = true;
|
||||
pbConnectVisible = true;
|
||||
rbModeEnabled = true;
|
||||
break;
|
||||
case VpnProtocol::Unknown:
|
||||
pbConnectEnabled = true;
|
||||
pbConnectVisible = true;
|
||||
rbModeEnabled = true;
|
||||
}
|
||||
|
||||
set_pushButtonConnectEnabled(pbConnectEnabled);
|
||||
set_pushButtonConnectVisible(pbConnectVisible);
|
||||
set_widgetVpnModeEnabled(rbModeEnabled);
|
||||
}
|
||||
|
||||
|
@ -166,20 +188,19 @@ void VpnLogic::onConnectWorker(int serverIndex, const ServerCredentials &credent
|
|||
|
||||
qApp->processEvents();
|
||||
|
||||
ErrorCode errorCode = uiLogic()->m_vpnConnection->connectToVpn(
|
||||
serverIndex, credentials, container, containerConfig);
|
||||
emit connectToVpn(serverIndex, credentials, container, containerConfig);
|
||||
|
||||
if (errorCode) {
|
||||
//ui->pushButton_connect->setChecked(false);
|
||||
uiLogic()->setDialogConnectErrorText(errorString(errorCode));
|
||||
emit uiLogic()->showConnectErrorDialog();
|
||||
return;
|
||||
}
|
||||
// if (errorCode) {
|
||||
// //ui->pushButton_connect->setChecked(false);
|
||||
// uiLogic()->setDialogConnectErrorText(errorString(errorCode));
|
||||
// emit uiLogic()->showConnectErrorDialog();
|
||||
// return;
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
void VpnLogic::onDisconnect()
|
||||
{
|
||||
set_pushButtonConnectChecked(false);
|
||||
uiLogic()->m_vpnConnection->disconnectFromVpn();
|
||||
emit disconnectFromVpn();
|
||||
}
|
||||
|
|
|
@ -14,7 +14,10 @@ class VpnLogic : public PageLogicBase
|
|||
AUTO_PROPERTY(QString, labelSpeedReceivedText)
|
||||
AUTO_PROPERTY(QString, labelSpeedSentText)
|
||||
AUTO_PROPERTY(QString, labelStateText)
|
||||
AUTO_PROPERTY(QString, labelCurrentServer)
|
||||
AUTO_PROPERTY(QString, labelCurrentService)
|
||||
AUTO_PROPERTY(bool, pushButtonConnectEnabled)
|
||||
AUTO_PROPERTY(bool, pushButtonConnectVisible)
|
||||
AUTO_PROPERTY(bool, widgetVpnModeEnabled)
|
||||
AUTO_PROPERTY(QString, labelErrorText)
|
||||
AUTO_PROPERTY(bool, pushButtonVpnAddSiteEnabled)
|
||||
|
@ -24,7 +27,7 @@ class VpnLogic : public PageLogicBase
|
|||
AUTO_PROPERTY(bool, radioButtonVpnModeExceptSitesChecked)
|
||||
|
||||
public:
|
||||
Q_INVOKABLE void updateVpnPage();
|
||||
Q_INVOKABLE void onUpdatePage() override;
|
||||
|
||||
Q_INVOKABLE void onRadioButtonVpnModeAllSitesToggled(bool checked);
|
||||
Q_INVOKABLE void onRadioButtonVpnModeForwardSitesToggled(bool checked);
|
||||
|
@ -48,5 +51,10 @@ public slots:
|
|||
void onConnectionStateChanged(VpnProtocol::ConnectionState state);
|
||||
void onVpnProtocolError(amnezia::ErrorCode errorCode);
|
||||
|
||||
signals:
|
||||
void connectToVpn(int serverIndex,
|
||||
const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig);
|
||||
|
||||
void disconnectFromVpn();
|
||||
};
|
||||
#endif // VPN_LOGIC_H
|
||||
|
|
|
@ -15,6 +15,7 @@ WizardLogic::WizardLogic(UiLogic *logic, QObject *parent):
|
|||
void WizardLogic::onUpdatePage()
|
||||
{
|
||||
set_lineEditHighWebsiteMaskingText(protocols::cloak::defaultRedirSite);
|
||||
set_radioButtonMediumChecked(true);
|
||||
}
|
||||
|
||||
QMap<DockerContainer, QJsonObject> WizardLogic::getInstallConfigsFromWizardPage() const
|
||||
|
|
|
@ -8,17 +8,17 @@ using namespace PageEnumNS;
|
|||
|
||||
CloakLogic::CloakLogic(UiLogic *logic, QObject *parent):
|
||||
PageProtocolLogicBase(logic, parent),
|
||||
m_comboBoxProtoCloakCipherText{"chacha20-poly1305"},
|
||||
m_lineEditProtoCloakSiteText{"tile.openstreetmap.org"},
|
||||
m_lineEditProtoCloakPortText{},
|
||||
m_pushButtonCloakSaveVisible{false},
|
||||
m_progressBarProtoCloakResetVisible{false},
|
||||
m_lineEditProtoCloakPortEnabled{false},
|
||||
m_pageProtoCloakEnabled{true},
|
||||
m_labelProtoCloakInfoVisible{true},
|
||||
m_labelProtoCloakInfoText{},
|
||||
m_progressBarProtoCloakResetValue{0},
|
||||
m_progressBarProtoCloakResetMaximium{100}
|
||||
m_comboBoxCipherText{"chacha20-poly1305"},
|
||||
m_lineEditSiteText{"tile.openstreetmap.org"},
|
||||
m_lineEditPortText{},
|
||||
m_pushButtonSaveVisible{false},
|
||||
m_progressBarResetVisible{false},
|
||||
m_lineEditPortEnabled{false},
|
||||
m_pageEnabled{true},
|
||||
m_labelInfoVisible{true},
|
||||
m_labelInfoText{},
|
||||
m_progressBarResetValue{0},
|
||||
m_progressBarResetMaximium{100}
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -26,31 +26,31 @@ CloakLogic::CloakLogic(UiLogic *logic, QObject *parent):
|
|||
void CloakLogic::updateProtocolPage(const QJsonObject &ckConfig, DockerContainer container, bool haveAuthData)
|
||||
{
|
||||
set_pageEnabled(haveAuthData);
|
||||
set_pushButtonCloakSaveVisible(haveAuthData);
|
||||
set_progressBarProtoCloakResetVisible(haveAuthData);
|
||||
set_pushButtonSaveVisible(haveAuthData);
|
||||
set_progressBarResetVisible(haveAuthData);
|
||||
|
||||
set_comboBoxProtoCloakCipherText(ckConfig.value(config_key::cipher).
|
||||
set_comboBoxCipherText(ckConfig.value(config_key::cipher).
|
||||
toString(protocols::cloak::defaultCipher));
|
||||
|
||||
set_lineEditProtoCloakSiteText(ckConfig.value(config_key::site).
|
||||
set_lineEditSiteText(ckConfig.value(config_key::site).
|
||||
toString(protocols::cloak::defaultRedirSite));
|
||||
|
||||
set_lineEditProtoCloakPortText(ckConfig.value(config_key::port).
|
||||
set_lineEditPortText(ckConfig.value(config_key::port).
|
||||
toString(protocols::cloak::defaultPort));
|
||||
|
||||
set_lineEditProtoCloakPortEnabled(container == DockerContainer::Cloak);
|
||||
set_lineEditPortEnabled(container == DockerContainer::Cloak);
|
||||
}
|
||||
|
||||
QJsonObject CloakLogic::getProtocolConfigFromPage(QJsonObject oldConfig)
|
||||
{
|
||||
oldConfig.insert(config_key::cipher, comboBoxProtoCloakCipherText());
|
||||
oldConfig.insert(config_key::site, lineEditProtoCloakSiteText());
|
||||
oldConfig.insert(config_key::port, lineEditProtoCloakPortText());
|
||||
oldConfig.insert(config_key::cipher, comboBoxCipherText());
|
||||
oldConfig.insert(config_key::site, lineEditSiteText());
|
||||
oldConfig.insert(config_key::port, lineEditPortText());
|
||||
|
||||
return oldConfig;
|
||||
}
|
||||
|
||||
void CloakLogic::onPushButtonProtoCloakSaveClicked()
|
||||
void CloakLogic::onPushButtonSaveClicked()
|
||||
{
|
||||
QJsonObject protocolConfig = m_settings.protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Protocol::Cloak);
|
||||
protocolConfig = getProtocolConfigFromPage(protocolConfig);
|
||||
|
@ -59,40 +59,40 @@ void CloakLogic::onPushButtonProtoCloakSaveClicked()
|
|||
QJsonObject newContainerConfig = containerConfig;
|
||||
newContainerConfig.insert(ProtocolProps::protoToString(Protocol::Cloak), protocolConfig);
|
||||
|
||||
UiLogic::PageFunc page_proto_cloak;
|
||||
page_proto_cloak.setEnabledFunc = [this] (bool enabled) -> void {
|
||||
set_pageProtoCloakEnabled(enabled);
|
||||
UiLogic::PageFunc page_func;
|
||||
page_func.setEnabledFunc = [this] (bool enabled) -> void {
|
||||
set_pageEnabled(enabled);
|
||||
};
|
||||
UiLogic::ButtonFunc pushButton_proto_cloak_save;
|
||||
pushButton_proto_cloak_save.setVisibleFunc = [this] (bool visible) ->void {
|
||||
set_pushButtonCloakSaveVisible(visible);
|
||||
UiLogic::ButtonFunc pushButton_save_func;
|
||||
pushButton_save_func.setVisibleFunc = [this] (bool visible) ->void {
|
||||
set_pushButtonSaveVisible(visible);
|
||||
};
|
||||
UiLogic::LabelFunc label_proto_cloak_info;
|
||||
label_proto_cloak_info.setVisibleFunc = [this] (bool visible) ->void {
|
||||
set_labelProtoCloakInfoVisible(visible);
|
||||
UiLogic::LabelFunc label_info_func;
|
||||
label_info_func.setVisibleFunc = [this] (bool visible) ->void {
|
||||
set_labelInfoVisible(visible);
|
||||
};
|
||||
label_proto_cloak_info.setTextFunc = [this] (const QString& text) ->void {
|
||||
set_labelProtoCloakInfoText(text);
|
||||
label_info_func.setTextFunc = [this] (const QString& text) ->void {
|
||||
set_labelInfoText(text);
|
||||
};
|
||||
UiLogic::ProgressFunc progressBar_proto_cloak_reset;
|
||||
progressBar_proto_cloak_reset.setVisibleFunc = [this] (bool visible) ->void {
|
||||
set_progressBarProtoCloakResetVisible(visible);
|
||||
UiLogic::ProgressFunc progressBar_reset;
|
||||
progressBar_reset.setVisibleFunc = [this] (bool visible) ->void {
|
||||
set_progressBarResetVisible(visible);
|
||||
};
|
||||
progressBar_proto_cloak_reset.setValueFunc = [this] (int value) ->void {
|
||||
set_progressBarProtoCloakResetValue(value);
|
||||
progressBar_reset.setValueFunc = [this] (int value) ->void {
|
||||
set_progressBarResetValue(value);
|
||||
};
|
||||
progressBar_proto_cloak_reset.getValueFunc = [this] (void) -> int {
|
||||
return progressBarProtoCloakResetValue();
|
||||
progressBar_reset.getValueFunc = [this] (void) -> int {
|
||||
return progressBarResetValue();
|
||||
};
|
||||
progressBar_proto_cloak_reset.getMaximiumFunc = [this] (void) -> int {
|
||||
return progressBarProtoCloakResetMaximium();
|
||||
progressBar_reset.getMaximiumFunc = [this] (void) -> int {
|
||||
return progressBarResetMaximium();
|
||||
};
|
||||
|
||||
ErrorCode e = uiLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){
|
||||
return ServerController::updateContainer(m_settings.serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig);
|
||||
},
|
||||
page_proto_cloak, progressBar_proto_cloak_reset,
|
||||
pushButton_proto_cloak_save, label_proto_cloak_info);
|
||||
page_func, progressBar_reset,
|
||||
pushButton_save_func, label_info_func);
|
||||
|
||||
if (!e) {
|
||||
m_settings.setContainerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, newContainerConfig);
|
||||
|
|
|
@ -9,20 +9,20 @@ class CloakLogic : public PageProtocolLogicBase
|
|||
{
|
||||
Q_OBJECT
|
||||
|
||||
AUTO_PROPERTY(QString, comboBoxProtoCloakCipherText)
|
||||
AUTO_PROPERTY(QString, lineEditProtoCloakSiteText)
|
||||
AUTO_PROPERTY(QString, lineEditProtoCloakPortText)
|
||||
AUTO_PROPERTY(bool, pushButtonCloakSaveVisible)
|
||||
AUTO_PROPERTY(bool, progressBarProtoCloakResetVisible)
|
||||
AUTO_PROPERTY(bool, lineEditProtoCloakPortEnabled)
|
||||
AUTO_PROPERTY(bool, pageProtoCloakEnabled)
|
||||
AUTO_PROPERTY(bool, labelProtoCloakInfoVisible)
|
||||
AUTO_PROPERTY(QString, labelProtoCloakInfoText)
|
||||
AUTO_PROPERTY(int, progressBarProtoCloakResetValue)
|
||||
AUTO_PROPERTY(int, progressBarProtoCloakResetMaximium)
|
||||
AUTO_PROPERTY(QString, comboBoxCipherText)
|
||||
AUTO_PROPERTY(QString, lineEditSiteText)
|
||||
AUTO_PROPERTY(QString, lineEditPortText)
|
||||
AUTO_PROPERTY(bool, pushButtonSaveVisible)
|
||||
AUTO_PROPERTY(bool, progressBarResetVisible)
|
||||
AUTO_PROPERTY(bool, lineEditPortEnabled)
|
||||
AUTO_PROPERTY(bool, pageEnabled)
|
||||
AUTO_PROPERTY(bool, labelInfoVisible)
|
||||
AUTO_PROPERTY(QString, labelInfoText)
|
||||
AUTO_PROPERTY(int, progressBarResetValue)
|
||||
AUTO_PROPERTY(int, progressBarResetMaximium)
|
||||
|
||||
public:
|
||||
Q_INVOKABLE void onPushButtonProtoCloakSaveClicked();
|
||||
Q_INVOKABLE void onPushButtonSaveClicked();
|
||||
|
||||
public:
|
||||
explicit CloakLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
||||
|
|
|
@ -8,16 +8,15 @@ using namespace PageEnumNS;
|
|||
|
||||
ShadowSocksLogic::ShadowSocksLogic(UiLogic *logic, QObject *parent):
|
||||
PageProtocolLogicBase(logic, parent),
|
||||
m_comboBoxProtoShadowSocksCipherText{"chacha20-poly1305"},
|
||||
m_lineEditProtoShadowSocksPortText{},
|
||||
m_pushButtonShadowSocksSaveVisible{false},
|
||||
m_progressBarProtoShadowSocksResetVisible{false},
|
||||
m_lineEditProtoShadowSocksPortEnabled{false},
|
||||
m_pageProtoShadowSocksEnabled{true},
|
||||
m_labelProtoShadowSocksInfoVisible{true},
|
||||
m_labelProtoShadowSocksInfoText{},
|
||||
m_progressBarProtoShadowSocksResetValue{0},
|
||||
m_progressBarProtoShadowSocksResetMaximium{100}
|
||||
m_comboBoxCipherText{"chacha20-poly1305"},
|
||||
m_lineEditPortText{},
|
||||
m_pushButtonSaveVisible{false},
|
||||
m_progressBaResetVisible{false},
|
||||
m_lineEditPortEnabled{false},
|
||||
m_labelInfoVisible{true},
|
||||
m_labelInfoText{},
|
||||
m_progressBaResetValue{0},
|
||||
m_progressBaResetMaximium{100}
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -25,27 +24,27 @@ ShadowSocksLogic::ShadowSocksLogic(UiLogic *logic, QObject *parent):
|
|||
void ShadowSocksLogic::updateProtocolPage(const QJsonObject &ssConfig, DockerContainer container, bool haveAuthData)
|
||||
{
|
||||
set_pageEnabled(haveAuthData);
|
||||
set_pushButtonShadowSocksSaveVisible(haveAuthData);
|
||||
set_progressBarProtoShadowSocksResetVisible(haveAuthData);
|
||||
set_pushButtonSaveVisible(haveAuthData);
|
||||
set_progressBaResetVisible(haveAuthData);
|
||||
|
||||
set_comboBoxProtoShadowSocksCipherText(ssConfig.value(config_key::cipher).
|
||||
set_comboBoxCipherText(ssConfig.value(config_key::cipher).
|
||||
toString(protocols::shadowsocks::defaultCipher));
|
||||
|
||||
set_lineEditProtoShadowSocksPortText(ssConfig.value(config_key::port).
|
||||
set_lineEditPortText(ssConfig.value(config_key::port).
|
||||
toString(protocols::shadowsocks::defaultPort));
|
||||
|
||||
set_lineEditProtoShadowSocksPortEnabled(container == DockerContainer::ShadowSocks);
|
||||
set_lineEditPortEnabled(container == DockerContainer::ShadowSocks);
|
||||
}
|
||||
|
||||
QJsonObject ShadowSocksLogic::getProtocolConfigFromPage(QJsonObject oldConfig)
|
||||
{
|
||||
oldConfig.insert(config_key::cipher, comboBoxProtoShadowSocksCipherText());
|
||||
oldConfig.insert(config_key::port, lineEditProtoShadowSocksPortText());
|
||||
oldConfig.insert(config_key::cipher, comboBoxCipherText());
|
||||
oldConfig.insert(config_key::port, lineEditPortText());
|
||||
|
||||
return oldConfig;
|
||||
}
|
||||
|
||||
void ShadowSocksLogic::onPushButtonProtoShadowSocksSaveClicked()
|
||||
void ShadowSocksLogic::onPushButtonSaveClicked()
|
||||
{
|
||||
QJsonObject protocolConfig = m_settings.protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Protocol::ShadowSocks);
|
||||
//protocolConfig = getShadowSocksConfigFromPage(protocolConfig);
|
||||
|
@ -55,37 +54,37 @@ void ShadowSocksLogic::onPushButtonProtoShadowSocksSaveClicked()
|
|||
newContainerConfig.insert(ProtocolProps::protoToString(Protocol::ShadowSocks), protocolConfig);
|
||||
UiLogic::PageFunc page_proto_shadowsocks;
|
||||
page_proto_shadowsocks.setEnabledFunc = [this] (bool enabled) -> void {
|
||||
set_pageProtoShadowSocksEnabled(enabled);
|
||||
set_pageEnabled(enabled);
|
||||
};
|
||||
UiLogic::ButtonFunc pushButton_proto_shadowsocks_save;
|
||||
pushButton_proto_shadowsocks_save.setVisibleFunc = [this] (bool visible) ->void {
|
||||
set_pushButtonShadowSocksSaveVisible(visible);
|
||||
set_pushButtonSaveVisible(visible);
|
||||
};
|
||||
UiLogic::LabelFunc label_proto_shadowsocks_info;
|
||||
label_proto_shadowsocks_info.setVisibleFunc = [this] (bool visible) ->void {
|
||||
set_labelProtoShadowSocksInfoVisible(visible);
|
||||
set_labelInfoVisible(visible);
|
||||
};
|
||||
label_proto_shadowsocks_info.setTextFunc = [this] (const QString& text) ->void {
|
||||
set_labelProtoShadowSocksInfoText(text);
|
||||
set_labelInfoText(text);
|
||||
};
|
||||
UiLogic::ProgressFunc progressBar_proto_shadowsocks_reset;
|
||||
progressBar_proto_shadowsocks_reset.setVisibleFunc = [this] (bool visible) ->void {
|
||||
set_progressBarProtoShadowSocksResetVisible(visible);
|
||||
UiLogic::ProgressFunc progressBar_reset;
|
||||
progressBar_reset.setVisibleFunc = [this] (bool visible) ->void {
|
||||
set_progressBaResetVisible(visible);
|
||||
};
|
||||
progressBar_proto_shadowsocks_reset.setValueFunc = [this] (int value) ->void {
|
||||
set_progressBarProtoShadowSocksResetValue(value);
|
||||
progressBar_reset.setValueFunc = [this] (int value) ->void {
|
||||
set_progressBaResetValue(value);
|
||||
};
|
||||
progressBar_proto_shadowsocks_reset.getValueFunc = [this] (void) -> int {
|
||||
return progressBarProtoShadowSocksResetValue();
|
||||
progressBar_reset.getValueFunc = [this] (void) -> int {
|
||||
return progressBaResetValue();
|
||||
};
|
||||
progressBar_proto_shadowsocks_reset.getMaximiumFunc = [this] (void) -> int {
|
||||
return progressBarProtoShadowSocksResetMaximium();
|
||||
progressBar_reset.getMaximiumFunc = [this] (void) -> int {
|
||||
return progressBaResetMaximium();
|
||||
};
|
||||
|
||||
ErrorCode e = uiLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){
|
||||
return ServerController::updateContainer(m_settings.serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig);
|
||||
},
|
||||
page_proto_shadowsocks, progressBar_proto_shadowsocks_reset,
|
||||
page_proto_shadowsocks, progressBar_reset,
|
||||
pushButton_proto_shadowsocks_save, label_proto_shadowsocks_info);
|
||||
|
||||
if (!e) {
|
||||
|
|
|
@ -9,19 +9,18 @@ class ShadowSocksLogic : public PageProtocolLogicBase
|
|||
{
|
||||
Q_OBJECT
|
||||
|
||||
AUTO_PROPERTY(QString, comboBoxProtoShadowSocksCipherText)
|
||||
AUTO_PROPERTY(QString, lineEditProtoShadowSocksPortText)
|
||||
AUTO_PROPERTY(bool, pushButtonShadowSocksSaveVisible)
|
||||
AUTO_PROPERTY(bool, progressBarProtoShadowSocksResetVisible)
|
||||
AUTO_PROPERTY(bool, lineEditProtoShadowSocksPortEnabled)
|
||||
AUTO_PROPERTY(bool, pageProtoShadowSocksEnabled)
|
||||
AUTO_PROPERTY(bool, labelProtoShadowSocksInfoVisible)
|
||||
AUTO_PROPERTY(QString, labelProtoShadowSocksInfoText)
|
||||
AUTO_PROPERTY(int, progressBarProtoShadowSocksResetValue)
|
||||
AUTO_PROPERTY(int, progressBarProtoShadowSocksResetMaximium)
|
||||
AUTO_PROPERTY(QString, comboBoxCipherText)
|
||||
AUTO_PROPERTY(QString, lineEditPortText)
|
||||
AUTO_PROPERTY(bool, pushButtonSaveVisible)
|
||||
AUTO_PROPERTY(bool, progressBaResetVisible)
|
||||
AUTO_PROPERTY(bool, lineEditPortEnabled)
|
||||
AUTO_PROPERTY(bool, labelInfoVisible)
|
||||
AUTO_PROPERTY(QString, labelInfoText)
|
||||
AUTO_PROPERTY(int, progressBaResetValue)
|
||||
AUTO_PROPERTY(int, progressBaResetMaximium)
|
||||
|
||||
public:
|
||||
Q_INVOKABLE void onPushButtonProtoShadowSocksSaveClicked();
|
||||
Q_INVOKABLE void onPushButtonSaveClicked();
|
||||
|
||||
public:
|
||||
explicit ShadowSocksLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
||||
|
|
|
@ -6,8 +6,6 @@ BasicButtonType {
|
|||
id: root
|
||||
width: parent.width - 80
|
||||
height: 40
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.topMargin: 20
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
|
|
33
client/ui/qml/Controls/ContextMenu.qml
Normal file
33
client/ui/qml/Controls/ContextMenu.qml
Normal file
|
@ -0,0 +1,33 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import Qt.labs.platform 1.0
|
||||
|
||||
Menu {
|
||||
property var textObj
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("C&ut")
|
||||
shortcut: StandardKey.Cut
|
||||
enabled: textObj.selectedText
|
||||
onTriggered: textObj.cut()
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("&Copy")
|
||||
shortcut: StandardKey.Copy
|
||||
enabled: textObj.selectedText
|
||||
onTriggered: textObj.copy()
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("&Paste")
|
||||
shortcut: StandardKey.Paste
|
||||
enabled: textObj.canPaste
|
||||
onTriggered: textObj.paste()
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("&SelectAll")
|
||||
shortcut: StandardKey.SelectAll
|
||||
enabled: textObj.length > 0
|
||||
onTriggered: textObj.selectAll()
|
||||
}
|
||||
}
|
26
client/ui/qml/Controls/ShareConnectionButtonCopyType.qml
Normal file
26
client/ui/qml/Controls/ShareConnectionButtonCopyType.qml
Normal file
|
@ -0,0 +1,26 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
ShareConnectionButtonType {
|
||||
property string start_text: qsTr("Copy")
|
||||
property string end_text: qsTr("Copied")
|
||||
|
||||
property string copyText
|
||||
|
||||
enabled: copyText.length > 0
|
||||
visible: copyText.length > 0
|
||||
|
||||
Timer {
|
||||
id: timer
|
||||
interval: 1000; running: false; repeat: false
|
||||
onTriggered: text = start_text
|
||||
}
|
||||
|
||||
text: start_text
|
||||
|
||||
onClicked: {
|
||||
text = end_text
|
||||
timer.running = true
|
||||
UiLogic.copyToClipboard(copyText)
|
||||
}
|
||||
}
|
|
@ -4,10 +4,13 @@ import QtQuick.Controls 2.12
|
|||
|
||||
BasicButtonType {
|
||||
id: root
|
||||
height: 40
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: 4
|
||||
color: root.containsMouse ? "#282932" : "#181922"
|
||||
color: root.enabled
|
||||
? (root.containsMouse ? "#282932" : "#181922")
|
||||
: "#484952"
|
||||
}
|
||||
font.pixelSize: 16
|
||||
contentItem: Text {
|
||||
|
|
|
@ -5,9 +5,7 @@ import QtGraphicalEffects 1.12
|
|||
Item {
|
||||
id: root
|
||||
property bool active: false
|
||||
property Component content: undefined
|
||||
property string text: ""
|
||||
width: 360
|
||||
height: active ? contentLoader.item.height + 40 + 5 * 2 : 40
|
||||
signal clicked()
|
||||
|
||||
|
@ -64,12 +62,5 @@ Item {
|
|||
onClicked: root.clicked()
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
x: 0
|
||||
y: 40 + 5
|
||||
id: contentLoader
|
||||
sourceComponent: root.content
|
||||
visible: root.active
|
||||
}
|
||||
}
|
||||
|
||||
|
|
63
client/ui/qml/Controls/TextAreaType.qml
Normal file
63
client/ui/qml/Controls/TextAreaType.qml
Normal file
|
@ -0,0 +1,63 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import Qt.labs.platform 1.0
|
||||
|
||||
import "../Config"
|
||||
|
||||
Flickable
|
||||
{
|
||||
property alias textArea: root
|
||||
id: flickable
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
clip: true
|
||||
TextArea.flickable:
|
||||
|
||||
TextArea {
|
||||
id: root
|
||||
property bool error: false
|
||||
|
||||
height: 40
|
||||
anchors.topMargin: 5
|
||||
selectByMouse: false
|
||||
|
||||
selectionColor: "darkgray"
|
||||
font.pixelSize: 16
|
||||
color: "#333333"
|
||||
background: Rectangle {
|
||||
implicitWidth: 200
|
||||
implicitHeight: 40
|
||||
border.width: 1
|
||||
color: {
|
||||
if (root.error) {
|
||||
return Qt.rgba(213, 40, 60, 255)
|
||||
}
|
||||
return root.enabled ? "#F4F4F4" : Qt.rgba(127, 127, 127, 255)
|
||||
}
|
||||
border.color: {
|
||||
if (!root.enabled) {
|
||||
return Qt.rgba(127, 127, 127, 255)
|
||||
}
|
||||
if (root.error) {
|
||||
return Qt.rgba(213, 40, 60, 255)
|
||||
}
|
||||
if (root.focus) {
|
||||
return "#A7A7A7"
|
||||
}
|
||||
return "#A7A7A7"
|
||||
}
|
||||
}
|
||||
|
||||
// MouseArea {
|
||||
// anchors.fill: root
|
||||
// enabled: GC.isDesktop()
|
||||
// acceptedButtons: Qt.RightButton
|
||||
// onClicked: contextMenu.open()
|
||||
// }
|
||||
|
||||
// ContextMenu {
|
||||
// id: contextMenu
|
||||
// textObj: root
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
|
@ -44,29 +44,8 @@ TextField {
|
|||
onClicked: contextMenu.open()
|
||||
}
|
||||
|
||||
Menu {
|
||||
ContextMenu {
|
||||
id: contextMenu
|
||||
|
||||
onAboutToShow: console.log("aboutToShow")
|
||||
onAboutToHide: console.log("aboutToHide")
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("C&ut")
|
||||
shortcut: StandardKey.Cut
|
||||
enabled: root.selectedText
|
||||
onTriggered: root.cut()
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("&Copy")
|
||||
shortcut: StandardKey.Copy
|
||||
enabled: root.selectedText
|
||||
onTriggered: root.copy()
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("&Paste")
|
||||
shortcut: StandardKey.Paste
|
||||
enabled: root.canPaste
|
||||
onTriggered: root.paste()
|
||||
}
|
||||
textObj: root
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ Drawer {
|
|||
height: parent.height
|
||||
|
||||
modal: true
|
||||
interactive: true
|
||||
interactive: activeFocus
|
||||
|
||||
SortFilterProxyModel {
|
||||
id: proxyModel
|
||||
|
|
|
@ -13,82 +13,49 @@ PageBase {
|
|||
BackButton {
|
||||
id: back
|
||||
}
|
||||
|
||||
// ---------- App settings ------------
|
||||
Rectangle {
|
||||
y: 40
|
||||
id: l1
|
||||
visible: !GC.isMobile()
|
||||
anchors.top: back.bottom
|
||||
x: 20
|
||||
width: parent.width - 40
|
||||
height: 1
|
||||
color: "#DDDDDD"
|
||||
}
|
||||
Rectangle {
|
||||
y: 100
|
||||
x: 20
|
||||
width: parent.width - 40
|
||||
height: 1
|
||||
color: "#DDDDDD"
|
||||
}
|
||||
Rectangle {
|
||||
y: 160
|
||||
x: 20
|
||||
width: parent.width - 40
|
||||
height: 1
|
||||
color: "#DDDDDD"
|
||||
}
|
||||
Rectangle {
|
||||
y: 220
|
||||
x: 20
|
||||
width: parent.width - 40
|
||||
height: 1
|
||||
color: "#DDDDDD"
|
||||
}
|
||||
Rectangle {
|
||||
y: 280
|
||||
x: 20
|
||||
width: parent.width - 40
|
||||
height: 1
|
||||
color: "#DDDDDD"
|
||||
}
|
||||
Rectangle {
|
||||
y: 340
|
||||
x: 20
|
||||
width: parent.width - 40
|
||||
height: 1
|
||||
color: "#DDDDDD"
|
||||
}
|
||||
Rectangle {
|
||||
y: 400
|
||||
x: 20
|
||||
width: parent.width - 40
|
||||
height: 1
|
||||
height: GC.isMobile() ? 0: 1
|
||||
color: "#DDDDDD"
|
||||
}
|
||||
|
||||
SettingButtonType {
|
||||
id: b1
|
||||
visible: !GC.isMobile()
|
||||
anchors.top: l1.bottom
|
||||
anchors.topMargin: GC.isMobile() ? 0: 15
|
||||
x: 30
|
||||
y: 355
|
||||
width: 330
|
||||
height: 30
|
||||
icon.source: "qrc:/images/plus.png"
|
||||
text: qsTr("Add server")
|
||||
onClicked: {
|
||||
UiLogic.goToPage(PageEnum.Start)
|
||||
}
|
||||
}
|
||||
SettingButtonType {
|
||||
x: 30
|
||||
y: 55
|
||||
width: 330
|
||||
height: 30
|
||||
width: parent.width - 40
|
||||
height: GC.isMobile() ? 0: 30
|
||||
icon.source: "qrc:/images/settings.png"
|
||||
text: qsTr("App settings")
|
||||
onClicked: {
|
||||
UiLogic.goToPage(PageEnum.AppSettings)
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- Network settings ------------
|
||||
Rectangle {
|
||||
id: l2
|
||||
anchors.top: b1.bottom
|
||||
anchors.topMargin: 15
|
||||
x: 20
|
||||
width: parent.width - 40
|
||||
height: 1
|
||||
color: "#DDDDDD"
|
||||
}
|
||||
SettingButtonType {
|
||||
id: b2
|
||||
x: 30
|
||||
y: 115
|
||||
width: 330
|
||||
anchors.top: l2.bottom
|
||||
anchors.topMargin: 15
|
||||
width: parent.width - 40
|
||||
height: 30
|
||||
icon.source: "qrc:/images/settings.png"
|
||||
text: qsTr("Network settings")
|
||||
|
@ -96,31 +63,46 @@ PageBase {
|
|||
UiLogic.goToPage(PageEnum.NetworkSettings)
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- Server settings ------------
|
||||
Rectangle {
|
||||
id: l3
|
||||
anchors.top: b2.bottom
|
||||
anchors.topMargin: 15
|
||||
x: 20
|
||||
width: parent.width - 40
|
||||
height: 1
|
||||
color: "#DDDDDD"
|
||||
}
|
||||
SettingButtonType {
|
||||
id: b3
|
||||
x: 30
|
||||
y: 175
|
||||
anchors.top: l3.bottom
|
||||
anchors.topMargin: 15
|
||||
width: 330
|
||||
height: 30
|
||||
icon.source: "qrc:/images/server_settings.png"
|
||||
text: qsTr("Server management")
|
||||
text: qsTr("Server Settings")
|
||||
onClicked: {
|
||||
GeneralSettingsLogic.onPushButtonGeneralSettingsServerSettingsClicked()
|
||||
}
|
||||
}
|
||||
SettingButtonType {
|
||||
x: 30
|
||||
y: 295
|
||||
width: 330
|
||||
height: 30
|
||||
icon.source: "qrc:/images/server_settings.png"
|
||||
text: qsTr("Servers")
|
||||
onClicked: {
|
||||
UiLogic.goToPage(PageEnum.ServersList)
|
||||
}
|
||||
|
||||
// ---------- Share connection ------------
|
||||
Rectangle {
|
||||
id: l4
|
||||
anchors.top: b3.bottom
|
||||
anchors.topMargin: 15
|
||||
x: 20
|
||||
width: parent.width - 40
|
||||
height: 1
|
||||
color: "#DDDDDD"
|
||||
}
|
||||
SettingButtonType {
|
||||
id: b4
|
||||
x: 30
|
||||
y: 235
|
||||
anchors.top: l4.bottom
|
||||
anchors.topMargin: 15
|
||||
width: 330
|
||||
height: 30
|
||||
icon.source: "qrc:/images/share.png"
|
||||
|
@ -130,6 +112,66 @@ PageBase {
|
|||
GeneralSettingsLogic.onPushButtonGeneralSettingsShareConnectionClicked()
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- Servers ------------
|
||||
Rectangle {
|
||||
id: l5
|
||||
anchors.top: b4.bottom
|
||||
anchors.topMargin: 15
|
||||
x: 20
|
||||
width: parent.width - 40
|
||||
height: 1
|
||||
color: "#DDDDDD"
|
||||
}
|
||||
SettingButtonType {
|
||||
id: b5
|
||||
x: 30
|
||||
anchors.top: l5.bottom
|
||||
anchors.topMargin: 15
|
||||
width: 330
|
||||
height: 30
|
||||
icon.source: "qrc:/images/server_settings.png"
|
||||
text: qsTr("Servers")
|
||||
onClicked: {
|
||||
UiLogic.goToPage(PageEnum.ServersList)
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- Add server ------------
|
||||
Rectangle {
|
||||
id: l6
|
||||
anchors.top: b5.bottom
|
||||
anchors.topMargin: 15
|
||||
x: 20
|
||||
width: parent.width - 40
|
||||
height: 1
|
||||
color: "#DDDDDD"
|
||||
}
|
||||
SettingButtonType {
|
||||
id: b6
|
||||
x: 30
|
||||
anchors.top: l6.bottom
|
||||
anchors.topMargin: 15
|
||||
width: 330
|
||||
height: 30
|
||||
icon.source: "qrc:/images/plus.png"
|
||||
text: qsTr("Add server")
|
||||
onClicked: {
|
||||
UiLogic.goToPage(PageEnum.Start)
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: l7
|
||||
anchors.top: b6.bottom
|
||||
anchors.topMargin: 15
|
||||
x: 20
|
||||
width: parent.width - 40
|
||||
height: 1
|
||||
color: "#DDDDDD"
|
||||
}
|
||||
|
||||
|
||||
SettingButtonType {
|
||||
x: 30
|
||||
anchors.bottom: parent.bottom
|
||||
|
|
|
@ -30,6 +30,7 @@ PageBase {
|
|||
id: pushButtonWizard
|
||||
text: qsTr("Run Setup Wizard")
|
||||
anchors.top: labelWizard.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.topMargin: 10
|
||||
onClicked: {
|
||||
UiLogic.goToPage(PageEnum.Wizard);
|
||||
|
|
|
@ -147,172 +147,4 @@ PageBase {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ScrollView {
|
||||
// id: scrollView
|
||||
// width: parent.width - 40
|
||||
// anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
// anchors.top: pb_add_container.bottom
|
||||
// anchors.topMargin: 10
|
||||
|
||||
// anchors.bottom: pushButtonConfigure.top
|
||||
// anchors.bottomMargin: 10
|
||||
|
||||
// clip: true
|
||||
// Column {
|
||||
// width: scrollView.width
|
||||
// anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
// spacing: 5
|
||||
// InstallSettingsBase {
|
||||
// containerDescription: qsTr("OpenVPN and ShadowSocks\n with masking using Cloak plugin")
|
||||
// onContainerChecked: NewServerProtocolsLogic.checkBoxCloakChecked = checked
|
||||
|
||||
// LabelType {
|
||||
// width: 130
|
||||
// height: (parent.height - parent.spacing - parent.topPadding * 2) / 2
|
||||
// text: qsTr("Port (TCP)")
|
||||
// }
|
||||
// TextFieldType {
|
||||
// width: parent.width - 130 - parent.spacing - parent.leftPadding * 2
|
||||
// height: (parent.height - parent.spacing - parent.topPadding * 2) / 2
|
||||
// text: NewServerProtocolsLogic.lineEditCloakPortText
|
||||
// onEditingFinished: {
|
||||
// NewServerProtocolsLogic.lineEditCloakPortText = text
|
||||
// }
|
||||
// }
|
||||
// LabelType {
|
||||
// width: 130
|
||||
// height: (parent.height - parent.spacing - parent.topPadding * 2) / 2
|
||||
// text: qsTr("Fake Web Site")
|
||||
// }
|
||||
// TextFieldType {
|
||||
// width: parent.width - 130 - parent.spacing - parent.leftPadding * 2
|
||||
// height: (parent.height - parent.spacing - parent.topPadding * 2) / 2
|
||||
// text: NewServerProtocolsLogic.lineEditCloakSiteText
|
||||
// onEditingFinished: {
|
||||
// NewServerProtocolsLogic.lineEditCloakSiteText = text
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// InstallSettingsBase {
|
||||
// containerDescription: qsTr("ShadowSocks")
|
||||
// onContainerChecked: NewServerProtocolsLogic.checkBoxSsChecked = checked
|
||||
|
||||
// LabelType {
|
||||
// width: 130
|
||||
// height: (parent.height - parent.spacing - parent.topPadding * 2) / 2
|
||||
// text: qsTr("Port (TCP)")
|
||||
// }
|
||||
// TextFieldType {
|
||||
// width: parent.width - 130 - parent.spacing - parent.leftPadding * 2
|
||||
// height: (parent.height - parent.spacing - parent.topPadding * 2) / 2
|
||||
// text: NewServerProtocolsLogic.lineEditSsPortText
|
||||
// onEditingFinished: {
|
||||
// NewServerProtocolsLogic.lineEditSsPortText = text
|
||||
// }
|
||||
// }
|
||||
// LabelType {
|
||||
// width: 130
|
||||
// height: (parent.height - parent.spacing - parent.topPadding * 2) / 2
|
||||
// text: qsTr("Encryption")
|
||||
// }
|
||||
// ComboBoxType {
|
||||
// width: parent.width - 130 - parent.spacing - parent.leftPadding * 2
|
||||
// height: (parent.height - parent.spacing - parent.topPadding * 2) / 2
|
||||
// model: [
|
||||
// qsTr("chacha20-ietf-poly1305"),
|
||||
// qsTr("xchacha20-ietf-poly1305"),
|
||||
// qsTr("aes-256-gcm"),
|
||||
// qsTr("aes-192-gcm"),
|
||||
// qsTr("aes-128-gcm")
|
||||
// ]
|
||||
// currentIndex: {
|
||||
// for (let i = 0; i < model.length; ++i) {
|
||||
// if (NewServerProtocolsLogic.comboBoxSsCipherText === model[i]) {
|
||||
// return i
|
||||
// }
|
||||
// }
|
||||
// return -1
|
||||
// }
|
||||
// onCurrentTextChanged: {
|
||||
// NewServerProtocolsLogic.comboBoxSsCipherText = currentText
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// InstallSettingsBase {
|
||||
// containerDescription: qsTr("OpenVPN")
|
||||
// onContainerChecked: NewServerProtocolsLogic.checkBoxOpenVpnChecked = checked
|
||||
|
||||
// LabelType {
|
||||
// width: 130
|
||||
// height: (parent.height - parent.spacing - parent.topPadding * 2) / 2
|
||||
// text: qsTr("Port (TCP/UDP)")
|
||||
// }
|
||||
// TextFieldType {
|
||||
// width: parent.width - 130 - parent.spacing - parent.leftPadding * 2
|
||||
// height: (parent.height - parent.spacing - parent.topPadding * 2) / 2
|
||||
// text: NewServerProtocolsLogic.lineEditOpenvpnPortText
|
||||
// onEditingFinished: {
|
||||
// NewServerProtocolsLogic.lineEditOpenvpnPortText = text
|
||||
// }
|
||||
// }
|
||||
// LabelType {
|
||||
// width: 130
|
||||
// height: (parent.height - parent.spacing - parent.topPadding * 2) / 2
|
||||
// text: qsTr("Protocol")
|
||||
// }
|
||||
// ComboBoxType {
|
||||
// width: parent.width - 130 - parent.spacing - parent.leftPadding * 2
|
||||
// height: (parent.height - parent.spacing - parent.topPadding * 2) / 2
|
||||
// model: [
|
||||
// qsTr("udp"),
|
||||
// qsTr("tcp"),
|
||||
// ]
|
||||
// currentIndex: {
|
||||
// for (let i = 0; i < model.length; ++i) {
|
||||
// if (NewServerProtocolsLogic.comboBoxOpenvpnProtoText === model[i]) {
|
||||
// return i
|
||||
// }
|
||||
// }
|
||||
// return -1
|
||||
// }
|
||||
// onCurrentTextChanged: {
|
||||
// NewServerProtocolsLogic.comboBoxOpenvpnProtoText = currentText
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// InstallSettingsBase {
|
||||
// visible: false
|
||||
// containerDescription: qsTr("WireGuard")
|
||||
// onContainerChecked: NewServerProtocolsLogic.checkBoxWireGuardChecked = checked
|
||||
|
||||
// LabelType {
|
||||
// width: 130
|
||||
// height: (parent.height - parent.spacing - parent.topPadding * 2)
|
||||
// text: qsTr("Port (UDP)")
|
||||
// }
|
||||
// TextFieldType {
|
||||
// width: parent.width - 130 - parent.spacing - parent.leftPadding * 2
|
||||
// height: (parent.height - parent.spacing - parent.topPadding * 2)
|
||||
// text: "32767"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Dialogs 1.1
|
||||
import QtQuick.Layouts 1.15
|
||||
import SortFilterProxyModel 0.2
|
||||
import ContainerProps 1.0
|
||||
|
@ -292,19 +293,30 @@ PageBase {
|
|||
}
|
||||
|
||||
ImageButtonType {
|
||||
id: button_default
|
||||
visible: service_type_role == ProtocolEnum.Vpn
|
||||
|
||||
id: button_remove
|
||||
visible: index === tb_c.currentIndex
|
||||
Layout.alignment: Qt.AlignRight
|
||||
checkable: true
|
||||
img.source: checked ? "qrc:/images/check.png" : "qrc:/images/uncheck.png"
|
||||
icon.source: "qrc:/images/delete.png"
|
||||
implicitWidth: 30
|
||||
implicitHeight: 30
|
||||
|
||||
checked: default_role
|
||||
onClicked: {
|
||||
ServerContainersLogic.onPushButtonDefaultClicked(proxyContainersModel.mapToSource(index))
|
||||
|
||||
MessageDialog {
|
||||
id: dialogRemove
|
||||
standardButtons: StandardButton.Yes | StandardButton.Cancel
|
||||
title: "AmneziaVPN"
|
||||
text: qsTr("Remove container") + " " + name_role + "?" + "\n" + qsTr("This action will erase all data of this container on the server.")
|
||||
onAccepted: {
|
||||
tb_c.currentIndex = -1
|
||||
ServerContainersLogic.onPushButtonRemoveClicked(proxyContainersModel.mapToSource(index))
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: dialogRemove.open()
|
||||
|
||||
VisibleBehavior on visible { }
|
||||
}
|
||||
|
||||
ImageButtonType {
|
||||
|
@ -322,23 +334,20 @@ PageBase {
|
|||
}
|
||||
|
||||
ImageButtonType {
|
||||
id: button_remove
|
||||
visible: index === tb_c.currentIndex
|
||||
id: button_default
|
||||
visible: service_type_role == ProtocolEnum.Vpn
|
||||
|
||||
Layout.alignment: Qt.AlignRight
|
||||
checkable: true
|
||||
icon.source: "qrc:/images/delete.png"
|
||||
img.source: checked ? "qrc:/images/check.png" : "qrc:/images/uncheck.png"
|
||||
implicitWidth: 30
|
||||
implicitHeight: 30
|
||||
|
||||
checked: default_role
|
||||
onClicked: {
|
||||
tb_c.currentIndex = -1
|
||||
ServerContainersLogic.onPushButtonRemoveClicked(proxyContainersModel.mapToSource(index))
|
||||
ServerContainersLogic.onPushButtonDefaultClicked(proxyContainersModel.mapToSource(index))
|
||||
}
|
||||
|
||||
VisibleBehavior on visible { }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -49,7 +49,13 @@ PageBase {
|
|||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
listWidget_servers.currentIndex = index
|
||||
if (GC.isMobile()) {
|
||||
ServerListLogic.onServerListPushbuttonSettingsClicked(index)
|
||||
}
|
||||
else {
|
||||
listWidget_servers.currentIndex = index
|
||||
}
|
||||
|
||||
mouse.accepted = false
|
||||
}
|
||||
onEntered: {
|
||||
|
@ -104,22 +110,11 @@ PageBase {
|
|||
wrapMode: Text.Wrap
|
||||
text: desc
|
||||
}
|
||||
ImageButtonType {
|
||||
x: 212
|
||||
y: 25
|
||||
width: 32
|
||||
height: 24
|
||||
checkable: true
|
||||
iconMargin: 0
|
||||
icon.source: checked ? "qrc:/images/connect_button_connected.png"
|
||||
: "qrc:/images/connect_button_disconnected.png"
|
||||
visible: false
|
||||
}
|
||||
ImageButtonType {
|
||||
x: parent.width - 30
|
||||
y: 25
|
||||
width: 24
|
||||
height: 24
|
||||
y: 15
|
||||
width: 30
|
||||
height: 30
|
||||
checkable: true
|
||||
icon.source: checked ? "qrc:/images/check.png"
|
||||
: "qrc:/images/uncheck.png"
|
||||
|
@ -131,10 +126,10 @@ PageBase {
|
|||
}
|
||||
ImageButtonType {
|
||||
id: pushButtonSetting
|
||||
x: parent.width - 60
|
||||
y: 25
|
||||
width: 24
|
||||
height: 24
|
||||
x: parent.width - 70
|
||||
y: 15
|
||||
width: 30
|
||||
height: 30
|
||||
icon.source: "qrc:/images/settings.png"
|
||||
opacity: 0
|
||||
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Dialogs 1.1
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtGraphicalEffects 1.12
|
||||
import SortFilterProxyModel 0.2
|
||||
import ContainerProps 1.0
|
||||
import ProtocolProps 1.0
|
||||
import PageEnum 1.0
|
||||
import ProtocolEnum 1.0
|
||||
import "./"
|
||||
import "../Controls"
|
||||
import "../Config"
|
||||
|
@ -13,400 +20,69 @@ PageBase {
|
|||
BackButton {
|
||||
id: back
|
||||
}
|
||||
ScrollView {
|
||||
x: 10
|
||||
y: 40
|
||||
width: 360
|
||||
height: 580
|
||||
Item {
|
||||
id: ct
|
||||
width: parent.width
|
||||
height: childrenRect.height + 10
|
||||
property var contentList: [
|
||||
full_access,
|
||||
share_amezia,
|
||||
share_openvpn,
|
||||
share_shadowshock,
|
||||
share_cloak
|
||||
]
|
||||
property int currentIndex: ShareConnectionLogic.toolBoxShareConnectionCurrentIndex
|
||||
onCurrentIndexChanged: {
|
||||
ShareConnectionLogic.toolBoxShareConnectionCurrentIndex = currentIndex
|
||||
for (let i = 0; i < contentList.length; ++i) {
|
||||
if (i == currentIndex) {
|
||||
contentList[i].active = true
|
||||
} else {
|
||||
contentList[i].active = false
|
||||
}
|
||||
|
||||
Caption {
|
||||
id: caption
|
||||
text: qsTr("Share protocol config")
|
||||
width: undefined
|
||||
}
|
||||
|
||||
|
||||
Flickable {
|
||||
clip: true
|
||||
width: parent.width
|
||||
anchors.top: caption.bottom
|
||||
anchors.bottom: root.bottom
|
||||
contentHeight: col.height
|
||||
|
||||
Column {
|
||||
id: col
|
||||
anchors {
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
}
|
||||
topPadding: 20
|
||||
spacing: 10
|
||||
|
||||
SortFilterProxyModel {
|
||||
id: proxyProtocolsModel
|
||||
sourceModel: UiLogic.protocolsModel
|
||||
filters: ValueFilter {
|
||||
roleName: "is_installed_role"
|
||||
value: true
|
||||
}
|
||||
}
|
||||
|
||||
function clearActive() {
|
||||
for (let i = 0; i < contentList.length; ++i) {
|
||||
contentList[i].active = false
|
||||
}
|
||||
currentIndex = -1;
|
||||
|
||||
ShareConnectionContent {
|
||||
x: 10
|
||||
text: qsTr("Share for Amnezia")
|
||||
height: 40
|
||||
width: tb_c.width - 10
|
||||
onClicked: UiLogic.onGotoShareProtocolPage(ProtocolEnum.Any)
|
||||
}
|
||||
Column {
|
||||
spacing: 5
|
||||
ShareConnectionContent {
|
||||
id: full_access
|
||||
x: 0
|
||||
text: qsTr("Full access")
|
||||
visible: ShareConnectionLogic.pageShareFullAccessVisible
|
||||
content: Component {
|
||||
Item {
|
||||
width: 360
|
||||
height: 380
|
||||
Text {
|
||||
x: 10
|
||||
y: 250
|
||||
width: 341
|
||||
height: 111
|
||||
font.family: "Lato"
|
||||
font.styleName: "normal"
|
||||
font.pixelSize: 16
|
||||
color: "#181922"
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
wrapMode: Text.Wrap
|
||||
text: qsTr("Anyone who logs in with this code will have the same permissions to use VPN and your server as you. \nThis code includes your server credentials!\nProvide this code only to TRUSTED users.")
|
||||
}
|
||||
ShareConnectionButtonType {
|
||||
x: 10
|
||||
y: 130
|
||||
width: 341
|
||||
height: 40
|
||||
text: ShareConnectionLogic.pushButtonShareFullCopyText
|
||||
onClicked: {
|
||||
ShareConnectionLogic.onPushButtonShareFullCopyClicked()
|
||||
}
|
||||
}
|
||||
ShareConnectionButtonType {
|
||||
x: 10
|
||||
y: 180
|
||||
width: 341
|
||||
height: 40
|
||||
text: qsTr("Save file")
|
||||
onClicked: {
|
||||
ShareConnectionLogic.onPushButtonShareFullSaveClicked()
|
||||
}
|
||||
}
|
||||
TextFieldType {
|
||||
x: 10
|
||||
y: 10
|
||||
width: 341
|
||||
height: 100
|
||||
verticalAlignment: Text.AlignTop
|
||||
text: ShareConnectionLogic.textEditShareFullCodeText
|
||||
onEditingFinished: {
|
||||
ShareConnectionLogic.textEditShareFullCodeText = text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
onClicked: {
|
||||
if (active) {
|
||||
ct.currentIndex = -1
|
||||
} else {
|
||||
ct.clearActive()
|
||||
ct.currentIndex = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
ShareConnectionContent {
|
||||
id: share_amezia
|
||||
x: 0
|
||||
text: qsTr("Share for Amnezia client")
|
||||
visible: ShareConnectionLogic.pageShareAmneziaVisible
|
||||
content: Component {
|
||||
Item {
|
||||
width: 360
|
||||
height: 380
|
||||
Text {
|
||||
x: 10
|
||||
y: 280
|
||||
width: 341
|
||||
height: 111
|
||||
font.family: "Lato"
|
||||
font.styleName: "normal"
|
||||
font.pixelSize: 16
|
||||
color: "#181922"
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
wrapMode: Text.Wrap
|
||||
text: qsTr("Anyone who logs in with this code will be able to connect to this VPN server. \nThis code does not include server credentials.")
|
||||
}
|
||||
ShareConnectionButtonType {
|
||||
x: 10
|
||||
y: 180
|
||||
width: 341
|
||||
height: 40
|
||||
text: ShareConnectionLogic.pushButtonShareAmneziaCopyText
|
||||
onClicked: {
|
||||
ShareConnectionLogic.onPushButtonShareAmneziaCopyClicked()
|
||||
}
|
||||
enabled: ShareConnectionLogic.pushButtonShareAmneziaCopyEnabled
|
||||
}
|
||||
ShareConnectionButtonType {
|
||||
x: 10
|
||||
y: 130
|
||||
width: 341
|
||||
height: 40
|
||||
text: ShareConnectionLogic.pushButtonShareAmneziaGenerateText
|
||||
enabled: ShareConnectionLogic.pushButtonShareAmneziaGenerateEnabled
|
||||
onClicked: {
|
||||
ShareConnectionLogic.onPushButtonShareAmneziaGenerateClicked()
|
||||
}
|
||||
}
|
||||
ShareConnectionButtonType {
|
||||
x: 10
|
||||
y: 230
|
||||
width: 341
|
||||
height: 40
|
||||
text: qsTr("Save file")
|
||||
onClicked: {
|
||||
ShareConnectionLogic.onPushButtonShareAmneziaSaveClicked()
|
||||
}
|
||||
}
|
||||
TextFieldType {
|
||||
x: 10
|
||||
y: 10
|
||||
width: 341
|
||||
height: 100
|
||||
verticalAlignment: Text.AlignTop
|
||||
text: ShareConnectionLogic.textEditShareAmneziaCodeText
|
||||
onEditingFinished: {
|
||||
ShareConnectionLogic.textEditShareAmneziaCodeText = text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
onClicked: {
|
||||
if (active) {
|
||||
ct.currentIndex = -1
|
||||
} else {
|
||||
ct.clearActive()
|
||||
ct.currentIndex = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
ShareConnectionContent {
|
||||
id: share_openvpn
|
||||
x: 0
|
||||
text: qsTr("Share for OpenVPN client")
|
||||
visible: ShareConnectionLogic.pageShareOpenVpnVisible
|
||||
content: Component {
|
||||
Item {
|
||||
width: 360
|
||||
height: 380
|
||||
ShareConnectionButtonType {
|
||||
x: 10
|
||||
y: 180
|
||||
width: 341
|
||||
height: 40
|
||||
text: ShareConnectionLogic.pushButtonShareOpenVpnCopyText
|
||||
enabled: ShareConnectionLogic.pushButtonShareOpenVpnCopyEnabled
|
||||
onClicked: {
|
||||
ShareConnectionLogic.onPushButtonShareOpenVpnCopyClicked()
|
||||
}
|
||||
}
|
||||
ShareConnectionButtonType {
|
||||
x: 10
|
||||
y: 130
|
||||
width: 341
|
||||
height: 40
|
||||
text: ShareConnectionLogic.pushButtonShareOpenVpnGenerateText
|
||||
onClicked: {
|
||||
ShareConnectionLogic.onPushButtonShareOpenVpnGenerateClicked()
|
||||
}
|
||||
enabled: ShareConnectionLogic.pushButtonShareOpenVpnGenerateEnabled
|
||||
}
|
||||
ShareConnectionButtonType {
|
||||
x: 10
|
||||
y: 230
|
||||
width: 341
|
||||
height: 40
|
||||
text: qsTr("Save file")
|
||||
enabled: ShareConnectionLogic.pushButtonShareOpenVpnSaveEnabled
|
||||
onClicked: {
|
||||
ShareConnectionLogic.onPushButtonShareOpenVpnSaveClicked()
|
||||
}
|
||||
}
|
||||
TextFieldType {
|
||||
x: 10
|
||||
y: 10
|
||||
width: 341
|
||||
height: 100
|
||||
verticalAlignment: Text.AlignTop
|
||||
text: ShareConnectionLogic.textEditShareOpenVpnCodeText
|
||||
onEditingFinished: {
|
||||
ShareConnectionLogic.textEditShareOpenVpnCodeText = text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
onClicked: {
|
||||
if (active) {
|
||||
ct.currentIndex = -1
|
||||
} else {
|
||||
ct.clearActive()
|
||||
ct.currentIndex = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
ShareConnectionContent {
|
||||
id: share_shadowshock
|
||||
x: 0
|
||||
text: qsTr("Share for ShadowSocks client")
|
||||
visible: ShareConnectionLogic.pageShareShadowSocksVisible
|
||||
content: Component {
|
||||
Item {
|
||||
width: 360
|
||||
height: 380
|
||||
LabelType {
|
||||
x: 10
|
||||
y: 70
|
||||
width: 100
|
||||
height: 20
|
||||
text: qsTr("Password")
|
||||
}
|
||||
LabelType {
|
||||
x: 10
|
||||
y: 10
|
||||
width: 100
|
||||
height: 20
|
||||
text: qsTr("Server:")
|
||||
}
|
||||
LabelType {
|
||||
x: 10
|
||||
y: 50
|
||||
width: 100
|
||||
height: 20
|
||||
text: qsTr("Encryption:")
|
||||
}
|
||||
LabelType {
|
||||
x: 10
|
||||
y: 30
|
||||
width: 100
|
||||
height: 20
|
||||
text: qsTr("Port:")
|
||||
}
|
||||
LabelType {
|
||||
x: 10
|
||||
y: 100
|
||||
width: 191
|
||||
height: 20
|
||||
text: qsTr("Connection string")
|
||||
}
|
||||
LabelType {
|
||||
x: 130
|
||||
y: 70
|
||||
width: 100
|
||||
height: 20
|
||||
text: ShareConnectionLogic.labelShareShadowSocksPasswordText
|
||||
}
|
||||
LabelType {
|
||||
x: 130
|
||||
y: 10
|
||||
width: 100
|
||||
height: 20
|
||||
text: ShareConnectionLogic.labelShareShadowSocksServerText
|
||||
}
|
||||
LabelType {
|
||||
x: 130
|
||||
y: 50
|
||||
width: 100
|
||||
height: 20
|
||||
text: ShareConnectionLogic.labelShareShadowSocksMethodText
|
||||
}
|
||||
LabelType {
|
||||
x: 130
|
||||
y: 30
|
||||
width: 100
|
||||
height: 20
|
||||
text: ShareConnectionLogic.labelShareShadowSocksPortText
|
||||
}
|
||||
Image {
|
||||
id: label_share_ss_qr_code
|
||||
x: 85
|
||||
y: 235
|
||||
width: 200
|
||||
height: 200
|
||||
source: ShareConnectionLogic.labelShareShadowSocksQrCodeText === "" ? "" : "data:image/png;base64," + UiLogic.labelShareShadowSocksQrCodeText
|
||||
}
|
||||
ShareConnectionButtonType {
|
||||
x: 10
|
||||
y: 180
|
||||
width: 331
|
||||
height: 40
|
||||
text: ShareConnectionLogic.pushButtonShareShadowSocksCopyText
|
||||
enabled: ShareConnectionLogic.pushButtonShareShadowSocksCopyEnabled
|
||||
onClicked: {
|
||||
ShareConnectionLogic.onPushButtonShareShadowSocksCopyClicked()
|
||||
}
|
||||
}
|
||||
TextFieldType {
|
||||
x: 10
|
||||
y: 130
|
||||
width: 331
|
||||
height: 100
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: ShareConnectionLogic.lineEditShareShadowSocksStringText
|
||||
onEditingFinished: {
|
||||
ShareConnectionLogic.lineEditShareShadowSocksStringText = text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
onClicked: {
|
||||
if (active) {
|
||||
ct.currentIndex = -1
|
||||
} else {
|
||||
ct.clearActive()
|
||||
ct.currentIndex = 3
|
||||
}
|
||||
}
|
||||
}
|
||||
ShareConnectionContent {
|
||||
id: share_cloak
|
||||
x: 0
|
||||
text: qsTr("Share for Cloak client")
|
||||
visible: ShareConnectionLogic.pageShareCloakVisible
|
||||
content: Component {
|
||||
Item {
|
||||
width: 360
|
||||
height: 380
|
||||
ShareConnectionButtonType {
|
||||
x: 10
|
||||
y: 290
|
||||
width: 331
|
||||
height: 40
|
||||
text: ShareConnectionLogic.pushButtonShareCloakCopyText
|
||||
enabled: ShareConnectionLogic.pushButtonShareCloakCopyEnabled
|
||||
onClicked: {
|
||||
ShareConnectionLogic.onPushButtonShareCloakCopyClicked()
|
||||
}
|
||||
}
|
||||
TextInput {
|
||||
x: 10
|
||||
y: 30
|
||||
width: 331
|
||||
height: 100
|
||||
text: ShareConnectionLogic.plainTextEditShareCloakText
|
||||
onEditingFinished: {
|
||||
ShareConnectionLogic.plainTextEditShareCloakText = text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
onClicked: {
|
||||
if (active) {
|
||||
ct.currentIndex = -1
|
||||
} else {
|
||||
ct.clearActive()
|
||||
ct.currentIndex = 4
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: tb_c
|
||||
x: 10
|
||||
width: parent.width - 10
|
||||
height: tb_c.contentItem.height
|
||||
currentIndex: -1
|
||||
spacing: 10
|
||||
clip: true
|
||||
interactive: false
|
||||
model: proxyProtocolsModel
|
||||
|
||||
delegate: Item {
|
||||
implicitWidth: tb_c.width - 10
|
||||
implicitHeight: c_item.height
|
||||
|
||||
ShareConnectionContent {
|
||||
id: c_item
|
||||
text: qsTr("Share for ") + name_role
|
||||
height: 40
|
||||
width: tb_c.width - 10
|
||||
onClicked: UiLogic.onGotoShareProtocolPage(proxyProtocolsModel.mapToSource(index))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,36 +15,30 @@ PageBase {
|
|||
BackButton {
|
||||
id: back
|
||||
}
|
||||
Text {
|
||||
font.family: "Lato"
|
||||
font.styleName: "normal"
|
||||
font.pixelSize: 16
|
||||
|
||||
Caption {
|
||||
id: caption
|
||||
text: SitesLogic.labelSitesAddCustomText
|
||||
}
|
||||
|
||||
LabelType {
|
||||
id: lb_addr
|
||||
color: "#333333"
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
text: qsTr("Web site/Hostname/IP address/Subnet")
|
||||
x: 20
|
||||
y: 110
|
||||
width: 311
|
||||
anchors.top: caption.bottom
|
||||
anchors.topMargin: 10
|
||||
width: parent.width
|
||||
height: 21
|
||||
}
|
||||
Text {
|
||||
font.family: "Lato"
|
||||
font.styleName: "normal"
|
||||
font.pixelSize: 20
|
||||
color: "#100A44"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignTop
|
||||
text: SitesLogic.labelSitesAddCustomText
|
||||
x: 20
|
||||
y: 40
|
||||
width: 340
|
||||
height: 60
|
||||
}
|
||||
|
||||
TextFieldType {
|
||||
x: 20
|
||||
y: 140
|
||||
width: 231
|
||||
anchors.top: lb_addr.bottom
|
||||
anchors.topMargin: 10
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 20
|
||||
anchors.right: sites_add.left
|
||||
anchors.rightMargin: 10
|
||||
height: 31
|
||||
placeholderText: qsTr("yousite.com or IP address")
|
||||
text: SitesLogic.lineEditSitesAddCustomText
|
||||
|
@ -55,10 +49,13 @@ PageBase {
|
|||
SitesLogic.onPushButtonAddCustomSitesClicked()
|
||||
}
|
||||
}
|
||||
|
||||
BlueButtonType {
|
||||
id: sites_add
|
||||
x: 260
|
||||
y: 140
|
||||
anchors.right: sites_import.left
|
||||
anchors.rightMargin: 10
|
||||
anchors.top: lb_addr.bottom
|
||||
anchors.topMargin: 10
|
||||
width: 51
|
||||
height: 31
|
||||
font.pixelSize: 24
|
||||
|
@ -67,23 +64,13 @@ PageBase {
|
|||
SitesLogic.onPushButtonAddCustomSitesClicked()
|
||||
}
|
||||
}
|
||||
BlueButtonType {
|
||||
id: sites_delete
|
||||
x: 80
|
||||
y: 589
|
||||
width: 231
|
||||
height: 31
|
||||
font.pixelSize: 16
|
||||
text: qsTr("Delete selected")
|
||||
onClicked: {
|
||||
SitesLogic.onPushButtonSitesDeleteClicked(tb.currentRow)
|
||||
}
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: sites_import
|
||||
x: 320
|
||||
y: 140
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 20
|
||||
anchors.top: lb_addr.bottom
|
||||
anchors.topMargin: 10
|
||||
width: 51
|
||||
height: 31
|
||||
background: Rectangle {
|
||||
|
@ -116,12 +103,15 @@ PageBase {
|
|||
SitesLogic.onPushButtonSitesImportClicked(fileUrl)
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: tb
|
||||
x: 20
|
||||
y: 200
|
||||
width: 341
|
||||
height: 371
|
||||
anchors.top: sites_add.bottom
|
||||
anchors.topMargin: 10
|
||||
width: parent.width - 40
|
||||
anchors.bottom: sites_delete.top
|
||||
anchors.bottomMargin: 10
|
||||
spacing: 1
|
||||
clip: true
|
||||
property int currentRow: -1
|
||||
|
@ -187,4 +177,17 @@ PageBase {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
BlueButtonType {
|
||||
id: sites_delete
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 20
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
height: 31
|
||||
font.pixelSize: 16
|
||||
text: qsTr("Delete selected")
|
||||
onClicked: {
|
||||
SitesLogic.onPushButtonSitesDeleteClicked(tb.currentRow)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ PageBase {
|
|||
anchors.top: parent.top
|
||||
anchors.topMargin: 5
|
||||
|
||||
text: qsTr("Where to get connection data →")
|
||||
text: qsTr("How to get own server? →")
|
||||
background: Item {
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ PageBase {
|
|||
checkable: true
|
||||
checked: true
|
||||
onClicked: {
|
||||
Qt.openUrlExternally("https://amnezia.org")
|
||||
Qt.openUrlExternally("https://amnezia.org/instruction.html")
|
||||
}
|
||||
}
|
||||
LabelType {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.15
|
||||
import PageEnum 1.0
|
||||
import "./"
|
||||
import "../Controls"
|
||||
|
@ -11,12 +12,11 @@ PageBase {
|
|||
logic: VpnLogic
|
||||
|
||||
Image {
|
||||
id: bg_top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
y: 0
|
||||
width: parent.width
|
||||
|
||||
// width: 380
|
||||
// height: 325
|
||||
height: parent.height * 0.28
|
||||
source: "qrc:/images/background_connected.png"
|
||||
}
|
||||
|
||||
|
@ -31,38 +31,26 @@ PageBase {
|
|||
}
|
||||
}
|
||||
|
||||
LabelType {
|
||||
id: error_text
|
||||
x: 0
|
||||
y: 280
|
||||
width: 381
|
||||
height: 61
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
wrapMode: Text.Wrap
|
||||
text: VpnLogic.labelErrorText
|
||||
}
|
||||
Text {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
y: 250
|
||||
width: 380
|
||||
height: 31
|
||||
font.family: "Lato"
|
||||
font.styleName: "normal"
|
||||
font.pixelSize: 15
|
||||
color: "#181922"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
wrapMode: Text.Wrap
|
||||
text: VpnLogic.labelStateText
|
||||
AnimatedImage {
|
||||
id: connect_anim
|
||||
source: "qrc:/images/animation.gif"
|
||||
anchors.top: bg_top.bottom
|
||||
anchors.topMargin: 10
|
||||
anchors.horizontalCenter: root.horizontalCenter
|
||||
width: Math.min(parent.width, parent.height) / 4
|
||||
height: width
|
||||
|
||||
visible: !VpnLogic.pushButtonConnectVisible
|
||||
paused: VpnLogic.pushButtonConnectVisible
|
||||
//VisibleBehavior on visible { }
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: button_connect
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
y: 200
|
||||
width: 80
|
||||
height: 40
|
||||
anchors.horizontalCenter: connect_anim.horizontalCenter
|
||||
anchors.verticalCenter: connect_anim.verticalCenter
|
||||
width: connect_anim.width
|
||||
height: width
|
||||
checkable: true
|
||||
checked: VpnLogic.pushButtonConnectChecked
|
||||
onCheckedChanged: {
|
||||
|
@ -71,18 +59,102 @@ PageBase {
|
|||
}
|
||||
background: Image {
|
||||
anchors.fill: parent
|
||||
source: button_connect.checked ? "qrc:/images/connect_button_connected.png"
|
||||
: "qrc:/images/connect_button_disconnected.png"
|
||||
source: button_connect.checked ? "qrc:/images/connected.png"
|
||||
: "qrc:/images/disconnected.png"
|
||||
}
|
||||
contentItem: Item {}
|
||||
antialiasing: true
|
||||
enabled: VpnLogic.pushButtonConnectEnabled
|
||||
opacity: VpnLogic.pushButtonConnectVisible ? 1 : 0
|
||||
|
||||
// transitions: Transition {
|
||||
// NumberAnimation { properties: "opacity"; easing.type: Easing.InOutQuad; duration: 500 }
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
LabelType {
|
||||
id: lb_state
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: button_connect.bottom
|
||||
width: parent.width
|
||||
height: 21
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: VpnLogic.labelStateText
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: layout1
|
||||
anchors.top: lb_state.bottom
|
||||
//anchors.topMargin: 5
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
height: 21
|
||||
|
||||
|
||||
LabelType {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
height: 21
|
||||
text: qsTr("Server") + ": "
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
height: 21
|
||||
background: Item {}
|
||||
text: VpnLogic.labelCurrentServer
|
||||
font.family: "Lato"
|
||||
font.styleName: "normal"
|
||||
font.pixelSize: 16
|
||||
onClicked: {
|
||||
UiLogic.goToPage(PageEnum.ServersList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: layout2
|
||||
anchors.top: layout1.bottom
|
||||
anchors.topMargin: 5
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
height: 21
|
||||
|
||||
|
||||
LabelType {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
height: 21
|
||||
text: qsTr("Service") + ": "
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
height: 21
|
||||
background: Item {}
|
||||
text: VpnLogic.labelCurrentService
|
||||
font.family: "Lato"
|
||||
font.styleName: "normal"
|
||||
font.pixelSize: 16
|
||||
onClicked: {
|
||||
UiLogic.onGotoCurrentProtocolsPage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LabelType {
|
||||
id: error_text
|
||||
anchors.top: layout2.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: parent.width
|
||||
height: 21
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.Wrap
|
||||
text: VpnLogic.labelErrorText
|
||||
}
|
||||
|
||||
Item {
|
||||
x: 0
|
||||
anchors.bottom: line.top
|
||||
anchors.bottomMargin: 10
|
||||
anchors.bottomMargin: GC.isMobile() ? 0 :10
|
||||
width: parent.width
|
||||
height: 51
|
||||
Image {
|
||||
|
@ -136,7 +208,7 @@ PageBase {
|
|||
x: 20
|
||||
width: parent.width - 40
|
||||
height: 1
|
||||
anchors.bottom: conn_type_label.top
|
||||
anchors.bottom: GC.isMobile() ? root.bottom : conn_type_label.top
|
||||
anchors.bottomMargin: 10
|
||||
color: "#DDDDDD"
|
||||
}
|
||||
|
@ -146,7 +218,7 @@ PageBase {
|
|||
visible: !GC.isMobile()
|
||||
x: 20
|
||||
anchors.bottom: conn_type_group.top
|
||||
anchors.bottomMargin: 10
|
||||
anchors.bottomMargin: GC.isMobile() ? 0 :10
|
||||
width: 281
|
||||
height: GC.isMobile() ? 0: 21
|
||||
font.family: "Lato"
|
||||
|
@ -208,11 +280,11 @@ PageBase {
|
|||
|
||||
BasicButtonType {
|
||||
id: button_add_site
|
||||
visible: !GC.isMobile()
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
y: parent.height - 60
|
||||
//anchors.bottom: parent.bottom
|
||||
width: parent.width - 40
|
||||
height: 40
|
||||
height: GC.isMobile() ? 0: 40
|
||||
text: qsTr("+ Add site")
|
||||
enabled: VpnLogic.pushButtonVpnAddSiteEnabled
|
||||
background: Rectangle {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.15
|
||||
import ProtocolEnum 1.0
|
||||
import "../"
|
||||
import "../../Controls"
|
||||
|
@ -10,144 +11,155 @@ PageProtocolBase {
|
|||
protocol: ProtocolEnum.Cloak
|
||||
logic: UiLogic.protocolLogic(protocol)
|
||||
|
||||
enabled: logic.pageProtoCloakEnabled
|
||||
enabled: logic.pageEnabled
|
||||
BackButton {
|
||||
id: back
|
||||
}
|
||||
Item {
|
||||
x: 0
|
||||
y: 40
|
||||
width: 380
|
||||
height: 600
|
||||
|
||||
Caption {
|
||||
id: caption
|
||||
text: qsTr("Cloak Settings")
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: content
|
||||
enabled: logic.pageEnabled
|
||||
ComboBoxType {
|
||||
x: 190
|
||||
y: 60
|
||||
width: 151
|
||||
height: 31
|
||||
model: [
|
||||
qsTr("chacha20-poly1305"),
|
||||
qsTr("aes-256-gcm"),
|
||||
qsTr("aes-192-gcm"),
|
||||
qsTr("aes-128-gcm")
|
||||
]
|
||||
currentIndex: {
|
||||
for (let i = 0; i < model.length; ++i) {
|
||||
if (logic.comboBoxProtoCloakCipherText === model[i]) {
|
||||
return i
|
||||
anchors.top: caption.bottom
|
||||
anchors.left: root.left
|
||||
anchors.right: root.right
|
||||
anchors.bottom: pb_save.top
|
||||
anchors.margins: 20
|
||||
anchors.topMargin: 10
|
||||
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
LabelType {
|
||||
height: 31
|
||||
text: qsTr("Cipher")
|
||||
Layout.preferredWidth: 0.3 * root.width - 10
|
||||
}
|
||||
|
||||
ComboBoxType {
|
||||
Layout.fillWidth: true
|
||||
height: 31
|
||||
model: [
|
||||
qsTr("chacha20-poly1305"),
|
||||
qsTr("aes-256-gcm"),
|
||||
qsTr("aes-192-gcm"),
|
||||
qsTr("aes-128-gcm")
|
||||
]
|
||||
currentIndex: {
|
||||
for (let i = 0; i < model.length; ++i) {
|
||||
if (logic.comboBoxCipherText === model[i]) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
return -1
|
||||
}
|
||||
onCurrentTextChanged: {
|
||||
logic.comboBoxProtoCloakCipherText = currentText
|
||||
}
|
||||
}
|
||||
LabelType {
|
||||
x: 30
|
||||
y: 60
|
||||
width: 151
|
||||
height: 31
|
||||
text: qsTr("Cipher")
|
||||
}
|
||||
LabelType {
|
||||
x: 30
|
||||
y: 160
|
||||
width: 151
|
||||
height: 31
|
||||
text: qsTr("Port")
|
||||
}
|
||||
Text {
|
||||
font.family: "Lato"
|
||||
font.styleName: "normal"
|
||||
font.pixelSize: 24
|
||||
color: "#100A44"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
text: qsTr("Cloak Settings")
|
||||
x: 20
|
||||
y: 0
|
||||
width: 340
|
||||
height: 30
|
||||
}
|
||||
LabelType {
|
||||
x: 30
|
||||
y: 110
|
||||
width: 151
|
||||
height: 31
|
||||
text: qsTr("Fake Web Site")
|
||||
}
|
||||
|
||||
LabelType {
|
||||
id: label_proto_cloak_info
|
||||
x: 30
|
||||
y: 550
|
||||
width: 321
|
||||
height: 41
|
||||
visible: logic.labelProtoCloakInfoVisible
|
||||
text: logic.labelProtoCloakInfoText
|
||||
}
|
||||
TextFieldType {
|
||||
id: lineEdit_proto_cloak_port
|
||||
x: 190
|
||||
y: 160
|
||||
width: 151
|
||||
height: 31
|
||||
text: logic.lineEditProtoCloakPortText
|
||||
onEditingFinished: {
|
||||
logic.lineEditProtoCloakPortText = text
|
||||
}
|
||||
enabled: logic.lineEditProtoCloakPortEnabled
|
||||
}
|
||||
TextFieldType {
|
||||
id: lineEdit_proto_cloak_site
|
||||
x: 190
|
||||
y: 110
|
||||
width: 151
|
||||
height: 31
|
||||
text: logic.lineEditProtoCloakSiteText
|
||||
onEditingFinished: {
|
||||
logic.lineEditProtoCloakSiteText = text
|
||||
}
|
||||
}
|
||||
ProgressBar {
|
||||
id: progressBar_proto_cloak_reset
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
y: 500
|
||||
width: 321
|
||||
height: 40
|
||||
from: 0
|
||||
to: logic.progressBarProtoCloakResetMaximium
|
||||
value: logic.progressBarProtoCloakResetValue
|
||||
background: Rectangle {
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: parent.height
|
||||
color: "#100A44"
|
||||
radius: 4
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: parent.height
|
||||
Rectangle {
|
||||
width: progressBar_proto_cloak_reset.visualPosition * parent.width
|
||||
height: parent.height
|
||||
radius: 4
|
||||
color: Qt.rgba(255, 255, 255, 0.15);
|
||||
onCurrentTextChanged: {
|
||||
logic.comboBoxCipherText = currentText
|
||||
}
|
||||
}
|
||||
visible: logic.progressBarProtoCloakResetVisible
|
||||
}
|
||||
BlueButtonType {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
y: 500
|
||||
width: 321
|
||||
height: 40
|
||||
text: qsTr("Save and restart VPN")
|
||||
visible: logic.pushButtonCloakSaveVisible
|
||||
onClicked: {
|
||||
logic.onPushButtonProtoCloakSaveClicked()
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
LabelType {
|
||||
Layout.preferredWidth: 0.3 * root.width - 10
|
||||
height: 31
|
||||
text: qsTr("Fake Web Site")
|
||||
}
|
||||
|
||||
TextFieldType {
|
||||
id: lineEdit_proto_cloak_site
|
||||
Layout.fillWidth: true
|
||||
height: 31
|
||||
text: logic.lineEditSiteText
|
||||
onEditingFinished: {
|
||||
logic.lineEditSiteText = text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
LabelType {
|
||||
Layout.preferredWidth: 0.3 * root.width - 10
|
||||
height: 31
|
||||
text: qsTr("Port")
|
||||
}
|
||||
|
||||
TextFieldType {
|
||||
id: lineEdit_proto_cloak_port
|
||||
Layout.fillWidth: true
|
||||
height: 31
|
||||
text: logic.lineEditPortText
|
||||
onEditingFinished: {
|
||||
logic.lineEditPortText = text
|
||||
}
|
||||
enabled: logic.lineEditPortEnabled
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
}
|
||||
|
||||
LabelType {
|
||||
id: label_proto_cloak_info
|
||||
x: 30
|
||||
anchors.bottom: pb_save.top
|
||||
anchors.bottomMargin: 10
|
||||
width: parent.width - 40
|
||||
visible: logic.labelInfoVisible
|
||||
text: logic.labelInfoText
|
||||
}
|
||||
|
||||
|
||||
ProgressBar {
|
||||
id: progressBar_proto_cloak_reset
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.fill: pb_save
|
||||
from: 0
|
||||
to: logic.progressBarResetMaximium
|
||||
value: logic.progressBarResetValue
|
||||
background: Rectangle {
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: parent.height
|
||||
color: "#100A44"
|
||||
radius: 4
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: parent.height
|
||||
Rectangle {
|
||||
width: progressBar_proto_cloak_reset.visualPosition * parent.width
|
||||
height: parent.height
|
||||
radius: 4
|
||||
color: Qt.rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
}
|
||||
visible: logic.progressBarResetVisible
|
||||
}
|
||||
BlueButtonType {
|
||||
id: pb_save
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
enabled: logic.pageEnabled
|
||||
anchors.bottom: root.bottom
|
||||
anchors.bottomMargin: 20
|
||||
width: root.width - 60
|
||||
height: 40
|
||||
text: qsTr("Save and restart VPN")
|
||||
visible: logic.pushButtonSaveVisible
|
||||
onClicked: {
|
||||
logic.onPushButtonSaveClicked()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -338,9 +338,6 @@ PageProtocolBase {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
LabelType {
|
||||
id: label_proto_openvpn_info
|
||||
|
||||
|
@ -349,8 +346,6 @@ PageProtocolBase {
|
|||
text: logic.labelProtoOpenVpnInfoText
|
||||
}
|
||||
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: it_save
|
||||
implicitWidth: parent.width
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.15
|
||||
import ProtocolEnum 1.0
|
||||
import "../"
|
||||
import "../../Controls"
|
||||
|
@ -10,123 +11,136 @@ PageProtocolBase {
|
|||
protocol: ProtocolEnum.ShadowSocks
|
||||
logic: UiLogic.protocolLogic(protocol)
|
||||
|
||||
enabled: logic.pageProtoShadowSocksEnabled
|
||||
enabled: logic.pageEnabled
|
||||
BackButton {
|
||||
id: back
|
||||
}
|
||||
Item {
|
||||
x: 0
|
||||
y: 40
|
||||
width: 380
|
||||
height: 600
|
||||
|
||||
Caption {
|
||||
id: caption
|
||||
text: qsTr("ShadowSocks Settings")
|
||||
}
|
||||
|
||||
|
||||
ColumnLayout {
|
||||
id: content
|
||||
enabled: logic.pageEnabled
|
||||
ComboBoxType {
|
||||
x: 190
|
||||
y: 60
|
||||
width: 151
|
||||
height: 31
|
||||
model: [
|
||||
qsTr("chacha20-ietf-poly1305"),
|
||||
qsTr("xchacha20-ietf-poly1305"),
|
||||
qsTr("aes-256-gcm"),
|
||||
qsTr("aes-192-gcm"),
|
||||
qsTr("aes-128-gcm")
|
||||
]
|
||||
currentIndex: {
|
||||
for (let i = 0; i < model.length; ++i) {
|
||||
if (logic.comboBoxProtoShadowSocksCipherText === model[i]) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
}
|
||||
LabelType {
|
||||
x: 30
|
||||
y: 60
|
||||
width: 151
|
||||
height: 31
|
||||
text: qsTr("Cipher")
|
||||
}
|
||||
LabelType {
|
||||
x: 30
|
||||
y: 110
|
||||
width: 151
|
||||
height: 31
|
||||
text: qsTr("Port")
|
||||
}
|
||||
Text {
|
||||
font.family: "Lato"
|
||||
font.styleName: "normal"
|
||||
font.pixelSize: 24
|
||||
color: "#100A44"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
text: qsTr("ShadowSocks Settings")
|
||||
x: 30
|
||||
y: 0
|
||||
width: 340
|
||||
height: 30
|
||||
}
|
||||
LabelType {
|
||||
id: label_proto_shadowsocks_info
|
||||
x: 30
|
||||
y: 550
|
||||
width: 321
|
||||
height: 41
|
||||
visible: logic.labelProtoShadowSocksInfoVisible
|
||||
text: logic.labelProtoShadowSocksInfoText
|
||||
}
|
||||
TextFieldType {
|
||||
id: lineEdit_proto_shadowsocks_port
|
||||
x: 190
|
||||
y: 110
|
||||
width: 151
|
||||
height: 31
|
||||
text: logic.lineEditProtoShadowSocksPortText
|
||||
onEditingFinished: {
|
||||
logic.lineEditProtoShadowSocksPortText = text
|
||||
}
|
||||
enabled: logic.lineEditProtoShadowSocksPortEnabled
|
||||
}
|
||||
ProgressBar {
|
||||
id: progressBar_proto_shadowsocks_reset
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
y: 500
|
||||
width: 321
|
||||
height: 40
|
||||
from: 0
|
||||
to: logic.progressBarProtoShadowSocksResetMaximium
|
||||
value: logic.progressBarProtoShadowSocksResetValue
|
||||
visible: logic.progressBarProtoShadowSocksResetVisible
|
||||
background: Rectangle {
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: parent.height
|
||||
color: "#100A44"
|
||||
radius: 4
|
||||
anchors.top: caption.bottom
|
||||
anchors.left: root.left
|
||||
anchors.right: root.right
|
||||
anchors.bottom: pb_save.top
|
||||
anchors.margins: 20
|
||||
anchors.topMargin: 10
|
||||
|
||||
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
LabelType {
|
||||
height: 31
|
||||
text: qsTr("Cipher")
|
||||
Layout.preferredWidth: 0.3 * root.width - 10
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: parent.height
|
||||
Rectangle {
|
||||
width: progressBar_proto_shadowsocks_reset.visualPosition * parent.width
|
||||
height: parent.height
|
||||
radius: 4
|
||||
color: Qt.rgba(255, 255, 255, 0.15);
|
||||
ComboBoxType {
|
||||
height: 31
|
||||
Layout.fillWidth: true
|
||||
|
||||
model: [
|
||||
qsTr("chacha20-ietf-poly1305"),
|
||||
qsTr("xchacha20-ietf-poly1305"),
|
||||
qsTr("aes-256-gcm"),
|
||||
qsTr("aes-192-gcm"),
|
||||
qsTr("aes-128-gcm")
|
||||
]
|
||||
currentIndex: {
|
||||
for (let i = 0; i < model.length; ++i) {
|
||||
if (logic.comboBoxCipherText === model[i]) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
}
|
||||
}
|
||||
BlueButtonType {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
y: 500
|
||||
width: 321
|
||||
height: 40
|
||||
text: qsTr("Save and restart VPN")
|
||||
visible: logic.pushButtonShadowSocksSaveVisible
|
||||
onClicked: {
|
||||
logic.onPushButtonProtoShadowSocksSaveClicked()
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
LabelType {
|
||||
Layout.preferredWidth: 0.3 * root.width - 10
|
||||
height: 31
|
||||
text: qsTr("Port")
|
||||
}
|
||||
|
||||
TextFieldType {
|
||||
id: lineEdit_proto_shadowsocks_port
|
||||
Layout.fillWidth: true
|
||||
height: 31
|
||||
text: logic.lineEditPortText
|
||||
onEditingFinished: {
|
||||
logic.lineEditPortText = text
|
||||
}
|
||||
enabled: logic.lineEditPortEnabled
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LabelType {
|
||||
id: label_proto_shadowsocks_info
|
||||
x: 30
|
||||
anchors.bottom: pb_save.top
|
||||
anchors.bottomMargin: 10
|
||||
width: parent.width - 40
|
||||
height: 41
|
||||
visible: logic.labelInfoVisible
|
||||
text: logic.labelInfoText
|
||||
}
|
||||
|
||||
ProgressBar {
|
||||
id: progressBar_reset
|
||||
anchors.fill: pb_save
|
||||
from: 0
|
||||
to: logic.progressBaResetMaximium
|
||||
value: logic.progressBaResetValue
|
||||
visible: logic.progressBaResetVisible
|
||||
background: Rectangle {
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: parent.height
|
||||
color: "#100A44"
|
||||
radius: 4
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: parent.height
|
||||
Rectangle {
|
||||
width: progressBar_reset.visualPosition * parent.width
|
||||
height: parent.height
|
||||
radius: 4
|
||||
color: Qt.rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BlueButtonType {
|
||||
id: pb_save
|
||||
enabled: logic.pageEnabled
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: root.bottom
|
||||
anchors.bottomMargin: 20
|
||||
width: root.width - 60
|
||||
height: 40
|
||||
text: qsTr("Save and restart VPN")
|
||||
visible: logic.pushButtonSaveVisible
|
||||
onClicked: {
|
||||
logic.onPushButtonSaveClicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
133
client/ui/qml/Pages/Share/PageShareProtoAmnezia.qml
Normal file
133
client/ui/qml/Pages/Share/PageShareProtoAmnezia.qml
Normal file
|
@ -0,0 +1,133 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.15
|
||||
import ProtocolEnum 1.0
|
||||
import "../"
|
||||
import "../../Controls"
|
||||
import "../../Config"
|
||||
|
||||
PageShareProtocolBase {
|
||||
id: root
|
||||
protocol: ProtocolEnum.Any
|
||||
|
||||
BackButton {
|
||||
id: back
|
||||
}
|
||||
Caption {
|
||||
id: caption
|
||||
text: qsTr("Share for Amnezia")
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: fl
|
||||
width: root.width
|
||||
anchors.top: caption.bottom
|
||||
anchors.topMargin: 20
|
||||
anchors.bottom: root.bottom
|
||||
anchors.bottomMargin: 20
|
||||
anchors.left: root.left
|
||||
anchors.leftMargin: 30
|
||||
anchors.right: root.right
|
||||
anchors.rightMargin: 30
|
||||
|
||||
contentHeight: content.height + 20
|
||||
clip: true
|
||||
|
||||
ColumnLayout {
|
||||
id: content
|
||||
enabled: logic.pageEnabled
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Text {
|
||||
id: lb_desc
|
||||
Layout.fillWidth: true
|
||||
font.family: "Lato"
|
||||
font.styleName: "normal"
|
||||
font.pixelSize: 16
|
||||
color: "#181922"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
wrapMode: Text.Wrap
|
||||
text: ShareConnectionLogic.shareFullAccess
|
||||
? qsTr("Anyone who logs in with this code will have the same permissions to use VPN and YOUR SERVER as you. \n
|
||||
This code includes your server credentials!\n
|
||||
Provide this code only to TRUSTED users.")
|
||||
: qsTr("Anyone who logs in with this code will be able to connect to this VPN server. \n
|
||||
This code does not include server credentials.\n
|
||||
New encryption keys pair will be generated.")
|
||||
}
|
||||
|
||||
ShareConnectionButtonType {
|
||||
Layout.topMargin: 20
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
|
||||
text: ShareConnectionLogic.shareFullAccess
|
||||
? showConfigText
|
||||
: (genConfigProcess ? generatingConfigText : generateConfigText)
|
||||
onClicked: {
|
||||
enabled = false
|
||||
genConfigProcess = true
|
||||
ShareConnectionLogic.onPushButtonShareAmneziaGenerateClicked()
|
||||
enabled = true
|
||||
genConfigProcess = false
|
||||
}
|
||||
}
|
||||
|
||||
TextAreaType {
|
||||
id: tfShareCode
|
||||
|
||||
Layout.topMargin: 20
|
||||
Layout.bottomMargin: 20
|
||||
Layout.preferredHeight: 200
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
textArea.readOnly: true
|
||||
textArea.wrapMode: TextEdit.WrapAnywhere
|
||||
textArea.verticalAlignment: Text.AlignTop
|
||||
textArea.text: ShareConnectionLogic.textEditShareAmneziaCodeText
|
||||
|
||||
visible: tfShareCode.textArea.length > 0
|
||||
}
|
||||
|
||||
|
||||
ShareConnectionButtonCopyType {
|
||||
Layout.bottomMargin: 10
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
copyText: tfShareCode.textArea.text
|
||||
}
|
||||
ShareConnectionButtonType {
|
||||
Layout.bottomMargin: 10
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
text: qsTr("Save to file")
|
||||
enabled: tfShareCode.textArea.length > 0
|
||||
visible: tfShareCode.textArea.length > 0
|
||||
|
||||
onClicked: {
|
||||
UiLogic.saveTextFile(qsTr("Save AmneziaVPN config"), "*.vpn", tfShareCode.textArea.text)
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: label_share_code
|
||||
Layout.topMargin: 20
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: width
|
||||
smooth: false
|
||||
source: ShareConnectionLogic.shareAmneziaQrCodeText
|
||||
visible: ShareConnectionLogic.shareAmneziaQrCodeText.length > 0
|
||||
}
|
||||
|
||||
LabelType {
|
||||
height: 20
|
||||
text: qsTr("Config too long to be displayed as QR code")
|
||||
visible: ShareConnectionLogic.shareAmneziaQrCodeText.length == 0 && tfShareCode.textArea.length > 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
109
client/ui/qml/Pages/Share/PageShareProtoCloak.qml
Normal file
109
client/ui/qml/Pages/Share/PageShareProtoCloak.qml
Normal file
|
@ -0,0 +1,109 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.15
|
||||
import ProtocolEnum 1.0
|
||||
import "../"
|
||||
import "../../Controls"
|
||||
import "../../Config"
|
||||
|
||||
PageShareProtocolBase {
|
||||
id: root
|
||||
protocol: ProtocolEnum.Cloak
|
||||
|
||||
BackButton {
|
||||
id: back
|
||||
}
|
||||
Caption {
|
||||
id: caption
|
||||
text: qsTr("Share Cloak Settings")
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: fl
|
||||
width: root.width
|
||||
anchors.top: caption.bottom
|
||||
anchors.topMargin: 20
|
||||
anchors.bottom: root.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
|
||||
enabled: logic.pageEnabled
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
|
||||
LabelType {
|
||||
id: lb_desc
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 10
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
wrapMode: Text.Wrap
|
||||
text: qsTr("Note: Cloak protocol using same password for all connections")
|
||||
}
|
||||
|
||||
ShareConnectionButtonType {
|
||||
Layout.topMargin: 10
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
|
||||
text: genConfigProcess ? generatingConfigText : generateConfigText
|
||||
onClicked: {
|
||||
enabled = false
|
||||
genConfigProcess = true
|
||||
ShareConnectionLogic.onPushButtonShareCloakGenerateClicked()
|
||||
enabled = true
|
||||
genConfigProcess = false
|
||||
}
|
||||
}
|
||||
|
||||
TextAreaType {
|
||||
id: tfShareCode
|
||||
|
||||
Layout.topMargin: 20
|
||||
Layout.bottomMargin: 20
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 200
|
||||
|
||||
textArea.readOnly: true
|
||||
textArea.text: ShareConnectionLogic.textEditShareCloakText
|
||||
|
||||
visible: tfShareCode.textArea.length > 0
|
||||
}
|
||||
|
||||
ShareConnectionButtonCopyType {
|
||||
Layout.bottomMargin: 10
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
|
||||
copyText: tfShareCode.textArea.text
|
||||
}
|
||||
|
||||
ShareConnectionButtonType {
|
||||
Layout.bottomMargin: 10
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
|
||||
text: qsTr("Save to file")
|
||||
enabled: tfShareCode.textArea.length > 0
|
||||
visible: tfShareCode.textArea.length > 0
|
||||
|
||||
onClicked: {
|
||||
UiLogic.saveTextFile(qsTr("Save AmneziaVPN config"), "*.json", tfShareCode.textArea.text)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
140
client/ui/qml/Pages/Share/PageShareProtoIkev2.qml
Normal file
140
client/ui/qml/Pages/Share/PageShareProtoIkev2.qml
Normal file
|
@ -0,0 +1,140 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.15
|
||||
import ProtocolEnum 1.0
|
||||
import "../"
|
||||
import "../../Controls"
|
||||
import "../../Config"
|
||||
|
||||
PageShareProtocolBase {
|
||||
id: root
|
||||
protocol: ProtocolEnum.Ikev2
|
||||
|
||||
BackButton {
|
||||
id: back
|
||||
}
|
||||
Caption {
|
||||
id: caption
|
||||
text: qsTr("Share IKEv2 Settings")
|
||||
}
|
||||
|
||||
TextAreaType {
|
||||
id: tfCert
|
||||
textArea.readOnly: true
|
||||
textArea.text: ShareConnectionLogic.textEditShareIkev2CertText
|
||||
|
||||
visible: false
|
||||
}
|
||||
|
||||
TextAreaType {
|
||||
id: tfMobileConfig
|
||||
textArea.readOnly: true
|
||||
textArea.text: ShareConnectionLogic.textEditShareIkev2MobileConfigText
|
||||
|
||||
visible: false
|
||||
}
|
||||
|
||||
TextAreaType {
|
||||
id: tfStrongSwanConfig
|
||||
textArea.readOnly: true
|
||||
textArea.text: ShareConnectionLogic.textEditShareIkev2StrongSwanConfigText
|
||||
|
||||
visible: false
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: fl
|
||||
width: root.width
|
||||
anchors.top: caption.bottom
|
||||
anchors.topMargin: 20
|
||||
anchors.bottom: root.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
|
||||
enabled: logic.pageEnabled
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
// LabelType {
|
||||
// id: lb_desc
|
||||
// Layout.fillWidth: true
|
||||
// Layout.topMargin: 10
|
||||
|
||||
// horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
// wrapMode: Text.Wrap
|
||||
// text: qsTr("Note: ShadowSocks protocol using same password for all connections")
|
||||
// }
|
||||
|
||||
ShareConnectionButtonType {
|
||||
Layout.topMargin: 10
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
|
||||
text: genConfigProcess ? generatingConfigText : generateConfigText
|
||||
onClicked: {
|
||||
enabled = false
|
||||
genConfigProcess = true
|
||||
ShareConnectionLogic.onPushButtonShareIkev2GenerateClicked()
|
||||
enabled = true
|
||||
genConfigProcess = false
|
||||
}
|
||||
}
|
||||
|
||||
ShareConnectionButtonType {
|
||||
Layout.topMargin: 30
|
||||
Layout.bottomMargin: 10
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
width: parent.width - 60
|
||||
|
||||
text: qsTr("Export p12 certificate")
|
||||
enabled: tfCert.textArea.length > 0
|
||||
visible: tfCert.textArea.length > 0
|
||||
|
||||
onClicked: {
|
||||
UiLogic.saveTextFile(qsTr("Export p12 certificate"), "*.p12", tfCert.textArea.text)
|
||||
}
|
||||
}
|
||||
|
||||
ShareConnectionButtonType {
|
||||
Layout.bottomMargin: 10
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
width: parent.width - 60
|
||||
|
||||
text: qsTr("Export config for Apple")
|
||||
enabled: tfMobileConfig.textArea.length > 0
|
||||
visible: tfMobileConfig.textArea.length > 0
|
||||
|
||||
onClicked: {
|
||||
UiLogic.saveTextFile(qsTr("Export config for Apple"), "*.plist", tfMobileConfig.textArea.text)
|
||||
}
|
||||
}
|
||||
|
||||
ShareConnectionButtonType {
|
||||
Layout.bottomMargin: 10
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
width: parent.width - 60
|
||||
|
||||
text: qsTr("Export config for StrongSwan")
|
||||
enabled: tfStrongSwanConfig.textArea.length > 0
|
||||
visible: tfStrongSwanConfig.textArea.length > 0
|
||||
|
||||
onClicked: {
|
||||
UiLogic.saveTextFile(qsTr("Export config for StrongSwan"), "*.profile", tfStrongSwanConfig.textArea.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
106
client/ui/qml/Pages/Share/PageShareProtoOpenVPN.qml
Normal file
106
client/ui/qml/Pages/Share/PageShareProtoOpenVPN.qml
Normal file
|
@ -0,0 +1,106 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.15
|
||||
import ProtocolEnum 1.0
|
||||
import "../"
|
||||
import "../../Controls"
|
||||
import "../../Config"
|
||||
|
||||
PageShareProtocolBase {
|
||||
id: root
|
||||
protocol: ProtocolEnum.OpenVpn
|
||||
|
||||
BackButton {
|
||||
id: back
|
||||
}
|
||||
Caption {
|
||||
id: caption
|
||||
text: qsTr("Share OpenVPN Settings")
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: fl
|
||||
width: root.width
|
||||
anchors.top: caption.bottom
|
||||
anchors.topMargin: 20
|
||||
anchors.bottom: root.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
|
||||
enabled: logic.pageEnabled
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
|
||||
LabelType {
|
||||
id: lb_desc
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 10
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
wrapMode: Text.Wrap
|
||||
text: qsTr("New encryption keys pair will be generated.")
|
||||
}
|
||||
|
||||
ShareConnectionButtonType {
|
||||
Layout.topMargin: 20
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
|
||||
text: genConfigProcess ? generatingConfigText : generateConfigText
|
||||
onClicked: {
|
||||
enabled = false
|
||||
genConfigProcess = true
|
||||
ShareConnectionLogic.onPushButtonShareOpenVpnGenerateClicked()
|
||||
genConfigProcess = false
|
||||
enabled = true
|
||||
}
|
||||
}
|
||||
|
||||
TextAreaType {
|
||||
id: tfShareCode
|
||||
Layout.topMargin: 20
|
||||
Layout.preferredHeight: 200
|
||||
Layout.fillWidth: true
|
||||
|
||||
textArea.readOnly: true
|
||||
|
||||
textArea.verticalAlignment: Text.AlignTop
|
||||
textArea.text: ShareConnectionLogic.textEditShareOpenVpnCodeText
|
||||
|
||||
visible: tfShareCode.textArea.length > 0
|
||||
}
|
||||
|
||||
ShareConnectionButtonCopyType {
|
||||
Layout.preferredHeight: 40
|
||||
Layout.fillWidth: true
|
||||
|
||||
copyText: tfShareCode.textArea.text
|
||||
}
|
||||
ShareConnectionButtonType {
|
||||
Layout.bottomMargin: 10
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
width: parent.width - 60
|
||||
|
||||
text: qsTr("Save to file")
|
||||
enabled: tfShareCode.textArea.length > 0
|
||||
visible: tfShareCode.textArea.length > 0
|
||||
|
||||
onClicked: {
|
||||
UiLogic.saveTextFile(qsTr("Save OpenVPN config"), "*.ovpn", tfShareCode.textArea.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
21
client/ui/qml/Pages/Share/PageShareProtoSftp.qml
Normal file
21
client/ui/qml/Pages/Share/PageShareProtoSftp.qml
Normal file
|
@ -0,0 +1,21 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import ProtocolEnum 1.0
|
||||
import "../"
|
||||
import "../../Controls"
|
||||
import "../../Config"
|
||||
|
||||
PageShareProtocolBase {
|
||||
id: root
|
||||
protocol: ProtocolEnum.Sftp
|
||||
|
||||
BackButton {
|
||||
id: back
|
||||
}
|
||||
|
||||
Caption {
|
||||
id: caption
|
||||
text: qsTr("Share SFTF settings")
|
||||
}
|
||||
|
||||
}
|
124
client/ui/qml/Pages/Share/PageShareProtoShadowSocks.qml
Normal file
124
client/ui/qml/Pages/Share/PageShareProtoShadowSocks.qml
Normal file
|
@ -0,0 +1,124 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.15
|
||||
import ProtocolEnum 1.0
|
||||
import "../"
|
||||
import "../../Controls"
|
||||
import "../../Config"
|
||||
|
||||
PageShareProtocolBase {
|
||||
id: root
|
||||
protocol: ProtocolEnum.ShadowSocks
|
||||
|
||||
BackButton {
|
||||
id: back
|
||||
}
|
||||
Caption {
|
||||
id: caption
|
||||
text: qsTr("Share ShadowSocks Settings")
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: fl
|
||||
width: root.width
|
||||
anchors.top: caption.bottom
|
||||
anchors.topMargin: 20
|
||||
anchors.bottom: root.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
|
||||
enabled: logic.pageEnabled
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
LabelType {
|
||||
id: lb_desc
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 10
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
wrapMode: Text.Wrap
|
||||
text: qsTr("Note: ShadowSocks protocol using same password for all connections")
|
||||
}
|
||||
|
||||
ShareConnectionButtonType {
|
||||
Layout.topMargin: 10
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
|
||||
text: genConfigProcess ? generatingConfigText : generateConfigText
|
||||
onClicked: {
|
||||
enabled = false
|
||||
genConfigProcess = true
|
||||
ShareConnectionLogic.onPushButtonShareShadowSocksGenerateClicked()
|
||||
enabled = true
|
||||
genConfigProcess = false
|
||||
}
|
||||
}
|
||||
|
||||
TextAreaType {
|
||||
id: tfShareCode
|
||||
|
||||
Layout.topMargin: 20
|
||||
Layout.preferredHeight: 200
|
||||
Layout.fillWidth: true
|
||||
|
||||
textArea.readOnly: true
|
||||
textArea.wrapMode: TextEdit.WrapAnywhere
|
||||
textArea.verticalAlignment: Text.AlignTop
|
||||
textArea.text: ShareConnectionLogic.textEditShareShadowSocksText
|
||||
|
||||
visible: tfShareCode.textArea.length > 0
|
||||
}
|
||||
ShareConnectionButtonCopyType {
|
||||
Layout.preferredHeight: 40
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: 20
|
||||
|
||||
start_text: qsTr("Copy config")
|
||||
copyText: tfShareCode.textArea.text
|
||||
}
|
||||
|
||||
LabelType {
|
||||
height: 20
|
||||
visible: tfConnString.length > 0
|
||||
text: qsTr("Connection string")
|
||||
}
|
||||
TextFieldType {
|
||||
id: tfConnString
|
||||
height: 100
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
text: ShareConnectionLogic.lineEditShareShadowSocksStringText
|
||||
visible: tfConnString.length > 0
|
||||
|
||||
readOnly: true
|
||||
}
|
||||
ShareConnectionButtonCopyType {
|
||||
Layout.preferredHeight: 40
|
||||
Layout.fillWidth: true
|
||||
start_text: qsTr("Copy string")
|
||||
copyText: tfConnString.text
|
||||
}
|
||||
|
||||
Image {
|
||||
id: label_share_ss_qr_code
|
||||
Layout.topMargin: 20
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: width
|
||||
smooth: false
|
||||
source: ShareConnectionLogic.shareShadowSocksQrCodeText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
20
client/ui/qml/Pages/Share/PageShareProtoTorWebSite.qml
Normal file
20
client/ui/qml/Pages/Share/PageShareProtoTorWebSite.qml
Normal file
|
@ -0,0 +1,20 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import ProtocolEnum 1.0
|
||||
import "../"
|
||||
import "../../Controls"
|
||||
import "../../Config"
|
||||
|
||||
PageShareProtocolBase {
|
||||
id: root
|
||||
protocol: ProtocolEnum.TorWebSite
|
||||
|
||||
BackButton {
|
||||
id: back
|
||||
}
|
||||
|
||||
Caption {
|
||||
id: caption
|
||||
text: qsTr("Share TOR Web site")
|
||||
}
|
||||
}
|
112
client/ui/qml/Pages/Share/PageShareProtoWireGuard.qml
Normal file
112
client/ui/qml/Pages/Share/PageShareProtoWireGuard.qml
Normal file
|
@ -0,0 +1,112 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.15
|
||||
import ProtocolEnum 1.0
|
||||
import "../"
|
||||
import "../../Controls"
|
||||
import "../../Config"
|
||||
|
||||
PageShareProtocolBase {
|
||||
id: root
|
||||
protocol: ProtocolEnum.WireGuard
|
||||
|
||||
BackButton {
|
||||
id: back
|
||||
}
|
||||
Caption {
|
||||
id: caption
|
||||
text: qsTr("Share WireGuard Settings")
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: fl
|
||||
width: root.width
|
||||
anchors.top: caption.bottom
|
||||
anchors.topMargin: 20
|
||||
anchors.bottom: root.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
|
||||
enabled: logic.pageEnabled
|
||||
anchors.top: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
LabelType {
|
||||
id: lb_desc
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 10
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
wrapMode: Text.Wrap
|
||||
text: qsTr("New encryption keys pair will be generated.")
|
||||
}
|
||||
|
||||
ShareConnectionButtonType {
|
||||
Layout.topMargin: 10
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
|
||||
text: genConfigProcess ? generatingConfigText : generateConfigText
|
||||
onClicked: {
|
||||
enabled = false
|
||||
genConfigProcess = true
|
||||
ShareConnectionLogic.onPushButtonShareWireGuardGenerateClicked()
|
||||
enabled = true
|
||||
genConfigProcess = false
|
||||
}
|
||||
}
|
||||
|
||||
TextAreaType {
|
||||
id: tfShareCode
|
||||
|
||||
Layout.topMargin: 20
|
||||
Layout.preferredHeight: 200
|
||||
Layout.fillWidth: true
|
||||
|
||||
textArea.readOnly: true
|
||||
textArea.wrapMode: TextEdit.WrapAnywhere
|
||||
textArea.verticalAlignment: Text.AlignTop
|
||||
textArea.text: ShareConnectionLogic.textEditShareWireGuardCodeText
|
||||
|
||||
visible: tfShareCode.textArea.length > 0
|
||||
}
|
||||
ShareConnectionButtonCopyType {
|
||||
Layout.preferredHeight: 40
|
||||
Layout.fillWidth: true
|
||||
|
||||
copyText: tfShareCode.textArea.text
|
||||
}
|
||||
|
||||
ShareConnectionButtonType {
|
||||
Layout.preferredHeight: 40
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Save to file")
|
||||
enabled: tfShareCode.textArea.length > 0
|
||||
visible: tfShareCode.textArea.length > 0
|
||||
|
||||
onClicked: {
|
||||
UiLogic.saveTextFile(qsTr("Save OpenVPN config"), "*.conf", tfShareCode.textArea.text)
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
Layout.topMargin: 20
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: width
|
||||
smooth: false
|
||||
source: ShareConnectionLogic.shareWireGuardQrCodeText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
client/ui/qml/Pages/Share/PageShareProtocolBase.qml
Normal file
19
client/ui/qml/Pages/Share/PageShareProtocolBase.qml
Normal file
|
@ -0,0 +1,19 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import PageEnum 1.0
|
||||
import ProtocolEnum 1.0
|
||||
import "./.."
|
||||
import "../../Controls"
|
||||
import "../../Config"
|
||||
|
||||
PageBase {
|
||||
id: root
|
||||
property var protocol: ProtocolEnum.Any
|
||||
page: PageEnum.ProtocolShare
|
||||
logic: ShareConnectionLogic
|
||||
|
||||
readonly property string generateConfigText: qsTr("Generate config")
|
||||
readonly property string generatingConfigText: qsTr("Generating config...")
|
||||
readonly property string showConfigText: qsTr("Show config")
|
||||
property bool genConfigProcess: false
|
||||
}
|
|
@ -3,17 +3,20 @@ import QtQuick.Window 2.14
|
|||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Controls.Material 2.12
|
||||
import PageEnum 1.0
|
||||
import PageType 1.0
|
||||
import Qt.labs.platform 1.1
|
||||
import Qt.labs.folderlistmodel 2.12
|
||||
import QtQuick.Dialogs 1.1
|
||||
import "./"
|
||||
import "Pages"
|
||||
import "Pages/Protocols"
|
||||
import "Pages/Share"
|
||||
import "Config"
|
||||
|
||||
Window {
|
||||
property var pages: ({})
|
||||
property var protocolPages: ({})
|
||||
property var sharePages: ({})
|
||||
|
||||
id: root
|
||||
visible: true
|
||||
|
@ -28,73 +31,28 @@ Window {
|
|||
//flags: Qt.FramelessWindowHint
|
||||
title: "AmneziaVPN"
|
||||
|
||||
function gotoPage(page, reset, slide) {
|
||||
function gotoPage(type, page, reset, slide) {
|
||||
|
||||
let p_obj;
|
||||
if (type === PageType.Basic) p_obj = pages[page]
|
||||
else if (type === PageType.Proto) p_obj = protocolPages[page]
|
||||
else if (type === PageType.ShareProto) p_obj = sharePages[page]
|
||||
else return
|
||||
|
||||
console.debug("QML gotoPage " + type + " " + page + " " + p_obj)
|
||||
|
||||
|
||||
if (slide) {
|
||||
pageLoader.push(p_obj, {}, StackView.PushTransition)
|
||||
} else {
|
||||
pageLoader.push(p_obj, {}, StackView.Immediate)
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
if (page === PageEnum.ServerSettings) {
|
||||
ServerSettingsLogic.onUpdatePage();
|
||||
}
|
||||
if (page === PageEnum.ShareConnection) {
|
||||
}
|
||||
if (page === PageEnum.Wizard) {
|
||||
WizardLogic.radioButtonMediumChecked = true
|
||||
}
|
||||
if (page === PageEnum.WizardHigh) {
|
||||
WizardLogic.onUpdatePage();
|
||||
}
|
||||
if (page === PageEnum.ServerConfiguringProgress) {
|
||||
ServerConfiguringProgressLogic.progressBarValue = 0;
|
||||
}
|
||||
if (page === PageEnum.GeneralSettings) {
|
||||
GeneralSettingsLogic.onUpdatePage();
|
||||
}
|
||||
if (page === PageEnum.ServersList) {
|
||||
ServerListLogic.onUpdatePage();
|
||||
}
|
||||
if (page === PageEnum.Start) {
|
||||
StartPageLogic.pushButtonBackFromStartVisible = !pageLoader.empty
|
||||
StartPageLogic.onUpdatePage();
|
||||
}
|
||||
if (page === PageEnum.NewServerProtocols) {
|
||||
NewServerProtocolsLogic.onUpdatePage()
|
||||
}
|
||||
if (page === PageEnum.ServerContainers) {
|
||||
ServerContainersLogic.onUpdatePage()
|
||||
}
|
||||
if (page === PageEnum.AppSettings) {
|
||||
AppSettingsLogic.onUpdatePage()
|
||||
}
|
||||
if (page === PageEnum.NetworkSettings) {
|
||||
NetworkSettingsLogic.onUpdatePage()
|
||||
}
|
||||
if (page === PageEnum.Sites) {
|
||||
SitesLogic.updateSitesPage()
|
||||
}
|
||||
if (page === PageEnum.Vpn) {
|
||||
VpnLogic.updateVpnPage()
|
||||
}
|
||||
p_obj.logic.onUpdatePage();
|
||||
}
|
||||
|
||||
if (slide) {
|
||||
pageLoader.push(pages[page], {}, StackView.PushTransition)
|
||||
} else {
|
||||
pageLoader.push(pages[page], {}, StackView.Immediate)
|
||||
}
|
||||
|
||||
pages[page].activated(reset)
|
||||
}
|
||||
|
||||
function gotoProtocolPage(protocol, reset, slide) {
|
||||
if (reset && protocolPages[protocol] !== "undefined") {
|
||||
protocolPages[protocol].logic.onUpdatePage();
|
||||
}
|
||||
|
||||
if (slide) {
|
||||
pageLoader.push(protocolPages[protocol], {}, StackView.PushTransition)
|
||||
} else {
|
||||
pageLoader.push(protocolPages[protocol], {}, StackView.Immediate)
|
||||
}
|
||||
|
||||
protocolPages[protocol].activated(reset)
|
||||
p_obj.activated(reset)
|
||||
}
|
||||
|
||||
function close_page() {
|
||||
|
@ -146,6 +104,8 @@ Window {
|
|||
color: "white"
|
||||
}
|
||||
|
||||
//PageShareProtoAmnezia {}
|
||||
|
||||
StackView {
|
||||
id: pageLoader
|
||||
y: GC.isDesktop() ? titleBar.height : 0
|
||||
|
@ -157,6 +117,10 @@ Window {
|
|||
UiLogic.currentPageValue = currentItem.page
|
||||
}
|
||||
|
||||
onDepthChanged: {
|
||||
UiLogic.pagesStackDepth = depth
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
UiLogic.keyPressEvent(event.key)
|
||||
event.accepted = true
|
||||
|
@ -171,7 +135,7 @@ Window {
|
|||
|
||||
onStatusChanged: if (status == FolderListModel.Ready) {
|
||||
for (var i=0; i<folderModelPages.count; i++) {
|
||||
createPagesObjects(folderModelPages.get(i, "filePath"), false);
|
||||
createPagesObjects(folderModelPages.get(i, "filePath"), PageType.Basic);
|
||||
}
|
||||
UiLogic.initalizeUiLogic()
|
||||
}
|
||||
|
@ -185,40 +149,56 @@ Window {
|
|||
|
||||
onStatusChanged: if (status == FolderListModel.Ready) {
|
||||
for (var i=0; i<folderModelProtocols.count; i++) {
|
||||
createPagesObjects(folderModelProtocols.get(i, "filePath"), true);
|
||||
createPagesObjects(folderModelProtocols.get(i, "filePath"), PageType.Proto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createPagesObjects(file, isProtocol) {
|
||||
FolderListModel {
|
||||
id: folderModelShareProtocols
|
||||
folder: "qrc:/ui/qml/Pages/Share/"
|
||||
nameFilters: ["*.qml"]
|
||||
showDirs: false
|
||||
|
||||
onStatusChanged: if (status == FolderListModel.Ready) {
|
||||
for (var i=0; i<folderModelShareProtocols.count; i++) {
|
||||
createPagesObjects(folderModelShareProtocols.get(i, "filePath"), PageType.ShareProto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createPagesObjects(file, type) {
|
||||
if (file.indexOf("Base") !== -1) return; // skip Base Pages
|
||||
//console.debug("Creating compenent " + file + " for " + type);
|
||||
|
||||
var c = Qt.createComponent("qrc" + file);
|
||||
|
||||
var finishCreation = function (component){
|
||||
if (component.status == Component.Ready) {
|
||||
if (component.status === Component.Ready) {
|
||||
var obj = component.createObject(root);
|
||||
if (obj == null) {
|
||||
if (obj === null) {
|
||||
console.debug("Error creating object " + component.url);
|
||||
}
|
||||
else {
|
||||
obj.visible = false
|
||||
if (isProtocol) {
|
||||
protocolPages[obj.protocol] = obj
|
||||
}
|
||||
else {
|
||||
if (type === PageType.Basic) {
|
||||
pages[obj.page] = obj
|
||||
}
|
||||
else if (type === PageType.Proto) {
|
||||
protocolPages[obj.protocol] = obj
|
||||
}
|
||||
else if (type === PageType.ShareProto) {
|
||||
sharePages[obj.protocol] = obj
|
||||
}
|
||||
|
||||
|
||||
|
||||
//console.debug("Created compenent " + component.url + " for " + type);
|
||||
}
|
||||
} else if (component.status == Component.Error) {
|
||||
} else if (component.status === Component.Error) {
|
||||
console.debug("Error loading component:", component.errorString());
|
||||
}
|
||||
}
|
||||
|
||||
if (c.status == Component.Ready)
|
||||
if (c.status === Component.Ready)
|
||||
finishCreation(c);
|
||||
else {
|
||||
console.debug("Warning: Pages components are not ready");
|
||||
|
@ -228,13 +208,19 @@ Window {
|
|||
Connections {
|
||||
target: UiLogic
|
||||
function onGoToPage(page, reset, slide) {
|
||||
console.debug("Connections onGoToPage " + page);
|
||||
root.gotoPage(page, reset, slide)
|
||||
console.debug("Qml Connections onGoToPage " + page);
|
||||
root.gotoPage(PageType.Basic, page, reset, slide)
|
||||
}
|
||||
function onGoToProtocolPage(protocol, reset, slide) {
|
||||
console.debug("Connections onGoToProtocolPage " + protocol);
|
||||
root.gotoProtocolPage(protocol, reset, slide)
|
||||
console.debug("Qml Connections onGoToProtocolPage " + protocol);
|
||||
root.gotoPage(PageType.Proto, protocol, reset, slide)
|
||||
}
|
||||
function onGoToShareProtocolPage(protocol, reset, slide) {
|
||||
console.debug("Qml Connections onGoToShareProtocolPage " + protocol);
|
||||
root.gotoPage(PageType.ShareProto, protocol, reset, slide)
|
||||
}
|
||||
|
||||
|
||||
function onClosePage() {
|
||||
root.close_page()
|
||||
}
|
||||
|
@ -253,6 +239,11 @@ Window {
|
|||
function onHide() {
|
||||
root.hide()
|
||||
}
|
||||
function onRaise() {
|
||||
root.show()
|
||||
root.raise()
|
||||
root.requestActivate()
|
||||
}
|
||||
}
|
||||
|
||||
MessageDialog {
|
||||
|
@ -267,62 +258,6 @@ Window {
|
|||
}
|
||||
visible: false
|
||||
}
|
||||
SystemTrayIcon {
|
||||
visible: true
|
||||
icon.source: UiLogic.trayIconUrl
|
||||
onActivated: {
|
||||
if (Qt.platform.os == "osx" ||
|
||||
Qt.platform.os == "linux") {
|
||||
if (reason === SystemTrayIcon.DoubleClick ||
|
||||
reason === SystemTrayIcon.Trigger) {
|
||||
root.show()
|
||||
root.raise()
|
||||
root.requestActivate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
menu: Menu {
|
||||
MenuItem {
|
||||
iconSource: "qrc:/images/tray/application.png"
|
||||
text: qsTr("Show") + " " + "AmneziaVPN"
|
||||
onTriggered: {
|
||||
root.show()
|
||||
root.raise()
|
||||
}
|
||||
}
|
||||
MenuSeparator { }
|
||||
MenuItem {
|
||||
text: qsTr("Connect")
|
||||
enabled: UiLogic.trayActionConnectEnabled
|
||||
onTriggered: {
|
||||
UiLogic.onConnect()
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Disconnect")
|
||||
enabled: UiLogic.trayActionDisconnectEnabled
|
||||
onTriggered: {
|
||||
UiLogic.onDisconnect()
|
||||
}
|
||||
}
|
||||
MenuSeparator { }
|
||||
MenuItem {
|
||||
iconSource: "qrc:/images/tray/link.png"
|
||||
text: qsTr("Visit Website")
|
||||
onTriggered: {
|
||||
Qt.openUrlExternally("https://amnezia.org")
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
iconSource: "qrc:/images/tray/cancel.png"
|
||||
text: qsTr("Quit") + " " + "AmneziaVPN"
|
||||
onTriggered: {
|
||||
closePrompt.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MessageDialog {
|
||||
id: publicKeyWarning
|
||||
title: "AmneziaVPN"
|
||||
|
|
|
@ -69,15 +69,13 @@ using namespace PageEnumNS;
|
|||
|
||||
UiLogic::UiLogic(QObject *parent) :
|
||||
QObject(parent),
|
||||
m_currentPageValue{0},
|
||||
m_trayIconUrl{},
|
||||
m_trayActionDisconnectEnabled{true},
|
||||
m_trayActionConnectEnabled{true},
|
||||
m_dialogConnectErrorText{}
|
||||
{
|
||||
m_containersModel = new ContainersModel(this);
|
||||
m_protocolsModel = new ProtocolsModel(this);
|
||||
m_vpnConnection = new VpnConnection(this);
|
||||
m_vpnConnection = new VpnConnection();
|
||||
m_vpnConnection->moveToThread(&m_vpnConnectionThread);
|
||||
m_vpnConnectionThread.start();
|
||||
|
||||
m_appSettingsLogic = new AppSettingsLogic(this);
|
||||
m_generalSettingsLogic = new GeneralSettingsLogic(this);
|
||||
|
@ -104,6 +102,30 @@ UiLogic::UiLogic(QObject *parent) :
|
|||
|
||||
}
|
||||
|
||||
UiLogic::~UiLogic()
|
||||
{
|
||||
m_tray = nullptr;
|
||||
|
||||
emit hide();
|
||||
|
||||
if (m_vpnConnection->connectionState() != VpnProtocol::ConnectionState::Disconnected) {
|
||||
m_vpnConnection->disconnectFromVpn();
|
||||
for (int i = 0; i < 50; i++) {
|
||||
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
QThread::msleep(100);
|
||||
if (m_vpnConnection->isDisconnected()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_vpnConnectionThread.quit();
|
||||
m_vpnConnectionThread.wait(3000);
|
||||
delete m_vpnConnection;
|
||||
|
||||
qDebug() << "Application closed";
|
||||
}
|
||||
|
||||
void UiLogic::initalizeUiLogic()
|
||||
{
|
||||
qDebug() << "UiLogic::initalizeUiLogic()";
|
||||
|
@ -168,86 +190,8 @@ void UiLogic::initalizeUiLogic()
|
|||
// ui->lineEdit_proto_shadowsocks_port->setValidator(&m_ipPortValidator);
|
||||
// ui->lineEdit_proto_cloak_port->setValidator(&m_ipPortValidator);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int UiLogic::getCurrentPageValue() const
|
||||
{
|
||||
return m_currentPageValue;
|
||||
}
|
||||
|
||||
void UiLogic::setCurrentPageValue(int currentPageValue)
|
||||
{
|
||||
if (m_currentPageValue != currentPageValue) {
|
||||
m_currentPageValue = currentPageValue;
|
||||
emit currentPageValueChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QString UiLogic::getTrayIconUrl() const
|
||||
{
|
||||
return m_trayIconUrl;
|
||||
}
|
||||
|
||||
void UiLogic::setTrayIconUrl(const QString &trayIconUrl)
|
||||
{
|
||||
if (m_trayIconUrl != trayIconUrl) {
|
||||
m_trayIconUrl = trayIconUrl;
|
||||
emit trayIconUrlChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool UiLogic::getTrayActionDisconnectEnabled() const
|
||||
{
|
||||
return m_trayActionDisconnectEnabled;
|
||||
}
|
||||
|
||||
void UiLogic::setTrayActionDisconnectEnabled(bool trayActionDisconnectEnabled)
|
||||
{
|
||||
if (m_trayActionDisconnectEnabled != trayActionDisconnectEnabled) {
|
||||
m_trayActionDisconnectEnabled = trayActionDisconnectEnabled;
|
||||
emit trayActionDisconnectEnabledChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool UiLogic::getTrayActionConnectEnabled() const
|
||||
{
|
||||
return m_trayActionConnectEnabled;
|
||||
}
|
||||
|
||||
void UiLogic::setTrayActionConnectEnabled(bool trayActionConnectEnabled)
|
||||
{
|
||||
if (m_trayActionConnectEnabled != trayActionConnectEnabled) {
|
||||
m_trayActionConnectEnabled = trayActionConnectEnabled;
|
||||
emit trayActionConnectEnabledChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
QString UiLogic::getDialogConnectErrorText() const
|
||||
{
|
||||
return m_dialogConnectErrorText;
|
||||
|
@ -261,24 +205,6 @@ void UiLogic::setDialogConnectErrorText(const QString &dialogConnectErrorText)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
UiLogic::~UiLogic()
|
||||
{
|
||||
hide();
|
||||
m_vpnConnection->disconnectFromVpn();
|
||||
for (int i = 0; i < 50; i++) {
|
||||
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
QThread::msleep(100);
|
||||
if (m_vpnConnection->isDisconnected()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete m_vpnConnection;
|
||||
|
||||
qDebug() << "Application closed";
|
||||
}
|
||||
|
||||
void UiLogic::showOnStartup()
|
||||
{
|
||||
if (! m_settings.isStartMinimized()) {
|
||||
|
@ -290,6 +216,26 @@ void UiLogic::showOnStartup()
|
|||
}
|
||||
}
|
||||
|
||||
void UiLogic::onUpdateAllPages()
|
||||
{
|
||||
for (PageLogicBase *logic : {
|
||||
(PageLogicBase *) m_appSettingsLogic,
|
||||
(PageLogicBase *) m_generalSettingsLogic,
|
||||
(PageLogicBase *) m_networkSettingsLogic,
|
||||
(PageLogicBase *) m_serverConfiguringProgressLogic,
|
||||
(PageLogicBase *) m_newServerProtocolsLogic,
|
||||
(PageLogicBase *) m_serverListLogic,
|
||||
(PageLogicBase *) m_serverSettingsLogic,
|
||||
(PageLogicBase *) m_serverVpnProtocolsLogic,
|
||||
(PageLogicBase *) m_shareConnectionLogic,
|
||||
(PageLogicBase *) m_sitesLogic,
|
||||
(PageLogicBase *) m_startPageLogic,
|
||||
(PageLogicBase *) m_vpnLogic,
|
||||
(PageLogicBase *) m_wizardLogic
|
||||
}) {
|
||||
logic->onUpdatePage();
|
||||
}
|
||||
}
|
||||
|
||||
void UiLogic::keyPressEvent(Qt::Key key)
|
||||
{
|
||||
|
@ -326,9 +272,7 @@ void UiLogic::keyPressEvent(Qt::Key key)
|
|||
emit goToPage(Page::ServerSettings);
|
||||
break;
|
||||
case Qt::Key_P:
|
||||
selectedServerIndex = m_settings.defaultServerIndex();
|
||||
selectedDockerContainer = m_settings.defaultContainer(selectedServerIndex);
|
||||
emit goToPage(Page::ServerContainers);
|
||||
onGotoCurrentProtocolsPage();
|
||||
break;
|
||||
case Qt::Key_T:
|
||||
SshConfigurator::openSshTerminal(m_settings.serverCredentials(m_settings.defaultServerIndex()));
|
||||
|
@ -371,6 +315,13 @@ QString UiLogic::containerDesc(int container)
|
|||
|
||||
}
|
||||
|
||||
void UiLogic::onGotoCurrentProtocolsPage()
|
||||
{
|
||||
selectedServerIndex = m_settings.defaultServerIndex();
|
||||
selectedDockerContainer = m_settings.defaultContainer(selectedServerIndex);
|
||||
emit goToPage(Page::ServerContainers);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//void UiLogic::showEvent(QShowEvent *event)
|
||||
|
@ -650,12 +601,22 @@ ErrorCode UiLogic::doInstallAction(const std::function<ErrorCode()> &action,
|
|||
|
||||
void UiLogic::setupTray()
|
||||
{
|
||||
setTrayState(VpnProtocol::Disconnected);
|
||||
m_tray = new QSystemTrayIcon(qmlRoot());
|
||||
setTrayState(VpnProtocol::Disconnected);
|
||||
|
||||
m_tray->show();
|
||||
|
||||
connect(m_tray, &QSystemTrayIcon::activated, this, &UiLogic::onTrayActivated);
|
||||
}
|
||||
|
||||
void UiLogic::setTrayIcon(const QString &iconPath)
|
||||
{
|
||||
setTrayIconUrl(iconPath);
|
||||
if (m_tray) m_tray->setIcon(QIcon(QPixmap(iconPath).scaled(128,128)));
|
||||
}
|
||||
|
||||
void UiLogic::onTrayActivated(QSystemTrayIcon::ActivationReason reason)
|
||||
{
|
||||
emit raise();
|
||||
}
|
||||
|
||||
PageProtocolLogicBase *UiLogic::protocolLogic(Protocol p) {
|
||||
|
@ -667,17 +628,24 @@ PageProtocolLogicBase *UiLogic::protocolLogic(Protocol p) {
|
|||
}
|
||||
}
|
||||
|
||||
QObject *UiLogic::qmlRoot() const
|
||||
{
|
||||
return m_qmlRoot;
|
||||
}
|
||||
|
||||
void UiLogic::setQmlRoot(QObject *newQmlRoot)
|
||||
{
|
||||
m_qmlRoot = newQmlRoot;
|
||||
}
|
||||
|
||||
PageEnumNS::Page UiLogic::currentPage()
|
||||
{
|
||||
return static_cast<PageEnumNS::Page>(getCurrentPageValue());
|
||||
return static_cast<PageEnumNS::Page>(currentPageValue());
|
||||
}
|
||||
|
||||
void UiLogic::setTrayState(VpnProtocol::ConnectionState state)
|
||||
{
|
||||
QString resourcesPath = "qrc:/images/tray/%1";
|
||||
|
||||
setTrayActionDisconnectEnabled(state == VpnProtocol::Connected);
|
||||
setTrayActionConnectEnabled(state == VpnProtocol::Disconnected);
|
||||
QString resourcesPath = ":/images/tray/%1";
|
||||
|
||||
switch (state) {
|
||||
case VpnProtocol::Disconnected:
|
||||
|
@ -713,8 +681,40 @@ void UiLogic::setTrayState(VpnProtocol::ConnectionState state)
|
|||
// resourcesPath = ":/images_mac/tray_icon/%1";
|
||||
// useIconName = useIconName.replace(".png", darkTaskBar ? "@2x.png" : " dark@2x.png");
|
||||
//#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool UiLogic::saveTextFile(const QString& desc, const QString& ext, const QString& data)
|
||||
{
|
||||
QString fileName = QFileDialog::getSaveFileName(nullptr, desc,
|
||||
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), ext);
|
||||
|
||||
QSaveFile save(fileName);
|
||||
save.open(QIODevice::WriteOnly);
|
||||
save.write(data.toUtf8());
|
||||
|
||||
QFileInfo fi(fileName);
|
||||
QDesktopServices::openUrl(fi.absoluteDir().absolutePath());
|
||||
|
||||
return save.commit();
|
||||
}
|
||||
|
||||
bool UiLogic::saveBinaryFile(const QString &desc, const QString &ext, const QString &data)
|
||||
{
|
||||
QString fileName = QFileDialog::getSaveFileName(nullptr, desc,
|
||||
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), ext);
|
||||
|
||||
QSaveFile save(fileName);
|
||||
save.open(QIODevice::WriteOnly);
|
||||
save.write(QByteArray::fromBase64(data.toUtf8()));
|
||||
|
||||
QFileInfo fi(fileName);
|
||||
QDesktopServices::openUrl(fi.absoluteDir().absolutePath());
|
||||
|
||||
return save.commit();
|
||||
}
|
||||
|
||||
void UiLogic::copyToClipboard(const QString &text)
|
||||
{
|
||||
qApp->clipboard()->setText(text);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <QQmlEngine>
|
||||
#include <functional>
|
||||
#include <QKeyEvent>
|
||||
#include <QThread>
|
||||
#include <QSystemTrayIcon>
|
||||
|
||||
#include "property_helper.h"
|
||||
#include "pages.h"
|
||||
|
@ -45,15 +47,13 @@ class UiLogic : public QObject
|
|||
Q_OBJECT
|
||||
|
||||
AUTO_PROPERTY(bool, pageEnabled)
|
||||
AUTO_PROPERTY(int, pagesStackDepth)
|
||||
AUTO_PROPERTY(int, currentPageValue)
|
||||
|
||||
READONLY_PROPERTY(QObject *, containersModel)
|
||||
READONLY_PROPERTY(QObject *, protocolsModel)
|
||||
|
||||
Q_PROPERTY(int currentPageValue READ getCurrentPageValue WRITE setCurrentPageValue NOTIFY currentPageValueChanged)
|
||||
Q_PROPERTY(QString trayIconUrl READ getTrayIconUrl WRITE setTrayIconUrl NOTIFY trayIconUrlChanged)
|
||||
Q_PROPERTY(bool trayActionDisconnectEnabled READ getTrayActionDisconnectEnabled WRITE setTrayActionDisconnectEnabled NOTIFY trayActionDisconnectEnabledChanged)
|
||||
Q_PROPERTY(bool trayActionConnectEnabled READ getTrayActionConnectEnabled WRITE setTrayActionConnectEnabled NOTIFY trayActionConnectEnabledChanged)
|
||||
|
||||
// TODO: review
|
||||
Q_PROPERTY(QString dialogConnectErrorText READ getDialogConnectErrorText WRITE setDialogConnectErrorText NOTIFY dialogConnectErrorTextChanged)
|
||||
|
||||
public:
|
||||
|
@ -82,6 +82,9 @@ public:
|
|||
|
||||
friend class OtherProtocolsLogic;
|
||||
|
||||
Q_INVOKABLE virtual void onUpdatePage() {} // UiLogic is set as logic class for some qml pages
|
||||
Q_INVOKABLE void onUpdateAllPages();
|
||||
|
||||
Q_INVOKABLE void initalizeUiLogic();
|
||||
Q_INVOKABLE void onCloseWindow();
|
||||
|
||||
|
@ -90,24 +93,20 @@ public:
|
|||
|
||||
Q_INVOKABLE void onGotoPage(PageEnumNS::Page p, bool reset = true, bool slide = true) { emit goToPage(p, reset, slide); }
|
||||
Q_INVOKABLE void onGotoProtocolPage(Protocol p, bool reset = true, bool slide = true) { emit goToProtocolPage(p, reset, slide); }
|
||||
Q_INVOKABLE void onGotoShareProtocolPage(Protocol p, bool reset = true, bool slide = true) { emit goToShareProtocolPage(p, reset, slide); }
|
||||
|
||||
Q_INVOKABLE void onGotoCurrentProtocolsPage();
|
||||
|
||||
Q_INVOKABLE void keyPressEvent(Qt::Key key);
|
||||
|
||||
|
||||
int getCurrentPageValue() const;
|
||||
void setCurrentPageValue(int currentPageValue);
|
||||
QString getTrayIconUrl() const;
|
||||
void setTrayIconUrl(const QString &trayIconUrl);
|
||||
bool getTrayActionDisconnectEnabled() const;
|
||||
void setTrayActionDisconnectEnabled(bool trayActionDisconnectEnabled);
|
||||
bool getTrayActionConnectEnabled() const;
|
||||
void setTrayActionConnectEnabled(bool trayActionConnectEnabled);
|
||||
Q_INVOKABLE bool saveTextFile(const QString& desc, const QString& ext, const QString& data);
|
||||
Q_INVOKABLE bool saveBinaryFile(const QString& desc, const QString& ext, const QString& data);
|
||||
Q_INVOKABLE void copyToClipboard(const QString& text);
|
||||
|
||||
QString getDialogConnectErrorText() const;
|
||||
void setDialogConnectErrorText(const QString &dialogConnectErrorText);
|
||||
|
||||
signals:
|
||||
void currentPageValueChanged();
|
||||
void trayIconUrlChanged();
|
||||
void trayActionDisconnectEnabledChanged();
|
||||
void trayActionConnectEnabledChanged();
|
||||
|
@ -116,18 +115,18 @@ signals:
|
|||
|
||||
void goToPage(PageEnumNS::Page page, bool reset = true, bool slide = true);
|
||||
void goToProtocolPage(Protocol protocol, bool reset = true, bool slide = true);
|
||||
void goToShareProtocolPage(Protocol protocol, bool reset = true, bool slide = true);
|
||||
|
||||
void closePage();
|
||||
void setStartPage(PageEnumNS::Page page, bool slide = true);
|
||||
void showPublicKeyWarning();
|
||||
void showConnectErrorDialog();
|
||||
void show();
|
||||
void hide();
|
||||
void raise();
|
||||
|
||||
private:
|
||||
int m_currentPageValue;
|
||||
QString m_trayIconUrl;
|
||||
bool m_trayActionDisconnectEnabled;
|
||||
bool m_trayActionConnectEnabled;
|
||||
QSystemTrayIcon *m_tray;
|
||||
|
||||
QString m_dialogConnectErrorText;
|
||||
|
||||
|
@ -136,6 +135,7 @@ private slots:
|
|||
void installServer(QMap<DockerContainer, QJsonObject> &containers);
|
||||
|
||||
void setTrayState(VpnProtocol::ConnectionState state);
|
||||
void onTrayActivated(QSystemTrayIcon::ActivationReason reason);
|
||||
|
||||
private:
|
||||
PageEnumNS::Page currentPage();
|
||||
|
@ -192,7 +192,12 @@ public:
|
|||
|
||||
Q_INVOKABLE PageProtocolLogicBase *protocolLogic(Protocol p);
|
||||
|
||||
QObject *qmlRoot() const;
|
||||
void setQmlRoot(QObject *newQmlRoot);
|
||||
|
||||
private:
|
||||
QObject *m_qmlRoot{nullptr};
|
||||
|
||||
AppSettingsLogic *m_appSettingsLogic;
|
||||
GeneralSettingsLogic *m_generalSettingsLogic;
|
||||
NetworkSettingsLogic *m_networkSettingsLogic;
|
||||
|
@ -210,6 +215,7 @@ private:
|
|||
QMap<Protocol, PageProtocolLogicBase *> m_protocolLogicMap;
|
||||
|
||||
VpnConnection* m_vpnConnection;
|
||||
QThread m_vpnConnectionThread;
|
||||
Settings m_settings;
|
||||
|
||||
|
||||
|
|
|
@ -23,12 +23,7 @@
|
|||
|
||||
VpnConnection::VpnConnection(QObject* parent) : QObject(parent)
|
||||
{
|
||||
QTimer::singleShot(0, this, [this](){
|
||||
if (!IpcClient::init()) {
|
||||
qWarning() << "Error occured when init IPC client";
|
||||
emit serviceIsNotReady();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
VpnConnection::~VpnConnection()
|
||||
|
@ -190,10 +185,6 @@ QJsonObject VpnConnection::createVpnConfiguration(int serverIndex,
|
|||
|
||||
|
||||
for (ProtocolEnumNS::Protocol proto : ContainerProps::protocolsForContainer(container)) {
|
||||
// QString vpnConfigData =
|
||||
// createVpnConfigurationForProto(
|
||||
// serverIndex, credentials, container, containerConfig, proto, &e);
|
||||
|
||||
QJsonObject vpnConfigData = QJsonDocument::fromJson(
|
||||
createVpnConfigurationForProto(
|
||||
serverIndex, credentials, container, containerConfig, proto, &e).toUtf8()).
|
||||
|
@ -205,7 +196,6 @@ QJsonObject VpnConnection::createVpnConfiguration(int serverIndex,
|
|||
}
|
||||
|
||||
vpnConfiguration.insert(ProtocolProps::key_proto_config_data(proto), vpnConfigData);
|
||||
|
||||
}
|
||||
|
||||
Protocol proto = ContainerProps::defaultProtocol(container);
|
||||
|
@ -214,11 +204,27 @@ QJsonObject VpnConnection::createVpnConfiguration(int serverIndex,
|
|||
return vpnConfiguration;
|
||||
}
|
||||
|
||||
ErrorCode VpnConnection::connectToVpn(int serverIndex,
|
||||
void VpnConnection::connectToVpn(int serverIndex,
|
||||
const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig)
|
||||
{
|
||||
qDebug() << QString("СonnectToVpn, Server index is %1, container is %2, route mode is")
|
||||
.arg(serverIndex).arg(ContainerProps::containerToString(container)) << m_settings.routeMode();
|
||||
|
||||
#if !defined (Q_OS_ANDROID) && !defined (Q_OS_IOS)
|
||||
if (!m_IpcClient) {
|
||||
m_IpcClient = new IpcClient;
|
||||
}
|
||||
|
||||
if (!m_IpcClient->isSocketConnected()) {
|
||||
if (!IpcClient::init(m_IpcClient)) {
|
||||
qWarning() << "Error occured when init IPC client";
|
||||
emit serviceIsNotReady();
|
||||
emit connectionStateChanged(VpnProtocol::Error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
m_remoteAddress = credentials.hostName;
|
||||
|
||||
emit connectionStateChanged(VpnProtocol::Connecting);
|
||||
|
@ -233,26 +239,26 @@ ErrorCode VpnConnection::connectToVpn(int serverIndex,
|
|||
m_vpnConfiguration = createVpnConfiguration(serverIndex, credentials, container, containerConfig);
|
||||
if (e) {
|
||||
emit connectionStateChanged(VpnProtocol::Error);
|
||||
return e;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#ifndef Q_OS_ANDROID
|
||||
|
||||
m_vpnProtocol.reset(VpnProtocol::factory(container, m_vpnConfiguration));
|
||||
if (!m_vpnProtocol) {
|
||||
return ErrorCode::InternalError;
|
||||
emit VpnProtocol::Error;
|
||||
return;
|
||||
}
|
||||
|
||||
m_vpnProtocol->prepare();
|
||||
|
||||
|
||||
#else
|
||||
Protocol proto = ContainerProps::defaultProtocol(container);
|
||||
AndroidVpnProtocol *androidVpnProtocol = new AndroidVpnProtocol(proto, m_vpnConfiguration);
|
||||
if (!androidVpnProtocol->initialize()) {
|
||||
qDebug() << QString("Init failed") ;
|
||||
return UnknownError;
|
||||
emit VpnProtocol::Error;
|
||||
return;
|
||||
}
|
||||
m_vpnProtocol.reset(androidVpnProtocol);
|
||||
#endif
|
||||
|
@ -263,7 +269,8 @@ ErrorCode VpnConnection::connectToVpn(int serverIndex,
|
|||
|
||||
ServerController::disconnectFromHost(credentials);
|
||||
|
||||
return m_vpnProtocol.data()->start();
|
||||
e = m_vpnProtocol.data()->start();
|
||||
if (e) emit VpnProtocol::Error;
|
||||
}
|
||||
|
||||
QString VpnConnection::bytesPerSecToText(quint64 bytes)
|
||||
|
|
|
@ -34,10 +34,7 @@ public:
|
|||
const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
|
||||
ErrorCode connectToVpn(int serverIndex,
|
||||
const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig);
|
||||
|
||||
void disconnectFromVpn();
|
||||
|
||||
bool isConnected() const;
|
||||
bool isDisconnected() const;
|
||||
|
@ -51,6 +48,12 @@ public:
|
|||
|
||||
const QString &remoteAddress() const;
|
||||
|
||||
public slots:
|
||||
void connectToVpn(int serverIndex,
|
||||
const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig);
|
||||
|
||||
void disconnectFromVpn();
|
||||
|
||||
signals:
|
||||
void bytesChanged(quint64 receivedBytes, quint64 sentBytes);
|
||||
void connectionStateChanged(VpnProtocol::ConnectionState state);
|
||||
|
@ -70,6 +73,7 @@ private:
|
|||
QJsonObject m_vpnConfiguration;
|
||||
QJsonObject m_routeMode;
|
||||
QString m_remoteAddress;
|
||||
IpcClient *m_IpcClient {nullptr};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ signtool sign /v /sm /s My /n "Privacy Technologies OU" /fd sha256 /tr http://ti
|
|||
|
||||
echo "Copying deploy data..."
|
||||
xcopy %DEPLOY_DATA_DIR% %OUT_APP_DIR% /s /e /y /i /f
|
||||
copy "%WORK_DIR:"=%\service\wireguard-service\release\wireguard-service.exe" %OUT_APP_DIR%\wireguard\
|
||||
|
||||
del %OUT_APP_DIR%\botand.dll
|
||||
|
||||
|
|
BIN
deploy/data/windows/x32/wireguard/tunnel.dll
Normal file
BIN
deploy/data/windows/x32/wireguard/tunnel.dll
Normal file
Binary file not shown.
BIN
deploy/data/windows/x32/wireguard/wireguard.dll
Normal file
BIN
deploy/data/windows/x32/wireguard/wireguard.dll
Normal file
Binary file not shown.
BIN
deploy/data/windows/x64/wireguard/tunnel.dll
Normal file
BIN
deploy/data/windows/x64/wireguard/tunnel.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
deploy/data/windows/x64/wireguard/wireguard.dll
Normal file
BIN
deploy/data/windows/x64/wireguard/wireguard.dll
Normal file
Binary file not shown.
Binary file not shown.
|
@ -4,4 +4,7 @@
|
|||
include(common.pri)
|
||||
qtservice-uselib:SUBDIRS=buildlib
|
||||
SUBDIRS+=server
|
||||
win32 {
|
||||
SUBDIRS+=wireguard-service
|
||||
}
|
||||
}
|
||||
|
|
31
service/wireguard-service/main.cpp
Normal file
31
service/wireguard-service/main.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include "wireguardtunnelservice.h"
|
||||
#include <strsafe.h>
|
||||
#include <Windows.h>
|
||||
|
||||
int wmain(int argc, wchar_t** argv)
|
||||
{
|
||||
if (argc != 3) {
|
||||
debug_log(L"Wrong argument provided");
|
||||
return 1;
|
||||
}
|
||||
TCHAR option[20];
|
||||
TCHAR configFile[5000];
|
||||
|
||||
StringCchCopy(option, 20, argv[1]);
|
||||
StringCchCopy(configFile, 5000, argv[2]);
|
||||
|
||||
WireguardTunnelService tunnel(configFile);
|
||||
|
||||
if (lstrcmpi(option, TEXT("--run")) == 0) {
|
||||
debug_log(L"start tunnel");
|
||||
tunnel.startTunnel();
|
||||
} else if (lstrcmpi(option, TEXT("--add")) == 0) {
|
||||
tunnel.addService();
|
||||
} else if (lstrcmpi(option, TEXT("--remove")) == 0) {
|
||||
tunnel.removeService();
|
||||
} else {
|
||||
debug_log(L"Wrong argument provided");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
23
service/wireguard-service/wireguard-service.pro
Normal file
23
service/wireguard-service/wireguard-service.pro
Normal file
|
@ -0,0 +1,23 @@
|
|||
TARGET = wireguard-service
|
||||
TEMPLATE = app
|
||||
CONFIG += console
|
||||
CONFIG -= app_bundle
|
||||
CONFIG -= qt
|
||||
LIBS += \
|
||||
-luser32 \
|
||||
-lrasapi32 \
|
||||
-lshlwapi \
|
||||
-liphlpapi \
|
||||
-lws2_32 \
|
||||
-liphlpapi \
|
||||
-lgdi32 \
|
||||
-lAdvapi32 \
|
||||
-lKernel32
|
||||
|
||||
HEADERS = \
|
||||
wireguardtunnelservice.h
|
||||
|
||||
SOURCES = \
|
||||
main.cpp \
|
||||
wireguardtunnelservice.cpp
|
||||
|
160
service/wireguard-service/wireguardtunnelservice.cpp
Normal file
160
service/wireguard-service/wireguardtunnelservice.cpp
Normal file
|
@ -0,0 +1,160 @@
|
|||
#include "wireguardtunnelservice.h"
|
||||
#include <Windows.h>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <strsafe.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void debug_log(const std::wstring& msg)
|
||||
{
|
||||
std::wcerr << msg << std::endl;
|
||||
}
|
||||
|
||||
WireguardTunnelService::WireguardTunnelService(const std::wstring& configFile):
|
||||
m_configFile{configFile}
|
||||
{
|
||||
}
|
||||
|
||||
void WireguardTunnelService::addService()
|
||||
{
|
||||
SC_HANDLE scm;
|
||||
SC_HANDLE service;
|
||||
scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||
if (NULL == scm) {
|
||||
debug_log(L"OpenSCManager failed");
|
||||
return;
|
||||
}
|
||||
WCHAR szFileName[MAX_PATH];
|
||||
|
||||
GetModuleFileNameW(NULL, szFileName, MAX_PATH);
|
||||
std::wstring runCommand = szFileName;
|
||||
runCommand += TEXT(" --run ");
|
||||
runCommand += m_configFile;
|
||||
|
||||
debug_log(runCommand);
|
||||
// check if service is already running
|
||||
service = OpenServiceW(
|
||||
scm,
|
||||
SVCNAME,
|
||||
SERVICE_ALL_ACCESS
|
||||
);
|
||||
if (NULL != service) {
|
||||
//service is already running, remove it before add new service
|
||||
debug_log(L"service is already running, remove it before add new service");
|
||||
CloseServiceHandle(service);
|
||||
removeService();
|
||||
}
|
||||
service = CreateServiceW(
|
||||
scm,
|
||||
SVCNAME,
|
||||
SVCNAME,
|
||||
SERVICE_ALL_ACCESS,
|
||||
SERVICE_WIN32_OWN_PROCESS,
|
||||
SERVICE_DEMAND_START,
|
||||
SERVICE_ERROR_NORMAL,
|
||||
runCommand.c_str(),
|
||||
NULL,
|
||||
NULL,
|
||||
TEXT("Nsi\0TcpIp"),
|
||||
NULL,
|
||||
NULL);
|
||||
if (NULL == service) {
|
||||
debug_log(L"CreateServiceW failed");
|
||||
CloseServiceHandle(scm);
|
||||
return;
|
||||
}
|
||||
SERVICE_SID_INFO info;
|
||||
info.dwServiceSidType = SERVICE_SID_TYPE_UNRESTRICTED;
|
||||
if (ChangeServiceConfig2W(service,
|
||||
SERVICE_CONFIG_SERVICE_SID_INFO,
|
||||
&info) == 0) {
|
||||
debug_log(L"ChangeServiceConfig2 failed");
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(scm);
|
||||
return;
|
||||
}
|
||||
if (StartServiceW(service, 0, NULL) == 0) {
|
||||
debug_log(L"StartServiceW failed");
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(scm);
|
||||
return;
|
||||
}
|
||||
if (DeleteService(service) == 0) {
|
||||
debug_log(L"DeleteService failed");
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(scm);
|
||||
return;
|
||||
}
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(scm);
|
||||
}
|
||||
|
||||
void WireguardTunnelService::removeService()
|
||||
{
|
||||
SC_HANDLE scm;
|
||||
SC_HANDLE service;
|
||||
scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||
if (NULL == scm) {
|
||||
debug_log(L"OpenSCManager failed");
|
||||
return;
|
||||
}
|
||||
service = OpenServiceW(
|
||||
scm,
|
||||
SVCNAME,
|
||||
SERVICE_ALL_ACCESS
|
||||
);
|
||||
if (NULL == service) {
|
||||
debug_log(L"OpenServiceW failed");
|
||||
CloseServiceHandle(scm);
|
||||
return;
|
||||
}
|
||||
SERVICE_STATUS stt;
|
||||
if (ControlService(service, SERVICE_CONTROL_STOP, &stt) == 0) {
|
||||
debug_log(L"ControlService failed");
|
||||
DeleteService(service);
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(scm);
|
||||
return;
|
||||
}
|
||||
for (int i = 0;
|
||||
i < 180 && QueryServiceStatus(scm, &stt) && stt.dwCurrentState != SERVICE_STOPPED;
|
||||
++i) {
|
||||
std::this_thread::sleep_for(std::chrono::seconds{1});
|
||||
}
|
||||
DeleteService(service);
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(scm);
|
||||
}
|
||||
|
||||
|
||||
int WireguardTunnelService::startTunnel()
|
||||
{
|
||||
debug_log(TEXT(__FUNCTION__));
|
||||
|
||||
HMODULE tunnelLib = LoadLibrary(TEXT("tunnel.dll"));
|
||||
if (!tunnelLib) {
|
||||
debug_log(L"Failed to load tunnel.dll");
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef bool WireGuardTunnelService(const LPCWSTR settings);
|
||||
|
||||
WireGuardTunnelService* tunnelProc = (WireGuardTunnelService*)GetProcAddress(
|
||||
tunnelLib, "WireGuardTunnelService");
|
||||
if (!tunnelProc) {
|
||||
debug_log(L"Failed to get WireGuardTunnelService function");
|
||||
return 1;
|
||||
}
|
||||
|
||||
debug_log(m_configFile.c_str());
|
||||
|
||||
if (!tunnelProc(m_configFile.c_str())) {
|
||||
debug_log(L"Failed to activate the tunnel service");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
22
service/wireguard-service/wireguardtunnelservice.h
Normal file
22
service/wireguard-service/wireguardtunnelservice.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#ifndef WIREGUARDTUNNELSERVICE_H
|
||||
#define WIREGUARDTUNNELSERVICE_H
|
||||
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
|
||||
#define SVCNAME TEXT("AmneziaVPNWireGuardService")
|
||||
|
||||
class WireguardTunnelService
|
||||
{
|
||||
public:
|
||||
WireguardTunnelService(const std::wstring& configFile);
|
||||
void addService();
|
||||
void removeService();
|
||||
int startTunnel();
|
||||
private:
|
||||
std::wstring m_configFile;
|
||||
};
|
||||
|
||||
void debug_log(const std::wstring& msg);
|
||||
|
||||
#endif // WIREGUARDTUNNELSERVICE_H
|
Loading…
Add table
Add a link
Reference in a new issue