[change] USE STRONG TYPE NOW TO PREVENT MISUSE OF QJsonObject

This commit is contained in:
Leroy.H.Y 2019-11-27 23:16:30 +08:00
parent 06c78091b4
commit 84d8167822
No known key found for this signature in database
GPG Key ID: 6AC1673B587DC37D
18 changed files with 143 additions and 131 deletions

View File

@ -1 +1 @@
936 960

View File

@ -71,27 +71,11 @@
#define MAX(a, b) (((a) > (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif #endif
#define SAFE_TYPEDEF(Base, name) \
class name : public Base { \
public: \
template <class... Args> \
explicit name (Args... args) : Base(args...) {} \
const Base& raw() const { return *this; } \
};
namespace Qv2ray namespace Qv2ray
{ {
// To prevent anonying QJsonObject misuse
SAFE_TYPEDEF(QJsonObject, INBOUND)
SAFE_TYPEDEF(QJsonObject, OUTBOUND)
SAFE_TYPEDEF(QJsonObject, ROOT)
SAFE_TYPEDEF(QJsonArray, OUTBOUNDS)
SAFE_TYPEDEF(QJsonArray, INBOUNDS)
SAFE_TYPEDEF(QJsonArray, ROUTING)
SAFE_TYPEDEF(QJsonObject, ROUTERULE)
// //
// Extra header for QvConfigUpgrade.cpp // Extra header for QvConfigUpgrade.cpp
QJsonObject UpgradeConfig(int fromVersion, int toVersion, QJsonObject root); CONFIGROOT UpgradeConfig(int fromVersion, int toVersion, CONFIGROOT root);
struct QvBarLine { struct QvBarLine {
string Family; string Family;

View File

@ -10,7 +10,7 @@
namespace Qv2ray namespace Qv2ray
{ {
// Private member // Private member
QJsonObject UpgradeConfig_Inc(int fromVersion, QJsonObject root) CONFIGROOT UpgradeConfig_Inc(int fromVersion, CONFIGROOT root)
{ {
switch (fromVersion) { switch (fromVersion) {
case 1: { case 1: {
@ -128,7 +128,7 @@ namespace Qv2ray
} }
// Exported function // Exported function
QJsonObject UpgradeConfig(int fromVersion, int toVersion, QJsonObject root) CONFIGROOT UpgradeConfig(int fromVersion, int toVersion, CONFIGROOT root)
{ {
LOG(MODULE_CONFIG, "Migrating config from version " + to_string(fromVersion) + " to " + to_string(toVersion)) LOG(MODULE_CONFIG, "Migrating config from version " + to_string(fromVersion) + " to " + to_string(toVersion))

View File

@ -2,13 +2,39 @@
#define V2CONFIG_H #define V2CONFIG_H
#include <list> #include <list>
#include <string> #include <string>
#include <QJsonObject>
#include <QJsonArray>
#include <x2struct/x2struct.hpp> #include <x2struct/x2struct.hpp>
using namespace x2struct; using namespace x2struct;
using namespace std; using namespace std;
/* ----------------------------------------- * --------------------- #define SAFE_TYPEDEF(Base, name) \
* --------------------- * ----------------------------------------- */ class name : public Base { \
public: \
template <class... Args> \
explicit name (Args... args) : Base(args...) {} \
const Base& raw() const { return *this; } \
};
namespace Qv2ray
{
// To prevent anonying QJsonObject misuse
SAFE_TYPEDEF(QJsonObject, INBOUNDSETTING)
SAFE_TYPEDEF(QJsonObject, OUTBOUNDSETTING)
SAFE_TYPEDEF(QJsonObject, INBOUND)
SAFE_TYPEDEF(QJsonObject, OUTBOUND)
SAFE_TYPEDEF(QJsonObject, CONFIGROOT)
//
SAFE_TYPEDEF(QJsonArray, INOUTLIST)
SAFE_TYPEDEF(INOUTLIST, OUTBOUNDS)
SAFE_TYPEDEF(INOUTLIST, INBOUNDS)
SAFE_TYPEDEF(QJsonObject, ROUTING)
SAFE_TYPEDEF(QJsonObject, ROUTERULE)
SAFE_TYPEDEF(QJsonArray, ROUTERULELIST)
}
/* ----------------------------------------- */
namespace Qv2ray namespace Qv2ray
{ {
@ -320,6 +346,7 @@ namespace Qv2ray
} }
} }
using namespace Qv2ray;
using namespace Qv2ray::V2ConfigModels; using namespace Qv2ray::V2ConfigModels;
using namespace Qv2ray::V2ConfigModels::Protocols; using namespace Qv2ray::V2ConfigModels::Protocols;

View File

@ -5,20 +5,20 @@ namespace Qv2ray
namespace ConfigOperations namespace ConfigOperations
{ {
QMap<QString, QJsonObject> GetConnections(list<string> connectionNames) QMap<QString, CONFIGROOT> GetConnections(list<string> connectionNames)
{ {
QMap<QString, QJsonObject> list; QMap<QString, CONFIGROOT> list;
for (auto conn : connectionNames) { for (auto conn : connectionNames) {
QString jsonString = StringFromFile(new QFile(QV2RAY_CONFIG_DIR + QSTRING(conn) + QV2RAY_CONFIG_FILE_EXTENSION)); QString jsonString = StringFromFile(new QFile(QV2RAY_CONFIG_DIR + QSTRING(conn) + QV2RAY_CONFIG_FILE_EXTENSION));
QJsonObject connectionObject = JsonFromString(jsonString); CONFIGROOT connectionObject = CONFIGROOT(JsonFromString(jsonString));
list.insert(QString::fromStdString(conn), connectionObject); list.insert(QString::fromStdString(conn), connectionObject);
} }
return list; return list;
} }
bool CheckIsComplexConfig(QJsonObject root) bool CheckIsComplexConfig(CONFIGROOT root)
{ {
bool cRouting = root.contains("routing"); bool cRouting = root.contains("routing");
bool cRule = cRouting && root["routing"].toObject().contains("rules"); bool cRule = cRouting && root["routing"].toObject().contains("rules");
@ -26,14 +26,15 @@ namespace Qv2ray
return cRules; return cRules;
} }
int StartPreparation(QJsonObject fullConfig) int StartPreparation(CONFIGROOT fullConfig)
{ {
// Writes the final configuration to the disk. // Writes the final configuration to the disk.
QString json = JsonToString(fullConfig); QString json = JsonToString(fullConfig);
StringToFile(&json, new QFile(QV2RAY_GENERATED_FILE_PATH)); StringToFile(&json, new QFile(QV2RAY_GENERATED_FILE_PATH));
return 0; return 0;
} }
int FindIndexByTag(QJsonArray list, QString *tag)
int FindIndexByTag(INOUTLIST list, QString *tag)
{ {
for (int i = 0; i < list.count(); i++) { for (int i = 0; i < list.count(); i++) {
auto value = list[i].toObject(); auto value = list[i].toObject();

View File

@ -16,10 +16,10 @@ namespace Qv2ray
// -------------------------- BEGIN GENERAL FUNCTIONS ---------------------------------------------- // -------------------------- BEGIN GENERAL FUNCTIONS ----------------------------------------------
namespace ConfigOperations namespace ConfigOperations
{ {
QMap<QString, QJsonObject> GetConnections(list<string> connections); QMap<QString, CONFIGROOT> GetConnections(list<string> connections);
bool CheckIsComplexConfig(QJsonObject root); bool CheckIsComplexConfig(CONFIGROOT root);
int StartPreparation(QJsonObject fullConfig); int StartPreparation(CONFIGROOT fullConfig);
int FindIndexByTag(QJsonArray list, QString *tag); int FindIndexByTag(INOUTLIST list, QString *tag);
// //
// -------------------------- BEGIN CONFIG CONVERSIONS -------------------------- // -------------------------- BEGIN CONFIG CONVERSIONS --------------------------
@ -29,12 +29,12 @@ namespace Qv2ray
QString DecodeSubscriptionString(QByteArray arr); QString DecodeSubscriptionString(QByteArray arr);
// //
// Save Connection Config // Save Connection Config
bool SaveConnectionConfig(QJsonObject obj, QString *alias, bool canOverrideExisting); bool SaveConnectionConfig(CONFIGROOT obj, QString *alias, bool canOverrideExisting);
bool RemoveConnection(const QString &alias); bool RemoveConnection(const QString &alias);
bool RenameConnection(QString originalName, QString newName); bool RenameConnection(QString originalName, QString newName);
// VMess URI Protocol // VMess URI Protocol
QJsonObject ConvertConfigFromVMessString(QString vmess, QString *alias, QString *errMessage); CONFIGROOT ConvertConfigFromVMessString(QString vmess, QString *alias, QString *errMessage);
QJsonObject ConvertConfigFromFile(QString sourceFilePath, bool keepInbounds); CONFIGROOT ConvertConfigFromFile(QString sourceFilePath, bool keepInbounds);
QString ConvertConfigToVMessString(const StreamSettingsObject &transfer, const VMessServerObject &serverConfig, const QString &alias); QString ConvertConfigToVMessString(const StreamSettingsObject &transfer, const VMessServerObject &serverConfig, const QString &alias);
} }
@ -42,26 +42,26 @@ namespace Qv2ray
// -------------------------- BEGIN CONFIG GENERATIONS --------------------------------------------- // -------------------------- BEGIN CONFIG GENERATIONS ---------------------------------------------
namespace Generation namespace Generation
{ {
QJsonObject GenerateRoutes(bool enableProxy, bool cnProxy); ROUTING GenerateRoutes(bool enableProxy, bool cnProxy);
QJsonObject GenerateSingleRouteRule(QStringList list, bool isDomain, QString outboundTag, QString type = "field"); ROUTERULE GenerateSingleRouteRule(QStringList list, bool isDomain, QString outboundTag, QString type = "field");
QJsonObject GenerateDNS(bool withLocalhost, QStringList dnsServers); QJsonObject GenerateDNS(bool withLocalhost, QStringList dnsServers);
QJsonObject GenerateAPIEntry(QString tag, bool withHandler = true, bool withLogger = true, bool withStats = true); QJsonObject GenerateAPIEntry(QString tag, bool withHandler = true, bool withLogger = true, bool withStats = true);
// //
// Outbound Protocols // Outbound Protocols
QJsonObject GenerateFreedomOUT(QString domainStrategy, QString redirect, int userLevel); OUTBOUNDSETTING GenerateFreedomOUT(QString domainStrategy, QString redirect, int userLevel);
QJsonObject GenerateBlackHoleOUT(bool useHTTP); OUTBOUNDSETTING GenerateBlackHoleOUT(bool useHTTP);
QJsonObject GenerateShadowSocksServerOUT(QString email, QString address, int port, QString method, QString password, bool ota, int level); OUTBOUNDSETTING GenerateShadowSocksServerOUT(QString email, QString address, int port, QString method, QString password, bool ota, int level);
QJsonObject GenerateShadowSocksOUT(QList<QJsonObject> servers); OUTBOUNDSETTING GenerateShadowSocksOUT(QList<QJsonObject> servers);
// //
// Inbounds Protocols // Inbounds Protocols
QJsonObject GenerateDokodemoIN(QString address, int port, QString network, int timeout, bool followRedirect, int userLevel); INBOUNDSETTING GenerateDokodemoIN(QString address, int port, QString network, int timeout, bool followRedirect, int userLevel);
QJsonObject GenerateHTTPIN(QList<AccountObject> accounts, int timeout = 300, bool allowTransparent = true, int userLevel = 0); INBOUNDSETTING GenerateHTTPIN(QList<AccountObject> accounts, int timeout = 300, bool allowTransparent = true, int userLevel = 0);
QJsonObject GenerateSocksIN(QString auth, QList<AccountObject> _accounts, bool udp = false, QString ip = "127.0.0.1", 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 // Generate FINAL Configs
QJsonObject GenerateRuntimeConfig(QJsonObject root); CONFIGROOT GenerateRuntimeConfig(CONFIGROOT root);
QJsonObject GenerateOutboundEntry(QString protocol, QJsonObject settings, QJsonObject streamSettings, QJsonObject mux = QJsonObject(), QString sendThrough = "0.0.0.0", QString tag = ""); OUTBOUND GenerateOutboundEntry(QString protocol, OUTBOUNDSETTING settings, QJsonObject streamSettings, QJsonObject mux = QJsonObject(), QString sendThrough = "0.0.0.0", QString tag = "");
QJsonObject GenerateInboundEntry(QString listen, int port, QString protocol, QJsonObject settings, QString tag, QJsonObject sniffing = QJsonObject(), QJsonObject allocate = QJsonObject()); INBOUND GenerateInboundEntry(QString listen, int port, QString protocol, INBOUNDSETTING settings, QString tag, QJsonObject sniffing = QJsonObject(), QJsonObject allocate = QJsonObject());
} }
} }
} }

View File

@ -55,7 +55,7 @@ namespace Qv2ray
// //
/// Save Connection to a place, with checking if there's existing file. /// Save Connection to a place, with checking if there's existing file.
/// If so, append "_N" to the name. /// If so, append "_N" to the name.
bool SaveConnectionConfig(QJsonObject obj, QString *alias, bool canOverrideExisting) bool SaveConnectionConfig(CONFIGROOT obj, QString *alias, bool canOverrideExisting)
{ {
auto str = JsonToString(obj); auto str = JsonToString(obj);
QFile *config = new QFile(QV2RAY_CONFIG_DIR + *alias + QV2RAY_CONFIG_FILE_EXTENSION); QFile *config = new QFile(QV2RAY_CONFIG_DIR + *alias + QV2RAY_CONFIG_FILE_EXTENSION);
@ -84,14 +84,14 @@ namespace Qv2ray
} }
// This generates global config containing only one outbound.... // This generates global config containing only one outbound....
QJsonObject ConvertConfigFromVMessString(QString vmess, QString *alias, QString *errMessage) CONFIGROOT ConvertConfigFromVMessString(QString vmess, QString *alias, QString *errMessage)
{ {
// Reset errMessage // Reset errMessage
*errMessage = ""; *errMessage = "";
if (!vmess.toLower().startsWith("vmess://")) { if (!vmess.toLower().startsWith("vmess://")) {
*errMessage = QObject::tr("VMess string should start with 'vmess://'"); *errMessage = QObject::tr("VMess string should start with 'vmess://'");
return QJsonObject(); return CONFIGROOT();
} }
try { try {
@ -100,7 +100,7 @@ namespace Qv2ray
if (b64Str.isEmpty()) { if (b64Str.isEmpty()) {
*errMessage = QObject::tr("VMess string should be a valid base64 string"); *errMessage = QObject::tr("VMess string should be a valid base64 string");
return QJsonObject(); return CONFIGROOT();
} }
auto vmessString = Base64Decode(b64Str); auto vmessString = Base64Decode(b64Str);
@ -108,14 +108,14 @@ namespace Qv2ray
if (!jsonErr.isEmpty()) { if (!jsonErr.isEmpty()) {
*errMessage = jsonErr; *errMessage = jsonErr;
return QJsonObject(); return CONFIGROOT();
} }
auto vmessConf = JsonFromString(vmessString); auto vmessConf = JsonFromString(vmessString);
if (vmessConf.isEmpty()) { if (vmessConf.isEmpty()) {
*errMessage = QObject::tr("JSON should not be empty"); *errMessage = QObject::tr("JSON should not be empty");
return QJsonObject(); return CONFIGROOT();
} }
// C is a quick hack... // C is a quick hack...
@ -140,11 +140,11 @@ namespace Qv2ray
} catch (exception *e) { } catch (exception *e) {
LOG(MODULE_CONNECTION_VMESS, "Failed to decode vmess string: " << e->what()) LOG(MODULE_CONNECTION_VMESS, "Failed to decode vmess string: " << e->what())
*errMessage = QSTRING(e->what()); *errMessage = QSTRING(e->what());
return QJsonObject(); return CONFIGROOT();
} }
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
DROOT CONFIGROOT root;
QStringRef vmessJsonB64(&vmess, 8, vmess.length() - 8); QStringRef vmessJsonB64(&vmess, 8, vmess.length() - 8);
auto vmessConf = JsonFromString(Base64Decode(vmessJsonB64.toString())); auto vmessConf = JsonFromString(Base64Decode(vmessJsonB64.toString()));
// //
@ -179,7 +179,7 @@ namespace Qv2ray
serv.users.push_back(user); serv.users.push_back(user);
// //
// VMess root config // VMess root config
QJsonObject vConf; OUTBOUNDSETTING vConf;
QJsonArray vnextArray; QJsonArray vnextArray;
vnextArray.append(JsonFromString(StructToJsonString(serv))); vnextArray.append(JsonFromString(StructToJsonString(serv)));
vConf["vnext"] = vnextArray; vConf["vnext"] = vnextArray;
@ -224,16 +224,16 @@ namespace Qv2ray
RROOT RROOT
} }
QJsonObject ConvertConfigFromFile(QString sourceFilePath, bool keepInbounds) CONFIGROOT ConvertConfigFromFile(QString sourceFilePath, bool keepInbounds)
{ {
QFile source(sourceFilePath); QFile source(sourceFilePath);
if (!source.exists()) { if (!source.exists()) {
LOG(MODULE_FILE, "Trying to import from an non-existing file.") LOG(MODULE_FILE, "Trying to import from an non-existing file.")
return QJsonObject(); return CONFIGROOT();
} }
auto root = JsonFromString(StringFromFile(&source)); auto root = CONFIGROOT(JsonFromString(StringFromFile(&source)));
if (!keepInbounds) { if (!keepInbounds) {
JSON_ROOT_TRY_REMOVE("inbounds") JSON_ROOT_TRY_REMOVE("inbounds")
@ -246,14 +246,14 @@ namespace Qv2ray
return root; return root;
} }
QMap<QString, QJsonObject> GetConnections(list<string> connectionNames) QMap<QString, CONFIGROOT> GetConnections(list<string> connectionNames)
{ {
QMap<QString, QJsonObject> list; QMap<QString, CONFIGROOT> list;
for (auto conn : connectionNames) { for (auto conn : connectionNames) {
QString jsonString = StringFromFile(new QFile(QV2RAY_CONFIG_DIR + QSTRING(conn) + QV2RAY_CONFIG_FILE_EXTENSION)); QString jsonString = StringFromFile(new QFile(QV2RAY_CONFIG_DIR + QSTRING(conn) + QV2RAY_CONFIG_FILE_EXTENSION));
QJsonObject connectionObject = JsonFromString(jsonString); QJsonObject connectionObject = JsonFromString(jsonString);
list.insert(QString::fromStdString(conn), connectionObject); list.insert(QString::fromStdString(conn), CONFIGROOT(connectionObject));
} }
return list; return list;
@ -265,7 +265,7 @@ namespace Qv2ray
return QFile::rename(QV2RAY_CONFIG_DIR + originalName + QV2RAY_CONFIG_FILE_EXTENSION, QV2RAY_CONFIG_DIR + newName + QV2RAY_CONFIG_FILE_EXTENSION); return QFile::rename(QV2RAY_CONFIG_DIR + originalName + QV2RAY_CONFIG_FILE_EXTENSION, QV2RAY_CONFIG_DIR + newName + QV2RAY_CONFIG_FILE_EXTENSION);
} }
int StartPreparation(QJsonObject fullConfig) int StartPreparation(CONFIGROOT fullConfig)
{ {
// Writes the final configuration to the disk. // Writes the final configuration to the disk.
QString json = JsonToString(fullConfig); QString json = JsonToString(fullConfig);

View File

@ -9,13 +9,13 @@ namespace Qv2ray
// Important config generation algorithms. // Important config generation algorithms.
static const QStringList vLogLevels = {"none", "debug", "info", "warning", "error"}; static const QStringList vLogLevels = {"none", "debug", "info", "warning", "error"};
// -------------------------- BEGIN CONFIG GENERATIONS ---------------------------------------------------------------------------- // -------------------------- BEGIN CONFIG GENERATIONS ----------------------------------------------------------------------------
QJsonObject GenerateRoutes(bool enableProxy, bool proxyCN) ROUTING GenerateRoutes(bool enableProxy, bool proxyCN)
{ {
DROOT ROUTING root;
root.insert("domainStrategy", "IPIfNonMatch"); root.insert("domainStrategy", "IPIfNonMatch");
// //
// For Rules list // For Rules list
QJsonArray rulesList; ROUTERULELIST rulesList;
if (!enableProxy) { if (!enableProxy) {
// This is added to disable all proxies, as a alternative influence of #64 // This is added to disable all proxies, as a alternative influence of #64
@ -35,32 +35,32 @@ namespace Qv2ray
RROOT RROOT
} }
QJsonObject GenerateSingleRouteRule(QStringList list, bool isDomain, QString outboundTag, QString type) ROUTERULE GenerateSingleRouteRule(QStringList list, bool isDomain, QString outboundTag, QString type)
{ {
DROOT ROUTERULE root;
root.insert(isDomain ? "domain" : "ip", QJsonArray::fromStringList(list)); root.insert(isDomain ? "domain" : "ip", QJsonArray::fromStringList(list));
JADD(outboundTag, type) JADD(outboundTag, type)
RROOT RROOT
} }
QJsonObject GenerateFreedomOUT(QString domainStrategy, QString redirect, int userLevel) OUTBOUNDSETTING GenerateFreedomOUT(QString domainStrategy, QString redirect, int userLevel)
{ {
DROOT OUTBOUNDSETTING root;
JADD(domainStrategy, redirect, userLevel) JADD(domainStrategy, redirect, userLevel)
RROOT RROOT
} }
QJsonObject GenerateBlackHoleOUT(bool useHTTP) OUTBOUNDSETTING GenerateBlackHoleOUT(bool useHTTP)
{ {
DROOT OUTBOUNDSETTING root;
QJsonObject resp; QJsonObject resp;
resp.insert("type", useHTTP ? "http" : "none"); resp.insert("type", useHTTP ? "http" : "none");
root.insert("response", resp); root.insert("response", resp);
RROOT RROOT
} }
QJsonObject GenerateShadowSocksOUT(QList<QJsonObject> servers) OUTBOUNDSETTING GenerateShadowSocksOUT(QList<QJsonObject> servers)
{ {
DROOT OUTBOUNDSETTING root;
QJsonArray x; QJsonArray x;
foreach (auto server, servers) { foreach (auto server, servers) {
@ -71,16 +71,16 @@ namespace Qv2ray
RROOT RROOT
} }
QJsonObject GenerateShadowSocksServerOUT(QString email, QString address, int port, QString method, QString password, bool ota, int level) OUTBOUNDSETTING GenerateShadowSocksServerOUT(QString email, QString address, int port, QString method, QString password, bool ota, int level)
{ {
DROOT OUTBOUNDSETTING root;
JADD(email, address, port, method, password, level, ota) JADD(email, address, port, method, password, level, ota)
RROOT RROOT
} }
QJsonObject GenerateDNS(bool withLocalhost, QStringList dnsServers) QJsonObject GenerateDNS(bool withLocalhost, QStringList dnsServers)
{ {
DROOT QJsonObject root;
QJsonArray servers(QJsonArray::fromStringList(dnsServers)); QJsonArray servers(QJsonArray::fromStringList(dnsServers));
if (withLocalhost) { if (withLocalhost) {
@ -95,16 +95,16 @@ namespace Qv2ray
RROOT RROOT
} }
QJsonObject GenerateDokodemoIN(QString address, int port, QString network, int timeout, bool followRedirect, int userLevel) INBOUNDSETTING GenerateDokodemoIN(QString address, int port, QString network, int timeout, bool followRedirect, int userLevel)
{ {
DROOT INBOUNDSETTING root;
JADD(address, port, network, timeout, followRedirect, userLevel) JADD(address, port, network, timeout, followRedirect, userLevel)
RROOT RROOT
} }
QJsonObject GenerateHTTPIN(QList<AccountObject> _accounts, int timeout, bool allowTransparent, int userLevel) INBOUNDSETTING GenerateHTTPIN(QList<AccountObject> _accounts, int timeout, bool allowTransparent, int userLevel)
{ {
DROOT INBOUNDSETTING root;
QJsonArray accounts; QJsonArray accounts;
foreach (auto account, _accounts) { foreach (auto account, _accounts) {
@ -115,9 +115,9 @@ namespace Qv2ray
RROOT RROOT
} }
QJsonObject GenerateSocksIN(QString auth, QList<AccountObject> _accounts, bool udp, QString ip, int userLevel) INBOUNDSETTING GenerateSocksIN(QString auth, QList<AccountObject> _accounts, bool udp, QString ip, int userLevel)
{ {
DROOT INBOUNDSETTING root;
QJsonArray accounts; QJsonArray accounts;
foreach (auto acc, _accounts) { foreach (auto acc, _accounts) {
@ -133,16 +133,16 @@ namespace Qv2ray
RROOT RROOT
} }
QJsonObject GenerateOutboundEntry(QString protocol, QJsonObject settings, QJsonObject streamSettings, QJsonObject mux, QString sendThrough, QString tag) OUTBOUND GenerateOutboundEntry(QString protocol, OUTBOUNDSETTING settings, QJsonObject streamSettings, QJsonObject mux, QString sendThrough, QString tag)
{ {
DROOT OUTBOUND root;
JADD(sendThrough, protocol, settings, tag, streamSettings, mux) JADD(sendThrough, protocol, settings, tag, streamSettings, mux)
RROOT RROOT
} }
QJsonObject GenerateInboundEntry(QString listen, int port, QString protocol, QJsonObject settings, QString tag, QJsonObject sniffing, QJsonObject allocate) INBOUND GenerateInboundEntry(QString listen, int port, QString protocol, INBOUNDSETTING settings, QString tag, QJsonObject sniffing, QJsonObject allocate)
{ {
DROOT INBOUND root;
LOG(MODULE_CONNECTION, "allocation is not used here.") LOG(MODULE_CONNECTION, "allocation is not used here.")
Q_UNUSED(allocate) Q_UNUSED(allocate)
JADD(listen, port, protocol, settings, tag, sniffing) JADD(listen, port, protocol, settings, tag, sniffing)
@ -151,7 +151,7 @@ namespace Qv2ray
QJsonObject GenerateAPIEntry(QString tag, bool withHandler, bool withLogger, bool withStats) QJsonObject GenerateAPIEntry(QString tag, bool withHandler, bool withLogger, bool withStats)
{ {
DROOT QJsonObject root;
QJsonArray services; QJsonArray services;
if (withHandler) if (withHandler)
@ -170,7 +170,7 @@ namespace Qv2ray
// -------------------------- END CONFIG GENERATIONS ------------------------------------------------------------------------------ // -------------------------- END CONFIG GENERATIONS ------------------------------------------------------------------------------
// BEGIN RUNTIME CONFIG GENERATION // BEGIN RUNTIME CONFIG GENERATION
QJsonObject GenerateRuntimeConfig(QJsonObject root) CONFIGROOT GenerateRuntimeConfig(CONFIGROOT root)
{ {
auto gConf = GetGlobalConfig(); auto gConf = GetGlobalConfig();
QJsonObject logObject; QJsonObject logObject;
@ -191,11 +191,11 @@ namespace Qv2ray
root.insert("dns", dnsObject); root.insert("dns", dnsObject);
// //
// //
QJsonArray inboundsList; INBOUNDS inboundsList;
// HTTP InBound // HTTP InBound
if (gConf.inboundConfig.http_port != 0) { if (gConf.inboundConfig.http_port != 0) {
QJsonObject httpInBoundObject; INBOUND httpInBoundObject;
httpInBoundObject.insert("listen", QString::fromStdString(gConf.inboundConfig.listenip)); httpInBoundObject.insert("listen", QString::fromStdString(gConf.inboundConfig.listenip));
httpInBoundObject.insert("port", gConf.inboundConfig.http_port); httpInBoundObject.insert("port", gConf.inboundConfig.http_port);
httpInBoundObject.insert("protocol", "http"); httpInBoundObject.insert("protocol", "http");
@ -211,7 +211,7 @@ namespace Qv2ray
// SOCKS InBound // SOCKS InBound
if (gConf.inboundConfig.socks_port != 0) { if (gConf.inboundConfig.socks_port != 0) {
QJsonObject socksInBoundObject; INBOUND socksInBoundObject;
socksInBoundObject.insert("listen", QString::fromStdString(gConf.inboundConfig.listenip)); socksInBoundObject.insert("listen", QString::fromStdString(gConf.inboundConfig.listenip));
socksInBoundObject.insert("port", gConf.inboundConfig.socks_port); socksInBoundObject.insert("port", gConf.inboundConfig.socks_port);
socksInBoundObject.insert("protocol", "socks"); socksInBoundObject.insert("protocol", "socks");
@ -240,8 +240,8 @@ namespace Qv2ray
// //
// HOWEVER, we need to verify the QV2RAY_RULE_ENABLED entry. // HOWEVER, we need to verify the QV2RAY_RULE_ENABLED entry.
// And what's more, process (by removing unused items) from a rule object. // And what's more, process (by removing unused items) from a rule object.
QJsonObject routing = root["routing"].toObject(); ROUTING routing = ROUTING(root["routing"].toObject());
QJsonArray rules; ROUTERULELIST rules;
LOG(MODULE_CONNECTION, "Processing an existing routing table.") LOG(MODULE_CONNECTION, "Processing an existing routing table.")
for (auto _a : routing["rules"].toArray()) { for (auto _a : routing["rules"].toArray()) {
@ -281,7 +281,7 @@ namespace Qv2ray
auto routeObject = GenerateRoutes(gConf.connectionConfig.enableProxy, gConf.connectionConfig.bypassCN); auto routeObject = GenerateRoutes(gConf.connectionConfig.enableProxy, gConf.connectionConfig.bypassCN);
root.insert("routing", routeObject); root.insert("routing", routeObject);
QJsonArray outbounds = root["outbounds"].toArray(); OUTBOUNDS outbounds = OUTBOUNDS(root["outbounds"].toArray());
outbounds.append(GenerateOutboundEntry("freedom", GenerateFreedomOUT("AsIs", ":0", 0), QJsonObject(), QJsonObject(), "0.0.0.0", OUTBOUND_TAG_DIRECT)); outbounds.append(GenerateOutboundEntry("freedom", GenerateFreedomOUT("AsIs", ":0", 0), QJsonObject(), QJsonObject(), "0.0.0.0", OUTBOUND_TAG_DIRECT));
root["outbounds"] = outbounds; root["outbounds"] = outbounds;
} }
@ -320,8 +320,8 @@ namespace Qv2ray
// //
// Inbounds // Inbounds
// //
QJsonArray inbounds = root["inbounds"].toArray(); INBOUNDS inbounds = INBOUNDS(root["inbounds"].toArray());
QJsonObject fakeDocodemoDoor; INBOUNDSETTING fakeDocodemoDoor;
fakeDocodemoDoor["address"] = "127.0.0.1"; fakeDocodemoDoor["address"] = "127.0.0.1";
QJsonObject apiInboundsRoot = GenerateInboundEntry("127.0.0.1", gConf.connectionConfig.statsPort, "dokodemo-door", fakeDocodemoDoor, QV2RAY_API_TAG_INBOUND); QJsonObject apiInboundsRoot = GenerateInboundEntry("127.0.0.1", gConf.connectionConfig.statsPort, "dokodemo-door", fakeDocodemoDoor, QV2RAY_API_TAG_INBOUND);
inbounds.push_front(apiInboundsRoot); inbounds.push_front(apiInboundsRoot);

View File

@ -197,7 +197,7 @@ int main(int argc, char *argv[])
return -1; return -1;
} }
auto conf = JsonFromString(StringFromFile(new QFile(QV2RAY_CONFIG_FILE))); auto conf = CONFIGROOT(JsonFromString(StringFromFile(new QFile(QV2RAY_CONFIG_FILE))));
// //
auto confVersion = conf["config_version"].toVariant().toString(); auto confVersion = conf["config_version"].toVariant().toString();
auto newVersion = QSTRING(to_string(QV2RAY_CONFIG_VERSION)); auto newVersion = QSTRING(to_string(QV2RAY_CONFIG_VERSION));

View File

@ -24,13 +24,13 @@ ImportConfigWindow::ImportConfigWindow(QWidget *parent)
nameTxt->setText(QDateTime::currentDateTime().toString("MM-dd_hh-mm") + "_" + tr("Imported") + "_"); nameTxt->setText(QDateTime::currentDateTime().toString("MM-dd_hh-mm") + "_" + tr("Imported") + "_");
} }
QMap<QString, QJsonObject> ImportConfigWindow::OpenImport(bool outboundsOnly) QMap<QString, CONFIGROOT> ImportConfigWindow::OpenImport(bool outboundsOnly)
{ {
// if Outbound Only, set keepImported to false and disable the checkbox // if Outbound Only, set keepImported to false and disable the checkbox
// keepImportedInboundCheckBox->setChecked(!outboundsOnly); // keepImportedInboundCheckBox->setChecked(!outboundsOnly);
keepImportedInboundCheckBox->setEnabled(!outboundsOnly); keepImportedInboundCheckBox->setEnabled(!outboundsOnly);
this->exec(); this->exec();
return this->result() == QDialog::Accepted ? connections : QMap<QString, QJsonObject>(); return this->result() == QDialog::Accepted ? connections : QMap<QString, CONFIGROOT>();
} }
void ImportConfigWindow::on_importSourceCombo_currentIndexChanged(int index) void ImportConfigWindow::on_importSourceCombo_currentIndexChanged(int index)
@ -65,7 +65,7 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked()
void ImportConfigWindow::on_beginImportBtn_clicked() void ImportConfigWindow::on_beginImportBtn_clicked()
{ {
QString aliasPrefix = nameTxt->text(); QString aliasPrefix = nameTxt->text();
QJsonObject config; CONFIGROOT config;
//auto conf = GetGlobalConfig(); //auto conf = GetGlobalConfig();
switch (importSourceCombo->currentIndex()) { switch (importSourceCombo->currentIndex()) {
@ -224,9 +224,9 @@ void ImportConfigWindow::on_connectionEditBtn_clicked()
delete w; delete w;
if (isChanged) { if (isChanged) {
QJsonArray outboundsList; OUTBOUNDS outboundsList;
outboundsList.push_back(outboundEntry); outboundsList.push_back(outboundEntry);
QJsonObject root; CONFIGROOT root;
root.insert("outbounds", outboundsList); root.insert("outbounds", outboundsList);
// //
// WARN This one will change the connection name, because of some duplicates. // WARN This one will change the connection name, because of some duplicates.

View File

@ -4,6 +4,7 @@
#include <QDialog> #include <QDialog>
#include <QString> #include <QString>
#include <QJsonObject> #include <QJsonObject>
#include "QvCoreConfigObjects.hpp"
#include "ui_w_ImportConfig.h" #include "ui_w_ImportConfig.h"
class ImportConfigWindow : public QDialog, private Ui::ImportConfigWindow class ImportConfigWindow : public QDialog, private Ui::ImportConfigWindow
@ -13,7 +14,7 @@ class ImportConfigWindow : public QDialog, private Ui::ImportConfigWindow
public: public:
explicit ImportConfigWindow(QWidget *parent = nullptr); explicit ImportConfigWindow(QWidget *parent = nullptr);
~ImportConfigWindow() { } ~ImportConfigWindow() { }
QMap<QString, QJsonObject> OpenImport(bool outboundsOnly = false); QMap<QString, CONFIGROOT> OpenImport(bool outboundsOnly = false);
private slots: private slots:
void on_importSourceCombo_currentIndexChanged(int index); void on_importSourceCombo_currentIndexChanged(int index);
@ -31,7 +32,7 @@ class ImportConfigWindow : public QDialog, private Ui::ImportConfigWindow
void on_cancelImportBtn_clicked(); void on_cancelImportBtn_clicked();
private: private:
QMap<QString, QJsonObject> connections; QMap<QString, CONFIGROOT> connections;
QMap<QString, QString> vmessErrors; QMap<QString, QString> vmessErrors;
}; };

View File

@ -698,7 +698,7 @@ void MainWindow::on_editConfigButton_clicked()
auto alias = connectionListWidget->currentItem()->text(); auto alias = connectionListWidget->currentItem()->text();
auto outBoundRoot = connections[alias]; auto outBoundRoot = connections[alias];
QJsonObject root; CONFIGROOT root;
bool isChanged = false; bool isChanged = false;
if (CheckIsComplexConfig(outBoundRoot)) { if (CheckIsComplexConfig(outBoundRoot)) {
@ -708,7 +708,7 @@ void MainWindow::on_editConfigButton_clicked()
isChanged = routeWindow->result() == QDialog::Accepted; isChanged = routeWindow->result() == QDialog::Accepted;
} else { } else {
LOG(MODULE_UI, "INFO: Opening single connection edit window.") LOG(MODULE_UI, "INFO: Opening single connection edit window.")
OutboundEditor *w = new OutboundEditor(outBoundRoot["outbounds"].toArray().first().toObject(), this); OutboundEditor *w = new OutboundEditor(OUTBOUND(outBoundRoot["outbounds"].toArray().first().toObject()), this);
auto outboundEntry = w->OpenEditor(); auto outboundEntry = w->OpenEditor();
isChanged = w->result() == QDialog::Accepted; isChanged = w->result() == QDialog::Accepted;
QJsonArray outboundsList; QJsonArray outboundsList;
@ -740,7 +740,7 @@ void MainWindow::on_action_RCM_ConvToComplex_triggered()
auto alias = connectionListWidget->currentItem()->text(); auto alias = connectionListWidget->currentItem()->text();
auto outBoundRoot = connections[alias]; auto outBoundRoot = connections[alias];
QJsonObject root; CONFIGROOT root;
bool isChanged = false; bool isChanged = false;
// //
LOG(MODULE_UI, "INFO: Opening route editor.") LOG(MODULE_UI, "INFO: Opening route editor.")
@ -767,7 +767,7 @@ void MainWindow::on_action_RCM_EditJson_triggered()
auto alias = connectionListWidget->currentItem()->text(); auto alias = connectionListWidget->currentItem()->text();
JsonEditor *w = new JsonEditor(connections[alias], this); JsonEditor *w = new JsonEditor(connections[alias], this);
auto root = w->OpenEditor(); auto root = CONFIGROOT(w->OpenEditor());
bool isChanged = w->result() == QDialog::Accepted; bool isChanged = w->result() == QDialog::Accepted;
delete w; delete w;

View File

@ -68,7 +68,7 @@ class MainWindow : public QMainWindow, Ui::MainWindow
void on_duplicateBtn_clicked(); void on_duplicateBtn_clicked();
public: public:
QJsonObject CurrentFullConfig; CONFIGROOT CurrentFullConfig;
QString CurrentConnectionName = ""; QString CurrentConnectionName = "";
ConnectionInstance *vinstance; ConnectionInstance *vinstance;
QString totalDataUp; QString totalDataUp;
@ -98,7 +98,7 @@ class MainWindow : public QMainWindow, Ui::MainWindow
// //
QMenu *trayMenu = new QMenu(this); QMenu *trayMenu = new QMenu(this);
QMenu *listMenu; QMenu *listMenu;
QMap<QString, QJsonObject> connections; QMap<QString, CONFIGROOT> connections;
// //
QString originalName; QString originalName;
bool isRenamingInProgress; bool isRenamingInProgress;

View File

@ -29,7 +29,7 @@ OutboundEditor::OutboundEditor(QWidget *parent)
Result = GenerateConnectionJson(); Result = GenerateConnectionJson();
} }
OutboundEditor::OutboundEditor(QJsonObject outboundEntry, QWidget *parent) OutboundEditor::OutboundEditor(OUTBOUND outboundEntry, QWidget *parent)
: OutboundEditor(parent) : OutboundEditor(parent)
{ {
Original = outboundEntry; Original = outboundEntry;
@ -68,7 +68,7 @@ OutboundEditor::~OutboundEditor()
{ {
} }
QJsonObject OutboundEditor::OpenEditor() OUTBOUND OutboundEditor::OpenEditor()
{ {
int resultCode = this->exec(); int resultCode = this->exec();
return resultCode == QDialog::Accepted ? Result : Original; return resultCode == QDialog::Accepted ? Result : Original;
@ -263,9 +263,9 @@ void OutboundEditor::on_tcpRespDefBtn_clicked()
tcpRespTxt->insertPlainText("{\"version\":\"1.1\",\"status\":\"200\",\"reason\":\"OK\",\"headers\":{\"Content-Type\":[\"application/octet-stream\",\"video/mpeg\"],\"Transfer-Encoding\":[\"chunked\"],\"Connection\":[\"keep-alive\"],\"Pragma\":\"no-cache\"}}"); tcpRespTxt->insertPlainText("{\"version\":\"1.1\",\"status\":\"200\",\"reason\":\"OK\",\"headers\":{\"Content-Type\":[\"application/octet-stream\",\"video/mpeg\"],\"Transfer-Encoding\":[\"chunked\"],\"Connection\":[\"keep-alive\"],\"Pragma\":\"no-cache\"}}");
} }
QJsonObject OutboundEditor::GenerateConnectionJson() OUTBOUND OutboundEditor::GenerateConnectionJson()
{ {
QJsonObject settings; OUTBOUNDSETTING settings;
auto streaming = JsonFromString(StructToJsonString(stream)); auto streaming = JsonFromString(StructToJsonString(stream));
if (OutboundType == "vmess") { if (OutboundType == "vmess") {

View File

@ -11,9 +11,9 @@ class OutboundEditor : public QDialog, private Ui::OutboundEditor
Q_OBJECT Q_OBJECT
public: public:
explicit OutboundEditor(QWidget *parent = nullptr); explicit OutboundEditor(QWidget *parent = nullptr);
explicit OutboundEditor(QJsonObject outboundEntry, QWidget *parent = nullptr); explicit OutboundEditor(OUTBOUND outboundEntry, QWidget *parent = nullptr);
~OutboundEditor(); ~OutboundEditor();
QJsonObject OpenEditor(); OUTBOUND OpenEditor();
QString GetFriendlyName(); QString GetFriendlyName();
signals: signals:
void s_reload_config(bool need_restart); void s_reload_config(bool need_restart);
@ -109,9 +109,9 @@ class OutboundEditor : public QDialog, private Ui::OutboundEditor
private: private:
QString Tag; QString Tag;
void ReLoad_GUI_JSON_ModelContent(); void ReLoad_GUI_JSON_ModelContent();
QJsonObject GenerateConnectionJson(); OUTBOUND GenerateConnectionJson();
QJsonObject Original; OUTBOUND Original;
QJsonObject Result; OUTBOUND Result;
QJsonObject Mux; QJsonObject Mux;
// //
// Connection Configs // Connection Configs

View File

@ -27,8 +27,8 @@ RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) :
balabcerAddBtn->setIcon(QICON_R("add.png")); balabcerAddBtn->setIcon(QICON_R("add.png"));
balancerDelBtn->setIcon(QICON_R("delete.png")); balancerDelBtn->setIcon(QICON_R("delete.png"));
// //
inbounds = root["inbounds"].toArray(); inbounds = INBOUNDS(root["inbounds"].toArray());
outbounds = root["outbounds"].toArray(); outbounds = OUTBOUNDS(root["outbounds"].toArray());
DomainStrategy = root["routing"].toObject()["domainStrategy"].toString(); DomainStrategy = root["routing"].toObject()["domainStrategy"].toString();
// Applying Balancers. // Applying Balancers.
@ -109,7 +109,7 @@ RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) :
} }
} }
QJsonObject RouteEditor::OpenEditor() CONFIGROOT RouteEditor::OpenEditor()
{ {
auto result = this->exec(); auto result = this->exec();
@ -340,7 +340,7 @@ void RouteEditor::on_editOutboundBtn_clicked()
return; return;
} }
auto currentOutbound = outbounds[row].toObject(); auto currentOutbound = OUTBOUND(outbounds[row].toObject());
auto protocol = currentOutbound["protocol"].toString(); auto protocol = currentOutbound["protocol"].toString();
if (protocol != "vmess" && protocol != "shadowsocks" && protocol != "socks") { if (protocol != "vmess" && protocol != "shadowsocks" && protocol != "socks") {

View File

@ -16,7 +16,7 @@ class RouteEditor : public QDialog, private Ui::RouteEditor
public: public:
explicit RouteEditor(QJsonObject connection, QWidget *parent = nullptr); explicit RouteEditor(QJsonObject connection, QWidget *parent = nullptr);
~RouteEditor(); ~RouteEditor();
QJsonObject OpenEditor(); CONFIGROOT OpenEditor();
private slots: private slots:
void on_buttonBox_accepted(); void on_buttonBox_accepted();
@ -91,10 +91,10 @@ class RouteEditor : public QDialog, private Ui::RouteEditor
QList<RuleObject> rules; QList<RuleObject> rules;
QString DomainStrategy; QString DomainStrategy;
// //
QJsonArray inbounds; INBOUNDS inbounds;
QJsonArray outbounds; OUTBOUNDS outbounds;
QJsonObject root; CONFIGROOT root;
QJsonObject original; CONFIGROOT original;
}; };
#endif // W_QVOUTBOUNDEDITOR_H #endif // W_QVOUTBOUNDEDITOR_H

View File

@ -46,7 +46,6 @@
// Add key value pair into JSON named 'root' // Add key value pair into JSON named 'root'
#define JADD(...) FOR_EACH(JADDEx, __VA_ARGS__) #define JADD(...) FOR_EACH(JADDEx, __VA_ARGS__)
#define DROOT QJsonObject root;
#define RROOT return root; #define RROOT return root;
#endif #endif