Fix lots of bugs

This commit is contained in:
Nova 2025-11-17 12:49:11 +03:30
parent fa25de7b74
commit 6bacd1c7a3
24 changed files with 175 additions and 96 deletions

View File

@ -274,8 +274,8 @@ set(PROJECT_SOURCES
src/configs/generate.cpp src/configs/generate.cpp
include/configs/common/utils.h include/configs/common/utils.h
src/configs/common/utils.cpp src/configs/common/utils.cpp
include/configs/outbounds/Custom.h include/configs/outbounds/custom.h
include/configs/outbounds/Chain.h include/configs/outbounds/chain.h
include/configs/outbounds/extracore.h include/configs/outbounds/extracore.h
) )

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include <QHostInfo>
#include "DialFields.h" #include "DialFields.h"
#include "multiplex.h" #include "multiplex.h"
#include "TLS.h" #include "TLS.h"
@ -13,6 +14,7 @@ namespace Configs
QString name; QString name;
QString server; QString server;
int server_port = 0; int server_port = 0;
bool invalid = false;
std::shared_ptr<DialFields> dialFields = std::make_shared<DialFields>(); std::shared_ptr<DialFields> dialFields = std::make_shared<DialFields>();
outbound() outbound()
@ -23,7 +25,19 @@ namespace Configs
_add(new configItem("dial_fields", dynamic_cast<JsonStore *>(dialFields.get()), jsonStore)); _add(new configItem("dial_fields", dynamic_cast<JsonStore *>(dialFields.get()), jsonStore));
} }
void ResolveDomainToIP(const std::function<void()> &onFinished); void ResolveDomainToIP(const std::function<void()> &onFinished) {
bool noResolve = false;
if (IsIpAddress(server) || server.isEmpty()) noResolve = true;
if (noResolve) {
onFinished();
return;
}
QHostInfo::lookupHost(server, QApplication::instance(), [=, this](const QHostInfo &host) {
auto addrs = host.addresses();
if (!addrs.isEmpty()) server = addrs.first().toString();
onFinished();
});
}
virtual QString GetAddress() virtual QString GetAddress()
{ {
@ -56,6 +70,8 @@ namespace Configs
virtual bool HasTLS() { return false; } virtual bool HasTLS() { return false; }
virtual bool MustTLS() { return false; }
virtual std::shared_ptr<TLS> GetTLS() { return std::make_shared<TLS>(); } virtual std::shared_ptr<TLS> GetTLS() { return std::make_shared<TLS>(); }
virtual std::shared_ptr<Transport> GetTransport() { return std::make_shared<Transport>(); } virtual std::shared_ptr<Transport> GetTransport() { return std::make_shared<Transport>(); }
@ -64,6 +80,17 @@ namespace Configs
virtual bool IsEndpoint() { return false; }; virtual bool IsEndpoint() { return false; };
QString ExportJsonLink() {
auto json = ExportToJson();
QUrl url;
url.setScheme("json");
url.setHost("throne");
url.setFragment(QJsonObject2QString(json, true)
.toUtf8()
.toBase64(QByteArray::Base64UrlEncoding));
return url.toString();
}
// baseConfig overrides // baseConfig overrides
bool ParseFromLink(const QString& link) override; bool ParseFromLink(const QString& link) override;
bool ParseFromJson(const QJsonObject& object) override; bool ParseFromJson(const QJsonObject& object) override;

View File

@ -58,7 +58,10 @@ namespace Configs
} }
void saveMuxState(int state) { void saveMuxState(int state) {
if (state == 1) enabled = true; if (state == 1) {
enabled = true;
return;
}
enabled = false; enabled = false;
if (state == 0) unspecified = true; if (state == 0) unspecified = true;
} }

View File

