Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71bf9b4887 | ||
|
|
9039d401da | ||
|
|
74a0a93201 | ||
|
|
522571f0b3 | ||
|
|
123c49c22d | ||
|
|
1ff88d29be | ||
|
|
63d5a2a1be | ||
|
|
1e9a6cb06b | ||
|
|
31748aa660 | ||
|
|
d0c6ea6a63 | ||
|
|
7ffe286a56 | ||
|
|
b99b30163b | ||
|
|
83b4f1e660 | ||
|
|
b57ba6a98b | ||
|
|
d748e6eff4 | ||
|
|
315d4b75b2 | ||
|
|
31267cbc33 | ||
|
|
c23379b3b6 | ||
|
|
568144d6a2 |
@@ -9,9 +9,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Google.Protobuf" Version="3.26.1" />
|
<PackageReference Include="Google.Protobuf" Version="3.27.0" />
|
||||||
<PackageReference Include="Grpc.Net.Client" Version="2.62.0" />
|
<PackageReference Include="Grpc.Net.Client" Version="2.63.0" />
|
||||||
<PackageReference Include="Grpc.Tools" Version="2.63.0">
|
<PackageReference Include="Grpc.Tools" Version="2.64.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@@ -58,10 +58,12 @@ namespace v2rayN
|
|||||||
Environment.Exit(0);
|
Environment.Exit(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//if (RuntimeInformation.ProcessArchitecture != Architecture.X86 && RuntimeInformation.ProcessArchitecture != Architecture.X64)
|
|
||||||
//{
|
//Under Win10
|
||||||
// _config.guiItem.enableStatistics = false;
|
if (Environment.OSVersion.Version.Major < 10)
|
||||||
//}
|
{
|
||||||
|
Environment.SetEnvironmentVariable("DOTNET_EnableWriteXorExecute", "0", EnvironmentVariableTarget.Process);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
|
private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
|
||||||
|
|||||||
@@ -105,9 +105,12 @@ namespace v2rayN
|
|||||||
/// <param name="filePath"></param>
|
/// <param name="filePath"></param>
|
||||||
/// <param name="nullValue"></param>
|
/// <param name="nullValue"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static int ToFile(object? obj, string filePath, bool nullValue = true)
|
public static int ToFile(object? obj, string? filePath, bool nullValue = true)
|
||||||
{
|
{
|
||||||
int result;
|
if (filePath is null)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using FileStream file = File.Create(filePath);
|
using FileStream file = File.Create(filePath);
|
||||||
@@ -119,14 +122,13 @@ namespace v2rayN
|
|||||||
};
|
};
|
||||||
|
|
||||||
JsonSerializer.Serialize(file, obj, options);
|
JsonSerializer.Serialize(file, obj, options);
|
||||||
result = 0;
|
return 0;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(ex.Message, ex);
|
||||||
result = -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,13 @@
|
|||||||
using QRCoder;
|
using QRCoder;
|
||||||
using QRCoder.Xaml;
|
using QRCoder.Xaml;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Interop;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
using ZXing;
|
||||||
|
using ZXing.Common;
|
||||||
|
using ZXing.QrCode;
|
||||||
|
using ZXing.Windows.Compatibility;
|
||||||
|
|
||||||
namespace v2rayN
|
namespace v2rayN
|
||||||
{
|
{
|
||||||
@@ -28,5 +35,70 @@ namespace v2rayN
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string ScanScreen(float dpiX, float dpiY)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var left = (int)(SystemParameters.WorkArea.Left);
|
||||||
|
var top = (int)(SystemParameters.WorkArea.Top);
|
||||||
|
var width = (int)(SystemParameters.WorkArea.Width / dpiX);
|
||||||
|
var height = (int)(SystemParameters.WorkArea.Height / dpiY);
|
||||||
|
|
||||||
|
using Bitmap fullImage = new Bitmap(width, height);
|
||||||
|
using (Graphics g = Graphics.FromImage(fullImage))
|
||||||
|
{
|
||||||
|
g.CopyFromScreen(left, top, 0, 0, fullImage.Size, CopyPixelOperation.SourceCopy);
|
||||||
|
}
|
||||||
|
int maxTry = 10;
|
||||||
|
for (int i = 0; i < maxTry; i++)
|
||||||
|
{
|
||||||
|
int marginLeft = (int)((double)fullImage.Width * i / 2.5 / maxTry);
|
||||||
|
int marginTop = (int)((double)fullImage.Height * i / 2.5 / maxTry);
|
||||||
|
Rectangle cropRect = new(marginLeft, marginTop, fullImage.Width - marginLeft * 2, fullImage.Height - marginTop * 2);
|
||||||
|
Bitmap target = new(width, height);
|
||||||
|
|
||||||
|
double imageScale = (double)width / (double)cropRect.Width;
|
||||||
|
using (Graphics g = Graphics.FromImage(target))
|
||||||
|
{
|
||||||
|
g.DrawImage(fullImage, new Rectangle(0, 0, target.Width, target.Height),
|
||||||
|
cropRect,
|
||||||
|
GraphicsUnit.Pixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
BitmapLuminanceSource source = new(target);
|
||||||
|
QRCodeReader reader = new();
|
||||||
|
|
||||||
|
BinaryBitmap bitmap = new(new HybridBinarizer(source));
|
||||||
|
var result = reader.decode(bitmap);
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
return result.Text;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BinaryBitmap bitmap2 = new(new HybridBinarizer(source.invert()));
|
||||||
|
var result2 = reader.decode(bitmap2);
|
||||||
|
if (result2 != null)
|
||||||
|
{
|
||||||
|
return result2.Text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(ex.Message, ex);
|
||||||
|
}
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Tuple<float, float> GetDpiXY(Window window)
|
||||||
|
{
|
||||||
|
IntPtr hWnd = new WindowInteropHelper(window).EnsureHandle();
|
||||||
|
Graphics g = Graphics.FromHwnd(hWnd);
|
||||||
|
|
||||||
|
return new(96 / g.DpiX, 96 / g.DpiY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,10 +18,6 @@ using System.Windows;
|
|||||||
using System.Windows.Interop;
|
using System.Windows.Interop;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using ZXing;
|
|
||||||
using ZXing.Common;
|
|
||||||
using ZXing.QrCode;
|
|
||||||
using ZXing.Windows.Compatibility;
|
|
||||||
|
|
||||||
namespace v2rayN
|
namespace v2rayN
|
||||||
{
|
{
|
||||||
@@ -481,7 +477,7 @@ namespace v2rayN
|
|||||||
/// 验证Domain地址是否合法
|
/// 验证Domain地址是否合法
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="domain"></param>
|
/// <param name="domain"></param>
|
||||||
public static bool IsDomain(string domain)
|
public static bool IsDomain(string? domain)
|
||||||
{
|
{
|
||||||
//如果为空
|
//如果为空
|
||||||
if (IsNullOrEmpty(domain))
|
if (IsNullOrEmpty(domain))
|
||||||
@@ -950,66 +946,6 @@ namespace v2rayN
|
|||||||
|
|
||||||
#endregion TempPath
|
#endregion TempPath
|
||||||
|
|
||||||
#region scan screen
|
|
||||||
|
|
||||||
public static string ScanScreen(float dpiX, float dpiY)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var left = (int)(SystemParameters.WorkArea.Left);
|
|
||||||
var top = (int)(SystemParameters.WorkArea.Top);
|
|
||||||
var width = (int)(SystemParameters.WorkArea.Width / dpiX);
|
|
||||||
var height = (int)(SystemParameters.WorkArea.Height / dpiY);
|
|
||||||
|
|
||||||
using Bitmap fullImage = new Bitmap(width, height);
|
|
||||||
using (Graphics g = Graphics.FromImage(fullImage))
|
|
||||||
{
|
|
||||||
g.CopyFromScreen(left, top, 0, 0, fullImage.Size, CopyPixelOperation.SourceCopy);
|
|
||||||
}
|
|
||||||
int maxTry = 10;
|
|
||||||
for (int i = 0; i < maxTry; i++)
|
|
||||||
{
|
|
||||||
int marginLeft = (int)((double)fullImage.Width * i / 2.5 / maxTry);
|
|
||||||
int marginTop = (int)((double)fullImage.Height * i / 2.5 / maxTry);
|
|
||||||
Rectangle cropRect = new(marginLeft, marginTop, fullImage.Width - marginLeft * 2, fullImage.Height - marginTop * 2);
|
|
||||||
Bitmap target = new(width, height);
|
|
||||||
|
|
||||||
double imageScale = (double)width / (double)cropRect.Width;
|
|
||||||
using (Graphics g = Graphics.FromImage(target))
|
|
||||||
{
|
|
||||||
g.DrawImage(fullImage, new Rectangle(0, 0, target.Width, target.Height),
|
|
||||||
cropRect,
|
|
||||||
GraphicsUnit.Pixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
BitmapLuminanceSource source = new(target);
|
|
||||||
BinaryBitmap bitmap = new(new HybridBinarizer(source));
|
|
||||||
QRCodeReader reader = new();
|
|
||||||
Result result = reader.decode(bitmap);
|
|
||||||
if (result != null)
|
|
||||||
{
|
|
||||||
string ret = result.Text;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logging.SaveLog(ex.Message, ex);
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Tuple<float, float> GetDpiXY(Window window)
|
|
||||||
{
|
|
||||||
IntPtr hWnd = new WindowInteropHelper(window).EnsureHandle();
|
|
||||||
Graphics g = Graphics.FromHwnd(hWnd);
|
|
||||||
|
|
||||||
return new(96 / g.DpiX, 96 / g.DpiY);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion scan screen
|
|
||||||
|
|
||||||
#region 开机自动启动等
|
#region 开机自动启动等
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1148,8 +1084,10 @@ namespace v2rayN
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var sum = MD5.HashData(Encoding.UTF8.GetBytes("wintunsingbox_tun"));
|
||||||
|
var guid = new Guid(sum);
|
||||||
string pnputilPath = @"C:\Windows\System32\pnputil.exe";
|
string pnputilPath = @"C:\Windows\System32\pnputil.exe";
|
||||||
string arg = $" /remove-device /deviceid \"wintun\"";
|
string arg = $$""" /remove-device "SWD\Wintun\{{{guid}}}" """;
|
||||||
|
|
||||||
// Try to remove the device
|
// Try to remove the device
|
||||||
Process proc = new()
|
Process proc = new()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace v2rayN.Models
|
namespace v2rayN.Enums
|
||||||
{
|
{
|
||||||
public enum EConfigType
|
public enum EConfigType
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace v2rayN.Models
|
namespace v2rayN.Enums
|
||||||
{
|
{
|
||||||
public enum ECoreType
|
public enum ECoreType
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace v2rayN.Models
|
namespace v2rayN.Enums
|
||||||
{
|
{
|
||||||
public enum EGlobalHotkey
|
public enum EGlobalHotkey
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace v2rayN.Models
|
namespace v2rayN.Enums
|
||||||
{
|
{
|
||||||
public enum EInboundProtocol
|
public enum EInboundProtocol
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace v2rayN.Models
|
namespace v2rayN.Enums
|
||||||
{
|
{
|
||||||
public enum EMove
|
public enum EMove
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace v2rayN.Models
|
namespace v2rayN.Enums
|
||||||
{
|
{
|
||||||
public enum EServerColName
|
public enum EServerColName
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace v2rayN.Models
|
namespace v2rayN.Enums
|
||||||
{
|
{
|
||||||
public enum ESpeedActionType
|
public enum ESpeedActionType
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace v2rayN.Models
|
namespace v2rayN.Enums
|
||||||
{
|
{
|
||||||
public enum ESysProxyType
|
public enum ESysProxyType
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace v2rayN.Models
|
namespace v2rayN.Enums
|
||||||
{
|
{
|
||||||
public enum ETransport
|
public enum ETransport
|
||||||
{
|
{
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
kcp,
|
kcp,
|
||||||
ws,
|
ws,
|
||||||
httpupgrade,
|
httpupgrade,
|
||||||
|
splithttp,
|
||||||
h2,
|
h2,
|
||||||
http,
|
http,
|
||||||
quic,
|
quic,
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace v2rayN.Models
|
namespace v2rayN.Enums
|
||||||
{
|
{
|
||||||
public enum EViewAction
|
public enum EViewAction
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using v2rayN.Models;
|
using v2rayN.Enums;
|
||||||
|
|
||||||
namespace v2rayN
|
namespace v2rayN
|
||||||
{
|
{
|
||||||
@@ -106,7 +106,6 @@ namespace v2rayN
|
|||||||
@"https://speed.cloudflare.com/__down?bytes=100000000",
|
@"https://speed.cloudflare.com/__down?bytes=100000000",
|
||||||
@"https://speed.cloudflare.com/__down?bytes=10000000",
|
@"https://speed.cloudflare.com/__down?bytes=10000000",
|
||||||
@"http://cachefly.cachefly.net/50mb.test",
|
@"http://cachefly.cachefly.net/50mb.test",
|
||||||
@"http://cachefly.cachefly.net/100mb.test",
|
|
||||||
@"http://cachefly.cachefly.net/10mb.test"
|
@"http://cachefly.cachefly.net/10mb.test"
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -158,7 +157,7 @@ namespace v2rayN
|
|||||||
public static readonly List<string> SsSecuritiesInXray = new() { "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "xchacha20-poly1305", "xchacha20-ietf-poly1305", "none", "plain", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" };
|
public static readonly List<string> SsSecuritiesInXray = new() { "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "xchacha20-poly1305", "xchacha20-ietf-poly1305", "none", "plain", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" };
|
||||||
public static readonly List<string> SsSecuritiesInSingbox = new() { "aes-256-gcm", "aes-192-gcm", "aes-128-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305", "none", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "rc4-md5", "chacha20-ietf", "xchacha20" };
|
public static readonly List<string> SsSecuritiesInSingbox = new() { "aes-256-gcm", "aes-192-gcm", "aes-128-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305", "none", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "rc4-md5", "chacha20-ietf", "xchacha20" };
|
||||||
public static readonly List<string> Flows = new() { "", "xtls-rprx-vision", "xtls-rprx-vision-udp443" };
|
public static readonly List<string> Flows = new() { "", "xtls-rprx-vision", "xtls-rprx-vision-udp443" };
|
||||||
public static readonly List<string> Networks = new() { "tcp", "kcp", "ws", "httpupgrade", "h2", "quic", "grpc" };
|
public static readonly List<string> Networks = new() { "tcp", "kcp", "ws", "httpupgrade", "splithttp", "h2", "quic", "grpc" };
|
||||||
public static readonly List<string> KcpHeaderTypes = new() { "srtp", "utp", "wechat-video", "dtls", "wireguard" };
|
public static readonly List<string> KcpHeaderTypes = new() { "srtp", "utp", "wechat-video", "dtls", "wireguard" };
|
||||||
public static readonly List<string> CoreTypes = new() { "v2fly", "SagerNet", "Xray", "sing_box" };
|
public static readonly List<string> CoreTypes = new() { "v2fly", "SagerNet", "Xray", "sing_box" };
|
||||||
public static readonly List<string> CoreTypes4VLESS = new() { "Xray", "sing_box" };
|
public static readonly List<string> CoreTypes4VLESS = new() { "Xray", "sing_box" };
|
||||||
@@ -175,6 +174,7 @@ namespace v2rayN
|
|||||||
public static readonly List<string> LogLevels = new() { "debug", "info", "warning", "error", "none" };
|
public static readonly List<string> LogLevels = new() { "debug", "info", "warning", "error", "none" };
|
||||||
public static readonly List<string> InboundTags = new() { "socks", "http", "socks2", "http2" };
|
public static readonly List<string> InboundTags = new() { "socks", "http", "socks2", "http2" };
|
||||||
public static readonly List<string> RuleProtocols = new() { "http", "tls", "bittorrent" };
|
public static readonly List<string> RuleProtocols = new() { "http", "tls", "bittorrent" };
|
||||||
|
public static readonly List<string> destOverrideProtocols = ["http", "tls", "quic", "fakedns", "fakedns+others"];
|
||||||
public static readonly List<string> TunMtus = new() { "1280", "1408", "1500", "9000" };
|
public static readonly List<string> TunMtus = new() { "1280", "1408", "1500", "9000" };
|
||||||
public static readonly List<string> TunStacks = new() { "gvisor", "system" };
|
public static readonly List<string> TunStacks = new() { "gvisor", "system" };
|
||||||
public static readonly List<string> PresetMsgFilters = new() { "proxy", "direct", "block", "" };
|
public static readonly List<string> PresetMsgFilters = new() { "proxy", "direct", "block", "" };
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using System.Data;
|
using System.Data;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using v2rayN.Enums;
|
||||||
|
using v2rayN.Handler.Fmt;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
|
|
||||||
namespace v2rayN.Handler
|
namespace v2rayN.Handler
|
||||||
@@ -1069,12 +1071,12 @@ namespace v2rayN.Handler
|
|||||||
/// 批量添加服务器
|
/// 批量添加服务器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="config"></param>
|
/// <param name="config"></param>
|
||||||
/// <param name="clipboardData"></param>
|
/// <param name="strData"></param>
|
||||||
/// <param name="subid"></param>
|
/// <param name="subid"></param>
|
||||||
/// <returns>成功导入的数量</returns>
|
/// <returns>成功导入的数量</returns>
|
||||||
private static int AddBatchServers(Config config, string clipboardData, string subid, bool isSub, List<ProfileItem> lstOriSub)
|
private static int AddBatchServers(Config config, string strData, string subid, bool isSub, List<ProfileItem> lstOriSub)
|
||||||
{
|
{
|
||||||
if (Utils.IsNullOrEmpty(clipboardData))
|
if (Utils.IsNullOrEmpty(strData))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1091,7 +1093,7 @@ namespace v2rayN.Handler
|
|||||||
//Check for duplicate indexId
|
//Check for duplicate indexId
|
||||||
List<string>? lstDbIndexId = null;
|
List<string>? lstDbIndexId = null;
|
||||||
List<ProfileItem> lstAdd = new();
|
List<ProfileItem> lstAdd = new();
|
||||||
var arrData = clipboardData.Split(Environment.NewLine.ToCharArray()).Where(t => !t.IsNullOrEmpty());
|
var arrData = strData.Split(Environment.NewLine.ToCharArray()).Where(t => !t.IsNullOrEmpty());
|
||||||
if (isSub)
|
if (isSub)
|
||||||
{
|
{
|
||||||
arrData = arrData.Distinct();
|
arrData = arrData.Distinct();
|
||||||
@@ -1107,7 +1109,7 @@ namespace v2rayN.Handler
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var profileItem = ShareHandler.ImportFromClipboardConfig(str, out string msg);
|
var profileItem = FmtHandler.ResolveConfig(str, out string msg);
|
||||||
if (profileItem is null)
|
if (profileItem is null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -1176,55 +1178,39 @@ namespace v2rayN.Handler
|
|||||||
return countServers;
|
return countServers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int AddBatchServers4Custom(Config config, string clipboardData, string subid, bool isSub, List<ProfileItem> lstOriSub)
|
private static int AddBatchServers4Custom(Config config, string strData, string subid, bool isSub, List<ProfileItem> lstOriSub)
|
||||||
{
|
{
|
||||||
if (Utils.IsNullOrEmpty(clipboardData))
|
if (Utils.IsNullOrEmpty(strData))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
var subRemarks = LazyConfig.Instance.GetSubItem(subid)?.remarks;
|
||||||
|
|
||||||
//判断str是否包含s的任意一个字符串
|
List<ProfileItem>? lstProfiles = null;
|
||||||
static bool Contains(string str, params string[] s)
|
//Is sing-box array configuration
|
||||||
|
if (lstProfiles is null || lstProfiles.Count <= 0)
|
||||||
{
|
{
|
||||||
foreach (var item in s)
|
lstProfiles = SingboxFmt.ResolveFullArray(strData, subRemarks);
|
||||||
{
|
|
||||||
if (str.Contains(item, StringComparison.OrdinalIgnoreCase)) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Is v2ray array configuration
|
//Is v2ray array configuration
|
||||||
var configObjects = JsonUtils.Deserialize<Object[]>(clipboardData);
|
if (lstProfiles is null || lstProfiles.Count <= 0)
|
||||||
if (configObjects != null && configObjects.Length > 0)
|
{
|
||||||
|
lstProfiles = V2rayFmt.ResolveFullArray(strData, subRemarks);
|
||||||
|
}
|
||||||
|
if (lstProfiles != null && lstProfiles.Count > 0)
|
||||||
{
|
{
|
||||||
if (isSub && !Utils.IsNullOrEmpty(subid))
|
if (isSub && !Utils.IsNullOrEmpty(subid))
|
||||||
{
|
{
|
||||||
RemoveServerViaSubid(config, subid, isSub);
|
RemoveServerViaSubid(config, subid, isSub);
|
||||||
}
|
}
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
foreach (var configObject in configObjects)
|
foreach (var it in lstProfiles)
|
||||||
{
|
{
|
||||||
var objectString = JsonUtils.Serialize(configObject);
|
it.subid = subid;
|
||||||
var v2rayCon = JsonUtils.Deserialize<V2rayConfig>(objectString);
|
it.isSub = isSub;
|
||||||
if (v2rayCon?.inbounds?.Count > 0 && v2rayCon.outbounds?.Count > 0)
|
if (AddCustomServer(config, it, true) == 0)
|
||||||
{
|
{
|
||||||
var fileName = Utils.GetTempPath($"{Utils.GetGUID(false)}.json");
|
count++;
|
||||||
File.WriteAllText(fileName, objectString);
|
|
||||||
|
|
||||||
var profileIt = new ProfileItem
|
|
||||||
{
|
|
||||||
coreType = ECoreType.Xray,
|
|
||||||
address = fileName,
|
|
||||||
remarks = v2rayCon.remarks ?? "v2ray_custom",
|
|
||||||
subid = subid,
|
|
||||||
isSub = isSub
|
|
||||||
};
|
|
||||||
|
|
||||||
if (AddCustomServer(config, profileIt, true) == 0)
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
@@ -1233,58 +1219,39 @@ namespace v2rayN.Handler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfileItem profileItem = new();
|
ProfileItem? profileItem = null;
|
||||||
//Is v2ray configuration
|
//Is sing-box configuration
|
||||||
var v2rayConfig = JsonUtils.Deserialize<V2rayConfig>(clipboardData);
|
if (profileItem is null)
|
||||||
if (v2rayConfig?.inbounds?.Count > 0
|
|
||||||
&& v2rayConfig.outbounds?.Count > 0)
|
|
||||||
{
|
{
|
||||||
var fileName = Utils.GetTempPath($"{Utils.GetGUID(false)}.json");
|
profileItem = SingboxFmt.ResolveFull(strData, subRemarks);
|
||||||
File.WriteAllText(fileName, clipboardData);
|
}
|
||||||
|
//Is v2ray configuration
|
||||||
profileItem.coreType = ECoreType.Xray;
|
if (profileItem is null)
|
||||||
profileItem.address = fileName;
|
{
|
||||||
profileItem.remarks = v2rayConfig.remarks ?? "v2ray_custom";
|
profileItem = V2rayFmt.ResolveFull(strData, subRemarks);
|
||||||
}
|
}
|
||||||
//Is Clash configuration
|
//Is Clash configuration
|
||||||
else if (Contains(clipboardData, "port", "socks-port", "proxies"))
|
if (profileItem is null)
|
||||||
{
|
{
|
||||||
var fileName = Utils.GetTempPath($"{Utils.GetGUID(false)}.yaml");
|
profileItem = ClashFmt.ResolveFull(strData, subRemarks);
|
||||||
File.WriteAllText(fileName, clipboardData);
|
|
||||||
|
|
||||||
profileItem.coreType = ECoreType.mihomo;
|
|
||||||
profileItem.address = fileName;
|
|
||||||
profileItem.remarks = "clash_custom";
|
|
||||||
}
|
}
|
||||||
//Is hysteria configuration
|
//Is hysteria configuration
|
||||||
else if (Contains(clipboardData, "server", "up", "down", "listen", "<html>", "<body>"))
|
if (profileItem is null)
|
||||||
{
|
{
|
||||||
var fileName = Utils.GetTempPath($"{Utils.GetGUID(false)}.json");
|
profileItem = Hysteria2Fmt.ResolveFull2(strData, subRemarks);
|
||||||
File.WriteAllText(fileName, clipboardData);
|
}
|
||||||
|
if (profileItem is null)
|
||||||
profileItem.coreType = ECoreType.hysteria;
|
{
|
||||||
profileItem.address = fileName;
|
profileItem = Hysteria2Fmt.ResolveFull(strData, subRemarks);
|
||||||
profileItem.remarks = "hysteria_custom";
|
|
||||||
}
|
}
|
||||||
//Is naiveproxy configuration
|
//Is naiveproxy configuration
|
||||||
else if (Contains(clipboardData, "listen", "proxy", "<html>", "<body>"))
|
if (profileItem is null)
|
||||||
{
|
{
|
||||||
var fileName = Utils.GetTempPath($"{Utils.GetGUID(false)}.json");
|
profileItem = NaiveproxyFmt.ResolveFull(strData, subRemarks);
|
||||||
File.WriteAllText(fileName, clipboardData);
|
|
||||||
|
|
||||||
profileItem.coreType = ECoreType.naiveproxy;
|
|
||||||
profileItem.address = fileName;
|
|
||||||
profileItem.remarks = "naiveproxy_custom";
|
|
||||||
}
|
}
|
||||||
//Is Other configuration
|
if (profileItem is null || Utils.IsNullOrEmpty(profileItem.address))
|
||||||
else
|
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
//var fileName = Utile.GetTempPath($"{Utile.GetGUID(false)}.txt");
|
|
||||||
//File.WriteAllText(fileName, clipboardData);
|
|
||||||
|
|
||||||
//profileItem.address = fileName;
|
|
||||||
//profileItem.remarks = "other_custom";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSub && !Utils.IsNullOrEmpty(subid))
|
if (isSub && !Utils.IsNullOrEmpty(subid))
|
||||||
@@ -1297,12 +1264,6 @@ namespace v2rayN.Handler
|
|||||||
}
|
}
|
||||||
profileItem.subid = subid;
|
profileItem.subid = subid;
|
||||||
profileItem.isSub = isSub;
|
profileItem.isSub = isSub;
|
||||||
|
|
||||||
if (Utils.IsNullOrEmpty(profileItem.address))
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AddCustomServer(config, profileItem, true) == 0)
|
if (AddCustomServer(config, profileItem, true) == 0)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
@@ -1313,9 +1274,9 @@ namespace v2rayN.Handler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int AddBatchServers4SsSIP008(Config config, string clipboardData, string subid, bool isSub, List<ProfileItem> lstOriSub)
|
private static int AddBatchServers4SsSIP008(Config config, string strData, string subid, bool isSub, List<ProfileItem> lstOriSub)
|
||||||
{
|
{
|
||||||
if (Utils.IsNullOrEmpty(clipboardData))
|
if (Utils.IsNullOrEmpty(strData))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1325,31 +1286,12 @@ namespace v2rayN.Handler
|
|||||||
RemoveServerViaSubid(config, subid, isSub);
|
RemoveServerViaSubid(config, subid, isSub);
|
||||||
}
|
}
|
||||||
|
|
||||||
//SsSIP008
|
var lstSsServer = ShadowsocksFmt.ResolveSip008(strData);
|
||||||
var lstSsServer = JsonUtils.Deserialize<List<SsServer>>(clipboardData);
|
|
||||||
if (lstSsServer?.Count <= 0)
|
|
||||||
{
|
|
||||||
var ssSIP008 = JsonUtils.Deserialize<SsSIP008>(clipboardData);
|
|
||||||
if (ssSIP008?.servers?.Count > 0)
|
|
||||||
{
|
|
||||||
lstSsServer = ssSIP008.servers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lstSsServer?.Count > 0)
|
if (lstSsServer?.Count > 0)
|
||||||
{
|
{
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
foreach (var it in lstSsServer)
|
foreach (var ssItem in lstSsServer)
|
||||||
{
|
{
|
||||||
var ssItem = new ProfileItem()
|
|
||||||
{
|
|
||||||
subid = subid,
|
|
||||||
remarks = it.remarks,
|
|
||||||
security = it.method,
|
|
||||||
id = it.password,
|
|
||||||
address = it.server,
|
|
||||||
port = Utils.ToInt(it.server_port)
|
|
||||||
};
|
|
||||||
ssItem.subid = subid;
|
ssItem.subid = subid;
|
||||||
ssItem.isSub = isSub;
|
ssItem.isSub = isSub;
|
||||||
if (AddShadowsocksServer(config, ssItem) == 0)
|
if (AddShadowsocksServer(config, ssItem) == 0)
|
||||||
@@ -1364,7 +1306,7 @@ namespace v2rayN.Handler
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int AddBatchServers(Config config, string clipboardData, string subid, bool isSub)
|
public static int AddBatchServers(Config config, string strData, string subid, bool isSub)
|
||||||
{
|
{
|
||||||
List<ProfileItem>? lstOriSub = null;
|
List<ProfileItem>? lstOriSub = null;
|
||||||
if (isSub && !Utils.IsNullOrEmpty(subid))
|
if (isSub && !Utils.IsNullOrEmpty(subid))
|
||||||
@@ -1373,28 +1315,28 @@ namespace v2rayN.Handler
|
|||||||
}
|
}
|
||||||
|
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
if (Utils.IsBase64String(clipboardData))
|
if (Utils.IsBase64String(strData))
|
||||||
{
|
{
|
||||||
counter = AddBatchServers(config, Utils.Base64Decode(clipboardData), subid, isSub, lstOriSub);
|
counter = AddBatchServers(config, Utils.Base64Decode(strData), subid, isSub, lstOriSub);
|
||||||
}
|
}
|
||||||
if (counter < 1)
|
if (counter < 1)
|
||||||
{
|
{
|
||||||
counter = AddBatchServers(config, clipboardData, subid, isSub, lstOriSub);
|
counter = AddBatchServers(config, strData, subid, isSub, lstOriSub);
|
||||||
}
|
}
|
||||||
if (counter < 1)
|
if (counter < 1)
|
||||||
{
|
{
|
||||||
counter = AddBatchServers(config, Utils.Base64Decode(clipboardData), subid, isSub, lstOriSub);
|
counter = AddBatchServers(config, Utils.Base64Decode(strData), subid, isSub, lstOriSub);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (counter < 1)
|
if (counter < 1)
|
||||||
{
|
{
|
||||||
counter = AddBatchServers4SsSIP008(config, clipboardData, subid, isSub, lstOriSub);
|
counter = AddBatchServers4SsSIP008(config, strData, subid, isSub, lstOriSub);
|
||||||
}
|
}
|
||||||
|
|
||||||
//maybe other sub
|
//maybe other sub
|
||||||
if (counter < 1)
|
if (counter < 1)
|
||||||
{
|
{
|
||||||
counter = AddBatchServers4Custom(config, clipboardData, subid, isSub, lstOriSub);
|
counter = AddBatchServers4Custom(config, strData, subid, isSub, lstOriSub);
|
||||||
}
|
}
|
||||||
|
|
||||||
return counter;
|
return counter;
|
||||||
@@ -1532,16 +1474,16 @@ namespace v2rayN.Handler
|
|||||||
/// AddBatchRoutingRules
|
/// AddBatchRoutingRules
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="config"></param>
|
/// <param name="config"></param>
|
||||||
/// <param name="clipboardData"></param>
|
/// <param name="strData"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static int AddBatchRoutingRules(ref RoutingItem routingItem, string clipboardData)
|
public static int AddBatchRoutingRules(ref RoutingItem routingItem, string strData)
|
||||||
{
|
{
|
||||||
if (Utils.IsNullOrEmpty(clipboardData))
|
if (Utils.IsNullOrEmpty(strData))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var lstRules = JsonUtils.Deserialize<List<RulesItem>>(clipboardData);
|
var lstRules = JsonUtils.Deserialize<List<RulesItem>>(strData);
|
||||||
if (lstRules == null)
|
if (lstRules == null)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
|
|
||||||
namespace v2rayN.Handler
|
namespace v2rayN.Handler.CoreConfig
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Core configuration file processing class
|
/// Core configuration file processing class
|
||||||
@@ -154,7 +155,7 @@ namespace v2rayN.Handler
|
|||||||
{
|
{
|
||||||
if (coreType == ECoreType.sing_box)
|
if (coreType == ECoreType.sing_box)
|
||||||
{
|
{
|
||||||
if ((new CoreConfigSingbox(config)).GenerateClientSpeedtestConfig(selecteds, out SingboxConfig? singboxConfig, out msg) != 0)
|
if (new CoreConfigSingbox(config).GenerateClientSpeedtestConfig(selecteds, out SingboxConfig? singboxConfig, out msg) != 0)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -162,7 +163,7 @@ namespace v2rayN.Handler
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((new CoreConfigV2ray(config)).GenerateClientSpeedtestConfig(selecteds, out V2rayConfig? v2rayConfig, out msg) != 0)
|
if (new CoreConfigV2ray(config).GenerateClientSpeedtestConfig(selecteds, out V2rayConfig? v2rayConfig, out msg) != 0)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
|
|
||||||
namespace v2rayN.Handler
|
namespace v2rayN.Handler.CoreConfig
|
||||||
{
|
{
|
||||||
internal class CoreConfigSingbox
|
internal class CoreConfigSingbox
|
||||||
{
|
{
|
||||||
@@ -25,6 +26,11 @@ namespace v2rayN.Handler
|
|||||||
msg = ResUI.CheckServerSettings;
|
msg = ResUI.CheckServerSettings;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (node.GetNetwork() is nameof(ETransport.kcp) or nameof(ETransport.splithttp))
|
||||||
|
{
|
||||||
|
msg = ResUI.Incorrectconfiguration + $" - {node.GetNetwork()}";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
msg = ResUI.InitialConfiguration;
|
msg = ResUI.InitialConfiguration;
|
||||||
|
|
||||||
@@ -111,9 +117,10 @@ namespace v2rayN.Handler
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
singboxConfig.inbounds.Clear();
|
var listen = "::";
|
||||||
|
singboxConfig.inbounds = [];
|
||||||
|
|
||||||
if (!_config.tunModeItem.enableTun || (_config.tunModeItem.enableTun && _config.tunModeItem.enableExInbound))
|
if (!_config.tunModeItem.enableTun || _config.tunModeItem.enableTun && _config.tunModeItem.enableExInbound)
|
||||||
{
|
{
|
||||||
var inbound = new Inbound4Sbox()
|
var inbound = new Inbound4Sbox()
|
||||||
{
|
{
|
||||||
@@ -146,11 +153,11 @@ namespace v2rayN.Handler
|
|||||||
if (_config.inbound[0].newPort4LAN)
|
if (_config.inbound[0].newPort4LAN)
|
||||||
{
|
{
|
||||||
var inbound3 = GetInbound(inbound, EInboundProtocol.socks2, true);
|
var inbound3 = GetInbound(inbound, EInboundProtocol.socks2, true);
|
||||||
inbound3.listen = "::";
|
inbound3.listen = listen;
|
||||||
singboxConfig.inbounds.Add(inbound3);
|
singboxConfig.inbounds.Add(inbound3);
|
||||||
|
|
||||||
var inbound4 = GetInbound(inbound, EInboundProtocol.http2, false);
|
var inbound4 = GetInbound(inbound, EInboundProtocol.http2, false);
|
||||||
inbound4.listen = "::";
|
inbound4.listen = listen;
|
||||||
singboxConfig.inbounds.Add(inbound4);
|
singboxConfig.inbounds.Add(inbound4);
|
||||||
|
|
||||||
//auth
|
//auth
|
||||||
@@ -162,8 +169,8 @@ namespace v2rayN.Handler
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
inbound.listen = "::";
|
inbound.listen = listen;
|
||||||
inbound2.listen = "::";
|
inbound2.listen = listen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -810,24 +817,9 @@ namespace v2rayN.Handler
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
//Add the dns of the remote server domain
|
|
||||||
if (dns4Sbox.rules is null)
|
|
||||||
{
|
|
||||||
dns4Sbox.rules = new();
|
|
||||||
}
|
|
||||||
dns4Sbox.servers.Add(new()
|
|
||||||
{
|
|
||||||
tag = "local_local",
|
|
||||||
address = "223.5.5.5",
|
|
||||||
detour = Global.DirectTag,
|
|
||||||
});
|
|
||||||
dns4Sbox.rules.Add(new()
|
|
||||||
{
|
|
||||||
server = "local_local",
|
|
||||||
outbound = "any"
|
|
||||||
});
|
|
||||||
|
|
||||||
singboxConfig.dns = dns4Sbox;
|
singboxConfig.dns = dns4Sbox;
|
||||||
|
|
||||||
|
GenDnsDomains(singboxConfig);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -836,6 +828,35 @@ namespace v2rayN.Handler
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int GenDnsDomains(SingboxConfig singboxConfig)
|
||||||
|
{
|
||||||
|
var dns4Sbox = singboxConfig.dns ?? new();
|
||||||
|
dns4Sbox.servers ??= [];
|
||||||
|
dns4Sbox.rules ??= [];
|
||||||
|
|
||||||
|
var lstDomain = singboxConfig.outbounds
|
||||||
|
.Where(t => !Utils.IsNullOrEmpty(t.server) && Utils.IsDomain(t.server))
|
||||||
|
.Select(t => t.server)
|
||||||
|
.ToList();
|
||||||
|
if (lstDomain != null && lstDomain.Count > 0)
|
||||||
|
{
|
||||||
|
var tag = "local_local";
|
||||||
|
dns4Sbox.servers.Add(new()
|
||||||
|
{
|
||||||
|
tag = tag,
|
||||||
|
address = "223.5.5.5",
|
||||||
|
detour = Global.DirectTag,
|
||||||
|
});
|
||||||
|
dns4Sbox.rules.Add(new()
|
||||||
|
{
|
||||||
|
server = tag,
|
||||||
|
domain = lstDomain
|
||||||
|
});
|
||||||
|
}
|
||||||
|
singboxConfig.dns = dns4Sbox;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
private int GenExperimental(SingboxConfig singboxConfig)
|
private int GenExperimental(SingboxConfig singboxConfig)
|
||||||
{
|
{
|
||||||
if (_config.guiItem.enableStatistics)
|
if (_config.guiItem.enableStatistics)
|
||||||
@@ -1076,18 +1097,18 @@ namespace v2rayN.Handler
|
|||||||
singboxConfig.route.rules.Add(rule);
|
singboxConfig.route.rules.Add(rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
GenDns(new(), singboxConfig);
|
GenDnsDomains(singboxConfig);
|
||||||
var dnsServer = singboxConfig.dns?.servers.FirstOrDefault();
|
//var dnsServer = singboxConfig.dns?.servers.FirstOrDefault();
|
||||||
if (dnsServer != null)
|
//if (dnsServer != null)
|
||||||
{
|
//{
|
||||||
dnsServer.detour = singboxConfig.route.rules.LastOrDefault()?.outbound;
|
// dnsServer.detour = singboxConfig.route.rules.LastOrDefault()?.outbound;
|
||||||
}
|
//}
|
||||||
var dnsRule = singboxConfig.dns?.rules.Where(t => t.outbound != null).FirstOrDefault();
|
//var dnsRule = singboxConfig.dns?.rules.Where(t => t.outbound != null).FirstOrDefault();
|
||||||
if (dnsRule != null)
|
//if (dnsRule != null)
|
||||||
{
|
//{
|
||||||
singboxConfig.dns.rules = [];
|
// singboxConfig.dns.rules = [];
|
||||||
singboxConfig.dns.rules.Add(dnsRule);
|
// singboxConfig.dns.rules.Add(dnsRule);
|
||||||
}
|
//}
|
||||||
|
|
||||||
//msg = string.Format(ResUI.SuccessfulConfiguration"), node.getSummary());
|
//msg = string.Format(ResUI.SuccessfulConfiguration"), node.getSummary());
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
|
|
||||||
namespace v2rayN.Handler
|
namespace v2rayN.Handler.CoreConfig
|
||||||
{
|
{
|
||||||
internal class CoreConfigV2ray
|
internal class CoreConfigV2ray
|
||||||
{
|
{
|
||||||
@@ -98,7 +99,8 @@ namespace v2rayN.Handler
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
v2rayConfig.inbounds = new List<Inbounds4Ray>();
|
var listen = "0.0.0.0";
|
||||||
|
v2rayConfig.inbounds = [];
|
||||||
|
|
||||||
Inbounds4Ray? inbound = GetInbound(_config.inbound[0], EInboundProtocol.socks, true);
|
Inbounds4Ray? inbound = GetInbound(_config.inbound[0], EInboundProtocol.socks, true);
|
||||||
v2rayConfig.inbounds.Add(inbound);
|
v2rayConfig.inbounds.Add(inbound);
|
||||||
@@ -112,11 +114,11 @@ namespace v2rayN.Handler
|
|||||||
if (_config.inbound[0].newPort4LAN)
|
if (_config.inbound[0].newPort4LAN)
|
||||||
{
|
{
|
||||||
var inbound3 = GetInbound(_config.inbound[0], EInboundProtocol.socks2, true);
|
var inbound3 = GetInbound(_config.inbound[0], EInboundProtocol.socks2, true);
|
||||||
inbound3.listen = "0.0.0.0";
|
inbound3.listen = listen;
|
||||||
v2rayConfig.inbounds.Add(inbound3);
|
v2rayConfig.inbounds.Add(inbound3);
|
||||||
|
|
||||||
var inbound4 = GetInbound(_config.inbound[0], EInboundProtocol.http2, false);
|
var inbound4 = GetInbound(_config.inbound[0], EInboundProtocol.http2, false);
|
||||||
inbound4.listen = "0.0.0.0";
|
inbound4.listen = listen;
|
||||||
v2rayConfig.inbounds.Add(inbound4);
|
v2rayConfig.inbounds.Add(inbound4);
|
||||||
|
|
||||||
//auth
|
//auth
|
||||||
@@ -131,8 +133,8 @@ namespace v2rayN.Handler
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
inbound.listen = "0.0.0.0";
|
inbound.listen = listen;
|
||||||
inbound2.listen = "0.0.0.0";
|
inbound2.listen = listen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -143,24 +145,25 @@ namespace v2rayN.Handler
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Inbounds4Ray? GetInbound(InItem inItem, EInboundProtocol protocol, bool bSocks)
|
private Inbounds4Ray GetInbound(InItem inItem, EInboundProtocol protocol, bool bSocks)
|
||||||
{
|
{
|
||||||
string result = Utils.GetEmbedText(Global.V2raySampleInbound);
|
string result = Utils.GetEmbedText(Global.V2raySampleInbound);
|
||||||
if (Utils.IsNullOrEmpty(result))
|
if (Utils.IsNullOrEmpty(result))
|
||||||
{
|
{
|
||||||
return null;
|
return new();
|
||||||
}
|
}
|
||||||
|
|
||||||
var inbound = JsonUtils.Deserialize<Inbounds4Ray>(result);
|
var inbound = JsonUtils.Deserialize<Inbounds4Ray>(result);
|
||||||
if (inbound == null)
|
if (inbound == null)
|
||||||
{
|
{
|
||||||
return null;
|
return new();
|
||||||
}
|
}
|
||||||
inbound.tag = protocol.ToString();
|
inbound.tag = protocol.ToString();
|
||||||
inbound.port = inItem.localPort + (int)protocol;
|
inbound.port = inItem.localPort + (int)protocol;
|
||||||
inbound.protocol = bSocks ? EInboundProtocol.socks.ToString() : EInboundProtocol.http.ToString();
|
inbound.protocol = bSocks ? EInboundProtocol.socks.ToString() : EInboundProtocol.http.ToString();
|
||||||
inbound.settings.udp = inItem.udpEnabled;
|
inbound.settings.udp = inItem.udpEnabled;
|
||||||
inbound.sniffing.enabled = inItem.sniffingEnabled;
|
inbound.sniffing.enabled = inItem.sniffingEnabled;
|
||||||
|
inbound.sniffing.destOverride = inItem.destOverride;
|
||||||
inbound.sniffing.routeOnly = inItem.routeOnly;
|
inbound.sniffing.routeOnly = inItem.routeOnly;
|
||||||
|
|
||||||
return inbound;
|
return inbound;
|
||||||
@@ -274,8 +277,8 @@ namespace v2rayN.Handler
|
|||||||
if (!hasDomainIp)
|
if (!hasDomainIp)
|
||||||
{
|
{
|
||||||
if (!Utils.IsNullOrEmpty(rules.port)
|
if (!Utils.IsNullOrEmpty(rules.port)
|
||||||
|| (rules.protocol?.Count > 0)
|
|| rules.protocol?.Count > 0
|
||||||
|| (rules.inboundTag?.Count > 0)
|
|| rules.inboundTag?.Count > 0
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var it = JsonUtils.DeepCopy(rules);
|
var it = JsonUtils.DeepCopy(rules);
|
||||||
@@ -562,6 +565,7 @@ namespace v2rayN.Handler
|
|||||||
publicKey = node.publicKey,
|
publicKey = node.publicKey,
|
||||||
shortId = node.shortId,
|
shortId = node.shortId,
|
||||||
spiderX = node.spiderX,
|
spiderX = node.spiderX,
|
||||||
|
show = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
streamSettings.realitySettings = realitySettings;
|
streamSettings.realitySettings = realitySettings;
|
||||||
@@ -627,6 +631,25 @@ namespace v2rayN.Handler
|
|||||||
}
|
}
|
||||||
streamSettings.httpupgradeSettings = httpupgradeSettings;
|
streamSettings.httpupgradeSettings = httpupgradeSettings;
|
||||||
|
|
||||||
|
break;
|
||||||
|
//splithttp
|
||||||
|
case nameof(ETransport.splithttp):
|
||||||
|
SplithttpSettings4Ray splithttpSettings = new()
|
||||||
|
{
|
||||||
|
maxUploadSize = 1000000,
|
||||||
|
maxConcurrentUploads = 10
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!Utils.IsNullOrEmpty(node.path))
|
||||||
|
{
|
||||||
|
splithttpSettings.path = node.path;
|
||||||
|
}
|
||||||
|
if (!Utils.IsNullOrEmpty(host))
|
||||||
|
{
|
||||||
|
splithttpSettings.host = host;
|
||||||
|
}
|
||||||
|
streamSettings.splithttpSettings = splithttpSettings;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
//h2
|
//h2
|
||||||
case nameof(ETransport.h2):
|
case nameof(ETransport.h2):
|
||||||
@@ -671,7 +694,7 @@ namespace v2rayN.Handler
|
|||||||
{
|
{
|
||||||
authority = Utils.IsNullOrEmpty(host) ? null : host,
|
authority = Utils.IsNullOrEmpty(host) ? null : host,
|
||||||
serviceName = node.path,
|
serviceName = node.path,
|
||||||
multiMode = (node.headerType == Global.GrpcMultiMode),
|
multiMode = node.headerType == Global.GrpcMultiMode,
|
||||||
idle_timeout = _config.grpcItem.idle_timeout,
|
idle_timeout = _config.grpcItem.idle_timeout,
|
||||||
health_check_timeout = _config.grpcItem.health_check_timeout,
|
health_check_timeout = _config.grpcItem.health_check_timeout,
|
||||||
permit_without_stream = _config.grpcItem.permit_without_stream,
|
permit_without_stream = _config.grpcItem.permit_without_stream,
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using v2rayN.Enums;
|
||||||
|
using v2rayN.Handler.CoreConfig;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
|
|
||||||
@@ -39,6 +41,7 @@ namespace v2rayN.Handler
|
|||||||
if (CoreConfigHandler.GenerateClientConfig(node, fileName, out string msg, out string content) != 0)
|
if (CoreConfigHandler.GenerateClientConfig(node, fileName, out string msg, out string content) != 0)
|
||||||
{
|
{
|
||||||
ShowMsg(false, msg);
|
ShowMsg(false, msg);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using System.Net;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using v2rayN.Models;
|
using v2rayN.Enums;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
|
|
||||||
namespace v2rayN.Handler
|
namespace v2rayN.Handler
|
||||||
|
|||||||
203
v2rayN/v2rayN/Handler/Fmt/BaseFmt.cs
Normal file
203
v2rayN/v2rayN/Handler/Fmt/BaseFmt.cs
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.IO;
|
||||||
|
using v2rayN.Enums;
|
||||||
|
using v2rayN.Models;
|
||||||
|
|
||||||
|
namespace v2rayN.Handler.Fmt
|
||||||
|
{
|
||||||
|
internal class BaseFmt
|
||||||
|
{
|
||||||
|
protected static string GetIpv6(string address)
|
||||||
|
{
|
||||||
|
if (Utils.IsIpv6(address))
|
||||||
|
{
|
||||||
|
// 检查地址是否已经被方括号包围,如果没有,则添加方括号
|
||||||
|
return address.StartsWith('[') && address.EndsWith(']') ? address : $"[{address}]";
|
||||||
|
}
|
||||||
|
return address; // 如果不是IPv6地址,直接返回原地址
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static int GetStdTransport(ProfileItem item, string? securityDef, ref Dictionary<string, string> dicQuery)
|
||||||
|
{
|
||||||
|
if (!Utils.IsNullOrEmpty(item.flow))
|
||||||
|
{
|
||||||
|
dicQuery.Add("flow", item.flow);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Utils.IsNullOrEmpty(item.streamSecurity))
|
||||||
|
{
|
||||||
|
dicQuery.Add("security", item.streamSecurity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (securityDef != null)
|
||||||
|
{
|
||||||
|
dicQuery.Add("security", securityDef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!Utils.IsNullOrEmpty(item.sni))
|
||||||
|
{
|
||||||
|
dicQuery.Add("sni", item.sni);
|
||||||
|
}
|
||||||
|
if (!Utils.IsNullOrEmpty(item.alpn))
|
||||||
|
{
|
||||||
|
dicQuery.Add("alpn", Utils.UrlEncode(item.alpn));
|
||||||
|
}
|
||||||
|
if (!Utils.IsNullOrEmpty(item.fingerprint))
|
||||||
|
{
|
||||||
|
dicQuery.Add("fp", Utils.UrlEncode(item.fingerprint));
|
||||||
|
}
|
||||||
|
if (!Utils.IsNullOrEmpty(item.publicKey))
|
||||||
|
{
|
||||||
|
dicQuery.Add("pbk", Utils.UrlEncode(item.publicKey));
|
||||||
|
}
|
||||||
|
if (!Utils.IsNullOrEmpty(item.shortId))
|
||||||
|
{
|
||||||
|
dicQuery.Add("sid", Utils.UrlEncode(item.shortId));
|
||||||
|
}
|
||||||
|
if (!Utils.IsNullOrEmpty(item.spiderX))
|
||||||
|
{
|
||||||
|
dicQuery.Add("spx", Utils.UrlEncode(item.spiderX));
|
||||||
|
}
|
||||||
|
|
||||||
|
dicQuery.Add("type", !Utils.IsNullOrEmpty(item.network) ? item.network : nameof(ETransport.tcp));
|
||||||
|
|
||||||
|
switch (item.network)
|
||||||
|
{
|
||||||
|
case nameof(ETransport.tcp):
|
||||||
|
dicQuery.Add("headerType", !Utils.IsNullOrEmpty(item.headerType) ? item.headerType : Global.None);
|
||||||
|
if (!Utils.IsNullOrEmpty(item.requestHost))
|
||||||
|
{
|
||||||
|
dicQuery.Add("host", Utils.UrlEncode(item.requestHost));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(ETransport.kcp):
|
||||||
|
dicQuery.Add("headerType", !Utils.IsNullOrEmpty(item.headerType) ? item.headerType : Global.None);
|
||||||
|
if (!Utils.IsNullOrEmpty(item.path))
|
||||||
|
{
|
||||||
|
dicQuery.Add("seed", Utils.UrlEncode(item.path));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(ETransport.ws):
|
||||||
|
case nameof(ETransport.httpupgrade):
|
||||||
|
case nameof(ETransport.splithttp):
|
||||||
|
if (!Utils.IsNullOrEmpty(item.requestHost))
|
||||||
|
{
|
||||||
|
dicQuery.Add("host", Utils.UrlEncode(item.requestHost));
|
||||||
|
}
|
||||||
|
if (!Utils.IsNullOrEmpty(item.path))
|
||||||
|
{
|
||||||
|
dicQuery.Add("path", Utils.UrlEncode(item.path));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(ETransport.http):
|
||||||
|
case nameof(ETransport.h2):
|
||||||
|
dicQuery["type"] = nameof(ETransport.http);
|
||||||
|
if (!Utils.IsNullOrEmpty(item.requestHost))
|
||||||
|
{
|
||||||
|
dicQuery.Add("host", Utils.UrlEncode(item.requestHost));
|
||||||
|
}
|
||||||
|
if (!Utils.IsNullOrEmpty(item.path))
|
||||||
|
{
|
||||||
|
dicQuery.Add("path", Utils.UrlEncode(item.path));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(ETransport.quic):
|
||||||
|
dicQuery.Add("headerType", !Utils.IsNullOrEmpty(item.headerType) ? item.headerType : Global.None);
|
||||||
|
dicQuery.Add("quicSecurity", Utils.UrlEncode(item.requestHost));
|
||||||
|
dicQuery.Add("key", Utils.UrlEncode(item.path));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(ETransport.grpc):
|
||||||
|
if (!Utils.IsNullOrEmpty(item.path))
|
||||||
|
{
|
||||||
|
dicQuery.Add("authority", Utils.UrlEncode(item.requestHost));
|
||||||
|
dicQuery.Add("serviceName", Utils.UrlEncode(item.path));
|
||||||
|
if (item.headerType is Global.GrpcGunMode or Global.GrpcMultiMode)
|
||||||
|
{
|
||||||
|
dicQuery.Add("mode", Utils.UrlEncode(item.headerType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static int ResolveStdTransport(NameValueCollection query, ref ProfileItem item)
|
||||||
|
{
|
||||||
|
item.flow = query["flow"] ?? "";
|
||||||
|
item.streamSecurity = query["security"] ?? "";
|
||||||
|
item.sni = query["sni"] ?? "";
|
||||||
|
item.alpn = Utils.UrlDecode(query["alpn"] ?? "");
|
||||||
|
item.fingerprint = Utils.UrlDecode(query["fp"] ?? "");
|
||||||
|
item.publicKey = Utils.UrlDecode(query["pbk"] ?? "");
|
||||||
|
item.shortId = Utils.UrlDecode(query["sid"] ?? "");
|
||||||
|
item.spiderX = Utils.UrlDecode(query["spx"] ?? "");
|
||||||
|
|
||||||
|
item.network = query["type"] ?? nameof(ETransport.tcp);
|
||||||
|
switch (item.network)
|
||||||
|
{
|
||||||
|
case nameof(ETransport.tcp):
|
||||||
|
item.headerType = query["headerType"] ?? Global.None;
|
||||||
|
item.requestHost = Utils.UrlDecode(query["host"] ?? "");
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(ETransport.kcp):
|
||||||
|
item.headerType = query["headerType"] ?? Global.None;
|
||||||
|
item.path = Utils.UrlDecode(query["seed"] ?? "");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(ETransport.ws):
|
||||||
|
case nameof(ETransport.httpupgrade):
|
||||||
|
case nameof(ETransport.splithttp):
|
||||||
|
item.requestHost = Utils.UrlDecode(query["host"] ?? "");
|
||||||
|
item.path = Utils.UrlDecode(query["path"] ?? "/");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(ETransport.http):
|
||||||
|
case nameof(ETransport.h2):
|
||||||
|
item.network = nameof(ETransport.h2);
|
||||||
|
item.requestHost = Utils.UrlDecode(query["host"] ?? "");
|
||||||
|
item.path = Utils.UrlDecode(query["path"] ?? "/");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(ETransport.quic):
|
||||||
|
item.headerType = query["headerType"] ?? Global.None;
|
||||||
|
item.requestHost = query["quicSecurity"] ?? Global.None;
|
||||||
|
item.path = Utils.UrlDecode(query["key"] ?? "");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(ETransport.grpc):
|
||||||
|
item.requestHost = Utils.UrlDecode(query["authority"] ?? "");
|
||||||
|
item.path = Utils.UrlDecode(query["serviceName"] ?? "");
|
||||||
|
item.headerType = Utils.UrlDecode(query["mode"] ?? Global.GrpcGunMode);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static bool Contains(string str, params string[] s)
|
||||||
|
{
|
||||||
|
foreach (var item in s)
|
||||||
|
{
|
||||||
|
if (str.Contains(item, StringComparison.OrdinalIgnoreCase)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static string WriteAllText(string strData, string ext = "json")
|
||||||
|
{
|
||||||
|
var fileName = Utils.GetTempPath($"{Utils.GetGUID(false)}.{ext}");
|
||||||
|
File.WriteAllText(fileName, strData);
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
v2rayN/v2rayN/Handler/Fmt/ClashFmt.cs
Normal file
26
v2rayN/v2rayN/Handler/Fmt/ClashFmt.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using v2rayN.Enums;
|
||||||
|
using v2rayN.Models;
|
||||||
|
|
||||||
|
namespace v2rayN.Handler.Fmt
|
||||||
|
{
|
||||||
|
internal class ClashFmt : BaseFmt
|
||||||
|
{
|
||||||
|
public static ProfileItem? ResolveFull(string strData, string? subRemarks)
|
||||||
|
{
|
||||||
|
if (Contains(strData, "port", "socks-port", "proxies"))
|
||||||
|
{
|
||||||
|
var fileName = WriteAllText(strData, "yaml");
|
||||||
|
|
||||||
|
var profileItem = new ProfileItem
|
||||||
|
{
|
||||||
|
coreType = ECoreType.mihomo,
|
||||||
|
address = fileName,
|
||||||
|
remarks = subRemarks ?? "clash_custom"
|
||||||
|
};
|
||||||
|
return profileItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
94
v2rayN/v2rayN/Handler/Fmt/FmtHandler.cs
Normal file
94
v2rayN/v2rayN/Handler/Fmt/FmtHandler.cs
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
using v2rayN.Enums;
|
||||||
|
using v2rayN.Models;
|
||||||
|
using v2rayN.Resx;
|
||||||
|
|
||||||
|
namespace v2rayN.Handler.Fmt
|
||||||
|
{
|
||||||
|
internal class FmtHandler
|
||||||
|
{
|
||||||
|
public static string? GetShareUri(ProfileItem item)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var url = item.configType switch
|
||||||
|
{
|
||||||
|
EConfigType.VMess => VmessFmt.ToUri(item),
|
||||||
|
EConfigType.Shadowsocks => ShadowsocksFmt.ToUri(item),
|
||||||
|
EConfigType.Socks => SocksFmt.ToUri(item),
|
||||||
|
EConfigType.Trojan => TrojanFmt.ToUri(item),
|
||||||
|
EConfigType.VLESS => VLESSFmt.ToUri(item),
|
||||||
|
EConfigType.Hysteria2 => Hysteria2Fmt.ToUri(item),
|
||||||
|
EConfigType.Tuic => TuicFmt.ToUri(item),
|
||||||
|
EConfigType.Wireguard => WireguardFmt.ToUri(item),
|
||||||
|
_ => null,
|
||||||
|
};
|
||||||
|
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(ex.Message, ex);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProfileItem? ResolveConfig(string config, out string msg)
|
||||||
|
{
|
||||||
|
msg = ResUI.ConfigurationFormatIncorrect;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string str = config.TrimEx();
|
||||||
|
if (Utils.IsNullOrEmpty(str))
|
||||||
|
{
|
||||||
|
msg = ResUI.FailedReadConfiguration;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str.StartsWith(Global.ProtocolShares[EConfigType.VMess]))
|
||||||
|
{
|
||||||
|
return VmessFmt.Resolve(str, out msg);
|
||||||
|
}
|
||||||
|
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Shadowsocks]))
|
||||||
|
{
|
||||||
|
return ShadowsocksFmt.Resolve(str, out msg);
|
||||||
|
}
|
||||||
|
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Socks]))
|
||||||
|
{
|
||||||
|
return SocksFmt.Resolve(str, out msg);
|
||||||
|
}
|
||||||
|
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Trojan]))
|
||||||
|
{
|
||||||
|
return TrojanFmt.Resolve(str, out msg);
|
||||||
|
}
|
||||||
|
else if (str.StartsWith(Global.ProtocolShares[EConfigType.VLESS]))
|
||||||
|
{
|
||||||
|
return VLESSFmt.Resolve(str, out msg);
|
||||||
|
}
|
||||||
|
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Hysteria2]) || str.StartsWith(Global.Hysteria2ProtocolShare))
|
||||||
|
{
|
||||||
|
return Hysteria2Fmt.Resolve(str, out msg);
|
||||||
|
}
|
||||||
|
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Tuic]))
|
||||||
|
{
|
||||||
|
return TuicFmt.Resolve(str, out msg);
|
||||||
|
}
|
||||||
|
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Wireguard]))
|
||||||
|
{
|
||||||
|
return WireguardFmt.Resolve(str, out msg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg = ResUI.NonvmessOrssProtocol;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(ex.Message, ex);
|
||||||
|
msg = ResUI.Incorrectconfiguration;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
104
v2rayN/v2rayN/Handler/Fmt/Hysteria2Fmt.cs
Normal file
104
v2rayN/v2rayN/Handler/Fmt/Hysteria2Fmt.cs
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
using v2rayN.Enums;
|
||||||
|
using v2rayN.Models;
|
||||||
|
using v2rayN.Resx;
|
||||||
|
|
||||||
|
namespace v2rayN.Handler.Fmt
|
||||||
|
{
|
||||||
|
internal class Hysteria2Fmt : BaseFmt
|
||||||
|
{
|
||||||
|
public static ProfileItem? Resolve(string str, out string msg)
|
||||||
|
{
|
||||||
|
msg = ResUI.ConfigurationFormatIncorrect;
|
||||||
|
ProfileItem item = new()
|
||||||
|
{
|
||||||
|
configType = EConfigType.Hysteria2
|
||||||
|
};
|
||||||
|
|
||||||
|
Uri url = new(str);
|
||||||
|
|
||||||
|
item.address = url.IdnHost;
|
||||||
|
item.port = url.Port;
|
||||||
|
item.remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
|
||||||
|
item.id = Utils.UrlDecode(url.UserInfo);
|
||||||
|
|
||||||
|
var query = Utils.ParseQueryString(url.Query);
|
||||||
|
ResolveStdTransport(query, ref item);
|
||||||
|
item.path = Utils.UrlDecode(query["obfs-password"] ?? "");
|
||||||
|
item.allowInsecure = (query["insecure"] ?? "") == "1" ? "true" : "false";
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string? ToUri(ProfileItem? item)
|
||||||
|
{
|
||||||
|
if (item == null) return null;
|
||||||
|
string url = string.Empty;
|
||||||
|
|
||||||
|
string remark = string.Empty;
|
||||||
|
if (!Utils.IsNullOrEmpty(item.remarks))
|
||||||
|
{
|
||||||
|
remark = "#" + Utils.UrlEncode(item.remarks);
|
||||||
|
}
|
||||||
|
var dicQuery = new Dictionary<string, string>();
|
||||||
|
if (!Utils.IsNullOrEmpty(item.sni))
|
||||||
|
{
|
||||||
|
dicQuery.Add("sni", item.sni);
|
||||||
|
}
|
||||||
|
if (!Utils.IsNullOrEmpty(item.alpn))
|
||||||
|
{
|
||||||
|
dicQuery.Add("alpn", Utils.UrlEncode(item.alpn));
|
||||||
|
}
|
||||||
|
if (!Utils.IsNullOrEmpty(item.path))
|
||||||
|
{
|
||||||
|
dicQuery.Add("obfs", "salamander");
|
||||||
|
dicQuery.Add("obfs-password", Utils.UrlEncode(item.path));
|
||||||
|
}
|
||||||
|
dicQuery.Add("insecure", item.allowInsecure.ToLower() == "true" ? "1" : "0");
|
||||||
|
|
||||||
|
string query = "?" + string.Join("&", dicQuery.Select(x => x.Key + "=" + x.Value).ToArray());
|
||||||
|
|
||||||
|
url = string.Format("{0}@{1}:{2}",
|
||||||
|
item.id,
|
||||||
|
GetIpv6(item.address),
|
||||||
|
item.port);
|
||||||
|
url = $"{Global.ProtocolShares[EConfigType.Hysteria2]}{url}/{query}{remark}";
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProfileItem? ResolveFull(string strData, string? subRemarks)
|
||||||
|
{
|
||||||
|
if (Contains(strData, "server", "up", "down", "listen", "<html>", "<body>"))
|
||||||
|
{
|
||||||
|
var fileName = WriteAllText(strData);
|
||||||
|
|
||||||
|
var profileItem = new ProfileItem
|
||||||
|
{
|
||||||
|
coreType = ECoreType.hysteria,
|
||||||
|
address = fileName,
|
||||||
|
remarks = subRemarks ?? "hysteria_custom"
|
||||||
|
};
|
||||||
|
return profileItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProfileItem? ResolveFull2(string strData, string? subRemarks)
|
||||||
|
{
|
||||||
|
if (Contains(strData, "server", "auth", "up", "down", "listen"))
|
||||||
|
{
|
||||||
|
var fileName = WriteAllText(strData);
|
||||||
|
|
||||||
|
var profileItem = new ProfileItem
|
||||||
|
{
|
||||||
|
coreType = ECoreType.hysteria2,
|
||||||
|
address = fileName,
|
||||||
|
remarks = subRemarks ?? "hysteria2_custom"
|
||||||
|
};
|
||||||
|
return profileItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
v2rayN/v2rayN/Handler/Fmt/NaiveproxyFmt.cs
Normal file
26
v2rayN/v2rayN/Handler/Fmt/NaiveproxyFmt.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using v2rayN.Enums;
|
||||||
|
using v2rayN.Models;
|
||||||
|
|
||||||
|
namespace v2rayN.Handler.Fmt
|
||||||
|
{
|
||||||
|
internal class NaiveproxyFmt : BaseFmt
|
||||||
|
{
|
||||||
|
public static ProfileItem? ResolveFull(string strData, string? subRemarks)
|
||||||
|
{
|
||||||
|
if (Contains(strData, "listen", "proxy", "<html>", "<body>"))
|
||||||
|
{
|
||||||
|
var fileName = WriteAllText(strData);
|
||||||
|
|
||||||
|
var profileItem = new ProfileItem
|
||||||
|
{
|
||||||
|
coreType = ECoreType.naiveproxy,
|
||||||
|
address = fileName,
|
||||||
|
remarks = subRemarks ?? "naiveproxy_custom"
|
||||||
|
};
|
||||||
|
return profileItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
183
v2rayN/v2rayN/Handler/Fmt/ShadowsocksFmt.cs
Normal file
183
v2rayN/v2rayN/Handler/Fmt/ShadowsocksFmt.cs
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using v2rayN.Enums;
|
||||||
|
using v2rayN.Models;
|
||||||
|
using v2rayN.Resx;
|
||||||
|
|
||||||
|
namespace v2rayN.Handler.Fmt
|
||||||
|
{
|
||||||
|
internal class ShadowsocksFmt : BaseFmt
|
||||||
|
{
|
||||||
|
public static ProfileItem? Resolve(string str, out string msg)
|
||||||
|
{
|
||||||
|
msg = ResUI.ConfigurationFormatIncorrect;
|
||||||
|
ProfileItem? item;
|
||||||
|
|
||||||
|
item = ResolveSSLegacy(str) ?? ResolveSip002(str);
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (item.address.Length == 0 || item.port == 0 || item.security.Length == 0 || item.id.Length == 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
item.configType = EConfigType.Shadowsocks;
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string? ToUri(ProfileItem? item)
|
||||||
|
{
|
||||||
|
if (item == null) return null;
|
||||||
|
string url = string.Empty;
|
||||||
|
|
||||||
|
string remark = string.Empty;
|
||||||
|
if (!Utils.IsNullOrEmpty(item.remarks))
|
||||||
|
{
|
||||||
|
remark = "#" + Utils.UrlEncode(item.remarks);
|
||||||
|
}
|
||||||
|
//url = string.Format("{0}:{1}@{2}:{3}",
|
||||||
|
// item.security,
|
||||||
|
// item.id,
|
||||||
|
// item.address,
|
||||||
|
// item.port);
|
||||||
|
//url = Utile.Base64Encode(url);
|
||||||
|
//new Sip002
|
||||||
|
var pw = Utils.Base64Encode($"{item.security}:{item.id}");
|
||||||
|
url = $"{pw}@{GetIpv6(item.address)}:{item.port}";
|
||||||
|
url = $"{Global.ProtocolShares[EConfigType.Shadowsocks]}{url}{remark}";
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly Regex UrlFinder = new(@"ss://(?<base64>[A-Za-z0-9+-/=_]+)(?:#(?<tag>\S+))?", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
private static readonly Regex DetailsParser = new(@"^((?<method>.+?):(?<password>.*)@(?<hostname>.+?):(?<port>\d+?))$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
|
||||||
|
private static ProfileItem? ResolveSSLegacy(string result)
|
||||||
|
{
|
||||||
|
var match = UrlFinder.Match(result);
|
||||||
|
if (!match.Success)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
ProfileItem item = new();
|
||||||
|
var base64 = match.Groups["base64"].Value.TrimEnd('/');
|
||||||
|
var tag = match.Groups["tag"].Value;
|
||||||
|
if (!Utils.IsNullOrEmpty(tag))
|
||||||
|
{
|
||||||
|
item.remarks = Utils.UrlDecode(tag);
|
||||||
|
}
|
||||||
|
Match details;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
details = DetailsParser.Match(Utils.Base64Decode(base64));
|
||||||
|
}
|
||||||
|
catch (FormatException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!details.Success)
|
||||||
|
return null;
|
||||||
|
item.security = details.Groups["method"].Value;
|
||||||
|
item.id = details.Groups["password"].Value;
|
||||||
|
item.address = details.Groups["hostname"].Value;
|
||||||
|
item.port = Utils.ToInt(details.Groups["port"].Value);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ProfileItem? ResolveSip002(string result)
|
||||||
|
{
|
||||||
|
Uri parsedUrl;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
parsedUrl = new Uri(result);
|
||||||
|
}
|
||||||
|
catch (UriFormatException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ProfileItem item = new()
|
||||||
|
{
|
||||||
|
remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),
|
||||||
|
address = parsedUrl.IdnHost,
|
||||||
|
port = parsedUrl.Port,
|
||||||
|
};
|
||||||
|
string rawUserInfo = parsedUrl.GetComponents(UriComponents.UserInfo, UriFormat.UriEscaped);
|
||||||
|
//2022-blake3
|
||||||
|
if (rawUserInfo.Contains(':'))
|
||||||
|
{
|
||||||
|
string[] userInfoParts = rawUserInfo.Split(new[] { ':' }, 2);
|
||||||
|
if (userInfoParts.Length != 2)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
item.security = userInfoParts[0];
|
||||||
|
item.id = Utils.UrlDecode(userInfoParts[1]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// parse base64 UserInfo
|
||||||
|
string userInfo = Utils.Base64Decode(rawUserInfo);
|
||||||
|
string[] userInfoParts = userInfo.Split(new[] { ':' }, 2);
|
||||||
|
if (userInfoParts.Length != 2)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
item.security = userInfoParts[0];
|
||||||
|
item.id = userInfoParts[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
var queryParameters = Utils.ParseQueryString(parsedUrl.Query);
|
||||||
|
if (queryParameters["plugin"] != null)
|
||||||
|
{
|
||||||
|
//obfs-host exists
|
||||||
|
var obfsHost = queryParameters["plugin"]?.Split(';').FirstOrDefault(t => t.Contains("obfs-host"));
|
||||||
|
if (queryParameters["plugin"].Contains("obfs=http") && !Utils.IsNullOrEmpty(obfsHost))
|
||||||
|
{
|
||||||
|
obfsHost = obfsHost?.Replace("obfs-host=", "");
|
||||||
|
item.network = Global.DefaultNetwork;
|
||||||
|
item.headerType = Global.TcpHeaderHttp;
|
||||||
|
item.requestHost = obfsHost ?? "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ProfileItem>? ResolveSip008(string result)
|
||||||
|
{
|
||||||
|
//SsSIP008
|
||||||
|
var lstSsServer = JsonUtils.Deserialize<List<SsServer>>(result);
|
||||||
|
if (lstSsServer?.Count <= 0)
|
||||||
|
{
|
||||||
|
var ssSIP008 = JsonUtils.Deserialize<SsSIP008>(result);
|
||||||
|
if (ssSIP008?.servers?.Count > 0)
|
||||||
|
{
|
||||||
|
lstSsServer = ssSIP008.servers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lstSsServer?.Count > 0)
|
||||||
|
{
|
||||||
|
List<ProfileItem> lst = [];
|
||||||
|
foreach (var it in lstSsServer)
|
||||||
|
{
|
||||||
|
var ssItem = new ProfileItem()
|
||||||
|
{
|
||||||
|
remarks = it.remarks,
|
||||||
|
security = it.method,
|
||||||
|
id = it.password,
|
||||||
|
address = it.server,
|
||||||
|
port = Utils.ToInt(it.server_port)
|
||||||
|
};
|
||||||
|
lst.Add(ssItem);
|
||||||
|
}
|
||||||
|
return lst;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
58
v2rayN/v2rayN/Handler/Fmt/SingboxFmt.cs
Normal file
58
v2rayN/v2rayN/Handler/Fmt/SingboxFmt.cs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
using v2rayN.Enums;
|
||||||
|
using v2rayN.Models;
|
||||||
|
|
||||||
|
namespace v2rayN.Handler.Fmt
|
||||||
|
{
|
||||||
|
internal class SingboxFmt : BaseFmt
|
||||||
|
{
|
||||||
|
public static List<ProfileItem>? ResolveFullArray(string strData, string? subRemarks)
|
||||||
|
{
|
||||||
|
var configObjects = JsonUtils.Deserialize<Object[]>(strData);
|
||||||
|
if (configObjects != null && configObjects.Length > 0)
|
||||||
|
{
|
||||||
|
List<ProfileItem> lstResult = [];
|
||||||
|
foreach (var configObject in configObjects)
|
||||||
|
{
|
||||||
|
var objectString = JsonUtils.Serialize(configObject);
|
||||||
|
var singboxCon = JsonUtils.Deserialize<SingboxConfig>(objectString);
|
||||||
|
if (singboxCon?.inbounds?.Count > 0
|
||||||
|
&& singboxCon.outbounds?.Count > 0
|
||||||
|
&& singboxCon.route != null)
|
||||||
|
{
|
||||||
|
var fileName = WriteAllText(objectString);
|
||||||
|
|
||||||
|
var profileIt = new ProfileItem
|
||||||
|
{
|
||||||
|
coreType = ECoreType.sing_box,
|
||||||
|
address = fileName,
|
||||||
|
remarks = subRemarks ?? "singbox_custom",
|
||||||
|
};
|
||||||
|
lstResult.Add(profileIt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lstResult;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProfileItem? ResolveFull(string strData, string? subRemarks)
|
||||||
|
{
|
||||||
|
var singboxConfig = JsonUtils.Deserialize<SingboxConfig>(strData);
|
||||||
|
if (singboxConfig?.inbounds?.Count > 0
|
||||||
|
&& singboxConfig.outbounds?.Count > 0
|
||||||
|
&& singboxConfig.route != null)
|
||||||
|
{
|
||||||
|
var fileName = WriteAllText(strData);
|
||||||
|
var profileItem = new ProfileItem
|
||||||
|
{
|
||||||
|
coreType = ECoreType.sing_box,
|
||||||
|
address = fileName,
|
||||||
|
remarks = subRemarks ?? "singbox_custom"
|
||||||
|
};
|
||||||
|
|
||||||
|
return profileItem;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
131
v2rayN/v2rayN/Handler/Fmt/SocksFmt.cs
Normal file
131
v2rayN/v2rayN/Handler/Fmt/SocksFmt.cs
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
using v2rayN.Enums;
|
||||||
|
using v2rayN.Models;
|
||||||
|
using v2rayN.Resx;
|
||||||
|
|
||||||
|
namespace v2rayN.Handler.Fmt
|
||||||
|
{
|
||||||
|
internal class SocksFmt : BaseFmt
|
||||||
|
{
|
||||||
|
public static ProfileItem? Resolve(string str, out string msg)
|
||||||
|
{
|
||||||
|
msg = ResUI.ConfigurationFormatIncorrect;
|
||||||
|
ProfileItem? item;
|
||||||
|
|
||||||
|
item = ResolveSocksNew(str) ?? ResolveSocks(str);
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (item.address.Length == 0 || item.port == 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
item.configType = EConfigType.Socks;
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string? ToUri(ProfileItem? item)
|
||||||
|
{
|
||||||
|
if (item == null) return null;
|
||||||
|
string url = string.Empty;
|
||||||
|
|
||||||
|
string remark = string.Empty;
|
||||||
|
if (!Utils.IsNullOrEmpty(item.remarks))
|
||||||
|
{
|
||||||
|
remark = "#" + Utils.UrlEncode(item.remarks);
|
||||||
|
}
|
||||||
|
//url = string.Format("{0}:{1}@{2}:{3}",
|
||||||
|
// item.security,
|
||||||
|
// item.id,
|
||||||
|
// item.address,
|
||||||
|
// item.port);
|
||||||
|
//url = Utile.Base64Encode(url);
|
||||||
|
//new
|
||||||
|
var pw = Utils.Base64Encode($"{item.security}:{item.id}");
|
||||||
|
url = $"{pw}@{GetIpv6(item.address)}:{item.port}";
|
||||||
|
url = $"{Global.ProtocolShares[EConfigType.Socks]}{url}{remark}";
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ProfileItem? ResolveSocks(string result)
|
||||||
|
{
|
||||||
|
ProfileItem item = new()
|
||||||
|
{
|
||||||
|
configType = EConfigType.Socks
|
||||||
|
};
|
||||||
|
result = result[Global.ProtocolShares[EConfigType.Socks].Length..];
|
||||||
|
//remark
|
||||||
|
int indexRemark = result.IndexOf("#");
|
||||||
|
if (indexRemark > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
item.remarks = Utils.UrlDecode(result.Substring(indexRemark + 1, result.Length - indexRemark - 1));
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
result = result[..indexRemark];
|
||||||
|
}
|
||||||
|
//part decode
|
||||||
|
int indexS = result.IndexOf("@");
|
||||||
|
if (indexS > 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = Utils.Base64Decode(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] arr1 = result.Split('@');
|
||||||
|
if (arr1.Length != 2)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
string[] arr21 = arr1[0].Split(':');
|
||||||
|
//string[] arr22 = arr1[1].Split(':');
|
||||||
|
int indexPort = arr1[1].LastIndexOf(":");
|
||||||
|
if (arr21.Length != 2 || indexPort < 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
item.address = arr1[1][..indexPort];
|
||||||
|
item.port = Utils.ToInt(arr1[1][(indexPort + 1)..]);
|
||||||
|
item.security = arr21[0];
|
||||||
|
item.id = arr21[1];
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ProfileItem? ResolveSocksNew(string result)
|
||||||
|
{
|
||||||
|
Uri parsedUrl;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
parsedUrl = new Uri(result);
|
||||||
|
}
|
||||||
|
catch (UriFormatException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ProfileItem item = new()
|
||||||
|
{
|
||||||
|
remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),
|
||||||
|
address = parsedUrl.IdnHost,
|
||||||
|
port = parsedUrl.Port,
|
||||||
|
};
|
||||||
|
|
||||||
|
// parse base64 UserInfo
|
||||||
|
string rawUserInfo = parsedUrl.GetComponents(UriComponents.UserInfo, UriFormat.Unescaped);
|
||||||
|
string userInfo = Utils.Base64Decode(rawUserInfo);
|
||||||
|
string[] userInfoParts = userInfo.Split(new[] { ':' }, 2);
|
||||||
|
if (userInfoParts.Length == 2)
|
||||||
|
{
|
||||||
|
item.security = userInfoParts[0];
|
||||||
|
item.id = userInfoParts[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
53
v2rayN/v2rayN/Handler/Fmt/TrojanFmt.cs
Normal file
53
v2rayN/v2rayN/Handler/Fmt/TrojanFmt.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using v2rayN.Enums;
|
||||||
|
using v2rayN.Models;
|
||||||
|
using v2rayN.Resx;
|
||||||
|
|
||||||
|
namespace v2rayN.Handler.Fmt
|
||||||
|
{
|
||||||
|
internal class TrojanFmt : BaseFmt
|
||||||
|
{
|
||||||
|
public static ProfileItem? Resolve(string str, out string msg)
|
||||||
|
{
|
||||||
|
msg = ResUI.ConfigurationFormatIncorrect;
|
||||||
|
|
||||||
|
ProfileItem item = new()
|
||||||
|
{
|
||||||
|
configType = EConfigType.Trojan
|
||||||
|
};
|
||||||
|
|
||||||
|
Uri url = new(str);
|
||||||
|
|
||||||
|
item.address = url.IdnHost;
|
||||||
|
item.port = url.Port;
|
||||||
|
item.remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
|
||||||
|
item.id = Utils.UrlDecode(url.UserInfo);
|
||||||
|
|
||||||
|
var query = Utils.ParseQueryString(url.Query);
|
||||||
|
ResolveStdTransport(query, ref item);
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string? ToUri(ProfileItem? item)
|
||||||
|
{
|
||||||
|
if (item == null) return null;
|
||||||
|
string url = string.Empty;
|
||||||
|
|
||||||
|
string remark = string.Empty;
|
||||||
|
if (!Utils.IsNullOrEmpty(item.remarks))
|
||||||
|
{
|
||||||
|
remark = "#" + Utils.UrlEncode(item.remarks);
|
||||||
|
}
|
||||||
|
var dicQuery = new Dictionary<string, string>();
|
||||||
|
GetStdTransport(item, null, ref dicQuery);
|
||||||
|
string query = "?" + string.Join("&", dicQuery.Select(x => x.Key + "=" + x.Value).ToArray());
|
||||||
|
|
||||||
|
url = string.Format("{0}@{1}:{2}",
|
||||||
|
item.id,
|
||||||
|
GetIpv6(item.address),
|
||||||
|
item.port);
|
||||||
|
url = $"{Global.ProtocolShares[EConfigType.Trojan]}{url}{query}{remark}";
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
68
v2rayN/v2rayN/Handler/Fmt/TuicFmt.cs
Normal file
68
v2rayN/v2rayN/Handler/Fmt/TuicFmt.cs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
using v2rayN.Enums;
|
||||||
|
using v2rayN.Models;
|
||||||
|
using v2rayN.Resx;
|
||||||
|
|
||||||
|
namespace v2rayN.Handler.Fmt
|
||||||
|
{
|
||||||
|
internal class TuicFmt : BaseFmt
|
||||||
|
{
|
||||||
|
public static ProfileItem? Resolve(string str, out string msg)
|
||||||
|
{
|
||||||
|
msg = ResUI.ConfigurationFormatIncorrect;
|
||||||
|
|
||||||
|
ProfileItem item = new()
|
||||||
|
{
|
||||||
|
configType = EConfigType.Tuic
|
||||||
|
};
|
||||||
|
|
||||||
|
Uri url = new(str);
|
||||||
|
|
||||||
|
item.address = url.IdnHost;
|
||||||
|
item.port = url.Port;
|
||||||
|
item.remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
|
||||||
|
var userInfoParts = url.UserInfo.Split(new[] { ':' }, 2);
|
||||||
|
if (userInfoParts.Length == 2)
|
||||||
|
{
|
||||||
|
item.id = userInfoParts[0];
|
||||||
|
item.security = userInfoParts[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
var query = Utils.ParseQueryString(url.Query);
|
||||||
|
ResolveStdTransport(query, ref item);
|
||||||
|
item.headerType = query["congestion_control"] ?? "";
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string? ToUri(ProfileItem? item)
|
||||||
|
{
|
||||||
|
if (item == null) return null;
|
||||||
|
string url = string.Empty;
|
||||||
|
|
||||||
|
string remark = string.Empty;
|
||||||
|
if (!Utils.IsNullOrEmpty(item.remarks))
|
||||||
|
{
|
||||||
|
remark = "#" + Utils.UrlEncode(item.remarks);
|
||||||
|
}
|
||||||
|
var dicQuery = new Dictionary<string, string>();
|
||||||
|
if (!Utils.IsNullOrEmpty(item.sni))
|
||||||
|
{
|
||||||
|
dicQuery.Add("sni", item.sni);
|
||||||
|
}
|
||||||
|
if (!Utils.IsNullOrEmpty(item.alpn))
|
||||||
|
{
|
||||||
|
dicQuery.Add("alpn", Utils.UrlEncode(item.alpn));
|
||||||
|
}
|
||||||
|
dicQuery.Add("congestion_control", item.headerType);
|
||||||
|
|
||||||
|
string query = "?" + string.Join("&", dicQuery.Select(x => x.Key + "=" + x.Value).ToArray());
|
||||||
|
|
||||||
|
url = string.Format("{0}@{1}:{2}",
|
||||||
|
$"{item.id}:{item.security}",
|
||||||
|
GetIpv6(item.address),
|
||||||
|
item.port);
|
||||||
|
url = $"{Global.ProtocolShares[EConfigType.Tuic]}{url}{query}{remark}";
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
59
v2rayN/v2rayN/Handler/Fmt/V2rayFmt.cs
Normal file
59
v2rayN/v2rayN/Handler/Fmt/V2rayFmt.cs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
using v2rayN.Enums;
|
||||||
|
using v2rayN.Models;
|
||||||
|
|
||||||
|
namespace v2rayN.Handler.Fmt
|
||||||
|
{
|
||||||
|
internal class V2rayFmt : BaseFmt
|
||||||
|
{
|
||||||
|
public static List<ProfileItem>? ResolveFullArray(string strData, string? subRemarks)
|
||||||
|
{
|
||||||
|
var configObjects = JsonUtils.Deserialize<Object[]>(strData);
|
||||||
|
if (configObjects != null && configObjects.Length > 0)
|
||||||
|
{
|
||||||
|
List<ProfileItem> lstResult = [];
|
||||||
|
foreach (var configObject in configObjects)
|
||||||
|
{
|
||||||
|
var objectString = JsonUtils.Serialize(configObject);
|
||||||
|
var v2rayCon = JsonUtils.Deserialize<V2rayConfig>(objectString);
|
||||||
|
if (v2rayCon?.inbounds?.Count > 0
|
||||||
|
&& v2rayCon.outbounds?.Count > 0
|
||||||
|
&& v2rayCon.routing != null)
|
||||||
|
{
|
||||||
|
var fileName = WriteAllText(objectString);
|
||||||
|
|
||||||
|
var profileIt = new ProfileItem
|
||||||
|
{
|
||||||
|
coreType = ECoreType.Xray,
|
||||||
|
address = fileName,
|
||||||
|
remarks = v2rayCon.remarks ?? subRemarks ?? "v2ray_custom",
|
||||||
|
};
|
||||||
|
lstResult.Add(profileIt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lstResult;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProfileItem? ResolveFull(string strData, string? subRemarks)
|
||||||
|
{
|
||||||
|
var v2rayConfig = JsonUtils.Deserialize<V2rayConfig>(strData);
|
||||||
|
if (v2rayConfig?.inbounds?.Count > 0
|
||||||
|
&& v2rayConfig.outbounds?.Count > 0
|
||||||
|
&& v2rayConfig.routing != null)
|
||||||
|
{
|
||||||
|
var fileName = WriteAllText(strData);
|
||||||
|
|
||||||
|
var profileItem = new ProfileItem
|
||||||
|
{
|
||||||
|
coreType = ECoreType.Xray,
|
||||||
|
address = fileName,
|
||||||
|
remarks = v2rayConfig.remarks ?? subRemarks ?? "v2ray_custom"
|
||||||
|
};
|
||||||
|
|
||||||
|
return profileItem;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
64
v2rayN/v2rayN/Handler/Fmt/VLESSFmt.cs
Normal file
64
v2rayN/v2rayN/Handler/Fmt/VLESSFmt.cs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
using v2rayN.Enums;
|
||||||
|
using v2rayN.Models;
|
||||||
|
using v2rayN.Resx;
|
||||||
|
|
||||||
|
namespace v2rayN.Handler.Fmt
|
||||||
|
{
|
||||||
|
internal class VLESSFmt : BaseFmt
|
||||||
|
{
|
||||||
|
public static ProfileItem? Resolve(string str, out string msg)
|
||||||
|
{
|
||||||
|
msg = ResUI.ConfigurationFormatIncorrect;
|
||||||
|
|
||||||
|
ProfileItem item = new()
|
||||||
|
{
|
||||||
|
configType = EConfigType.VLESS,
|
||||||
|
security = Global.None
|
||||||
|
};
|
||||||
|
|
||||||
|
Uri url = new(str);
|
||||||
|
|
||||||
|
item.address = url.IdnHost;
|
||||||
|
item.port = url.Port;
|
||||||
|
item.remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
|
||||||
|
item.id = Utils.UrlDecode(url.UserInfo);
|
||||||
|
|
||||||
|
var query = Utils.ParseQueryString(url.Query);
|
||||||
|
item.security = query["encryption"] ?? Global.None;
|
||||||
|
item.streamSecurity = query["security"] ?? "";
|
||||||
|
ResolveStdTransport(query, ref item);
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string? ToUri(ProfileItem? item)
|
||||||
|
{
|
||||||
|
if (item == null) return null;
|
||||||
|
string url = string.Empty;
|
||||||
|
|
||||||
|
string remark = string.Empty;
|
||||||
|
if (!Utils.IsNullOrEmpty(item.remarks))
|
||||||
|
{
|
||||||
|
remark = "#" + Utils.UrlEncode(item.remarks);
|
||||||
|
}
|
||||||
|
var dicQuery = new Dictionary<string, string>();
|
||||||
|
if (!Utils.IsNullOrEmpty(item.security))
|
||||||
|
{
|
||||||
|
dicQuery.Add("encryption", item.security);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dicQuery.Add("encryption", Global.None);
|
||||||
|
}
|
||||||
|
GetStdTransport(item, Global.None, ref dicQuery);
|
||||||
|
string query = "?" + string.Join("&", dicQuery.Select(x => x.Key + "=" + x.Value).ToArray());
|
||||||
|
|
||||||
|
url = string.Format("{0}@{1}:{2}",
|
||||||
|
item.id,
|
||||||
|
GetIpv6(item.address),
|
||||||
|
item.port);
|
||||||
|
url = $"{Global.ProtocolShares[EConfigType.VLESS]}{url}{query}{remark}";
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
229
v2rayN/v2rayN/Handler/Fmt/VmessFmt.cs
Normal file
229
v2rayN/v2rayN/Handler/Fmt/VmessFmt.cs
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using v2rayN.Enums;
|
||||||
|
using v2rayN.Models;
|
||||||
|
using v2rayN.Resx;
|
||||||
|
|
||||||
|
namespace v2rayN.Handler.Fmt
|
||||||
|
{
|
||||||
|
internal class VmessFmt : BaseFmt
|
||||||
|
{
|
||||||
|
private static readonly Regex StdVmessUserInfo = new(
|
||||||
|
@"^(?<network>[a-z]+)(\+(?<streamSecurity>[a-z]+))?:(?<id>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$", RegexOptions.Compiled);
|
||||||
|
|
||||||
|
public static ProfileItem? Resolve(string str, out string msg)
|
||||||
|
{
|
||||||
|
msg = ResUI.ConfigurationFormatIncorrect;
|
||||||
|
ProfileItem? item;
|
||||||
|
int indexSplit = str.IndexOf("?");
|
||||||
|
if (indexSplit > 0)
|
||||||
|
{
|
||||||
|
item = ResolveStdVmess(str) ?? ResolveVmess4Kitsunebi(str);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item = ResolveVmess(str, out msg);
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string? ToUri(ProfileItem? item)
|
||||||
|
{
|
||||||
|
if (item == null) return null;
|
||||||
|
string url = string.Empty;
|
||||||
|
|
||||||
|
VmessQRCode vmessQRCode = new()
|
||||||
|
{
|
||||||
|
v = item.configVersion,
|
||||||
|
ps = item.remarks.TrimEx(),
|
||||||
|
add = item.address,
|
||||||
|
port = item.port,
|
||||||
|
id = item.id,
|
||||||
|
aid = item.alterId,
|
||||||
|
scy = item.security,
|
||||||
|
net = item.network,
|
||||||
|
type = item.headerType,
|
||||||
|
host = item.requestHost,
|
||||||
|
path = item.path,
|
||||||
|
tls = item.streamSecurity,
|
||||||
|
sni = item.sni,
|
||||||
|
alpn = item.alpn,
|
||||||
|
fp = item.fingerprint
|
||||||
|
};
|
||||||
|
|
||||||
|
url = JsonUtils.Serialize(vmessQRCode);
|
||||||
|
url = Utils.Base64Encode(url);
|
||||||
|
url = $"{Global.ProtocolShares[EConfigType.VMess]}{url}";
|
||||||
|
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ProfileItem? ResolveVmess(string result, out string msg)
|
||||||
|
{
|
||||||
|
msg = string.Empty;
|
||||||
|
var item = new ProfileItem
|
||||||
|
{
|
||||||
|
configType = EConfigType.VMess
|
||||||
|
};
|
||||||
|
|
||||||
|
result = result[Global.ProtocolShares[EConfigType.VMess].Length..];
|
||||||
|
result = Utils.Base64Decode(result);
|
||||||
|
|
||||||
|
//转成Json
|
||||||
|
VmessQRCode? vmessQRCode = JsonUtils.Deserialize<VmessQRCode>(result);
|
||||||
|
if (vmessQRCode == null)
|
||||||
|
{
|
||||||
|
msg = ResUI.FailedConversionConfiguration;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
item.network = Global.DefaultNetwork;
|
||||||
|
item.headerType = Global.None;
|
||||||
|
|
||||||
|
item.configVersion = Utils.ToInt(vmessQRCode.v);
|
||||||
|
item.remarks = Utils.ToString(vmessQRCode.ps);
|
||||||
|
item.address = Utils.ToString(vmessQRCode.add);
|
||||||
|
item.port = Utils.ToInt(vmessQRCode.port);
|
||||||
|
item.id = Utils.ToString(vmessQRCode.id);
|
||||||
|
item.alterId = Utils.ToInt(vmessQRCode.aid);
|
||||||
|
item.security = Utils.ToString(vmessQRCode.scy);
|
||||||
|
|
||||||
|
item.security = !Utils.IsNullOrEmpty(vmessQRCode.scy) ? vmessQRCode.scy : Global.DefaultSecurity;
|
||||||
|
if (!Utils.IsNullOrEmpty(vmessQRCode.net))
|
||||||
|
{
|
||||||
|
item.network = vmessQRCode.net;
|
||||||
|
}
|
||||||
|
if (!Utils.IsNullOrEmpty(vmessQRCode.type))
|
||||||
|
{
|
||||||
|
item.headerType = vmessQRCode.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
item.requestHost = Utils.ToString(vmessQRCode.host);
|
||||||
|
item.path = Utils.ToString(vmessQRCode.path);
|
||||||
|
item.streamSecurity = Utils.ToString(vmessQRCode.tls);
|
||||||
|
item.sni = Utils.ToString(vmessQRCode.sni);
|
||||||
|
item.alpn = Utils.ToString(vmessQRCode.alpn);
|
||||||
|
item.fingerprint = Utils.ToString(vmessQRCode.fp);
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ProfileItem? ResolveStdVmess(string result)
|
||||||
|
{
|
||||||
|
ProfileItem item = new()
|
||||||
|
{
|
||||||
|
configType = EConfigType.VMess,
|
||||||
|
security = "auto"
|
||||||
|
};
|
||||||
|
|
||||||
|
Uri u = new(result);
|
||||||
|
|
||||||
|
item.address = u.IdnHost;
|
||||||
|
item.port = u.Port;
|
||||||
|
item.remarks = u.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
|
||||||
|
var query = Utils.ParseQueryString(u.Query);
|
||||||
|
|
||||||
|
var m = StdVmessUserInfo.Match(u.UserInfo);
|
||||||
|
if (!m.Success) return null;
|
||||||
|
|
||||||
|
item.id = m.Groups["id"].Value;
|
||||||
|
|
||||||
|
if (m.Groups["streamSecurity"].Success)
|
||||||
|
{
|
||||||
|
item.streamSecurity = m.Groups["streamSecurity"].Value;
|
||||||
|
}
|
||||||
|
switch (item.streamSecurity)
|
||||||
|
{
|
||||||
|
case Global.StreamSecurity:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (!Utils.IsNullOrEmpty(item.streamSecurity))
|
||||||
|
return null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
item.network = m.Groups["network"].Value;
|
||||||
|
switch (item.network)
|
||||||
|
{
|
||||||
|
case nameof(ETransport.tcp):
|
||||||
|
string t1 = query["type"] ?? Global.None;
|
||||||
|
item.headerType = t1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(ETransport.kcp):
|
||||||
|
item.headerType = query["type"] ?? Global.None;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(ETransport.ws):
|
||||||
|
case nameof(ETransport.httpupgrade):
|
||||||
|
case nameof(ETransport.splithttp):
|
||||||
|
string p1 = query["path"] ?? "/";
|
||||||
|
string h1 = query["host"] ?? "";
|
||||||
|
item.requestHost = Utils.UrlDecode(h1);
|
||||||
|
item.path = p1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(ETransport.http):
|
||||||
|
case nameof(ETransport.h2):
|
||||||
|
item.network = nameof(ETransport.h2);
|
||||||
|
string p2 = query["path"] ?? "/";
|
||||||
|
string h2 = query["host"] ?? "";
|
||||||
|
item.requestHost = Utils.UrlDecode(h2);
|
||||||
|
item.path = p2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(ETransport.quic):
|
||||||
|
string s = query["security"] ?? Global.None;
|
||||||
|
string k = query["key"] ?? "";
|
||||||
|
string t3 = query["type"] ?? Global.None;
|
||||||
|
item.headerType = t3;
|
||||||
|
item.requestHost = Utils.UrlDecode(s);
|
||||||
|
item.path = k;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ProfileItem? ResolveVmess4Kitsunebi(string result)
|
||||||
|
{
|
||||||
|
ProfileItem item = new()
|
||||||
|
{
|
||||||
|
configType = EConfigType.VMess
|
||||||
|
};
|
||||||
|
result = result[Global.ProtocolShares[EConfigType.VMess].Length..];
|
||||||
|
int indexSplit = result.IndexOf("?");
|
||||||
|
if (indexSplit > 0)
|
||||||
|
{
|
||||||
|
result = result[..indexSplit];
|
||||||
|
}
|
||||||
|
result = Utils.Base64Decode(result);
|
||||||
|
|
||||||
|
string[] arr1 = result.Split('@');
|
||||||
|
if (arr1.Length != 2)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
string[] arr21 = arr1[0].Split(':');
|
||||||
|
string[] arr22 = arr1[1].Split(':');
|
||||||
|
if (arr21.Length != 2 || arr22.Length != 2)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
item.address = arr22[0];
|
||||||
|
item.port = Utils.ToInt(arr22[1]);
|
||||||
|
item.security = arr21[0];
|
||||||
|
item.id = arr21[1];
|
||||||
|
|
||||||
|
item.network = Global.DefaultNetwork;
|
||||||
|
item.headerType = Global.None;
|
||||||
|
item.remarks = "Alien";
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
73
v2rayN/v2rayN/Handler/Fmt/WireguardFmt.cs
Normal file
73
v2rayN/v2rayN/Handler/Fmt/WireguardFmt.cs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
using v2rayN.Enums;
|
||||||
|
using v2rayN.Models;
|
||||||
|
using v2rayN.Resx;
|
||||||
|
|
||||||
|
namespace v2rayN.Handler.Fmt
|
||||||
|
{
|
||||||
|
internal class WireguardFmt : BaseFmt
|
||||||
|
{
|
||||||
|
public static ProfileItem? Resolve(string str, out string msg)
|
||||||
|
{
|
||||||
|
msg = ResUI.ConfigurationFormatIncorrect;
|
||||||
|
|
||||||
|
ProfileItem item = new()
|
||||||
|
{
|
||||||
|
configType = EConfigType.Wireguard
|
||||||
|
};
|
||||||
|
|
||||||
|
Uri url = new(str);
|
||||||
|
|
||||||
|
item.address = url.IdnHost;
|
||||||
|
item.port = url.Port;
|
||||||
|
item.remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
|
||||||
|
item.id = Utils.UrlDecode(url.UserInfo);
|
||||||
|
|
||||||
|
var query = Utils.ParseQueryString(url.Query);
|
||||||
|
|
||||||
|
item.publicKey = Utils.UrlDecode(query["publickey"] ?? "");
|
||||||
|
item.path = Utils.UrlDecode(query["reserved"] ?? "");
|
||||||
|
item.requestHost = Utils.UrlDecode(query["address"] ?? "");
|
||||||
|
item.shortId = Utils.UrlDecode(query["mtu"] ?? "");
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string? ToUri(ProfileItem? item)
|
||||||
|
{
|
||||||
|
if (item == null) return null;
|
||||||
|
string url = string.Empty;
|
||||||
|
|
||||||
|
string remark = string.Empty;
|
||||||
|
if (!Utils.IsNullOrEmpty(item.remarks))
|
||||||
|
{
|
||||||
|
remark = "#" + Utils.UrlEncode(item.remarks);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dicQuery = new Dictionary<string, string>();
|
||||||
|
if (!Utils.IsNullOrEmpty(item.publicKey))
|
||||||
|
{
|
||||||
|
dicQuery.Add("publickey", Utils.UrlEncode(item.publicKey));
|
||||||
|
}
|
||||||
|
if (!Utils.IsNullOrEmpty(item.path))
|
||||||
|
{
|
||||||
|
dicQuery.Add("reserved", Utils.UrlEncode(item.path));
|
||||||
|
}
|
||||||
|
if (!Utils.IsNullOrEmpty(item.requestHost))
|
||||||
|
{
|
||||||
|
dicQuery.Add("address", Utils.UrlEncode(item.requestHost));
|
||||||
|
}
|
||||||
|
if (!Utils.IsNullOrEmpty(item.shortId))
|
||||||
|
{
|
||||||
|
dicQuery.Add("mtu", Utils.UrlEncode(item.shortId));
|
||||||
|
}
|
||||||
|
string query = "?" + string.Join("&", dicQuery.Select(x => x.Key + "=" + x.Value).ToArray());
|
||||||
|
|
||||||
|
url = string.Format("{0}@{1}:{2}",
|
||||||
|
Utils.UrlEncode(item.id),
|
||||||
|
GetIpv6(item.address),
|
||||||
|
item.port);
|
||||||
|
url = $"{Global.ProtocolShares[EConfigType.Wireguard]}{url}/{query}{remark}";
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ using System.Text;
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Interop;
|
using System.Windows.Interop;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Runtime.Intrinsics.X86;
|
using System.Runtime.Intrinsics.X86;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
|
|
||||||
namespace v2rayN.Handler
|
namespace v2rayN.Handler
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ using Splat;
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
|
using v2rayN.Enums;
|
||||||
|
using v2rayN.Handler.CoreConfig;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
|
|
||||||
namespace v2rayN.Handler
|
namespace v2rayN.Handler
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Grpc.Core;
|
using Grpc.Core;
|
||||||
using Grpc.Net.Client;
|
using Grpc.Net.Client;
|
||||||
using ProtosLib.Statistics;
|
using ProtosLib.Statistics;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
|
|
||||||
namespace v2rayN.Handler
|
namespace v2rayN.Handler
|
||||||
@@ -86,6 +87,8 @@ namespace v2rayN.Handler
|
|||||||
private void ParseOutput(Google.Protobuf.Collections.RepeatedField<Stat> source, out ServerSpeedItem server)
|
private void ParseOutput(Google.Protobuf.Collections.RepeatedField<Stat> source, out ServerSpeedItem server)
|
||||||
{
|
{
|
||||||
server = new();
|
server = new();
|
||||||
|
long aggregateProxyUp = 0;
|
||||||
|
long aggregateProxyDown = 0;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach (Stat stat in source)
|
foreach (Stat stat in source)
|
||||||
@@ -100,15 +103,15 @@ namespace v2rayN.Handler
|
|||||||
name = nStr[1];
|
name = nStr[1];
|
||||||
type = nStr[3];
|
type = nStr[3];
|
||||||
|
|
||||||
if (name == Global.ProxyTag)
|
if (name.StartsWith(Global.ProxyTag))
|
||||||
{
|
{
|
||||||
if (type == "uplink")
|
if (type == "uplink")
|
||||||
{
|
{
|
||||||
server.proxyUp = value;
|
aggregateProxyUp += value;
|
||||||
}
|
}
|
||||||
else if (type == "downlink")
|
else if (type == "downlink")
|
||||||
{
|
{
|
||||||
server.proxyDown = value;
|
aggregateProxyDown += value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (name == Global.DirectTag)
|
else if (name == Global.DirectTag)
|
||||||
@@ -123,6 +126,8 @@ namespace v2rayN.Handler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
server.proxyUp = aggregateProxyUp;
|
||||||
|
server.proxyDown = aggregateProxyDown;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using PacLib;
|
using PacLib;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
|
|
||||||
namespace v2rayN.Handler
|
namespace v2rayN.Handler
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using System.Runtime.InteropServices;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
|
|
||||||
@@ -299,9 +300,6 @@ namespace v2rayN.Handler
|
|||||||
{
|
{
|
||||||
await UpdateGeoFile("geosite", _config, update);
|
await UpdateGeoFile("geosite", _config, update);
|
||||||
await UpdateGeoFile("geoip", _config, update);
|
await UpdateGeoFile("geoip", _config, update);
|
||||||
|
|
||||||
//await UpdateGeoFile4Singbox("geosite", _config, false, update);
|
|
||||||
//await UpdateGeoFile4Singbox("geoip", _config, true, update);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,7 +325,7 @@ namespace v2rayN.Handler
|
|||||||
var result = await (new DownloadHandle()).DownloadStringAsync(url, true, "");
|
var result = await (new DownloadHandle()).DownloadStringAsync(url, true, "");
|
||||||
if (!Utils.IsNullOrEmpty(result))
|
if (!Utils.IsNullOrEmpty(result))
|
||||||
{
|
{
|
||||||
responseHandler(type, result, preRelease);
|
ResponseHandler(type, result, preRelease);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -345,7 +343,7 @@ namespace v2rayN.Handler
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取V2RayCore版本
|
/// 获取V2RayCore版本
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private SemanticVersion getCoreVersion(ECoreType type)
|
private SemanticVersion GetCoreVersion(ECoreType type)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -410,7 +408,7 @@ namespace v2rayN.Handler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void responseHandler(ECoreType type, string gitHubReleaseApi, bool preRelease)
|
private void ResponseHandler(ECoreType type, string gitHubReleaseApi, bool preRelease)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -431,7 +429,7 @@ namespace v2rayN.Handler
|
|||||||
case ECoreType.Xray:
|
case ECoreType.Xray:
|
||||||
case ECoreType.v2fly_v5:
|
case ECoreType.v2fly_v5:
|
||||||
{
|
{
|
||||||
curVersion = getCoreVersion(type);
|
curVersion = GetCoreVersion(type);
|
||||||
message = string.Format(ResUI.IsLatestCore, type, curVersion.ToVersionString("v"));
|
message = string.Format(ResUI.IsLatestCore, type, curVersion.ToVersionString("v"));
|
||||||
string osBit = "64";
|
string osBit = "64";
|
||||||
switch (RuntimeInformation.ProcessArchitecture)
|
switch (RuntimeInformation.ProcessArchitecture)
|
||||||
@@ -456,7 +454,7 @@ namespace v2rayN.Handler
|
|||||||
case ECoreType.clash_meta:
|
case ECoreType.clash_meta:
|
||||||
case ECoreType.mihomo:
|
case ECoreType.mihomo:
|
||||||
{
|
{
|
||||||
curVersion = getCoreVersion(type);
|
curVersion = GetCoreVersion(type);
|
||||||
message = string.Format(ResUI.IsLatestCore, type, curVersion);
|
message = string.Format(ResUI.IsLatestCore, type, curVersion);
|
||||||
switch (RuntimeInformation.ProcessArchitecture)
|
switch (RuntimeInformation.ProcessArchitecture)
|
||||||
{
|
{
|
||||||
@@ -477,7 +475,7 @@ namespace v2rayN.Handler
|
|||||||
}
|
}
|
||||||
case ECoreType.sing_box:
|
case ECoreType.sing_box:
|
||||||
{
|
{
|
||||||
curVersion = getCoreVersion(type);
|
curVersion = GetCoreVersion(type);
|
||||||
message = string.Format(ResUI.IsLatestCore, type, curVersion.ToVersionString("v"));
|
message = string.Format(ResUI.IsLatestCore, type, curVersion.ToVersionString("v"));
|
||||||
switch (RuntimeInformation.ProcessArchitecture)
|
switch (RuntimeInformation.ProcessArchitecture)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
namespace v2rayN.Models
|
using v2rayN.Enums;
|
||||||
|
|
||||||
|
namespace v2rayN.Models
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 本软件配置文件实体类
|
/// 本软件配置文件实体类
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
using v2rayN.Enums;
|
||||||
|
|
||||||
namespace v2rayN.Models
|
namespace v2rayN.Models
|
||||||
{
|
{
|
||||||
@@ -47,8 +48,8 @@ namespace v2rayN.Models
|
|||||||
public bool udpEnabled { get; set; }
|
public bool udpEnabled { get; set; }
|
||||||
|
|
||||||
public bool sniffingEnabled { get; set; } = true;
|
public bool sniffingEnabled { get; set; } = true;
|
||||||
|
public List<string>? destOverride { get; set; } = ["http", "tls"];
|
||||||
public bool routeOnly { get; set; }
|
public bool routeOnly { get; set; }
|
||||||
|
|
||||||
public bool allowLANConn { get; set; }
|
public bool allowLANConn { get; set; }
|
||||||
|
|
||||||
public bool newPort4LAN { get; set; }
|
public bool newPort4LAN { get; set; }
|
||||||
@@ -186,7 +187,7 @@ namespace v2rayN.Models
|
|||||||
public string domainStrategy4Singbox { get; set; }
|
public string domainStrategy4Singbox { get; set; }
|
||||||
public string domainMatcher { get; set; }
|
public string domainMatcher { get; set; }
|
||||||
public string routingIndexId { get; set; }
|
public string routingIndexId { get; set; }
|
||||||
public bool enableRoutingAdvanced { get; set; }
|
public bool enableRoutingAdvanced { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
|||||||
@@ -1,440 +0,0 @@
|
|||||||
namespace v2rayN.Models
|
|
||||||
{
|
|
||||||
[Serializable]
|
|
||||||
public class ConfigOld
|
|
||||||
{
|
|
||||||
#region property
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 允许日志
|
|
||||||
/// </summary>
|
|
||||||
public bool logEnabled
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 日志等级
|
|
||||||
/// </summary>
|
|
||||||
public string loglevel
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string indexId
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 允许Mux多路复用
|
|
||||||
/// </summary>
|
|
||||||
public bool muxEnabled
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public ESysProxyType sysProxyType
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 启用实时网速和流量统计
|
|
||||||
/// </summary>
|
|
||||||
public bool enableStatistics
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 去重时优先保留较旧(顶部)节点
|
|
||||||
/// </summary>
|
|
||||||
public bool keepOlderDedupl
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 视图刷新率
|
|
||||||
/// </summary>
|
|
||||||
public int statisticsFreshRate
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 自定义远程DNS
|
|
||||||
/// </summary>
|
|
||||||
public string remoteDNS
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Outbound Freedom domainStrategy
|
|
||||||
/// </summary>
|
|
||||||
public string domainStrategy4Freedom
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否允许不安全连接
|
|
||||||
/// </summary>
|
|
||||||
public bool defAllowInsecure
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 域名解析策略
|
|
||||||
/// </summary>
|
|
||||||
public string domainStrategy
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string domainMatcher
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int routingIndex
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool enableRoutingAdvanced
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ignoreGeoUpdateCore
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// systemProxyExceptions
|
|
||||||
/// </summary>
|
|
||||||
public string systemProxyExceptions
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string systemProxyAdvancedProtocol { get; set; }
|
|
||||||
|
|
||||||
public int autoUpdateInterval { get; set; } = 0;
|
|
||||||
|
|
||||||
public int autoUpdateSubInterval { get; set; } = 0;
|
|
||||||
|
|
||||||
public bool checkPreReleaseUpdate { get; set; } = false;
|
|
||||||
|
|
||||||
public bool enableSecurityProtocolTls13
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int trayMenuServersLimit { get; set; }
|
|
||||||
|
|
||||||
#endregion property
|
|
||||||
|
|
||||||
#region other entities
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 本地监听
|
|
||||||
/// </summary>
|
|
||||||
public List<InItem> inbound
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// vmess服务器信息
|
|
||||||
/// </summary>
|
|
||||||
public List<VmessItem> vmess
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// KcpItem
|
|
||||||
/// </summary>
|
|
||||||
public KcpItem kcpItem
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 订阅
|
|
||||||
/// </summary>
|
|
||||||
public List<SubItem> subItem
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// UI
|
|
||||||
/// </summary>
|
|
||||||
public UIItem uiItem
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<RoutingItemOld> routings
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConstItem constItem
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<KeyEventItem> globalHotkeys
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<CoreTypeItem> coreTypeItem
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion other entities
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class VmessItem
|
|
||||||
{
|
|
||||||
public VmessItem()
|
|
||||||
{
|
|
||||||
indexId = string.Empty;
|
|
||||||
configType = EConfigType.VMess;
|
|
||||||
configVersion = 2;
|
|
||||||
sort = 0;
|
|
||||||
address = string.Empty;
|
|
||||||
port = 0;
|
|
||||||
id = string.Empty;
|
|
||||||
alterId = 0;
|
|
||||||
security = string.Empty;
|
|
||||||
network = string.Empty;
|
|
||||||
remarks = string.Empty;
|
|
||||||
headerType = string.Empty;
|
|
||||||
requestHost = string.Empty;
|
|
||||||
path = string.Empty;
|
|
||||||
streamSecurity = string.Empty;
|
|
||||||
allowInsecure = string.Empty;
|
|
||||||
testResult = string.Empty;
|
|
||||||
subid = string.Empty;
|
|
||||||
flow = string.Empty;
|
|
||||||
groupId = string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string indexId
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// config type(1=normal,2=custom)
|
|
||||||
/// </summary>
|
|
||||||
public EConfigType configType
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 版本(现在=2)
|
|
||||||
/// </summary>
|
|
||||||
public int configVersion
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int sort
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 远程服务器地址
|
|
||||||
/// </summary>
|
|
||||||
public string address
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 远程服务器端口
|
|
||||||
/// </summary>
|
|
||||||
public int port
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 远程服务器ID
|
|
||||||
/// </summary>
|
|
||||||
public string id
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 远程服务器额外ID
|
|
||||||
/// </summary>
|
|
||||||
public int alterId
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 本地安全策略
|
|
||||||
/// </summary>
|
|
||||||
public string security
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// tcp,kcp,ws,h2,quic
|
|
||||||
/// </summary>
|
|
||||||
public string network
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string remarks
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 伪装类型
|
|
||||||
/// </summary>
|
|
||||||
public string headerType
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 伪装的域名
|
|
||||||
/// </summary>
|
|
||||||
public string requestHost
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// ws h2 path
|
|
||||||
/// </summary>
|
|
||||||
public string path
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 传输层安全
|
|
||||||
/// </summary>
|
|
||||||
public string streamSecurity
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否允许不安全连接(用于客户端)
|
|
||||||
/// </summary>
|
|
||||||
public string allowInsecure
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string testResult
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// SubItem id
|
|
||||||
/// </summary>
|
|
||||||
public string subid
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// VLESS flow
|
|
||||||
/// </summary>
|
|
||||||
public string flow
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// tls sni
|
|
||||||
/// </summary>
|
|
||||||
public string sni
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string groupId
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
} = string.Empty;
|
|
||||||
|
|
||||||
public ECoreType? coreType
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int preSocksPort
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string fingerprint { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class RoutingItemOld
|
|
||||||
{
|
|
||||||
public string remarks
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string url
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<RulesItem> rules
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool enabled { get; set; } = true;
|
|
||||||
|
|
||||||
public bool locked
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string customIcon
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
namespace v2rayN.Models
|
using v2rayN.Enums;
|
||||||
|
|
||||||
|
namespace v2rayN.Models
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class CoreInfo
|
public class CoreInfo
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using SQLite;
|
using SQLite;
|
||||||
|
using v2rayN.Enums;
|
||||||
|
|
||||||
namespace v2rayN.Models
|
namespace v2rayN.Models
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using SQLite;
|
using SQLite;
|
||||||
|
using v2rayN.Enums;
|
||||||
|
|
||||||
namespace v2rayN.Models
|
namespace v2rayN.Models
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
namespace v2rayN.Models
|
using v2rayN.Enums;
|
||||||
|
|
||||||
|
namespace v2rayN.Models
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
internal class ServerTestItem
|
internal class ServerTestItem
|
||||||
|
|||||||
@@ -95,7 +95,7 @@
|
|||||||
{
|
{
|
||||||
public string type { get; set; }
|
public string type { get; set; }
|
||||||
public string tag { get; set; }
|
public string tag { get; set; }
|
||||||
public string server { get; set; }
|
public string? server { get; set; }
|
||||||
public int? server_port { get; set; }
|
public int? server_port { get; set; }
|
||||||
public string uuid { get; set; }
|
public string uuid { get; set; }
|
||||||
public string security { get; set; }
|
public string security { get; set; }
|
||||||
@@ -241,6 +241,6 @@
|
|||||||
public string? path { get; set; }
|
public string? path { get; set; }
|
||||||
public string? url { get; set; }
|
public string? url { get; set; }
|
||||||
public string? download_detour { get; set; }
|
public string? download_detour { get; set; }
|
||||||
public string? update_interval { get; set; }
|
public string? update_interval { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,7 +195,7 @@ namespace v2rayN.Models
|
|||||||
public class Sniffing4Ray
|
public class Sniffing4Ray
|
||||||
{
|
{
|
||||||
public bool enabled { get; set; }
|
public bool enabled { get; set; }
|
||||||
public List<string> destOverride { get; set; }
|
public List<string>? destOverride { get; set; }
|
||||||
public bool routeOnly { get; set; }
|
public bool routeOnly { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,47 +421,52 @@ namespace v2rayN.Models
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TlsSettings4Ray tlsSettings { get; set; }
|
public TlsSettings4Ray? tlsSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tcp传输额外设置
|
/// Tcp传输额外设置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TcpSettings4Ray tcpSettings { get; set; }
|
public TcpSettings4Ray? tcpSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Kcp传输额外设置
|
/// Kcp传输额外设置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public KcpSettings4Ray kcpSettings { get; set; }
|
public KcpSettings4Ray? kcpSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ws传输额外设置
|
/// ws传输额外设置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public WsSettings4Ray wsSettings { get; set; }
|
public WsSettings4Ray? wsSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public HttpupgradeSettings4Ray? httpupgradeSettings { get; set; }
|
public HttpupgradeSettings4Ray? httpupgradeSettings { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public SplithttpSettings4Ray? splithttpSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// h2传输额外设置
|
/// h2传输额外设置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public HttpSettings4Ray httpSettings { get; set; }
|
public HttpSettings4Ray? httpSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// QUIC
|
/// QUIC
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public QuicSettings4Ray quicSettings { get; set; }
|
public QuicSettings4Ray? quicSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// VLESS only
|
/// VLESS only
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TlsSettings4Ray realitySettings { get; set; }
|
public TlsSettings4Ray? realitySettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// grpc
|
/// grpc
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public GrpcSettings4Ray grpcSettings { get; set; }
|
public GrpcSettings4Ray? grpcSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// sockopt
|
/// sockopt
|
||||||
@@ -488,7 +493,7 @@ namespace v2rayN.Models
|
|||||||
|
|
||||||
public string? fingerprint { get; set; }
|
public string? fingerprint { get; set; }
|
||||||
|
|
||||||
public bool? show { get; set; } = false;
|
public bool? show { get; set; }
|
||||||
public string? publicKey { get; set; }
|
public string? publicKey { get; set; }
|
||||||
public string? shortId { get; set; }
|
public string? shortId { get; set; }
|
||||||
public string? spiderX { get; set; }
|
public string? spiderX { get; set; }
|
||||||
@@ -608,6 +613,17 @@ namespace v2rayN.Models
|
|||||||
public string? host { get; set; }
|
public string? host { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class SplithttpSettings4Ray
|
||||||
|
{
|
||||||
|
public string? path { get; set; }
|
||||||
|
|
||||||
|
public string? host { get; set; }
|
||||||
|
|
||||||
|
public int? maxUploadSize { get; set; }
|
||||||
|
|
||||||
|
public int? maxConcurrentUploads { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class HttpSettings4Ray
|
public class HttpSettings4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
4
v2rayN/v2rayN/Resx/ResUI.Designer.cs
generated
4
v2rayN/v2rayN/Resx/ResUI.Designer.cs
generated
@@ -3266,7 +3266,7 @@ namespace v2rayN.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 *ws/httpupgrade path 的本地化字符串。
|
/// 查找类似 *ws/httpupgrade/splithttp path 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TransportPathTip1 {
|
public static string TransportPathTip1 {
|
||||||
get {
|
get {
|
||||||
@@ -3320,7 +3320,7 @@ namespace v2rayN.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 *ws/httpupgrade host 的本地化字符串。
|
/// 查找类似 *ws/httpupgrade/splithttp host 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TransportRequestHostTip2 {
|
public static string TransportRequestHostTip2 {
|
||||||
get {
|
get {
|
||||||
|
|||||||
@@ -359,7 +359,7 @@
|
|||||||
<value>Please fill in the correct custom DNS</value>
|
<value>Please fill in the correct custom DNS</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportPathTip1" xml:space="preserve">
|
<data name="TransportPathTip1" xml:space="preserve">
|
||||||
<value>*ws/httpupgrade path</value>
|
<value>*ws/httpupgrade/splithttp path</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportPathTip2" xml:space="preserve">
|
<data name="TransportPathTip2" xml:space="preserve">
|
||||||
<value>*h2 path</value>
|
<value>*h2 path</value>
|
||||||
@@ -374,7 +374,7 @@
|
|||||||
<value>*http host Separated by commas (,)</value>
|
<value>*http host Separated by commas (,)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportRequestHostTip2" xml:space="preserve">
|
<data name="TransportRequestHostTip2" xml:space="preserve">
|
||||||
<value>*ws/httpupgrade host</value>
|
<value>*ws/httpupgrade/splithttp host</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportRequestHostTip3" xml:space="preserve">
|
<data name="TransportRequestHostTip3" xml:space="preserve">
|
||||||
<value>*h2 host Separated by commas (,)</value>
|
<value>*h2 host Separated by commas (,)</value>
|
||||||
|
|||||||
@@ -359,7 +359,7 @@
|
|||||||
<value>请填写正确的自定义DNS</value>
|
<value>请填写正确的自定义DNS</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportPathTip1" xml:space="preserve">
|
<data name="TransportPathTip1" xml:space="preserve">
|
||||||
<value>*ws/httpupgrade path</value>
|
<value>*ws/httpupgrade/splithttp path</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportPathTip2" xml:space="preserve">
|
<data name="TransportPathTip2" xml:space="preserve">
|
||||||
<value>*h2 path</value>
|
<value>*h2 path</value>
|
||||||
@@ -374,7 +374,7 @@
|
|||||||
<value>*http host中间逗号(,)分隔</value>
|
<value>*http host中间逗号(,)分隔</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportRequestHostTip2" xml:space="preserve">
|
<data name="TransportRequestHostTip2" xml:space="preserve">
|
||||||
<value>*ws/httpupgrade host</value>
|
<value>*ws/httpupgrade/splithttp host</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportRequestHostTip3" xml:space="preserve">
|
<data name="TransportRequestHostTip3" xml:space="preserve">
|
||||||
<value>*h2 host中间逗号(,)分隔</value>
|
<value>*h2 host中间逗号(,)分隔</value>
|
||||||
|
|||||||
@@ -358,7 +358,7 @@
|
|||||||
<value>請填寫正確的自訂DNS</value>
|
<value>請填寫正確的自訂DNS</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportPathTip1" xml:space="preserve">
|
<data name="TransportPathTip1" xml:space="preserve">
|
||||||
<value>*ws/httpupgrade path</value>
|
<value>*ws/httpupgrade/splithttp path</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportPathTip2" xml:space="preserve">
|
<data name="TransportPathTip2" xml:space="preserve">
|
||||||
<value>*h2 path</value>
|
<value>*h2 path</value>
|
||||||
@@ -373,7 +373,7 @@
|
|||||||
<value>*http host中間逗號(,)分隔</value>
|
<value>*http host中間逗號(,)分隔</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportRequestHostTip2" xml:space="preserve">
|
<data name="TransportRequestHostTip2" xml:space="preserve">
|
||||||
<value>*ws/httpupgrade host</value>
|
<value>*ws/httpupgrade/splithttp host</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportRequestHostTip3" xml:space="preserve">
|
<data name="TransportRequestHostTip3" xml:space="preserve">
|
||||||
<value>*h2 host中間逗號(,)分隔</value>
|
<value>*h2 host中間逗號(,)分隔</value>
|
||||||
|
|||||||
@@ -4,56 +4,7 @@
|
|||||||
"error": "Verror.log",
|
"error": "Verror.log",
|
||||||
"loglevel": "warning"
|
"loglevel": "warning"
|
||||||
},
|
},
|
||||||
"inbounds": [{
|
"inbounds": [],
|
||||||
"tag": "tag1",
|
|
||||||
"port": 10808,
|
|
||||||
"protocol": "socks",
|
|
||||||
"listen": "127.0.0.1",
|
|
||||||
"settings": {
|
|
||||||
"auth": "noauth",
|
|
||||||
"udp": true
|
|
||||||
},
|
|
||||||
"sniffing": {
|
|
||||||
"enabled": true,
|
|
||||||
"destOverride": [
|
|
||||||
"http",
|
|
||||||
"tls"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tag": "tag2",
|
|
||||||
"port": 10809,
|
|
||||||
"protocol": "http",
|
|
||||||
"listen": "127.0.0.1",
|
|
||||||
"settings": {
|
|
||||||
"allowTransparent": false
|
|
||||||
},
|
|
||||||
"sniffing": {
|
|
||||||
"enabled": true,
|
|
||||||
"destOverride": [
|
|
||||||
"http",
|
|
||||||
"tls"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tag": "tag3",
|
|
||||||
"port": 10809,
|
|
||||||
"protocol": "http",
|
|
||||||
"listen": "127.0.0.1",
|
|
||||||
"settings": {
|
|
||||||
"allowTransparent": false
|
|
||||||
},
|
|
||||||
"sniffing": {
|
|
||||||
"enabled": true,
|
|
||||||
"destOverride": [
|
|
||||||
"http",
|
|
||||||
"tls"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outbounds": [{
|
"outbounds": [{
|
||||||
"tag": "proxy",
|
"tag": "proxy",
|
||||||
"protocol": "vmess",
|
"protocol": "vmess",
|
||||||
|
|||||||
@@ -3,14 +3,7 @@
|
|||||||
"level": "debug",
|
"level": "debug",
|
||||||
"timestamp": true
|
"timestamp": true
|
||||||
},
|
},
|
||||||
"inbounds": [
|
"inbounds": [],
|
||||||
{
|
|
||||||
"type": "socks",
|
|
||||||
"tag": "socks",
|
|
||||||
"listen": "127.0.0.1",
|
|
||||||
"listen_port": 10000
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outbounds": [
|
"outbounds": [
|
||||||
{
|
{
|
||||||
"type": "vless",
|
"type": "vless",
|
||||||
|
|||||||
@@ -30,5 +30,6 @@
|
|||||||
],
|
],
|
||||||
"server": "block"
|
"server": "block"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"final": "local"
|
||||||
}
|
}
|
||||||
@@ -30,5 +30,6 @@
|
|||||||
],
|
],
|
||||||
"server": "block"
|
"server": "block"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"final": "local"
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ using ReactiveUI.Fody.Helpers;
|
|||||||
using Splat;
|
using Splat;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Handler;
|
using v2rayN.Handler;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using ReactiveUI.Fody.Helpers;
|
|||||||
using Splat;
|
using Splat;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Handler;
|
using v2rayN.Handler;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ using System.Reactive.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Handler;
|
using v2rayN.Handler;
|
||||||
|
using v2rayN.Handler.Fmt;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
using v2rayN.Views;
|
using v2rayN.Views;
|
||||||
@@ -1026,10 +1028,10 @@ namespace v2rayN.ViewModels
|
|||||||
{
|
{
|
||||||
ShowHideWindow(false);
|
ShowHideWindow(false);
|
||||||
|
|
||||||
var dpiXY = Utils.GetDpiXY(Application.Current.MainWindow);
|
var dpiXY = QRCodeHelper.GetDpiXY(Application.Current.MainWindow);
|
||||||
string result = await Task.Run(() =>
|
string result = await Task.Run(() =>
|
||||||
{
|
{
|
||||||
return Utils.ScanScreen(dpiXY.Item1, dpiXY.Item2);
|
return QRCodeHelper.ScanScreen(dpiXY.Item1, dpiXY.Item2);
|
||||||
});
|
});
|
||||||
|
|
||||||
ShowHideWindow(true);
|
ShowHideWindow(true);
|
||||||
@@ -1152,7 +1154,7 @@ namespace v2rayN.ViewModels
|
|||||||
_noticeHandler?.Enqueue(ResUI.PleaseSelectServer);
|
_noticeHandler?.Enqueue(ResUI.PleaseSelectServer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var url = ShareHandler.GetShareUrl(item);
|
var url = FmtHandler.GetShareUri(item);
|
||||||
if (Utils.IsNullOrEmpty(url))
|
if (Utils.IsNullOrEmpty(url))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -1293,7 +1295,7 @@ namespace v2rayN.ViewModels
|
|||||||
StringBuilder sb = new();
|
StringBuilder sb = new();
|
||||||
foreach (var it in lstSelecteds)
|
foreach (var it in lstSelecteds)
|
||||||
{
|
{
|
||||||
string url = ShareHandler.GetShareUrl(it);
|
string url = FmtHandler.GetShareUri(it);
|
||||||
if (Utils.IsNullOrEmpty(url))
|
if (Utils.IsNullOrEmpty(url))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -1318,7 +1320,7 @@ namespace v2rayN.ViewModels
|
|||||||
StringBuilder sb = new();
|
StringBuilder sb = new();
|
||||||
foreach (var it in lstSelecteds)
|
foreach (var it in lstSelecteds)
|
||||||
{
|
{
|
||||||
string? url = ShareHandler.GetShareUrl(it);
|
string? url = FmtHandler.GetShareUri(it);
|
||||||
if (Utils.IsNullOrEmpty(url))
|
if (Utils.IsNullOrEmpty(url))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using ReactiveUI.Fody.Helpers;
|
|||||||
using Splat;
|
using Splat;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Handler;
|
using v2rayN.Handler;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
@@ -20,6 +21,7 @@ namespace v2rayN.ViewModels
|
|||||||
[Reactive] public int localPort { get; set; }
|
[Reactive] public int localPort { get; set; }
|
||||||
[Reactive] public bool udpEnabled { get; set; }
|
[Reactive] public bool udpEnabled { get; set; }
|
||||||
[Reactive] public bool sniffingEnabled { get; set; }
|
[Reactive] public bool sniffingEnabled { get; set; }
|
||||||
|
public IList<string> destOverride { get; set; }
|
||||||
[Reactive] public bool routeOnly { get; set; }
|
[Reactive] public bool routeOnly { get; set; }
|
||||||
[Reactive] public bool allowLANConn { get; set; }
|
[Reactive] public bool allowLANConn { get; set; }
|
||||||
[Reactive] public bool newPort4LAN { get; set; }
|
[Reactive] public bool newPort4LAN { get; set; }
|
||||||
@@ -262,7 +264,7 @@ namespace v2rayN.ViewModels
|
|||||||
var needReboot = (EnableStatistics != _config.guiItem.enableStatistics
|
var needReboot = (EnableStatistics != _config.guiItem.enableStatistics
|
||||||
|| EnableDragDropSort != _config.uiItem.enableDragDropSort
|
|| EnableDragDropSort != _config.uiItem.enableDragDropSort
|
||||||
|| EnableHWA != _config.guiItem.enableHWA
|
|| EnableHWA != _config.guiItem.enableHWA
|
||||||
|| CurrentFontFamily != _config.uiItem.currentFontFamily);
|
|| CurrentFontFamily != _config.uiItem.currentFontFamily);
|
||||||
|
|
||||||
//if (Utile.IsNullOrEmpty(Kcpmtu.ToString()) || !Utile.IsNumeric(Kcpmtu.ToString())
|
//if (Utile.IsNullOrEmpty(Kcpmtu.ToString()) || !Utile.IsNumeric(Kcpmtu.ToString())
|
||||||
// || Utile.IsNullOrEmpty(Kcptti.ToString()) || !Utile.IsNumeric(Kcptti.ToString())
|
// || Utile.IsNullOrEmpty(Kcptti.ToString()) || !Utile.IsNumeric(Kcptti.ToString())
|
||||||
@@ -279,6 +281,7 @@ namespace v2rayN.ViewModels
|
|||||||
_config.inbound[0].localPort = localPort;
|
_config.inbound[0].localPort = localPort;
|
||||||
_config.inbound[0].udpEnabled = udpEnabled;
|
_config.inbound[0].udpEnabled = udpEnabled;
|
||||||
_config.inbound[0].sniffingEnabled = sniffingEnabled;
|
_config.inbound[0].sniffingEnabled = sniffingEnabled;
|
||||||
|
_config.inbound[0].destOverride = destOverride?.ToList();
|
||||||
_config.inbound[0].routeOnly = routeOnly;
|
_config.inbound[0].routeOnly = routeOnly;
|
||||||
_config.inbound[0].allowLANConn = allowLANConn;
|
_config.inbound[0].allowLANConn = allowLANConn;
|
||||||
_config.inbound[0].newPort4LAN = newPort4LAN;
|
_config.inbound[0].newPort4LAN = newPort4LAN;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using ReactiveUI.Fody.Helpers;
|
|||||||
using Splat;
|
using Splat;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Handler;
|
using v2rayN.Handler;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
@@ -289,7 +290,7 @@ namespace v2rayN.ViewModels
|
|||||||
|
|
||||||
private void ImportRulesFromClipboard()
|
private void ImportRulesFromClipboard()
|
||||||
{
|
{
|
||||||
string clipboardData = Utils.GetClipboardData();
|
var clipboardData = Utils.GetClipboardData();
|
||||||
if (AddBatchRoutingRules(SelectedRouting, clipboardData) == 0)
|
if (AddBatchRoutingRules(SelectedRouting, clipboardData) == 0)
|
||||||
{
|
{
|
||||||
RefreshRulesItems();
|
RefreshRulesItems();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.ViewModels;
|
using v2rayN.ViewModels;
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Handler;
|
using v2rayN.Handler;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
@@ -332,6 +333,7 @@ namespace v2rayN.Views
|
|||||||
|
|
||||||
case nameof(ETransport.ws):
|
case nameof(ETransport.ws):
|
||||||
case nameof(ETransport.httpupgrade):
|
case nameof(ETransport.httpupgrade):
|
||||||
|
case nameof(ETransport.splithttp):
|
||||||
tipRequestHost.Text = ResUI.TransportRequestHostTip2;
|
tipRequestHost.Text = ResUI.TransportRequestHostTip2;
|
||||||
tipPath.Text = ResUI.TransportPathTip1;
|
tipPath.Text = ResUI.TransportPathTip1;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace v2rayN.Views
|
|||||||
|
|
||||||
private void linkDnsObjectDoc_Click(object sender, RoutedEventArgs e)
|
private void linkDnsObjectDoc_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Utils.ProcessStart("https://www.v2fly.org/config/dns.html#dnsobject");
|
Utils.ProcessStart("https://xtls.github.io/config/dns.html#dnsobject");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void linkDnsSingboxObjectDoc_Click(object sender, RoutedEventArgs e)
|
private void linkDnsSingboxObjectDoc_Click(object sender, RoutedEventArgs e)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Handler;
|
using v2rayN.Handler;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
<materialDesign:DialogHost
|
<materialDesign:DialogHost
|
||||||
Identifier="RootDialog"
|
Identifier="RootDialog"
|
||||||
|
materialDesign:TransitionAssist.DisableTransitions="True"
|
||||||
SnackbarMessageQueue="{Binding ElementName=MainSnackbar, Path=MessageQueue}"
|
SnackbarMessageQueue="{Binding ElementName=MainSnackbar, Path=MessageQueue}"
|
||||||
Style="{StaticResource MaterialDesignEmbeddedDialogHost}">
|
Style="{StaticResource MaterialDesignEmbeddedDialogHost}">
|
||||||
<Grid>
|
<Grid>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using System.Windows.Input;
|
|||||||
using System.Windows.Interop;
|
using System.Windows.Interop;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using v2rayN.Base;
|
using v2rayN.Base;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Handler;
|
using v2rayN.Handler;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
|
|||||||
@@ -119,12 +119,22 @@
|
|||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Style="{StaticResource ToolbarTextBlock}"
|
Style="{StaticResource ToolbarTextBlock}"
|
||||||
Text="{x:Static resx:ResUI.TbSettingsSniffingEnabled}" />
|
Text="{x:Static resx:ResUI.TbSettingsSniffingEnabled}" />
|
||||||
<ToggleButton
|
<StackPanel
|
||||||
x:Name="togsniffingEnabled"
|
|
||||||
Grid.Row="2"
|
Grid.Row="2"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Margin="{StaticResource SettingItemMargin}"
|
Grid.ColumnSpan="2"
|
||||||
HorizontalAlignment="Left" />
|
Orientation="Horizontal">
|
||||||
|
<ToggleButton
|
||||||
|
x:Name="togsniffingEnabled"
|
||||||
|
Margin="{StaticResource SettingItemMargin}"
|
||||||
|
HorizontalAlignment="Left" />
|
||||||
|
<ListBox
|
||||||
|
x:Name="clbdestOverride"
|
||||||
|
Margin="4"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
FontSize="{DynamicResource StdFontSize}"
|
||||||
|
Style="{StaticResource MaterialDesignFilterChipPrimaryListBox}" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="3"
|
Grid.Row="3"
|
||||||
|
|||||||
@@ -34,6 +34,15 @@ namespace v2rayN.Views
|
|||||||
|
|
||||||
ViewModel = new OptionSettingViewModel(this);
|
ViewModel = new OptionSettingViewModel(this);
|
||||||
|
|
||||||
|
clbdestOverride.SelectionChanged += ClbdestOverride_SelectionChanged;
|
||||||
|
Global.destOverrideProtocols.ForEach(it =>
|
||||||
|
{
|
||||||
|
clbdestOverride.Items.Add(it);
|
||||||
|
});
|
||||||
|
_config.inbound[0].destOverride?.ForEach(it =>
|
||||||
|
{
|
||||||
|
clbdestOverride.SelectedItems.Add(it);
|
||||||
|
});
|
||||||
Global.IEProxyProtocols.ForEach(it =>
|
Global.IEProxyProtocols.ForEach(it =>
|
||||||
{
|
{
|
||||||
cmbsystemProxyAdvancedProtocol.Items.Add(it);
|
cmbsystemProxyAdvancedProtocol.Items.Add(it);
|
||||||
@@ -213,5 +222,10 @@ namespace v2rayN.Views
|
|||||||
}
|
}
|
||||||
return lstFonts;
|
return lstFonts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ClbdestOverride_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
ViewModel.destOverride = clbdestOverride.SelectedItems.Cast<string>().ToList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ namespace v2rayN.Views
|
|||||||
|
|
||||||
private void linkRuleobjectDoc_Click(object sender, RoutedEventArgs e)
|
private void linkRuleobjectDoc_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Utils.ProcessStart("https://www.v2fly.org/config/routing.html#ruleobject");
|
Utils.ProcessStart("https://xtls.github.io/config/routing.html#ruleobject");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
using v2rayN.Enums;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.ViewModels;
|
using v2rayN.ViewModels;
|
||||||
|
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ namespace v2rayN.Views
|
|||||||
|
|
||||||
private void linkdomainStrategy_Click(object sender, System.Windows.RoutedEventArgs e)
|
private void linkdomainStrategy_Click(object sender, System.Windows.RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Utils.ProcessStart("https://www.v2fly.org/config/routing.html");
|
Utils.ProcessStart("https://xtls.github.io/config/routing.html");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void linkdomainStrategy4Singbox_Click(object sender, RoutedEventArgs e)
|
private void linkdomainStrategy4Singbox_Click(object sender, RoutedEventArgs e)
|
||||||
|
|||||||
@@ -23,7 +23,10 @@
|
|||||||
TextOptions.TextRenderingMode="Auto"
|
TextOptions.TextRenderingMode="Auto"
|
||||||
WindowStartupLocation="CenterScreen"
|
WindowStartupLocation="CenterScreen"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
<materialDesign:DialogHost Identifier="SubDialog" Style="{StaticResource MaterialDesignEmbeddedDialogHost}">
|
<materialDesign:DialogHost
|
||||||
|
materialDesign:TransitionAssist.DisableTransitions="True"
|
||||||
|
Identifier="SubDialog"
|
||||||
|
Style="{StaticResource MaterialDesignEmbeddedDialogHost}">
|
||||||
<DockPanel>
|
<DockPanel>
|
||||||
<ToolBarTray DockPanel.Dock="Top">
|
<ToolBarTray DockPanel.Dock="Top">
|
||||||
<ToolBar
|
<ToolBar
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<ApplicationIcon>v2rayN.ico</ApplicationIcon>
|
<ApplicationIcon>v2rayN.ico</ApplicationIcon>
|
||||||
<Copyright>Copyright © 2017-2024 (GPLv3)</Copyright>
|
<Copyright>Copyright © 2017-2024 (GPLv3)</Copyright>
|
||||||
<FileVersion>6.44</FileVersion>
|
<FileVersion>6.46</FileVersion>
|
||||||
<SupportedOSPlatformVersion>7.0</SupportedOSPlatformVersion>
|
<SupportedOSPlatformVersion>7.0</SupportedOSPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
@@ -23,9 +23,9 @@
|
|||||||
<PackageReference Include="TaskScheduler" Version="2.11.0" />
|
<PackageReference Include="TaskScheduler" Version="2.11.0" />
|
||||||
<PackageReference Include="ZXing.Net.Bindings.Windows.Compatibility" Version="0.16.12" />
|
<PackageReference Include="ZXing.Net.Bindings.Windows.Compatibility" Version="0.16.12" />
|
||||||
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
|
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
|
||||||
<PackageReference Include="ReactiveUI.Validation" Version="4.0.6" />
|
<PackageReference Include="ReactiveUI.Validation" Version="4.0.9" />
|
||||||
<PackageReference Include="ReactiveUI.WPF" Version="20.0.1" />
|
<PackageReference Include="ReactiveUI.WPF" Version="20.1.1" />
|
||||||
<PackageReference Include="Splat.NLog" Version="15.0.1" />
|
<PackageReference Include="Splat.NLog" Version="15.1.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user