Migrate ui to outbounds

This commit is contained in:
Nova 2025-11-16 12:29:57 +03:30
parent 45d9c5a875
commit fa25de7b74
85 changed files with 1650 additions and 1602 deletions

View File

@ -130,18 +130,15 @@ set(PROJECT_SOURCES
include/ui/profile/edit_chain.h
src/ui/profile/edit_chain.cpp
include/ui/profile/edit_chain.ui
include/ui/profile/edit_socks_http.h
src/ui/profile/edit_socks_http.cpp
include/ui/profile/edit_socks_http.ui
include/ui/profile/edit_shadowsocks.h
src/ui/profile/edit_shadowsocks.cpp
include/ui/profile/edit_shadowsocks.ui
include/ui/profile/edit_vmess.h
src/ui/profile/edit_vmess.cpp
include/ui/profile/edit_vmess.ui
include/ui/profile/edit_trojan_vless.h
src/ui/profile/edit_trojan_vless.cpp
include/ui/profile/edit_trojan_vless.ui
include/ui/profile/edit_vless.h
src/ui/profile/edit_vless.cpp
include/ui/profile/edit_vless.ui
include/ui/profile/edit_anytls.h
src/ui/profile/edit_anytls.cpp
include/ui/profile/edit_anytls.ui
@ -149,10 +146,24 @@ set(PROJECT_SOURCES
src/ui/profile/edit_tailscale.cpp
include/ui/profile/edit_tailscale.ui
include/configs/proxy/Tailscale.hpp
include/ui/profile/edit_quic.h
src/ui/profile/edit_quic.cpp
include/ui/profile/edit_quic.ui
include/ui/profile/edit_trojan.h
src/ui/profile/edit_trojan.cpp
include/ui/profile/edit_trojan.ui
include/ui/profile/edit_http.h
src/ui/profile/edit_http.cpp
include/ui/profile/edit_http.ui
include/ui/profile/edit_socks.h
src/ui/profile/edit_socks.cpp
include/ui/profile/edit_socks.ui
include/ui/profile/edit_hysteria.h
src/ui/profile/edit_hysteria.cpp
include/ui/profile/edit_hysteria.ui
include/ui/profile/edit_hysteria2.h
src/ui/profile/edit_hysteria2.cpp
include/ui/profile/edit_hysteria2.ui
include/ui/profile/edit_tuic.h
src/ui/profile/edit_tuic.cpp
include/ui/profile/edit_tuic.ui
include/ui/profile/edit_custom.h
src/ui/profile/edit_custom.cpp
@ -279,6 +290,12 @@ endif ()
qt_add_executable(Throne
MANUAL_FINALIZATION
${PROJECT_SOURCES}
include/ui/profile/edit_socks.h src/ui/profile/edit_socks.cpp include/ui/profile/edit_socks.ui
include/ui/profile/edit_http.h src/ui/profile/edit_http.cpp include/ui/profile/edit_http.ui
include/ui/profile/edit_trojan.h src/ui/profile/edit_trojan.cpp include/ui/profile/edit_trojan.ui
include/ui/profile/edit_hysteria.h src/ui/profile/edit_hysteria.cpp include/ui/profile/edit_hysteria.ui
include/ui/profile/edit_tuic.h src/ui/profile/edit_tuic.cpp include/ui/profile/edit_tuic.ui
include/ui/profile/edit_hysteria2.h src/ui/profile/edit_hysteria2.cpp include/ui/profile/edit_hysteria2.ui
)
# Target

View File

@ -1,18 +1,21 @@
#pragma once
#include "DialFields.h"
#include "multiplex.h"
#include "TLS.h"
#include "transport.h"
#include "include/configs/baseConfig.h"
namespace Configs
{
class OutboundCommons : public baseConfig
class outbound : public baseConfig
{
public:
public:
QString name;
QString server;
int server_port = 0;
std::shared_ptr<DialFields> dialFields = std::make_shared<DialFields>();
OutboundCommons()
outbound()
{
_add(new configItem("name", &name, string));
_add(new configItem("server", &server, string));
@ -20,37 +23,24 @@ namespace Configs
_add(new configItem("dial_fields", dynamic_cast<JsonStore *>(dialFields.get()), jsonStore));
}
// baseConfig overrides
bool ParseFromLink(const QString& link) override;
bool ParseFromJson(const QJsonObject& object) override;
QString ExportToLink() override;
QJsonObject ExportToJson() override;
BuildResult Build() override;
};
class outbound : public baseConfig
{
public:
std::shared_ptr<OutboundCommons> commons = std::make_shared<OutboundCommons>();
void ResolveDomainToIP(const std::function<void()> &onFinished);
virtual QString GetAddress()
{
return commons->server;
return server;
}
virtual QString DisplayAddress()
{
return ::DisplayAddress(commons->server, commons->server_port);
return ::DisplayAddress(server, server_port);
}
virtual QString DisplayName()
{
if (commons->name.isEmpty()) {
if (name.isEmpty()) {
return DisplayAddress();
}
return commons->name;
return name;
}
virtual QString DisplayType() { return {}; };
@ -60,6 +50,25 @@ namespace Configs
return QString("[%1] %2").arg(DisplayType(), DisplayName());
}
virtual bool HasMux() { return false; }
virtual bool HasTransport() { return false; }
virtual bool HasTLS() { return false; }
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<Multiplex> GetMux() { return std::make_shared<Multiplex>(); }
virtual bool IsEndpoint() { return false; };
// baseConfig overrides
bool ParseFromLink(const QString& link) override;
bool ParseFromJson(const QJsonObject& object) override;
QString ExportToLink() override;
QJsonObject ExportToJson() override;
BuildResult Build() override;
};
}

View File

@ -51,6 +51,18 @@ namespace Configs
_add(new configItem("brutal", dynamic_cast<JsonStore *>(brutal.get()), jsonStore));
}
int getMuxState() {
if (enabled) return 1;
if (!unspecified) return 2;
return 0;
}
void saveMuxState(int state) {
if (state == 1) enabled = true;
enabled = false;
if (state == 0) unspecified = true;
}
// baseConfig overrides
bool ParseFromLink(const QString& link) override;
bool ParseFromJson(const QJsonObject& object) override;

View File

@ -37,6 +37,10 @@ namespace Configs
_add(new configItem("service_name", &service_name, string));
}
QString getHeadersString();
static QStringList getHeaderPairs(QString rawHeader);
// baseConfig overrides
bool ParseFromLink(const QString& link) override;
bool ParseFromJson(const QJsonObject& object) override;

View File

@ -15,7 +15,6 @@ namespace Configs
anyTLS() : outbound()
{
_add(new configItem("commons", dynamic_cast<JsonStore *>(commons.get()), jsonStore));
_add(new configItem("password", &password, string));
_add(new configItem("idle_session_check_interval", &idle_session_check_interval, string));
_add(new configItem("idle_session_timeout", &idle_session_timeout, string));
@ -23,6 +22,14 @@ namespace Configs
_add(new configItem("tls", dynamic_cast<JsonStore *>(tls.get()), jsonStore));
}
bool HasTLS() override {
return true;
}
std::shared_ptr<TLS> GetTLS() override {
return tls;
}
// baseConfig overrides
bool ParseFromLink(const QString& link) override;
bool ParseFromJson(const QJsonObject& object) override;

View File

@ -10,7 +10,6 @@ namespace Configs
chain() : outbound()
{
_add(new configItem("commons", dynamic_cast<JsonStore *>(commons.get()), jsonStore));
_add(new configItem("list", &list, integerList));
}

View File

@ -11,7 +11,6 @@ namespace Configs
Custom() : outbound()
{
_add(new configItem("commons", dynamic_cast<JsonStore *>(commons.get()), jsonStore));
_add(new configItem("config", &config, string));
_add(new configItem("type", &type, string));
}

View File

@ -13,7 +13,6 @@ namespace Configs
bool noLogs = false;
extracore() : outbound() {
_add(new configItem("commons", dynamic_cast<JsonStore *>(commons.get()), jsonStore));
_add(new configItem("socks_address", &socksAddress, itemType::string));
_add(new configItem("socks_port", &socksPort, itemType::integer));
_add(new configItem("extra_core_path", &extraCorePath, itemType::string));

View File

@ -16,7 +16,6 @@ namespace Configs
http() : outbound()
{
_add(new configItem("commons", dynamic_cast<JsonStore *>(commons.get()), jsonStore));
_add(new configItem("username", &username, string));
_add(new configItem("password", &password, string));
_add(new configItem("path", &path, string));
@ -24,6 +23,14 @@ namespace Configs
_add(new configItem("tls", dynamic_cast<JsonStore *>(tls.get()), jsonStore));
}
bool HasTLS() override {
return true;
}
std::shared_ptr<TLS> GetTLS() override {
return tls;
}
// baseConfig overrides
bool ParseFromLink(const QString& link) override;
bool ParseFromJson(const QJsonObject& object) override;

View File

@ -21,7 +21,6 @@ namespace Configs
hysteria() : outbound()
{
_add(new configItem("commons", dynamic_cast<JsonStore *>(commons.get()), jsonStore));
_add(new configItem("server_ports", &server_ports, stringList));
_add(new configItem("hop_interval", &hop_interval, string));
_add(new configItem("up_mbps", &up_mbps, integer));
@ -35,6 +34,14 @@ namespace Configs
_add(new configItem("tls", dynamic_cast<JsonStore *>(tls.get()), jsonStore));
}
bool HasTLS() override {
return true;
}
std::shared_ptr<TLS> GetTLS() override {
return tls;
}
// baseConfig overrides
bool ParseFromLink(const QString& link) override;
bool ParseFromJson(const QJsonObject& object) override;

View File

@ -18,7 +18,6 @@ namespace Configs
hysteria2() : outbound()
{
_add(new configItem("commons", dynamic_cast<JsonStore *>(commons.get()), jsonStore));
_add(new configItem("server_ports", &server_ports, stringList));
_add(new configItem("hop_interval", &hop_interval, string));
_add(new configItem("up_mbps", &up_mbps, integer));
@ -29,6 +28,14 @@ namespace Configs
_add(new configItem("tls", dynamic_cast<JsonStore *>(tls.get()), jsonStore));
}
bool HasTLS() override {
return true;
}
std::shared_ptr<TLS> GetTLS() override {
return tls;
}
// baseConfig overrides
bool ParseFromLink(const QString& link) override;
bool ParseFromJson(const QJsonObject& object) override;

View File

@ -19,7 +19,6 @@ namespace Configs
shadowsocks() : outbound()
{
_add(new configItem("commons", dynamic_cast<JsonStore *>(commons.get()), jsonStore));
_add(new configItem("method", &method, string));
_add(new configItem("password", &password, string));
_add(new configItem("plugin", &plugin, string));
@ -28,6 +27,14 @@ namespace Configs
_add(new configItem("multiplex", dynamic_cast<JsonStore *>(multiplex.get()), jsonStore));
}
bool HasMux() override {
return true;
}
std::shared_ptr<Multiplex> GetMux() override {
return multiplex;
}
// baseConfig overrides
bool ParseFromLink(const QString& link) override;
bool ParseFromJson(const QJsonObject& object) override;

View File

@ -14,7 +14,6 @@ namespace Configs
socks() : outbound()
{
_add(new configItem("commons", dynamic_cast<JsonStore *>(commons.get()), jsonStore));
_add(new configItem("username", &username, string));
_add(new configItem("password", &password, string));
_add(new configItem("version", &version, integer));

View File

@ -17,7 +17,6 @@ namespace Configs
ssh() : outbound()
{
_add(new configItem("commons", dynamic_cast<JsonStore *>(commons.get()), jsonStore));
_add(new configItem("user", &user, string));
_add(new configItem("password", &password, string));
_add(new configItem("private_key", &private_key, string));

View File

@ -20,7 +20,6 @@ namespace Configs
tailscale() : outbound()
{
_add(new configItem("commons", dynamic_cast<JsonStore *>(commons.get()), jsonStore));
_add(new configItem("state_directory", &state_directory, itemType::string));
_add(new configItem("auth_key", &auth_key, itemType::string));
_add(new configItem("control_url", &control_url, itemType::string));

View File

@ -16,13 +16,36 @@ namespace Configs
Trojan() : outbound()
{
_add(new configItem("commons", dynamic_cast<JsonStore *>(commons.get()), jsonStore));
_add(new configItem("password", &password, string));
_add(new configItem("tls", dynamic_cast<JsonStore *>(tls.get()), jsonStore));
_add(new configItem("multiplex", dynamic_cast<JsonStore *>(multiplex.get()), jsonStore));
_add(new configItem("transport", dynamic_cast<JsonStore *>(transport.get()), jsonStore));
}
bool HasTLS() override {
return true;
}
bool HasMux() override {
return true;
}
bool HasTransport() override {
return true;
}
std::shared_ptr<TLS> GetTLS() override {
return tls;
}
std::shared_ptr<Multiplex> GetMux() override {
return multiplex;
}
std::shared_ptr<Transport> GetTransport() override {
return transport;
}
// baseConfig overrides
bool ParseFromLink(const QString& link) override;
bool ParseFromJson(const QJsonObject& object) override;

View File

@ -22,7 +22,6 @@ namespace Configs
tuic() : outbound()
{
_add(new configItem("commons", dynamic_cast<JsonStore *>(commons.get()), jsonStore));
_add(new configItem("uuid", &uuid, string));
_add(new configItem("password", &password, string));
_add(new configItem("congestion_control", &congestion_control, string));
@ -33,6 +32,14 @@ namespace Configs
_add(new configItem("tls", dynamic_cast<JsonStore *>(tls.get()), jsonStore));
}
bool HasTLS() override {
return true;
}
std::shared_ptr<TLS> GetTLS() override {
return tls;
}
// baseConfig overrides
bool ParseFromLink(const QString& link) override;
bool ParseFromJson(const QJsonObject& object) override;

View File

@ -20,7 +20,6 @@ namespace Configs
vless() : outbound()
{
_add(new configItem("commons", dynamic_cast<JsonStore *>(commons.get()), jsonStore));
_add(new configItem("uuid", &uuid, string));
_add(new configItem("flow", &flow, string));
_add(new configItem("tls", dynamic_cast<JsonStore *>(tls.get()), jsonStore));
@ -29,6 +28,30 @@ namespace Configs
_add(new configItem("transport", dynamic_cast<JsonStore *>(transport.get()), jsonStore));
}
bool HasTLS() override {
return true;
}
bool HasMux() override {
return true;
}
bool HasTransport() override {
return true;
}
std::shared_ptr<TLS> GetTLS() override {
return tls;
}
std::shared_ptr<Multiplex> GetMux() override {
return multiplex;
}
std::shared_ptr<Transport> GetTransport() override {
return transport;
}
// baseConfig overrides
bool ParseFromLink(const QString& link) override;
bool ParseFromJson(const QJsonObject& object) override;

View File

@ -25,7 +25,6 @@ namespace Configs
vmess() : outbound()
{
_add(new configItem("commons", dynamic_cast<JsonStore *>(commons.get()), jsonStore));
_add(new configItem("uuid", &uuid, string));
_add(new configItem("security", &security, string));
_add(new configItem("alter-id", &alter_id, integer));
@ -37,6 +36,30 @@ namespace Configs
_add(new configItem("multiplex", dynamic_cast<JsonStore *>(multiplex.get()), jsonStore));
}
bool HasTLS() override {
return true;
}
bool HasMux() override {
return true;
}
bool HasTransport() override {
return true;
}
std::shared_ptr<TLS> GetTLS() override {
return tls;
}
std::shared_ptr<Multiplex> GetMux() override {
return multiplex;
}
std::shared_ptr<Transport> GetTransport() override {
return transport;
}
// baseConfig overrides
bool ParseFromLink(const QString& link) override;
bool ParseFromJson(const QJsonObject& object) override;

View File

@ -56,8 +56,6 @@ namespace Configs
wireguard() : outbound()
{
_add(new configItem("commons", dynamic_cast<JsonStore *>(commons.get()), jsonStore));
_add(new configItem("private_key", &private_key, itemType::string));
_add(new configItem("peer", dynamic_cast<JsonStore *>(peer.get()), jsonStore));
_add(new configItem("address", &address, itemType::stringList));

View File

@ -58,7 +58,7 @@ namespace Configs {
void UpdateRouteChains(const QList<std::shared_ptr<RoutingChain>>& newChain);
QStringList GetExtraCorePaths() const;
[[nodiscard]] QStringList GetExtraCorePaths() const;
bool AddExtraCorePath(const QString &path);

View File

@ -36,7 +36,7 @@ namespace Configs {
QString dl_speed;
QString ul_speed;
QString test_country;
std::shared_ptr<Configs::AbstractBean> bean;
std::shared_ptr<Configs::AbstractBean> _bean;
std::shared_ptr<Configs::outbound> outbound;
std::shared_ptr<Stats::TrafficData> traffic_data = std::make_shared<Stats::TrafficData>("");

View File

@ -57,6 +57,8 @@ QStringList SplitLines(const QString &_string);
QStringList SplitLinesSkipSharp(const QString &_string, int maxLine = 0);
QStringList SplitAndTrim(QString raw, QString seperator);
// Base64
QByteArray DecodeB64IfValid(const QString &input, QByteArray::Base64Options options = QByteArray::Base64Option::Base64Encoding);

View File

@ -25,15 +25,7 @@ public slots:
void accept() override;
private slots:
void on_custom_outbound_edit_clicked();
void on_custom_config_edit_clicked();
void on_certificate_edit_clicked();
void on_apply_to_group_clicked();
private:
Ui::DialogEditProfile *ui;
@ -50,8 +42,6 @@ private:
QString network_title_base;
struct {
QString custom_outbound;
QString custom_config;
QString certificate;
} CACHE;
@ -60,8 +50,6 @@ private:
bool onEnd();
void editor_cache_updated_impl();
void do_apply_to_group(const std::shared_ptr<Configs::Group> &group, QWidget *key);
};
#endif // DIALOG_EDIT_PROFILE_H

View File

@ -141,8 +141,28 @@
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="_2">
<item row="2" column="1">
<widget class="QComboBox" name="packet_encoding">
<item row="2" column="0">
<widget class="QLabel" name="multiplex_l">
<property name="toolTip">
<string>Server support is required</string>
</property>
<property name="text">
<string>Multiplex</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="security_l">
<property name="toolTip">
<string>Transport Layer Security. It must be consistent with the server, otherwise, the connection cannot be established.</string>
</property>
<property name="text">
<string>Security</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="security">
<item>
<property name="text">
<string notr="true"/>
@ -150,12 +170,7 @@
</item>
<item>
<property name="text">
<string notr="true">packetaddr</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">xudp</string>
<string notr="true">tls</string>
</property>
</item>
</widget>
@ -170,6 +185,25 @@
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="multiplex">
<item>
<property name="text">
<string>Keep Default</string>
</property>
</item>
<item>
<property name="text">
<string>On</string>
</property>
</item>
<item>
<property name="text">
<string>Off</string>
</property>
</item>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="network">
<property name="sizePolicy">
@ -215,69 +249,6 @@
</item>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="multiplex_l">
<property name="toolTip">
<string>Server support is required</string>
</property>
<property name="text">
<string>Multiplex</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="security_l">
<property name="toolTip">
<string>Transport Layer Security. It must be consistent with the server, otherwise, the connection cannot be established.</string>
</property>
<property name="text">
<string>Security</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="security">
<item>
<property name="text">
<string notr="true"/>
</property>
</item>
<item>
<property name="text">
<string notr="true">tls</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="packet_encoding_l">
<property name="toolTip">
<string>UDP FullCone Packet encoding for implementing features such as UDP FullCone. Server support is required, if the wrong selection is made, the connection cannot be made. Please leave it blank.</string>
</property>
<property name="text">
<string>Packet Encoding</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="multiplex">
<item>
<property name="text">
<string>Keep Default</string>
</property>
</item>
<item>
<property name="text">
<string>On</string>
</property>
</item>
<item>
<property name="text">
<string>Off</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
@ -326,57 +297,8 @@
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QGroupBox" name="custom_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Custom Outbound Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QPushButton" name="custom_outbound_edit">
<property name="text">
<string notr="true">Edit</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="custom_global_box">
<property name="title">
<string>Custom Config Settings</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="custom_config_edit">
<property name="text">
<string notr="true">Edit</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QPushButton" name="apply_to_group">
<property name="text">
<string>Apply settings to this group</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="sizePolicy">
@ -431,14 +353,36 @@
<string>Network Settings (%1)</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="6" column="0">
<item row="2" column="1">
<widget class="MyLineEdit" name="path"/>
</item>
<item row="4" column="1">
<widget class="MyLineEdit" name="ws_early_data_length"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="path_l">
<property name="toolTip">
<string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;http path (ws/http/httpUpgrade)&lt;/p&gt;&lt;p&gt;serviceName (gRPC)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string notr="true">Path</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="ws_early_data_name_l">
<property name="text">
<string notr="true">EarlyData Name</string>
</property>
</widget>
</item>
<item row="1" column="0">
<item row="0" column="1">
<widget class="QLineEdit" name="headers"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="method"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="headers_l">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
@ -457,49 +401,14 @@
</property>
</widget>
</item>
<item row="5" column="0">
<item row="4" column="0">
<widget class="QLabel" name="ws_early_data_length_l">
<property name="text">
<string notr="true">EarlyData Length</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="method"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="path_l">
<property name="toolTip">
<string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;http path (ws/http/httpUpgrade)&lt;/p&gt;&lt;p&gt;serviceName (gRPC)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string notr="true">Path</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="MyLineEdit" name="path"/>
</item>
<item row="6" column="1">
<widget class="MyLineEdit" name="ws_early_data_name"/>
</item>
<item row="5" column="1">
<widget class="MyLineEdit" name="ws_early_data_length"/>
</item>
<item row="4" column="1">
<widget class="MyLineEdit" name="host"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="method_l">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Method of http request, will be converted to uppercase&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Method</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="host_l">
<property name="toolTip">
<string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;http host (ws/http/httpUpgrade)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@ -509,30 +418,22 @@
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="headers"/>
<item row="3" column="1">
<widget class="MyLineEdit" name="host"/>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="header_type">
<item>
<property name="text">
<string/>
</property>
</item>
<item>
<property name="text">
<string notr="true">http</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="header_type_l">
<item row="1" column="0">
<widget class="QLabel" name="method_l">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Method of http request, will be converted to uppercase&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>header type</string>
<string>Method</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="MyLineEdit" name="ws_early_data_name"/>
</item>
</layout>
</widget>
</item>
@ -805,12 +706,8 @@
<tabstop>name</tabstop>
<tabstop>address</tabstop>
<tabstop>port</tabstop>
<tabstop>custom_outbound_edit</tabstop>
<tabstop>custom_config_edit</tabstop>
<tabstop>apply_to_group</tabstop>
<tabstop>network</tabstop>
<tabstop>security</tabstop>
<tabstop>packet_encoding</tabstop>
<tabstop>multiplex</tabstop>
<tabstop>path</tabstop>
<tabstop>host</tabstop>

View File

@ -1,26 +1,29 @@
#pragma once
#ifndef EDIT_HTTP_H
#define EDIT_HTTP_H
#include <QWidget>
#include "profile_editor.h"
#include "ui_edit_socks_http.h"
#include "ui_edit_http.h"
namespace Ui {
class EditSocksHttp;
class EditHttp;
}
class EditSocksHttp : public QWidget, public ProfileEditor {
class EditHttp : public QWidget, public ProfileEditor {
Q_OBJECT
public:
explicit EditSocksHttp(QWidget *parent = nullptr);
explicit EditHttp(QWidget *parent = nullptr);
~EditSocksHttp() override;
~EditHttp() override;
void onStart(std::shared_ptr<Configs::ProxyEntity> _ent) override;
bool onEnd() override;
private:
Ui::EditSocksHttp *ui;
Ui::EditHttp *ui;
std::shared_ptr<Configs::ProxyEntity> ent;
};
#endif

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditHttp</class>
<widget class="QWidget" name="EditHttp">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Username</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="username"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Password</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="password"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,29 @@
#ifndef EDIT_HYSTERIA_H
#define EDIT_HYSTERIA_H
#include <QWidget>
#include "profile_editor.h"
#include "ui_edit_hysteria.h"
namespace Ui {
class EditHysteria;
}
class EditHysteria : public QWidget, public ProfileEditor {
Q_OBJECT
public:
explicit EditHysteria(QWidget *parent = nullptr);
~EditHysteria() override;
void onStart(std::shared_ptr<Configs::ProxyEntity> _ent) override;
bool onEnd() override;
private:
Ui::EditHysteria *ui;
std::shared_ptr<Configs::ProxyEntity> ent;
};
#endif

View File

@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditHysteria</class>
<widget class="QWidget" name="EditHysteria">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>363</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Down Mbps</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="auth_str"/>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="auth"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Recv window conn</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Hop Interval</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="obfs"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Server Ports</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Auth</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="down_mbps"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Up Mbps</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="server_ports"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Auth Str</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="hop_interval"/>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="up_mbps"/>
</item>
<item row="7" column="1">
<widget class="QLineEdit" name="recv_window_conn"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Obfs</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Recv window</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLineEdit" name="recv_window"/>
</item>
<item row="9" column="1">
<widget class="QCheckBox" name="disable_mtu_discovery">
<property name="text">
<string>Disable Mtu Discovery</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,29 @@
#ifndef EDIT_HYSTERIA2_H
#define EDIT_HYSTERIA2_H
#include <QWidget>
#include "profile_editor.h"
#include "ui_edit_hysteria2.h"
namespace Ui {
class EditHysteria2;
}
class EditHysteria2 : public QWidget, public ProfileEditor {
Q_OBJECT
public:
explicit EditHysteria2(QWidget *parent = nullptr);
~EditHysteria2() override;
void onStart(std::shared_ptr<Configs::ProxyEntity> _ent) override;
bool onEnd() override;
private:
Ui::EditHysteria2 *ui;
std::shared_ptr<Configs::ProxyEntity> ent;
};
#endif // EDIT_HYSTERIA2_H

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditHysteria2</class>
<widget class="QWidget" name="EditHysteria2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="1">
<widget class="QLineEdit" name="up_mbps"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Server Ports</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="hop_interval"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Password</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Down Mbps</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Obfs Password</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="obfs_password"/>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="password"/>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="down_mbps"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Hop Interval</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Up Mbps</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="server_ports"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -1,40 +0,0 @@
#pragma once
#include <QWidget>
#include <QGridLayout>
#include <QHBoxLayout>
#include "profile_editor.h"
#include "ui_edit_quic.h"
QT_BEGIN_NAMESPACE
namespace Ui {
class EditQUIC;
}
QT_END_NAMESPACE
class EditQUIC : public QWidget, public ProfileEditor {
Q_OBJECT
public:
explicit EditQUIC(QWidget *parent = nullptr);
~EditQUIC() override;
void onStart(std::shared_ptr<Configs::ProxyEntity> _ent) override;
bool onEnd() override;
QList<QPair<QPushButton *, QString>> get_editor_cached() override;
private:
Ui::EditQUIC *ui;
std::shared_ptr<Configs::ProxyEntity> ent;
struct {
QString caText;
} CACHE;
private slots:
void on_certificate_clicked();
};

View File

@ -1,412 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditQUIC</class>
<widget class="QWidget" name="EditQUIC">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>500</width>
<height>628</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">EditHysteria</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="upBox">
<item row="2" column="0">
<layout class="QHBoxLayout" name="heartbeatLay">
<item>
<widget class="QLabel" name="heartbeat_l">
<property name="text">
<string>Heartbeat</string>
</property>
</widget>
</item>
<item>
<widget class="MyLineEdit" name="heartbeat">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="downloadMbpsLay">
<item>
<widget class="QLabel" name="downloadMbps_l">
<property name="text">
<string>Download (Mbps)</string>
</property>
</widget>
</item>
<item>
<widget class="MyLineEdit" name="downloadMbps"/>
</item>
</layout>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="uos">
<property name="toolTip">
<string notr="true">Requires sing-box server</string>
</property>
<property name="text">
<string notr="true">UDP over Stream</string>
</property>
</widget>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="uploadMbpsLay">
<item>
<widget class="QLabel" name="uploadMbps_l">
<property name="text">
<string>Upload (Mbps)</string>
</property>
</widget>
</item>
<item>
<widget class="MyLineEdit" name="uploadMbps"/>
</item>
</layout>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="zeroRttHandshake">
<property name="text">
<string>Zero Rtt Handshake</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="udpRelayModeLay">
<item>
<widget class="QLabel" name="udpRelayMode_l">
<property name="text">
<string>UDP Relay Mode</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="udpRelayMode">
<item>
<property name="text">
<string notr="true">native</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">quic</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="congestionControlLay">
<item>
<widget class="QLabel" name="congestionControl_l">
<property name="text">
<string>Congestion Control</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="congestionControl">
<item>
<property name="text">
<string notr="true">bbr</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">cubic</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">new_reno</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="obfuscation">
<item row="0" column="1">
<widget class="QLineEdit" name="port_range">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Comma seperated ranges: 100:200,500:600&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="obfsPassword_l">
<property name="text">
<string>Obfs Password</string>
</property>
</widget>
</item>
<item row="0" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_2"/>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="disableMtuDiscovery">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Disable MTU Discovery</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="port_range_l">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Comma seperated ranges: 100:200,500:600&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Port range</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="MyLineEdit" name="obfsPassword"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="hop_interval_l">
<property name="text">
<string>Hop Interval</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="hop_interval">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;100ms&lt;br/&gt;1s&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="authentication">
<item row="2" column="1">
<widget class="MyLineEdit" name="uuid"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="authPayloadType_l">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Auth Type</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="authPayload_l">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Auth Payload</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="password_l">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Password</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="uuid_l">
<property name="text">
<string notr="true">UUID</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="uuidgen">
<property name="text">
<string>Generate UUID</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="MyLineEdit" name="password"/>
</item>
<item row="1" column="1" colspan="2">
<widget class="MyLineEdit" name="authPayload"/>
</item>
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="authPayloadType">
<item>
<property name="text">
<string notr="true">NONE</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">STRING</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">BASE64</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="TLS" rowstretch="0,0,0">
<item row="2" column="0">
<widget class="QLabel" name="certificate_l">
<property name="text">
<string>Certificate</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="certificate">
<property name="text">
<string notr="true">PushButton</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="MyLineEdit" name="alpn"/>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="disableSni">
<property name="text">
<string>Disable SNI</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="MyLineEdit" name="sni"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="alpn_l">
<property name="text">
<string notr="true">ALPN</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="sni_l">
<property name="text">
<string>SNI</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QCheckBox" name="allowInsecure">
<property name="text">
<string>Allow Insecure</string>
</property>
</widget>
</item>
<item row="1" column="2">
<spacer name="alpn_sp">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Maximum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="flowControlWindow">
<item>
<widget class="QLabel" name="streamReceiveWindow_l">
<property name="text">
<string notr="true">recv_window</string>
</property>
</widget>
</item>
<item>
<widget class="MyLineEdit" name="streamReceiveWindow"/>
</item>
<item>
<widget class="QLabel" name="connectionReceiveWindow_l">
<property name="text">
<string notr="true">recv_window_conn</string>
</property>
</widget>
</item>
<item>
<widget class="MyLineEdit" name="connectionReceiveWindow"/>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>MyLineEdit</class>
<extends>QLineEdit</extends>
<header>include/ui/utils/MyLineEdit.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>uploadMbps</tabstop>
<tabstop>downloadMbps</tabstop>
<tabstop>congestionControl</tabstop>
<tabstop>udpRelayMode</tabstop>
<tabstop>heartbeat</tabstop>
<tabstop>zeroRttHandshake</tabstop>
<tabstop>uos</tabstop>
<tabstop>authPayloadType</tabstop>
<tabstop>authPayload</tabstop>
<tabstop>uuid</tabstop>
<tabstop>uuidgen</tabstop>
<tabstop>password</tabstop>
<tabstop>sni</tabstop>
<tabstop>disableSni</tabstop>
<tabstop>alpn</tabstop>
<tabstop>certificate</tabstop>
<tabstop>allowInsecure</tabstop>
<tabstop>streamReceiveWindow</tabstop>
<tabstop>connectionReceiveWindow</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,29 @@
#ifndef EDIT_SOCKS_H
#define EDIT_SOCKS_H
#include <QWidget>
#include "profile_editor.h"
#include "ui_edit_socks.h"
namespace Ui {
class EditSocks;
}
class EditSocks : public QWidget, public ProfileEditor {
Q_OBJECT
public:
explicit EditSocks(QWidget *parent = nullptr);
~EditSocks() override;
void onStart(std::shared_ptr<Configs::ProxyEntity> _ent) override;
bool onEnd() override;
private:
Ui::EditSocks *ui;
std::shared_ptr<Configs::ProxyEntity> ent;
};
#endif // EDIT_SOCKS_H

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditSocksHttp</class>
<widget class="QWidget" name="EditSocksHttp">
<class>EditSocks</class>
<widget class="QWidget" name="EditSocks">
<property name="geometry">
<rect>
<x>0</x>
@ -11,57 +11,52 @@
</rect>
</property>
<property name="windowTitle">
<string notr="true">Form</string>
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="version_l">
<property name="text">
<string>Version</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="username"/>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="password"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Username</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="version">
<item>
<property name="text">
<string notr="true">5</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">4</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Password</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Version</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Username</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="password"/>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="username"/>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="version">
<item>
<property name="text">
<string>5</string>
</property>
</item>
<item>
<property name="text">
<string>4</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>version</tabstop>
<tabstop>username</tabstop>
<tabstop>password</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,29 @@
#ifndef EDIT_TROJAN_H
#define EDIT_TROJAN_H
#include <QWidget>
#include "profile_editor.h"
#include "ui_edit_trojan.h"
namespace Ui {
class EditTrojan;
}
class EditTrojan : public QWidget, public ProfileEditor {
Q_OBJECT
public:
explicit EditTrojan(QWidget *parent = nullptr);
~EditTrojan() override;
void onStart(std::shared_ptr<Configs::ProxyEntity> _ent) override;
bool onEnd() override;
private:
Ui::EditTrojan *ui;
std::shared_ptr<Configs::ProxyEntity> ent;
};
#endif // EDIT_TROJAN_H

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditTrojan</class>
<widget class="QWidget" name="EditTrojan">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Password</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="password"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,29 @@
#ifndef EDIT_TUIC_H
#define EDIT_TUIC_H
#include <QWidget>
#include "profile_editor.h"
#include "ui_edit_tuic.h"
namespace Ui {
class EditTuic;
}
class EditTuic : public QWidget, public ProfileEditor {
Q_OBJECT
public:
explicit EditTuic(QWidget *parent = nullptr);
~EditTuic() override;
void onStart(std::shared_ptr<Configs::ProxyEntity> _ent) override;
bool onEnd() override;
private:
Ui::EditTuic *ui;
std::shared_ptr<Configs::ProxyEntity> ent;
};
#endif // EDIT_TUIC_H

View File

@ -0,0 +1,112 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditTuic</class>
<widget class="QWidget" name="EditTuic">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="5" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Heartbeat</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>UDP Relay Mode</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Password</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="zero_rtt">
<property name="text">
<string>Zero RTT Handshake</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="uuid"/>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="heartbeat"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="password"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>UUID</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="congestion_control">
<item>
<property name="text">
<string>bbr</string>
</property>
</item>
<item>
<property name="text">
<string>cubic</string>
</property>
</item>
<item>
<property name="text">
<string>new_reno</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Congestion Control</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="udp_relay_mode">
<item>
<property name="text">
<string>native</string>
</property>
</item>
<item>
<property name="text">
<string>quic</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="udp_over_stream">
<property name="text">
<string>UDP over Stream</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -2,29 +2,28 @@
#include <QWidget>
#include "profile_editor.h"
#include "ui_edit_trojan_vless.h"
#include "ui_edit_vless.h"
QT_BEGIN_NAMESPACE
namespace Ui {
class EditTrojanVLESS;
class EditVless;
}
QT_END_NAMESPACE
class EditTrojanVLESS : public QWidget, public ProfileEditor {
class EditVless : public QWidget, public ProfileEditor {
Q_OBJECT
public:
explicit EditTrojanVLESS(QWidget *parent = nullptr);
explicit EditVless(QWidget *parent = nullptr);
~EditTrojanVLESS() override;
~EditVless() override;
void onStart(std::shared_ptr<Configs::ProxyEntity> _ent) override;
bool onEnd() override;
QComboBox* flow_;
QComboBox *_flow;
private:
Ui::EditTrojanVLESS *ui;
Ui::EditVless *ui;
std::shared_ptr<Configs::ProxyEntity> ent;
};

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditTrojanVLESS</class>
<widget class="QWidget" name="EditTrojanVLESS">
<class>EditVless</class>
<widget class="QWidget" name="EditVless">
<property name="geometry">
<rect>
<x>0</x>
@ -14,16 +14,6 @@
<string notr="true"/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="MyLineEdit" name="password"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Password</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="flow_l">
<property name="text">
@ -40,6 +30,26 @@
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>UUID</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="MyLineEdit" name="uuid"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Packet Encoding</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="packet_encoding"/>
</item>
</layout>
</widget>
<customwidgets>

View File

@ -14,62 +14,6 @@
<string notr="true">EditVMess</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="4" column="1">
<widget class="QComboBox" name="security">
<property name="editable">
<bool>true</bool>
</property>
<item>
<property name="text">
<string notr="true">auto</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">zero</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">none</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">chacha20-poly1305</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">aes-128-gcm</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Security</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Alter Id</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>UUID</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="MyLineEdit" name="uuid"/>
</item>
<item row="3" column="1">
<widget class="QWidget" name="horizontalWidget" native="true">
<property name="sizePolicy">
@ -104,6 +48,72 @@
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Alter Id</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="security">
<property name="editable">
<bool>true</bool>
</property>
<item>
<property name="text">
<string notr="true">auto</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">zero</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">none</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">chacha20-poly1305</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">aes-128-gcm</string>
</property>
</item>
</widget>
</item>
<item row="0" column="1">
<widget class="MyLineEdit" name="uuid"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Security</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>UUID</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Packet Encoding</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="packet_encoding"/>
</item>
</layout>
</widget>
<customwidgets>

View File

@ -2,7 +2,7 @@
#include "include/configs/common/utils.h"
namespace Configs {
bool OutboundCommons::ParseFromLink(const QString& link)
bool outbound::ParseFromLink(const QString& link)
{
auto url = QUrl(link);
if (!url.isValid()) return false;
@ -13,7 +13,7 @@ namespace Configs {
dialFields->ParseFromLink(link);
return true;
}
bool OutboundCommons::ParseFromJson(const QJsonObject& object)
bool outbound::ParseFromJson(const QJsonObject& object)
{
if (object.isEmpty()) return false;
if (object.contains("tag")) name = object["tag"].toString();
@ -22,13 +22,13 @@ namespace Configs {
dialFields->ParseFromJson(object);
return true;
}
QString OutboundCommons::ExportToLink()
QString outbound::ExportToLink()
{
QUrlQuery query;
mergeUrlQuery(query, dialFields->ExportToLink());
return query.toString();
}
QJsonObject OutboundCommons::ExportToJson()
QJsonObject outbound::ExportToJson()
{
QJsonObject object;
if (!name.isEmpty()) object["tag"] = name;
@ -38,7 +38,7 @@ namespace Configs {
mergeJsonObjects(object, dialFieldsObj);
return object;
}
BuildResult OutboundCommons::Build()
BuildResult outbound::Build()
{
return {ExportToJson(), ""};
}

View File

@ -137,7 +137,13 @@ namespace Configs {
}
BuildResult Reality::Build()
{
return {ExportToJson(), ""};
QJsonObject object;
if (!public_key.isEmpty() || enabled) {
object["enabled"] = true;
object["public_key"] = public_key;
if (!short_id.isEmpty()) object["short_id"] = short_id;
}
return {object, ""};
}
bool TLS::ParseFromLink(const QString& link)

View File

@ -7,6 +7,57 @@
#include "include/configs/common/utils.h"
namespace Configs {
QString Transport::getHeadersString() {
QString result;
for (int i=0;i<headers.length();i+=2) {
result += headers[i]+"=";
result += "\""+headers[i+1]+"\" ";
}
return result;
}
QStringList Transport::getHeaderPairs(QString rawHeader) {
bool inQuote = false;
QString curr;
QStringList list;
for (const auto &ch: rawHeader) {
if (inQuote) {
if (ch == '"') {
inQuote = false;
list << curr;
curr = "";
continue;
} else {
curr += ch;
continue;
}
}
if (ch == '"') {
inQuote = true;
continue;
}
if (ch == ' ') {
if (!curr.isEmpty()) {
list << curr;
curr = "";
}
continue;
}
if (ch == '=') {
if (!curr.isEmpty()) {
list << curr;
curr = "";
}
continue;
}
curr+=ch;
}
if (!curr.isEmpty()) list<<curr;
return list;
}
bool Transport::ParseFromLink(const QString& link)
{
auto url = QUrl(link);

View File

@ -886,7 +886,7 @@ namespace Configs {
}
if (resp.isEmpty()) return true;
// else
MW_show_log("Invalid ent " + ent->outbound->commons->name + ": " + resp);
MW_show_log("Invalid ent " + ent->outbound->name + ": " + resp);
return false;
}
@ -921,7 +921,7 @@ namespace Configs {
continue;
}
if (!IsValid(item)) {
MW_show_log("Skipping invalid config: " + item->outbound->commons->name);
MW_show_log("Skipping invalid config: " + item->outbound->name);
item->latency = -1;
continue;
}

View File

@ -12,10 +12,10 @@ namespace Configs {
if (!url.isValid()) return false;
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
commons->ParseFromLink(link);
outbound::ParseFromLink(link);
password = url.userName();
if (commons->server_port == 0) commons->server_port = 443;
if (server_port == 0) server_port = 443;
if (query.hasQueryItem("idle_session_check_interval")) idle_session_check_interval = query.queryItemValue("idle_session_check_interval");
if (query.hasQueryItem("idle_session_timeout")) idle_session_timeout = query.queryItemValue("idle_session_timeout");
@ -30,7 +30,7 @@ namespace Configs {
bool anyTLS::ParseFromJson(const QJsonObject& object)
{
if (object.isEmpty() || object["type"].toString() != "anytls") return false;
commons->ParseFromJson(object);
outbound::ParseFromJson(object);
if (object.contains("password")) password = object["password"].toString();
if (object.contains("idle_session_check_interval")) idle_session_check_interval = object["idle_session_check_interval"].toString();
if (object.contains("idle_session_timeout")) idle_session_timeout = object["idle_session_timeout"].toString();
@ -45,16 +45,16 @@ namespace Configs {
QUrlQuery query;
url.setScheme("anytls");
url.setUserName(password);
url.setHost(commons->server);
url.setPort(commons->server_port);
if (!commons->name.isEmpty()) url.setFragment(commons->name);
url.setHost(server);
url.setPort(server_port);
if (!name.isEmpty()) url.setFragment(name);
if (!idle_session_check_interval.isEmpty()) query.addQueryItem("idle_session_check_interval", idle_session_check_interval);
if (!idle_session_timeout.isEmpty()) query.addQueryItem("idle_session_timeout", idle_session_timeout);
if (min_idle_session > 0) query.addQueryItem("min_idle_session", QString::number(min_idle_session));
mergeUrlQuery(query, tls->ExportToLink());
mergeUrlQuery(query, commons->ExportToLink());
mergeUrlQuery(query, outbound::ExportToLink());
if (!query.isEmpty()) url.setQuery(query);
return url.toString();
@ -64,7 +64,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "anytls";
mergeJsonObjects(object, commons->ExportToJson());
mergeJsonObjects(object, outbound::ExportToJson());
if (!password.isEmpty()) object["password"] = password;
if (!idle_session_check_interval.isEmpty()) object["idle_session_check_interval"] = idle_session_check_interval;
if (!idle_session_timeout.isEmpty()) object["idle_session_timeout"] = idle_session_timeout;
@ -77,7 +77,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "anytls";
mergeJsonObjects(object, commons->Build().object);
mergeJsonObjects(object, outbound::Build().object);
if (!password.isEmpty()) object["password"] = password;
if (!idle_session_check_interval.isEmpty()) object["idle_session_check_interval"] = idle_session_check_interval;
if (!idle_session_timeout.isEmpty()) object["idle_session_timeout"] = idle_session_timeout;

View File

@ -12,7 +12,7 @@ namespace Configs {
if (!url.isValid()) return false;
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
commons->ParseFromLink(link);
outbound::ParseFromLink(link);
username = url.userName();
password = url.password();
if (query.hasQueryItem("path")) path = query.queryItemValue("path");
@ -22,13 +22,13 @@ namespace Configs {
tls->ParseFromLink(link);
tls->enabled = true; // force enable in case scheme is https and no security queryValue is set
}
if (commons->server_port == 0) commons->server_port = 443;
if (server_port == 0) server_port = 443;
return true;
}
bool http::ParseFromJson(const QJsonObject& object)
{
if (object.empty() || object["type"] != "http") return false;
commons->ParseFromJson(object);
outbound::ParseFromJson(object);
if (object.contains("username")) username = object["username"].toString();
if (object.contains("password")) password = object["password"].toString();
if (object.contains("path")) path = object["path"].toString();
@ -41,15 +41,15 @@ namespace Configs {
QUrl url;
QUrlQuery query;
url.setScheme(tls->enabled ? "https" : "http");
url.setHost(commons->server);
url.setPort(commons->server_port);
if (!commons->name.isEmpty()) url.setFragment(commons->name);
url.setHost(server);
url.setPort(server_port);
if (!name.isEmpty()) url.setFragment(name);
if (!username.isEmpty()) url.setUserName(username);
if (!password.isEmpty()) url.setPassword(password);
if (!path.isEmpty()) query.addQueryItem("path", path);
if (!headers.empty()) query.addQueryItem("headers", headers.join(","));
mergeUrlQuery(query, tls->ExportToLink());
mergeUrlQuery(query, commons->ExportToLink());
mergeUrlQuery(query, outbound::ExportToLink());
if (!query.isEmpty()) url.setQuery(query);
return url.toString();
}
@ -57,7 +57,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "http";
mergeJsonObjects(object, commons->ExportToJson());
mergeJsonObjects(object, outbound::ExportToJson());
if (!username.isEmpty()) object["username"] = username;
if (!password.isEmpty()) object["password"] = password;
if (!path.isEmpty()) object["path"] = path;
@ -69,7 +69,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "http";
mergeJsonObjects(object, commons->Build().object);
mergeJsonObjects(object, outbound::Build().object);
if (!username.isEmpty()) object["username"] = username;
if (!password.isEmpty()) object["password"] = password;
if (!path.isEmpty()) object["path"] = path;

View File

@ -15,7 +15,7 @@ namespace Configs {
{
if(!url.errorString().startsWith("Invalid port"))
return false;
commons->server_port = 0;
server_port = 0;
server_ports = QString::fromStdString(URLParser::Parse((link.split("?")[0] + "/").toStdString()).port).split(",");
for (auto & serverPort : server_ports) {
serverPort.replace("-", ":");
@ -23,7 +23,7 @@ namespace Configs {
}
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
commons->ParseFromLink(link);
outbound::ParseFromLink(link);
if (query.hasQueryItem("upmbps")) up_mbps = query.queryItemValue("upmbps").toInt();
if (query.hasQueryItem("downmbps")) down_mbps = query.queryItemValue("downmbps").toInt();
@ -42,7 +42,7 @@ namespace Configs {
tls->ParseFromLink(link);
if (commons->server_port == 0 && server_ports.isEmpty()) commons->server_port = 443;
if (server_port == 0 && server_ports.isEmpty()) server_port = 443;
return true;
}
@ -50,7 +50,7 @@ namespace Configs {
bool hysteria::ParseFromJson(const QJsonObject& object)
{
if (object.isEmpty() || object["type"].toString() != "hysteria") return false;
commons->ParseFromJson(object);
outbound::ParseFromJson(object);
if (object.contains("server_ports")) {
server_ports = QJsonArray2QListString(object["server_ports"].toArray());
}
@ -72,7 +72,7 @@ namespace Configs {
QUrl url;
QUrlQuery query;
url.setScheme("hysteria");
url.setHost(commons->server);
url.setHost(server);
url.setPort(0);
if (!server_ports.isEmpty()) {
@ -85,10 +85,10 @@ namespace Configs {
url.setPort(0);
query.addQueryItem("mport", portList.join(","));
} else {
url.setPort(commons->server_port);
url.setPort(server_port);
}
if (!commons->name.isEmpty()) url.setFragment(commons->name);
if (!name.isEmpty()) url.setFragment(name);
if (up_mbps > 0) query.addQueryItem("upmbps", QString::number(up_mbps));
if (down_mbps > 0) query.addQueryItem("downmbps", QString::number(down_mbps));
@ -102,7 +102,7 @@ namespace Configs {
if (!hop_interval.isEmpty()) query.addQueryItem("hop_interval", hop_interval);
mergeUrlQuery(query, tls->ExportToLink());
mergeUrlQuery(query, commons->ExportToLink());
mergeUrlQuery(query, outbound::ExportToLink());
if (!query.isEmpty()) url.setQuery(query);
@ -117,7 +117,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "hysteria";
mergeJsonObjects(object, commons->ExportToJson());
mergeJsonObjects(object, outbound::ExportToJson());
if (!server_ports.isEmpty()) object["server_ports"] = QListStr2QJsonArray(server_ports);
if (!hop_interval.isEmpty()) object["hop_interval"] = hop_interval;
if (up_mbps > 0) object["up_mbps"] = up_mbps;
@ -136,7 +136,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "hysteria";
mergeJsonObjects(object, commons->Build().object);
mergeJsonObjects(object, outbound::Build().object);
if (!server_ports.isEmpty()) object["server_ports"] = QListStr2QJsonArray(server_ports);
if (!hop_interval.isEmpty()) object["hop_interval"] = hop_interval;
if (up_mbps > 0) object["up_mbps"] = up_mbps;

View File

@ -15,7 +15,7 @@ namespace Configs {
{
if(!url.errorString().startsWith("Invalid port"))
return false;
commons->server_port = 0;
server_port = 0;
server_ports = QString::fromStdString(URLParser::Parse((link.split("?")[0] + "/").toStdString()).port).split(",");
for (auto & serverPort : server_ports) {
serverPort.replace("-", ":");
@ -23,7 +23,7 @@ namespace Configs {
}
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
commons->ParseFromLink(link);
outbound::ParseFromLink(link);
if (url.password().isEmpty()) {
password = url.userName();
@ -48,7 +48,7 @@ namespace Configs {
tls->ParseFromLink(link);
if (commons->server_port == 0 && server_ports.isEmpty()) commons->server_port = 443;
if (server_port == 0 && server_ports.isEmpty()) server_port = 443;
return true;
}
@ -56,7 +56,7 @@ namespace Configs {
bool hysteria2::ParseFromJson(const QJsonObject& object)
{
if (object.isEmpty() || object["type"].toString() != "hysteria2") return false;
commons->ParseFromJson(object);
outbound::ParseFromJson(object);
if (object.contains("server_ports")) {
server_ports = QJsonArray2QListString(object["server_ports"].toArray());
}
@ -79,7 +79,7 @@ namespace Configs {
QUrl url;
QUrlQuery query;
url.setScheme("hy2");
url.setHost(commons->server);
url.setHost(server);
if (password.contains(":")) {
url.setUserName(SubStrBefore(password, ":"));
@ -98,10 +98,10 @@ namespace Configs {
url.setPort(0);
query.addQueryItem("mport", portList.join(","));
} else {
url.setPort(commons->server_port);
url.setPort(server_port);
}
if (!commons->name.isEmpty()) url.setFragment(commons->name);
if (!name.isEmpty()) url.setFragment(name);
if (!obfsPassword.isEmpty()) {
query.addQueryItem("obfs-password", QUrl::toPercentEncoding(obfsPassword));
@ -111,7 +111,7 @@ namespace Configs {
if (!hop_interval.isEmpty()) query.addQueryItem("hop_interval", hop_interval);
mergeUrlQuery(query, tls->ExportToLink());
mergeUrlQuery(query, commons->ExportToLink());
mergeUrlQuery(query, outbound::ExportToLink());
if (!query.isEmpty()) url.setQuery(query);
@ -126,7 +126,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "hysteria2";
mergeJsonObjects(object, commons->ExportToJson());
mergeJsonObjects(object, outbound::ExportToJson());
if (!server_ports.isEmpty()) object["server_ports"] = QListStr2QJsonArray(server_ports);
if (!hop_interval.isEmpty()) object["hop_interval"] = hop_interval;
if (up_mbps > 0) object["up_mbps"] = up_mbps;
@ -144,7 +144,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "hysteria2";
mergeJsonObjects(object, commons->Build().object);
mergeJsonObjects(object, outbound::Build().object);
if (!server_ports.isEmpty()) object["server_ports"] = QListStr2QJsonArray(server_ports);
if (!hop_interval.isEmpty()) object["hop_interval"] = hop_interval;
if (up_mbps > 0) object["up_mbps"] = up_mbps;

View File

@ -12,7 +12,7 @@ namespace Configs {
if (!url.isValid()) return false;
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
commons->ParseFromLink(link);
outbound::ParseFromLink(link);
if (SubStrBefore(link, "#").contains("@")) {
// Traditional SS format
@ -35,7 +35,7 @@ namespace Configs {
url = QUrl("https://" + linkN);
if (!url.isValid()) return false;
query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
commons->ParseFromLink(url.toString());
outbound::ParseFromLink(url.toString());
method = url.userName();
password = url.password();
}
@ -45,13 +45,13 @@ namespace Configs {
if (query.hasQueryItem("uot")) uot = query.queryItemValue("uot") == "true" || query.queryItemValue("uot").toInt() > 0;
multiplex->ParseFromLink(link);
return !(commons->server.isEmpty() || method.isEmpty() || password.isEmpty());
return !(server.isEmpty() || method.isEmpty() || password.isEmpty());
}
bool shadowsocks::ParseFromJson(const QJsonObject& object)
{
if (object.isEmpty() || object["type"].toString() != "shadowsocks") return false;
commons->ParseFromJson(object);
outbound::ParseFromJson(object);
if (object.contains("method")) method = object["method"].toString();
if (object.contains("password")) password = object["password"].toString();
if (object.contains("plugin")) plugin = object["plugin"].toString();
@ -81,16 +81,16 @@ namespace Configs {
url.setUserName(method_password.toUtf8().toBase64(QByteArray::Base64Option::Base64UrlEncoding));
}
url.setHost(commons->server);
url.setPort(commons->server_port);
if (!commons->name.isEmpty()) url.setFragment(commons->name);
url.setHost(server);
url.setPort(server_port);
if (!name.isEmpty()) url.setFragment(name);
if (!plugin.isEmpty()) query.addQueryItem("plugin", plugin);
if (!plugin_opts.isEmpty()) query.addQueryItem("plugin-opts", plugin_opts);
if (uot) query.addQueryItem("uot", "true");
mergeUrlQuery(query, multiplex->ExportToLink());
mergeUrlQuery(query, commons->ExportToLink());
mergeUrlQuery(query, outbound::ExportToLink());
if (!query.isEmpty()) url.setQuery(query);
return url.toString();
@ -100,7 +100,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "shadowsocks";
mergeJsonObjects(object, commons->ExportToJson());
mergeJsonObjects(object, outbound::ExportToJson());
if (!method.isEmpty()) object["method"] = method;
if (!password.isEmpty()) object["password"] = password;
if (!plugin.isEmpty()) object["plugin"] = plugin;
@ -114,7 +114,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "shadowsocks";
mergeJsonObjects(object, commons->Build().object);
mergeJsonObjects(object, outbound::Build().object);
if (!method.isEmpty()) object["method"] = method;
if (!password.isEmpty()) object["password"] = password;
if (!plugin.isEmpty()) object["plugin"] = plugin;

View File

@ -12,7 +12,7 @@ namespace Configs {
if (!url.isValid()) return false;
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
commons->ParseFromLink(link);
outbound::ParseFromLink(link);
if (query.hasQueryItem("version"))
{
version = query.queryItemValue("version").toInt();
@ -40,15 +40,15 @@ namespace Configs {
if (query.hasQueryItem("uot")) uot = query.queryItemValue("uot") == "true" || query.queryItemValue("uot").toInt() > 0;
// Default port
if (commons->server_port == 0) commons->server_port = 1080;
if (server_port == 0) server_port = 1080;
return !commons->server.isEmpty();
return !server.isEmpty();
}
bool socks::ParseFromJson(const QJsonObject& object)
{
if (object.isEmpty() || object["type"].toString() != "socks") return false;
commons->ParseFromJson(object);
outbound::ParseFromJson(object);
if (object.contains("username")) username = object["username"].toString();
if (object.contains("password")) password = object["password"].toString();
if (object.contains("version")) version = object["version"].toInt();
@ -68,15 +68,15 @@ namespace Configs {
}
url.setScheme(scheme);
url.setHost(commons->server);
url.setPort(commons->server_port);
if (!commons->name.isEmpty()) url.setFragment(commons->name);
url.setHost(server);
url.setPort(server_port);
if (!name.isEmpty()) url.setFragment(name);
if (!username.isEmpty()) url.setUserName(username);
if (!password.isEmpty()) url.setPassword(password);
if (uot) query.addQueryItem("uot", "1");
mergeUrlQuery(query, commons->ExportToLink());
mergeUrlQuery(query, outbound::ExportToLink());
if (!query.isEmpty()) url.setQuery(query);
return url.toString();
}
@ -85,7 +85,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "socks";
mergeJsonObjects(object, commons->ExportToJson());
mergeJsonObjects(object, outbound::ExportToJson());
if (!username.isEmpty()) object["username"] = username;
if (!password.isEmpty()) object["password"] = password;
if (version == 4) object["version"] = "4";
@ -97,7 +97,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "socks";
mergeJsonObjects(object, commons->Build().object);
mergeJsonObjects(object, outbound::Build().object);
if (!username.isEmpty()) object["username"] = username;
if (!password.isEmpty()) object["password"] = password;
if (version == 4) object["version"] = "4";

View File

@ -13,7 +13,7 @@ namespace Configs {
if (!url.isValid()) return false;
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
commons->ParseFromLink(link);
outbound::ParseFromLink(link);
if (query.hasQueryItem("user")) user = query.queryItemValue("user");
if (query.hasQueryItem("password")) password = query.queryItemValue("password");
@ -43,13 +43,13 @@ namespace Configs {
if (query.hasQueryItem("client_version")) client_version = query.queryItemValue("client_version");
return !commons->server.isEmpty();
return !server.isEmpty();
}
bool ssh::ParseFromJson(const QJsonObject& object)
{
if (object.isEmpty() || object["type"].toString() != "ssh") return false;
commons->ParseFromJson(object);
outbound::ParseFromJson(object);
if (object.contains("user")) user = object["user"].toString();
if (object.contains("password")) password = object["password"].toString();
if (object.contains("private_key")) private_key = object["private_key"].toString();
@ -70,9 +70,9 @@ namespace Configs {
QUrl url;
QUrlQuery query;
url.setScheme("ssh");
url.setHost(commons->server);
url.setPort(commons->server_port);
if (!commons->name.isEmpty()) url.setFragment(commons->name);
url.setHost(server);
url.setPort(server_port);
if (!name.isEmpty()) url.setFragment(name);
if (!user.isEmpty()) query.addQueryItem("user", user);
if (!password.isEmpty()) query.addQueryItem("password", password);
@ -100,7 +100,7 @@ namespace Configs {
if (!client_version.isEmpty()) query.addQueryItem("client_version", client_version);
mergeUrlQuery(query, commons->ExportToLink());
mergeUrlQuery(query, outbound::ExportToLink());
if (!query.isEmpty()) url.setQuery(query);
return url.toString();
@ -110,7 +110,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "ssh";
mergeJsonObjects(object, commons->ExportToJson());
mergeJsonObjects(object, outbound::ExportToJson());
if (!user.isEmpty()) object["user"] = user;
if (!password.isEmpty()) object["password"] = password;
if (!private_key.isEmpty()) object["private_key"] = private_key;
@ -126,7 +126,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "ssh";
mergeJsonObjects(object, commons->Build().object);
mergeJsonObjects(object, outbound::Build().object);
if (!user.isEmpty()) object["user"] = user;
if (!password.isEmpty()) object["password"] = password;
if (!private_key.isEmpty()) object["private_key"] = private_key;

View File

@ -13,7 +13,7 @@ namespace Configs {
if (!url.isValid()) return false;
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
commons->ParseFromLink(link);
outbound::ParseFromLink(link);
if (query.hasQueryItem("state_directory")) state_directory = QUrl::fromPercentEncoding(query.queryItemValue("state_directory").toUtf8());
if (query.hasQueryItem("auth_key")) auth_key = QUrl::fromPercentEncoding(query.queryItemValue("auth_key").toUtf8());
@ -36,7 +36,7 @@ namespace Configs {
bool tailscale::ParseFromJson(const QJsonObject& object)
{
if (object.isEmpty() || object["type"].toString() != "tailscale") return false;
commons->ParseFromJson(object);
outbound::ParseFromJson(object);
if (object.contains("state_directory")) state_directory = object["state_directory"].toString();
if (object.contains("auth_key")) auth_key = object["auth_key"].toString();
if (object.contains("control_url")) control_url = object["control_url"].toString();
@ -59,7 +59,7 @@ namespace Configs {
QUrlQuery query;
url.setScheme("ts");
url.setHost("tailscale");
if (!commons->name.isEmpty()) url.setFragment(commons->name);
if (!name.isEmpty()) url.setFragment(name);
if (!state_directory.isEmpty()) query.addQueryItem("state_directory", QUrl::toPercentEncoding(state_directory));
if (!auth_key.isEmpty()) query.addQueryItem("auth_key", QUrl::toPercentEncoding(auth_key));
@ -81,7 +81,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "tailscale";
mergeJsonObjects(object, commons->ExportToJson());
object["tag"] = name;
if (!state_directory.isEmpty()) object["state_directory"] = state_directory;
if (!auth_key.isEmpty()) object["auth_key"] = auth_key;
if (!control_url.isEmpty()) object["control_url"] = control_url;
@ -100,7 +100,6 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "tailscale";
mergeJsonObjects(object, commons->Build().object);
if (!state_directory.isEmpty()) object["state_directory"] = state_directory;
if (!auth_key.isEmpty()) object["auth_key"] = auth_key;
if (!control_url.isEmpty()) object["control_url"] = control_url;

View File

@ -11,7 +11,7 @@ namespace Configs {
auto url = QUrl(link);
if (!url.isValid()) return false;
commons->ParseFromLink(link);
outbound::ParseFromLink(link);
password = url.userName();
tls->ParseFromLink(link);
transport->ParseFromLink(link);
@ -21,7 +21,7 @@ namespace Configs {
bool Trojan::ParseFromJson(const QJsonObject& object)
{
if (object.isEmpty() || object["type"].toString() != "trojan") return false;
commons->ParseFromJson(object);
outbound::ParseFromJson(object);
if (object.contains("password")) password = object["password"].toString();
if (object.contains("tls")) tls->ParseFromJson(object["tls"].toObject());
if (object.contains("transport")) transport->ParseFromJson(object["transport"].toObject());
@ -32,10 +32,10 @@ namespace Configs {
{
QUrl url;
QUrlQuery query;
url.setHost(commons->server);
url.setPort(commons->server_port);
url.setHost(server);
url.setPort(server_port);
url.setScheme("trojan");
if (!commons->name.isEmpty()) url.setFragment(commons->name);
if (!name.isEmpty()) url.setFragment(name);
url.setUserName(password);
if (tls->enabled) mergeUrlQuery(query, tls->ExportToLink());
if (!transport->type.isEmpty()) mergeUrlQuery(query, transport->ExportToLink());
@ -47,7 +47,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "trojan";
mergeJsonObjects(object, commons->ExportToJson());
mergeJsonObjects(object, outbound::ExportToJson());
if (!password.isEmpty()) object["password"] = password;
if (tls->enabled) object["tls"] = tls->ExportToJson();
if (!transport->type.isEmpty()) object["transport"] = transport->ExportToJson();
@ -58,7 +58,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "trojan";
mergeJsonObjects(object, commons->Build().object);
mergeJsonObjects(object, outbound::Build().object);
if (!password.isEmpty()) object["password"] = password;
if (tls->enabled) object["tls"] = tls->Build().object;
if (!transport->type.isEmpty()) object["transport"] = transport->Build().object;

View File

@ -12,7 +12,7 @@ namespace Configs {
if (!url.isValid()) return false;
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
commons->ParseFromLink(link);
outbound::ParseFromLink(link);
uuid = url.userName();
password = url.password();
@ -24,15 +24,15 @@ namespace Configs {
tls->ParseFromLink(link);
if (commons->server_port == 0) commons->server_port = 443;
if (server_port == 0) server_port = 443;
return !(uuid.isEmpty() || password.isEmpty() || commons->server.isEmpty());
return !(uuid.isEmpty() || password.isEmpty() || server.isEmpty());
}
bool tuic::ParseFromJson(const QJsonObject& object)
{
if (object.isEmpty() || object["type"].toString() != "tuic") return false;
commons->ParseFromJson(object);
outbound::ParseFromJson(object);
if (object.contains("uuid")) uuid = object["uuid"].toString();
if (object.contains("password")) password = object["password"].toString();
if (object.contains("congestion_control")) congestion_control = object["congestion_control"].toString();
@ -51,9 +51,9 @@ namespace Configs {
url.setScheme("tuic");
url.setUserName(uuid);
url.setPassword(password);
url.setHost(commons->server);
url.setPort(commons->server_port);
if (!commons->name.isEmpty()) url.setFragment(commons->name);
url.setHost(server);
url.setPort(server_port);
if (!name.isEmpty()) url.setFragment(name);
if (!congestion_control.isEmpty()) query.addQueryItem("congestion_control", congestion_control);
if (!udp_relay_mode.isEmpty()) query.addQueryItem("udp_relay_mode", udp_relay_mode);
@ -62,7 +62,7 @@ namespace Configs {
if (!heartbeat.isEmpty()) query.addQueryItem("heartbeat", heartbeat);
mergeUrlQuery(query, tls->ExportToLink());
mergeUrlQuery(query, commons->ExportToLink());
mergeUrlQuery(query, outbound::ExportToLink());
if (!query.isEmpty()) url.setQuery(query);
return url.toString();
@ -72,7 +72,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "tuic";
mergeJsonObjects(object, commons->ExportToJson());
mergeJsonObjects(object, outbound::ExportToJson());
if (!uuid.isEmpty()) object["uuid"] = uuid;
if (!password.isEmpty()) object["password"] = password;
if (!congestion_control.isEmpty()) object["congestion_control"] = congestion_control;
@ -88,7 +88,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "tuic";
mergeJsonObjects(object, commons->Build().object);
mergeJsonObjects(object, outbound::Build().object);
if (!uuid.isEmpty()) object["uuid"] = uuid;
if (!password.isEmpty()) object["password"] = password;
if (!congestion_control.isEmpty()) object["congestion_control"] = congestion_control;

View File

@ -12,9 +12,9 @@ namespace Configs {
if (!url.isValid()) return false;
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
commons->ParseFromLink(link);
outbound::ParseFromLink(link);
uuid = url.userName();
if (commons->server_port == 0) commons->server_port = 443;
if (server_port == 0) server_port = 443;
flow = GetQueryValue(query, "flow", "");
@ -28,13 +28,13 @@ namespace Configs {
packet_encoding = GetQueryValue(query, "packetEncoding", "");
multiplex->ParseFromLink(link);
return !(uuid.isEmpty() || commons->server.isEmpty());
return !(uuid.isEmpty() || server.isEmpty());
}
bool vless::ParseFromJson(const QJsonObject& object)
{
if (object.isEmpty() || object["type"].toString() != "vless") return false;
commons->ParseFromJson(object);
outbound::ParseFromJson(object);
if (object.contains("uuid")) uuid = object["uuid"].toString();
if (object.contains("flow")) flow = object["flow"].toString();
if (object.contains("packet_encoding")) packet_encoding = object["packet_encoding"].toString();
@ -50,9 +50,9 @@ namespace Configs {
QUrlQuery query;
url.setScheme("vless");
url.setUserName(uuid);
url.setHost(commons->server);
url.setPort(commons->server_port);
if (!commons->name.isEmpty()) url.setFragment(commons->name);
url.setHost(server);
url.setPort(server_port);
if (!name.isEmpty()) url.setFragment(name);
query.addQueryItem("encryption", "none");
if (!flow.isEmpty()) query.addQueryItem("flow", flow);
@ -71,7 +71,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "vless";
mergeJsonObjects(object, commons->ExportToJson());
mergeJsonObjects(object, outbound::ExportToJson());
if (!uuid.isEmpty()) object["uuid"] = uuid;
if (!flow.isEmpty()) object["flow"] = flow;
if (!packet_encoding.isEmpty()) object["packet_encoding"] = packet_encoding;
@ -85,7 +85,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "vless";
mergeJsonObjects(object, commons->Build().object);
mergeJsonObjects(object, outbound::Build().object);
if (!uuid.isEmpty()) object["uuid"] = uuid;
if (!flow.isEmpty()) object["flow"] = flow;
if (!packet_encoding.isEmpty()) object["packet_encoding"] = packet_encoding;

View File

@ -14,9 +14,9 @@ namespace Configs {
auto objN = QString2QJsonObject(linkN);
if (!objN.isEmpty()) {
uuid = objN["id"].toString();
commons->server = objN["add"].toString();
commons->server_port = objN["port"].toVariant().toInt();
commons->name = objN["ps"].toString();
server = objN["add"].toString();
server_port = objN["port"].toVariant().toInt();
name = objN["ps"].toString();
alter_id = objN["aid"].toVariant().toInt();
QString net = objN["net"].toString();
@ -34,7 +34,7 @@ namespace Configs {
tls->server_name = objN["sni"].toString();
}
return !(uuid.isEmpty() || commons->server.isEmpty());
return !(uuid.isEmpty() || server.isEmpty());
}
}
@ -43,9 +43,9 @@ namespace Configs {
if (!url.isValid()) return false;
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
commons->ParseFromLink(link);
outbound::ParseFromLink(link);
uuid = url.userName();
if (commons->server_port == 0) commons->server_port = 443;
if (server_port == 0) server_port = 443;
security = GetQueryValue(query, "encryption", "auto");
@ -63,13 +63,13 @@ namespace Configs {
if (query.hasQueryItem("authenticatedLength")) authenticated_length = query.queryItemValue("authenticatedLength") == "true";
if (query.hasQueryItem("packetEncoding")) packet_encoding = query.queryItemValue("packetEncoding");
return !(uuid.isEmpty() || commons->server.isEmpty());
return !(uuid.isEmpty() || server.isEmpty());
}
bool vmess::ParseFromJson(const QJsonObject& object)
{
if (object.isEmpty() || object["type"].toString() != "vmess") return false;
commons->ParseFromJson(object);
outbound::ParseFromJson(object);
if (object.contains("uuid")) uuid = object["uuid"].toString();
if (object.contains("security")) security = object["security"].toString();
if (object.contains("alter_id")) alter_id = object["alter_id"].toInt();
@ -90,9 +90,9 @@ namespace Configs {
QUrlQuery query;
url.setScheme("vmess");
url.setUserName(uuid);
url.setHost(commons->server);
url.setPort(commons->server_port);
if (!commons->name.isEmpty()) url.setFragment(commons->name);
url.setHost(server);
url.setPort(server_port);
if (!name.isEmpty()) url.setFragment(name);
if (security != "auto") query.addQueryItem("encryption", security);
@ -113,7 +113,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "vmess";
mergeJsonObjects(object, commons->ExportToJson());
mergeJsonObjects(object, outbound::ExportToJson());
if (!uuid.isEmpty()) object["uuid"] = uuid;
if (security != "auto") object["security"] = security;
if (alter_id > 0) object["alter_id"] = alter_id;
@ -130,7 +130,7 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "vmess";
mergeJsonObjects(object, commons->Build().object);
mergeJsonObjects(object, outbound::Build().object);
if (!uuid.isEmpty()) object["uuid"] = uuid;
if (security != "auto") object["security"] = security;
if (alter_id > 0) object["alter_id"] = alter_id;

View File

@ -116,8 +116,8 @@ namespace Configs {
if (parts.size() >= 2) {
peer->address = parts[0].trimmed();
peer->port = parts.last().trimmed().toInt();
commons->server = peer->address;
commons->server_port = peer->port;
server = peer->address;
server_port = peer->port;
}
}
if (key == "S1") enable_amnezia = true, init_packet_junk_size = value.toInt();
@ -138,7 +138,7 @@ namespace Configs {
if (!url.isValid()) return false;
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
commons->ParseFromLink(link);
outbound::ParseFromLink(link);
if (query.hasQueryItem("private_key")) private_key = query.queryItemValue("private_key");
peer->ParseFromLink(link);
@ -166,13 +166,13 @@ namespace Configs {
if (query.hasQueryItem("transport_packet_magic_header")) transport_packet_magic_header = query.queryItemValue("transport_packet_magic_header").toInt();
}
return !(private_key.isEmpty() || peer->public_key.isEmpty() || commons->server.isEmpty());
return !(private_key.isEmpty() || peer->public_key.isEmpty() || server.isEmpty());
}
bool wireguard::ParseFromJson(const QJsonObject& object)
{
if (object.isEmpty() || object["type"].toString() != "wireguard") return false;
commons->ParseFromJson(object);
outbound::ParseFromJson(object);
if (object.contains("private_key")) private_key = object["private_key"].toString();
if (object.contains("peer") && object["peer"].isObject()) peer->ParseFromJson(object["peer"].toObject());
if (object.contains("address")) address = QJsonArray2QListString(object["address"].toArray());
@ -190,7 +190,7 @@ namespace Configs {
url.setScheme("wg");
url.setHost(peer->address);
url.setPort(peer->port);
if (!commons->name.isEmpty()) url.setFragment(commons->name);
if (!name.isEmpty()) url.setFragment(name);
if (!private_key.isEmpty()) query.addQueryItem("private_key", private_key);
@ -213,7 +213,7 @@ namespace Configs {
if (transport_packet_magic_header > 0) query.addQueryItem("transport_packet_magic_header", QString::number(transport_packet_magic_header));
}
mergeUrlQuery(query, commons->ExportToLink());
mergeUrlQuery(query, outbound::ExportToLink());
mergeUrlQuery(query, peer->ExportToLink());
if (!query.isEmpty()) url.setQuery(query);
@ -224,8 +224,8 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "wireguard";
if (!commons->name.isEmpty()) object["tag"] = commons->name;
mergeJsonObjects(object, commons->dialFields->ExportToJson());
if (!name.isEmpty()) object["tag"] = name;
mergeJsonObjects(object, dialFields->ExportToJson());
if (!private_key.isEmpty()) object["private_key"] = private_key;
if (!address.isEmpty()) object["address"] = QListStr2QJsonArray(address);
if (mtu > 0) object["mtu"] = mtu;
@ -245,8 +245,8 @@ namespace Configs {
{
QJsonObject object;
object["type"] = "wireguard";
if (!commons->name.isEmpty()) object["tag"] = commons->name;
mergeJsonObjects(object, commons->dialFields->Build().object);
if (!name.isEmpty()) object["tag"] = name;
mergeJsonObjects(object, dialFields->Build().object);
if (!private_key.isEmpty()) object["private_key"] = private_key;
if (!address.isEmpty()) object["address"] = QListStr2QJsonArray(address);
if (mtu > 0) object["mtu"] = mtu;

View File

@ -438,9 +438,9 @@ namespace Subscription {
bool needFix = false;
// common
ent->outbound->commons->name = Node2QString(proxy["name"]);
ent->outbound->commons->server = Node2QString(proxy["server"]);
ent->outbound->commons->server_port = Node2Int(proxy["port"]);
ent->outbound->name = Node2QString(proxy["name"]);
ent->outbound->server = Node2QString(proxy["server"]);
ent->outbound->server_port = Node2Int(proxy["port"]);
if (type_clash == "ss") {
auto bean = ent->ShadowSocks();
@ -810,8 +810,8 @@ namespace Subscription {
if (Node2Bool(proxy["udp-over-stream"])) bean->udp_over_stream = true;
if (!Node2QString(proxy["ip"]).isEmpty()) {
if (bean->tls->server_name.isEmpty()) bean->tls->server_name = bean->commons->server;
bean->commons->server = Node2QString(proxy["ip"]);
if (bean->tls->server_name.isEmpty()) bean->tls->server_name = bean->server;
bean->server = Node2QString(proxy["ip"]);
}
} else {
continue;

View File

@ -44,7 +44,7 @@ namespace Configs {
for (auto id: profilesIdOrder) {
auto ent = LoadProxyEntity(QString("profiles/%1.json").arg(id));
// Corrupted profile?
if (ent == nullptr || ent->bean == nullptr || ent->bean->version == -114514) {
if (ent == nullptr || ent->outbound == nullptr || ent->_bean->version == -114514) {
delProfile << id;
continue;
}
@ -121,7 +121,7 @@ namespace Configs {
{
if (ent->type == "chain")
{
auto bean = dynamic_cast<Configs::ChainBean*>(ent->bean.get());
auto bean = dynamic_cast<Configs::ChainBean*>(ent->_bean.get());
if (bean == nullptr)
{
qDebug() << "Broken state in migrate for chain";
@ -133,11 +133,11 @@ namespace Configs {
qDebug() << "Invalid state in migrate for chain";
return;
}
chain->commons->name = bean->name;
chain->name = bean->name;
chain->list = bean->list;
} else if (ent->type == "custom")
{
auto bean = dynamic_cast<Configs::CustomBean*>(ent->bean.get());
auto bean = dynamic_cast<Configs::CustomBean*>(ent->_bean.get());
if (bean == nullptr)
{
qDebug() << "Broken state in migrate for custom";
@ -149,12 +149,12 @@ namespace Configs {
qDebug() << "Invalid state in migrate for custom";
return;
}
custom->commons->name = bean->name;
custom->name = bean->name;
custom->config = bean->config_simple;
custom->type = bean->core == "internal" ? "outbound" : "fullconfig";
} else if (ent->type == "extracore")
{
auto bean = dynamic_cast<Configs::ExtraCoreBean*>(ent->bean.get());
auto bean = dynamic_cast<Configs::ExtraCoreBean*>(ent->_bean.get());
if (bean == nullptr)
{
qDebug() << "Broken state in migrate for extracore";
@ -166,7 +166,7 @@ namespace Configs {
qDebug() << "Invalid state in migrate for extracore";
return;
}
extraCore->commons->name = bean->name;
extraCore->name = bean->name;
extraCore->socksAddress = bean->socksAddress;
extraCore->socksPort = bean->socksPort;
extraCore->extraCorePath = bean->extraCorePath;
@ -175,13 +175,13 @@ namespace Configs {
extraCore->noLogs = bean->noLogs;
} else
{
auto beanJson = ent->bean->BuildCoreObjSingBox();
auto beanJson = ent->_bean->BuildCoreObjSingBox();
auto obj = beanJson.outbound;
if (ent->bean->mux_state == 0) obj["multiplex"] = QJsonObject{};
else if (ent->bean->mux_state == 1) obj["multiplex"] = QJsonObject{{"enabled", true}};
else if (ent->bean->mux_state == 2) obj["multiplex"] = QJsonObject{{"enabled", false}};
if (ent->_bean->mux_state == 0) obj["multiplex"] = QJsonObject{};
else if (ent->_bean->mux_state == 1) obj["multiplex"] = QJsonObject{{"enabled", true}};
else if (ent->_bean->mux_state == 2) obj["multiplex"] = QJsonObject{{"enabled", false}};
ent->outbound->ParseFromJson(obj);
ent->outbound->commons->name = ent->bean->name;
ent->outbound->name = ent->_bean->name;
}
}
@ -198,7 +198,7 @@ namespace Configs {
if (validType) {
ent = NewProxyEntity(type);
validType = ent->bean->version != -114514;
validType = ent->_bean->version != -114514;
}
if (validType) {

View File

@ -4,8 +4,8 @@ namespace Configs {
QString ProfileFilter_ent_key(const std::shared_ptr<Configs::ProxyEntity> &ent, bool by_address) {
by_address &= ent->type != "custom";
return by_address ? (ent->bean->DisplayAddress() + ent->bean->DisplayType())
: QJsonObject2QString(ent->bean->ToJson({"c_cfg", "c_out"}), true) + ent->bean->DisplayType();
return by_address ? (ent->outbound->DisplayAddress() + ent->outbound->DisplayType())
: QJsonObject2QString(ent->outbound->ToJson({"c_cfg", "c_out"}), true) + ent->outbound->DisplayType();
}
void ProfileFilter::Uniq(const QList<std::shared_ptr<ProxyEntity>> &in,

View File

@ -16,7 +16,7 @@ namespace Configs
_add(new configItem("country", &test_country, itemType::string));
if (bean != nullptr) {
this->bean = std::shared_ptr<Configs::AbstractBean>(bean);
this->_bean = std::shared_ptr<Configs::AbstractBean>(bean);
_add(new configItem("bean", dynamic_cast<JsonStore *>(bean), itemType::jsonStore));
}

View File

@ -49,6 +49,13 @@ QByteArray DecodeB64IfValid(const QString &input, QByteArray::Base64Options opti
return {};
}
QStringList SplitAndTrim(QString raw, QString separator) {
QStringList result;
auto spl = raw.split(separator);
for (auto str : spl) result << str.trimmed();
return result;
}
QString QStringList2Command(const QStringList &list) {
QStringList new_list;
for (auto str: list) {

View File

@ -578,7 +578,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
auto selected = get_now_selected_list();
if (!selected.isEmpty()) {
auto ent = selected.first();
name = ent->bean->DisplayCoreType();
name = software_core_name;
}
ui->menu_export_config->setVisible(name == software_core_name);
ui->menu_export_config->setText(tr("Export %1 config").arg(name));
@ -1342,7 +1342,7 @@ QList<std::shared_ptr<Configs::ProxyEntity>> MainWindow::filterProfilesList(cons
MW_show_log("Null profile, maybe data is corrupted");
continue;
}
if (searchString.isEmpty() || profile->bean->name.contains(searchString, Qt::CaseInsensitive) || profile->bean->serverAddress.contains(searchString, Qt::CaseInsensitive)
if (searchString.isEmpty() || profile->outbound->name.contains(searchString, Qt::CaseInsensitive) || profile->outbound->server.contains(searchString, Qt::CaseInsensitive)
|| (searchString.startsWith("CODE:") && searchString.mid(5) == profile->test_country))
res.append(profile);
}
@ -1382,7 +1382,7 @@ void MainWindow::refresh_status(const QString &traffic_update) {
}
if (QDateTime::currentSecsSinceEpoch() - last_test_time > 2) {
ui->label_running->setText(running ? QString("[%1] %2").arg(group_name, running->bean->DisplayName()).left(30) : tr("Not Running"));
ui->label_running->setText(running ? QString("[%1] %2").arg(group_name, running->outbound->DisplayName()).left(30) : tr("Not Running"));
}
//
auto display_socks = DisplayAddress(Configs::dataStore->inbound_address, Configs::dataStore->inbound_socks_port);
@ -1411,7 +1411,7 @@ void MainWindow::refresh_status(const QString &traffic_update) {
if (!Configs::dataStore->active_routing.isEmpty() && Configs::dataStore->active_routing != "Default") {
tt << "[" + Configs::dataStore->active_routing + "]";
}
if (running != nullptr) tt << running->bean->DisplayTypeAndName() + "@" + group_name;
if (running != nullptr) tt << running->outbound->DisplayTypeAndName() + "@" + group_name;
return tt.join(isTray ? "\n" : " ");
};
@ -1527,14 +1527,14 @@ void MainWindow::refresh_proxy_list_impl(const int &id, GroupSortAction groupSor
QString ms_a;
QString ms_b;
if (groupSortAction.method == GroupSortMethod::ByType) {
ms_a = Configs::profileManager->GetProfile(a)->bean->DisplayType();
ms_b = Configs::profileManager->GetProfile(b)->bean->DisplayType();
ms_a = Configs::profileManager->GetProfile(a)->outbound->DisplayType();
ms_b = Configs::profileManager->GetProfile(b)->outbound->DisplayType();
} else if (groupSortAction.method == GroupSortMethod::ByName) {
ms_a = Configs::profileManager->GetProfile(a)->bean->name;
ms_b = Configs::profileManager->GetProfile(b)->bean->name;
ms_a = Configs::profileManager->GetProfile(a)->outbound->name;
ms_b = Configs::profileManager->GetProfile(b)->outbound->name;
} else if (groupSortAction.method == GroupSortMethod::ByAddress) {
ms_a = Configs::profileManager->GetProfile(a)->bean->DisplayAddress();
ms_b = Configs::profileManager->GetProfile(b)->bean->DisplayAddress();
ms_a = Configs::profileManager->GetProfile(a)->outbound->DisplayAddress();
ms_b = Configs::profileManager->GetProfile(b)->outbound->DisplayAddress();
} else if (groupSortAction.method == GroupSortMethod::ByLatency) {
ms_a = Configs::profileManager->GetProfile(a)->full_test_report;
ms_b = Configs::profileManager->GetProfile(b)->full_test_report;
@ -1621,19 +1621,19 @@ void MainWindow::refresh_table_item(const int row, const std::shared_ptr<Configs
// C0: Type
auto f = f0->clone();
f->setText(profile->bean->DisplayType());
f->setText(profile->outbound->DisplayType());
if (isRunning) f->setForeground(palette().link());
ui->proxyListTable->setItem(row, 0, f);
// C1: Address+Port
f = f0->clone();
f->setText(profile->bean->DisplayAddress());
f->setText(profile->outbound->DisplayAddress());
if (isRunning) f->setForeground(palette().link());
ui->proxyListTable->setItem(row, 1, f);
// C2: Name
f = f0->clone();
f->setText(profile->bean->name);
f->setText(profile->outbound->name);
if (isRunning) f->setForeground(palette().link());
ui->proxyListTable->setItem(row, 2, f);
@ -1678,6 +1678,7 @@ void MainWindow::on_menu_add_from_clipboard_triggered() {
Subscription::groupUpdater->AsyncUpdate(clipboard);
}
// TODO fix full export
void MainWindow::on_menu_clone_triggered() {
auto ents = get_now_selected_list();
if (ents.isEmpty()) return;
@ -1687,7 +1688,7 @@ void MainWindow::on_menu_clone_triggered() {
QStringList sls;
for (const auto &ent: ents) {
sls << ent->bean->ToNekorayShareLink(ent->type);
sls << ent->outbound->ExportToLink();
}
Subscription::groupUpdater->AsyncUpdate(sls.join("\n"));
@ -1703,7 +1704,7 @@ void MainWindow::on_menu_delete_repeat_triggered () {
int remove_display_count = 0 ;
QString remove_display;
for ( const auto &ent: out_del) {
remove_display += ent-> bean -> DisplayTypeAndName () + " \n " ;
remove_display += ent-> outbound -> DisplayTypeAndName () + " \n " ;
if (++remove_display_count == 20 ) {
remove_display += " ... " ;
break ;
@ -1753,7 +1754,7 @@ void MainWindow::on_menu_copy_links_triggered() {
auto ents = get_now_selected_list();
QStringList links;
for (const auto &ent: ents) {
links += ent->bean->ToShareLink();
links += ent->outbound->ExportToLink();
}
if (links.length() == 0) return;
QApplication::clipboard()->setText(links.join("\n"));
@ -1764,7 +1765,7 @@ void MainWindow::on_menu_copy_links_nkr_triggered() {
auto ents = get_now_selected_list();
QStringList links;
for (const auto &ent: ents) {
links += ent->bean->ToNekorayShareLink(ent->type);
links += ent->outbound->ExportToLink();
}
if (links.length() == 0) return;
QApplication::clipboard()->setText(links.join("\n"));
@ -1775,7 +1776,6 @@ void MainWindow::on_menu_export_config_triggered() {
auto ents = get_now_selected_list();
if (ents.count() != 1) return;
auto ent = ents.first();
if (ent->bean->DisplayCoreType() != software_core_name) return;
auto result = Configs::BuildSingBoxConfig(ent);
QString config_core = QJsonObject2QString(result->coreConfig, true);
@ -1875,10 +1875,10 @@ void MainWindow::display_qr_link(bool nkrFormat) {
}
};
auto link = ents.first()->bean->ToShareLink();
auto link_nk = ents.first()->bean->ToNekorayShareLink(ents.first()->type);
auto link = ents.first()->outbound->ExportToLink();
auto link_nk = ents.first()->outbound->ExportToLink();
auto w = new W(link, link_nk);
w->setWindowTitle(ents.first()->bean->DisplayTypeAndName());
w->setWindowTitle(ents.first()->outbound->DisplayTypeAndName());
w->exec();
w->deleteLater();
}
@ -2029,7 +2029,7 @@ void MainWindow::on_menu_remove_unavailable_triggered() {
int remove_display_count = 0;
QString remove_display;
for (const auto &ent: out_del) {
remove_display += ent->bean->DisplayTypeAndName() + "\n";
remove_display += ent->outbound->DisplayTypeAndName() + "\n";
if (++remove_display_count == 20) {
remove_display += "...";
break;
@ -2077,7 +2077,7 @@ void MainWindow::on_menu_remove_invalid_triggered() {
int remove_display_count = 0;
QString remove_display;
for (const auto &ent: out_del) {
remove_display += ent->bean->DisplayTypeAndName() + "\n";
remove_display += ent->outbound->DisplayTypeAndName() + "\n";
if (++remove_display_count == 20) {
remove_display += "...";
break;
@ -2109,7 +2109,7 @@ void MainWindow::on_menu_resolve_selected_triggered() {
Configs::dataStore->resolve_count = profiles.count();
for (const auto &profile: profiles) {
profile->bean->ResolveDomainToIP([=,this] {
profile->outbound->ResolveDomainToIP([=,this] {
profile->Save();
if (--Configs::dataStore->resolve_count != 0) return;
refresh_proxy_list();
@ -2137,7 +2137,7 @@ void MainWindow::on_menu_resolve_domain_triggered() {
for (const auto id: profiles) {
auto profile = Configs::profileManager->GetProfile(id);
profile->bean->ResolveDomainToIP([=,this] {
profile->outbound->ResolveDomainToIP([=,this] {
profile->Save();
if (--Configs::dataStore->resolve_count != 0) return;
refresh_proxy_list();

View File

@ -1,11 +1,10 @@
#include "include/ui/profile/dialog_edit_profile.h"
#include "include/ui/profile/edit_socks_http.h"
#include "include/ui/profile/edit_http.h"
#include "include/ui/profile/edit_shadowsocks.h"
#include "include/ui/profile/edit_chain.h"
#include "include/ui/profile/edit_vmess.h"
#include "include/ui/profile/edit_trojan_vless.h"
#include "include/ui/profile/edit_quic.h"
#include "include/ui/profile/edit_vless.h"
#include "include/ui/profile/edit_anytls.h"
#include "include/ui/profile/edit_wireguard.h"
#include "include/ui/profile/edit_tailscale.h"
@ -21,8 +20,14 @@
#include <QInputDialog>
#include "include/ui/profile/edit_hysteria.h"
#include "include/ui/profile/edit_hysteria2.h"
#include "include/ui/profile/edit_socks.h"
#include "include/ui/profile/edit_trojan.h"
#include "include/ui/profile/edit_tuic.h"
#define ADJUST_SIZE runOnThread([=,this] { adjustSize(); adjustPosition(mainwindow); }, this);
#define LOAD_TYPE(a) ui->type->addItem(Configs::ProfileManager::NewProxyEntity(a)->bean->DisplayType(), a);
#define LOAD_TYPE(a) ui->type->addItem(Configs::ProfileManager::NewProxyEntity(a)->outbound->DisplayType(), a);
DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId, QWidget *parent)
: QDialog(parent), ui(new Ui::DialogEditProfile) {
@ -140,7 +145,6 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
}
});
// 确定模式和 ent
newEnt = _type != "";
if (newEnt) {
this->groupId = profileOrGroupId;
@ -169,8 +173,6 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
connect(ui->type, &QComboBox::currentIndexChanged, this, [=,this](int index) {
typeSelected(ui->type->itemData(index).toString());
});
ui->apply_to_group->hide();
} else {
this->ent = Configs::profileManager->GetProfile(profileOrGroupId);
if (this->ent == nullptr) return;
@ -191,8 +193,12 @@ void DialogEditProfile::typeSelected(const QString &newType) {
type = newType;
bool validType = true;
if (type == "socks" || type == "http") {
auto _innerWidget = new EditSocksHttp(this);
if (type == "http") {
auto _innerWidget = new EditHttp(this);
innerWidget = _innerWidget;
innerEditor = _innerWidget;
} else if (type == "socks") {
auto _innerWidget = new EditSocks(this);
innerWidget = _innerWidget;
innerEditor = _innerWidget;
} else if (type == "shadowsocks") {
@ -207,11 +213,11 @@ void DialogEditProfile::typeSelected(const QString &newType) {
auto _innerWidget = new EditVMess(this);
innerWidget = _innerWidget;
innerEditor = _innerWidget;
} else if (type == "trojan" || type == "vless") {
auto _innerWidget = new EditTrojanVLESS(this);
} else if ( type == "vless") {
auto _innerWidget = new EditVless(this);
innerWidget = _innerWidget;
innerEditor = _innerWidget;
connect(_innerWidget->flow_, &QComboBox::currentTextChanged, _innerWidget, [=,this](const QString &txt)
connect(_innerWidget->_flow, &QComboBox::currentTextChanged, _innerWidget, [=,this](const QString &txt)
{
if (txt == "xtls-rprx-vision")
{
@ -221,8 +227,20 @@ void DialogEditProfile::typeSelected(const QString &newType) {
ui->multiplex->setDisabled(false);
}
});
} else if (type == "hysteria" || type == "hysteria2" || type == "tuic") {
auto _innerWidget = new EditQUIC(this);
} else if (type == "trojan") {
auto _innerWidget = new EditTrojan(this);
innerWidget = _innerWidget;
innerEditor = _innerWidget;
} else if (type == "hysteria") {
auto _innerWidget = new EditHysteria(this);
innerWidget = _innerWidget;
innerEditor = _innerWidget;
} else if (type == "hysteria2") {
auto _innerWidget = new EditHysteria2(this);
innerWidget = _innerWidget;
innerEditor = _innerWidget;
} else if (type == "tuic") {
auto _innerWidget = new EditTuic(this);
innerWidget = _innerWidget;
innerEditor = _innerWidget;
} else if (type == "anytls") {
@ -248,13 +266,11 @@ void DialogEditProfile::typeSelected(const QString &newType) {
customType = newEnt ? type : ent->Custom()->type;
_innerWidget->preset_core = customType;
type = "custom";
ui->apply_to_group->hide();
} else if (type == "extracore")
{
auto _innerWidget = new EditExtraCore(this);
innerWidget = _innerWidget;
innerEditor = _innerWidget;
ui->apply_to_group->hide();
} else {
validType = false;
}
@ -276,70 +292,50 @@ void DialogEditProfile::typeSelected(const QString &newType) {
ui->port->setVisible(showAddressPort);
ui->port_l->setVisible(showAddressPort);
// 右边 stream
auto stream = GetStreamSettings(ent->bean.get());
if (stream != nullptr) {
if (ent->outbound->HasTLS() || ent->outbound->HasTransport()) {
ui->right_all_w->setVisible(true);
ui->network->setCurrentText(stream->network);
ui->security->setCurrentText(stream->security);
ui->packet_encoding->setCurrentText(stream->packet_encoding);
ui->path->setText(stream->path);
ui->host->setText(stream->host);
ui->method->setText(stream->method);
ui->sni->setText(stream->sni);
ui->alpn->setText(stream->alpn);
auto tls = ent->outbound->GetTLS();
auto transport = ent->outbound->GetTransport();
ui->network->setCurrentText(transport->type);
ui->security->setCurrentText(tls->enabled ? "tls" : "");
ui->path->setText(transport->path);
ui->host->setText(transport->host);
ui->method->setText(transport->method);
ui->sni->setText(tls->server_name);
ui->alpn->setText(tls->alpn.join(","));
if (newEnt) {
ui->utlsFingerprint->setCurrentText(Configs::dataStore->utlsFingerprint);
} else {
ui->utlsFingerprint->setCurrentText(stream->utlsFingerprint);
ui->utlsFingerprint->setCurrentText(tls->utls->fingerPrint);
}
ui->tls_frag->setChecked(stream->enable_tls_fragment);
ui->tls_frag_fall_delay->setEnabled(stream->enable_tls_fragment);
ui->tls_frag_fall_delay->setText(stream->tls_fragment_fallback_delay);
ui->tls_rec_frag->setChecked(stream->enable_tls_record_fragment);
ui->insecure->setChecked(stream->allow_insecure);
ui->header_type->setCurrentText(stream->header_type);
ui->headers->setText(stream->headers);
ui->ws_early_data_name->setText(stream->ws_early_data_name);
ui->ws_early_data_length->setText(Int2String(stream->ws_early_data_length));
ui->reality_pbk->setText(stream->reality_pbk);
ui->reality_sid->setText(stream->reality_sid);
ui->multiplex->setCurrentIndex(ent->bean->mux_state);
ui->brutal_enable->setCheckState(ent->bean->enable_brutal ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
ui->brutal_speed->setText(Int2String(ent->bean->brutal_speed));
CACHE.certificate = stream->certificate;
ui->tls_frag->setChecked(tls->fragment);
ui->tls_frag_fall_delay->setEnabled(tls->fragment);
ui->tls_frag_fall_delay->setText(tls->fragment_fallback_delay);
ui->tls_rec_frag->setChecked(tls->record_fragment);
ui->insecure->setChecked(tls->insecure);
ui->headers->setText(transport->getHeadersString());
ui->ws_early_data_name->setText(transport->early_data_header_name);
ui->ws_early_data_length->setText(Int2String(transport->max_early_data));
ui->reality_pbk->setText(tls->reality->public_key);
ui->reality_sid->setText(tls->reality->short_id);
CACHE.certificate = tls->certificate;
} else {
ui->right_all_w->setVisible(false);
}
// left: custom
CACHE.custom_config = ent->bean->custom_config;
CACHE.custom_outbound = ent->bean->custom_outbound;
bool show_custom_config = true;
bool show_custom_outbound = true;
if (type == "chain") {
show_custom_outbound = false;
} else if (type == "custom") {
if (customType == "internal") {
show_custom_outbound = false;
} else if (customType == "internal-full") {
show_custom_outbound = false;
show_custom_config = false;
}
} else if (type == "extracore")
{
show_custom_outbound = false;
show_custom_config = false;
if (ent->outbound->HasMux()) {
auto mux = ent->outbound->GetMux();
ui->multiplex->setCurrentIndex(mux->getMuxState());
ui->brutal_enable->setChecked(mux->brutal->enabled);
ui->brutal_speed->setText(Int2String(mux->brutal->down_mbps));
}
ui->custom_box->setVisible(show_custom_outbound);
ui->custom_global_box->setVisible(show_custom_config);
// 左边 bean
auto old = ui->bean->layout()->itemAt(0)->widget();
ui->bean->layout()->removeWidget(old);
innerWidget->layout()->setContentsMargins(0, 0, 0, 0);
ui->bean->layout()->addWidget(innerWidget);
ui->bean->setTitle(ent->bean->DisplayType());
ui->bean->setTitle(ent->outbound->DisplayType());
delete old;
// 左边 bean inner editor
@ -351,22 +347,14 @@ void DialogEditProfile::typeSelected(const QString &newType) {
innerEditor->onStart(ent);
// 左边 common
ui->name->setText(ent->bean->name);
ui->address->setText(ent->bean->serverAddress);
ui->port->setText(Int2String(ent->bean->serverPort));
ui->name->setText(ent->outbound->name);
ui->address->setText(ent->outbound->server);
ui->port->setText(Int2String(ent->outbound->server_port));
ui->port->setValidator(QRegExpValidator_Number);
// 星号
ADD_ASTERISK(this)
if (type == "vmess" || type == "vless") {
ui->packet_encoding->setVisible(true);
ui->packet_encoding_l->setVisible(true);
} else {
ui->packet_encoding->setVisible(false);
ui->packet_encoding_l->setVisible(false);
}
if (type == "vmess" || type == "vless" || type == "trojan") {
if (ent->outbound->HasTransport()) {
ui->network_l->setVisible(true);
ui->network->setVisible(true);
ui->network_box->setVisible(true);
@ -375,14 +363,14 @@ void DialogEditProfile::typeSelected(const QString &newType) {
ui->network->setVisible(false);
ui->network_box->setVisible(false);
}
if (type == "vmess" || type == "vless" || type == "trojan" || type == "http" || type == "anytls") {
if (ent->outbound->HasTLS()) {
ui->security->setVisible(true);
ui->security_l->setVisible(true);
} else {
ui->security->setVisible(false);
ui->security_l->setVisible(false);
}
if (type == "vmess" || type == "vless" || type == "trojan" || type == "shadowsocks") {
if (ent->outbound->HasMux()) {
ui->multiplex->setVisible(true);
ui->multiplex_l->setVisible(true);
ui->brutal_box->setVisible(true);
@ -417,49 +405,39 @@ bool DialogEditProfile::onEnd() {
return false;
}
// 左边
ent->bean->name = ui->name->text();
ent->bean->serverAddress = ui->address->text().remove(' ');
ent->bean->serverPort = ui->port->text().toInt();
ent->outbound->name = ui->name->text();
ent->outbound->server = ui->address->text().remove(' ');
ent->outbound->server_port = ui->port->text().toInt();
// 右边 stream
auto stream = GetStreamSettings(ent->bean.get());
if (stream != nullptr) {
stream->network = ui->network->currentText();
stream->security = ui->security->currentText();
stream->packet_encoding = ui->packet_encoding->currentText();
stream->path = ui->path->text();
stream->host = ui->host->text();
stream->sni = ui->sni->text();
stream->alpn = ui->alpn->text();
stream->utlsFingerprint = ui->utlsFingerprint->currentText();
stream->enable_tls_fragment = ui->tls_frag->isChecked();
stream->tls_fragment_fallback_delay = ui->tls_frag_fall_delay->text();
stream->enable_tls_record_fragment = ui->tls_rec_frag->isChecked();
stream->allow_insecure = ui->insecure->isChecked();
stream->headers = ui->headers->text();
stream->header_type = ui->header_type->currentText();
stream->method = ui->method->text();
stream->ws_early_data_name = ui->ws_early_data_name->text();
stream->ws_early_data_length = ui->ws_early_data_length->text().toInt();
stream->reality_pbk = ui->reality_pbk->text();
stream->reality_sid = ui->reality_sid->text();
ent->bean->mux_state = ui->multiplex->currentIndex();
ent->bean->enable_brutal = ui->brutal_enable->isChecked();
ent->bean->brutal_speed = ui->brutal_speed->text().toInt();
stream->certificate = CACHE.certificate;
bool validHeaders;
stream->GetHeaderPairs(&validHeaders);
if (!validHeaders) {
MW_show_log("Headers are not valid");
return false;
}
if (ent->outbound->HasTLS() || ent->outbound->HasTransport()) {
auto tls = ent->outbound->GetTLS();
auto transport = ent->outbound->GetTransport();
transport->type = ui->network->currentText();
tls->enabled = ui->security->currentText() == "tls";
transport->path = ui->path->text();
transport->host = ui->host->text();
tls->server_name = ui->sni->text();
tls->alpn = SplitAndTrim(ui->alpn->text(), ",");
tls->utls->fingerPrint = ui->utlsFingerprint->currentText();
tls->utls->enabled = !tls->utls->fingerPrint.isEmpty();
tls->fragment = ui->tls_frag->isChecked();
tls->fragment_fallback_delay = ui->tls_frag_fall_delay->text();
tls->record_fragment = ui->tls_rec_frag->isChecked();
tls->insecure = ui->insecure->isChecked();
transport->headers = transport->getHeaderPairs(ui->headers->text());
transport->method = ui->method->text();
transport->early_data_header_name = ui->ws_early_data_name->text();
transport->max_early_data = ui->ws_early_data_length->text().toInt();
tls->reality->public_key = ui->reality_pbk->text();
tls->reality->short_id = ui->reality_sid->text();
tls->certificate = CACHE.certificate;
}
if (ent->outbound->HasMux()) {
auto mux = ent->outbound->GetMux();
mux->saveMuxState(ui->multiplex->currentIndex());
mux->brutal->enabled = ui->brutal_enable->isChecked();
mux->brutal->down_mbps = ui->brutal_speed->text().toInt();
}
// cached custom
ent->bean->custom_outbound = CACHE.custom_outbound;
ent->bean->custom_config = CACHE.custom_config;
return true;
}
@ -495,16 +473,6 @@ void DialogEditProfile::editor_cache_updated_impl() {
} else {
ui->certificate_edit->setText(tr("Already set"));
}
if (CACHE.custom_outbound.isEmpty()) {
ui->custom_outbound_edit->setText(tr("Not set"));
} else {
ui->custom_outbound_edit->setText(tr("Already set"));
}
if (CACHE.custom_config.isEmpty()) {
ui->custom_config_edit->setText(tr("Not set"));
} else {
ui->custom_config_edit->setText(tr("Already set"));
}
// CACHE macro
for (auto a: innerEditor->get_editor_cached()) {
@ -516,16 +484,6 @@ void DialogEditProfile::editor_cache_updated_impl() {
}
}
void DialogEditProfile::on_custom_outbound_edit_clicked() {
C_EDIT_JSON_ALLOW_EMPTY(custom_outbound)
editor_cache_updated_impl();
}
void DialogEditProfile::on_custom_config_edit_clicked() {
C_EDIT_JSON_ALLOW_EMPTY(custom_config)
editor_cache_updated_impl();
}
void DialogEditProfile::on_certificate_edit_clicked() {
bool ok;
auto txt = QInputDialog::getMultiLineText(this, tr("Certificate"), "", CACHE.certificate, &ok);
@ -534,91 +492,3 @@ void DialogEditProfile::on_certificate_edit_clicked() {
editor_cache_updated_impl();
}
}
void DialogEditProfile::on_apply_to_group_clicked() {
if (apply_to_group_ui.empty()) {
apply_to_group_ui[ui->multiplex] = new FloatCheckBox(ui->multiplex, this);
apply_to_group_ui[ui->sni] = new FloatCheckBox(ui->sni, this);
apply_to_group_ui[ui->alpn] = new FloatCheckBox(ui->alpn, this);
apply_to_group_ui[ui->host] = new FloatCheckBox(ui->host, this);
apply_to_group_ui[ui->path] = new FloatCheckBox(ui->path, this);
apply_to_group_ui[ui->utlsFingerprint] = new FloatCheckBox(ui->utlsFingerprint, this);
apply_to_group_ui[ui->insecure] = new FloatCheckBox(ui->insecure, this);
apply_to_group_ui[ui->certificate_edit] = new FloatCheckBox(ui->certificate_edit, this);
apply_to_group_ui[ui->custom_config_edit] = new FloatCheckBox(ui->custom_config_edit, this);
apply_to_group_ui[ui->custom_outbound_edit] = new FloatCheckBox(ui->custom_outbound_edit, this);
ui->apply_to_group->setText(tr("Confirm"));
} else {
auto group = Configs::profileManager->GetGroup(ent->gid);
if (group == nullptr) {
MessageBoxWarning("failed", "unknown group");
return;
}
// save this
if (onEnd()) {
ent->Save();
} else {
MessageBoxWarning("failed", "failed to save");
return;
}
// copy keys
for (const auto &pair: apply_to_group_ui) {
if (pair.second->isChecked()) {
do_apply_to_group(group, pair.first);
}
delete pair.second;
}
apply_to_group_ui.clear();
ui->apply_to_group->setText(tr("Apply settings to this group"));
}
}
void DialogEditProfile::do_apply_to_group(const std::shared_ptr<Configs::Group> &group, QWidget *key) {
auto stream = GetStreamSettings(ent->bean.get());
auto copyStream = [=,this](void *p) {
for (const auto &profile: group->GetProfileEnts()) {
auto newStream = GetStreamSettings(profile->bean.get());
if (newStream == nullptr) continue;
if (stream == newStream) continue;
newStream->_setValue(stream->_name(p), p);
// qDebug() << newStream->ToJsonBytes();
profile->Save();
}
};
auto copyBean = [=,this](void *p) {
for (const auto &profile: group->GetProfileEnts()) {
if (profile == ent) continue;
profile->bean->_setValue(ent->bean->_name(p), p);
// qDebug() << profile->bean->ToJsonBytes();
profile->Save();
}
};
if (key == ui->multiplex) {
copyStream(&ent->bean->mux_state);
} else if (key == ui->brutal_enable) {
copyStream(&ent->bean->enable_brutal);
} else if (key == ui->brutal_speed) {
copyStream(&ent->bean->brutal_speed);
} else if (key == ui->sni) {
copyStream(&stream->sni);
} else if (key == ui->alpn) {
copyStream(&stream->alpn);
} else if (key == ui->host) {
copyStream(&stream->host);
} else if (key == ui->path) {
copyStream(&stream->path);
} else if (key == ui->utlsFingerprint) {
copyStream(&stream->utlsFingerprint);
} else if (key == ui->insecure) {
copyStream(&stream->allow_insecure);
} else if (key == ui->certificate_edit) {
copyStream(&stream->certificate);
} else if (key == ui->custom_config_edit) {
copyBean(&ent->bean->custom_config);
} else if (key == ui->custom_outbound_edit) {
copyBean(&ent->bean->custom_outbound);
}
}

View File

@ -1,7 +1,5 @@
#include "include/ui/profile/edit_anytls.h"
#include "include/configs/proxy/AnyTLSBean.hpp"
#include <QUuid>
#include <QRegularExpressionValidator>
#include "include/global/GuiUtils.hpp"
@ -19,21 +17,21 @@ EditAnyTLS::~EditAnyTLS() {
void EditAnyTLS::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
this->ent = _ent;
auto bean = this->ent->AnyTLS();
auto outbound = this->ent->AnyTLS();
ui->password->setText(bean->password);
ui->interval->setText(bean->idle_session_check_interval);
ui->timeout->setText(bean->idle_session_timeout);
ui->min->setText(Int2String(bean->min_idle_session));
ui->password->setText(outbound->password);
ui->interval->setText(outbound->idle_session_check_interval);
ui->timeout->setText(outbound->idle_session_timeout);
ui->min->setText(Int2String(outbound->min_idle_session));
}
bool EditAnyTLS::onEnd() {
auto bean = this->ent->AnyTLS();
auto outbound = this->ent->AnyTLS();
bean->password = ui->password->text();
bean->idle_session_check_interval = ui->interval->text();
bean->idle_session_timeout = ui->timeout->text();
bean->min_idle_session = ui->min->text().toInt();
outbound->password = ui->password->text();
outbound->idle_session_check_interval = ui->interval->text();
outbound->idle_session_timeout = ui->timeout->text();
outbound->min_idle_session = ui->min->text().toInt();
return true;
}

View File

@ -4,7 +4,6 @@
#include "include/ui/profile/ProxyItem.h"
#include "include/dataStore/Database.hpp"
#include "include/configs/proxy/ChainBean.hpp"
EditChain::EditChain(QWidget *parent) : QWidget(parent), ui(new Ui::EditChain) {
ui->setupUi(this);
@ -16,9 +15,9 @@ EditChain::~EditChain() {
void EditChain::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
this->ent = _ent;
auto bean = this->ent->Chain();
auto outbound = this->ent->Chain();
for (auto id: bean->list) {
for (auto id: outbound->list) {
AddProfileToListIfExist(id);
}
}
@ -29,13 +28,13 @@ bool EditChain::onEnd() {
return false;
}
auto bean = this->ent->Chain();
auto outbound = this->ent->Chain();
QList<int> idList;
for (int i = 0; i < ui->listWidget->count(); i++) {
idList << ui->listWidget->item(i)->data(114514).toInt();
}
bean->list = idList;
outbound->list = idList;
return true;
}

View File

@ -23,7 +23,7 @@ EditCustom::~EditCustom() {
void EditCustom::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
this->ent = _ent;
auto bean = this->ent->Custom();
auto outbound = this->ent->Custom();
if (preset_core == "outbound") {
preset_command = preset_config = "";
@ -42,7 +42,7 @@ void EditCustom::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
}
// load core ui
ui->config_simple->setPlainText(bean->config);
ui->config_simple->setPlainText(outbound->config);
// custom internal
if (preset_core == "outbound") {
@ -60,10 +60,10 @@ bool EditCustom::onEnd() {
return false;
}
auto bean = this->ent->Custom();
auto outbound = this->ent->Custom();
bean->config = ui->config_simple->toPlainText();
bean->type = preset_core;
outbound->config = ui->config_simple->toPlainText();
outbound->type = preset_core;
return true;
}

View File

@ -18,14 +18,14 @@ EditExtraCore::~EditExtraCore() {
void EditExtraCore::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
this->ent = _ent;
auto bean = ent->ExtraCore();
ui->socks_address->setText(bean->socksAddress);
auto outbound = ent->ExtraCore();
ui->socks_address->setText(outbound->socksAddress);
ui->socks_port->setValidator(new QIntValidator(1, 65534));
ui->socks_port->setText(Int2String(bean->socksPort));
ui->config->setPlainText(bean->extraCoreConf);
ui->args->setText(bean->extraCoreArgs);
ui->socks_port->setText(Int2String(outbound->socksPort));
ui->config->setPlainText(outbound->extraCoreConf);
ui->args->setText(outbound->extraCoreArgs);
ui->path_combo->addItems(Configs::profileManager->GetExtraCorePaths());
ui->path_combo->setCurrentText(bean->extraCorePath);
ui->path_combo->setCurrentText(outbound->extraCorePath);
connect(ui->path_button, &QPushButton::pressed, this, [=,this]
{
@ -46,12 +46,12 @@ void EditExtraCore::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
}
bool EditExtraCore::onEnd() {
auto bean = ent->ExtraCore();
bean->socksAddress = ui->socks_address->text();
bean->socksPort = ui->socks_port->text().toInt();
bean->extraCoreConf = ui->config->toPlainText();
bean->extraCorePath = ui->path_combo->currentText();
bean->extraCoreArgs = ui->args->text();
auto outbound = ent->ExtraCore();
outbound->socksAddress = ui->socks_address->text();
outbound->socksPort = ui->socks_port->text().toInt();
outbound->extraCoreConf = ui->config->toPlainText();
outbound->extraCorePath = ui->path_combo->currentText();
outbound->extraCoreArgs = ui->args->text();
return true;
}

View File

@ -0,0 +1,25 @@
#include "include/ui/profile/edit_http.h"
EditHttp::EditHttp(QWidget *parent) : QWidget(parent),
ui(new Ui::EditHttp) {
ui->setupUi(this);
}
EditHttp::~EditHttp() {
delete ui;
}
void EditHttp::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
this->ent = _ent;
auto outbound = this->ent->Http();
ui->username->setText(outbound->username);
ui->password->setText(outbound->password);
}
bool EditHttp::onEnd() {
auto outbound = this->ent->Http();
outbound->username = ui->username->text();
outbound->password = ui->password->text();
return true;
}

View File

@ -0,0 +1,41 @@
#include "include/ui/profile/edit_hysteria.h"
EditHysteria::EditHysteria(QWidget *parent)
: QWidget(parent),
ui(new Ui::EditHysteria) {
ui->setupUi(this);
}
EditHysteria::~EditHysteria() {
delete ui;
}
void EditHysteria::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
this->ent = _ent;
auto outbound = _ent->Hysteria();
ui->server_ports->setText(outbound->server_ports.join(","));
ui->hop_interval->setText(outbound->hop_interval);
ui->up_mbps->setText(Int2String(outbound->up_mbps));
ui->down_mbps->setText(Int2String(outbound->down_mbps));
ui->obfs->setText(outbound->obfs);
ui->auth->setText(outbound->auth);
ui->auth_str->setText(outbound->auth_str);
ui->recv_window->setText(Int2String(outbound->recv_window));
ui->recv_window_conn->setText(Int2String(outbound->recv_window_conn));
}
bool EditHysteria::onEnd() {
auto outbound = ent->Hysteria();
outbound->server_ports = SplitAndTrim(ui->server_ports->text(), ",");
outbound->hop_interval = ui->hop_interval->text();
outbound->up_mbps = ui->up_mbps->text().toInt();
outbound->down_mbps = ui->down_mbps->text().toInt();
outbound->obfs = ui->obfs->text();
outbound->auth = ui->auth->text();
outbound->auth_str = ui->auth_str->text();
outbound->recv_window = ui->recv_window->text().toInt();
outbound->recv_window_conn = ui->recv_window_conn->text().toInt();
return true;
}

View File

@ -0,0 +1,35 @@
#include "include/ui/profile/edit_hysteria2.h"
EditHysteria2::EditHysteria2(QWidget *parent)
: QWidget(parent),
ui(new Ui::EditHysteria2) {
ui->setupUi(this);
}
EditHysteria2::~EditHysteria2() {
delete ui;
}
void EditHysteria2::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
this->ent = _ent;
auto outbound = this->ent->Hysteria2();
ui->server_ports->setText(outbound->server_ports.join(","));
ui->hop_interval->setText(outbound->hop_interval);
ui->up_mbps->setText(Int2String(outbound->up_mbps));
ui->down_mbps->setText(Int2String(outbound->down_mbps));
ui->obfs_password->setText(outbound->obfsPassword);
ui->password->setText(outbound->password);
}
bool EditHysteria2::onEnd() {
auto outbound = this->ent->Hysteria2();
outbound->server_ports = SplitAndTrim(ui->server_ports->text(), ",");
outbound->hop_interval = ui->hop_interval->text();
outbound->up_mbps = ui->up_mbps->text().toInt();
outbound->down_mbps = ui->down_mbps->text().toInt();
outbound->obfsPassword = ui->obfs_password->text();
outbound->password = ui->password->text();
return true;
}

View File

@ -1,154 +0,0 @@
#include "include/ui/profile/edit_quic.h"
#include "include/configs/proxy/QUICBean.hpp"
#include <QInputDialog>
#include <QUuid>
EditQUIC::EditQUIC(QWidget *parent) : QWidget(parent), ui(new Ui::EditQUIC) {
ui->setupUi(this);
connect(ui->uuidgen, &QPushButton::clicked, this, [=,this] { ui->uuid->setText(QUuid::createUuid().toString().remove("{").remove("}")); });
}
EditQUIC::~EditQUIC() {
delete ui;
}
void EditQUIC::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
// this->ent = _ent;
// auto bean = this->ent->QUICBean();
//
// P_LOAD_INT(uploadMbps);
// P_LOAD_INT(downloadMbps);
// P_LOAD_BOOL(disableMtuDiscovery)
// P_LOAD_STRING(obfsPassword);
// P_LOAD_STRING(authPayload);
// P_LOAD_INT(streamReceiveWindow);
// P_LOAD_INT(connectionReceiveWindow);
//
// P_LOAD_COMBO_INT(authPayloadType);
// P_LOAD_STRING(uuid);
// P_LOAD_STRING(password);
//
// P_LOAD_COMBO_STRING(congestionControl);
// P_LOAD_COMBO_STRING(udpRelayMode);
// P_LOAD_BOOL(zeroRttHandshake);
// P_LOAD_STRING(heartbeat);
// P_LOAD_BOOL(uos);
//
// // TLS
// P_LOAD_STRING(sni);
// P_LOAD_STRING(alpn);
// P_C_LOAD_STRING(caText);
// P_LOAD_BOOL(allowInsecure);
// P_LOAD_BOOL(disableSni);
//
// if (bean->proxy_type == Configs::QUICBean::proxy_Hysteria || bean->proxy_type == Configs::QUICBean::proxy_Hysteria2) {
// ui->uuid->hide();
// ui->uuid_l->hide();
// ui->uuidgen->hide();
// ui->congestionControl->hide();
// ui->congestionControl_l->hide();
// ui->udpRelayMode->hide();
// ui->udpRelayMode_l->hide();
// ui->zeroRttHandshake->hide();
// ui->heartbeat->hide();
// ui->heartbeat_l->hide();
// ui->uos->hide();
// ui->port_range->setText(bean->serverPorts.join(","));
// ui->hop_interval->setText(bean->hop_interval);
//
// if (bean->proxy_type == Configs::QUICBean::proxy_Hysteria) { // hy1
// ui->password->hide();
// ui->password_l->hide();
// } else { // hy2
// ui->authPayload->hide();
// ui->authPayload_l->hide();
// ui->authPayloadType->hide();
// ui->authPayloadType_l->hide();
// ui->alpn->hide();
// ui->alpn_l->hide();
// ui->TLS->removeItem(ui->alpn_sp);
// ui->disableMtuDiscovery->hide();
// ui->connectionReceiveWindow->hide();
// ui->connectionReceiveWindow_l->hide();
// ui->streamReceiveWindow->hide();
// ui->streamReceiveWindow_l->hide();
// }
// } else if (bean->proxy_type == Configs::QUICBean::proxy_TUIC) {
// ui->uploadMbps->hide();
// ui->uploadMbps_l->hide();
// ui->downloadMbps->hide();
// ui->downloadMbps_l->hide();
// ui->disableMtuDiscovery->hide();
// ui->obfsPassword->hide();
// ui->obfsPassword_l->hide();
// ui->authPayload->hide();
// ui->authPayload_l->hide();
// ui->authPayloadType->hide();
// ui->authPayloadType_l->hide();
// ui->streamReceiveWindow->hide();
// ui->streamReceiveWindow_l->hide();
// ui->connectionReceiveWindow->hide();
// ui->connectionReceiveWindow_l->hide();
// ui->port_range->hide();
// ui->port_range_l->hide();
// ui->hop_interval->hide();
// ui->hop_interval_l->hide();
// }
}
bool EditQUIC::onEnd() {
// auto bean = this->ent->QUICBean();
//
// // Hysteria
// P_SAVE_INT(uploadMbps);
// P_SAVE_INT(downloadMbps);
// P_SAVE_BOOL(disableMtuDiscovery)
// P_SAVE_STRING(obfsPassword);
// P_SAVE_COMBO_INT(authPayloadType);
// P_SAVE_STRING(authPayload);
// P_SAVE_INT(streamReceiveWindow);
// P_SAVE_INT(connectionReceiveWindow);
// auto rawPorts = ui->port_range->text();
// QStringList serverPorts;
// for (const auto& portRange : rawPorts.split(','))
// {
// if (portRange.trimmed().isEmpty()) continue;
// serverPorts.append(portRange.trimmed());
// }
// bean->serverPorts = serverPorts;
// bean->hop_interval = ui->hop_interval->text();
//
// // TUIC
// P_SAVE_STRING(uuid);
// P_SAVE_STRING(password);
// P_SAVE_COMBO_STRING(congestionControl);
// P_SAVE_COMBO_STRING(udpRelayMode);
// P_SAVE_BOOL(zeroRttHandshake);
// P_SAVE_STRING(heartbeat);
// P_SAVE_BOOL(uos);
//
// // TLS
// P_SAVE_STRING(sni);
// P_SAVE_STRING(alpn);
// P_SAVE_BOOL(allowInsecure);
// P_C_SAVE_STRING(caText);
// P_SAVE_BOOL(disableSni);
return true;
}
QList<QPair<QPushButton *, QString>> EditQUIC::get_editor_cached() {
return {
{ui->certificate, CACHE.caText},
};
}
void EditQUIC::on_certificate_clicked() {
bool ok;
auto txt = QInputDialog::getMultiLineText(this, tr("Certificate"), "", CACHE.caText, &ok);
if (ok) {
CACHE.caText = txt;
editor_cache_updated();
}
}

View File

@ -14,27 +14,27 @@ EditShadowSocks::~EditShadowSocks() {
void EditShadowSocks::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
this->ent = _ent;
auto bean = this->ent->ShadowSocks();
auto outbound = this->ent->ShadowSocks();
ui->method->setCurrentText(bean->method);
ui->uot->setCurrentIndex(bean->uot);
ui->password->setText(bean->password);
auto ssPlugin = bean->plugin.split(";");
ui->method->setCurrentText(outbound->method);
ui->uot->setCurrentIndex(outbound->uot);
ui->password->setText(outbound->password);
auto ssPlugin = outbound->plugin.split(";");
if (!ssPlugin.empty()) {
ui->plugin->setCurrentText(ssPlugin[0]);
ui->plugin_opts->setText(SubStrAfter(bean->plugin, ";"));
ui->plugin_opts->setText(SubStrAfter(outbound->plugin, ";"));
}
}
bool EditShadowSocks::onEnd() {
auto bean = this->ent->ShadowSocks();
auto outbound = this->ent->ShadowSocks();
bean->method = ui->method->currentText();
bean->password = ui->password->text();
bean->uot = ui->uot->currentIndex();
bean->plugin = ui->plugin->currentText();
if (!bean->plugin.isEmpty()) {
bean->plugin += ";" + ui->plugin_opts->text();
outbound->method = ui->method->currentText();
outbound->password = ui->password->text();
outbound->uot = ui->uot->currentIndex();
outbound->plugin = ui->plugin->currentText();
if (!outbound->plugin.isEmpty()) {
outbound->plugin += ";" + ui->plugin_opts->text();
}
return true;

View File

@ -0,0 +1,30 @@
#include "include/ui/profile/edit_socks.h"
EditSocks::EditSocks(QWidget *parent)
: QWidget(parent),
ui(new Ui::EditSocks) {
ui->setupUi(this);
}
EditSocks::~EditSocks() {
delete ui;
}
void EditSocks::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
this->ent = _ent;
auto outbound = this->ent->Socks();
ui->version->setCurrentText(Int2String(outbound->version));
ui->username->setText(outbound->username);
ui->password->setText(outbound->password);
}
bool EditSocks::onEnd() {
auto outbound = this->ent->Socks();
outbound->version = ui->version->currentText().toInt();
outbound->username = ui->username->text();
outbound->password = ui->password->text();
return true;
}

View File

@ -1,45 +0,0 @@
#include "include/ui/profile/edit_socks_http.h"
EditSocksHttp::EditSocksHttp(QWidget *parent) : QWidget(parent),
ui(new Ui::EditSocksHttp) {
ui->setupUi(this);
}
EditSocksHttp::~EditSocksHttp() {
delete ui;
}
void EditSocksHttp::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
this->ent = _ent;
// auto bean = this->ent->SocksHTTPBean();
//
// if (bean->socks_http_type == Configs::SocksHttpBean::type_Socks4) {
// ui->version->setCurrentIndex(1);
// } else {
// ui->version->setCurrentIndex(0);
// }
// if (bean->socks_http_type == Configs::SocksHttpBean::type_HTTP) {
// ui->version->setVisible(false);
// ui->version_l->setVisible(false);
// }
//
// ui->username->setText(bean->username);
// ui->password->setText(bean->password);
}
bool EditSocksHttp::onEnd() {
// auto bean = this->ent->SocksHTTPBean();
//
// if (ui->version->isVisible()) {
// if (ui->version->currentIndex() == 1) {
// bean->socks_http_type = Configs::SocksHttpBean::type_Socks4;
// } else {
// bean->socks_http_type = Configs::SocksHttpBean::type_Socks5;
// }
// }
//
// bean->username = ui->username->text();
// bean->password = ui->password->text();
return true;
}

View File

@ -1,8 +1,6 @@
#include "include/ui/profile/edit_ssh.h"
#include <QFileDialog>
#include "include/configs/proxy/SSHBean.h"
EditSSH::EditSSH(QWidget *parent) : QWidget(parent), ui(new Ui::EditSSH) {
ui->setupUi(this);
}
@ -13,16 +11,16 @@ EditSSH::~EditSSH() {
void EditSSH::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
this->ent = _ent;
auto bean = this->ent->SSH();
auto outbound = this->ent->SSH();
ui->user->setText(bean->user);
ui->password->setText(bean->password);
ui->private_key->setText(bean->private_key);
ui->private_key_path->setText(bean->private_key_path);
ui->private_key_pass->setText(bean->private_key_passphrase);
ui->host_key->setText(bean->host_key.join(","));
ui->host_key_algs->setText(bean->host_key_algorithms.join(","));
ui->client_version->setText(bean->client_version);
ui->user->setText(outbound->user);
ui->password->setText(outbound->password);
ui->private_key->setText(outbound->private_key);
ui->private_key_path->setText(outbound->private_key_path);
ui->private_key_pass->setText(outbound->private_key_passphrase);
ui->host_key->setText(outbound->host_key.join(","));
ui->host_key_algs->setText(outbound->host_key_algorithms.join(","));
ui->client_version->setText(outbound->client_version);
connect(ui->choose_pk, &QPushButton::clicked, this, [=,this] {
auto fn = QFileDialog::getOpenFileName(this, QObject::tr("Select"), QDir::currentPath(),
@ -34,18 +32,18 @@ void EditSSH::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
}
bool EditSSH::onEnd() {
auto bean = this->ent->SSH();
auto outbound = this->ent->SSH();
bean->user = ui->user->text();
bean->password = ui->password->text();
bean->private_key = ui->private_key->toPlainText();
bean->private_key_path = ui->private_key_path->text();
bean->private_key_passphrase = ui->private_key_pass->text();
if (!ui->host_key->text().trimmed().isEmpty()) bean->host_key = ui->host_key->text().split(",");
else bean->host_key = {};
if (!ui->host_key_algs->text().trimmed().isEmpty()) bean->host_key_algorithms = ui->host_key_algs->text().split(",");
else bean->host_key_algorithms = {};
bean->client_version = ui->client_version->text();
outbound->user = ui->user->text();
outbound->password = ui->password->text();
outbound->private_key = ui->private_key->toPlainText();
outbound->private_key_path = ui->private_key_path->text();
outbound->private_key_passphrase = ui->private_key_pass->text();
if (!ui->host_key->text().trimmed().isEmpty()) outbound->host_key = ui->host_key->text().split(",");
else outbound->host_key = {};
if (!ui->host_key_algs->text().trimmed().isEmpty()) outbound->host_key_algorithms = ui->host_key_algs->text().split(",");
else outbound->host_key_algorithms = {};
outbound->client_version = ui->client_version->text();
return true;
}

View File

@ -12,35 +12,35 @@ EditTailScale::~EditTailScale() {
void EditTailScale::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
this->ent = _ent;
auto bean = this->ent->Tailscale();
auto outbound = this->ent->Tailscale();
ui->state_dir->setText(bean->state_directory);
ui->auth_key->setText(bean->auth_key);
ui->control_plane->setText(bean->control_url);
ui->ephemeral->setChecked(bean->ephemeral);
ui->hostname->setText(bean->hostname);
ui->accept_route->setChecked(bean->accept_routes);
ui->exit_node->setText(bean->exit_node);
ui->exit_node_lan_access->setChecked(bean->exit_node_allow_lan_access);
ui->advertise_routes->setText(bean->advertise_routes.join(","));
ui->advertise_exit_node->setChecked(bean->advertise_exit_node);
ui->global_dns->setChecked(bean->globalDNS);
ui->state_dir->setText(outbound->state_directory);
ui->auth_key->setText(outbound->auth_key);
ui->control_plane->setText(outbound->control_url);
ui->ephemeral->setChecked(outbound->ephemeral);
ui->hostname->setText(outbound->hostname);
ui->accept_route->setChecked(outbound->accept_routes);
ui->exit_node->setText(outbound->exit_node);
ui->exit_node_lan_access->setChecked(outbound->exit_node_allow_lan_access);
ui->advertise_routes->setText(outbound->advertise_routes.join(","));
ui->advertise_exit_node->setChecked(outbound->advertise_exit_node);
ui->global_dns->setChecked(outbound->globalDNS);
}
bool EditTailScale::onEnd() {
auto bean = this->ent->Tailscale();
auto outbound = this->ent->Tailscale();
bean->state_directory = ui->state_dir->text();
bean->auth_key = ui->auth_key->text();
bean->control_url = ui->control_plane->text();
bean->ephemeral = ui->ephemeral->isChecked();
bean->hostname = ui->hostname->text();
bean->accept_routes = ui->accept_route->isChecked();
bean->exit_node = ui->exit_node->text();
bean->exit_node_allow_lan_access = ui->exit_node_lan_access->isChecked();
bean->advertise_routes = ui->advertise_routes->text().replace(" ", "").split(",");
bean->advertise_exit_node = ui->advertise_exit_node->isChecked();
bean->globalDNS = ui->global_dns->isChecked();
outbound->state_directory = ui->state_dir->text();
outbound->auth_key = ui->auth_key->text();
outbound->control_url = ui->control_plane->text();
outbound->ephemeral = ui->ephemeral->isChecked();
outbound->hostname = ui->hostname->text();
outbound->accept_routes = ui->accept_route->isChecked();
outbound->exit_node = ui->exit_node->text();
outbound->exit_node_allow_lan_access = ui->exit_node_lan_access->isChecked();
outbound->advertise_routes = ui->advertise_routes->text().replace(" ", "").split(",");
outbound->advertise_exit_node = ui->advertise_exit_node->isChecked();
outbound->globalDNS = ui->global_dns->isChecked();
return true;
}

View File

@ -0,0 +1,24 @@
#include "include/ui/profile/edit_trojan.h"
EditTrojan::EditTrojan(QWidget *parent)
: QWidget(parent),
ui(new Ui::EditTrojan) {
}
EditTrojan::~EditTrojan() {
delete ui;
}
void EditTrojan::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
this->ent = _ent;
auto outbound = ent->Trojan();
ui->password->setText(outbound->password);
}
bool EditTrojan::onEnd() {
auto outbound = ent->Trojan();
outbound->password = ui->password->text();
return true;
}

View File

@ -1,35 +0,0 @@
#include "include/ui/profile/edit_trojan_vless.h"
#include "include/configs/proxy/TrojanVLESSBean.hpp"
#include "include/configs/proxy/Preset.hpp"
EditTrojanVLESS::EditTrojanVLESS(QWidget *parent) : QWidget(parent), ui(new Ui::EditTrojanVLESS) {
ui->setupUi(this);
flow_ = ui->flow;
}
EditTrojanVLESS::~EditTrojanVLESS() {
delete ui;
}
void EditTrojanVLESS::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
this->ent = _ent;
// auto bean = this->ent->TrojanVLESSBean();
// if (bean->proxy_type == Configs::TrojanVLESSBean::proxy_VLESS) {
// ui->label->setText("UUID");
// }
// if (bean->proxy_type != Configs::TrojanVLESSBean::proxy_VLESS) {
// ui->flow->hide();
// ui->flow_l->hide();
// }
// ui->password->setText(bean->password);
// ui->flow->addItems(Preset::SingBox::Flows );
// ui->flow->setCurrentText(bean->flow);
}
bool EditTrojanVLESS::onEnd() {
// auto bean = this->ent->TrojanVLESSBean();
// bean->password = ui->password->text();
// bean->flow = ui->flow->currentText();
return true;
}

View File

@ -0,0 +1,38 @@
#include "include/ui/profile/edit_tuic.h"
EditTuic::EditTuic(QWidget *parent)
: QWidget(parent),
ui(new Ui::EditTuic) {
ui->setupUi(this);
}
EditTuic::~EditTuic() {
delete ui;
}
void EditTuic::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
this->ent = _ent;
auto outbound = ent->TUIC();
ui->uuid->setText(outbound->uuid);
ui->password->setText(outbound->password);
ui->congestion_control->setCurrentText(outbound->congestion_control.isEmpty() ? "bbr" : outbound->congestion_control);
ui->udp_relay_mode->setCurrentText(outbound->udp_relay_mode.isEmpty() ? "native" : outbound->udp_relay_mode);
ui->udp_over_stream->setChecked(outbound->udp_over_stream);
ui->zero_rtt->setChecked(outbound->zero_rtt_handshake);
ui->heartbeat->setText(outbound->heartbeat);
}
bool EditTuic::onEnd() {
auto outbound = ent->TUIC();
outbound->uuid = ui->uuid->text();
outbound->password = ui->password->text();
outbound->congestion_control = ui->congestion_control->currentText();
outbound->udp_relay_mode = ui->udp_relay_mode->currentText();
outbound->udp_over_stream = ui->udp_over_stream->isChecked();
outbound->zero_rtt_handshake = ui->zero_rtt->isChecked();
outbound->heartbeat = ui->heartbeat->text();
return true;
}

View File

@ -0,0 +1,35 @@
#include "include/ui/profile/edit_vless.h"
EditVless::EditVless(QWidget *parent)
: QWidget(parent),
ui(new Ui::EditVless) {
ui->setupUi(this);
_flow = ui->flow;
QStringList flows = {""};
flows << Configs::vlessFlows;
ui->flow->addItems(flows);
ui->packet_encoding->addItems(Configs::vPacketEncoding);
}
EditVless::~EditVless() {
delete ui;
}
void EditVless::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
this->ent = _ent;
auto outbound = this->ent->VLESS();
ui->uuid->setText(outbound->uuid);
ui->flow->setCurrentText(outbound->flow);
ui->packet_encoding->setCurrentText(outbound->packet_encoding);
}
bool EditVless::onEnd() {
auto outbound = this->ent->VLESS();
outbound->uuid = ui->uuid->text();
outbound->flow = ui->flow->currentText();
outbound->packet_encoding = ui->packet_encoding->currentText();
return true;
}

View File

@ -1,12 +1,11 @@
#include "include/ui/profile/edit_vmess.h"
#include "include/configs/proxy/VMessBean.hpp"
#include <QUuid>
EditVMess::EditVMess(QWidget *parent) : QWidget(parent), ui(new Ui::EditVMess) {
ui->setupUi(this);
connect(ui->uuidgen, &QPushButton::clicked, this, [=,this] { ui->uuid->setText(QUuid::createUuid().toString().remove("{").remove("}")); });
ui->packet_encoding->addItems(Configs::vPacketEncoding);
}
EditVMess::~EditVMess() {
@ -15,19 +14,21 @@ EditVMess::~EditVMess() {
void EditVMess::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
this->ent = _ent;
auto bean = this->ent->VMess();
auto outbound = this->ent->VMess();
ui->uuid->setText(bean->uuid);
ui->aid->setText(Int2String(bean->alter_id));
ui->security->setCurrentText(bean->security);
ui->uuid->setText(outbound->uuid);
ui->aid->setText(Int2String(outbound->alter_id));
ui->packet_encoding->setCurrentText(outbound->packet_encoding);
ui->security->setCurrentText(outbound->security);
}
bool EditVMess::onEnd() {
auto bean = this->ent->VMess();
auto outbound = this->ent->VMess();
bean->uuid = ui->uuid->text();
bean->alter_id = ui->aid->text().toInt();
bean->security = ui->security->currentText();
outbound->uuid = ui->uuid->text();
outbound->alter_id = ui->aid->text().toInt();
outbound->packet_encoding = ui->packet_encoding->currentText();
outbound->security = ui->security->currentText();
return true;
}

View File

@ -10,63 +10,63 @@ EditWireguard::~EditWireguard() {
void EditWireguard::onStart(std::shared_ptr<Configs::ProxyEntity> _ent) {
this->ent = _ent;
auto bean = this->ent->Wireguard();
auto outbound = this->ent->Wireguard();
#ifndef Q_OS_LINUX
adjustSize();
#endif
ui->private_key->setText(bean->private_key);
ui->public_key->setText(bean->peer->public_key);
ui->preshared_key->setText(bean->peer->pre_shared_key);
// auto reservedStr = bean->peer->reserved;
ui->private_key->setText(outbound->private_key);
ui->public_key->setText(outbound->peer->public_key);
ui->preshared_key->setText(outbound->peer->pre_shared_key);
// auto reservedStr = outbound->peer->reserved;
// ui->reserved->setText(reservedStr);
ui->persistent_keepalive->setText(Int2String(bean->peer->persistent_keepalive));
ui->mtu->setText(Int2String(bean->mtu));
ui->sys_ifc->setChecked(bean->system);
ui->local_addr->setText(bean->address.join(","));
ui->workers->setText(Int2String(bean->worker_count));
ui->persistent_keepalive->setText(Int2String(outbound->peer->persistent_keepalive));
ui->mtu->setText(Int2String(outbound->mtu));
ui->sys_ifc->setChecked(outbound->system);
ui->local_addr->setText(outbound->address.join(","));
ui->workers->setText(Int2String(outbound->worker_count));
ui->enable_amnezia->setChecked(bean->enable_amnezia);
ui->junk_packet_count->setText(Int2String(bean->junk_packet_count));
ui->junk_packet_min_size->setText(Int2String(bean->junk_packet_min_size));
ui->junk_packet_max_size->setText(Int2String(bean->junk_packet_max_size));
ui->init_packet_junk_size->setText(Int2String(bean->init_packet_junk_size));
ui->response_packet_junk_size->setText(Int2String(bean->response_packet_junk_size));
ui->init_packet_magic_header->setText(Int2String(bean->init_packet_magic_header));
ui->response_packet_magic_header->setText(Int2String(bean->response_packet_magic_header));
ui->underload_packet_magic_header->setText(Int2String(bean->underload_packet_magic_header));
ui->transport_packet_magic_header->setText(Int2String(bean->transport_packet_magic_header));
ui->enable_amnezia->setChecked(outbound->enable_amnezia);
ui->junk_packet_count->setText(Int2String(outbound->junk_packet_count));
ui->junk_packet_min_size->setText(Int2String(outbound->junk_packet_min_size));
ui->junk_packet_max_size->setText(Int2String(outbound->junk_packet_max_size));
ui->init_packet_junk_size->setText(Int2String(outbound->init_packet_junk_size));
ui->response_packet_junk_size->setText(Int2String(outbound->response_packet_junk_size));
ui->init_packet_magic_header->setText(Int2String(outbound->init_packet_magic_header));
ui->response_packet_magic_header->setText(Int2String(outbound->response_packet_magic_header));
ui->underload_packet_magic_header->setText(Int2String(outbound->underload_packet_magic_header));
ui->transport_packet_magic_header->setText(Int2String(outbound->transport_packet_magic_header));
}
bool EditWireguard::onEnd() {
auto bean = this->ent->Wireguard();
auto outbound = this->ent->Wireguard();
bean->private_key = ui->private_key->text();
bean->peer->public_key = ui->public_key->text();
bean->peer->pre_shared_key = ui->preshared_key->text();
outbound->private_key = ui->private_key->text();
outbound->peer->public_key = ui->public_key->text();
outbound->peer->pre_shared_key = ui->preshared_key->text();
auto rawReserved = ui->reserved->text();
// bean->reserved = {};
// outbound->reserved = {};
// for (const auto& item: rawReserved.split(",")) {
// if (item.trimmed().isEmpty()) continue;
// bean->reserved += item.trimmed().toInt();
// outbound->reserved += item.trimmed().toInt();
// }
bean->peer->persistent_keepalive = ui->persistent_keepalive->text().toInt();
bean->mtu = ui->mtu->text().toInt();
bean->system = ui->sys_ifc->isChecked();
bean->address = ui->local_addr->text().replace(" ", "").split(",");
bean->worker_count = ui->workers->text().toInt();
outbound->peer->persistent_keepalive = ui->persistent_keepalive->text().toInt();
outbound->mtu = ui->mtu->text().toInt();
outbound->system = ui->sys_ifc->isChecked();
outbound->address = ui->local_addr->text().replace(" ", "").split(",");
outbound->worker_count = ui->workers->text().toInt();
bean->enable_amnezia = ui->enable_amnezia->isChecked();
bean->junk_packet_count = ui->junk_packet_count->text().toInt();
bean->junk_packet_min_size = ui->junk_packet_min_size->text().toInt();
bean->junk_packet_max_size = ui->junk_packet_max_size->text().toInt();
bean->init_packet_junk_size = ui->init_packet_junk_size->text().toInt();
bean->response_packet_junk_size = ui->response_packet_junk_size->text().toInt();
bean->init_packet_magic_header = ui->init_packet_magic_header->text().toInt();
bean->response_packet_magic_header = ui->response_packet_magic_header->text().toInt();
bean->underload_packet_magic_header = ui->underload_packet_magic_header->text().toInt();
bean->transport_packet_magic_header = ui->transport_packet_magic_header->text().toInt();
outbound->enable_amnezia = ui->enable_amnezia->isChecked();
outbound->junk_packet_count = ui->junk_packet_count->text().toInt();
outbound->junk_packet_min_size = ui->junk_packet_min_size->text().toInt();
outbound->junk_packet_max_size = ui->junk_packet_max_size->text().toInt();
outbound->init_packet_junk_size = ui->init_packet_junk_size->text().toInt();
outbound->response_packet_junk_size = ui->response_packet_junk_size->text().toInt();
outbound->init_packet_magic_header = ui->init_packet_magic_header->text().toInt();
outbound->response_packet_magic_header = ui->response_packet_magic_header->text().toInt();
outbound->underload_packet_magic_header = ui->underload_packet_magic_header->text().toInt();
outbound->transport_packet_magic_header = ui->transport_packet_magic_header->text().toInt();
return true;
}