@ -26,6 +26,10 @@ namespace Configs
return true; return true;
} }
bool MustTLS() override {
return true;
}
std::shared_ptr<TLS> GetTLS() override { std::shared_ptr<TLS> GetTLS() override {
return tls; return tls;
} }

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "include/configs/common/Outbound.h" #include "include/configs/common/Outbound.h"
#include "QJsonArray"
namespace Configs namespace Configs
{ {
@ -17,6 +18,21 @@ namespace Configs
QString DisplayAddress() override { return ""; }; QString DisplayAddress() override { return ""; };
bool ParseFromJson(const QJsonObject &object) override {
if (object.isEmpty()) return false;
if (object.contains("name")) name = object["name"].toString();
if (object.contains("list")) list = QJsonArray2QListInt(object["list"].toArray());
return true;
}
QJsonObject ExportToJson() override {
QJsonObject object;
object["name"] = name;
object["type"] = "chain";
object["list"] = QListInt2QJsonArray(list);
return object;
}
BuildResult Build() override BuildResult Build() override
{ {
return {{}, "Cannot call Build on chain config"}; return {{}, "Cannot call Build on chain config"};

View File

@ -15,6 +15,23 @@ namespace Configs
_add(new configItem("type", &type, string)); _add(new configItem("type", &type, string));
} }
bool ParseFromJson(const QJsonObject &object) override {
if (object.isEmpty()) return false;
if (object.contains("name")) name = object["name"].toString();
if (object.contains("subtype")) type = object["subtype"].toString();
if (object.contains("config")) config = object["config"].toString();
return true;
}
QJsonObject ExportToJson() override {
QJsonObject object;
object["name"] = name;
object["type"] = "custom";
object["subtype"] = type;
object["config"] = config;
return object;
}
QString GetAddress() override QString GetAddress() override
{ {
if (type == "outbound") { if (type == "outbound") {

View File

@ -21,6 +21,31 @@ namespace Configs
_add(new configItem("no_logs", &noLogs, itemType::boolean)); _add(new configItem("no_logs", &noLogs, itemType::boolean));
}; };
bool ParseFromJson(const QJsonObject &object) override {
if (object.isEmpty()) return false;
if (object.contains("name")) name = object["name"].toString();
if (object.contains("socks_address")) socksAddress = object["socks_address"].toString();
if (object.contains("socks_port")) socksPort = object["socks_port"].toInt();
if (object.contains("extra_core_path")) extraCorePath = object["extra_core_path"].toString();
if (object.contains("extra_core_args")) extraCoreArgs = object["extra_core_args"].toString();
if (object.contains("extra_core_conf")) extraCoreConf = object["extra_core_conf"].toString();
if (object.contains("no_logs")) noLogs = object["no_logs"].toBool();
return true;
}
QJsonObject ExportToJson() override {
QJsonObject object;
object["name"] = name;
object["type"] = "extracore";
object["socks_address"] = socksAddress;
object["socks_port"] = socksPort;
object["extra_core_path"] = extraCorePath;
object["extra_core_args"] = extraCoreArgs;
object["extra_core_conf"] = extraCoreConf;
object["no_logs"] = noLogs;
return object;
}
QString DisplayType() override { return "ExtraCore"; }; QString DisplayType() override { return "ExtraCore"; };
BuildResult Build() override BuildResult Build() override

View File

@ -38,6 +38,10 @@ namespace Configs
return true; return true;
} }
bool MustTLS() override {
return true;
}
std::shared_ptr<TLS> GetTLS() override { std::shared_ptr<TLS> GetTLS() override {
return tls; return tls;
} }

View File

@ -32,6 +32,10 @@ namespace Configs
return true; return true;
} }
bool MustTLS() override {
return true;
}
std::shared_ptr<TLS> GetTLS() override { std::shared_ptr<TLS> GetTLS() override {
return tls; return tls;
} }

View File

@ -36,6 +36,10 @@ namespace Configs
return true; return true;
} }
bool MustTLS() override {
return true;
}
std::shared_ptr<TLS> GetTLS() override { std::shared_ptr<TLS> GetTLS() override {
return tls; return tls;
} }

View File

@ -878,7 +878,7 @@
</action> </action>
<action name="menu_copy_links_nkr"> <action name="menu_copy_links_nkr">
<property name="text"> <property name="text">
<string>Copy links of selected (Custom Links)</string> <string>Copy links of selected (Json Links)</string>
</property> </property>
<property name="shortcut"> <property name="shortcut">
<string notr="true">Ctrl+Alt+C</string> <string notr="true">Ctrl+Alt+C</string>

View File

@ -40,7 +40,11 @@ namespace Configs {
} }
BuildResult outbound::Build() BuildResult outbound::Build()
{ {
return {ExportToJson(), ""}; QJsonObject object;
if (!server.isEmpty()) object["server"] = server;
if (server_port > 0) object["server_port"] = server_port;
mergeJsonObjects(object, dialFields->Build().object);
return {object, ""};
} }
} }

View File

@ -152,7 +152,13 @@ namespace Configs {
if (!url.isValid()) return false; if (!url.isValid()) return false;
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded)); auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
if (query.hasQueryItem("security")) enabled = query.queryItemValue("security").replace("reality", "tls").replace("none", "") == "tls"; if (query.hasQueryItem("security")) enabled = query.queryItemValue("security")
.replace("reality", "tls")
.replace("none", "")
.replace("0", "")
.replace("false", "tls")
.replace("1", "tls")
.replace("true", "tls") == "tls";
if (query.hasQueryItem("disable_sni")) disable_sni = query.queryItemValue("disable_sni").replace("1", "true") == "true"; if (query.hasQueryItem("disable_sni")) disable_sni = query.queryItemValue("disable_sni").replace("1", "true") == "true";
if (query.hasQueryItem("sni")) server_name = query.queryItemValue("sni"); if (query.hasQueryItem("sni")) server_name = query.queryItemValue("sni");
if (query.hasQueryItem("peer")) server_name = query.queryItemValue("peer"); if (query.hasQueryItem("peer")) server_name = query.queryItemValue("peer");

