mirror of
https://github.com/Qv2ray/Qv2ray.git
synced 2025-05-20 02:40:20 +08:00
refactor: stage 3.5 class separation
This commit is contained in:
parent
a2d5920959
commit
36dc29bd9c
@ -1 +1 @@
|
|||||||
3403
|
3423
|
||||||
|
@ -120,9 +120,9 @@ Qv2rayAddSource(components, proxy, QvProxyConfigurator, cpp, hpp)
|
|||||||
Qv2rayAddSource(components, tcping, QvTCPing, cpp, hpp)
|
Qv2rayAddSource(components, tcping, QvTCPing, cpp, hpp)
|
||||||
Qv2rayAddSource(core, config, ConfigBackend, cpp, hpp)
|
Qv2rayAddSource(core, config, ConfigBackend, cpp, hpp)
|
||||||
Qv2rayAddSource(core, config, ConfigUpgrade, cpp)
|
Qv2rayAddSource(core, config, ConfigUpgrade, cpp)
|
||||||
Qv2rayAddSource(core, connection, ConnectionConfig_Convertion, cpp)
|
Qv2rayAddSource(core, connection, ConnectionIO, cpp, hpp)
|
||||||
Qv2rayAddSource(core, connection, ConnectionConfig_Generation, cpp)
|
Qv2rayAddSource(core, connection, Generation, cpp, hpp)
|
||||||
Qv2rayAddSource(core, connection, ConnectionConfigOperations, cpp, hpp)
|
Qv2rayAddSource(core, connection, Serialization, cpp, hpp)
|
||||||
Qv2rayAddSource(core, _, CoreUtils, cpp, hpp)
|
Qv2rayAddSource(core, _, CoreUtils, cpp, hpp)
|
||||||
Qv2rayAddSource(core, kernel, QvKernelInteractions, cpp, hpp)
|
Qv2rayAddSource(core, kernel, QvKernelInteractions, cpp, hpp)
|
||||||
Qv2rayAddSource(ui, editors, w_InboundEditor, cpp, hpp, ui)
|
Qv2rayAddSource(ui, editors, w_InboundEditor, cpp, hpp, ui)
|
||||||
|
@ -93,6 +93,18 @@ extern const bool isDebugBuild;
|
|||||||
|
|
||||||
#define QSTRN(num) QString::number(num)
|
#define QSTRN(num) QString::number(num)
|
||||||
|
|
||||||
|
|
||||||
|
#define OUTBOUND_TAG_DIRECT "outBound_DIRECT"
|
||||||
|
#define OUTBOUND_TAG_PROXY "outBound_PROXY"
|
||||||
|
#define OUTBOUND_TAG_FORWARD_PROXY "_QV2RAY_FORWARD_PROXY_"
|
||||||
|
|
||||||
|
#define API_TAG_DEFAULT "_QV2RAY_API_"
|
||||||
|
#define API_TAG_INBOUND "_QV2RAY_API_INBOUND_"
|
||||||
|
|
||||||
|
#define QV2RAY_USE_FPROXY_KEY "_QV2RAY_USE_GLOBAL_FORWARD_PROXY_"
|
||||||
|
|
||||||
|
#define JSON_ROOT_TRY_REMOVE(obj) if (root.contains(obj)) { root.remove(obj); }
|
||||||
|
|
||||||
namespace Qv2ray
|
namespace Qv2ray
|
||||||
{
|
{
|
||||||
// Extra header for QvConfigUpgrade.cpp
|
// Extra header for QvConfigUpgrade.cpp
|
||||||
|
@ -53,5 +53,13 @@ namespace Qv2ray::core
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CheckIsComplexConfig(CONFIGROOT root)
|
||||||
|
{
|
||||||
|
bool cRouting = root.contains("routing");
|
||||||
|
bool cRule = cRouting && root["routing"].toObject().contains("rules");
|
||||||
|
bool cRules = cRule && root["routing"].toObject()["rules"].toArray().count() > 0;
|
||||||
|
return cRules;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ namespace Qv2ray::core
|
|||||||
|
|
||||||
tuple<QString, int, QString> GetConnectionInfo(const CONFIGROOT &alias);
|
tuple<QString, int, QString> GetConnectionInfo(const CONFIGROOT &alias);
|
||||||
bool GetOutboundData(const OUTBOUND &out, QString *host, int *port, QString *protocol);
|
bool GetOutboundData(const OUTBOUND &out, QString *host, int *port, QString *protocol);
|
||||||
|
bool CheckIsComplexConfig(CONFIGROOT root);
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace Qv2ray::core;
|
using namespace Qv2ray::core;
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
#include "ConnectionConfigOperations.hpp"
|
|
||||||
#include "common/QvHelpers.hpp"
|
|
||||||
|
|
||||||
namespace Qv2ray::core::connection
|
|
||||||
{
|
|
||||||
CONFIGROOT _ReadConnection(const QString &connection)
|
|
||||||
{
|
|
||||||
QString jsonString = StringFromFile(new QFile(connection));
|
|
||||||
auto conf = CONFIGROOT(JsonFromString(jsonString));
|
|
||||||
|
|
||||||
if (conf.count() == 0) {
|
|
||||||
LOG(MODULE_CONFIG, "WARN: Possible file corruption, failed to load file: " + connection + " --> File might be empty.")
|
|
||||||
}
|
|
||||||
|
|
||||||
return conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
QMap<QString, CONFIGROOT> GetRegularConnections(QStringList connectionNames)
|
|
||||||
{
|
|
||||||
QMap<QString, CONFIGROOT> list;
|
|
||||||
|
|
||||||
for (auto conn : connectionNames) {
|
|
||||||
list.insert(conn, _ReadConnection(QV2RAY_CONFIG_DIR + conn + QV2RAY_CONFIG_FILE_EXTENSION));
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
QMap<QString, CONFIGROOT> GetSubscriptionConnection(QString subscription)
|
|
||||||
{
|
|
||||||
auto _files = GetFileList(QV2RAY_SUBSCRIPTION_DIR + subscription);
|
|
||||||
QMap<QString, CONFIGROOT> _config;
|
|
||||||
|
|
||||||
for (auto _file : _files) {
|
|
||||||
// check if is proper connection file.
|
|
||||||
if (_file.endsWith(QV2RAY_CONFIG_FILE_EXTENSION)) {
|
|
||||||
auto confName = _file;
|
|
||||||
// Remove the extension
|
|
||||||
confName.chop(sizeof(QV2RAY_CONFIG_FILE_EXTENSION) - 1);
|
|
||||||
_config[confName] = _ReadConnection(QV2RAY_SUBSCRIPTION_DIR + subscription + "/" + _file);
|
|
||||||
} else {
|
|
||||||
LOG(MODULE_SUBSCRIPTION, "Found a file in subscription folder but without proper suffix: " + _file)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_config.isEmpty()) {
|
|
||||||
LOG(MODULE_SUBSCRIPTION, "WARN: Maybe loading an empty subscrption: " + subscription)
|
|
||||||
}
|
|
||||||
|
|
||||||
return _config;
|
|
||||||
}
|
|
||||||
|
|
||||||
QMap<QString, QMap<QString, CONFIGROOT>> GetSubscriptionConnections(QStringList subscriptions)
|
|
||||||
{
|
|
||||||
// SUB-NAME CONN-NAME CONN-ROOT
|
|
||||||
QMap<QString, QMap<QString, CONFIGROOT>> list;
|
|
||||||
|
|
||||||
for (auto singleSub : subscriptions) {
|
|
||||||
LOG(MODULE_SUBSCRIPTION, "Processing subscription: " + singleSub)
|
|
||||||
list[singleSub] = GetSubscriptionConnection(singleSub);
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
bool CheckIsComplexConfig(CONFIGROOT root)
|
|
||||||
{
|
|
||||||
bool cRouting = root.contains("routing");
|
|
||||||
bool cRule = cRouting && root["routing"].toObject().contains("rules");
|
|
||||||
bool cRules = cRule && root["routing"].toObject()["rules"].toArray().count() > 0;
|
|
||||||
return cRules;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "base/Qv2rayBase.hpp"
|
|
||||||
|
|
||||||
#define OUTBOUND_TAG_DIRECT "outBound_DIRECT"
|
|
||||||
#define OUTBOUND_TAG_PROXY "outBound_PROXY"
|
|
||||||
#define OUTBOUND_TAG_FORWARD_PROXY "_QV2RAY_FORWARD_PROXY_"
|
|
||||||
|
|
||||||
#define API_TAG_DEFAULT "_QV2RAY_API_"
|
|
||||||
#define API_TAG_INBOUND "_QV2RAY_API_INBOUND_"
|
|
||||||
|
|
||||||
#define QV2RAY_USE_FPROXY_KEY "_QV2RAY_USE_GLOBAL_FORWARD_PROXY_"
|
|
||||||
|
|
||||||
#define JSON_ROOT_TRY_REMOVE(obj) if (root.contains(obj)) { root.remove(obj); }
|
|
||||||
|
|
||||||
namespace Qv2ray::core::connection
|
|
||||||
{
|
|
||||||
// -------------------------- BEGIN GENERAL FUNCTIONS ----------------------------------------------
|
|
||||||
|
|
||||||
QMap<QString, CONFIGROOT> GetRegularConnections(QStringList connections);
|
|
||||||
QMap<QString, CONFIGROOT> GetSubscriptionConnection(QString subscription);
|
|
||||||
QMap<QString, QMap<QString, CONFIGROOT>> GetSubscriptionConnections(QStringList subscriptions);
|
|
||||||
bool CheckIsComplexConfig(CONFIGROOT root);
|
|
||||||
|
|
||||||
//
|
|
||||||
// -------------------------- BEGIN CONFIG CONVERSIONS --------------------------
|
|
||||||
inline namespace Convertion
|
|
||||||
{
|
|
||||||
//int VerifyVMessProtocolString(QString vmess);
|
|
||||||
QString DecodeSubscriptionString(QByteArray arr);
|
|
||||||
//
|
|
||||||
// Save Connection Config
|
|
||||||
bool SaveConnectionConfig(CONFIGROOT obj, QString *alias, bool canOverrideExisting);
|
|
||||||
bool SaveSubscriptionConfig(CONFIGROOT obj, const QString &subscription, QString *name);
|
|
||||||
bool RemoveConnection(const QString &alias);
|
|
||||||
bool RemoveSubscriptionConnection(const QString &subsName, const QString &name);
|
|
||||||
bool RenameConnection(const QString &originalName, const QString &newName);
|
|
||||||
bool RenameSubscription(const QString &originalName, const QString &newName);
|
|
||||||
|
|
||||||
// VMess URI Protocol
|
|
||||||
CONFIGROOT ConvertConfigFromVMessString(const QString &vmess, QString *alias, QString *errMessage);
|
|
||||||
CONFIGROOT ConvertConfigFromFile(QString sourceFilePath, bool keepInbounds);
|
|
||||||
QString ConvertConfigToVMessString(const StreamSettingsObject &transfer, const VMessServerObject &serverConfig, const QString &alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// -------------------------- BEGIN CONFIG GENERATIONS ---------------------------------------------
|
|
||||||
inline namespace Generation
|
|
||||||
{
|
|
||||||
ROUTING GenerateRoutes(bool enableProxy, bool cnProxy);
|
|
||||||
ROUTERULE GenerateSingleRouteRule(QStringList list, bool isDomain, QString outboundTag, QString type = "field");
|
|
||||||
QJsonObject GenerateDNS(bool withLocalhost, QStringList dnsServers);
|
|
||||||
QJsonObject GenerateAPIEntry(QString tag, bool withHandler = true, bool withLogger = true, bool withStats = true);
|
|
||||||
//
|
|
||||||
// Outbound Protocols
|
|
||||||
OUTBOUNDSETTING GenerateFreedomOUT(QString domainStrategy, QString redirect, int userLevel);
|
|
||||||
OUTBOUNDSETTING GenerateBlackHoleOUT(bool useHTTP);
|
|
||||||
OUTBOUNDSETTING GenerateShadowSocksServerOUT(QString email, QString address, int port, QString method, QString password, bool ota, int level);
|
|
||||||
OUTBOUNDSETTING GenerateShadowSocksOUT(QList<QJsonObject> servers);
|
|
||||||
OUTBOUNDSETTING GenerateHTTPSOCKSOut(QString address, int port, bool useAuth, QString username, QString password);
|
|
||||||
//
|
|
||||||
// Inbounds Protocols
|
|
||||||
INBOUNDSETTING GenerateDokodemoIN(QString address, int port, QString network, int timeout, bool followRedirect, int userLevel);
|
|
||||||
INBOUNDSETTING GenerateHTTPIN(QList<AccountObject> accounts, int timeout = 300, bool allowTransparent = true, int userLevel = 0);
|
|
||||||
INBOUNDSETTING GenerateSocksIN(QString auth, QList<AccountObject> _accounts, bool udp = false, QString ip = "127.0.0.1", int userLevel = 0);
|
|
||||||
//
|
|
||||||
// Generate FINAL Configs
|
|
||||||
CONFIGROOT GenerateRuntimeConfig(CONFIGROOT root);
|
|
||||||
OUTBOUND GenerateOutboundEntry(QString protocol, OUTBOUNDSETTING settings, QJsonObject streamSettings, QJsonObject mux = QJsonObject(), QString sendThrough = "0.0.0.0", QString tag = "");
|
|
||||||
INBOUND GenerateInboundEntry(QString listen, int port, QString protocol, INBOUNDSETTING settings, QString tag, QJsonObject sniffing = QJsonObject(), QJsonObject allocate = QJsonObject());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace Qv2ray::core;
|
|
||||||
using namespace Qv2ray::core::connection;
|
|
172
src/core/connection/ConnectionIO.cpp
Normal file
172
src/core/connection/ConnectionIO.cpp
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
#include "ConnectionIO.hpp"
|
||||||
|
#include "common/QvHelpers.hpp"
|
||||||
|
|
||||||
|
namespace Qv2ray::core::connection
|
||||||
|
{
|
||||||
|
namespace ConnectionIO
|
||||||
|
{
|
||||||
|
CONFIGROOT _ReadConnection(const QString &connection)
|
||||||
|
{
|
||||||
|
QString jsonString = StringFromFile(new QFile(connection));
|
||||||
|
auto conf = CONFIGROOT(JsonFromString(jsonString));
|
||||||
|
|
||||||
|
if (conf.count() == 0) {
|
||||||
|
LOG(MODULE_CONFIG, "WARN: Possible file corruption, failed to load file: " + connection + " --> File might be empty.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, CONFIGROOT> GetRegularConnections(QStringList connectionNames)
|
||||||
|
{
|
||||||
|
QMap<QString, CONFIGROOT> list;
|
||||||
|
|
||||||
|
for (auto conn : connectionNames) {
|
||||||
|
list.insert(conn, _ReadConnection(QV2RAY_CONFIG_DIR + conn + QV2RAY_CONFIG_FILE_EXTENSION));
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, CONFIGROOT> GetSubscriptionConnection(QString subscription)
|
||||||
|
{
|
||||||
|
auto _files = GetFileList(QV2RAY_SUBSCRIPTION_DIR + subscription);
|
||||||
|
QMap<QString, CONFIGROOT> _config;
|
||||||
|
|
||||||
|
for (auto _file : _files) {
|
||||||
|
// check if is proper connection file.
|
||||||
|
if (_file.endsWith(QV2RAY_CONFIG_FILE_EXTENSION)) {
|
||||||
|
auto confName = _file;
|
||||||
|
// Remove the extension
|
||||||
|
confName.chop(sizeof(QV2RAY_CONFIG_FILE_EXTENSION) - 1);
|
||||||
|
_config[confName] = _ReadConnection(QV2RAY_SUBSCRIPTION_DIR + subscription + "/" + _file);
|
||||||
|
} else {
|
||||||
|
LOG(MODULE_SUBSCRIPTION, "Found a file in subscription folder but without proper suffix: " + _file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_config.isEmpty()) {
|
||||||
|
LOG(MODULE_SUBSCRIPTION, "WARN: Maybe loading an empty subscrption: " + subscription)
|
||||||
|
}
|
||||||
|
|
||||||
|
return _config;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, QMap<QString, CONFIGROOT>> GetSubscriptionConnections(QStringList subscriptions)
|
||||||
|
{
|
||||||
|
// SUB-NAME CONN-NAME CONN-ROOT
|
||||||
|
QMap<QString, QMap<QString, CONFIGROOT>> list;
|
||||||
|
|
||||||
|
for (auto singleSub : subscriptions) {
|
||||||
|
LOG(MODULE_SUBSCRIPTION, "Processing subscription: " + singleSub)
|
||||||
|
list[singleSub] = GetSubscriptionConnection(singleSub);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Save Connection to a place, with checking if there's existing file.
|
||||||
|
// If so, append "_N" to the name.
|
||||||
|
bool SaveConnectionConfig(CONFIGROOT obj, QString *alias, bool canOverrideExisting)
|
||||||
|
{
|
||||||
|
auto str = JsonToString(obj);
|
||||||
|
QFile *config = new QFile(QV2RAY_CONFIG_DIR + *alias + QV2RAY_CONFIG_FILE_EXTENSION);
|
||||||
|
|
||||||
|
// If there's already a file AND we CANNOT override existing file.
|
||||||
|
if (config->exists() && !canOverrideExisting) {
|
||||||
|
// Alias is a pointer to a QString.
|
||||||
|
DeducePossibleFileName(QV2RAY_CONFIG_DIR, alias, QV2RAY_CONFIG_FILE_EXTENSION);
|
||||||
|
config = new QFile(QV2RAY_CONFIG_DIR + *alias + QV2RAY_CONFIG_FILE_EXTENSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(MODULE_CONFIG, "Saving a config named: " + *alias)
|
||||||
|
return StringToFile(&str, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SaveSubscriptionConfig(CONFIGROOT obj, const QString &subscription, QString *name)
|
||||||
|
{
|
||||||
|
auto str = JsonToString(obj);
|
||||||
|
auto fName = *name;
|
||||||
|
|
||||||
|
if (!IsValidFileName(fName)) {
|
||||||
|
fName = RemoveInvalidFileName(fName);
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile *config = new QFile(QV2RAY_SUBSCRIPTION_DIR + subscription + "/" + fName + QV2RAY_CONFIG_FILE_EXTENSION);
|
||||||
|
|
||||||
|
// If there's already a file. THIS IS EXTREMELY RARE
|
||||||
|
if (config->exists()) {
|
||||||
|
LOG(MODULE_FILE, "Trying to overrwrite an existing subscription config file. THIS IS RARE")
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(MODULE_CONFIG, "Saving a subscription named: " + fName)
|
||||||
|
bool result = StringToFile(&str, config);
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
LOG(MODULE_FILE, "Failed to save a connection config from subscription: " + subscription + ", name: " + fName)
|
||||||
|
}
|
||||||
|
|
||||||
|
*name = fName;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RemoveConnection(const QString &alias)
|
||||||
|
{
|
||||||
|
QFile config(QV2RAY_CONFIG_DIR + alias + QV2RAY_CONFIG_FILE_EXTENSION);
|
||||||
|
|
||||||
|
if (!config.exists()) {
|
||||||
|
LOG(MODULE_FILE, "Trying to remove a non-existing file?")
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return config.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RemoveSubscriptionConnection(const QString &subsName, const QString &name)
|
||||||
|
{
|
||||||
|
QFile config(QV2RAY_SUBSCRIPTION_DIR + subsName + "/" + name + QV2RAY_CONFIG_FILE_EXTENSION);
|
||||||
|
|
||||||
|
if (!config.exists()) {
|
||||||
|
LOG(MODULE_FILE, "Trying to remove a non-existing file?")
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return config.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RenameConnection(const QString &originalName, const QString &newName)
|
||||||
|
{
|
||||||
|
LOG(MODULE_CONFIG, "[RENAME] --> ORIGINAL: " + originalName + ", NEW: " + newName)
|
||||||
|
return QFile::rename(QV2RAY_CONFIG_DIR + originalName + QV2RAY_CONFIG_FILE_EXTENSION, QV2RAY_CONFIG_DIR + newName + QV2RAY_CONFIG_FILE_EXTENSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RenameSubscription(const QString &originalName, const QString &newName)
|
||||||
|
{
|
||||||
|
LOG(MODULE_SUBSCRIPTION, "[RENAME] --> ORIGINAL: " + originalName + ", NEW: " + newName)
|
||||||
|
return QDir().rename(QV2RAY_SUBSCRIPTION_DIR + originalName, QV2RAY_SUBSCRIPTION_DIR + newName);
|
||||||
|
}
|
||||||
|
|
||||||
|
CONFIGROOT ConvertConfigFromFile(QString sourceFilePath, bool keepInbounds)
|
||||||
|
{
|
||||||
|
QFile source(sourceFilePath);
|
||||||
|
|
||||||
|
if (!source.exists()) {
|
||||||
|
LOG(MODULE_FILE, "Trying to import from an non-existing file.")
|
||||||
|
return CONFIGROOT();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto root = CONFIGROOT(JsonFromString(StringFromFile(&source)));
|
||||||
|
|
||||||
|
if (!keepInbounds) {
|
||||||
|
JSON_ROOT_TRY_REMOVE("inbounds")
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_ROOT_TRY_REMOVE("log")
|
||||||
|
JSON_ROOT_TRY_REMOVE("api")
|
||||||
|
JSON_ROOT_TRY_REMOVE("stats")
|
||||||
|
JSON_ROOT_TRY_REMOVE("dns")
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
src/core/connection/ConnectionIO.hpp
Normal file
28
src/core/connection/ConnectionIO.hpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include "base/Qv2rayBase.hpp"
|
||||||
|
|
||||||
|
namespace Qv2ray::core::connection
|
||||||
|
{
|
||||||
|
namespace ConnectionIO
|
||||||
|
{
|
||||||
|
QMap<QString, CONFIGROOT> GetRegularConnections(QStringList connections);
|
||||||
|
QMap<QString, CONFIGROOT> GetSubscriptionConnection(QString subscription);
|
||||||
|
QMap<QString, QMap<QString, CONFIGROOT>> GetSubscriptionConnections(QStringList subscriptions);
|
||||||
|
//
|
||||||
|
// Save Connection Config
|
||||||
|
bool SaveConnectionConfig(CONFIGROOT obj, QString *alias, bool canOverrideExisting);
|
||||||
|
bool SaveSubscriptionConfig(CONFIGROOT obj, const QString &subscription, QString *name);
|
||||||
|
//
|
||||||
|
bool RemoveConnection(const QString &alias);
|
||||||
|
bool RemoveSubscriptionConnection(const QString &subsName, const QString &name);
|
||||||
|
//
|
||||||
|
bool RenameConnection(const QString &originalName, const QString &newName);
|
||||||
|
bool RenameSubscription(const QString &originalName, const QString &newName);
|
||||||
|
|
||||||
|
// File Protocol
|
||||||
|
CONFIGROOT ConvertConfigFromFile(QString sourceFilePath, bool keepInbounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace Qv2ray::core;
|
||||||
|
using namespace Qv2ray::core::connection;
|
||||||
|
using namespace Qv2ray::core::connection::ConnectionIO;
|
@ -1,12 +1,11 @@
|
|||||||
#include "ConnectionConfigOperations.hpp"
|
#include "Generation.hpp"
|
||||||
|
#include "core/CoreUtils.hpp"
|
||||||
#include "common/QvHelpers.hpp"
|
#include "common/QvHelpers.hpp"
|
||||||
|
|
||||||
namespace Qv2ray::core::connection
|
namespace Qv2ray::core::connection
|
||||||
{
|
{
|
||||||
inline namespace Generation
|
namespace Generation
|
||||||
{
|
{
|
||||||
// Important config generation algorithms.
|
|
||||||
static const QStringList vLogLevels = {"none", "debug", "info", "warning", "error"};
|
|
||||||
// -------------------------- BEGIN CONFIG GENERATIONS ----------------------------------------------------------------------------
|
// -------------------------- BEGIN CONFIG GENERATIONS ----------------------------------------------------------------------------
|
||||||
ROUTING GenerateRoutes(bool enableProxy, bool proxyCN)
|
ROUTING GenerateRoutes(bool enableProxy, bool proxyCN)
|
||||||
{
|
{
|
||||||
@ -57,13 +56,13 @@ namespace Qv2ray::core::connection
|
|||||||
RROOT
|
RROOT
|
||||||
}
|
}
|
||||||
|
|
||||||
OUTBOUNDSETTING GenerateShadowSocksOUT(QList<QJsonObject> servers)
|
OUTBOUNDSETTING GenerateShadowSocksOUT(QList<ShadowSocksServerObject> servers)
|
||||||
{
|
{
|
||||||
OUTBOUNDSETTING root;
|
OUTBOUNDSETTING root;
|
||||||
QJsonArray x;
|
QJsonArray x;
|
||||||
|
|
||||||
foreach (auto server, servers) {
|
foreach (auto server, servers) {
|
||||||
x.append(server);
|
x.append(GenerateShadowSocksServerOUT(server.email, server.address, server.port, server.method, server.password, server.ota, server.level));
|
||||||
}
|
}
|
||||||
|
|
||||||
root.insert("servers", x);
|
root.insert("servers", x);
|
35
src/core/connection/Generation.hpp
Normal file
35
src/core/connection/Generation.hpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include "base/Qv2rayBase.hpp"
|
||||||
|
|
||||||
|
namespace Qv2ray::core::connection
|
||||||
|
{
|
||||||
|
namespace Generation
|
||||||
|
{
|
||||||
|
// Important config generation algorithms.
|
||||||
|
const QStringList vLogLevels = {"none", "debug", "info", "warning", "error"};
|
||||||
|
ROUTING GenerateRoutes(bool enableProxy, bool cnProxy);
|
||||||
|
ROUTERULE GenerateSingleRouteRule(QStringList list, bool isDomain, QString outboundTag, QString type = "field");
|
||||||
|
QJsonObject GenerateDNS(bool withLocalhost, QStringList dnsServers);
|
||||||
|
QJsonObject GenerateAPIEntry(QString tag, bool withHandler = true, bool withLogger = true, bool withStats = true);
|
||||||
|
//
|
||||||
|
// Outbound Protocols
|
||||||
|
OUTBOUNDSETTING GenerateFreedomOUT(QString domainStrategy, QString redirect, int userLevel);
|
||||||
|
OUTBOUNDSETTING GenerateBlackHoleOUT(bool useHTTP);
|
||||||
|
OUTBOUNDSETTING GenerateShadowSocksOUT(QList<ShadowSocksServerObject> servers);
|
||||||
|
OUTBOUNDSETTING GenerateShadowSocksServerOUT(QString email, QString address, int port, QString method, QString password, bool ota, int level);
|
||||||
|
OUTBOUNDSETTING GenerateHTTPSOCKSOut(QString address, int port, bool useAuth, QString username, QString password);
|
||||||
|
//
|
||||||
|
// Inbounds Protocols
|
||||||
|
INBOUNDSETTING GenerateDokodemoIN(QString address, int port, QString network, int timeout, bool followRedirect, int userLevel);
|
||||||
|
INBOUNDSETTING GenerateHTTPIN(QList<AccountObject> accounts, int timeout = 300, bool allowTransparent = true, int userLevel = 0);
|
||||||
|
INBOUNDSETTING GenerateSocksIN(QString auth, QList<AccountObject> _accounts, bool udp = false, QString ip = "127.0.0.1", int userLevel = 0);
|
||||||
|
//
|
||||||
|
// Generate FINAL Configs
|
||||||
|
CONFIGROOT GenerateRuntimeConfig(CONFIGROOT root);
|
||||||
|
OUTBOUND GenerateOutboundEntry(QString protocol, OUTBOUNDSETTING settings, QJsonObject streamSettings, QJsonObject mux = QJsonObject(), QString sendThrough = "0.0.0.0", QString tag = OUTBOUND_TAG_PROXY);
|
||||||
|
INBOUND GenerateInboundEntry(QString listen, int port, QString protocol, INBOUNDSETTING settings, QString tag, QJsonObject sniffing = QJsonObject(), QJsonObject allocate = QJsonObject());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace Qv2ray::core;
|
||||||
|
using namespace Qv2ray::core::connection;
|
||||||
|
using namespace Qv2ray::core::connection::Generation;
|
@ -1,9 +1,10 @@
|
|||||||
#include "ConnectionConfigOperations.hpp"
|
#include "Serialization.hpp"
|
||||||
|
#include "Generation.hpp"
|
||||||
#include "common/QvHelpers.hpp"
|
#include "common/QvHelpers.hpp"
|
||||||
|
|
||||||
namespace Qv2ray::core::connection
|
namespace Qv2ray::core::connection
|
||||||
{
|
{
|
||||||
inline namespace Convertion
|
namespace Serialization
|
||||||
{
|
{
|
||||||
// From https://github.com/2dust/v2rayN/wiki/%E5%88%86%E4%BA%AB%E9%93%BE%E6%8E%A5%E6%A0%BC%E5%BC%8F%E8%AF%B4%E6%98%8E(ver-2)
|
// From https://github.com/2dust/v2rayN/wiki/%E5%88%86%E4%BA%AB%E9%93%BE%E6%8E%A5%E6%A0%BC%E5%BC%8F%E8%AF%B4%E6%98%8E(ver-2)
|
||||||
QString ConvertConfigToVMessString(const StreamSettingsObject &transfer, const VMessServerObject &serverConfig, const QString &alias)
|
QString ConvertConfigToVMessString(const StreamSettingsObject &transfer, const VMessServerObject &serverConfig, const QString &alias)
|
||||||
@ -44,6 +45,7 @@ namespace Qv2ray::core::connection
|
|||||||
auto vmessPart = Base64Encode(JsonToString(vmessUriRoot, QJsonDocument::JsonFormat::Compact));
|
auto vmessPart = Base64Encode(JsonToString(vmessUriRoot, QJsonDocument::JsonFormat::Compact));
|
||||||
return "vmess://" + vmessPart;
|
return "vmess://" + vmessPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DecodeSubscriptionString(QByteArray arr)
|
QString DecodeSubscriptionString(QByteArray arr)
|
||||||
{
|
{
|
||||||
// Some subscription providers may use plain vmess:// saperated by lines
|
// Some subscription providers may use plain vmess:// saperated by lines
|
||||||
@ -51,76 +53,118 @@ namespace Qv2ray::core::connection
|
|||||||
auto result = QString::fromUtf8(arr).trimmed();
|
auto result = QString::fromUtf8(arr).trimmed();
|
||||||
return result.startsWith("vmess://") ? result : Base64Decode(result);
|
return result.startsWith("vmess://") ? result : Base64Decode(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CONFIGROOT fromUri(const QString &ssUri, QString *alias, QString *errMessage)
|
||||||
|
{
|
||||||
|
ShadowSocksServerObject server;
|
||||||
|
QString d_name;
|
||||||
|
|
||||||
|
//auto ssUri = _ssUri.toStdString();
|
||||||
|
if (ssUri.length() < 5) {
|
||||||
|
LOG(MODULE_CONNECTION, "ss:// string too short")
|
||||||
|
*errMessage = QObject::tr("SS URI is too short");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto uri = ssUri.mid(5);
|
||||||
|
auto hashPos = uri.lastIndexOf("#");
|
||||||
|
DEBUG(MODULE_CONNECTION, "Hash sign position: " + QSTRN(hashPos))
|
||||||
|
|
||||||
|
if (hashPos >= 0) {
|
||||||
|
// Get the name/remark
|
||||||
|
d_name = uri.mid(uri.lastIndexOf("#") + 1);
|
||||||
|
uri.truncate(hashPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No plugins for Qv2ray so disable those lnes.i
|
||||||
|
//size_t pluginPos = uri.find_first_of('/');
|
||||||
|
//
|
||||||
|
//if (pluginPos != std::string::npos) {
|
||||||
|
// // TODO: support plugins. For now, just ignore them
|
||||||
|
// uri.erase(pluginPos);
|
||||||
|
//}
|
||||||
|
auto atPos = uri.indexOf('@');
|
||||||
|
DEBUG(MODULE_CONNECTION, "At sign position: " + QSTRN(atPos))
|
||||||
|
|
||||||
|
if (atPos < 0) {
|
||||||
|
// Old URI scheme
|
||||||
|
QString decoded = QByteArray::fromBase64(uri.toUtf8(), QByteArray::Base64Option::OmitTrailingEquals);
|
||||||
|
auto colonPos = decoded.indexOf(':');
|
||||||
|
DEBUG(MODULE_CONNECTION, "Colon position: " + QSTRN(colonPos))
|
||||||
|
|
||||||
|
if (colonPos < 0) {
|
||||||
|
*errMessage = QObject::tr("Can't find the colon separator between method and password");
|
||||||
|
}
|
||||||
|
|
||||||
|
server.method = decoded.left(colonPos);
|
||||||
|
decoded.remove(0, colonPos + 1);
|
||||||
|
atPos = decoded.lastIndexOf('@');
|
||||||
|
DEBUG(MODULE_CONNECTION, "At sign position: " + QSTRN(atPos))
|
||||||
|
|
||||||
|
if (atPos < 0) {
|
||||||
|
*errMessage = QObject::tr("Can't find the at separator between password and hostname");
|
||||||
|
}
|
||||||
|
|
||||||
|
server.password = decoded.mid(0, atPos);
|
||||||
|
decoded.remove(0, atPos + 1);
|
||||||
|
colonPos = decoded.lastIndexOf(':');
|
||||||
|
DEBUG(MODULE_CONNECTION, "Colon position: " + QSTRN(colonPos))
|
||||||
|
|
||||||
|
if (colonPos < 0) {
|
||||||
|
*errMessage = QObject::tr("Can't find the colon separator between hostname and port");
|
||||||
|
}
|
||||||
|
|
||||||
|
server.address = decoded.mid(0, colonPos);
|
||||||
|
server.port = decoded.mid(colonPos + 1).toInt();
|
||||||
|
} else {
|
||||||
|
// SIP002 URI scheme
|
||||||
|
QString userInfo(QByteArray::fromBase64(QByteArray(uri.mid(0, atPos).toUtf8(), QByteArray::Base64Option::Base64UrlEncoding)));
|
||||||
|
auto userInfoSp = userInfo.indexOf(':');
|
||||||
|
DEBUG(MODULE_CONNECTION, "Userinfo splitter position: " + QSTRN(userInfoSp))
|
||||||
|
|
||||||
|
if (userInfoSp < 0) {
|
||||||
|
*errMessage = QObject::tr("Can't find the colon separator between method and password");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString method = userInfo.mid(0, userInfoSp);
|
||||||
|
server.method = method;
|
||||||
|
server.password = userInfo.mid(userInfoSp + 1);
|
||||||
|
uri.remove(0, atPos + 1);
|
||||||
|
auto hostSpPos = uri.lastIndexOf(':');
|
||||||
|
DEBUG(MODULE_CONNECTION, "Host splitter position: " + QSTRN(hostSpPos))
|
||||||
|
|
||||||
|
if (hostSpPos < 0) {
|
||||||
|
*errMessage = QObject::tr("Can't find the colon separator between hostname and port");
|
||||||
|
}
|
||||||
|
|
||||||
|
server.address = uri.mid(0, hostSpPos);
|
||||||
|
server.port = uri.mid(hostSpPos + 1).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
CONFIGROOT root;
|
||||||
|
OUTBOUNDS outbounds;
|
||||||
|
outbounds.append(GenerateOutboundEntry("shadowsocks", GenerateShadowSocksOUT(QList<ShadowSocksServerObject>() << server), QJsonObject()));
|
||||||
|
JADD(outbounds)
|
||||||
|
*alias = alias->isEmpty() ? d_name : *alias + "_" + d_name;
|
||||||
|
LOG(MODULE_CONNECTION, "Deduced alias: " + *alias)
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString toUri(const ShadowSocksServerObject &server, const QString &alias)
|
||||||
|
{
|
||||||
|
LOG(MODULE_CONNECTION, "Converting an ss-server config to old ss:// string format")
|
||||||
|
QString ssUri = server.method + ":" + server.password + "@" + server.address + ":" + QSTRN(server.port);
|
||||||
|
return "ss://" + ssUri.toUtf8().toBase64(QByteArray::Base64Option::OmitTrailingEquals) + "#" + alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString toUriSip002(const ShadowSocksServerObject &server, const QString &alias)
|
||||||
|
{
|
||||||
|
LOG(MODULE_CONNECTION, "Converting an ss-server config to Sip002 ss:// format")
|
||||||
|
QString plainUserInfo = server.method + ":" + server.password;
|
||||||
|
QString userinfo(plainUserInfo.toUtf8().toBase64(QByteArray::Base64Option::Base64UrlEncoding).data());
|
||||||
|
return "ss://" + userinfo + "@" + server.address + ":" + QSTRN(server.port) + "#" + alias;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Save Connection to a place, with checking if there's existing file.
|
|
||||||
// If so, append "_N" to the name.
|
|
||||||
bool SaveConnectionConfig(CONFIGROOT obj, QString *alias, bool canOverrideExisting)
|
|
||||||
{
|
|
||||||
auto str = JsonToString(obj);
|
|
||||||
QFile *config = new QFile(QV2RAY_CONFIG_DIR + *alias + QV2RAY_CONFIG_FILE_EXTENSION);
|
|
||||||
|
|
||||||
// If there's already a file AND we CANNOT override existing file.
|
|
||||||
if (config->exists() && !canOverrideExisting) {
|
|
||||||
// Alias is a pointer to a QString.
|
|
||||||
DeducePossibleFileName(QV2RAY_CONFIG_DIR, alias, QV2RAY_CONFIG_FILE_EXTENSION);
|
|
||||||
config = new QFile(QV2RAY_CONFIG_DIR + *alias + QV2RAY_CONFIG_FILE_EXTENSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(MODULE_CONFIG, "Saving a config named: " + *alias)
|
|
||||||
return StringToFile(&str, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SaveSubscriptionConfig(CONFIGROOT obj, const QString &subscription, QString *name)
|
|
||||||
{
|
|
||||||
auto str = JsonToString(obj);
|
|
||||||
auto fName = *name;
|
|
||||||
|
|
||||||
if (!IsValidFileName(fName)) {
|
|
||||||
fName = RemoveInvalidFileName(fName);
|
|
||||||
}
|
|
||||||
|
|
||||||
QFile *config = new QFile(QV2RAY_SUBSCRIPTION_DIR + subscription + "/" + fName + QV2RAY_CONFIG_FILE_EXTENSION);
|
|
||||||
|
|
||||||
// If there's already a file. THIS IS EXTREMELY RARE
|
|
||||||
if (config->exists()) {
|
|
||||||
LOG(MODULE_FILE, "Trying to overrwrite an existing subscription config file. THIS IS RARE")
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(MODULE_CONFIG, "Saving a subscription named: " + fName)
|
|
||||||
bool result = StringToFile(&str, config);
|
|
||||||
|
|
||||||
if (!result) {
|
|
||||||
LOG(MODULE_FILE, "Failed to save a connection config from subscription: " + subscription + ", name: " + fName)
|
|
||||||
}
|
|
||||||
|
|
||||||
*name = fName;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RemoveConnection(const QString &alias)
|
|
||||||
{
|
|
||||||
QFile config(QV2RAY_CONFIG_DIR + alias + QV2RAY_CONFIG_FILE_EXTENSION);
|
|
||||||
|
|
||||||
if (!config.exists()) {
|
|
||||||
LOG(MODULE_FILE, "Trying to remove a non-existing file?")
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return config.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RemoveSubscriptionConnection(const QString &subsName, const QString &name)
|
|
||||||
{
|
|
||||||
QFile config(QV2RAY_SUBSCRIPTION_DIR + subsName + "/" + name + QV2RAY_CONFIG_FILE_EXTENSION);
|
|
||||||
|
|
||||||
if (!config.exists()) {
|
|
||||||
LOG(MODULE_FILE, "Trying to remove a non-existing file?")
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return config.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This generates global config containing only one outbound....
|
// This generates global config containing only one outbound....
|
||||||
CONFIGROOT ConvertConfigFromVMessString(const QString &vmessStr, QString *alias, QString *errMessage)
|
CONFIGROOT ConvertConfigFromVMessString(const QString &vmessStr, QString *alias, QString *errMessage)
|
||||||
{
|
{
|
||||||
@ -294,39 +338,5 @@ namespace Qv2ray::core::connection
|
|||||||
#undef default
|
#undef default
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
CONFIGROOT ConvertConfigFromFile(QString sourceFilePath, bool keepInbounds)
|
|
||||||
{
|
|
||||||
QFile source(sourceFilePath);
|
|
||||||
|
|
||||||
if (!source.exists()) {
|
|
||||||
LOG(MODULE_FILE, "Trying to import from an non-existing file.")
|
|
||||||
return CONFIGROOT();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto root = CONFIGROOT(JsonFromString(StringFromFile(&source)));
|
|
||||||
|
|
||||||
if (!keepInbounds) {
|
|
||||||
JSON_ROOT_TRY_REMOVE("inbounds")
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON_ROOT_TRY_REMOVE("log")
|
|
||||||
JSON_ROOT_TRY_REMOVE("api")
|
|
||||||
JSON_ROOT_TRY_REMOVE("stats")
|
|
||||||
JSON_ROOT_TRY_REMOVE("dns")
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RenameConnection(const QString &originalName, const QString &newName)
|
|
||||||
{
|
|
||||||
LOG(MODULE_CONFIG, "[RENAME] --> ORIGINAL: " + originalName + ", NEW: " + newName)
|
|
||||||
return QFile::rename(QV2RAY_CONFIG_DIR + originalName + QV2RAY_CONFIG_FILE_EXTENSION, QV2RAY_CONFIG_DIR + newName + QV2RAY_CONFIG_FILE_EXTENSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RenameSubscription(const QString &originalName, const QString &newName)
|
|
||||||
{
|
|
||||||
LOG(MODULE_SUBSCRIPTION, "[RENAME] --> ORIGINAL: " + originalName + ", NEW: " + newName)
|
|
||||||
return QDir().rename(QV2RAY_SUBSCRIPTION_DIR + originalName, QV2RAY_SUBSCRIPTION_DIR + newName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
22
src/core/connection/Serialization.hpp
Normal file
22
src/core/connection/Serialization.hpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "base/Qv2rayBase.hpp"
|
||||||
|
|
||||||
|
namespace Qv2ray::core::connection
|
||||||
|
{
|
||||||
|
namespace Serialization
|
||||||
|
{
|
||||||
|
//int VerifyVMessProtocolString(QString vmess);
|
||||||
|
QString DecodeSubscriptionString(QByteArray arr);
|
||||||
|
|
||||||
|
// VMess URI Protocol
|
||||||
|
CONFIGROOT ConvertConfigFromVMessString(const QString &vmess, QString *alias, QString *errMessage);
|
||||||
|
QString ConvertConfigToVMessString(const StreamSettingsObject &transfer, const VMessServerObject &serverConfig, const QString &alias);
|
||||||
|
|
||||||
|
// SS URI Protocol
|
||||||
|
CONFIGROOT ConvertConfigFromSSString(const QString &ss, QString *alias, QString *errMessage);
|
||||||
|
QString ConvertConfigToSSString(const ShadowSocksServerObject &serverConfig, const QString &alias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace Qv2ray::core;
|
||||||
|
using namespace Qv2ray::core::connection;
|
||||||
|
using namespace Qv2ray::core::connection::Serialization;
|
@ -3,7 +3,7 @@
|
|||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include "common/QvHelpers.hpp"
|
#include "common/QvHelpers.hpp"
|
||||||
#include "QvKernelInteractions.hpp"
|
#include "QvKernelInteractions.hpp"
|
||||||
#include "core/connection/ConnectionConfigOperations.hpp"
|
#include "core/connection/ConnectionIO.hpp"
|
||||||
|
|
||||||
#ifdef WITH_LIB_GRPCPP
|
#ifdef WITH_LIB_GRPCPP
|
||||||
using namespace v2ray::core::app::stats::command;
|
using namespace v2ray::core::app::stats::command;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "w_InboundEditor.hpp"
|
#include "w_InboundEditor.hpp"
|
||||||
#include "core/CoreUtils.hpp"
|
#include "core/CoreUtils.hpp"
|
||||||
#include "common/QvHelpers.hpp"
|
#include "common/QvHelpers.hpp"
|
||||||
#include "core/connection/ConnectionConfigOperations.hpp"
|
#include "core/connection/ConnectionIO.hpp"
|
||||||
|
|
||||||
static bool isLoading = false;
|
static bool isLoading = false;
|
||||||
#define CHECKLOADING if(isLoading) return;
|
#define CHECKLOADING if(isLoading) return;
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "ui/w_MainWindow.hpp"
|
#include "ui/w_MainWindow.hpp"
|
||||||
#include "ui/editors/w_JsonEditor.hpp"
|
#include "ui/editors/w_JsonEditor.hpp"
|
||||||
#include "ui/editors/w_RoutesEditor.hpp"
|
#include "ui/editors/w_RoutesEditor.hpp"
|
||||||
|
#include "core/connection/Generation.hpp"
|
||||||
|
|
||||||
OutboundEditor::OutboundEditor(QWidget *parent)
|
OutboundEditor::OutboundEditor(QWidget *parent)
|
||||||
: QDialog(parent),
|
: QDialog(parent),
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "w_RoutesEditor.hpp"
|
#include "w_RoutesEditor.hpp"
|
||||||
#include "core/connection/ConnectionConfigOperations.hpp"
|
#include "core/connection/ConnectionIO.hpp"
|
||||||
|
#include "core/connection/Generation.hpp"
|
||||||
#include "w_OutboundEditor.hpp"
|
#include "w_OutboundEditor.hpp"
|
||||||
#include "w_JsonEditor.hpp"
|
#include "w_JsonEditor.hpp"
|
||||||
#include "w_InboundEditor.hpp"
|
#include "w_InboundEditor.hpp"
|
||||||
|
@ -16,19 +16,22 @@ ConfigExporter::~ConfigExporter()
|
|||||||
UNREGISTER_WINDOW
|
UNREGISTER_WINDOW
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigExporter::ConfigExporter(const QImage &img, QWidget *parent): ConfigExporter(parent)
|
ConfigExporter::ConfigExporter(const CONFIGROOT &root, QWidget *parent)
|
||||||
{
|
{
|
||||||
image = img;
|
//
|
||||||
message = tr("Empty");
|
//auto vmessServer = StructFromJsonString<VMessServerObject>(JsonToString(outBoundRoot["settings"].toObject()["vnext"].toArray().first().toObject()));
|
||||||
}
|
//auto transport = StructFromJsonString<StreamSettingsObject>(JsonToString(outBoundRoot["streamSettings"].toObject()));
|
||||||
ConfigExporter::ConfigExporter(const QString &data, QWidget *parent): ConfigExporter(parent)
|
//auto vmess = ConvertConfigToVMessString(transport, vmessServer, _identifier.connectionName);
|
||||||
{
|
//
|
||||||
QZXingEncoderConfig conf;
|
//image = img;
|
||||||
conf.border = true;
|
//message = tr("Empty");
|
||||||
conf.imageSize = QSize(400, 400);
|
////
|
||||||
auto img = qzxing.encodeData(data, conf);
|
//QZXingEncoderConfig conf;
|
||||||
image = img.copy();
|
//conf.border = true;
|
||||||
message = data;
|
//conf.imageSize = QSize(400, 400);
|
||||||
|
//auto img = qzxing.encodeData(data, conf);
|
||||||
|
//image = img.copy();
|
||||||
|
//message = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigExporter::OpenExport()
|
void ConfigExporter::OpenExport()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui_w_ExportConfig.h"
|
#include "ui_w_ExportConfig.h"
|
||||||
|
#include "base/Qv2rayBase.hpp"
|
||||||
#include "3rdparty/qzxing/src/QZXing.h"
|
#include "3rdparty/qzxing/src/QZXing.h"
|
||||||
|
|
||||||
class ConfigExporter : public QDialog, private Ui::ExportConfigWindow
|
class ConfigExporter : public QDialog, private Ui::ExportConfigWindow
|
||||||
@ -8,8 +9,7 @@ class ConfigExporter : public QDialog, private Ui::ExportConfigWindow
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ConfigExporter(const QImage &img, QWidget *parent = nullptr);
|
explicit ConfigExporter(const CONFIGROOT &root, QWidget *parent = nullptr);
|
||||||
explicit ConfigExporter(const QString &data, QWidget *parent = nullptr);
|
|
||||||
~ConfigExporter();
|
~ConfigExporter();
|
||||||
void OpenExport();
|
void OpenExport();
|
||||||
protected:
|
protected:
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
|
|
||||||
#include "core/CoreUtils.hpp"
|
#include "core/CoreUtils.hpp"
|
||||||
#include "core/kernel/QvKernelInteractions.hpp"
|
#include "core/kernel/QvKernelInteractions.hpp"
|
||||||
#include "core/connection/ConnectionConfigOperations.hpp"
|
#include "core/connection/ConnectionIO.hpp"
|
||||||
|
#include "core/connection/Serialization.hpp"
|
||||||
|
|
||||||
#include "w_ScreenShot_Core.hpp"
|
#include "w_ScreenShot_Core.hpp"
|
||||||
#include "ui/editors/w_OutboundEditor.hpp"
|
#include "ui/editors/w_OutboundEditor.hpp"
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
#include "components/plugins/toolbar/QvToolbar.hpp"
|
#include "components/plugins/toolbar/QvToolbar.hpp"
|
||||||
#include "components/pac/QvPACHandler.hpp"
|
#include "components/pac/QvPACHandler.hpp"
|
||||||
|
|
||||||
|
#include "core/connection/ConnectionIO.hpp"
|
||||||
|
|
||||||
// MainWindow.cpp --> Main MainWindow source file, handles mostly UI-related operations.
|
// MainWindow.cpp --> Main MainWindow source file, handles mostly UI-related operations.
|
||||||
|
|
||||||
#define TRAY_TOOLTIP_PREFIX "Qv2ray " QV2RAY_VERSION_STRING
|
#define TRAY_TOOLTIP_PREFIX "Qv2ray " QV2RAY_VERSION_STRING
|
||||||
@ -1004,17 +1006,13 @@ void MainWindow::on_shareBtn_clicked()
|
|||||||
|
|
||||||
auto _identifier = ItemConnectionIdentifier(connectionListWidget->currentItem());
|
auto _identifier = ItemConnectionIdentifier(connectionListWidget->currentItem());
|
||||||
auto root = connections[_identifier].config;
|
auto root = connections[_identifier].config;
|
||||||
auto outBoundRoot = root["outbounds"].toArray().first().toObject();
|
auto type = get<2>(GetConnectionInfo(root));
|
||||||
auto outboundType = outBoundRoot["protocol"].toString();
|
|
||||||
|
|
||||||
if (!CheckIsComplexConfig(root) && outboundType == "vmess") {
|
if (!CheckIsComplexConfig(root) && (type == "vmess" || type == "shadowsocks")) {
|
||||||
auto vmessServer = StructFromJsonString<VMessServerObject>(JsonToString(outBoundRoot["settings"].toObject()["vnext"].toArray().first().toObject()));
|
ConfigExporter v(root, this);
|
||||||
auto transport = StructFromJsonString<StreamSettingsObject>(JsonToString(outBoundRoot["streamSettings"].toObject()));
|
|
||||||
auto vmess = ConvertConfigToVMessString(transport, vmessServer, _identifier.connectionName);
|
|
||||||
ConfigExporter v(vmess, this);
|
|
||||||
v.OpenExport();
|
v.OpenExport();
|
||||||
} else {
|
} else {
|
||||||
QvMessageBoxWarn(this, tr("Share Connection"), tr("There're no support of sharing configs other than vmess"));
|
QvMessageBoxWarn(this, tr("Share Connection"), tr("There're no support of sharing configs other than vmess and shadowsocks"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void MainWindow::on_action_RCM_ShareQR_triggered()
|
void MainWindow::on_action_RCM_ShareQR_triggered()
|
||||||
@ -1086,11 +1084,12 @@ void MainWindow::on_duplicateBtn_clicked()
|
|||||||
CONFIGROOT conf;
|
CONFIGROOT conf;
|
||||||
// Alias may change.
|
// Alias may change.
|
||||||
QString alias = _identifier.connectionName;
|
QString alias = _identifier.connectionName;
|
||||||
|
bool isComplex = CheckIsComplexConfig(connections[_identifier].config);
|
||||||
|
|
||||||
if (connections[_identifier].configType == CONNECTION_REGULAR) {
|
if (connections[_identifier].configType == CONNECTION_REGULAR) {
|
||||||
conf = ConvertConfigFromFile(QV2RAY_CONFIG_DIR + _identifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION, false);
|
conf = ConvertConfigFromFile(QV2RAY_CONFIG_DIR + _identifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION, isComplex);
|
||||||
} else {
|
} else {
|
||||||
conf = ConvertConfigFromFile(QV2RAY_SUBSCRIPTION_DIR + _identifier.subscriptionName + "/" + _identifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION, false);
|
conf = ConvertConfigFromFile(QV2RAY_SUBSCRIPTION_DIR + _identifier.subscriptionName + "/" + _identifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION, isComplex);
|
||||||
alias = _identifier.subscriptionName + "_" + _identifier.connectionName;
|
alias = _identifier.subscriptionName + "_" + _identifier.connectionName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
#include "core/CoreUtils.hpp"
|
#include "core/CoreUtils.hpp"
|
||||||
#include "core/kernel/QvKernelInteractions.hpp"
|
#include "core/kernel/QvKernelInteractions.hpp"
|
||||||
#include "core/connection/ConnectionConfigOperations.hpp"
|
#include "core/connection/ConnectionIO.hpp"
|
||||||
|
|
||||||
#include "components/pac/QvPACHandler.hpp"
|
#include "components/pac/QvPACHandler.hpp"
|
||||||
#include "common/LogHighlighter.hpp"
|
#include "common/LogHighlighter.hpp"
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
// We NEED to include the cpp file to define the macros.
|
// We NEED to include the cpp file to define the macros.
|
||||||
#include "w_MainWindow.cpp"
|
#include "w_MainWindow.cpp"
|
||||||
#include "components/proxy/QvProxyConfigurator.hpp"
|
#include "components/proxy/QvProxyConfigurator.hpp"
|
||||||
|
#include "core/connection/Generation.hpp"
|
||||||
|
|
||||||
QTreeWidgetItem *MainWindow::FindItemByIdentifier(QvConfigIdentifier identifier)
|
QTreeWidgetItem *MainWindow::FindItemByIdentifier(QvConfigIdentifier identifier)
|
||||||
{
|
{
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
#include "common/QvHelpers.hpp"
|
#include "common/QvHelpers.hpp"
|
||||||
#include "common/HTTPRequestHelper.hpp"
|
#include "common/HTTPRequestHelper.hpp"
|
||||||
#include "core/config/ConfigBackend.hpp"
|
#include "core/config/ConfigBackend.hpp"
|
||||||
|
#include "core/connection/ConnectionIO.hpp"
|
||||||
#include "core/kernel/QvKernelInteractions.hpp"
|
#include "core/kernel/QvKernelInteractions.hpp"
|
||||||
#include "core/connection/ConnectionConfigOperations.hpp"
|
|
||||||
#include "components/plugins/toolbar/QvToolbar.hpp"
|
#include "components/plugins/toolbar/QvToolbar.hpp"
|
||||||
#include "components/autolaunch/QvAutoLaunch.hpp"
|
#include "components/autolaunch/QvAutoLaunch.hpp"
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
#include "w_SubscriptionManager.hpp"
|
#include "w_SubscriptionManager.hpp"
|
||||||
#include "common/QvHelpers.hpp"
|
#include "common/QvHelpers.hpp"
|
||||||
#include "core/CoreUtils.hpp"
|
#include "core/CoreUtils.hpp"
|
||||||
#include "core/connection/ConnectionConfigOperations.hpp"
|
|
||||||
|
#include "core/connection/ConnectionIO.hpp"
|
||||||
|
#include "core/connection/Serialization.hpp"
|
||||||
|
|
||||||
SubscribeEditor::SubscribeEditor(QWidget *parent) :
|
SubscribeEditor::SubscribeEditor(QWidget *parent) :
|
||||||
QDialog(parent)
|
QDialog(parent)
|
||||||
|
Loading…
Reference in New Issue
Block a user