mirror of
https://github.com/Qv2ray/Qv2ray.git
synced 2025-05-20 19:00:22 +08:00
[Version] Version 1.3.7 Release
Signed-off-by: Leroy.H.Y <lhy20010403@hotmail.com>
This commit is contained in:
commit
ce6be82497
@ -14,7 +14,7 @@ CONFIG += c++11 openssl openssl-linked lrelease embed_translations
|
|||||||
win32: QMAKE_TARGET_DESCRIPTION = "Qv2ray, a cross-platform v2ray GUI client."
|
win32: QMAKE_TARGET_DESCRIPTION = "Qv2ray, a cross-platform v2ray GUI client."
|
||||||
win32: QMAKE_TARGET_PRODUCT = "Qv2ray"
|
win32: QMAKE_TARGET_PRODUCT = "Qv2ray"
|
||||||
|
|
||||||
VERSION = 1.3.6.1
|
VERSION = 1.3.7.0
|
||||||
DEFINES += QV_MAJOR_VERSION=\"\\\"$${VERSION}\\\"\"
|
DEFINES += QV_MAJOR_VERSION=\"\\\"$${VERSION}\\\"\"
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
@ -7,10 +7,22 @@
|
|||||||
|
|
||||||
#define QV2RAY_VERSION_STRING "v" QV_MAJOR_VERSION
|
#define QV2RAY_VERSION_STRING "v" QV_MAJOR_VERSION
|
||||||
|
|
||||||
#define QV2RAY_CONFIG_VERSION 2
|
#define QV2RAY_CONFIG_VERSION 3
|
||||||
|
// Base folder.
|
||||||
#define QV2RAY_CONFIG_DIR_PATH (Qv2ray::Utils::GetConfigDirPath() + "/")
|
#define QV2RAY_CONFIG_DIR_PATH (Qv2ray::Utils::GetConfigDirPath() + "/")
|
||||||
#define QV2RAY_CONFIG_FILE_PATH (QV2RAY_CONFIG_DIR_PATH + "Qv2ray.conf")
|
#define QV2RAY_CONFIG_FILE_PATH (QV2RAY_CONFIG_DIR_PATH + "Qv2ray.conf")
|
||||||
|
|
||||||
|
// We need v2ray.exe/v2ray executables here!
|
||||||
|
#define QV2RAY_V2RAY_CORE_DIR_PATH (QV2RAY_CONFIG_DIR_PATH + "vcore/")
|
||||||
|
|
||||||
|
#ifdef __WIN32
|
||||||
|
// Win32 has .exe
|
||||||
|
#define QV2RAY_V2RAY_CORE_PATH (QV2RAY_V2RAY_CORE_DIR_PATH + "v2ray.exe")
|
||||||
|
#else
|
||||||
|
// MacOS and Linux....
|
||||||
|
#define QV2RAY_V2RAY_CORE_PATH (QV2RAY_V2RAY_CORE_DIR_PATH + "v2ray")
|
||||||
|
#endif
|
||||||
|
|
||||||
#define QV2RAY_CONNECTION_FILE_EXTENSION ".qv2ray.json"
|
#define QV2RAY_CONNECTION_FILE_EXTENSION ".qv2ray.json"
|
||||||
#define QV2RAY_GENERATED_FILE_PATH (QV2RAY_CONFIG_DIR_PATH + "generated/config.gen.json")
|
#define QV2RAY_GENERATED_FILE_PATH (QV2RAY_CONFIG_DIR_PATH + "generated/config.gen.json")
|
||||||
|
|
||||||
@ -18,15 +30,6 @@
|
|||||||
#define QV2RAY_VCORE_ACCESS_LOG_FILENAME "access.log"
|
#define QV2RAY_VCORE_ACCESS_LOG_FILENAME "access.log"
|
||||||
#define QV2RAY_VCORE_ERROR_LOG_FILENAME "error.log"
|
#define QV2RAY_VCORE_ERROR_LOG_FILENAME "error.log"
|
||||||
|
|
||||||
// These is for early-2.0 version, final 2.0 will move these content into global config.
|
|
||||||
#define QV2RAY_CONFIG_TYPE_FILE "File"
|
|
||||||
#define QV2RAY_CONFIG_TYPE_MANUAL "Manual"
|
|
||||||
#define QV2RAY_CONFIG_TYPE_CONNECTIONSTRING "ConnectionString"
|
|
||||||
#define QV2RAY_CONFIG_TYPE_SUBSCRIPTION "Subscription"
|
|
||||||
#define QV2RAY_CONFIG_TYPE_JSON_KEY "_qv2ray.configSource"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// GUI TOOLS
|
// GUI TOOLS
|
||||||
#define RED(obj) \
|
#define RED(obj) \
|
||||||
auto _temp = ui->obj->palette(); \
|
auto _temp = ui->obj->palette(); \
|
||||||
@ -77,7 +80,6 @@ namespace Qv2ray
|
|||||||
int logLevel;
|
int logLevel;
|
||||||
//
|
//
|
||||||
string language;
|
string language;
|
||||||
string v2CorePath;
|
|
||||||
string v2AssetsPath;
|
string v2AssetsPath;
|
||||||
string autoStartConfig;
|
string autoStartConfig;
|
||||||
//
|
//
|
||||||
@ -97,13 +99,12 @@ namespace Qv2ray
|
|||||||
map<string, string> subscribes;
|
map<string, string> subscribes;
|
||||||
MuxObject mux;
|
MuxObject mux;
|
||||||
Qv2rayConfig(): config_version(QV2RAY_CONFIG_VERSION), runAsRoot(false), logLevel(), proxyDefault(), proxyCN(), withLocalDNS(), inBoundSettings(), configs(), subscribes(), mux() { }
|
Qv2rayConfig(): config_version(QV2RAY_CONFIG_VERSION), runAsRoot(false), logLevel(), proxyDefault(), proxyCN(), withLocalDNS(), inBoundSettings(), configs(), subscribes(), mux() { }
|
||||||
Qv2rayConfig(string lang, string exePath, string assetsPath, int log, Qv2rayBasicInboundsConfig _inBoundSettings): Qv2rayConfig()
|
Qv2rayConfig(string lang, string assetsPath, int log, Qv2rayBasicInboundsConfig _inBoundSettings): Qv2rayConfig()
|
||||||
{
|
{
|
||||||
// These settings below are defaults.
|
// These settings below are defaults.
|
||||||
ignoredVersion = "";
|
ignoredVersion = "";
|
||||||
autoStartConfig = "";
|
autoStartConfig = "";
|
||||||
language = lang;
|
language = lang;
|
||||||
v2CorePath = exePath;
|
|
||||||
v2AssetsPath = assetsPath;
|
v2AssetsPath = assetsPath;
|
||||||
logLevel = log;
|
logLevel = log;
|
||||||
inBoundSettings = _inBoundSettings;
|
inBoundSettings = _inBoundSettings;
|
||||||
@ -116,7 +117,7 @@ namespace Qv2ray
|
|||||||
proxyDefault = true;
|
proxyDefault = true;
|
||||||
withLocalDNS = true;
|
withLocalDNS = true;
|
||||||
}
|
}
|
||||||
XTOSTRUCT(O(config_version, runAsRoot, logLevel, language, autoStartConfig, ignoredVersion, v2CorePath, v2AssetsPath, proxyDefault, proxyCN, withLocalDNS, dnsList, inBoundSettings, mux, configs, subscribes))
|
XTOSTRUCT(O(config_version, runAsRoot, logLevel, language, autoStartConfig, ignoredVersion, v2AssetsPath, proxyDefault, proxyCN, withLocalDNS, dnsList, inBoundSettings, mux, configs, subscribes))
|
||||||
};
|
};
|
||||||
|
|
||||||
QJsonObject UpgradeConfig(int fromVersion, int toVersion, QJsonObject root);
|
QJsonObject UpgradeConfig(int fromVersion, int toVersion, QJsonObject root);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
// from old to newer versions of Qv2ray.
|
// from old to newer versions of Qv2ray.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "Qv2rayBase.h"
|
#include "QvUtils.h"
|
||||||
|
|
||||||
#define UPGRADELOG(item, old, _new) LOG(MODULE_CONFIG, "Upgrading " item " from old value " + old + " to " + _new);
|
#define UPGRADELOG(item, old, _new) LOG(MODULE_CONFIG, "Upgrading " item " from old value " + old + " to " + _new);
|
||||||
#define XConfLog(oldVersion, newVersion) LOG(MODULE_CONFIG, "Migrating config from version " + oldVersion + " to " + newVersion);
|
#define XConfLog(oldVersion, newVersion) LOG(MODULE_CONFIG, "Migrating config from version " + oldVersion + " to " + newVersion);
|
||||||
@ -18,15 +18,31 @@ namespace Qv2ray
|
|||||||
XConfLog(to_string(fromVersion), to_string(fromVersion + 1))
|
XConfLog(to_string(fromVersion), to_string(fromVersion + 1))
|
||||||
|
|
||||||
switch (fromVersion) {
|
switch (fromVersion) {
|
||||||
case 1:
|
case 1: {
|
||||||
// From 1 to 2, we changed the config_version from 'string' to 'int'
|
// From 1 to 2, we changed the config_version from 'string' to 'int'
|
||||||
auto old_config_version = root["config_version"].toString();
|
auto old_config_version = root["config_version"].toString();
|
||||||
root.remove("config_version");
|
root.remove("config_version");
|
||||||
root["config_version"] = 2;
|
root["config_version"] = 2;
|
||||||
UPGRADELOG("config_version", old_config_version.toStdString(), "2")
|
UPGRADELOG("config_version", old_config_version.toStdString(), "2")
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 2 : {
|
||||||
|
auto vCoreFilePath = root["v2CorePath"].toString();
|
||||||
|
auto vCoreDestPath = QV2RAY_V2RAY_CORE_PATH;
|
||||||
|
// We also need v2ctl
|
||||||
|
auto v2CtlFilePath = QFileInfo(vCoreFilePath).dir().path() + "/v2ctl";
|
||||||
|
auto v2CtlDestPath = QFileInfo(vCoreDestPath).dir().path() + "/v2ctl";
|
||||||
|
QFile::copy(vCoreFilePath, vCoreDestPath);
|
||||||
|
QFile::copy(v2CtlFilePath, v2CtlDestPath);
|
||||||
|
root.remove("v2CorePath");
|
||||||
|
UPGRADELOG("v2CorePath", vCoreFilePath.toStdString(), vCoreDestPath.toStdString())
|
||||||
|
UPGRADELOG("v2CtlFilePath", v2CtlFilePath.toStdString(), v2CtlDestPath.toStdString())
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
root["config_version"] = root["config_version"].toInt() + 1;
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,10 +16,6 @@ namespace Qv2ray
|
|||||||
{
|
{
|
||||||
namespace V2ConfigModels
|
namespace V2ConfigModels
|
||||||
{
|
{
|
||||||
struct VMessProtocolConfigObject {
|
|
||||||
string v, ps, add, port, id, aid, net, type, host, path, tls;
|
|
||||||
XTOSTRUCT(O(v, ps, add, port, id, aid, net, type, host, path, tls))
|
|
||||||
};
|
|
||||||
//
|
//
|
||||||
// Used in config generation
|
// Used in config generation
|
||||||
struct AccountObject {
|
struct AccountObject {
|
||||||
|
@ -57,7 +57,7 @@ namespace Qv2ray
|
|||||||
bool SaveConnectionConfig(QJsonObject obj, const QString *alias);
|
bool SaveConnectionConfig(QJsonObject obj, const QString *alias);
|
||||||
bool RenameConnection(QString originalName, QString newName);
|
bool RenameConnection(QString originalName, QString newName);
|
||||||
// VMess Protocol
|
// VMess Protocol
|
||||||
QJsonObject ConvertConfigFromVMessString(QString vmess, QString source = QV2RAY_CONFIG_TYPE_CONNECTIONSTRING);
|
QJsonObject ConvertConfigFromVMessString(QString vmess);
|
||||||
QJsonObject ConvertConfigFromFile(QString sourceFilePath, bool overrideInbounds);
|
QJsonObject ConvertConfigFromFile(QString sourceFilePath, bool overrideInbounds);
|
||||||
// Load Configs
|
// Load Configs
|
||||||
QMap<QString, QJsonObject> GetConnections(list<string> connections);
|
QMap<QString, QJsonObject> GetConnections(list<string> connections);
|
||||||
|
@ -7,25 +7,39 @@ namespace Qv2ray
|
|||||||
bool SaveConnectionConfig(QJsonObject obj, const QString *alias)
|
bool SaveConnectionConfig(QJsonObject obj, const QString *alias)
|
||||||
{
|
{
|
||||||
QFile config(QV2RAY_CONFIG_DIR_PATH + *alias + QV2RAY_CONNECTION_FILE_EXTENSION);
|
QFile config(QV2RAY_CONFIG_DIR_PATH + *alias + QV2RAY_CONNECTION_FILE_EXTENSION);
|
||||||
return StringToFile(JSONToString(obj), &config);
|
auto str = JSONToString(obj);
|
||||||
|
return StringToFile(&str, &config);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This generates global config containing only one outbound....
|
// This generates global config containing only one outbound....
|
||||||
QJsonObject ConvertConfigFromVMessString(QString str, QString source)
|
QJsonObject ConvertConfigFromVMessString(QString str)
|
||||||
{
|
{
|
||||||
DROOT
|
DROOT
|
||||||
QStringRef vmessJsonB64(&str, 8, str.length() - 8);
|
QStringRef vmessJsonB64(&str, 8, str.length() - 8);
|
||||||
auto vmessConf = StructFromJSONString<VMessProtocolConfigObject>(Base64Decode(vmessJsonB64.toString()));
|
auto vmessConf = JSONFromString(Base64Decode(vmessJsonB64.toString()));
|
||||||
|
string ps, add, id, net, type, host, path, tls;
|
||||||
|
int port, aid;
|
||||||
|
ps = vmessConf["ps"].toVariant().toString().toStdString();
|
||||||
|
add = vmessConf["add"].toVariant().toString().toStdString();
|
||||||
|
id = vmessConf["id"].toVariant().toString().toStdString();
|
||||||
|
net = vmessConf["net"].toVariant().toString().toStdString();
|
||||||
|
type = vmessConf["type"].toVariant().toString().toStdString();
|
||||||
|
host = vmessConf["host"].toVariant().toString().toStdString();
|
||||||
|
path = vmessConf["path"].toVariant().toString().toStdString();
|
||||||
|
tls = vmessConf["tls"].toVariant().toString().toStdString();
|
||||||
|
//
|
||||||
|
port = vmessConf["port"].toVariant().toInt();
|
||||||
|
aid = vmessConf["aid"].toVariant().toInt();
|
||||||
//
|
//
|
||||||
// User
|
// User
|
||||||
VMessServerObject::UserObject user;
|
VMessServerObject::UserObject user;
|
||||||
user.id = vmessConf.id;
|
user.id = id;
|
||||||
user.alterId = stoi(vmessConf.aid);
|
user.alterId = aid;
|
||||||
//
|
//
|
||||||
// Server
|
// Server
|
||||||
VMessServerObject serv;
|
VMessServerObject serv;
|
||||||
serv.port = stoi(vmessConf.port);
|
serv.port = port;
|
||||||
serv.address = vmessConf.add;
|
serv.address = add;
|
||||||
serv.users.push_back(user);
|
serv.users.push_back(user);
|
||||||
//
|
//
|
||||||
// VMess root config
|
// VMess root config
|
||||||
@ -38,35 +52,34 @@ namespace Qv2ray
|
|||||||
StreamSettingsObject streaming;
|
StreamSettingsObject streaming;
|
||||||
|
|
||||||
// Fill hosts for HTTP
|
// Fill hosts for HTTP
|
||||||
foreach (auto host, QString::fromStdString(vmessConf.host).split(',')) {
|
foreach (auto _host, QString::fromStdString(host).split(',')) {
|
||||||
streaming.httpSettings.host.push_back(host.toStdString());
|
streaming.httpSettings.host.push_back(_host.toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// hosts for ws, h2 and security for QUIC
|
// hosts for ws, h2 and security for QUIC
|
||||||
streaming.wsSettings.headers.insert(make_pair("Host", vmessConf.host));
|
streaming.wsSettings.headers.insert(make_pair("Host", host));
|
||||||
streaming.quicSettings.security = vmessConf.host;
|
streaming.quicSettings.security = host;
|
||||||
//
|
//
|
||||||
// Fake type for tcp, kcp and QUIC
|
// Fake type for tcp, kcp and QUIC
|
||||||
streaming.tcpSettings.header.type = vmessConf.type;
|
streaming.tcpSettings.header.type = type;
|
||||||
streaming.kcpSettings.header.type = vmessConf.type;
|
streaming.kcpSettings.header.type = type;
|
||||||
streaming.quicSettings.header.type = vmessConf.type;
|
streaming.quicSettings.header.type = type;
|
||||||
//
|
//
|
||||||
// Path for ws, h2, Quic
|
// Path for ws, h2, Quic
|
||||||
streaming.wsSettings.path = vmessConf.path;
|
streaming.wsSettings.path = path;
|
||||||
streaming.httpSettings.path = vmessConf.path;
|
streaming.httpSettings.path = path;
|
||||||
streaming.quicSettings.key = vmessConf.path;
|
streaming.quicSettings.key = path;
|
||||||
streaming.security = vmessConf.tls;
|
streaming.security = tls;
|
||||||
//
|
//
|
||||||
// Network type
|
// Network type
|
||||||
streaming.network = vmessConf.net;
|
streaming.network = net;
|
||||||
//
|
//
|
||||||
auto outbound = GenerateOutboundEntry("vmess", vConf, GetRootObject(streaming), GetRootObject(GetGlobalConfig().mux), "0.0.0.0", OUTBOUND_TAG_PROXY);
|
auto outbound = GenerateOutboundEntry("vmess", vConf, GetRootObject(streaming), GetRootObject(GetGlobalConfig().mux), "0.0.0.0", OUTBOUND_TAG_PROXY);
|
||||||
//
|
//
|
||||||
QJsonArray outbounds;
|
QJsonArray outbounds;
|
||||||
outbounds.append(outbound);
|
outbounds.append(outbound);
|
||||||
root.insert("outbounds", outbounds);
|
root.insert("outbounds", outbounds);
|
||||||
root.insert("QV2RAY_ALIAS", QString::fromStdString(vmessConf.ps));
|
root.insert("QV2RAY_ALIAS", QString::fromStdString(ps));
|
||||||
root.insert(QV2RAY_CONFIG_TYPE_JSON_KEY, source);
|
|
||||||
RROOT
|
RROOT
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +95,6 @@ namespace Qv2ray
|
|||||||
JSON_ROOT_TRY_REMOVE("api")
|
JSON_ROOT_TRY_REMOVE("api")
|
||||||
JSON_ROOT_TRY_REMOVE("stats")
|
JSON_ROOT_TRY_REMOVE("stats")
|
||||||
JSON_ROOT_TRY_REMOVE("dns")
|
JSON_ROOT_TRY_REMOVE("dns")
|
||||||
root.insert(QV2RAY_CONFIG_TYPE_JSON_KEY, QV2RAY_CONFIG_TYPE_FILE);
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +119,7 @@ namespace Qv2ray
|
|||||||
int StartPreparation(QJsonObject fullConfig)
|
int StartPreparation(QJsonObject fullConfig)
|
||||||
{
|
{
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ namespace Qv2ray
|
|||||||
{
|
{
|
||||||
namespace ConfigOperations
|
namespace ConfigOperations
|
||||||
{
|
{
|
||||||
|
static const QStringList vLogLevels = {"none", "debug", "info", "warning", "error"};
|
||||||
// -------------------------- BEGIN CONFIG GENERATIONS ----------------------------------------------------------------------------
|
// -------------------------- BEGIN CONFIG GENERATIONS ----------------------------------------------------------------------------
|
||||||
QJsonObject GenerateRoutes(bool globalProxy, bool cnProxy)
|
QJsonObject GenerateRoutes(bool globalProxy, bool cnProxy)
|
||||||
{
|
{
|
||||||
@ -129,33 +130,11 @@ namespace Qv2ray
|
|||||||
{
|
{
|
||||||
auto gConf = GetGlobalConfig();
|
auto gConf = GetGlobalConfig();
|
||||||
QJsonObject logObject;
|
QJsonObject logObject;
|
||||||
|
//
|
||||||
//logObject.insert("access", QV2RAY_CONFIG_PATH + QV2RAY_VCORE_LOG_DIRNAME + QV2RAY_VCORE_ACCESS_LOG_FILENAME);
|
//logObject.insert("access", QV2RAY_CONFIG_PATH + QV2RAY_VCORE_LOG_DIRNAME + QV2RAY_VCORE_ACCESS_LOG_FILENAME);
|
||||||
//logObject.insert("error", QV2RAY_CONFIG_PATH + QV2RAY_VCORE_LOG_DIRNAME + QV2RAY_VCORE_ERROR_LOG_FILENAME);
|
//logObject.insert("error", QV2RAY_CONFIG_PATH + QV2RAY_VCORE_LOG_DIRNAME + QV2RAY_VCORE_ERROR_LOG_FILENAME);
|
||||||
QString logLevel_s;
|
//
|
||||||
|
logObject.insert("loglevel", vLogLevels[gConf.logLevel]);
|
||||||
switch (gConf.logLevel) {
|
|
||||||
case 0:
|
|
||||||
logLevel_s = "none";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
logLevel_s = "debug";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
logLevel_s = "info";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
logLevel_s = "warning";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
logLevel_s = "error";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
logObject.insert("loglevel", logLevel_s);
|
|
||||||
root.insert("log", logObject);
|
root.insert("log", logObject);
|
||||||
//
|
//
|
||||||
QStringList dnsList;
|
QStringList dnsList;
|
||||||
@ -166,16 +145,6 @@ namespace Qv2ray
|
|||||||
|
|
||||||
auto dnsObject = GenerateDNS(gConf.withLocalDNS, dnsList);
|
auto dnsObject = GenerateDNS(gConf.withLocalDNS, dnsList);
|
||||||
root.insert("dns", dnsObject);
|
root.insert("dns", dnsObject);
|
||||||
|
|
||||||
//
|
|
||||||
// This is for imported config files as there are routing entries already.
|
|
||||||
// We don't add extra routings.
|
|
||||||
// We don't use QV2RAY_CONFIG_TYPE_FILE checking scheme because not all connections have this part.
|
|
||||||
if (!root.contains("routing")) {
|
|
||||||
auto routeObject = GenerateRoutes(gConf.proxyDefault, gConf.proxyCN);
|
|
||||||
root.insert("routing", routeObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
root.insert("stats", QJsonObject());
|
root.insert("stats", QJsonObject());
|
||||||
@ -210,23 +179,43 @@ namespace Qv2ray
|
|||||||
inboundsList.append(socksInBoundObject);
|
inboundsList.append(socksInBoundObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!root.contains("inbounds") || root["inbounds"].toArray().count() == 0) {
|
if (!root.contains("inbounds") || root["inbounds"].toArray().empty()) {
|
||||||
root.insert("inbounds", inboundsList);
|
root.insert("inbounds", inboundsList);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: MultiOutbound Settings
|
// Note: The part below always makes the whole functionality in trouble......
|
||||||
if (root.contains(QV2RAY_CONFIG_TYPE_JSON_KEY) && root[QV2RAY_CONFIG_TYPE_JSON_KEY] == QV2RAY_CONFIG_TYPE_FILE) {
|
// BE EXTREME CAREFUL when changing these code below...
|
||||||
LOG(MODULE_CONFIG, "Found an imported config file, skipping adding 'freedom' outbound.")
|
//
|
||||||
// Do nothing because it's an imported connection.
|
|
||||||
} else {
|
// For SOME configs, there is no "route" entries, so, we add some...
|
||||||
|
|
||||||
|
// We don't use QV2RAY_CONFIG_TYPE_FILE to check because not all IMPORTED connections have routings.
|
||||||
|
if (!root.contains("routing")) {
|
||||||
|
if (root["outbounds"].toArray().count() != 1) {
|
||||||
|
// There are no ROUTING but 2 or more outbounds.... This is rare, but possible.
|
||||||
|
LOG(MODULE_CONNECTION, "WARN: This message usually indicates the config file has some logic errors:")
|
||||||
|
LOG(MODULE_CONNECTION, "WARN: --> The config file has NO routing section, however more than 1 outbounds are detected.")
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(MODULE_CONNECTION, "Current connection has NO ROUTING section, we insert default values.")
|
||||||
|
auto routeObject = GenerateRoutes(gConf.proxyDefault, gConf.proxyCN);
|
||||||
|
root.insert("routing", routeObject);
|
||||||
QJsonArray outbounds = root["outbounds"].toArray();
|
QJsonArray outbounds = root["outbounds"].toArray();
|
||||||
// It's not imported so we add new stuff.
|
|
||||||
// For DIRECT
|
|
||||||
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));
|
||||||
QJsonObject first = outbounds.first().toObject();
|
// TODO
|
||||||
first.insert("mux", GetRootObject(gConf.mux));
|
//
|
||||||
outbounds[0] = first;
|
// We don't want to add MUX into the first one in the list.....
|
||||||
|
// However, this can be added to the Connection Edit Window...
|
||||||
|
//QJsonObject first = outbounds.first().toObject();
|
||||||
|
//first.insert("mux", GetRootObject(gConf.mux));
|
||||||
|
//outbounds[0] = first;
|
||||||
|
//
|
||||||
root["outbounds"] = outbounds;
|
root["outbounds"] = outbounds;
|
||||||
|
} else {
|
||||||
|
// For some config files that has routing entries already.
|
||||||
|
// We don't add extra routings.
|
||||||
|
// this part has been left blanking
|
||||||
|
LOG(MODULE_CONNECTION, "Skip adding 'freedom' entry.")
|
||||||
}
|
}
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
|
@ -16,10 +16,15 @@ namespace Qv2ray
|
|||||||
try {
|
try {
|
||||||
QStringRef vmessJsonB64(&vmess, 8, vmess.length() - 8);
|
QStringRef vmessJsonB64(&vmess, 8, vmess.length() - 8);
|
||||||
auto vmessString = Base64Decode(vmessJsonB64.toString());
|
auto vmessString = Base64Decode(vmessJsonB64.toString());
|
||||||
auto vmessConf = StructFromJSONString<VMessProtocolConfigObject>(vmessString);
|
auto vmessConf = JSONFromString(vmessString);
|
||||||
return 0;
|
// C is a quick hack...
|
||||||
|
#define C(k) vmessConf.contains(k)
|
||||||
|
//string v, ps, add, port, id, aid, net, type, host, path, tls;
|
||||||
|
bool flag = C("v") && C("ps") && C("add") && C("port") && C("id") && C("aid") && C("net") && C("type") && C("host") && C("path") && C("tls");
|
||||||
|
#undef C
|
||||||
|
return flag ? 0 : 1;
|
||||||
} catch (exception *e) {
|
} catch (exception *e) {
|
||||||
LOG(MODULE_CONNECTION, QObject::tr("#VMessDecodeError").toStdString() << e->what())
|
LOG(MODULE_CONNECTION, "Failed to decode vmess string: " << e->what())
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,56 +1,58 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include <QDesktopServices>
|
||||||
#include "QvCoreInteractions.h"
|
#include "QvCoreInteractions.h"
|
||||||
#include "QvCoreConfigOperations.h"
|
#include "QvCoreConfigOperations.h"
|
||||||
|
|
||||||
|
#include "QvTinyLog.h"
|
||||||
#include "w_MainWindow.h"
|
#include "w_MainWindow.h"
|
||||||
|
|
||||||
namespace Qv2ray
|
namespace Qv2ray
|
||||||
{
|
{
|
||||||
bool Qv2Instance::VerifyVConfigFile(const QString path)
|
bool Qv2Instance::VerifyVConfigFile(const QString *path)
|
||||||
{
|
{
|
||||||
if (ValidateV2rayCoreExe()) {
|
if (ValidateV2rayCoreExe()) {
|
||||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||||
env.insert("V2RAY_LOCATION_ASSET", QString::fromStdString(GetGlobalConfig().v2AssetsPath));
|
env.insert("V2RAY_LOCATION_ASSET", QString::fromStdString(GetGlobalConfig().v2AssetsPath));
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.setProcessEnvironment(env);
|
process.setProcessEnvironment(env);
|
||||||
process.start(QString::fromStdString(Utils::GetGlobalConfig().v2CorePath), QStringList() << "-test"
|
process.start(QV2RAY_V2RAY_CORE_PATH, QStringList() << "-test" << "-config" << *path, QIODevice::ReadWrite | QIODevice::Text);
|
||||||
<< "-config" << path,
|
|
||||||
QIODevice::ReadWrite | QIODevice::Text);
|
|
||||||
|
|
||||||
if (!process.waitForFinished()) {
|
if (!process.waitForFinished()) {
|
||||||
qDebug() << "v2ray core failed with exit code " << process.exitCode();
|
LOG(MODULE_VCORE, "v2ray core failed with exitcode: " << process.exitCode())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString output = QString(process.readAllStandardOutput());
|
QString output = QString(process.readAllStandardOutput());
|
||||||
|
|
||||||
if (!output.contains("Configuration OK")) {
|
if (process.exitCode() != 0) {
|
||||||
Utils::QvMessageBox(nullptr, QObject::tr("ConfigurationError"), output.mid(output.indexOf("anti-censorship.") + 17));
|
Utils::QvMessageBox(nullptr, QObject::tr("Configuration Error"), output.mid(output.indexOf("anti-censorship.") + 17));
|
||||||
return false;
|
return false;
|
||||||
} else
|
}
|
||||||
return true;
|
|
||||||
} else
|
return true;
|
||||||
return false;
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Qv2Instance::Qv2Instance(QWidget *parent)
|
Qv2Instance::Qv2Instance(QWidget *parent)
|
||||||
{
|
{
|
||||||
QProcess *proc = new QProcess();
|
auto proc = new QProcess();
|
||||||
vProcess = proc;
|
vProcess = proc;
|
||||||
QObject::connect(vProcess, &QProcess::readyReadStandardOutput, static_cast<MainWindow *>(parent), &MainWindow::UpdateLog);
|
QObject::connect(vProcess, &QProcess::readyReadStandardOutput, static_cast<MainWindow *>(parent), &MainWindow::UpdateLog);
|
||||||
Status = STOPPED;
|
Status = STOPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Qv2Instance::ReadProcessOutput()
|
QString Qv2Instance::ReadProcessOutput()
|
||||||
{
|
{
|
||||||
return vProcess->readAllStandardOutput();
|
return vProcess->readAllStandardOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Qv2Instance::ValidateV2rayCoreExe()
|
bool Qv2Instance::ValidateV2rayCoreExe()
|
||||||
{
|
{
|
||||||
auto path = QString::fromStdString(Utils::GetGlobalConfig().v2CorePath);
|
if (!QFile::exists(QV2RAY_V2RAY_CORE_PATH)) {
|
||||||
|
Utils::QvMessageBox(nullptr, QObject::tr("Cannot start v2ray"), QObject::tr("v2ray core file cannot be found at:") + QV2RAY_V2RAY_CORE_PATH);
|
||||||
if (!QFile::exists(path)) {
|
|
||||||
Utils::QvMessageBox(nullptr, QObject::tr("CoreNotFound"), QObject::tr("CoreFileNotFoundExplainationAt:") + path);
|
|
||||||
return false;
|
return false;
|
||||||
} else return true;
|
} else return true;
|
||||||
}
|
}
|
||||||
@ -64,13 +66,13 @@ namespace Qv2ray
|
|||||||
Status = STARTING;
|
Status = STARTING;
|
||||||
|
|
||||||
if (ValidateV2rayCoreExe()) {
|
if (ValidateV2rayCoreExe()) {
|
||||||
if (VerifyVConfigFile(QV2RAY_GENERATED_FILE_PATH)) {
|
auto filePath = QV2RAY_GENERATED_FILE_PATH;
|
||||||
|
|
||||||
|
if (VerifyVConfigFile(&filePath)) {
|
||||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||||
env.insert("V2RAY_LOCATION_ASSET", QString::fromStdString(GetGlobalConfig().v2AssetsPath));
|
env.insert("V2RAY_LOCATION_ASSET", QString::fromStdString(GetGlobalConfig().v2AssetsPath));
|
||||||
vProcess->setProcessEnvironment(env);
|
vProcess->setProcessEnvironment(env);
|
||||||
vProcess->start(QString::fromStdString(GetGlobalConfig().v2CorePath), QStringList() << "-config"
|
vProcess->start(QV2RAY_V2RAY_CORE_PATH, QStringList() << "-config" << filePath, QIODevice::ReadWrite | QIODevice::Text);
|
||||||
<< QV2RAY_GENERATED_FILE_PATH,
|
|
||||||
QIODevice::ReadWrite | QIODevice::Text);
|
|
||||||
vProcess->waitForStarted();
|
vProcess->waitForStarted();
|
||||||
Status = STARTED;
|
Status = STARTED;
|
||||||
return true;
|
return true;
|
||||||
|
@ -20,7 +20,7 @@ namespace Qv2ray
|
|||||||
bool Start();
|
bool Start();
|
||||||
void Stop();
|
void Stop();
|
||||||
V2RAY_INSTANCE_STARTUP_STATUS Status;
|
V2RAY_INSTANCE_STARTUP_STATUS Status;
|
||||||
static bool VerifyVConfigFile(QString path);
|
static bool VerifyVConfigFile(const QString *path);
|
||||||
static bool ValidateV2rayCoreExe();
|
static bool ValidateV2rayCoreExe();
|
||||||
QString ReadProcessOutput();
|
QString ReadProcessOutput();
|
||||||
|
|
||||||
|
@ -19,4 +19,8 @@ using namespace std;
|
|||||||
#define MODULE_FILE "FILE"
|
#define MODULE_FILE "FILE"
|
||||||
#define MODULE_SUBSCRIPTION "SUBSCRIPTION"
|
#define MODULE_SUBSCRIPTION "SUBSCRIPTION"
|
||||||
|
|
||||||
|
#define WARN "WARN"
|
||||||
|
#define INFO "INFO"
|
||||||
|
#define ERROR "ERROR"
|
||||||
|
|
||||||
#endif // QVTINYLOG_H
|
#endif // QVTINYLOG_H
|
||||||
|
@ -22,24 +22,24 @@ namespace Qv2ray
|
|||||||
return ConfigDirPath;
|
return ConfigDirPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetConfigDirPath(QString path)
|
void SetConfigDirPath(const QString *path)
|
||||||
{
|
{
|
||||||
ConfigDirPath = path;
|
ConfigDirPath = *path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveGlobalConfig()
|
void SaveGlobalConfig()
|
||||||
{
|
{
|
||||||
QFile config(QV2RAY_CONFIG_FILE_PATH);
|
QFile config(QV2RAY_CONFIG_FILE_PATH);
|
||||||
QString str = StructToJSONString(GetGlobalConfig());
|
QString str = StructToJSONString(GetGlobalConfig());
|
||||||
StringToFile(str, &config);
|
StringToFile(&str, &config);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StringToFile(QString text, QFile *targetFile)
|
bool StringToFile(const QString *text, QFile *targetFile)
|
||||||
{
|
{
|
||||||
bool override = targetFile->exists();
|
bool override = targetFile->exists();
|
||||||
targetFile->open(QFile::WriteOnly);
|
targetFile->open(QFile::WriteOnly);
|
||||||
QTextStream stream(targetFile);
|
QTextStream stream(targetFile);
|
||||||
stream << text << endl;
|
stream << *text << endl;
|
||||||
stream.flush();
|
stream.flush();
|
||||||
targetFile->close();
|
targetFile->close();
|
||||||
return override;
|
return override;
|
||||||
|
@ -18,7 +18,7 @@ namespace Qv2ray
|
|||||||
|
|
||||||
bool CheckFile(QDir *dir, QString fileName);
|
bool CheckFile(QDir *dir, QString fileName);
|
||||||
|
|
||||||
void SetConfigDirPath(QString path);
|
void SetConfigDirPath(const QString *path);
|
||||||
QString GetConfigDirPath();
|
QString GetConfigDirPath();
|
||||||
|
|
||||||
void SetGlobalConfig(Qv2rayConfig conf);
|
void SetGlobalConfig(Qv2rayConfig conf);
|
||||||
@ -30,7 +30,7 @@ namespace Qv2ray
|
|||||||
void QvMessageBox(QWidget *parent, QString title, QString text);
|
void QvMessageBox(QWidget *parent, QString title, QString text);
|
||||||
int QvMessageBoxAsk(QWidget *parent, QString title, QString text, QMessageBox::StandardButton extraButtons = QMessageBox::NoButton);
|
int QvMessageBoxAsk(QWidget *parent, QString title, QString text, QMessageBox::StandardButton extraButtons = QMessageBox::NoButton);
|
||||||
//
|
//
|
||||||
bool StringToFile(QString text, QFile *target);
|
bool StringToFile(const QString *text, QFile *target);
|
||||||
QString StringFromFile(QFile *sourceFile);
|
QString StringFromFile(QFile *sourceFile);
|
||||||
//
|
//
|
||||||
QJsonObject JSONFromString(QString string);
|
QJsonObject JSONFromString(QString string);
|
||||||
|
90
src/main.cpp
90
src/main.cpp
@ -7,68 +7,36 @@
|
|||||||
#include "QvRunguard.h"
|
#include "QvRunguard.h"
|
||||||
#include "w_MainWindow.h"
|
#include "w_MainWindow.h"
|
||||||
|
|
||||||
using namespace Qv2ray;
|
|
||||||
using namespace Qv2ray::Utils;
|
|
||||||
using namespace Qv2ray::QvConfigModels;
|
|
||||||
|
|
||||||
bool initQv()
|
bool initQv()
|
||||||
{
|
{
|
||||||
#ifdef QT_DEBUG
|
if (!QDir(QV2RAY_CONFIG_DIR_PATH).exists()) {
|
||||||
QString configPath = QDir::homePath() + "/.qv2ray_debug";
|
QDir().mkdir(QV2RAY_CONFIG_DIR_PATH);
|
||||||
#else
|
LOG(MODULE_INIT, "Created Qv2ray config dir at: " + QV2RAY_CONFIG_DIR_PATH.toStdString())
|
||||||
QString configPath = QDir::homePath() + "/.qv2ray";
|
|
||||||
#endif
|
|
||||||
/// Qv2ray Config Path and ends with "/"
|
|
||||||
QString exeDefaultPath = configPath + "/vcore/v2ray";
|
|
||||||
QString v2AssetsPath = configPath + "/vcore";
|
|
||||||
//
|
|
||||||
#if defined(__WIN32)
|
|
||||||
exeDefaultPath = exeDefaultPath + ".exe";
|
|
||||||
#elif defined(__linux__)
|
|
||||||
// Special case for GNU/Linux
|
|
||||||
//
|
|
||||||
// Unused these values
|
|
||||||
Q_UNUSED(v2AssetsPath)
|
|
||||||
Q_UNUSED(exeDefaultPath)
|
|
||||||
v2AssetsPath = "/etc/v2ray";
|
|
||||||
exeDefaultPath = "/bin/v2ray";
|
|
||||||
#endif
|
|
||||||
//
|
|
||||||
SetConfigDirPath(configPath);
|
|
||||||
auto ConfigDir = new QDir(configPath);
|
|
||||||
|
|
||||||
if (!ConfigDir->exists()) {
|
|
||||||
auto result = QDir().mkdir(QV2RAY_CONFIG_DIR_PATH);
|
|
||||||
|
|
||||||
if (result) {
|
|
||||||
LOG(MODULE_INIT, "Created Qv2ray config dir at: " + QV2RAY_CONFIG_DIR_PATH.toStdString())
|
|
||||||
} else {
|
|
||||||
LOG(MODULE_INIT, "Failed to create config dir at: " + QV2RAY_CONFIG_DIR_PATH.toStdString())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto genPath = QV2RAY_CONFIG_DIR_PATH + "generated/";
|
if (!QDir(QV2RAY_CONFIG_DIR_PATH + "generated/").exists()) {
|
||||||
|
QDir().mkdir(QV2RAY_CONFIG_DIR_PATH + "generated/");
|
||||||
if (!QDir(genPath).exists()) {
|
LOG(MODULE_INIT, "Created config generation dir.")
|
||||||
auto result2 = QDir().mkdir(genPath);
|
|
||||||
|
|
||||||
if (result2) {
|
|
||||||
LOG(MODULE_INIT, "Created config generation dir at: " + genPath.toStdString())
|
|
||||||
} else {
|
|
||||||
LOG(MODULE_INIT, "Failed to create config generation dir at: " + genPath.toStdString())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QFile configFile(QV2RAY_CONFIG_FILE_PATH);
|
if (!QDir(QV2RAY_V2RAY_CORE_DIR_PATH).exists()) {
|
||||||
|
QDir().mkdir(QV2RAY_V2RAY_CORE_DIR_PATH);
|
||||||
|
LOG(MODULE_INIT, "Created dir for v2ray core and assets.")
|
||||||
|
QFile _readmeFile(QV2RAY_V2RAY_CORE_DIR_PATH + "Put your v2ray.exe here.txt");
|
||||||
|
_readmeFile.open(QIODevice::WriteOnly);
|
||||||
|
_readmeFile.write("Please put your v2ray.exe and assets here!");
|
||||||
|
_readmeFile.close();
|
||||||
|
LOG(MODULE_INIT, "Done generating readme.")
|
||||||
|
}
|
||||||
|
|
||||||
if (!configFile.exists()) {
|
QFile qvConfigFile(QV2RAY_CONFIG_FILE_PATH);
|
||||||
// This is first run!
|
|
||||||
|
if (!qvConfigFile.exists()) {
|
||||||
|
// This is first run, even the config file does not exist...
|
||||||
//
|
//
|
||||||
// These below genenrated very basic global config.
|
// These below genenrated very basic global config.
|
||||||
Qv2rayBasicInboundsConfig inboundSetting = Qv2rayBasicInboundsConfig("127.0.0.1", 1080, 8000);
|
Qv2rayBasicInboundsConfig inboundSetting = Qv2rayBasicInboundsConfig("127.0.0.1", 1080, 8000);
|
||||||
Qv2rayConfig conf = Qv2rayConfig("zh-CN", exeDefaultPath.toStdString(), v2AssetsPath.toStdString(), 2, inboundSetting);
|
Qv2rayConfig conf = Qv2rayConfig("zh-CN", QV2RAY_V2RAY_CORE_DIR_PATH.toStdString(), 4, inboundSetting);
|
||||||
//
|
//
|
||||||
// Save initial config.
|
// Save initial config.
|
||||||
SetGlobalConfig(conf);
|
SetGlobalConfig(conf);
|
||||||
@ -77,12 +45,19 @@ bool initQv()
|
|||||||
LOG(MODULE_INIT, "Created initial config file.")
|
LOG(MODULE_INIT, "Created initial config file.")
|
||||||
} else {
|
} else {
|
||||||
// Some config file upgrades.
|
// Some config file upgrades.
|
||||||
auto conf = JSONFromString(StringFromFile(&configFile));
|
auto conf = JSONFromString(StringFromFile(&qvConfigFile));
|
||||||
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));
|
||||||
|
|
||||||
if (QString::compare(confVersion, newVersion) != 0) {
|
// Config version is larger than the current version...
|
||||||
conf = UpgradeConfig(stoi(conf["config_version"].toString().toStdString()), QV2RAY_CONFIG_VERSION, conf);
|
if (stoi(confVersion.toStdString()) > QV2RAY_CONFIG_VERSION) {
|
||||||
|
QvMessageBox(nullptr, QObject::tr("Qv2ray Cannot Continue"), QObject::tr("You are running a lower version of Qv2ray compared to the current config file.") +
|
||||||
|
"\r\n" +
|
||||||
|
QObject::tr("Please report if you think this is an error.") + "\r\n" +
|
||||||
|
QObject::tr("Qv2ray will now exit."));
|
||||||
|
return false;
|
||||||
|
} else if (QString::compare(confVersion, newVersion) != 0) {
|
||||||
|
conf = UpgradeConfig(stoi(confVersion.toStdString()), QV2RAY_CONFIG_VERSION, conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto confObject = StructFromJSONString<Qv2rayConfig>(JSONToString(conf));
|
auto confObject = StructFromJSONString<Qv2rayConfig>(JSONToString(conf));
|
||||||
@ -110,7 +85,11 @@ int main(int argc, char *argv[])
|
|||||||
//
|
//
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
LOG("DEBUG", "============================== This is a debug build, many features are not stable enough. ==============================")
|
LOG("DEBUG", "============================== This is a debug build, many features are not stable enough. ==============================")
|
||||||
|
QString configPath = QDir::homePath() + "/.qv2ray_debug";
|
||||||
|
#else
|
||||||
|
QString configPath = QDir::homePath() + "/.qv2ray";
|
||||||
#endif
|
#endif
|
||||||
|
SetConfigDirPath(&configPath);
|
||||||
QDirIterator it(":/translations");
|
QDirIterator it(":/translations");
|
||||||
|
|
||||||
if (!it.hasNext()) {
|
if (!it.hasNext()) {
|
||||||
@ -155,7 +134,6 @@ int main(int argc, char *argv[])
|
|||||||
"DEBUG_VERSION"
|
"DEBUG_VERSION"
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
|
||||||
auto osslReqVersion = QSslSocket::sslLibraryBuildVersionString().toStdString();
|
auto osslReqVersion = QSslSocket::sslLibraryBuildVersionString().toStdString();
|
||||||
auto osslCurVersion = QSslSocket::sslLibraryVersionString().toStdString();
|
auto osslCurVersion = QSslSocket::sslLibraryVersionString().toStdString();
|
||||||
LOG(MODULE_NETWORK, "Current OpenSSL version: " + osslCurVersion)
|
LOG(MODULE_NETWORK, "Current OpenSSL version: " + osslCurVersion)
|
||||||
|
@ -30,10 +30,10 @@ ConnectionEditWindow::ConnectionEditWindow(QWidget *parent)
|
|||||||
GEN_JSON
|
GEN_JSON
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionEditWindow::ConnectionEditWindow(QJsonObject editRootObject, QString alias, QWidget *parent)
|
ConnectionEditWindow::ConnectionEditWindow(QJsonObject editRootObject, const QString *alias, QWidget *parent)
|
||||||
: ConnectionEditWindow(parent)
|
: ConnectionEditWindow(parent)
|
||||||
{
|
{
|
||||||
_alias = alias;
|
_alias = *alias;
|
||||||
originalRoot = editRootObject;
|
originalRoot = editRootObject;
|
||||||
auto outBoundRoot = originalRoot["outbounds"].toArray().first().toObject();
|
auto outBoundRoot = originalRoot["outbounds"].toArray().first().toObject();
|
||||||
OutboundType = outBoundRoot["protocol"].toString();
|
OutboundType = outBoundRoot["protocol"].toString();
|
||||||
@ -156,7 +156,6 @@ void ConnectionEditWindow::on_buttonBox_accepted()
|
|||||||
}
|
}
|
||||||
|
|
||||||
originalRoot.insert("outbounds", outbounds);
|
originalRoot.insert("outbounds", outbounds);
|
||||||
originalRoot.insert(QV2RAY_CONFIG_TYPE_JSON_KEY, QV2RAY_CONFIG_TYPE_MANUAL);
|
|
||||||
SaveConnectionConfig(originalRoot, &alias);
|
SaveConnectionConfig(originalRoot, &alias);
|
||||||
auto globalConf = GetGlobalConfig();
|
auto globalConf = GetGlobalConfig();
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ class ConnectionEditWindow : public QDialog
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ConnectionEditWindow(QWidget *parent = nullptr);
|
explicit ConnectionEditWindow(QWidget *parent = nullptr);
|
||||||
explicit ConnectionEditWindow(QJsonObject editRootObject, QString alias, QWidget *parent = nullptr);
|
explicit ConnectionEditWindow(QJsonObject editRootObject, const QString *alias, QWidget *parent = nullptr);
|
||||||
~ConnectionEditWindow();
|
~ConnectionEditWindow();
|
||||||
signals:
|
signals:
|
||||||
void s_reload_config(bool need_restart);
|
void s_reload_config(bool need_restart);
|
||||||
|
@ -33,7 +33,7 @@ void ImportConfigWindow::on_importSourceCombo_currentIndexChanged(int index)
|
|||||||
|
|
||||||
void ImportConfigWindow::on_selectFileBtn_clicked()
|
void ImportConfigWindow::on_selectFileBtn_clicked()
|
||||||
{
|
{
|
||||||
QString dir = QFileDialog::getOpenFileName(this, tr("OpenConfigFile"), "~/");
|
QString dir = QFileDialog::getOpenFileName(this, tr("Select file to import"), QDir::currentPath());
|
||||||
ui->fileLineTxt->setText(dir);
|
ui->fileLineTxt->setText(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,9 +45,10 @@ void ImportConfigWindow::on_buttonBox_accepted()
|
|||||||
if (ui->importSourceCombo->currentIndex() == 0) {
|
if (ui->importSourceCombo->currentIndex() == 0) {
|
||||||
// From File...
|
// From File...
|
||||||
bool overrideInBound = !ui->keepImportedInboundCheckBox->isChecked();
|
bool overrideInBound = !ui->keepImportedInboundCheckBox->isChecked();
|
||||||
|
auto fileName = ui->fileLineTxt->text();
|
||||||
|
|
||||||
if (!Qv2Instance::VerifyVConfigFile(ui->fileLineTxt->text())) {
|
if (!Qv2Instance::VerifyVConfigFile(&fileName)) {
|
||||||
QvMessageBox(this, tr("#InvalidConfigFile"), tr("ConfigFileCheckFailed"));
|
QvMessageBox(this, tr("Import config file"), tr("Failed to check the validity of the config file."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,28 +59,33 @@ void ImportConfigWindow::on_buttonBox_accepted()
|
|||||||
QString vmess = ui->vmessConnectionStringTxt->toPlainText();
|
QString vmess = ui->vmessConnectionStringTxt->toPlainText();
|
||||||
int result = VerifyVMessProtocolString(vmess);
|
int result = VerifyVMessProtocolString(vmess);
|
||||||
|
|
||||||
if (result == 0) {
|
switch (result) {
|
||||||
// This result code passes the validation check.
|
case 0:
|
||||||
//QvMessageBox(this, tr("#VMessCheck"), tr("#AbleToImportConfig"));
|
// This result code passes the validation check.
|
||||||
} else if (result == -1) {
|
//QvMessageBox(this, tr("#VMessCheck"), tr("#AbleToImportConfig"));
|
||||||
QvMessageBox(this, tr("#VMessCheck"), tr("#NotValidVMessProtocolString"));
|
break;
|
||||||
done(0);
|
|
||||||
return;
|
case -1:
|
||||||
} else {
|
QvMessageBox(this, tr("VMess String Check"), tr("VMess string is not valid"));
|
||||||
QvMessageBox(this, tr("#VMessCheck"), tr("#INTERNAL_ERROR"));
|
done(0);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
QvMessageBox(this, tr("VMess String Check"), tr("Some internal error occured"));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
config = ConvertConfigFromVMessString(ui->vmessConnectionStringTxt->toPlainText());
|
config = ConvertConfigFromVMessString(ui->vmessConnectionStringTxt->toPlainText());
|
||||||
//
|
//
|
||||||
alias = alias != "" ? alias : config["QV2RAY_ALIAS"].toString();
|
alias = alias.isEmpty() ? alias : config["QV2RAY_ALIAS"].toString();
|
||||||
config.remove("QV2RAY_ALIAS");
|
config.remove("QV2RAY_ALIAS");
|
||||||
}
|
}
|
||||||
|
|
||||||
Qv2rayConfig conf = GetGlobalConfig();
|
Qv2rayConfig conf = GetGlobalConfig();
|
||||||
|
//
|
||||||
conf.configs.push_back(alias.toStdString());
|
conf.configs.push_back(alias.toStdString());
|
||||||
|
//
|
||||||
SetGlobalConfig(conf);
|
SetGlobalConfig(conf);
|
||||||
auto needReload = SaveConnectionConfig(config, &alias);
|
auto needReload = SaveConnectionConfig(config, &alias);
|
||||||
LOG(MODULE_CONNECTION_VMESS, "WARNING: POSSIBLE LOSS OF DATA")
|
|
||||||
emit s_reload_config(needReload);
|
emit s_reload_config(needReload);
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "w_PrefrencesWindow.h"
|
|
||||||
#include "w_ImportConfig.h"
|
|
||||||
#include "w_ConnectionEditWindow.h"
|
#include "w_ConnectionEditWindow.h"
|
||||||
|
#include "w_ImportConfig.h"
|
||||||
#include "w_MainWindow.h"
|
#include "w_MainWindow.h"
|
||||||
|
#include "w_PrefrencesWindow.h"
|
||||||
#include "w_SubscribeEditor.h"
|
#include "w_SubscribeEditor.h"
|
||||||
|
|
||||||
#define TRAY_TOOLTIP_PREFIX "Qv2ray " QV2RAY_VERSION_STRING "\r\n"
|
#define TRAY_TOOLTIP_PREFIX "Qv2ray " QV2RAY_VERSION_STRING "\r\n"
|
||||||
@ -75,23 +75,29 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
|
|
||||||
//
|
//
|
||||||
if (!vinstance->ValidateV2rayCoreExe()) {
|
if (!vinstance->ValidateV2rayCoreExe()) {
|
||||||
on_prefrencesBtn_clicked();
|
QDesktopServices::openUrl(QUrl::fromLocalFile(QV2RAY_V2RAY_CORE_DIR_PATH));
|
||||||
}
|
|
||||||
|
|
||||||
auto conf = GetGlobalConfig();
|
|
||||||
|
|
||||||
if (conf.autoStartConfig != "" && QList<string>::fromStdList(conf.configs).contains(conf.autoStartConfig)) {
|
|
||||||
CurrentConnectionName = QSTRING(conf.autoStartConfig);
|
|
||||||
auto item = ui->connectionListWidget->findItems(QSTRING(conf.autoStartConfig), Qt::MatchExactly).front();
|
|
||||||
item->setSelected(true);
|
|
||||||
ui->connectionListWidget->setCurrentItem(item);
|
|
||||||
on_connectionListWidget_itemClicked(item);
|
|
||||||
on_startButton_clicked();
|
|
||||||
//ToggleVisibility();
|
|
||||||
this->hide();
|
|
||||||
trayMenu->actions()[0]->setText(tr("Show"));
|
|
||||||
} else {
|
} else {
|
||||||
this->show();
|
auto conf = GetGlobalConfig();
|
||||||
|
|
||||||
|
if (conf.autoStartConfig != "" && QList<string>::fromStdList(conf.configs).contains(conf.autoStartConfig)) {
|
||||||
|
CurrentConnectionName = QSTRING(conf.autoStartConfig);
|
||||||
|
auto item = ui->connectionListWidget->findItems(QSTRING(conf.autoStartConfig), Qt::MatchExactly).front();
|
||||||
|
item->setSelected(true);
|
||||||
|
ui->connectionListWidget->setCurrentItem(item);
|
||||||
|
on_connectionListWidget_itemClicked(item);
|
||||||
|
on_startButton_clicked();
|
||||||
|
//ToggleVisibility();
|
||||||
|
this->hide();
|
||||||
|
trayMenu->actions()[0]->setText(tr("Show"));
|
||||||
|
} else {
|
||||||
|
this->show();
|
||||||
|
|
||||||
|
if (ui->connectionListWidget->count() != 0) {
|
||||||
|
// The first one is default.
|
||||||
|
ui->connectionListWidget->setCurrentRow(0);
|
||||||
|
ShowAndSetConnection(ui->connectionListWidget->item(0)->text(), true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,8 +202,8 @@ void MainWindow::on_startButton_clicked()
|
|||||||
bool startFlag = this->vinstance->Start();
|
bool startFlag = this->vinstance->Start();
|
||||||
|
|
||||||
if (startFlag) {
|
if (startFlag) {
|
||||||
this->hTray->showMessage("Qv2ray", tr("Connected To Server: ") + " " + CurrentConnectionName);
|
this->hTray->showMessage("Qv2ray", tr("Connected To Server: ") + CurrentConnectionName);
|
||||||
hTray->setToolTip(TRAY_TOOLTIP_PREFIX + tr("Connected To Server: ") + ": " + CurrentConnectionName);
|
hTray->setToolTip(TRAY_TOOLTIP_PREFIX + tr("Connected To Server: ") + CurrentConnectionName);
|
||||||
ui->statusLabel->setText(tr("Connected") + ": " + CurrentConnectionName);
|
ui->statusLabel->setText(tr("Connected") + ": " + CurrentConnectionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,11 +311,8 @@ void MainWindow::QTextScrollToBottom()
|
|||||||
if (bar->value() >= bar->maximum() - 10) bar->setValue(bar->maximum());
|
if (bar->value() >= bar->maximum() - 10) bar->setValue(bar->maximum());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::ShowAndSetConnection(int index, bool SetConnection, bool ApplyConnection)
|
void MainWindow::ShowAndSetConnection(QString guiConnectionName, bool SetConnection, bool ApplyConnection)
|
||||||
{
|
{
|
||||||
if (index < 0) return;
|
|
||||||
|
|
||||||
auto guiConnectionName = ui->connectionListWidget->item(index)->text();
|
|
||||||
// --------- BRGIN Show Connection
|
// --------- BRGIN Show Connection
|
||||||
auto outBoundRoot = (connections[guiConnectionName])["outbounds"].toArray().first().toObject();
|
auto outBoundRoot = (connections[guiConnectionName])["outbounds"].toArray().first().toObject();
|
||||||
//
|
//
|
||||||
@ -362,7 +365,12 @@ void MainWindow::on_connectionListWidget_itemClicked(QListWidgetItem *item)
|
|||||||
{
|
{
|
||||||
Q_UNUSED(item)
|
Q_UNUSED(item)
|
||||||
int currentRow = ui->connectionListWidget->currentRow();
|
int currentRow = ui->connectionListWidget->currentRow();
|
||||||
ShowAndSetConnection(currentRow, !isRenamingInProgress && (vinstance->Status != STARTED), false);
|
|
||||||
|
if (currentRow < 0) return;
|
||||||
|
|
||||||
|
QString currentText = ui->connectionListWidget->currentItem()->text();
|
||||||
|
bool canSetConnection = !isRenamingInProgress && vinstance->Status != STARTED ;
|
||||||
|
ShowAndSetConnection(currentText, canSetConnection, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_prefrencesBtn_clicked()
|
void MainWindow::on_prefrencesBtn_clicked()
|
||||||
@ -374,7 +382,13 @@ void MainWindow::on_prefrencesBtn_clicked()
|
|||||||
|
|
||||||
void MainWindow::on_connectionListWidget_doubleClicked(const QModelIndex &index)
|
void MainWindow::on_connectionListWidget_doubleClicked(const QModelIndex &index)
|
||||||
{
|
{
|
||||||
ShowAndSetConnection(index.row(), true, true);
|
Q_UNUSED(index)
|
||||||
|
int currentRow = ui->connectionListWidget->currentRow();
|
||||||
|
|
||||||
|
if (currentRow < 0) return;
|
||||||
|
|
||||||
|
QString currentText = ui->connectionListWidget->currentItem()->text();
|
||||||
|
ShowAndSetConnection(currentText, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_clearlogButton_clicked()
|
void MainWindow::on_clearlogButton_clicked()
|
||||||
@ -385,7 +399,7 @@ void MainWindow::on_clearlogButton_clicked()
|
|||||||
void MainWindow::on_connectionListWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
|
void MainWindow::on_connectionListWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
|
||||||
{
|
{
|
||||||
Q_UNUSED(previous)
|
Q_UNUSED(previous)
|
||||||
isRenamingInProgress = true;
|
isRenamingInProgress = false;
|
||||||
on_connectionListWidget_itemClicked(current);
|
on_connectionListWidget_itemClicked(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -401,14 +415,14 @@ void MainWindow::on_action_RenameConnection_triggered()
|
|||||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||||
ui->connectionListWidget->editItem(item);
|
ui->connectionListWidget->editItem(item);
|
||||||
originalName = item->text();
|
originalName = item->text();
|
||||||
isRenamingInProgress = false;
|
isRenamingInProgress = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_connectionListWidget_itemChanged(QListWidgetItem *item)
|
void MainWindow::on_connectionListWidget_itemChanged(QListWidgetItem *item)
|
||||||
{
|
{
|
||||||
LOG(MODULE_UI, "A connection ListViewItem is changed.")
|
LOG(MODULE_UI, "A connection ListViewItem is changed.")
|
||||||
|
|
||||||
if (!isRenamingInProgress) {
|
if (isRenamingInProgress) {
|
||||||
// In this case it's after we entered the name.
|
// In this case it's after we entered the name.
|
||||||
LOG(MODULE_CONNECTION, "RENAME: " + originalName.toStdString() + " -> " + item->text().toStdString())
|
LOG(MODULE_CONNECTION, "RENAME: " + originalName.toStdString() + " -> " + item->text().toStdString())
|
||||||
auto newName = item->text();
|
auto newName = item->text();
|
||||||
@ -416,16 +430,16 @@ void MainWindow::on_connectionListWidget_itemChanged(QListWidgetItem *item)
|
|||||||
auto configList = QList<string>::fromStdList(config.configs);
|
auto configList = QList<string>::fromStdList(config.configs);
|
||||||
|
|
||||||
if (newName.trimmed().isEmpty()) {
|
if (newName.trimmed().isEmpty()) {
|
||||||
QvMessageBox(this, tr("Rename A Connection"), tr("A name cannot be empty"));
|
QvMessageBox(this, tr("Rename a Connection"), tr("The name cannot be empty"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If I really did some changes.
|
|
||||||
LOG("RENAME", "ORIGINAL: " + originalName.toStdString() + ", NEW: " + newName.toStdString())
|
LOG("RENAME", "ORIGINAL: " + originalName.toStdString() + ", NEW: " + newName.toStdString())
|
||||||
|
|
||||||
|
// If I really did some changes.
|
||||||
if (originalName != newName) {
|
if (originalName != newName) {
|
||||||
if (configList.contains(newName.toStdString())) {
|
if (configList.contains(newName.toStdString())) {
|
||||||
QvMessageBox(this, tr("Rename A Connection"), tr("The name has been used already, Please choose another."));
|
QvMessageBox(this, tr("Rename a Connection"), tr("The name has been used already, Please choose another."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,7 +466,7 @@ void MainWindow::on_connectionListWidget_itemChanged(QListWidgetItem *item)
|
|||||||
|
|
||||||
void MainWindow::on_removeConfigButton_clicked()
|
void MainWindow::on_removeConfigButton_clicked()
|
||||||
{
|
{
|
||||||
if (QvMessageBoxAsk(this, tr("Removing A Connection"), tr("Are you sure to remove this connection?")) == QMessageBox::Yes) {
|
if (QvMessageBoxAsk(this, tr("Removing this Connection"), tr("Are you sure to remove this connection?")) == QMessageBox::Yes) {
|
||||||
auto conf = GetGlobalConfig();
|
auto conf = GetGlobalConfig();
|
||||||
QList<string> list = QList<string>::fromStdList(conf.configs);
|
QList<string> list = QList<string>::fromStdList(conf.configs);
|
||||||
auto currentSelected = ui->connectionListWidget->currentIndex().row();
|
auto currentSelected = ui->connectionListWidget->currentIndex().row();
|
||||||
@ -489,16 +503,14 @@ void MainWindow::on_addConfigButton_clicked()
|
|||||||
void MainWindow::on_editConfigButton_clicked()
|
void MainWindow::on_editConfigButton_clicked()
|
||||||
{
|
{
|
||||||
// Check if we have a connection selected...
|
// Check if we have a connection selected...
|
||||||
auto index = ui->connectionListWidget->currentIndex().row();
|
if (ui->connectionListWidget->currentIndex().row() < 0) {
|
||||||
|
|
||||||
if (index < 0) {
|
|
||||||
QvMessageBox(this, tr("NoConfigSelected"), tr("PleaseSelectAConfig"));
|
QvMessageBox(this, tr("NoConfigSelected"), tr("PleaseSelectAConfig"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto alias = ui->connectionListWidget->currentItem()->text();
|
auto alias = ui->connectionListWidget->currentItem()->text();
|
||||||
auto outBoundRoot = connections[alias];
|
auto outBoundRoot = connections[alias];
|
||||||
ConnectionEditWindow *w = new ConnectionEditWindow(outBoundRoot, alias, this);
|
ConnectionEditWindow *w = new ConnectionEditWindow(outBoundRoot, &alias, this);
|
||||||
connect(w, &ConnectionEditWindow::s_reload_config, this, &MainWindow::save_reload_globalconfig);
|
connect(w, &ConnectionEditWindow::s_reload_config, this, &MainWindow::save_reload_globalconfig);
|
||||||
w->show();
|
w->show();
|
||||||
}
|
}
|
||||||
@ -508,3 +520,8 @@ void MainWindow::on_pushButton_clicked()
|
|||||||
SubscribeEditor *w = new SubscribeEditor(this);
|
SubscribeEditor *w = new SubscribeEditor(this);
|
||||||
w->show();
|
w->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_reconnectButton_clicked()
|
||||||
|
{
|
||||||
|
on_restartButton_clicked();
|
||||||
|
}
|
||||||
|
@ -59,6 +59,8 @@ class MainWindow : public QMainWindow
|
|||||||
|
|
||||||
void on_pushButton_clicked();
|
void on_pushButton_clicked();
|
||||||
|
|
||||||
|
void on_reconnectButton_clicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void on_action_StartThis_triggered();
|
void on_action_StartThis_triggered();
|
||||||
void on_action_RenameConnection_triggered();
|
void on_action_RenameConnection_triggered();
|
||||||
@ -75,7 +77,7 @@ class MainWindow : public QMainWindow
|
|||||||
QString originalName;
|
QString originalName;
|
||||||
bool isRenamingInProgress;
|
bool isRenamingInProgress;
|
||||||
//
|
//
|
||||||
void ShowAndSetConnection(int index, bool SetConnection, bool Apply);
|
void ShowAndSetConnection(QString currentText, bool SetConnection, bool Apply);
|
||||||
void LoadConnections();
|
void LoadConnections();
|
||||||
void closeEvent(QCloseEvent *);
|
void closeEvent(QCloseEvent *);
|
||||||
};
|
};
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout" columnstretch="2,3">
|
<layout class="QGridLayout" name="gridLayout" columnstretch="2,3">
|
||||||
<item row="0" column="0" colspan="2">
|
<item row="0" column="0" colspan="2">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1,1,0,0,0">
|
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1,0,1,0,0,0">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>5</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
@ -58,6 +58,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="reconnectButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Reconnect</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="clearlogButton">
|
<widget class="QPushButton" name="clearlogButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -5,10 +5,6 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#ifdef __linux
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define NEEDRESTART if(finishedLoading) IsConnectionPropertyChanged = true;
|
#define NEEDRESTART if(finishedLoading) IsConnectionPropertyChanged = true;
|
||||||
|
|
||||||
PrefrencesWindow::PrefrencesWindow(QWidget *parent) : QDialog(parent),
|
PrefrencesWindow::PrefrencesWindow(QWidget *parent) : QDialog(parent),
|
||||||
@ -30,7 +26,7 @@ PrefrencesWindow::PrefrencesWindow(QWidget *parent) : QDialog(parent),
|
|||||||
//
|
//
|
||||||
ui->languageComboBox->setCurrentText(QSTRING(CurrentConfig.language));
|
ui->languageComboBox->setCurrentText(QSTRING(CurrentConfig.language));
|
||||||
ui->logLevelComboBox->setCurrentIndex(CurrentConfig.logLevel);
|
ui->logLevelComboBox->setCurrentIndex(CurrentConfig.logLevel);
|
||||||
ui->runAsRootCheckBox->setChecked(CurrentConfig.runAsRoot);
|
ui->tProxyCheckBox->setChecked(CurrentConfig.runAsRoot);
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
ui->listenIPTxt->setText(QSTRING(CurrentConfig.inBoundSettings.listenip));
|
ui->listenIPTxt->setText(QSTRING(CurrentConfig.inBoundSettings.listenip));
|
||||||
@ -63,7 +59,6 @@ PrefrencesWindow::PrefrencesWindow(QWidget *parent) : QDialog(parent),
|
|||||||
ui->socksPortLE->setValidator(new QIntValidator());
|
ui->socksPortLE->setValidator(new QIntValidator());
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
ui->vCoreExePathTxt->setText(QSTRING(CurrentConfig.v2CorePath));
|
|
||||||
ui->vCoreAssetsPathTxt->setText(QSTRING(CurrentConfig.v2AssetsPath));
|
ui->vCoreAssetsPathTxt->setText(QSTRING(CurrentConfig.v2AssetsPath));
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
@ -105,7 +100,7 @@ void PrefrencesWindow::on_buttonBox_accepted()
|
|||||||
int hp = ui->httpPortLE->text().toInt() ;
|
int hp = ui->httpPortLE->text().toInt() ;
|
||||||
|
|
||||||
if (!(sp == 0 || hp == 0) && sp == hp) {
|
if (!(sp == 0 || hp == 0) && sp == hp) {
|
||||||
QvMessageBox(this, tr("Prefrences"), tr("PortNumbersCannotBeSame"));
|
QvMessageBox(this, tr("Prefrences"), tr("Port numbers cannot be the same"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,38 +144,6 @@ void PrefrencesWindow::on_httpAuthCB_stateChanged(int checked)
|
|||||||
CurrentConfig.inBoundSettings.http_useAuth = checked == Qt::Checked;
|
CurrentConfig.inBoundSettings.http_useAuth = checked == Qt::Checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrefrencesWindow::on_runAsRootCheckBox_stateChanged(int arg1)
|
|
||||||
{
|
|
||||||
#ifdef __linux
|
|
||||||
// Set UID and GID for linux
|
|
||||||
QString vCorePath = QString::fromStdString(CurrentConfig.v2CorePath);
|
|
||||||
QFileInfo v2rayCoreExeFile(vCorePath);
|
|
||||||
|
|
||||||
if (arg1 == Qt::Checked && v2rayCoreExeFile.ownerId() != 0) {
|
|
||||||
QProcess::execute("pkexec", QStringList() << "bash"
|
|
||||||
<< "-c"
|
|
||||||
<< "chown root:root " + vCorePath + " && "
|
|
||||||
<< "chmod +s " + vCorePath);
|
|
||||||
CurrentConfig.runAsRoot = true;
|
|
||||||
NEEDRESTART
|
|
||||||
} else if (arg1 != Qt::Checked && v2rayCoreExeFile.ownerId() == 0) {
|
|
||||||
uid_t uid = getuid();
|
|
||||||
gid_t gid = getgid();
|
|
||||||
QProcess::execute("pkexec", QStringList()
|
|
||||||
<< "chown" << QString::number(uid) + ":" + QString::number(gid)
|
|
||||||
<< vCorePath);
|
|
||||||
CurrentConfig.runAsRoot = false;
|
|
||||||
NEEDRESTART
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
Q_UNUSED(arg1)
|
|
||||||
ui->runAsRootCheckBox->setChecked(false);
|
|
||||||
// No such uid gid thing on Windows and MacOS is in TODO ....
|
|
||||||
QvMessageBox(this, tr("Prefrences"), tr("RunAsRootNotOnWindows"));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrefrencesWindow::on_socksAuthCB_stateChanged(int checked)
|
void PrefrencesWindow::on_socksAuthCB_stateChanged(int checked)
|
||||||
{
|
{
|
||||||
NEEDRESTART
|
NEEDRESTART
|
||||||
@ -193,7 +156,7 @@ void PrefrencesWindow::on_languageComboBox_currentTextChanged(const QString &arg
|
|||||||
{
|
{
|
||||||
CurrentConfig.language = arg1.toStdString();
|
CurrentConfig.language = arg1.toStdString();
|
||||||
//
|
//
|
||||||
// A strange bug prevents us to change the UI language `live`ly
|
// A strange bug prevents us to change the UI language online
|
||||||
// https://github.com/lhy0403/Qv2ray/issues/34
|
// https://github.com/lhy0403/Qv2ray/issues/34
|
||||||
//
|
//
|
||||||
//if (QApplication::installTranslator(getTranslator(&arg1))) {
|
//if (QApplication::installTranslator(getTranslator(&arg1))) {
|
||||||
@ -210,12 +173,6 @@ void PrefrencesWindow::on_logLevelComboBox_currentIndexChanged(int index)
|
|||||||
CurrentConfig.logLevel = index;
|
CurrentConfig.logLevel = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrefrencesWindow::on_vCoreExePathTxt_textEdited(const QString &arg1)
|
|
||||||
{
|
|
||||||
NEEDRESTART
|
|
||||||
CurrentConfig.v2CorePath = arg1.toStdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrefrencesWindow::on_vCoreAssetsPathTxt_textEdited(const QString &arg1)
|
void PrefrencesWindow::on_vCoreAssetsPathTxt_textEdited(const QString &arg1)
|
||||||
{
|
{
|
||||||
NEEDRESTART
|
NEEDRESTART
|
||||||
@ -294,21 +251,10 @@ void PrefrencesWindow::on_localDNSCb_stateChanged(int arg1)
|
|||||||
CurrentConfig.withLocalDNS = arg1 == Qt::Checked;
|
CurrentConfig.withLocalDNS = arg1 == Qt::Checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrefrencesWindow::on_selectVCoreBtn_clicked()
|
|
||||||
{
|
|
||||||
NEEDRESTART
|
|
||||||
QString path = QFileDialog::getOpenFileName(this, tr("#OpenVCoreFile"), QDir::homePath());
|
|
||||||
ui->vCoreExePathTxt->setText(path);
|
|
||||||
on_vCoreExePathTxt_textEdited(path);
|
|
||||||
auto dir = QFileInfo(path).dir().path();
|
|
||||||
ui->vCoreAssetsPathTxt->setText(dir);
|
|
||||||
on_vCoreAssetsPathTxt_textEdited(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrefrencesWindow::on_selectVAssetBtn_clicked()
|
void PrefrencesWindow::on_selectVAssetBtn_clicked()
|
||||||
{
|
{
|
||||||
NEEDRESTART
|
NEEDRESTART
|
||||||
QString dir = QFileDialog::getExistingDirectory(this, tr("OpenVAssetsDir"), QDir::homePath());
|
QString dir = QFileDialog::getExistingDirectory(this, tr("Open v2ray assets folder"), QDir::currentPath());
|
||||||
ui->vCoreAssetsPathTxt->setText(dir);
|
ui->vCoreAssetsPathTxt->setText(dir);
|
||||||
on_vCoreAssetsPathTxt_textEdited(dir);
|
on_vCoreAssetsPathTxt_textEdited(dir);
|
||||||
}
|
}
|
||||||
@ -350,3 +296,55 @@ void PrefrencesWindow::on_cancelIgnoreVersionBtn_clicked()
|
|||||||
CurrentConfig.ignoredVersion.clear();
|
CurrentConfig.ignoredVersion.clear();
|
||||||
ui->cancelIgnoreVersionBtn->setEnabled(false);
|
ui->cancelIgnoreVersionBtn->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PrefrencesWindow::on_tProxyCheckBox_stateChanged(int arg1)
|
||||||
|
{
|
||||||
|
#ifdef __linux
|
||||||
|
|
||||||
|
if (finishedLoading) {
|
||||||
|
//LOG(MODULE_UI, "Running getcap....")
|
||||||
|
//QProcess::execute("getcap " + QV2RAY_V2RAY_CORE_PATH);
|
||||||
|
|
||||||
|
// Set UID and GID for linux
|
||||||
|
// Steps:
|
||||||
|
// --> 1. Copy v2ray core files to the #CONFIG_DIR#/vcore/ dir.
|
||||||
|
// --> 2. Change GlobalConfig.v2CorePath.
|
||||||
|
// --> 3. Call `pkexec setcap CAP_NET_ADMIN,CAP_NET_RAW,CAP_NET_BIND_SERVICE=eip` on the v2ray core.
|
||||||
|
if (arg1 == Qt::Checked) {
|
||||||
|
// We enable it!
|
||||||
|
if (QvMessageBoxAsk(this, tr("Enable tProxy Support"), tr("This will append capabilities to the v2ray executable.") + "\r\n"
|
||||||
|
+ tr("If anything goes wrong after enabling this, please refer to issue #57 or the link below:") + "\r\n" +
|
||||||
|
" https://github.com/lhy0403/Qv2ray/blob/master/docs/FAQ.md ") != QMessageBox::Yes) {
|
||||||
|
ui->tProxyCheckBox->setChecked(false);
|
||||||
|
LOG(MODULE_UI, "Canceled enabling tProxy feature.")
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = QProcess::execute("pkexec setcap CAP_NET_ADMIN,CAP_NET_RAW,CAP_NET_BIND_SERVICE=eip " + QV2RAY_V2RAY_CORE_PATH);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
LOG(MODULE_UI, "WARN: setcap exits with code: " + to_string(ret))
|
||||||
|
QvMessageBox(this, tr("Prefrences"), tr("Failed to setcap onto v2ray executable. You may need to run `setcap` manually."));
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentConfig.runAsRoot = true;
|
||||||
|
NEEDRESTART
|
||||||
|
} else {
|
||||||
|
int ret = QProcess::execute("pkexec setcap -r " + QV2RAY_V2RAY_CORE_PATH);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
LOG(MODULE_UI, "WARN: setcap exits with code: " + to_string(ret))
|
||||||
|
QvMessageBox(this, tr("Prefrences"), tr("Failed to setcap onto v2ray executable. You may need to run `setcap` manually."));
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentConfig.runAsRoot = false;
|
||||||
|
NEEDRESTART
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
Q_UNUSED(arg1)
|
||||||
|
ui->tProxyCheckBox->setChecked(false);
|
||||||
|
// No such uid gid thing on Windows and MacOS
|
||||||
|
QvMessageBox(this, tr("Prefrences"), tr("tProxy is not supported on MacOS and Windows"));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
@ -19,23 +19,22 @@ class PrefrencesWindow : public QDialog
|
|||||||
~PrefrencesWindow();
|
~PrefrencesWindow();
|
||||||
signals:
|
signals:
|
||||||
void s_reload_config(bool need_restart);
|
void s_reload_config(bool need_restart);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_buttonBox_accepted();
|
void on_buttonBox_accepted();
|
||||||
|
|
||||||
void on_httpCB_stateChanged(int arg1);
|
void on_httpCB_stateChanged(int arg1);
|
||||||
|
|
||||||
void on_socksCB_stateChanged(int arg1);
|
void on_socksCB_stateChanged(int arg1);
|
||||||
|
|
||||||
void on_httpAuthCB_stateChanged(int arg1);
|
void on_httpAuthCB_stateChanged(int arg1);
|
||||||
|
|
||||||
void on_runAsRootCheckBox_stateChanged(int arg1);
|
|
||||||
|
|
||||||
void on_socksAuthCB_stateChanged(int arg1);
|
void on_socksAuthCB_stateChanged(int arg1);
|
||||||
|
|
||||||
void on_languageComboBox_currentTextChanged(const QString &arg1);
|
void on_languageComboBox_currentTextChanged(const QString &arg1);
|
||||||
|
|
||||||
void on_logLevelComboBox_currentIndexChanged(int index);
|
void on_logLevelComboBox_currentIndexChanged(int index);
|
||||||
|
|
||||||
void on_vCoreExePathTxt_textEdited(const QString &arg1);
|
|
||||||
|
|
||||||
void on_vCoreAssetsPathTxt_textEdited(const QString &arg1);
|
void on_vCoreAssetsPathTxt_textEdited(const QString &arg1);
|
||||||
|
|
||||||
void on_muxEnabledCB_stateChanged(int arg1);
|
void on_muxEnabledCB_stateChanged(int arg1);
|
||||||
@ -62,8 +61,6 @@ class PrefrencesWindow : public QDialog
|
|||||||
|
|
||||||
void on_localDNSCb_stateChanged(int arg1);
|
void on_localDNSCb_stateChanged(int arg1);
|
||||||
|
|
||||||
void on_selectVCoreBtn_clicked();
|
|
||||||
|
|
||||||
void on_selectVAssetBtn_clicked();
|
void on_selectVAssetBtn_clicked();
|
||||||
|
|
||||||
void on_DNSListTxt_textChanged();
|
void on_DNSListTxt_textChanged();
|
||||||
@ -74,6 +71,8 @@ class PrefrencesWindow : public QDialog
|
|||||||
|
|
||||||
void on_cancelIgnoreVersionBtn_clicked();
|
void on_cancelIgnoreVersionBtn_clicked();
|
||||||
|
|
||||||
|
void on_tProxyCheckBox_stateChanged(int arg1);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool IsConnectionPropertyChanged = false;
|
bool IsConnectionPropertyChanged = false;
|
||||||
bool finishedLoading = false;
|
bool finishedLoading = false;
|
||||||
|
@ -64,27 +64,13 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_7">
|
|
||||||
<property name="text">
|
|
||||||
<string>Run As Root</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QCheckBox" name="runAsRootCheckBox">
|
|
||||||
<property name="text">
|
|
||||||
<string>Enabled</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Log Level</string>
|
<string>Log Level</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QComboBox" name="logLevelComboBox">
|
<widget class="QComboBox" name="logLevelComboBox">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
@ -125,14 +111,14 @@
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="label_19">
|
<widget class="QLabel" name="label_19">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Automatically Connect To</string>
|
<string>Automatically Connect To</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QComboBox" name="autoStartCombo">
|
<widget class="QComboBox" name="autoStartCombo">
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -141,35 +127,28 @@
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="label_14">
|
<widget class="QLabel" name="label_7">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>v2ray Core Path</string>
|
<string>Transparent Proxy Support</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="3" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
<widget class="QCheckBox" name="tProxyCheckBox">
|
||||||
<item>
|
<property name="text">
|
||||||
<widget class="QLineEdit" name="vCoreExePathTxt"/>
|
<string>Enabled</string>
|
||||||
</item>
|
</property>
|
||||||
<item>
|
</widget>
|
||||||
<widget class="QPushButton" name="selectVCoreBtn">
|
|
||||||
<property name="text">
|
|
||||||
<string>#Select</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QLabel" name="label_15">
|
<widget class="QLabel" name="label_15">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>v2ray Assets Path</string>
|
<string>v2ray Assets Path</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1">
|
<item row="4" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="vCoreAssetsPathTxt"/>
|
<widget class="QLineEdit" name="vCoreAssetsPathTxt"/>
|
||||||
|
@ -69,7 +69,7 @@ void SubscribeEditor::ProcessSubscriptionEntry(QByteArray result, QString subsci
|
|||||||
auto vmessList = content.split("\n");
|
auto vmessList = content.split("\n");
|
||||||
|
|
||||||
for (auto vmess : vmessList) {
|
for (auto vmess : vmessList) {
|
||||||
auto config = ConvertConfigFromVMessString(vmess, QV2RAY_CONFIG_TYPE_SUBSCRIPTION);
|
auto config = ConvertConfigFromVMessString(vmess);
|
||||||
|
|
||||||
if (subscriptions.contains(subsciptionName)) {
|
if (subscriptions.contains(subsciptionName)) {
|
||||||
}
|
}
|
||||||
|
@ -211,14 +211,14 @@
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ConnectionEditWindow.cpp" line="398"/>
|
<location filename="../src/w_ConnectionEditWindow.cpp" line="397"/>
|
||||||
<location filename="../src/w_ConnectionEditWindow.cpp" line="409"/>
|
<location filename="../src/w_ConnectionEditWindow.cpp" line="408"/>
|
||||||
<source>#JsonPrettify</source>
|
<source>#JsonPrettify</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ConnectionEditWindow.cpp" line="398"/>
|
<location filename="../src/w_ConnectionEditWindow.cpp" line="397"/>
|
||||||
<location filename="../src/w_ConnectionEditWindow.cpp" line="409"/>
|
<location filename="../src/w_ConnectionEditWindow.cpp" line="408"/>
|
||||||
<source>#JsonContainsError</source>
|
<source>#JsonContainsError</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -293,33 +293,33 @@
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="36"/>
|
<location filename="../src/w_ImportConfig.cpp" line="36"/>
|
||||||
<source>OpenConfigFile</source>
|
<source>Select file to import</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="50"/>
|
<location filename="../src/w_ImportConfig.cpp" line="51"/>
|
||||||
<source>#InvalidConfigFile</source>
|
<source>Import config file</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="50"/>
|
<location filename="../src/w_ImportConfig.cpp" line="51"/>
|
||||||
<source>ConfigFileCheckFailed</source>
|
<source>Failed to check the validity of the config file.</source>
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="65"/>
|
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="69"/>
|
|
||||||
<source>#VMessCheck</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="65"/>
|
|
||||||
<source>#NotValidVMessProtocolString</source>
|
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="69"/>
|
<location filename="../src/w_ImportConfig.cpp" line="69"/>
|
||||||
<source>#INTERNAL_ERROR</source>
|
<location filename="../src/w_ImportConfig.cpp" line="74"/>
|
||||||
|
<source>VMess String Check</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/w_ImportConfig.cpp" line="69"/>
|
||||||
|
<source>VMess string is not valid</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/w_ImportConfig.cpp" line="74"/>
|
||||||
|
<source>Some internal error occured</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
@ -343,129 +343,129 @@
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="64"/>
|
<location filename="../src/w_MainWindow.ui" line="71"/>
|
||||||
<source>Clear Log</source>
|
<source>Clear Log</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="71"/>
|
<location filename="../src/w_MainWindow.ui" line="78"/>
|
||||||
<source>Prefrences</source>
|
<source>Prefrences</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="94"/>
|
<location filename="../src/w_MainWindow.ui" line="101"/>
|
||||||
<source>Stopped</source>
|
<source>Stopped</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="103"/>
|
<location filename="../src/w_MainWindow.ui" line="110"/>
|
||||||
<source>Host List</source>
|
<source>Host List</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="110"/>
|
<location filename="../src/w_MainWindow.ui" line="117"/>
|
||||||
<source>Config Details</source>
|
<source>Config Details</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="116"/>
|
<location filename="../src/w_MainWindow.ui" line="123"/>
|
||||||
<source>Type</source>
|
<source>Type</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="130"/>
|
<location filename="../src/w_MainWindow.ui" line="137"/>
|
||||||
<source>Host</source>
|
<source>Host</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="144"/>
|
<location filename="../src/w_MainWindow.ui" line="151"/>
|
||||||
<source>Port</source>
|
<source>Port</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="158"/>
|
<location filename="../src/w_MainWindow.ui" line="165"/>
|
||||||
<source>Detail</source>
|
<source>Detail</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="236"/>
|
<location filename="../src/w_MainWindow.ui" line="243"/>
|
||||||
<source>#AddConnection</source>
|
<source>#AddConnection</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="239"/>
|
<location filename="../src/w_MainWindow.ui" line="246"/>
|
||||||
<source>A</source>
|
<source>A</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="256"/>
|
<location filename="../src/w_MainWindow.ui" line="263"/>
|
||||||
<location filename="../src/w_MainWindow.ui" line="346"/>
|
<location filename="../src/w_MainWindow.ui" line="353"/>
|
||||||
<source>#ImportConnection</source>
|
<source>#ImportConnection</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="259"/>
|
<location filename="../src/w_MainWindow.ui" line="266"/>
|
||||||
<source>I</source>
|
<source>I</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="290"/>
|
<location filename="../src/w_MainWindow.ui" line="297"/>
|
||||||
<source>#RemoveConnection</source>
|
<source>#RemoveConnection</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="293"/>
|
<location filename="../src/w_MainWindow.ui" line="300"/>
|
||||||
<source>R</source>
|
<source>R</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="270"/>
|
<location filename="../src/w_MainWindow.ui" line="277"/>
|
||||||
<source>#EditConnection</source>
|
<source>#EditConnection</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="273"/>
|
<location filename="../src/w_MainWindow.ui" line="280"/>
|
||||||
<source>...</source>
|
<source>...</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="319"/>
|
<location filename="../src/w_MainWindow.ui" line="326"/>
|
||||||
<source>Log</source>
|
<source>Log</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="341"/>
|
<location filename="../src/w_MainWindow.ui" line="348"/>
|
||||||
<source>#ManuallyCreateConnection</source>
|
<source>#ManuallyCreateConnection</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="351"/>
|
<location filename="../src/w_MainWindow.ui" line="358"/>
|
||||||
<source>#Exit</source>
|
<source>#Exit</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="356"/>
|
<location filename="../src/w_MainWindow.ui" line="363"/>
|
||||||
<source>#Preferences</source>
|
<source>#Preferences</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="361"/>
|
<location filename="../src/w_MainWindow.ui" line="368"/>
|
||||||
<source>#Start</source>
|
<source>#Start</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="366"/>
|
<location filename="../src/w_MainWindow.ui" line="373"/>
|
||||||
<source>#Stop</source>
|
<source>#Stop</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.ui" line="371"/>
|
<location filename="../src/w_MainWindow.ui" line="378"/>
|
||||||
<source>#Restart</source>
|
<source>#Restart</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="38"/>
|
<location filename="../src/w_MainWindow.cpp" line="38"/>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="283"/>
|
<location filename="../src/w_MainWindow.cpp" line="289"/>
|
||||||
<source>Hide</source>
|
<source>Hide</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -475,6 +475,7 @@
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
<location filename="../src/w_MainWindow.ui" line="64"/>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="41"/>
|
<location filename="../src/w_MainWindow.cpp" line="41"/>
|
||||||
<source>Reconnect</source>
|
<source>Reconnect</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
@ -485,19 +486,35 @@
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="92"/>
|
<location filename="../src/w_MainWindow.cpp" line="91"/>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="238"/>
|
<location filename="../src/w_MainWindow.cpp" line="244"/>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="286"/>
|
<location filename="../src/w_MainWindow.cpp" line="292"/>
|
||||||
<source>Show</source>
|
<source>Show</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="495"/>
|
<location filename="../src/w_MainWindow.cpp" line="433"/>
|
||||||
|
<location filename="../src/w_MainWindow.cpp" line="442"/>
|
||||||
|
<source>Rename a Connection</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/w_MainWindow.cpp" line="433"/>
|
||||||
|
<source>The name cannot be empty</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/w_MainWindow.cpp" line="469"/>
|
||||||
|
<source>Removing this Connection</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/w_MainWindow.cpp" line="507"/>
|
||||||
<source>NoConfigSelected</source>
|
<source>NoConfigSelected</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="495"/>
|
<location filename="../src/w_MainWindow.cpp" line="507"/>
|
||||||
<source>PleaseSelectAConfig</source>
|
<source>PleaseSelectAConfig</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -507,99 +524,83 @@
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="120"/>
|
<location filename="../src/w_MainWindow.cpp" line="126"/>
|
||||||
<source>Update</source>
|
<source>Update</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="121"/>
|
<location filename="../src/w_MainWindow.cpp" line="127"/>
|
||||||
<source>Found a new version: </source>
|
<source>Found a new version: </source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="127"/>
|
<location filename="../src/w_MainWindow.cpp" line="133"/>
|
||||||
<source>Download Link: </source>
|
<source>Download Link: </source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="188"/>
|
<location filename="../src/w_MainWindow.cpp" line="194"/>
|
||||||
<source>No connection selected!</source>
|
<source>No connection selected!</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="188"/>
|
<location filename="../src/w_MainWindow.cpp" line="194"/>
|
||||||
<source>Please select a config from the list.</source>
|
<source>Please select a config from the list.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="199"/>
|
<location filename="../src/w_MainWindow.cpp" line="205"/>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="200"/>
|
<location filename="../src/w_MainWindow.cpp" line="206"/>
|
||||||
<source>Connected To Server: </source>
|
<source>Connected To Server: </source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="201"/>
|
<location filename="../src/w_MainWindow.cpp" line="207"/>
|
||||||
<source>Connected</source>
|
<source>Connected</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="218"/>
|
<location filename="../src/w_MainWindow.cpp" line="224"/>
|
||||||
<source>Disconnected</source>
|
<source>Disconnected</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="324"/>
|
<location filename="../src/w_MainWindow.cpp" line="327"/>
|
||||||
<source>UUID</source>
|
<source>UUID</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="326"/>
|
<location filename="../src/w_MainWindow.cpp" line="329"/>
|
||||||
<source>AlterID</source>
|
<source>AlterID</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="328"/>
|
<location filename="../src/w_MainWindow.cpp" line="331"/>
|
||||||
<source>Transport</source>
|
<source>Transport</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="335"/>
|
<location filename="../src/w_MainWindow.cpp" line="338"/>
|
||||||
<source>Email</source>
|
<source>Email</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="337"/>
|
<location filename="../src/w_MainWindow.cpp" line="340"/>
|
||||||
<source>Encryption</source>
|
<source>Encryption</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="344"/>
|
<location filename="../src/w_MainWindow.cpp" line="347"/>
|
||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="419"/>
|
<location filename="../src/w_MainWindow.cpp" line="442"/>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="428"/>
|
|
||||||
<source>Rename A Connection</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_MainWindow.cpp" line="419"/>
|
|
||||||
<source>A name cannot be empty</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_MainWindow.cpp" line="428"/>
|
|
||||||
<source>The name has been used already, Please choose another.</source>
|
<source>The name has been used already, Please choose another.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_MainWindow.cpp" line="455"/>
|
<location filename="../src/w_MainWindow.cpp" line="469"/>
|
||||||
<source>Removing A Connection</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_MainWindow.cpp" line="455"/>
|
|
||||||
<source>Are you sure to remove this connection?</source>
|
<source>Are you sure to remove this connection?</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -608,8 +609,10 @@
|
|||||||
<name>PrefrencesWindow</name>
|
<name>PrefrencesWindow</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="20"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="20"/>
|
||||||
<location filename="../src/w_PrefrencesWindow.cpp" line="108"/>
|
<location filename="../src/w_PrefrencesWindow.cpp" line="103"/>
|
||||||
<location filename="../src/w_PrefrencesWindow.cpp" line="180"/>
|
<location filename="../src/w_PrefrencesWindow.cpp" line="326"/>
|
||||||
|
<location filename="../src/w_PrefrencesWindow.cpp" line="336"/>
|
||||||
|
<location filename="../src/w_PrefrencesWindow.cpp" line="348"/>
|
||||||
<source>Prefrences</source>
|
<source>Prefrences</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -635,271 +638,296 @@
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="69"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="69"/>
|
||||||
<source>Run As Root</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="83"/>
|
|
||||||
<source>Log Level</source>
|
<source>Log Level</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="103"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="89"/>
|
||||||
<source>none</source>
|
<source>none</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="108"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="94"/>
|
||||||
<source>debug</source>
|
<source>debug</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="113"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="99"/>
|
||||||
<source>info</source>
|
<source>info</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="118"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="104"/>
|
||||||
<source>warning</source>
|
<source>warning</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="123"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="109"/>
|
||||||
<source>error</source>
|
<source>error</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="131"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="117"/>
|
||||||
<source>Automatically Connect To</source>
|
<source>Automatically Connect To</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="147"/>
|
|
||||||
<source>v2ray Core Path</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="159"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="159"/>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="180"/>
|
|
||||||
<source>#Select</source>
|
<source>#Select</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="168"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="147"/>
|
||||||
<source>v2ray Assets Path</source>
|
<source>v2ray Assets Path</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="190"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="169"/>
|
||||||
<source>Mux Settings</source>
|
<source>Mux Settings</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="76"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="140"/>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="196"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="175"/>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="203"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="182"/>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="259"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="238"/>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="287"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="266"/>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="326"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="305"/>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="360"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="339"/>
|
||||||
|
<location filename="../src/w_PrefrencesWindow.ui" line="400"/>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="421"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="421"/>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="442"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="428"/>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="449"/>
|
|
||||||
<source>Enabled</source>
|
<source>Enabled</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="210"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="133"/>
|
||||||
|
<source>Transparent Proxy Support</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/w_PrefrencesWindow.ui" line="189"/>
|
||||||
<source>Concurrency</source>
|
<source>Concurrency</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="231"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="210"/>
|
||||||
<source>InBound Settings</source>
|
<source>InBound Settings</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="239"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="218"/>
|
||||||
<source>Listen IP</source>
|
<source>Listen IP</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="253"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="232"/>
|
||||||
<source>SOCKS InBound Settings</source>
|
<source>SOCKS InBound Settings</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="266"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="245"/>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="333"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="312"/>
|
||||||
<source>Port</source>
|
<source>Port</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="280"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="259"/>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="353"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="332"/>
|
||||||
<source>Authentication</source>
|
<source>Authentication</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="294"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="273"/>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="367"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="346"/>
|
||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="304"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="283"/>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="377"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="356"/>
|
||||||
<source>Password</source>
|
<source>Password</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="317"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="296"/>
|
||||||
<source>HTTP InBound Settings</source>
|
<source>HTTP InBound Settings</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="406"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="385"/>
|
||||||
<source>Route Settings</source>
|
<source>Route Settings</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="414"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="393"/>
|
||||||
<source>Enable Proxy</source>
|
<source>Enable Proxy</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="428"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="407"/>
|
||||||
<source>Chinese Addresses</source>
|
<source>Chinese Addresses</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="435"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="414"/>
|
||||||
<source>Use Local DNS</source>
|
<source>Use Local DNS</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="461"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="440"/>
|
||||||
<source>DNS List</source>
|
<source>DNS List</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="475"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="454"/>
|
||||||
<source>About</source>
|
<source>About</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="523"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="502"/>
|
||||||
<source>Qv2ray</source>
|
<source>Qv2ray</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="545"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="524"/>
|
||||||
<source>Version:</source>
|
<source>Version:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="578"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="557"/>
|
||||||
<source>Official Repo:</source>
|
<source>Official Repo:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="596"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="575"/>
|
||||||
<source><html><head/><body><p><a href="https://github.com/lhy0403/Qv2ray"><span style=" text-decoration: underline; color:#2980b9;">https://github.com/lhy0403/Qv2ray</span></a></p></body></html></source>
|
<source><html><head/><body><p><a href="https://github.com/lhy0403/Qv2ray"><span style=" text-decoration: underline; color:#2980b9;">https://github.com/lhy0403/Qv2ray</span></a></p></body></html></source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="629"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="608"/>
|
||||||
<source>License:</source>
|
<source>License:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="647"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="626"/>
|
||||||
<source><html><head/><body><p><a href="https://www.gnu.org/licenses/gpl-3.0.txt"><span style=" text-decoration: underline; color:#2980b9;">GPLv3 (https://www.gnu.org/licenses/gpl-3.0.txt)</span></a></p></body></html></source>
|
<source><html><head/><body><p><a href="https://www.gnu.org/licenses/gpl-3.0.txt"><span style=" text-decoration: underline; color:#2980b9;">GPLv3 (https://www.gnu.org/licenses/gpl-3.0.txt)</span></a></p></body></html></source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="684"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="663"/>
|
||||||
<source>About Qt</source>
|
<source>About Qt</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="719"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="698"/>
|
||||||
<source>Ingore Next Version</source>
|
<source>Ingore Next Version</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.ui" line="726"/>
|
<location filename="../src/w_PrefrencesWindow.ui" line="705"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.cpp" line="108"/>
|
<location filename="../src/w_PrefrencesWindow.cpp" line="103"/>
|
||||||
<source>PortNumbersCannotBeSame</source>
|
<source>Port numbers cannot be the same</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.cpp" line="180"/>
|
<location filename="../src/w_PrefrencesWindow.cpp" line="257"/>
|
||||||
<source>RunAsRootNotOnWindows</source>
|
<source>Open v2ray assets folder</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.cpp" line="300"/>
|
<location filename="../src/w_PrefrencesWindow.cpp" line="315"/>
|
||||||
<source>#OpenVCoreFile</source>
|
<source>Enable tProxy Support</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_PrefrencesWindow.cpp" line="311"/>
|
<location filename="../src/w_PrefrencesWindow.cpp" line="315"/>
|
||||||
<source>OpenVAssetsDir</source>
|
<source>This will append capabilities to the v2ray executable.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/w_PrefrencesWindow.cpp" line="316"/>
|
||||||
|
<source>If anything goes wrong after enabling this, please refer to issue #57 or the link below:</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/w_PrefrencesWindow.cpp" line="326"/>
|
||||||
|
<location filename="../src/w_PrefrencesWindow.cpp" line="336"/>
|
||||||
|
<source>Failed to setcap onto v2ray executable. You may need to run `setcap` manually.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/w_PrefrencesWindow.cpp" line="348"/>
|
||||||
|
<source>tProxy is not supported on MacOS and Windows</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>QObject</name>
|
<name>QObject</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/QvCoreConfigOperations_Verification.cpp" line="22"/>
|
<location filename="../src/main.cpp" line="54"/>
|
||||||
<source>#VMessDecodeError</source>
|
<source>Qv2ray Cannot Continue</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/QvCoreInteractions.cpp" line="29"/>
|
<location filename="../src/main.cpp" line="54"/>
|
||||||
<source>ConfigurationError</source>
|
<source>You are running a lower version of Qv2ray compared to the current config file.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/QvCoreInteractions.cpp" line="53"/>
|
<location filename="../src/main.cpp" line="56"/>
|
||||||
<source>CoreNotFound</source>
|
<source>Please report if you think this is an error.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/QvCoreInteractions.cpp" line="53"/>
|
<location filename="../src/main.cpp" line="57"/>
|
||||||
<source>CoreFileNotFoundExplainationAt:</source>
|
<source>Qv2ray will now exit.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/main.cpp" line="166"/>
|
<location filename="../src/main.cpp" line="144"/>
|
||||||
<source>DependencyMissing</source>
|
<source>DependencyMissing</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/main.cpp" line="167"/>
|
<location filename="../src/main.cpp" line="145"/>
|
||||||
<source>Cannot find openssl libs</source>
|
<source>Cannot find openssl libs</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/main.cpp" line="168"/>
|
<location filename="../src/main.cpp" line="146"/>
|
||||||
<source>This could be caused by a missing of `openssl` package in your system. Or an AppImage issue.</source>
|
<source>This could be caused by a missing of `openssl` package in your system. Or an AppImage issue.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/main.cpp" line="169"/>
|
<location filename="../src/main.cpp" line="147"/>
|
||||||
<source>If you are using AppImage, please report a bug.</source>
|
<source>If you are using AppImage, please report a bug.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/main.cpp" line="177"/>
|
<location filename="../src/main.cpp" line="153"/>
|
||||||
<source>Another instance of Qv2ray is already running.</source>
|
<source>Another instance of Qv2ray is already running.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/QvCoreInteractions.cpp" line="29"/>
|
||||||
|
<source>Configuration Error</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/QvCoreInteractions.cpp" line="55"/>
|
||||||
|
<source>Cannot start v2ray</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/QvCoreInteractions.cpp" line="55"/>
|
||||||
|
<source>v2ray core file cannot be found at:</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>RouteEditor</name>
|
<name>RouteEditor</name>
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user