View File

@ -67,7 +67,10 @@ namespace Configs {
if (query.hasQueryItem("type")) if (query.hasQueryItem("type"))
{ {
type = query.queryItemValue("type"); type = query.queryItemValue("type");
if ((type == "tcp" && query.queryItemValue("headerType") == "http") || type == "h2") type = "http"; if ((type == "tcp" && query.queryItemValue("headerType") == "http") || type == "h2") {
type = "http";
method = "GET";
}
} }
if (query.hasQueryItem("host")) host = query.queryItemValue("host"); if (query.hasQueryItem("host")) host = query.queryItemValue("host");
if (query.hasQueryItem("path")) path = query.queryItemValue("path"); if (query.hasQueryItem("path")) path = query.queryItemValue("path");

View File

@ -6,6 +6,7 @@
#include <QInputDialog> #include <QInputDialog>
#include <QUrlQuery> #include <QUrlQuery>
#include <QJsonDocument>
#include "3rdparty/fkYAML/node.hpp" #include "3rdparty/fkYAML/node.hpp"
@ -13,22 +14,6 @@ namespace Subscription {
GroupUpdater *groupUpdater = new GroupUpdater; GroupUpdater *groupUpdater = new GroupUpdater;
void RawUpdater_FixEnt(const std::shared_ptr<Configs::ProxyEntity> &ent) {
if (ent == nullptr) return;
auto stream = Configs::GetStreamSettings(ent->bean.get());
if (stream == nullptr) return;
// 1. "security"
if (stream->security == "none" || stream->security == "0" || stream->security == "false") {
stream->security = "";
} else if (stream->security == "1" || stream->security == "true") {
stream->security = "tls";
}
// 2. TLS SNI: v2rayN config builder generate sni like this, so set sni here for their format.
if (stream->security == "tls" && IsIpAddress(ent->bean->serverAddress) && (!stream->host.isEmpty()) && stream->sni.isEmpty()) {
stream->sni = stream->host;
}
}
int JsonEndIdx(const QString &str, int begin) { int JsonEndIdx(const QString &str, int begin) {
int sz = str.length(); int sz = str.length();
int counter = 1; int counter = 1;
@ -106,18 +91,18 @@ namespace Subscription {
} }
std::shared_ptr<Configs::ProxyEntity> ent; std::shared_ptr<Configs::ProxyEntity> ent;
bool needFix = true;
// Nekoray format // Json base64 link format
if (str.startsWith("nekoray://")) { if (str.startsWith("json://")) {
needFix = false;
auto link = QUrl(str); auto link = QUrl(str);
if (!link.isValid()) return; if (!link.isValid()) return;
ent = Configs::ProfileManager::NewProxyEntity(link.host()); auto dataBytes = DecodeB64IfValid(link.fragment().toUtf8(), QByteArray::Base64UrlEncoding);
if (ent->bean->version == -114514) return; if (dataBytes.isEmpty()) return;
auto j = DecodeB64IfValid(link.fragment().toUtf8(), QByteArray::Base64UrlEncoding); auto data = QJsonDocument::fromJson(dataBytes).object();
if (j.isEmpty()) return; if (data.isEmpty()) return;
ent->bean->FromJsonBytes(j); ent = Configs::ProfileManager::NewProxyEntity(data["type"].toString());
if (ent->outbound->invalid) return;
ent->outbound->ParseFromJson(data);
} }
// Json // Json
@ -188,7 +173,6 @@ namespace Subscription {
// Hysteria1 // Hysteria1
if (str.startsWith("hysteria://")) { if (str.startsWith("hysteria://")) {
needFix = false;
ent = Configs::ProfileManager::NewProxyEntity("hysteria"); ent = Configs::ProfileManager::NewProxyEntity("hysteria");
auto ok = ent->Hysteria()->ParseFromLink(str); auto ok = ent->Hysteria()->ParseFromLink(str);
if (!ok) return; if (!ok) return;
@ -196,7 +180,6 @@ namespace Subscription {
// Hysteria2 // Hysteria2
if (str.startsWith("hysteria2://") || str.startsWith("hy2://")) { if (str.startsWith("hysteria2://") || str.startsWith("hy2://")) {
needFix = false;
ent = Configs::ProfileManager::NewProxyEntity("hysteria2"); ent = Configs::ProfileManager::NewProxyEntity("hysteria2");
auto ok = ent->Hysteria2()->ParseFromLink(str); auto ok = ent->Hysteria2()->ParseFromLink(str);
if (!ok) return; if (!ok) return;
@ -204,7 +187,6 @@ namespace Subscription {
// TUIC // TUIC
if (str.startsWith("tuic://")) { if (str.startsWith("tuic://")) {
needFix = false;
ent = Configs::ProfileManager::NewProxyEntity("tuic"); ent = Configs::ProfileManager::NewProxyEntity("tuic");
auto ok = ent->TUIC()->ParseFromLink(str); auto ok = ent->TUIC()->ParseFromLink(str);
if (!ok) return; if (!ok) return;
@ -212,7 +194,6 @@ namespace Subscription {
// Wireguard // Wireguard
if (str.startsWith("wg://")) { if (str.startsWith("wg://")) {
needFix = false;
ent = Configs::ProfileManager::NewProxyEntity("wireguard"); ent = Configs::ProfileManager::NewProxyEntity("wireguard");
auto ok = ent->Wireguard()->ParseFromLink(str); auto ok = ent->Wireguard()->ParseFromLink(str);
if (!ok) return; if (!ok) return;
@ -220,7 +201,6 @@ namespace Subscription {
// SSH // SSH
if (str.startsWith("ssh://")) { if (str.startsWith("ssh://")) {
needFix = false;
ent = Configs::ProfileManager::NewProxyEntity("ssh"); ent = Configs::ProfileManager::NewProxyEntity("ssh");
auto ok = ent->SSH()->ParseFromLink(str); auto ok = ent->SSH()->ParseFromLink(str);
if (!ok) return; if (!ok) return;
@ -228,9 +208,6 @@ namespace Subscription {
if (ent == nullptr) return; if (ent == nullptr) return;
// Fix
if (needFix) RawUpdater_FixEnt(ent);
// End // End
updated_order += ent; updated_order += ent;
} }
@ -817,7 +794,7 @@ namespace Subscription {
continue; continue;
} }
if (needFix) RawUpdater_FixEnt(ent); // if (needFix) RawUpdater_FixEnt(ent); TODO
updated_order += ent; updated_order += ent;
} }
} catch (const fkyaml::exception &ex) { } catch (const fkyaml::exception &ex) {
@ -927,7 +904,7 @@ namespace Subscription {
if (Configs::dataStore->sub_clear) { if (Configs::dataStore->sub_clear) {
// all is new profile // all is new profile
for (const auto &ent: out_all) { for (const auto &ent: out_all) {
change_text += "[+] " + ent->bean->DisplayTypeAndName() + "\n"; change_text += "[+] " + ent->outbound->DisplayTypeAndName() + "\n";
} }
} else { } else {
// find and delete not updated profile by ProfileFilter // find and delete not updated profile by ProfileFilter
@ -940,7 +917,7 @@ namespace Subscription {
if (only_out.size() < 1000) if (only_out.size() < 1000)
{ {
for (const auto &ent: only_out) { for (const auto &ent: only_out) {
notice_added += "[+] " + ent->bean->DisplayTypeAndName() + "\n"; notice_added += "[+] " + ent->outbound->DisplayTypeAndName() + "\n";
} }
} else } else
{ {
@ -949,7 +926,7 @@ namespace Subscription {
if (only_in.size() < 1000) if (only_in.size() < 1000)
{ {
for (const auto &ent: only_in) { for (const auto &ent: only_in) {
notice_deleted += "[-] " + ent->bean->DisplayTypeAndName() + "\n"; notice_deleted += "[-] " + ent->outbound->DisplayTypeAndName() + "\n";
} }
} else } else
{ {

View File

@ -283,6 +283,7 @@ namespace Configs {
} else { } else {
bean = new Configs::AbstractBean(-114514); bean = new Configs::AbstractBean(-114514);
outbound = new Configs::outbound(); outbound = new Configs::outbound();
outbound->invalid = true;
} }
auto ent = std::make_shared<ProxyEntity>(outbound, bean, type); auto ent = std::make_shared<ProxyEntity>(outbound, bean, type);

View File

@ -191,7 +191,7 @@ namespace Configs {
MW_show_log("The outbound described in the rule chain is missing, maybe your data is corrupted"); MW_show_log("The outbound described in the rule chain is missing, maybe your data is corrupted");
return {}; return {};
} }
obj["outbound"] = prof->bean->DisplayName(); obj["outbound"] = prof->outbound->DisplayName();
} }
} else { } else {
if (!outboundTag.isEmpty()) obj["outbound"] = outboundTag; if (!outboundTag.isEmpty()) obj["outbound"] = outboundTag;
@ -511,7 +511,7 @@ namespace Configs {
if (name == "proxy") return -1; if (name == "proxy") return -1;
if (name == "direct") return -2; if (name == "direct") return -2;
for (const auto& item: profileManager->profiles) { for (const auto& item: profileManager->profiles) {
if (item.second->bean->name == name) return item.first; if (item.second->outbound->name == name) return item.first;
} }
return INVALID_ID; return INVALID_ID;

View File

@ -77,7 +77,7 @@ DialogEditGroup::DialogEditGroup(const std::shared_ptr<Configs::Group> &ent, QWi
QStringList links; QStringList links;
for (const auto &[_, profile]: Configs::profileManager->profiles) { for (const auto &[_, profile]: Configs::profileManager->profiles) {
if (profile->gid != ent->id) continue; if (profile->gid != ent->id) continue;
links += profile->bean->ToShareLink(); links += profile->outbound->ExportToLink();
} }
QApplication::clipboard()->setText(links.join("\n")); QApplication::clipboard()->setText(links.join("\n"));
MessageBoxInfo(software_name, tr("Copied")); MessageBoxInfo(software_name, tr("Copied"));
@ -86,7 +86,7 @@ DialogEditGroup::DialogEditGroup(const std::shared_ptr<Configs::Group> &ent, QWi
QStringList links; QStringList links;
for (const auto &[_, profile]: Configs::profileManager->profiles) { for (const auto &[_, profile]: Configs::profileManager->profiles) {
if (profile->gid != ent->id) continue; if (profile->gid != ent->id) continue;
links += profile->bean->ToNekorayShareLink(profile->type); links += profile->outbound->ExportToLink(); // TODO FIX neko link
} }
QApplication::clipboard()->setText(links.join("\n")); QApplication::clipboard()->setText(links.join("\n"));
MessageBoxInfo(software_name, tr("Copied")); MessageBoxInfo(software_name, tr("Copied"));
@ -122,7 +122,7 @@ QStringList DialogEditGroup::load_proxy_items() {
QStringList res = QStringList(); QStringList res = QStringList();
auto profiles = Configs::profileManager->profiles; auto profiles = Configs::profileManager->profiles;
for (const auto &item: profiles) { for (const auto &item: profiles) {
res.push_back(item.second->bean->DisplayName()); res.push_back(item.second->outbound->DisplayName());
} }
return res; return res;
@ -131,7 +131,7 @@ QStringList DialogEditGroup::load_proxy_items() {
int DialogEditGroup::get_proxy_id(QString name) { int DialogEditGroup::get_proxy_id(QString name) {
auto profiles = Configs::profileManager->profiles; auto profiles = Configs::profileManager->profiles;
for (const auto &item: profiles) { for (const auto &item: profiles) {
if (item.second->bean->DisplayName() == name) return item.first; if (item.second->outbound->DisplayName() == name) return item.first;
} }
return -1; return -1;
@ -139,5 +139,5 @@ int DialogEditGroup::get_proxy_id(QString name) {
QString DialogEditGroup::get_proxy_name(int id) { QString DialogEditGroup::get_proxy_name(int id) {
auto profiles = Configs::profileManager->profiles; auto profiles = Configs::profileManager->profiles;
return profiles.count(id) == 0 ? "None" : profiles[id]->bean->DisplayName(); return profiles.count(id) == 0 ? "None" : profiles[id]->outbound->DisplayName();
} }

View File

@ -1678,7 +1678,6 @@ void MainWindow::on_menu_add_from_clipboard_triggered() {
Subscription::groupUpdater->AsyncUpdate(clipboard); Subscription::groupUpdater->AsyncUpdate(clipboard);
} }
// TODO fix full export
void MainWindow::on_menu_clone_triggered() { void MainWindow::on_menu_clone_triggered() {
auto ents = get_now_selected_list(); auto ents = get_now_selected_list();
if (ents.isEmpty()) return; if (ents.isEmpty()) return;
@ -1688,7 +1687,7 @@ void MainWindow::on_menu_clone_triggered() {
QStringList sls; QStringList sls;
for (const auto &ent: ents) { for (const auto &ent: ents) {
sls << ent->outbound->ExportToLink(); sls << ent->outbound->ExportJsonLink();
} }
Subscription::groupUpdater->AsyncUpdate(sls.join("\n")); Subscription::groupUpdater->AsyncUpdate(sls.join("\n"));
@ -1765,7 +1764,7 @@ void MainWindow::on_menu_copy_links_nkr_triggered() {
auto ents = get_now_selected_list(); auto ents = get_now_selected_list();
QStringList links; QStringList links;
for (const auto &ent: ents) { for (const auto &ent: ents) {
links += ent->outbound->ExportToLink(); links += ent->outbound->ExportJsonLink();
} }
if (links.length() == 0) return; if (links.length() == 0) return;
QApplication::clipboard()->setText(links.join("\n")); QApplication::clipboard()->setText(links.join("\n"));

View File

@ -83,7 +83,7 @@ void MainWindow::runURLTest(const QString& config, bool useDefault, const QStrin
QString::fromStdString(res.error.value()).contains("context canceled")) ent->latency=0; QString::fromStdString(res.error.value()).contains("context canceled")) ent->latency=0;
else { else {
ent->latency = -1; ent->latency = -1;
MW_show_log(tr("[%1] test error: %2").arg(ent->bean->DisplayTypeAndName(), QString::fromStdString(res.error.value()))); MW_show_log(tr("[%1] test error: %2").arg(ent->outbound->DisplayTypeAndName(), QString::fromStdString(res.error.value())));
} }
} }
ent->Save(); ent->Save();
@ -127,7 +127,7 @@ void MainWindow::runURLTest(const QString& config, bool useDefault, const QStrin
QString::fromStdString(res.error.value()).contains("context canceled")) ent->latency=0; QString::fromStdString(res.error.value()).contains("context canceled")) ent->latency=0;
else { else {
ent->latency = -1; ent->latency = -1;
MW_show_log(tr("[%1] test error: %2").arg(ent->bean->DisplayTypeAndName(), QString::fromStdString(res.error.value()))); MW_show_log(tr("[%1] test error: %2").arg(ent->outbound->DisplayTypeAndName(), QString::fromStdString(res.error.value())));
} }
} }
ent->Save(); ent->Save();
@ -285,7 +285,7 @@ void MainWindow::querySpeedtest(QDateTime lastProxyListUpdate, const QMap<QStrin
runOnUiThread([=, this, &lastProxyListUpdate] runOnUiThread([=, this, &lastProxyListUpdate]
{ {
showSpeedtestData = true; showSpeedtestData = true;
currentSptProfileName = profile->bean->name; currentSptProfileName = profile->outbound->name;
currentTestResult = res.result.value(); currentTestResult = res.result.value();
UpdateDataView(); UpdateDataView();
@ -414,7 +414,7 @@ void MainWindow::runSpeedTest(const QString& config, bool useDefault, bool testC
ent->ul_speed = "N/A"; ent->ul_speed = "N/A";
ent->latency = -1; ent->latency = -1;
ent->test_country = ""; ent->test_country = "";
MW_show_log(tr("[%1] speed test error: %2").arg(ent->bean->DisplayTypeAndName(), QString::fromStdString(res.error.value()))); MW_show_log(tr("[%1] speed test error: %2").arg(ent->outbound->DisplayTypeAndName(), QString::fromStdString(res.error.value())));
} }
ent->Save(); ent->Save();
} }
@ -578,9 +578,9 @@ void MainWindow::profile_start(int _id) {
}, true); }, true);
} }
// do start // do start
MW_show_log(">>>>>>>> " + tr("Starting profile %1").arg(ent->bean->DisplayTypeAndName())); MW_show_log(">>>>>>>> " + tr("Starting profile %1").arg(ent->outbound->DisplayTypeAndName()));
if (!profile_start_stage2()) { if (!profile_start_stage2()) {
MW_show_log("<<<<<<<< " + tr("Failed to start profile %1").arg(ent->bean->DisplayTypeAndName())); MW_show_log("<<<<<<<< " + tr("Failed to start profile %1").arg(ent->outbound->DisplayTypeAndName()));
} }
mu_starting.unlock(); mu_starting.unlock();
// cancel timeout // cancel timeout
@ -664,7 +664,7 @@ void MainWindow::profile_stop(bool crash, bool block, bool manual) {
runOnNewThread([=, this, &blocker] { runOnNewThread([=, this, &blocker] {
// do stop // do stop
MW_show_log(">>>>>>>> " + tr("Stopping profile %1").arg(running->bean->DisplayTypeAndName())); MW_show_log(">>>>>>>> " + tr("Stopping profile %1").arg(running->outbound->DisplayTypeAndName()));
if (!profile_stop_stage2()) { if (!profile_stop_stage2()) {
MW_show_log("<<<<<<<< " + tr("Failed to stop, please restart the program.")); MW_show_log("<<<<<<<< " + tr("Failed to stop, please restart the program."));
} }

View File

@ -19,9 +19,9 @@ ProxyItem::~ProxyItem() {
} }
void ProxyItem::refresh_data() { void ProxyItem::refresh_data() {
ui->type->setText(ent->bean->DisplayType()); ui->type->setText(ent->outbound->DisplayType());
ui->name->setText(ent->bean->DisplayName()); ui->name->setText(ent->outbound->DisplayName());
ui->address->setText(ent->bean->DisplayAddress()); ui->address->setText(ent->outbound->DisplayAddress());
ui->traffic->setText(ent->traffic_data->DisplayTraffic()); ui->traffic->setText(ent->traffic_data->DisplayTraffic());
ui->test_result->setText(ent->DisplayTestResult()); ui->test_result->setText(ent->DisplayTestResult());
@ -36,7 +36,7 @@ void ProxyItem::refresh_data() {
void ProxyItem::on_remove_clicked() { void ProxyItem::on_remove_clicked() {
if (!this->remove_confirm || if (!this->remove_confirm ||
QMessageBox::question(this, tr("Confirmation"), tr("Remove %1?").arg(ent->bean->DisplayName())) == QMessageBox::StandardButton::Yes) { QMessageBox::question(this, tr("Confirmation"), tr("Remove %1?").arg(ent->outbound->DisplayName())) == QMessageBox::StandardButton::Yes) {
// TODO do remove (or not) -> callback // TODO do remove (or not) -> callback
delete item; delete item;
} }

View File

@ -39,20 +39,7 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
network_title_base = ui->network_box->title(); network_title_base = ui->network_box->title();
connect(ui->network, &QComboBox::currentTextChanged, this, [=,this](const QString &txt) { connect(ui->network, &QComboBox::currentTextChanged, this, [=,this](const QString &txt) {
ui->network_box->setTitle(network_title_base.arg(txt)); ui->network_box->setTitle(network_title_base.arg(txt));
if (txt == "tcp") { if (txt == "grpc") {
ui->header_type->setVisible(true);
ui->header_type_l->setVisible(true);
ui->headers->setVisible(false);
ui->headers_l->setVisible(false);
ui->method->setVisible(false);
ui->method_l->setVisible(false);
ui->path->setVisible(true);
ui->path_l->setVisible(true);
ui->host->setVisible(true);
ui->host_l->setVisible(true);
} else if (txt == "grpc") {
ui->header_type->setVisible(false);
ui->header_type_l->setVisible(false);
ui->headers->setVisible(false); ui->headers->setVisible(false);
ui->headers_l->setVisible(false); ui->headers_l->setVisible(false);
ui->method->setVisible(false); ui->method->setVisible(false);
@ -62,8 +49,6 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
ui->host->setVisible(false); ui->host->setVisible(false);
ui->host_l->setVisible(false); ui->host_l->setVisible(false);
} else if (txt == "ws" || txt == "httpupgrade") { } else if (txt == "ws" || txt == "httpupgrade") {
ui->header_type->setVisible(false);
ui->header_type_l->setVisible(false);
ui->headers->setVisible(true); ui->headers->setVisible(true);
ui->headers_l->setVisible(true); ui->headers_l->setVisible(true);
ui->method->setVisible(false); ui->method->setVisible(false);
@ -73,8 +58,6 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
ui->host->setVisible(true); ui->host->setVisible(true);
ui->host_l->setVisible(true); ui->host_l->setVisible(true);
} else if (txt == "http") { } else if (txt == "http") {
ui->header_type->setVisible(false);
ui->header_type_l->setVisible(false);
ui->headers->setVisible(true); ui->headers->setVisible(true);
ui->headers_l->setVisible(true); ui->headers_l->setVisible(true);
ui->method->setVisible(true); ui->method->setVisible(true);
@ -84,8 +67,6 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
ui->host->setVisible(true); ui->host->setVisible(true);
ui->host_l->setVisible(true); ui->host_l->setVisible(true);
} else { } else {
ui->header_type->setVisible(false);
ui->header_type_l->setVisible(false);
ui->headers->setVisible(false); ui->headers->setVisible(false);
ui->headers_l->setVisible(false); ui->headers_l->setVisible(false);
ui->method->setVisible(false); ui->method->setVisible(false);
@ -164,8 +145,8 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
LOAD_TYPE("wireguard") LOAD_TYPE("wireguard")
LOAD_TYPE("tailscale") LOAD_TYPE("tailscale")
LOAD_TYPE("ssh") LOAD_TYPE("ssh")
ui->type->addItem(tr("Custom (%1 outbound)").arg(software_core_name), "internal"); ui->type->addItem(tr("Custom (%1 outbound)").arg(software_core_name), "outbound");
ui->type->addItem(tr("Custom (%1 config)").arg(software_core_name), "internal-full"); ui->type->addItem(tr("Custom (%1 config)").arg(software_core_name), "fullconfig");
ui->type->addItem(tr("Extra Core"), "extracore"); ui->type->addItem(tr("Extra Core"), "extracore");
LOAD_TYPE("chain") LOAD_TYPE("chain")
@ -259,7 +240,7 @@ void DialogEditProfile::typeSelected(const QString &newType) {
auto _innerWidget = new EditSSH(this); auto _innerWidget = new EditSSH(this);
innerWidget = _innerWidget; innerWidget = _innerWidget;
innerEditor = _innerWidget; innerEditor = _innerWidget;
} else if (type == "internal" || type == "internal-full" || type == "custom") { } else if (type == "outbound" || type == "fullconfig" || type == "custom") {
auto _innerWidget = new EditCustom(this); auto _innerWidget = new EditCustom(this);
innerWidget = _innerWidget; innerWidget = _innerWidget;
innerEditor = _innerWidget; innerEditor = _innerWidget;
@ -286,7 +267,7 @@ void DialogEditProfile::typeSelected(const QString &newType) {
} }
// hide some widget // hide some widget
auto showAddressPort = type != "chain" && customType != "internal" && customType != "internal-full" && type != "extracore" && type != "tailscale"; auto showAddressPort = type != "chain" && customType != "outbound" && customType != "fullconfig" && type != "extracore" && type != "tailscale";
ui->address->setVisible(showAddressPort); ui->address->setVisible(showAddressPort);
ui->address_l->setVisible(showAddressPort); ui->address_l->setVisible(showAddressPort);
ui->port->setVisible(showAddressPort); ui->port->setVisible(showAddressPort);
@ -296,8 +277,13 @@ void DialogEditProfile::typeSelected(const QString &newType) {
ui->right_all_w->setVisible(true); ui->right_all_w->setVisible(true);
auto tls = ent->outbound->GetTLS(); auto tls = ent->outbound->GetTLS();
auto transport = ent->outbound->GetTransport(); auto transport = ent->outbound->GetTransport();
if (ent->outbound->MustTLS()) {
ui->security->setCurrentText("tls");
ui->security->setEnabled(false);
} else {
ui->security->setCurrentText(tls->enabled ? "tls" : "");
}
ui->network->setCurrentText(transport->type); ui->network->setCurrentText(transport->type);
ui->security->setCurrentText(tls->enabled ? "tls" : "");
ui->path->setText(transport->path); ui->path->setText(transport->path);
ui->host->setText(transport->host); ui->host->setText(transport->host);
ui->method->setText(transport->method); ui->method->setText(transport->method);
@ -357,11 +343,9 @@ void DialogEditProfile::typeSelected(const QString &newType) {
if (ent->outbound->HasTransport()) { if (ent->outbound->HasTransport()) {
ui->network_l->setVisible(true); ui->network_l->setVisible(true);
ui->network->setVisible(true); ui->network->setVisible(true);
ui->network_box->setVisible(true);
} else { } else {
ui->network_l->setVisible(false); ui->network_l->setVisible(false);
ui->network->setVisible(false); ui->network->setVisible(false);
ui->network_box->setVisible(false);
} }
if (ent->outbound->HasTLS()) { if (ent->outbound->HasTLS()) {
ui->security->setVisible(true); ui->security->setVisible(true);
@ -385,7 +369,7 @@ void DialogEditProfile::typeSelected(const QString &newType) {
} }
ui->stream_box->setVisible(streamBoxVisible); ui->stream_box->setVisible(streamBoxVisible);
auto rightNoBox = (ui->stream_box->isHidden() && ui->network_box->isHidden() && ui->security_box->isHidden()); auto rightNoBox = (ui->security_box->isHidden() && ui->network_box->isHidden() && ui->tls_camouflage_box->isHidden());
if (rightNoBox && !ui->right_all_w->isHidden()) { if (rightNoBox && !ui->right_all_w->isHidden()) {
ui->right_all_w->setVisible(false); ui->right_all_w->setVisible(false);
} }

View File

@ -3,6 +3,7 @@
EditTrojan::EditTrojan(QWidget *parent) EditTrojan::EditTrojan(QWidget *parent)
: QWidget(parent), : QWidget(parent),
ui(new Ui::EditTrojan) { ui(new Ui::EditTrojan) {
ui->setupUi(this);
} }
EditTrojan::~EditTrojan() { EditTrojan::~EditTrojan() {

View File

@ -33,7 +33,7 @@ QString get_outbound_name(int id) {
if (id == -1) return "proxy"; if (id == -1) return "proxy";
if (id == -2) return "direct"; if (id == -2) return "direct";
auto profiles = Configs::profileManager->profiles; auto profiles = Configs::profileManager->profiles;
if (profiles.count(id)) return profiles[id]->bean->name; if (profiles.count(id)) return profiles[id]->outbound->name;
return "INVALID OUTBOUND"; return "INVALID OUTBOUND";
} }
@ -41,7 +41,7 @@ QStringList get_all_outbounds() {
QStringList res; QStringList res;
auto profiles = Configs::profileManager->profiles; auto profiles = Configs::profileManager->profiles;
for (const auto &item: profiles) { for (const auto &item: profiles) {
res.append(item.second->bean->DisplayName()); res.append(item.second->outbound->DisplayName());
} }
return res; return res;