Merge pull request #407 from amnezia-vpn/feature/ss-and-cloak-native-configs
added native config generation for ss and cloak
This commit is contained in:
commit
1cc5c5384e
5 changed files with 171 additions and 10 deletions
|
|
@ -8,7 +8,9 @@
|
|||
#include <QImage>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include "configurators/cloak_configurator.h"
|
||||
#include "configurators/openvpn_configurator.h"
|
||||
#include "configurators/shadowsocks_configurator.h"
|
||||
#include "configurators/wireguard_configurator.h"
|
||||
#include "core/errorstrings.h"
|
||||
#include "systemController.h"
|
||||
|
|
@ -187,6 +189,88 @@ void ExportController::generateWireGuardConfig()
|
|||
m_config.append(line + "\n");
|
||||
}
|
||||
|
||||
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(m_config.toUtf8(), qrcodegen::QrCode::Ecc::LOW);
|
||||
m_qrCodes << svgToBase64(QString::fromStdString(toSvgString(qr, 1)));
|
||||
|
||||
emit exportConfigChanged();
|
||||
}
|
||||
|
||||
void ExportController::generateShadowSocksConfig()
|
||||
{
|
||||
clearPreviousConfig();
|
||||
|
||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
||||
ServerCredentials credentials =
|
||||
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
||||
|
||||
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
||||
QModelIndex containerModelIndex = m_containersModel->index(container);
|
||||
QJsonObject containerConfig =
|
||||
qvariant_cast<QJsonObject>(m_containersModel->data(containerModelIndex, ContainersModel::Roles::ConfigRole));
|
||||
containerConfig.insert(config_key::container, ContainerProps::containerToString(container));
|
||||
|
||||
ErrorCode errorCode = ErrorCode::NoError;
|
||||
QString config = m_configurator->shadowSocksConfigurator->genShadowSocksConfig(credentials, container,
|
||||
containerConfig, &errorCode);
|
||||
|
||||
if (errorCode) {
|
||||
emit exportErrorOccurred(errorString(errorCode));
|
||||
return;
|
||||
}
|
||||
config = m_configurator->processConfigWithExportSettings(serverIndex, container, Proto::ShadowSocks, config);
|
||||
QJsonObject configJson = QJsonDocument::fromJson(config.toUtf8()).object();
|
||||
|
||||
QStringList lines = QString(QJsonDocument(configJson).toJson()).replace("\r", "").split("\n");
|
||||
for (const QString &line : lines) {
|
||||
m_config.append(line + "\n");
|
||||
}
|
||||
|
||||
m_nativeConfigString =
|
||||
QString("%1:%2@%3:%4")
|
||||
.arg(configJson.value("method").toString(), configJson.value("password").toString(),
|
||||
configJson.value("server").toString(), configJson.value("server_port").toString());
|
||||
|
||||
m_nativeConfigString = "ss://" + m_nativeConfigString.toUtf8().toBase64();
|
||||
|
||||
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(m_nativeConfigString.toUtf8(), qrcodegen::QrCode::Ecc::LOW);
|
||||
m_qrCodes << svgToBase64(QString::fromStdString(toSvgString(qr, 1)));
|
||||
|
||||
emit exportConfigChanged();
|
||||
}
|
||||
|
||||
void ExportController::generateCloakConfig()
|
||||
{
|
||||
clearPreviousConfig();
|
||||
|
||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
||||
ServerCredentials credentials =
|
||||
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
||||
|
||||
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
||||
QModelIndex containerModelIndex = m_containersModel->index(container);
|
||||
QJsonObject containerConfig =
|
||||
qvariant_cast<QJsonObject>(m_containersModel->data(containerModelIndex, ContainersModel::Roles::ConfigRole));
|
||||
containerConfig.insert(config_key::container, ContainerProps::containerToString(container));
|
||||
|
||||
ErrorCode errorCode = ErrorCode::NoError;
|
||||
QString config =
|
||||
m_configurator->cloakConfigurator->genCloakConfig(credentials, container, containerConfig, &errorCode);
|
||||
|
||||
if (errorCode) {
|
||||
emit exportErrorOccurred(errorString(errorCode));
|
||||
return;
|
||||
}
|
||||
config = m_configurator->processConfigWithExportSettings(serverIndex, container, Proto::Cloak, config);
|
||||
QJsonObject configJson = QJsonDocument::fromJson(config.toUtf8()).object();
|
||||
|
||||
configJson.remove(config_key::transport_proto);
|
||||
configJson.insert("ProxyMethod", "shadowsocks");
|
||||
|
||||
QStringList lines = QString(QJsonDocument(configJson).toJson()).replace("\r", "").split("\n");
|
||||
for (const QString &line : lines) {
|
||||
m_config.append(line + "\n");
|
||||
}
|
||||
|
||||
emit exportConfigChanged();
|
||||
}
|
||||
|
||||
|
|
@ -195,6 +279,11 @@ QString ExportController::getConfig()
|
|||
return m_config;
|
||||
}
|
||||
|
||||
QString ExportController::getNativeConfigString()
|
||||
{
|
||||
return m_nativeConfigString;
|
||||
}
|
||||
|
||||
QList<QString> ExportController::getQrCodes()
|
||||
{
|
||||
return m_qrCodes;
|
||||
|
|
@ -219,7 +308,7 @@ QList<QString> ExportController::generateQrCodeImageSeries(const QByteArray &dat
|
|||
QByteArray ba = chunk.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||
|
||||
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(ba, qrcodegen::QrCode::Ecc::LOW);
|
||||
QString svg = QString::fromStdString(toSvgString(qr, 0));
|
||||
QString svg = QString::fromStdString(toSvgString(qr, 1));
|
||||
chunks.append(svgToBase64(svg));
|
||||
}
|
||||
|
||||
|
|
@ -239,5 +328,6 @@ int ExportController::getQrCodesCount()
|
|||
void ExportController::clearPreviousConfig()
|
||||
{
|
||||
m_config.clear();
|
||||
m_nativeConfigString.clear();
|
||||
m_qrCodes.clear();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ public:
|
|||
Q_PROPERTY(QList<QString> qrCodes READ getQrCodes NOTIFY exportConfigChanged)
|
||||
Q_PROPERTY(int qrCodesCount READ getQrCodesCount NOTIFY exportConfigChanged)
|
||||
Q_PROPERTY(QString config READ getConfig NOTIFY exportConfigChanged)
|
||||
Q_PROPERTY(QString nativeConfigString READ getNativeConfigString NOTIFY exportConfigChanged)
|
||||
|
||||
public slots:
|
||||
void generateFullAccessConfig();
|
||||
|
|
@ -31,8 +32,11 @@ public slots:
|
|||
void generateConnectionConfig();
|
||||
void generateOpenVpnConfig();
|
||||
void generateWireGuardConfig();
|
||||
void generateShadowSocksConfig();
|
||||
void generateCloakConfig();
|
||||
|
||||
QString getConfig();
|
||||
QString getNativeConfigString();
|
||||
QList<QString> getQrCodes();
|
||||
|
||||
void exportConfig(const QString &fileName);
|
||||
|
|
@ -59,6 +63,7 @@ private:
|
|||
std::shared_ptr<VpnConfigurator> m_configurator;
|
||||
|
||||
QString m_config;
|
||||
QString m_nativeConfigString;
|
||||
QList<QString> m_qrCodes;
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
|
|
|
|||
|
|
@ -112,6 +112,30 @@ DrawerType {
|
|||
}
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 8
|
||||
|
||||
visible: nativeConfigString.text !== ""
|
||||
|
||||
defaultColor: "transparent"
|
||||
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||
pressedColor: Qt.rgba(1, 1, 1, 0.12)
|
||||
disabledColor: "#878B91"
|
||||
textColor: "#D7D8DB"
|
||||
borderWidth: 1
|
||||
|
||||
text: qsTr("Copy config string")
|
||||
imageSource: "qrc:/images/controls/copy.svg"
|
||||
|
||||
onClicked: {
|
||||
nativeConfigString.selectAll()
|
||||
nativeConfigString.copy()
|
||||
nativeConfigString.select(0, 0)
|
||||
PageController.showNotificationMessage(qsTr("Copied"))
|
||||
}
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
|
|
@ -170,6 +194,12 @@ DrawerType {
|
|||
}
|
||||
|
||||
TextField {
|
||||
id: nativeConfigString
|
||||
visible: false
|
||||
text: ExportController.nativeConfigString
|
||||
}
|
||||
|
||||
TextArea {
|
||||
id: configText
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
|
@ -213,7 +243,6 @@ DrawerType {
|
|||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 2
|
||||
smooth: false
|
||||
|
||||
source: ExportController.qrCodesCount ? ExportController.qrCodes[0] : ""
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ PageType {
|
|||
regularExpression: InstallController.ipAddressPortRegExp()
|
||||
}
|
||||
|
||||
onTextFieldTextChanged: {
|
||||
onFocusChanged: {
|
||||
textField.text = textField.text.replace(/^\s+|\s+$/g, '');
|
||||
}
|
||||
}
|
||||
|
|
@ -81,6 +81,10 @@ PageType {
|
|||
clickedFunc: function() {
|
||||
hidePassword = !hidePassword
|
||||
}
|
||||
|
||||
onFocusChanged: {
|
||||
textField.text = textField.text.replace(/^\s+|\s+$/g, '');
|
||||
}
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
|
|
@ -90,6 +94,7 @@ PageType {
|
|||
text: qsTr("Continue")
|
||||
|
||||
onClicked: function() {
|
||||
forceActiveFocus()
|
||||
if (!isCredentialsFilled()) {
|
||||
return
|
||||
}
|
||||
|
|
@ -112,8 +117,7 @@ PageType {
|
|||
Layout.fillWidth: true
|
||||
Layout.topMargin: 12
|
||||
|
||||
text: qsTr("All data you enter will remain strictly confidential
|
||||
and will not be shared or disclosed to the Amnezia or any third parties")
|
||||
text: qsTr("All data you enter will remain strictly confidential and will not be shared or disclosed to the Amnezia or any third parties")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@ PageType {
|
|||
AmneziaConnection,
|
||||
AmneziaFullAccess,
|
||||
OpenVpn,
|
||||
WireGuard
|
||||
WireGuard,
|
||||
ShadowSocks,
|
||||
Cloak
|
||||
}
|
||||
|
||||
Connections {
|
||||
|
|
@ -44,18 +46,32 @@ PageType {
|
|||
break;
|
||||
}
|
||||
case PageShare.ConfigType.OpenVpn: {
|
||||
ExportController.generateOpenVpnConfig();
|
||||
ExportController.generateOpenVpnConfig()
|
||||
shareConnectionDrawer.configCaption = qsTr("Save OpenVPN config")
|
||||
shareConnectionDrawer.configExtension = ".ovpn"
|
||||
shareConnectionDrawer.configFileName = "amnezia_for_openvpn"
|
||||
break;
|
||||
break
|
||||
}
|
||||
case PageShare.ConfigType.WireGuard: {
|
||||
ExportController.generateWireGuardConfig();
|
||||
ExportController.generateWireGuardConfig()
|
||||
shareConnectionDrawer.configCaption = qsTr("Save WireGuard config")
|
||||
shareConnectionDrawer.configExtension = ".conf"
|
||||
shareConnectionDrawer.configFileName = "amnezia_for_wireguard"
|
||||
break;
|
||||
break
|
||||
}
|
||||
case PageShare.ConfigType.ShadowSocks: {
|
||||
ExportController.generateShadowSocksConfig()
|
||||
shareConnectionDrawer.configCaption = qsTr("Save ShadowSocks config")
|
||||
shareConnectionDrawer.configExtension = ".json"
|
||||
shareConnectionDrawer.configFileName = "amnezia_for_shadowsocks"
|
||||
break
|
||||
}
|
||||
case PageShare.ConfigType.Cloak: {
|
||||
ExportController.generateCloakConfig()
|
||||
shareConnectionDrawer.configCaption = qsTr("Save Cloak config")
|
||||
shareConnectionDrawer.configExtension = ".json"
|
||||
shareConnectionDrawer.configFileName = "amnezia_for_cloak"
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -96,6 +112,16 @@ PageType {
|
|||
property string name: qsTr("WireGuard native format")
|
||||
property var type: PageShare.ConfigType.WireGuard
|
||||
}
|
||||
QtObject {
|
||||
id: shadowSocksConnectionFormat
|
||||
property string name: qsTr("ShadowSocks native format")
|
||||
property var type: PageShare.ConfigType.ShadowSocks
|
||||
}
|
||||
QtObject {
|
||||
id: cloakConnectionFormat
|
||||
property string name: qsTr("Cloak native format")
|
||||
property var type: PageShare.ConfigType.Cloak
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
anchors.top: parent.top
|
||||
|
|
@ -322,6 +348,13 @@ PageType {
|
|||
root.connectionTypesModel.push(openVpnConnectionFormat)
|
||||
} else if (index === ContainerProps.containerFromString("amnezia-wireguard")) {
|
||||
root.connectionTypesModel.push(wireGuardConnectionFormat)
|
||||
} else if (index === ContainerProps.containerFromString("amnezia-shadowsocks")) {
|
||||
root.connectionTypesModel.push(openVpnConnectionFormat)
|
||||
root.connectionTypesModel.push(shadowSocksConnectionFormat)
|
||||
} else if (index === ContainerProps.containerFromString("amnezia-openvpn-cloak")) {
|
||||
root.connectionTypesModel.push(openVpnConnectionFormat)
|
||||
root.connectionTypesModel.push(shadowSocksConnectionFormat)
|
||||
root.connectionTypesModel.push(cloakConnectionFormat)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue