diff --git a/fmt/Preset.hpp b/fmt/Preset.hpp index e2f075d..133c2b0 100644 --- a/fmt/Preset.hpp +++ b/fmt/Preset.hpp @@ -17,4 +17,11 @@ namespace Preset { namespace SingBox { inline QStringList VpnImplementation = {"gvisor", "system"}; } + + namespace Windows { + inline QStringList system_proxy_format{"{ip}:{http_port}", + "socks={ip}:{socks_port}", + "http={ip}:{http_port};https={ip}:{http_port};ftp={ip}:{http_port};socks={ip}:{socks_port}", + "http=http://{ip}:{http_port};https=http://{ip}:{http_port}"}; + } } diff --git a/main/NekoRay.cpp b/main/NekoRay.cpp index f965076..b45d929 100644 --- a/main/NekoRay.cpp +++ b/main/NekoRay.cpp @@ -58,6 +58,7 @@ namespace NekoRay { _add(new configItem("vpn_bypass_process", &vpn_bypass_process, itemType::string)); _add(new configItem("vpn_bypass_cidr", &vpn_bypass_cidr, itemType::string)); _add(new configItem("check_include_pre", &check_include_pre, itemType::boolean)); + _add(new configItem("sp_format", &system_proxy_format, itemType::string)); } void DataStore::UpdateStartedId(int id) { diff --git a/main/NekoRay_DataStore.hpp b/main/NekoRay_DataStore.hpp index ac62300..f6d8e4b 100644 --- a/main/NekoRay_DataStore.hpp +++ b/main/NekoRay_DataStore.hpp @@ -72,6 +72,7 @@ namespace NekoRay { int language = 0; QString mw_size = ""; bool check_include_pre = false; + QString system_proxy_format = ""; // Security bool insecure_hint = true; diff --git a/main/NekoRay_Utils.hpp b/main/NekoRay_Utils.hpp index aa86662..0ecada8 100644 --- a/main/NekoRay_Utils.hpp +++ b/main/NekoRay_Utils.hpp @@ -25,6 +25,8 @@ inline std::function dialog_message; #define QJSONOBJECT_COPY(src, dst, key) if (src.contains(key)) dst[key] = src[key]; #define QJSONOBJECT_COPY2(src, dst, src_key, dst_key) if (src.contains(src_key)) dst[dst_key] = src[src_key]; +#define Int2String(num) QString::number(num) + inline QString SubStrBefore(QString str, const QString &sub) { if (!str.contains(sub)) return str; return str.left(str.indexOf(sub)); @@ -58,14 +60,6 @@ DecodeB64IfValid(const QString &input, QByteArray::Base64Option options = QByteA QString GetQueryValue(const QUrlQuery &q, const QString &key, const QString &def = ""); -inline QString Int2String(int i) { - return QVariant(i).toString(); -} - -inline QString Int2String(qint64 i) { - return QVariant(i).toString(); -} - QString GetRandomString(int randomStringLength); // QString >> QJson @@ -114,6 +108,8 @@ inline QStringList SplitLines(const QString &_string) { return _string.split(QRegularExpression("[\r\n]"), Qt::SplitBehaviorFlags::SkipEmptyParts); } +// Files + QByteArray ReadFile(const QString &path); QString ReadFileText(const QString &path); diff --git a/qv2ray/v2/components/proxy/QvProxyConfigurator.cpp b/qv2ray/v2/components/proxy/QvProxyConfigurator.cpp index 249e448..0ccab55 100644 --- a/qv2ray/v2/components/proxy/QvProxyConfigurator.cpp +++ b/qv2ray/v2/components/proxy/QvProxyConfigurator.cpp @@ -14,7 +14,8 @@ #include #include "qv2ray/wrapper.hpp" -#include "main/NekoRay_Utils.hpp" +#include "fmt/Preset.hpp" +#include "main/NekoRay.hpp" #define QV_MODULE_NAME "SystemProxy" @@ -250,8 +251,8 @@ namespace Qv2ray::components::proxy { } #endif - void SetSystemProxy(const QString &address, int httpPort, int socksPort) { - LOG("Setting up System Proxy"); +void SetSystemProxy(int httpPort, int socksPort) { + const QString &address = "127.0.0.1"; bool hasHTTP = (httpPort > 0 && httpPort < 65536); bool hasSOCKS = (socksPort > 0 && socksPort < 65536); @@ -281,23 +282,15 @@ namespace Qv2ray::components::proxy { #endif #ifdef Q_OS_WIN - QString __a; - const QHostAddress ha(address); - const auto type = ha.protocol(); - if (type == QAbstractSocket::IPv6Protocol) - { - // many software do not recognize IPv6 proxy server string though - const auto str = ha.toString(); // RFC5952 - __a = "[" + str + "]:" + QSTRN(httpPort); - } - else - { - __a = address + ":" + QSTRN(httpPort); - } - - LOG("Windows proxy string: " + __a); - auto proxyStrW = new WCHAR[__a.length() + 1]; - wcscpy(proxyStrW, __a.toStdWString().c_str()); + QString str = NekoRay::dataStore->system_proxy_format; + if (str.isEmpty()) str = Preset::Windows::system_proxy_format[0]; + str = str.replace("{ip}", address) + .replace("{http_port}", Int2String(httpPort)) + .replace("{socks_port}", Int2String(socksPort)); + // + LOG("Windows proxy string: " + str); + auto proxyStrW = new WCHAR[str.length() + 1]; + wcscpy(proxyStrW, str.toStdWString().c_str()); // __QueryProxyOptions(); diff --git a/qv2ray/v2/components/proxy/QvProxyConfigurator.hpp b/qv2ray/v2/components/proxy/QvProxyConfigurator.hpp index a6b0300..738c96b 100644 --- a/qv2ray/v2/components/proxy/QvProxyConfigurator.hpp +++ b/qv2ray/v2/components/proxy/QvProxyConfigurator.hpp @@ -6,7 +6,7 @@ namespace Qv2ray::components::proxy { void ClearSystemProxy(); - void SetSystemProxy(const QString &address, int http_port, int socks_port); + void SetSystemProxy(int http_port, int socks_port); } // namespace Qv2ray::components::proxy using namespace Qv2ray::components; diff --git a/translations/zh_CN.ts b/translations/zh_CN.ts index 15d59fb..a7c8868 100644 --- a/translations/zh_CN.ts +++ b/translations/zh_CN.ts @@ -191,6 +191,14 @@ Switching the core to %1, click "Yes" to complete the switch and the program will restart. This feature may be unstable, please do not switch frequently. 将核心切换到 %1。点击 "是" 完成切换,程序将重新启动。此功能可能不稳定,请不要频繁切换。 + + System proxy format + 系统代理格式 + + + Advanced system proxy settings. Please select a format. + 高级系统代理设置。请选择一种格式。 + DialogEditGroup diff --git a/ui/dialog_basic_settings.cpp b/ui/dialog_basic_settings.cpp index 286f93e..47de744 100644 --- a/ui/dialog_basic_settings.cpp +++ b/ui/dialog_basic_settings.cpp @@ -2,6 +2,7 @@ #include "ui_dialog_basic_settings.h" #include "qv2ray/v2/ui/widgets/editors/w_JsonEditor.hpp" +#include "fmt/Preset.hpp" #include "ui/ThemeManager.hpp" #include "main/GuiUtils.hpp" #include "main/NekoRay.hpp" @@ -78,6 +79,22 @@ DialogBasicSettings::DialogBasicSettings(QWidget *parent) C_EDIT_JSON_ALLOW_EMPTY(custom_inbound) }); +#ifdef Q_OS_WIN + connect(ui->sys_proxy_format, &QPushButton::clicked, this, [=] { + bool ok; + auto str = QInputDialog::getItem(this, ui->sys_proxy_format->text() + " (Windows)", + tr("Advanced system proxy settings. Please select a format."), + Preset::Windows::system_proxy_format, + Preset::Windows::system_proxy_format.indexOf( + NekoRay::dataStore->system_proxy_format), + false, &ok + ); + if (ok) NekoRay::dataStore->system_proxy_format = str; + }); +#else + ui->sys_proxy_format->hide(); +#endif + // Style if (IS_NEKO_BOX) { ui->connection_statistics_box->setDisabled(true); diff --git a/ui/dialog_basic_settings.ui b/ui/dialog_basic_settings.ui index 7671295..1e0cc60 100644 --- a/ui/dialog_basic_settings.ui +++ b/ui/dialog_basic_settings.ui @@ -209,6 +209,13 @@ + + + + System proxy format + + + diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp index ba05d8b..8fd2cb9 100644 --- a/ui/mainwindow.cpp +++ b/ui/mainwindow.cpp @@ -588,7 +588,7 @@ void MainWindow::neko_set_spmode(int mode, bool save) { // ENABLE if (mode == NekoRay::SystemProxyMode::SYSTEM_PROXY) { -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) || defined(Q_OS_MACOS) if (mode == NekoRay::SystemProxyMode::SYSTEM_PROXY && !IS_NEKO_BOX && !InRange(NekoRay::dataStore->inbound_http_port, 0, 65535)) { auto btn = QMessageBox::warning(this, software_name, @@ -604,9 +604,8 @@ void MainWindow::neko_set_spmode(int mode, bool save) { auto http_port = NekoRay::dataStore->inbound_http_port; if (IS_NEKO_BOX) { http_port = socks_port; - socks_port = -1; } - SetSystemProxy("127.0.0.1", http_port, socks_port); + SetSystemProxy(http_port, socks_port); } else if (mode == NekoRay::SystemProxyMode::VPN) { if (!StartVPNProcess()) { refresh_status();