diff --git a/v2rayN/AmazTool/Program.cs b/v2rayN/AmazTool/Program.cs
index cbfc1332..eb4b29a4 100644
--- a/v2rayN/AmazTool/Program.cs
+++ b/v2rayN/AmazTool/Program.cs
@@ -1,29 +1,29 @@
-namespace AmazTool
+namespace AmazTool
{
- internal static class Program
- {
- ///
- /// 应用程序的主入口点。
- ///
- [STAThread]
- private static void Main(string[] args)
- {
- if (args.Length == 0)
- {
- Console.WriteLine(Resx.Resource.Guidelines);
- Thread.Sleep(5000);
- return;
- }
+ internal static class Program
+ {
+ ///
+ /// 应用程序的主入口点。
+ ///
+ [STAThread]
+ private static void Main(string[] args)
+ {
+ if (args.Length == 0)
+ {
+ Console.WriteLine(Resx.Resource.Guidelines);
+ Thread.Sleep(5000);
+ return;
+ }
- var argData = Uri.UnescapeDataString(string.Join(" ", args));
- if (argData.Equals("rebootas"))
- {
- Thread.Sleep(1000);
- Utils.StartV2RayN();
- return;
- }
+ var argData = Uri.UnescapeDataString(string.Join(" ", args));
+ if (argData.Equals("rebootas"))
+ {
+ Thread.Sleep(1000);
+ Utils.StartV2RayN();
+ return;
+ }
- UpgradeApp.Upgrade(argData);
- }
- }
-}
\ No newline at end of file
+ UpgradeApp.Upgrade(argData);
+ }
+ }
+}
diff --git a/v2rayN/AmazTool/Resx/Resource.Designer.cs b/v2rayN/AmazTool/Resx/Resource.Designer.cs
index e13c70b6..62cd075f 100644
--- a/v2rayN/AmazTool/Resx/Resource.Designer.cs
+++ b/v2rayN/AmazTool/Resx/Resource.Designer.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
//
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
@@ -9,163 +9,163 @@
//------------------------------------------------------------------------------
namespace AmazTool.Resx {
- using System;
-
-
- ///
- /// 一个强类型的资源类,用于查找本地化的字符串等。
- ///
- // 此类是由 StronglyTypedResourceBuilder
- // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
- // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
- // (以 /str 作为命令选项),或重新生成 VS 项目。
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- internal class Resource {
-
- private static global::System.Resources.ResourceManager resourceMan;
-
- private static global::System.Globalization.CultureInfo resourceCulture;
-
- [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- internal Resource() {
- }
-
- ///
- /// 返回此类使用的缓存的 ResourceManager 实例。
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager {
- get {
- if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AmazTool.Resx.Resource", typeof(Resource).Assembly);
- resourceMan = temp;
- }
- return resourceMan;
- }
- }
-
- ///
- /// 重写当前线程的 CurrentUICulture 属性,对
- /// 使用此强类型资源类的所有资源查找执行重写。
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture {
- get {
- return resourceCulture;
- }
- set {
- resourceCulture = value;
- }
- }
-
- ///
- /// 查找类似 Failed to terminate the v2rayN.Close it manually,or the upgrade may fail. 的本地化字符串。
- ///
- internal static string FailedTerminateProcess {
- get {
- return ResourceManager.GetString("FailedTerminateProcess", resourceCulture);
- }
- }
-
- ///
- /// 查找类似 Failed to extract the update package. 的本地化字符串。
- ///
- internal static string FailedUnzipping {
- get {
- return ResourceManager.GetString("FailedUnzipping", resourceCulture);
- }
- }
-
- ///
- /// 查找类似 Upgrade failed. 的本地化字符串。
- ///
- internal static string FailedUpgrade {
- get {
- return ResourceManager.GetString("FailedUpgrade", resourceCulture);
- }
- }
-
- ///
- /// 查找类似 Please run it from the main application. 的本地化字符串。
- ///
- internal static string Guidelines {
- get {
- return ResourceManager.GetString("Guidelines", resourceCulture);
- }
- }
-
- ///
- /// 查找类似 Information 的本地化字符串。
- ///
- internal static string Information {
- get {
- return ResourceManager.GetString("Information", resourceCulture);
- }
- }
-
- ///
- /// 查找类似 In progress, please wait... 的本地化字符串。
- ///
- internal static string InProgress {
- get {
- return ResourceManager.GetString("InProgress", resourceCulture);
- }
- }
-
- ///
- /// 查找类似 Start v2rayN, please wait... 的本地化字符串。
- ///
- internal static string Restartv2rayN {
- get {
- return ResourceManager.GetString("Restartv2rayN", resourceCulture);
- }
- }
-
- ///
- /// 查找类似 Start extracting the update package... 的本地化字符串。
- ///
- internal static string StartUnzipping {
- get {
- return ResourceManager.GetString("StartUnzipping", resourceCulture);
- }
- }
-
- ///
- /// 查找类似 Successfully extracted the update package. 的本地化字符串。
- ///
- internal static string SuccessUnzipping {
- get {
- return ResourceManager.GetString("SuccessUnzipping", resourceCulture);
- }
- }
-
- ///
- /// 查找类似 Upgrade success. 的本地化字符串。
- ///
- internal static string SuccessUpgrade {
- get {
- return ResourceManager.GetString("SuccessUpgrade", resourceCulture);
- }
- }
-
- ///
- /// 查找类似 Try to terminate the v2rayN process... 的本地化字符串。
- ///
- internal static string TryTerminateProcess {
- get {
- return ResourceManager.GetString("TryTerminateProcess", resourceCulture);
- }
- }
-
- ///
- /// 查找类似 Upgrade failed, file not found. 的本地化字符串。
- ///
- internal static string UpgradeFileNotFound {
- get {
- return ResourceManager.GetString("UpgradeFileNotFound", resourceCulture);
- }
- }
- }
+ using System;
+
+
+ ///
+ /// 一个强类型的资源类,用于查找本地化的字符串等。
+ ///
+ // 此类是由 StronglyTypedResourceBuilder
+ // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
+ // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
+ // (以 /str 作为命令选项),或重新生成 VS 项目。
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resource {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resource() {
+ }
+
+ ///
+ /// 返回此类使用的缓存的 ResourceManager 实例。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AmazTool.Resx.Resource", typeof(Resource).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// 重写当前线程的 CurrentUICulture 属性,对
+ /// 使用此强类型资源类的所有资源查找执行重写。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// 查找类似 Failed to terminate the v2rayN.Close it manually,or the upgrade may fail. 的本地化字符串。
+ ///
+ internal static string FailedTerminateProcess {
+ get {
+ return ResourceManager.GetString("FailedTerminateProcess", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 Failed to extract the update package. 的本地化字符串。
+ ///
+ internal static string FailedUnzipping {
+ get {
+ return ResourceManager.GetString("FailedUnzipping", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 Upgrade failed. 的本地化字符串。
+ ///
+ internal static string FailedUpgrade {
+ get {
+ return ResourceManager.GetString("FailedUpgrade", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 Please run it from the main application. 的本地化字符串。
+ ///
+ internal static string Guidelines {
+ get {
+ return ResourceManager.GetString("Guidelines", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 Information 的本地化字符串。
+ ///
+ internal static string Information {
+ get {
+ return ResourceManager.GetString("Information", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 In progress, please wait... 的本地化字符串。
+ ///
+ internal static string InProgress {
+ get {
+ return ResourceManager.GetString("InProgress", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 Start v2rayN, please wait... 的本地化字符串。
+ ///
+ internal static string Restartv2rayN {
+ get {
+ return ResourceManager.GetString("Restartv2rayN", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 Start extracting the update package... 的本地化字符串。
+ ///
+ internal static string StartUnzipping {
+ get {
+ return ResourceManager.GetString("StartUnzipping", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 Successfully extracted the update package. 的本地化字符串。
+ ///
+ internal static string SuccessUnzipping {
+ get {
+ return ResourceManager.GetString("SuccessUnzipping", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 Upgrade success. 的本地化字符串。
+ ///
+ internal static string SuccessUpgrade {
+ get {
+ return ResourceManager.GetString("SuccessUpgrade", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 Try to terminate the v2rayN process... 的本地化字符串。
+ ///
+ internal static string TryTerminateProcess {
+ get {
+ return ResourceManager.GetString("TryTerminateProcess", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 Upgrade failed, file not found. 的本地化字符串。
+ ///
+ internal static string UpgradeFileNotFound {
+ get {
+ return ResourceManager.GetString("UpgradeFileNotFound", resourceCulture);
+ }
+ }
+ }
}
diff --git a/v2rayN/AmazTool/UpgradeApp.cs b/v2rayN/AmazTool/UpgradeApp.cs
index 03e234a0..96636fe2 100644
--- a/v2rayN/AmazTool/UpgradeApp.cs
+++ b/v2rayN/AmazTool/UpgradeApp.cs
@@ -1,104 +1,105 @@
-using System.Diagnostics;
+using System.Diagnostics;
using System.IO.Compression;
using System.Text;
namespace AmazTool
{
- internal class UpgradeApp
- {
- public static void Upgrade(string fileName)
- {
- Console.WriteLine($"{Resx.Resource.StartUnzipping}\n{fileName}");
+ internal class UpgradeApp
+ {
+ public static void Upgrade(string fileName)
+ {
+ Console.WriteLine($"{Resx.Resource.StartUnzipping}\n{fileName}");
- Utils.Waiting(5);
+ Utils.Waiting(5);
- if (!File.Exists(fileName))
- {
- Console.WriteLine(Resx.Resource.UpgradeFileNotFound);
- return;
- }
+ if (!File.Exists(fileName))
+ {
+ Console.WriteLine(Resx.Resource.UpgradeFileNotFound);
+ return;
+ }
- Console.WriteLine(Resx.Resource.TryTerminateProcess);
- try
- {
- var existing = Process.GetProcessesByName(Utils.V2rayN);
- foreach (var pp in existing)
- {
- var path = pp.MainModule?.FileName ?? "";
- if (path.StartsWith(Utils.GetPath(Utils.V2rayN)))
- {
- pp?.Kill();
- pp?.WaitForExit(1000);
- }
- }
- }
- catch (Exception ex)
- {
- // Access may be denied without admin right. The user may not be an administrator.
- Console.WriteLine(Resx.Resource.FailedTerminateProcess + ex.StackTrace);
- }
+ Console.WriteLine(Resx.Resource.TryTerminateProcess);
+ try
+ {
+ var existing = Process.GetProcessesByName(Utils.V2rayN);
+ foreach (var pp in existing)
+ {
+ var path = pp.MainModule?.FileName ?? "";
+ if (path.StartsWith(Utils.GetPath(Utils.V2rayN)))
+ {
+ pp?.Kill();
+ pp?.WaitForExit(1000);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ // Access may be denied without admin right. The user may not be an administrator.
+ Console.WriteLine(Resx.Resource.FailedTerminateProcess + ex.StackTrace);
+ }
- Console.WriteLine(Resx.Resource.StartUnzipping);
- StringBuilder sb = new();
- try
- {
- var thisAppOldFile = $"{Utils.GetExePath()}.tmp";
- File.Delete(thisAppOldFile);
- var splitKey = "/";
+ Console.WriteLine(Resx.Resource.StartUnzipping);
+ StringBuilder sb = new();
+ try
+ {
+ var thisAppOldFile = $"{Utils.GetExePath()}.tmp";
+ File.Delete(thisAppOldFile);
+ var splitKey = "/";
- using var archive = ZipFile.OpenRead(fileName);
- foreach (var entry in archive.Entries)
- {
- try
- {
- if (entry.Length == 0)
- {
- continue;
- }
+ using var archive = ZipFile.OpenRead(fileName);
+ foreach (var entry in archive.Entries)
+ {
+ try
+ {
+ if (entry.Length == 0)
+ {
+ continue;
+ }
- Console.WriteLine(entry.FullName);
+ Console.WriteLine(entry.FullName);
- var lst = entry.FullName.Split(splitKey);
- if (lst.Length == 1) continue;
- var fullName = string.Join(splitKey, lst[1..lst.Length]);
+ var lst = entry.FullName.Split(splitKey);
+ if (lst.Length == 1)
+ continue;
+ var fullName = string.Join(splitKey, lst[1..lst.Length]);
- if (string.Equals(Utils.GetExePath(), Utils.GetPath(fullName), StringComparison.OrdinalIgnoreCase))
- {
- File.Move(Utils.GetExePath(), thisAppOldFile);
- }
+ if (string.Equals(Utils.GetExePath(), Utils.GetPath(fullName), StringComparison.OrdinalIgnoreCase))
+ {
+ File.Move(Utils.GetExePath(), thisAppOldFile);
+ }
- var entryOutputPath = Utils.GetPath(fullName);
- Directory.CreateDirectory(Path.GetDirectoryName(entryOutputPath)!);
- //In the bin folder, if the file already exists, it will be skipped
- if (fullName.StartsWith("bin") && File.Exists(entryOutputPath))
- {
- continue;
- }
- entry.ExtractToFile(entryOutputPath, true);
+ var entryOutputPath = Utils.GetPath(fullName);
+ Directory.CreateDirectory(Path.GetDirectoryName(entryOutputPath)!);
+ //In the bin folder, if the file already exists, it will be skipped
+ if (fullName.StartsWith("bin") && File.Exists(entryOutputPath))
+ {
+ continue;
+ }
+ entry.ExtractToFile(entryOutputPath, true);
- Console.WriteLine(entryOutputPath);
- }
- catch (Exception ex)
- {
- sb.Append(ex.StackTrace);
- }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(Resx.Resource.FailedUpgrade + ex.StackTrace);
- //return;
- }
- if (sb.Length > 0)
- {
- Console.WriteLine(Resx.Resource.FailedUpgrade + sb.ToString());
- //return;
- }
+ Console.WriteLine(entryOutputPath);
+ }
+ catch (Exception ex)
+ {
+ sb.Append(ex.StackTrace);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(Resx.Resource.FailedUpgrade + ex.StackTrace);
+ //return;
+ }
+ if (sb.Length > 0)
+ {
+ Console.WriteLine(Resx.Resource.FailedUpgrade + sb.ToString());
+ //return;
+ }
- Console.WriteLine(Resx.Resource.Restartv2rayN);
- Utils.Waiting(2);
+ Console.WriteLine(Resx.Resource.Restartv2rayN);
+ Utils.Waiting(2);
- Utils.StartV2RayN();
- }
- }
-}
\ No newline at end of file
+ Utils.StartV2RayN();
+ }
+ }
+}
diff --git a/v2rayN/AmazTool/Utils.cs b/v2rayN/AmazTool/Utils.cs
index d4189644..773ee6fb 100644
--- a/v2rayN/AmazTool/Utils.cs
+++ b/v2rayN/AmazTool/Utils.cs
@@ -1,52 +1,52 @@
-using System.Diagnostics;
+using System.Diagnostics;
namespace AmazTool
{
- internal class Utils
- {
- public static string GetExePath()
- {
- return Environment.ProcessPath ?? Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty;
- }
+ internal class Utils
+ {
+ public static string GetExePath()
+ {
+ return Environment.ProcessPath ?? Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty;
+ }
- public static string StartupPath()
- {
- return AppDomain.CurrentDomain.BaseDirectory;
- }
+ public static string StartupPath()
+ {
+ return AppDomain.CurrentDomain.BaseDirectory;
+ }
- public static string GetPath(string fileName)
- {
- string startupPath = StartupPath();
- if (string.IsNullOrEmpty(fileName))
- {
- return startupPath;
- }
- return Path.Combine(startupPath, fileName);
- }
+ public static string GetPath(string fileName)
+ {
+ string startupPath = StartupPath();
+ if (string.IsNullOrEmpty(fileName))
+ {
+ return startupPath;
+ }
+ return Path.Combine(startupPath, fileName);
+ }
- public static string V2rayN => "v2rayN";
+ public static string V2rayN => "v2rayN";
- public static void StartV2RayN()
- {
- Process process = new()
- {
- StartInfo = new()
- {
- UseShellExecute = true,
- FileName = V2rayN,
- WorkingDirectory = StartupPath()
- }
- };
- process.Start();
- }
+ public static void StartV2RayN()
+ {
+ Process process = new()
+ {
+ StartInfo = new()
+ {
+ UseShellExecute = true,
+ FileName = V2rayN,
+ WorkingDirectory = StartupPath()
+ }
+ };
+ process.Start();
+ }
- public static void Waiting(int second)
- {
- for (var i = second; i > 0; i--)
- {
- Console.WriteLine(i);
- Thread.Sleep(1000);
- }
- }
- }
-}
\ No newline at end of file
+ public static void Waiting(int second)
+ {
+ for (var i = second; i > 0; i--)
+ {
+ Console.WriteLine(i);
+ Thread.Sleep(1000);
+ }
+ }
+ }
+}
diff --git a/v2rayN/ServiceLib/Base/MyReactiveObject.cs b/v2rayN/ServiceLib/Base/MyReactiveObject.cs
index 0049429d..7d5cba4c 100644
--- a/v2rayN/ServiceLib/Base/MyReactiveObject.cs
+++ b/v2rayN/ServiceLib/Base/MyReactiveObject.cs
@@ -1,10 +1,10 @@
-using ReactiveUI;
+using ReactiveUI;
namespace ServiceLib.Base
{
- public class MyReactiveObject : ReactiveObject
- {
- protected static Config? _config;
- protected Func>? _updateView;
- }
-}
\ No newline at end of file
+ public class MyReactiveObject : ReactiveObject
+ {
+ protected static Config? _config;
+ protected Func>? _updateView;
+ }
+}
diff --git a/v2rayN/ServiceLib/Common/AesUtils.cs b/v2rayN/ServiceLib/Common/AesUtils.cs
index dcd4ac2a..5157d605 100644
--- a/v2rayN/ServiceLib/Common/AesUtils.cs
+++ b/v2rayN/ServiceLib/Common/AesUtils.cs
@@ -3,99 +3,99 @@ using System.Text;
namespace ServiceLib.Common
{
- public class AesUtils
- {
- private const int KeySize = 256; // AES-256
- private const int IvSize = 16; // AES block size
- private const int Iterations = 10000;
- private static readonly byte[] Salt = Encoding.ASCII.GetBytes("saltysalt".PadRight(16, ' ')); // google浏览器默认盐值
- private static readonly string DefaultPassword = Utils.GetMd5(Utils.GetHomePath() + "AesUtils");
+ public class AesUtils
+ {
+ private const int KeySize = 256; // AES-256
+ private const int IvSize = 16; // AES block size
+ private const int Iterations = 10000;
+ private static readonly byte[] Salt = Encoding.ASCII.GetBytes("saltysalt".PadRight(16, ' ')); // google浏览器默认盐值
+ private static readonly string DefaultPassword = Utils.GetMd5(Utils.GetHomePath() + "AesUtils");
- ///
- /// Encrypt
- ///
- /// Plain text
- /// Password for key derivation or direct key in ASCII bytes
- /// Base64 encoded cipher text with IV
- public static string Encrypt(string text, string? password = null)
- {
- if (string.IsNullOrEmpty(text))
- return string.Empty;
+ ///
+ /// Encrypt
+ ///
+ /// Plain text
+ /// Password for key derivation or direct key in ASCII bytes
+ /// Base64 encoded cipher text with IV
+ public static string Encrypt(string text, string? password = null)
+ {
+ if (string.IsNullOrEmpty(text))
+ return string.Empty;
- var plaintext = Encoding.UTF8.GetBytes(text);
- var key = GetKey(password);
- var iv = GenerateIv();
+ var plaintext = Encoding.UTF8.GetBytes(text);
+ var key = GetKey(password);
+ var iv = GenerateIv();
- using var aes = Aes.Create();
- aes.Key = key;
- aes.IV = iv;
+ using var aes = Aes.Create();
+ aes.Key = key;
+ aes.IV = iv;
- using var ms = new MemoryStream();
- ms.Write(iv, 0, iv.Length);
+ using var ms = new MemoryStream();
+ ms.Write(iv, 0, iv.Length);
- using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
- {
- cs.Write(plaintext, 0, plaintext.Length);
- cs.FlushFinalBlock();
- }
+ using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
+ {
+ cs.Write(plaintext, 0, plaintext.Length);
+ cs.FlushFinalBlock();
+ }
- var cipherTextWithIv = ms.ToArray();
- return Convert.ToBase64String(cipherTextWithIv);
- }
+ var cipherTextWithIv = ms.ToArray();
+ return Convert.ToBase64String(cipherTextWithIv);
+ }
- ///
- /// Decrypt
- ///
- /// Base64 encoded cipher text with IV
- /// Password for key derivation or direct key in ASCII bytes
- /// Plain text
- public static string Decrypt(string cipherTextWithIv, string? password = null)
- {
- if (string.IsNullOrEmpty(cipherTextWithIv))
- return string.Empty;
+ ///
+ /// Decrypt
+ ///
+ /// Base64 encoded cipher text with IV
+ /// Password for key derivation or direct key in ASCII bytes
+ /// Plain text
+ public static string Decrypt(string cipherTextWithIv, string? password = null)
+ {
+ if (string.IsNullOrEmpty(cipherTextWithIv))
+ return string.Empty;
- var cipherTextWithIvBytes = Convert.FromBase64String(cipherTextWithIv);
- var key = GetKey(password);
+ var cipherTextWithIvBytes = Convert.FromBase64String(cipherTextWithIv);
+ var key = GetKey(password);
- var iv = new byte[IvSize];
- Buffer.BlockCopy(cipherTextWithIvBytes, 0, iv, 0, IvSize);
+ var iv = new byte[IvSize];
+ Buffer.BlockCopy(cipherTextWithIvBytes, 0, iv, 0, IvSize);
- var cipherText = new byte[cipherTextWithIvBytes.Length - IvSize];
- Buffer.BlockCopy(cipherTextWithIvBytes, IvSize, cipherText, 0, cipherText.Length);
+ var cipherText = new byte[cipherTextWithIvBytes.Length - IvSize];
+ Buffer.BlockCopy(cipherTextWithIvBytes, IvSize, cipherText, 0, cipherText.Length);
- using var aes = Aes.Create();
- aes.Key = key;
- aes.IV = iv;
+ using var aes = Aes.Create();
+ aes.Key = key;
+ aes.IV = iv;
- using var ms = new MemoryStream();
- using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
- {
- cs.Write(cipherText, 0, cipherText.Length);
- cs.FlushFinalBlock();
- }
+ using var ms = new MemoryStream();
+ using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
+ {
+ cs.Write(cipherText, 0, cipherText.Length);
+ cs.FlushFinalBlock();
+ }
- var plainText = ms.ToArray();
- return Encoding.UTF8.GetString(plainText);
- }
+ var plainText = ms.ToArray();
+ return Encoding.UTF8.GetString(plainText);
+ }
- private static byte[] GetKey(string? password)
- {
- if (password.IsNullOrEmpty())
- {
- password = DefaultPassword;
- }
+ private static byte[] GetKey(string? password)
+ {
+ if (password.IsNullOrEmpty())
+ {
+ password = DefaultPassword;
+ }
- using var pbkdf2 = new Rfc2898DeriveBytes(password, Salt, Iterations, HashAlgorithmName.SHA256);
- return pbkdf2.GetBytes(KeySize / 8);
- }
+ using var pbkdf2 = new Rfc2898DeriveBytes(password, Salt, Iterations, HashAlgorithmName.SHA256);
+ return pbkdf2.GetBytes(KeySize / 8);
+ }
- private static byte[] GenerateIv()
- {
- var randomNumber = new byte[IvSize];
+ private static byte[] GenerateIv()
+ {
+ var randomNumber = new byte[IvSize];
- using var rng = RandomNumberGenerator.Create();
- rng.GetBytes(randomNumber);
- return randomNumber;
- }
- }
-}
\ No newline at end of file
+ using var rng = RandomNumberGenerator.Create();
+ rng.GetBytes(randomNumber);
+ return randomNumber;
+ }
+ }
+}
diff --git a/v2rayN/ServiceLib/Common/DesUtils.cs b/v2rayN/ServiceLib/Common/DesUtils.cs
index 132fff65..7cf70b0d 100644
--- a/v2rayN/ServiceLib/Common/DesUtils.cs
+++ b/v2rayN/ServiceLib/Common/DesUtils.cs
@@ -3,73 +3,73 @@ using System.Text;
namespace ServiceLib.Common
{
- public class DesUtils
- {
- ///
- /// Encrypt
- ///
- ///
- /// ///
- ///
- public static string Encrypt(string? text, string? key = null)
- {
- if (text.IsNullOrEmpty())
- {
- return string.Empty;
- }
- GetKeyIv(key ?? GetDefaultKey(), out var rgbKey, out var rgbIv);
- var dsp = DES.Create();
- using var memStream = new MemoryStream();
- using var cryStream = new CryptoStream(memStream, dsp.CreateEncryptor(rgbKey, rgbIv), CryptoStreamMode.Write);
- using var sWriter = new StreamWriter(cryStream);
- sWriter.Write(text);
- sWriter.Flush();
- cryStream.FlushFinalBlock();
- memStream.Flush();
- return Convert.ToBase64String(memStream.GetBuffer(), 0, (int)memStream.Length);
- }
+ public class DesUtils
+ {
+ ///
+ /// Encrypt
+ ///
+ ///
+ /// ///
+ ///
+ public static string Encrypt(string? text, string? key = null)
+ {
+ if (text.IsNullOrEmpty())
+ {
+ return string.Empty;
+ }
+ GetKeyIv(key ?? GetDefaultKey(), out var rgbKey, out var rgbIv);
+ var dsp = DES.Create();
+ using var memStream = new MemoryStream();
+ using var cryStream = new CryptoStream(memStream, dsp.CreateEncryptor(rgbKey, rgbIv), CryptoStreamMode.Write);
+ using var sWriter = new StreamWriter(cryStream);
+ sWriter.Write(text);
+ sWriter.Flush();
+ cryStream.FlushFinalBlock();
+ memStream.Flush();
+ return Convert.ToBase64String(memStream.GetBuffer(), 0, (int)memStream.Length);
+ }
- ///
- /// Decrypt
- ///
- ///
- ///
- ///
- public static string Decrypt(string? encryptText, string? key = null)
- {
- if (encryptText.IsNullOrEmpty())
- {
- return string.Empty;
- }
- GetKeyIv(key ?? GetDefaultKey(), out var rgbKey, out var rgbIv);
- var dsp = DES.Create();
- var buffer = Convert.FromBase64String(encryptText);
+ ///
+ /// Decrypt
+ ///
+ ///
+ ///
+ ///
+ public static string Decrypt(string? encryptText, string? key = null)
+ {
+ if (encryptText.IsNullOrEmpty())
+ {
+ return string.Empty;
+ }
+ GetKeyIv(key ?? GetDefaultKey(), out var rgbKey, out var rgbIv);
+ var dsp = DES.Create();
+ var buffer = Convert.FromBase64String(encryptText);
- using var memStream = new MemoryStream();
- using var cryStream = new CryptoStream(memStream, dsp.CreateDecryptor(rgbKey, rgbIv), CryptoStreamMode.Write);
- cryStream.Write(buffer, 0, buffer.Length);
- cryStream.FlushFinalBlock();
- return Encoding.UTF8.GetString(memStream.ToArray());
- }
+ using var memStream = new MemoryStream();
+ using var cryStream = new CryptoStream(memStream, dsp.CreateDecryptor(rgbKey, rgbIv), CryptoStreamMode.Write);
+ cryStream.Write(buffer, 0, buffer.Length);
+ cryStream.FlushFinalBlock();
+ return Encoding.UTF8.GetString(memStream.ToArray());
+ }
- private static void GetKeyIv(string key, out byte[] rgbKey, out byte[] rgbIv)
- {
- if (key.IsNullOrEmpty())
- {
- throw new ArgumentNullException("The key cannot be null");
- }
- if (key.Length <= 8)
- {
- throw new ArgumentNullException("The key length cannot be less than 8 characters.");
- }
+ private static void GetKeyIv(string key, out byte[] rgbKey, out byte[] rgbIv)
+ {
+ if (key.IsNullOrEmpty())
+ {
+ throw new ArgumentNullException("The key cannot be null");
+ }
+ if (key.Length <= 8)
+ {
+ throw new ArgumentNullException("The key length cannot be less than 8 characters.");
+ }
- rgbKey = Encoding.ASCII.GetBytes(key.Substring(0, 8));
- rgbIv = Encoding.ASCII.GetBytes(key.Insert(0, "w").Substring(0, 8));
- }
+ rgbKey = Encoding.ASCII.GetBytes(key.Substring(0, 8));
+ rgbIv = Encoding.ASCII.GetBytes(key.Insert(0, "w").Substring(0, 8));
+ }
- private static string GetDefaultKey()
- {
- return Utils.GetMd5(Utils.GetHomePath() + "DesUtils");
- }
- }
-}
\ No newline at end of file
+ private static string GetDefaultKey()
+ {
+ return Utils.GetMd5(Utils.GetHomePath() + "DesUtils");
+ }
+ }
+}
diff --git a/v2rayN/ServiceLib/Common/DownloaderHelper.cs b/v2rayN/ServiceLib/Common/DownloaderHelper.cs
index 2aaa2371..20126ca8 100644
--- a/v2rayN/ServiceLib/Common/DownloaderHelper.cs
+++ b/v2rayN/ServiceLib/Common/DownloaderHelper.cs
@@ -1,184 +1,184 @@
-using Downloader;
+using Downloader;
using System.Net;
namespace ServiceLib.Common
{
- public class DownloaderHelper
- {
- private static readonly Lazy _instance = new(() => new());
- public static DownloaderHelper Instance => _instance.Value;
+ public class DownloaderHelper
+ {
+ private static readonly Lazy _instance = new(() => new());
+ public static DownloaderHelper Instance => _instance.Value;
- public async Task DownloadStringAsync(IWebProxy? webProxy, string url, string? userAgent, int timeout)
- {
- if (Utils.IsNullOrEmpty(url))
- {
- return null;
- }
+ public async Task DownloadStringAsync(IWebProxy? webProxy, string url, string? userAgent, int timeout)
+ {
+ if (Utils.IsNullOrEmpty(url))
+ {
+ return null;
+ }
- Uri uri = new(url);
- //Authorization Header
- var headers = new WebHeaderCollection();
- if (Utils.IsNotEmpty(uri.UserInfo))
- {
- headers.Add(HttpRequestHeader.Authorization, "Basic " + Utils.Base64Encode(uri.UserInfo));
- }
+ Uri uri = new(url);
+ //Authorization Header
+ var headers = new WebHeaderCollection();
+ if (Utils.IsNotEmpty(uri.UserInfo))
+ {
+ headers.Add(HttpRequestHeader.Authorization, "Basic " + Utils.Base64Encode(uri.UserInfo));
+ }
- var downloadOpt = new DownloadConfiguration()
- {
- Timeout = timeout * 1000,
- MaxTryAgainOnFailover = 2,
- RequestConfiguration =
- {
- Headers = headers,
- UserAgent = userAgent,
- Timeout = timeout * 1000,
- Proxy = webProxy
- }
- };
+ var downloadOpt = new DownloadConfiguration()
+ {
+ Timeout = timeout * 1000,
+ MaxTryAgainOnFailover = 2,
+ RequestConfiguration =
+ {
+ Headers = headers,
+ UserAgent = userAgent,
+ Timeout = timeout * 1000,
+ Proxy = webProxy
+ }
+ };
- await using var downloader = new Downloader.DownloadService(downloadOpt);
- downloader.DownloadFileCompleted += (sender, value) =>
- {
- if (value.Error != null)
- {
- throw value.Error;
- }
- };
+ await using var downloader = new Downloader.DownloadService(downloadOpt);
+ downloader.DownloadFileCompleted += (sender, value) =>
+ {
+ if (value.Error != null)
+ {
+ throw value.Error;
+ }
+ };
- using var cts = new CancellationTokenSource();
- await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token);
- using StreamReader reader = new(stream);
+ using var cts = new CancellationTokenSource();
+ await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token);
+ using StreamReader reader = new(stream);
- downloadOpt = null;
+ downloadOpt = null;
- return await reader.ReadToEndAsync(cts.Token);
- }
+ return await reader.ReadToEndAsync(cts.Token);
+ }
- public async Task DownloadDataAsync4Speed(IWebProxy webProxy, string url, IProgress progress, int timeout)
- {
- if (Utils.IsNullOrEmpty(url))
- {
- throw new ArgumentNullException(nameof(url));
- }
+ public async Task DownloadDataAsync4Speed(IWebProxy webProxy, string url, IProgress progress, int timeout)
+ {
+ if (Utils.IsNullOrEmpty(url))
+ {
+ throw new ArgumentNullException(nameof(url));
+ }
- var downloadOpt = new DownloadConfiguration()
- {
- Timeout = timeout * 1000,
- MaxTryAgainOnFailover = 2,
- RequestConfiguration =
- {
- Timeout= timeout * 1000,
- Proxy = webProxy
- }
- };
+ var downloadOpt = new DownloadConfiguration()
+ {
+ Timeout = timeout * 1000,
+ MaxTryAgainOnFailover = 2,
+ RequestConfiguration =
+ {
+ Timeout= timeout * 1000,
+ Proxy = webProxy
+ }
+ };
- var totalDatetime = DateTime.Now;
- var totalSecond = 0;
- var hasValue = false;
- double maxSpeed = 0;
- await using var downloader = new Downloader.DownloadService(downloadOpt);
- //downloader.DownloadStarted += (sender, value) =>
- //{
- // if (progress != null)
- // {
- // progress.Report("Start download data...");
- // }
- //};
- downloader.DownloadProgressChanged += (sender, value) =>
- {
- var ts = (DateTime.Now - totalDatetime);
- if (progress != null && ts.Seconds > totalSecond)
- {
- hasValue = true;
- totalSecond = ts.Seconds;
- if (value.BytesPerSecondSpeed > maxSpeed)
- {
- maxSpeed = value.BytesPerSecondSpeed;
- var speed = (maxSpeed / 1000 / 1000).ToString("#0.0");
- progress.Report(speed);
- }
- }
- };
- downloader.DownloadFileCompleted += (sender, value) =>
- {
- if (progress != null)
- {
- if (!hasValue && value.Error != null)
- {
- progress.Report(value.Error?.Message);
- }
- }
- };
- //progress.Report("......");
- using var cts = new CancellationTokenSource();
- cts.CancelAfter(timeout * 1000);
- await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token);
+ var totalDatetime = DateTime.Now;
+ var totalSecond = 0;
+ var hasValue = false;
+ double maxSpeed = 0;
+ await using var downloader = new Downloader.DownloadService(downloadOpt);
+ //downloader.DownloadStarted += (sender, value) =>
+ //{
+ // if (progress != null)
+ // {
+ // progress.Report("Start download data...");
+ // }
+ //};
+ downloader.DownloadProgressChanged += (sender, value) =>
+ {
+ var ts = (DateTime.Now - totalDatetime);
+ if (progress != null && ts.Seconds > totalSecond)
+ {
+ hasValue = true;
+ totalSecond = ts.Seconds;
+ if (value.BytesPerSecondSpeed > maxSpeed)
+ {
+ maxSpeed = value.BytesPerSecondSpeed;
+ var speed = (maxSpeed / 1000 / 1000).ToString("#0.0");
+ progress.Report(speed);
+ }
+ }
+ };
+ downloader.DownloadFileCompleted += (sender, value) =>
+ {
+ if (progress != null)
+ {
+ if (!hasValue && value.Error != null)
+ {
+ progress.Report(value.Error?.Message);
+ }
+ }
+ };
+ //progress.Report("......");
+ using var cts = new CancellationTokenSource();
+ cts.CancelAfter(timeout * 1000);
+ await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token);
- downloadOpt = null;
- }
+ downloadOpt = null;
+ }
- public async Task DownloadFileAsync(IWebProxy? webProxy, string url, string fileName, IProgress progress, int timeout)
- {
- if (Utils.IsNullOrEmpty(url))
- {
- throw new ArgumentNullException(nameof(url));
- }
- if (Utils.IsNullOrEmpty(fileName))
- {
- throw new ArgumentNullException(nameof(fileName));
- }
- if (File.Exists(fileName))
- {
- File.Delete(fileName);
- }
+ public async Task DownloadFileAsync(IWebProxy? webProxy, string url, string fileName, IProgress progress, int timeout)
+ {
+ if (Utils.IsNullOrEmpty(url))
+ {
+ throw new ArgumentNullException(nameof(url));
+ }
+ if (Utils.IsNullOrEmpty(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+ if (File.Exists(fileName))
+ {
+ File.Delete(fileName);
+ }
- var downloadOpt = new DownloadConfiguration()
- {
- Timeout = timeout * 1000,
- MaxTryAgainOnFailover = 2,
- RequestConfiguration =
- {
- Timeout= timeout * 1000,
- Proxy = webProxy
- }
- };
+ var downloadOpt = new DownloadConfiguration()
+ {
+ Timeout = timeout * 1000,
+ MaxTryAgainOnFailover = 2,
+ RequestConfiguration =
+ {
+ Timeout= timeout * 1000,
+ Proxy = webProxy
+ }
+ };
- var progressPercentage = 0;
- var hasValue = false;
- await using var downloader = new Downloader.DownloadService(downloadOpt);
- downloader.DownloadStarted += (sender, value) =>
- {
- progress?.Report(0);
- };
- downloader.DownloadProgressChanged += (sender, value) =>
- {
- hasValue = true;
- var percent = (int)value.ProgressPercentage;// Convert.ToInt32((totalRead * 1d) / (total * 1d) * 100);
- if (progressPercentage != percent && percent % 10 == 0)
- {
- progressPercentage = percent;
- progress.Report(percent);
- }
- };
- downloader.DownloadFileCompleted += (sender, value) =>
- {
- if (progress != null)
- {
- if (hasValue && value.Error == null)
- {
- progress.Report(101);
- }
- else if (value.Error != null)
- {
- throw value.Error;
- }
- }
- };
+ var progressPercentage = 0;
+ var hasValue = false;
+ await using var downloader = new Downloader.DownloadService(downloadOpt);
+ downloader.DownloadStarted += (sender, value) =>
+ {
+ progress?.Report(0);
+ };
+ downloader.DownloadProgressChanged += (sender, value) =>
+ {
+ hasValue = true;
+ var percent = (int)value.ProgressPercentage;// Convert.ToInt32((totalRead * 1d) / (total * 1d) * 100);
+ if (progressPercentage != percent && percent % 10 == 0)
+ {
+ progressPercentage = percent;
+ progress.Report(percent);
+ }
+ };
+ downloader.DownloadFileCompleted += (sender, value) =>
+ {
+ if (progress != null)
+ {
+ if (hasValue && value.Error == null)
+ {
+ progress.Report(101);
+ }
+ else if (value.Error != null)
+ {
+ throw value.Error;
+ }
+ }
+ };
- using var cts = new CancellationTokenSource();
- await downloader.DownloadFileTaskAsync(url, fileName, cts.Token);
+ using var cts = new CancellationTokenSource();
+ await downloader.DownloadFileTaskAsync(url, fileName, cts.Token);
- downloadOpt = null;
- }
- }
-}
\ No newline at end of file
+ downloadOpt = null;
+ }
+ }
+}
diff --git a/v2rayN/ServiceLib/Common/FileManager.cs b/v2rayN/ServiceLib/Common/FileManager.cs
index 4431fbea..5131ecfc 100644
--- a/v2rayN/ServiceLib/Common/FileManager.cs
+++ b/v2rayN/ServiceLib/Common/FileManager.cs
@@ -1,225 +1,225 @@
-using System.Formats.Tar;
+using System.Formats.Tar;
using System.IO.Compression;
using System.Text;
namespace ServiceLib.Common
{
- public static class FileManager
- {
- private static readonly string _tag = "FileManager";
+ public static class FileManager
+ {
+ private static readonly string _tag = "FileManager";
- public static bool ByteArrayToFile(string fileName, byte[] content)
- {
- try
- {
- File.WriteAllBytes(fileName, content);
- return true;
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
- return false;
- }
+ public static bool ByteArrayToFile(string fileName, byte[] content)
+ {
+ try
+ {
+ File.WriteAllBytes(fileName, content);
+ return true;
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+ return false;
+ }
- public static void DecompressFile(string fileName, byte[] content)
- {
- try
- {
- using var fs = File.Create(fileName);
- using GZipStream input = new(new MemoryStream(content), CompressionMode.Decompress, false);
- input.CopyTo(fs);
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
- }
+ public static void DecompressFile(string fileName, byte[] content)
+ {
+ try
+ {
+ using var fs = File.Create(fileName);
+ using GZipStream input = new(new MemoryStream(content), CompressionMode.Decompress, false);
+ input.CopyTo(fs);
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+ }
- public static void DecompressFile(string fileName, string toPath, string? toName)
- {
- try
- {
- FileInfo fileInfo = new(fileName);
- using var originalFileStream = fileInfo.OpenRead();
- using var decompressedFileStream = File.Create(toName != null ? Path.Combine(toPath, toName) : toPath);
- using GZipStream decompressionStream = new(originalFileStream, CompressionMode.Decompress);
- decompressionStream.CopyTo(decompressedFileStream);
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
- }
+ public static void DecompressFile(string fileName, string toPath, string? toName)
+ {
+ try
+ {
+ FileInfo fileInfo = new(fileName);
+ using var originalFileStream = fileInfo.OpenRead();
+ using var decompressedFileStream = File.Create(toName != null ? Path.Combine(toPath, toName) : toPath);
+ using GZipStream decompressionStream = new(originalFileStream, CompressionMode.Decompress);
+ decompressionStream.CopyTo(decompressedFileStream);
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+ }
- public static void DecompressTarFile(string fileName, string toPath)
- {
- try
- {
- using var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
- using var gz = new GZipStream(fs, CompressionMode.Decompress, leaveOpen: true);
- TarFile.ExtractToDirectory(gz, toPath, overwriteFiles: true);
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
- }
+ public static void DecompressTarFile(string fileName, string toPath)
+ {
+ try
+ {
+ using var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
+ using var gz = new GZipStream(fs, CompressionMode.Decompress, leaveOpen: true);
+ TarFile.ExtractToDirectory(gz, toPath, overwriteFiles: true);
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+ }
- public static string NonExclusiveReadAllText(string path)
- {
- return NonExclusiveReadAllText(path, Encoding.Default);
- }
+ public static string NonExclusiveReadAllText(string path)
+ {
+ return NonExclusiveReadAllText(path, Encoding.Default);
+ }
- private static string NonExclusiveReadAllText(string path, Encoding encoding)
- {
- try
- {
- using FileStream fs = new(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
- using StreamReader sr = new(fs, encoding);
- return sr.ReadToEnd();
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- throw;
- }
- }
+ private static string NonExclusiveReadAllText(string path, Encoding encoding)
+ {
+ try
+ {
+ using FileStream fs = new(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
+ using StreamReader sr = new(fs, encoding);
+ return sr.ReadToEnd();
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ throw;
+ }
+ }
- public static bool ZipExtractToFile(string fileName, string toPath, string ignoredName)
- {
- try
- {
- using var archive = ZipFile.OpenRead(fileName);
- foreach (var entry in archive.Entries)
- {
- if (entry.Length == 0)
- {
- continue;
- }
- try
- {
- if (Utils.IsNotEmpty(ignoredName) && entry.Name.Contains(ignoredName))
- {
- continue;
- }
- entry.ExtractToFile(Path.Combine(toPath, entry.Name), true);
- }
- catch (IOException ex)
- {
- Logging.SaveLog(_tag, ex);
- }
- }
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- return false;
- }
- return true;
- }
+ public static bool ZipExtractToFile(string fileName, string toPath, string ignoredName)
+ {
+ try
+ {
+ using var archive = ZipFile.OpenRead(fileName);
+ foreach (var entry in archive.Entries)
+ {
+ if (entry.Length == 0)
+ {
+ continue;
+ }
+ try
+ {
+ if (Utils.IsNotEmpty(ignoredName) && entry.Name.Contains(ignoredName))
+ {
+ continue;
+ }
+ entry.ExtractToFile(Path.Combine(toPath, entry.Name), true);
+ }
+ catch (IOException ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ return false;
+ }
+ return true;
+ }
- public static List? GetFilesFromZip(string fileName)
- {
- if (!File.Exists(fileName))
- {
- return null;
- }
- try
- {
- using var archive = ZipFile.OpenRead(fileName);
- return archive.Entries.Select(entry => entry.FullName).ToList();
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- return null;
- }
- }
+ public static List? GetFilesFromZip(string fileName)
+ {
+ if (!File.Exists(fileName))
+ {
+ return null;
+ }
+ try
+ {
+ using var archive = ZipFile.OpenRead(fileName);
+ return archive.Entries.Select(entry => entry.FullName).ToList();
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ return null;
+ }
+ }
- public static bool CreateFromDirectory(string sourceDirectoryName, string destinationArchiveFileName)
- {
- try
- {
- if (File.Exists(destinationArchiveFileName))
- {
- File.Delete(destinationArchiveFileName);
- }
+ public static bool CreateFromDirectory(string sourceDirectoryName, string destinationArchiveFileName)
+ {
+ try
+ {
+ if (File.Exists(destinationArchiveFileName))
+ {
+ File.Delete(destinationArchiveFileName);
+ }
- ZipFile.CreateFromDirectory(sourceDirectoryName, destinationArchiveFileName, CompressionLevel.SmallestSize, true);
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- return false;
- }
- return true;
- }
+ ZipFile.CreateFromDirectory(sourceDirectoryName, destinationArchiveFileName, CompressionLevel.SmallestSize, true);
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ return false;
+ }
+ return true;
+ }
- public static void CopyDirectory(string sourceDir, string destinationDir, bool recursive, bool overwrite, string? ignoredName = null)
- {
- // Get information about the source directory
- var dir = new DirectoryInfo(sourceDir);
+ public static void CopyDirectory(string sourceDir, string destinationDir, bool recursive, bool overwrite, string? ignoredName = null)
+ {
+ // Get information about the source directory
+ var dir = new DirectoryInfo(sourceDir);
- // Check if the source directory exists
- if (!dir.Exists)
- throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}");
+ // Check if the source directory exists
+ if (!dir.Exists)
+ throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}");
- // Cache directories before we start copying
- var dirs = dir.GetDirectories();
+ // Cache directories before we start copying
+ var dirs = dir.GetDirectories();
- // Create the destination directory
- Directory.CreateDirectory(destinationDir);
+ // Create the destination directory
+ Directory.CreateDirectory(destinationDir);
- // Get the files in the source directory and copy to the destination directory
- foreach (var file in dir.GetFiles())
- {
- if (Utils.IsNotEmpty(ignoredName) && file.Name.Contains(ignoredName))
- {
- continue;
- }
- if (file.Extension == file.Name)
- {
- continue;
- }
- var targetFilePath = Path.Combine(destinationDir, file.Name);
- if (!overwrite && File.Exists(targetFilePath))
- {
- continue;
- }
- file.CopyTo(targetFilePath, overwrite);
- }
+ // Get the files in the source directory and copy to the destination directory
+ foreach (var file in dir.GetFiles())
+ {
+ if (Utils.IsNotEmpty(ignoredName) && file.Name.Contains(ignoredName))
+ {
+ continue;
+ }
+ if (file.Extension == file.Name)
+ {
+ continue;
+ }
+ var targetFilePath = Path.Combine(destinationDir, file.Name);
+ if (!overwrite && File.Exists(targetFilePath))
+ {
+ continue;
+ }
+ file.CopyTo(targetFilePath, overwrite);
+ }
- // If recursive and copying subdirectories, recursively call this method
- if (recursive)
- {
- foreach (var subDir in dirs)
- {
- var newDestinationDir = Path.Combine(destinationDir, subDir.Name);
- CopyDirectory(subDir.FullName, newDestinationDir, true, overwrite, ignoredName);
- }
- }
- }
+ // If recursive and copying subdirectories, recursively call this method
+ if (recursive)
+ {
+ foreach (var subDir in dirs)
+ {
+ var newDestinationDir = Path.Combine(destinationDir, subDir.Name);
+ CopyDirectory(subDir.FullName, newDestinationDir, true, overwrite, ignoredName);
+ }
+ }
+ }
- public static void DeleteExpiredFiles(string sourceDir, DateTime dtLine)
- {
- try
- {
- var files = Directory.GetFiles(sourceDir, "*.*");
- foreach (var filePath in files)
- {
- var file = new FileInfo(filePath);
- if (file.CreationTime >= dtLine)
- {
- continue;
- }
- file.Delete();
- }
- }
- catch
- {
- // ignored
- }
- }
- }
-}
\ No newline at end of file
+ public static void DeleteExpiredFiles(string sourceDir, DateTime dtLine)
+ {
+ try
+ {
+ var files = Directory.GetFiles(sourceDir, "*.*");
+ foreach (var filePath in files)
+ {
+ var file = new FileInfo(filePath);
+ if (file.CreationTime >= dtLine)
+ {
+ continue;
+ }
+ file.Delete();
+ }
+ }
+ catch
+ {
+ // ignored
+ }
+ }
+ }
+}
diff --git a/v2rayN/ServiceLib/Common/HttpClientHelper.cs b/v2rayN/ServiceLib/Common/HttpClientHelper.cs
index 2959875b..4eb768c6 100644
--- a/v2rayN/ServiceLib/Common/HttpClientHelper.cs
+++ b/v2rayN/ServiceLib/Common/HttpClientHelper.cs
@@ -4,183 +4,188 @@ using System.Text;
namespace ServiceLib.Common
{
- ///
- ///
- public class HttpClientHelper
- {
- private static readonly Lazy _instance = new(() =>
- {
- SocketsHttpHandler handler = new() { UseCookies = false };
- HttpClientHelper helper = new(new HttpClient(handler));
- return helper;
- });
+ ///
+ ///
+ public class HttpClientHelper
+ {
+ private static readonly Lazy _instance = new(() =>
+ {
+ SocketsHttpHandler handler = new() { UseCookies = false };
+ HttpClientHelper helper = new(new HttpClient(handler));
+ return helper;
+ });
- public static HttpClientHelper Instance => _instance.Value;
- private readonly HttpClient httpClient;
+ public static HttpClientHelper Instance => _instance.Value;
+ private readonly HttpClient httpClient;
- private HttpClientHelper(HttpClient httpClient) => this.httpClient = httpClient;
+ private HttpClientHelper(HttpClient httpClient) => this.httpClient = httpClient;
- public async Task TryGetAsync(string url)
- {
- if (Utils.IsNullOrEmpty(url))
- return null;
+ public async Task TryGetAsync(string url)
+ {
+ if (Utils.IsNullOrEmpty(url))
+ return null;
- try
- {
- var response = await httpClient.GetAsync(url);
- return await response.Content.ReadAsStringAsync();
- }
- catch
- {
- return null;
- }
- }
+ try
+ {
+ var response = await httpClient.GetAsync(url);
+ return await response.Content.ReadAsStringAsync();
+ }
+ catch
+ {
+ return null;
+ }
+ }
- public async Task GetAsync(string url)
- {
- if (Utils.IsNullOrEmpty(url)) return null;
- return await httpClient.GetStringAsync(url);
- }
+ public async Task GetAsync(string url)
+ {
+ if (Utils.IsNullOrEmpty(url))
+ return null;
+ return await httpClient.GetStringAsync(url);
+ }
- public async Task GetAsync(HttpClient client, string url, CancellationToken token = default)
- {
- if (Utils.IsNullOrEmpty(url)) return null;
- return await client.GetStringAsync(url, token);
- }
+ public async Task GetAsync(HttpClient client, string url, CancellationToken token = default)
+ {
+ if (Utils.IsNullOrEmpty(url))
+ return null;
+ return await client.GetStringAsync(url, token);
+ }
- public async Task PutAsync(string url, Dictionary headers)
- {
- var jsonContent = JsonUtils.Serialize(headers);
- var content = new StringContent(jsonContent, Encoding.UTF8, MediaTypeNames.Application.Json);
+ public async Task PutAsync(string url, Dictionary headers)
+ {
+ var jsonContent = JsonUtils.Serialize(headers);
+ var content = new StringContent(jsonContent, Encoding.UTF8, MediaTypeNames.Application.Json);
- var result = await httpClient.PutAsync(url, content);
- }
+ var result = await httpClient.PutAsync(url, content);
+ }
- public async Task PatchAsync(string url, Dictionary headers)
- {
- var myContent = JsonUtils.Serialize(headers);
- var buffer = System.Text.Encoding.UTF8.GetBytes(myContent);
- var byteContent = new ByteArrayContent(buffer);
- byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
+ public async Task PatchAsync(string url, Dictionary headers)
+ {
+ var myContent = JsonUtils.Serialize(headers);
+ var buffer = System.Text.Encoding.UTF8.GetBytes(myContent);
+ var byteContent = new ByteArrayContent(buffer);
+ byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
- await httpClient.PatchAsync(url, byteContent);
- }
+ await httpClient.PatchAsync(url, byteContent);
+ }
- public async Task DeleteAsync(string url)
- {
- await httpClient.DeleteAsync(url);
- }
+ public async Task DeleteAsync(string url)
+ {
+ await httpClient.DeleteAsync(url);
+ }
- public static async Task DownloadFileAsync(HttpClient client, string url, string fileName, IProgress? progress, CancellationToken token = default)
- {
- ArgumentNullException.ThrowIfNull(url);
- ArgumentNullException.ThrowIfNull(fileName);
- if (File.Exists(fileName)) File.Delete(fileName);
+ public static async Task DownloadFileAsync(HttpClient client, string url, string fileName, IProgress? progress, CancellationToken token = default)
+ {
+ ArgumentNullException.ThrowIfNull(url);
+ ArgumentNullException.ThrowIfNull(fileName);
+ if (File.Exists(fileName))
+ File.Delete(fileName);
- using var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
+ using var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
- if (!response.IsSuccessStatusCode) throw new Exception(response.StatusCode.ToString());
+ if (!response.IsSuccessStatusCode)
+ throw new Exception(response.StatusCode.ToString());
- var total = response.Content.Headers.ContentLength ?? -1L;
- var canReportProgress = total != -1 && progress != null;
+ var total = response.Content.Headers.ContentLength ?? -1L;
+ var canReportProgress = total != -1 && progress != null;
- await using var stream = await response.Content.ReadAsStreamAsync(token);
- await using var file = File.Create(fileName);
- var totalRead = 0L;
- var buffer = new byte[1024 * 1024];
- var progressPercentage = 0;
+ await using var stream = await response.Content.ReadAsStreamAsync(token);
+ await using var file = File.Create(fileName);
+ var totalRead = 0L;
+ var buffer = new byte[1024 * 1024];
+ var progressPercentage = 0;
- while (true)
- {
- token.ThrowIfCancellationRequested();
+ while (true)
+ {
+ token.ThrowIfCancellationRequested();
- var read = await stream.ReadAsync(buffer, token);
- totalRead += read;
+ var read = await stream.ReadAsync(buffer, token);
+ totalRead += read;
- if (read == 0) break;
- await file.WriteAsync(buffer.AsMemory(0, read), token);
+ if (read == 0)
+ break;
+ await file.WriteAsync(buffer.AsMemory(0, read), token);
- if (canReportProgress)
- {
- var percent = (int)(100.0 * totalRead / total);
- //if (progressPercentage != percent && percent % 10 == 0)
- {
- progressPercentage = percent;
- progress?.Report(percent);
- }
- }
- }
- if (canReportProgress)
- {
- progress?.Report(101);
- }
- }
+ if (canReportProgress)
+ {
+ var percent = (int)(100.0 * totalRead / total);
+ //if (progressPercentage != percent && percent % 10 == 0)
+ {
+ progressPercentage = percent;
+ progress?.Report(percent);
+ }
+ }
+ }
+ if (canReportProgress)
+ {
+ progress?.Report(101);
+ }
+ }
- public async Task DownloadDataAsync4Speed(HttpClient client, string url, IProgress progress, CancellationToken token = default)
- {
- if (Utils.IsNullOrEmpty(url))
- {
- throw new ArgumentNullException(nameof(url));
- }
+ public async Task DownloadDataAsync4Speed(HttpClient client, string url, IProgress progress, CancellationToken token = default)
+ {
+ if (Utils.IsNullOrEmpty(url))
+ {
+ throw new ArgumentNullException(nameof(url));
+ }
- var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
+ var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
- if (!response.IsSuccessStatusCode)
- {
- throw new Exception(response.StatusCode.ToString());
- }
+ if (!response.IsSuccessStatusCode)
+ {
+ throw new Exception(response.StatusCode.ToString());
+ }
- //var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L;
- //var canReportProgress = total != -1 && progress != null;
+ //var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L;
+ //var canReportProgress = total != -1 && progress != null;
- await using var stream = await response.Content.ReadAsStreamAsync(token);
- var totalRead = 0L;
- var buffer = new byte[1024 * 64];
- var isMoreToRead = true;
- var progressSpeed = string.Empty;
- var totalDatetime = DateTime.Now;
- var totalSecond = 0;
+ await using var stream = await response.Content.ReadAsStreamAsync(token);
+ var totalRead = 0L;
+ var buffer = new byte[1024 * 64];
+ var isMoreToRead = true;
+ var progressSpeed = string.Empty;
+ var totalDatetime = DateTime.Now;
+ var totalSecond = 0;
- do
- {
- if (token.IsCancellationRequested)
- {
- if (totalRead > 0)
- {
- return;
- }
- else
- {
- token.ThrowIfCancellationRequested();
- }
- }
+ do
+ {
+ if (token.IsCancellationRequested)
+ {
+ if (totalRead > 0)
+ {
+ return;
+ }
+ else
+ {
+ token.ThrowIfCancellationRequested();
+ }
+ }
- var read = await stream.ReadAsync(buffer, token);
+ var read = await stream.ReadAsync(buffer, token);
- if (read == 0)
- {
- isMoreToRead = false;
- }
- else
- {
- var data = new byte[read];
- buffer.ToList().CopyTo(0, data, 0, read);
+ if (read == 0)
+ {
+ isMoreToRead = false;
+ }
+ else
+ {
+ var data = new byte[read];
+ buffer.ToList().CopyTo(0, data, 0, read);
- totalRead += read;
+ totalRead += read;
- var ts = (DateTime.Now - totalDatetime);
- if (progress != null && ts.Seconds > totalSecond)
- {
- totalSecond = ts.Seconds;
- var speed = (totalRead * 1d / ts.TotalMilliseconds / 1000).ToString("#0.0");
- if (progressSpeed != speed)
- {
- progressSpeed = speed;
- progress.Report(speed);
- }
- }
- }
- } while (isMoreToRead);
- }
- }
-}
\ No newline at end of file
+ var ts = DateTime.Now - totalDatetime;
+ if (progress != null && ts.Seconds > totalSecond)
+ {
+ totalSecond = ts.Seconds;
+ var speed = (totalRead * 1d / ts.TotalMilliseconds / 1000).ToString("#0.0");
+ if (progressSpeed != speed)
+ {
+ progressSpeed = speed;
+ progress.Report(speed);
+ }
+ }
+ }
+ } while (isMoreToRead);
+ }
+ }
+}
diff --git a/v2rayN/ServiceLib/Common/Job.cs b/v2rayN/ServiceLib/Common/Job.cs
index 4acf7520..5f82a09c 100644
--- a/v2rayN/ServiceLib/Common/Job.cs
+++ b/v2rayN/ServiceLib/Common/Job.cs
@@ -1,176 +1,177 @@
-using System.Diagnostics;
+using System.Diagnostics;
using System.Runtime.InteropServices;
namespace ServiceLib.Common
{
- /*
+ /*
* See:
* http://stackoverflow.com/questions/6266820/working-example-of-createjobobject-setinformationjobobject-pinvoke-in-net
*/
- public sealed class Job : IDisposable
- {
- private IntPtr handle = IntPtr.Zero;
+ public sealed class Job : IDisposable
+ {
+ private IntPtr handle = IntPtr.Zero;
- public Job()
- {
- handle = CreateJobObject(IntPtr.Zero, null);
- IntPtr extendedInfoPtr = IntPtr.Zero;
- JOBOBJECT_BASIC_LIMIT_INFORMATION info = new()
- {
- LimitFlags = 0x2000
- };
+ public Job()
+ {
+ handle = CreateJobObject(IntPtr.Zero, null);
+ IntPtr extendedInfoPtr = IntPtr.Zero;
+ JOBOBJECT_BASIC_LIMIT_INFORMATION info = new()
+ {
+ LimitFlags = 0x2000
+ };
- JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new()
- {
- BasicLimitInformation = info
- };
+ JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new()
+ {
+ BasicLimitInformation = info
+ };
- try
- {
- int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
- extendedInfoPtr = Marshal.AllocHGlobal(length);
- Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);
+ try
+ {
+ int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
+ extendedInfoPtr = Marshal.AllocHGlobal(length);
+ Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);
- if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr,
- (uint)length))
- throw new Exception(string.Format("Unable to set information. Error: {0}",
- Marshal.GetLastWin32Error()));
- }
- finally
- {
- if (extendedInfoPtr != IntPtr.Zero)
- {
- Marshal.FreeHGlobal(extendedInfoPtr);
- }
- }
- }
+ if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr,
+ (uint)length))
+ throw new Exception(string.Format("Unable to set information. Error: {0}",
+ Marshal.GetLastWin32Error()));
+ }
+ finally
+ {
+ if (extendedInfoPtr != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(extendedInfoPtr);
+ }
+ }
+ }
- public bool AddProcess(IntPtr processHandle)
- {
- bool succ = AssignProcessToJobObject(handle, processHandle);
+ public bool AddProcess(IntPtr processHandle)
+ {
+ bool succ = AssignProcessToJobObject(handle, processHandle);
- if (!succ)
- {
- Logging.SaveLog("Failed to call AssignProcessToJobObject! GetLastError=" + Marshal.GetLastWin32Error());
- }
+ if (!succ)
+ {
+ Logging.SaveLog("Failed to call AssignProcessToJobObject! GetLastError=" + Marshal.GetLastWin32Error());
+ }
- return succ;
- }
+ return succ;
+ }
- public bool AddProcess(int processId)
- {
- return AddProcess(Process.GetProcessById(processId).Handle);
- }
+ public bool AddProcess(int processId)
+ {
+ return AddProcess(Process.GetProcessById(processId).Handle);
+ }
- #region IDisposable
+ #region IDisposable
- private bool disposed;
+ private bool disposed;
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
- private void Dispose(bool disposing)
- {
- if (disposed) return;
- disposed = true;
+ private void Dispose(bool disposing)
+ {
+ if (disposed)
+ return;
+ disposed = true;
- if (disposing)
- {
- // no managed objects to free
- }
+ if (disposing)
+ {
+ // no managed objects to free
+ }
- if (handle != IntPtr.Zero)
- {
- CloseHandle(handle);
- handle = IntPtr.Zero;
- }
- }
+ if (handle != IntPtr.Zero)
+ {
+ CloseHandle(handle);
+ handle = IntPtr.Zero;
+ }
+ }
- ~Job()
- {
- Dispose(false);
- }
+ ~Job()
+ {
+ Dispose(false);
+ }
- #endregion IDisposable
+ #endregion IDisposable
- #region Interop
+ #region Interop
- [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- private static extern IntPtr CreateJobObject(IntPtr a, string? lpName);
+ [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
+ private static extern IntPtr CreateJobObject(IntPtr a, string? lpName);
- [DllImport("kernel32.dll", SetLastError = true)]
- private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, UInt32 cbJobObjectInfoLength);
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, UInt32 cbJobObjectInfoLength);
- [DllImport("kernel32.dll", SetLastError = true)]
- private static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);
- [DllImport("kernel32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- private static extern bool CloseHandle(IntPtr hObject);
+ [DllImport("kernel32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool CloseHandle(IntPtr hObject);
- #endregion Interop
- }
+ #endregion Interop
+ }
- #region Helper classes
+ #region Helper classes
- [StructLayout(LayoutKind.Sequential)]
- internal struct IO_COUNTERS
- {
- public UInt64 ReadOperationCount;
- public UInt64 WriteOperationCount;
- public UInt64 OtherOperationCount;
- public UInt64 ReadTransferCount;
- public UInt64 WriteTransferCount;
- public UInt64 OtherTransferCount;
- }
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct IO_COUNTERS
+ {
+ public UInt64 ReadOperationCount;
+ public UInt64 WriteOperationCount;
+ public UInt64 OtherOperationCount;
+ public UInt64 ReadTransferCount;
+ public UInt64 WriteTransferCount;
+ public UInt64 OtherTransferCount;
+ }
- [StructLayout(LayoutKind.Sequential)]
- internal struct JOBOBJECT_BASIC_LIMIT_INFORMATION
- {
- public Int64 PerProcessUserTimeLimit;
- public Int64 PerJobUserTimeLimit;
- public UInt32 LimitFlags;
- public UIntPtr MinimumWorkingSetSize;
- public UIntPtr MaximumWorkingSetSize;
- public UInt32 ActiveProcessLimit;
- public UIntPtr Affinity;
- public UInt32 PriorityClass;
- public UInt32 SchedulingClass;
- }
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct JOBOBJECT_BASIC_LIMIT_INFORMATION
+ {
+ public Int64 PerProcessUserTimeLimit;
+ public Int64 PerJobUserTimeLimit;
+ public UInt32 LimitFlags;
+ public UIntPtr MinimumWorkingSetSize;
+ public UIntPtr MaximumWorkingSetSize;
+ public UInt32 ActiveProcessLimit;
+ public UIntPtr Affinity;
+ public UInt32 PriorityClass;
+ public UInt32 SchedulingClass;
+ }
- [StructLayout(LayoutKind.Sequential)]
- public struct SECURITY_ATTRIBUTES
- {
- public UInt32 nLength;
- public IntPtr lpSecurityDescriptor;
- public Int32 bInheritHandle;
- }
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SECURITY_ATTRIBUTES
+ {
+ public UInt32 nLength;
+ public IntPtr lpSecurityDescriptor;
+ public Int32 bInheritHandle;
+ }
- [StructLayout(LayoutKind.Sequential)]
- internal struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
- {
- public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
- public IO_COUNTERS IoInfo;
- public UIntPtr ProcessMemoryLimit;
- public UIntPtr JobMemoryLimit;
- public UIntPtr PeakProcessMemoryUsed;
- public UIntPtr PeakJobMemoryUsed;
- }
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
+ {
+ public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
+ public IO_COUNTERS IoInfo;
+ public UIntPtr ProcessMemoryLimit;
+ public UIntPtr JobMemoryLimit;
+ public UIntPtr PeakProcessMemoryUsed;
+ public UIntPtr PeakJobMemoryUsed;
+ }
- public enum JobObjectInfoType
- {
- AssociateCompletionPortInformation = 7,
- BasicLimitInformation = 2,
- BasicUIRestrictions = 4,
- EndOfJobTimeInformation = 6,
- ExtendedLimitInformation = 9,
- SecurityLimitInformation = 5,
- GroupInformation = 11
- }
+ public enum JobObjectInfoType
+ {
+ AssociateCompletionPortInformation = 7,
+ BasicLimitInformation = 2,
+ BasicUIRestrictions = 4,
+ EndOfJobTimeInformation = 6,
+ ExtendedLimitInformation = 9,
+ SecurityLimitInformation = 5,
+ GroupInformation = 11
+ }
- #endregion Helper classes
-}
\ No newline at end of file
+ #endregion Helper classes
+}
diff --git a/v2rayN/ServiceLib/Common/JsonUtils.cs b/v2rayN/ServiceLib/Common/JsonUtils.cs
index 7d427f74..2c66b429 100644
--- a/v2rayN/ServiceLib/Common/JsonUtils.cs
+++ b/v2rayN/ServiceLib/Common/JsonUtils.cs
@@ -1,131 +1,131 @@
-using System.Text.Json;
+using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
namespace ServiceLib.Common
{
- public class JsonUtils
- {
- private static readonly string _tag = "JsonUtils";
+ public class JsonUtils
+ {
+ private static readonly string _tag = "JsonUtils";
- ///
- /// DeepCopy
- ///
- ///
- ///
- ///
- public static T DeepCopy(T obj)
- {
- return Deserialize(Serialize(obj, false))!;
- }
+ ///
+ /// DeepCopy
+ ///
+ ///
+ ///
+ ///
+ public static T DeepCopy(T obj)
+ {
+ return Deserialize(Serialize(obj, false))!;
+ }
- ///
- /// Deserialize to object
- ///
- ///
- ///
- ///
- public static T? Deserialize(string? strJson)
- {
- try
- {
- if (string.IsNullOrWhiteSpace(strJson))
- {
- return default;
- }
- var options = new JsonSerializerOptions
- {
- PropertyNameCaseInsensitive = true
- };
- return JsonSerializer.Deserialize(strJson, options);
- }
- catch
- {
- return default;
- }
- }
+ ///
+ /// Deserialize to object
+ ///
+ ///
+ ///
+ ///
+ public static T? Deserialize(string? strJson)
+ {
+ try
+ {
+ if (string.IsNullOrWhiteSpace(strJson))
+ {
+ return default;
+ }
+ var options = new JsonSerializerOptions
+ {
+ PropertyNameCaseInsensitive = true
+ };
+ return JsonSerializer.Deserialize(strJson, options);
+ }
+ catch
+ {
+ return default;
+ }
+ }
- ///
- /// parse
- ///
- ///
- ///
- public static JsonNode? ParseJson(string strJson)
- {
- try
- {
- if (string.IsNullOrWhiteSpace(strJson))
- {
- return null;
- }
- return JsonNode.Parse(strJson);
- }
- catch
- {
- //SaveLog(ex.Message, ex);
- return null;
- }
- }
+ ///
+ /// parse
+ ///
+ ///
+ ///
+ public static JsonNode? ParseJson(string strJson)
+ {
+ try
+ {
+ if (string.IsNullOrWhiteSpace(strJson))
+ {
+ return null;
+ }
+ return JsonNode.Parse(strJson);
+ }
+ catch
+ {
+ //SaveLog(ex.Message, ex);
+ return null;
+ }
+ }
- ///
- /// Serialize Object to Json string
- ///
- ///
- ///
- ///
- ///
- public static string Serialize(object? obj, bool indented = true, bool nullValue = false)
- {
- var result = string.Empty;
- try
- {
- if (obj == null)
- {
- return result;
- }
- var options = new JsonSerializerOptions
- {
- WriteIndented = indented,
- DefaultIgnoreCondition = nullValue ? JsonIgnoreCondition.Never : JsonIgnoreCondition.WhenWritingNull
- };
- result = JsonSerializer.Serialize(obj, options);
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
- return result;
- }
+ ///
+ /// Serialize Object to Json string
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string Serialize(object? obj, bool indented = true, bool nullValue = false)
+ {
+ var result = string.Empty;
+ try
+ {
+ if (obj == null)
+ {
+ return result;
+ }
+ var options = new JsonSerializerOptions
+ {
+ WriteIndented = indented,
+ DefaultIgnoreCondition = nullValue ? JsonIgnoreCondition.Never : JsonIgnoreCondition.WhenWritingNull
+ };
+ result = JsonSerializer.Serialize(obj, options);
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+ return result;
+ }
- ///
- /// Serialize Object to Json string
- ///
- ///
- ///
- ///
- public static string Serialize(object? obj, JsonSerializerOptions options)
- {
- var result = string.Empty;
- try
- {
- if (obj == null)
- {
- return result;
- }
- result = JsonSerializer.Serialize(obj, options);
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
- return result;
- }
+ ///
+ /// Serialize Object to Json string
+ ///
+ ///
+ ///
+ ///
+ public static string Serialize(object? obj, JsonSerializerOptions options)
+ {
+ var result = string.Empty;
+ try
+ {
+ if (obj == null)
+ {
+ return result;
+ }
+ result = JsonSerializer.Serialize(obj, options);
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+ return result;
+ }
- ///
- /// SerializeToNode
- ///
- ///
- ///
- public static JsonNode? SerializeToNode(object? obj) => JsonSerializer.SerializeToNode(obj);
- }
-}
\ No newline at end of file
+ ///
+ /// SerializeToNode
+ ///
+ ///
+ ///
+ public static JsonNode? SerializeToNode(object? obj) => JsonSerializer.SerializeToNode(obj);
+ }
+}
diff --git a/v2rayN/ServiceLib/Common/Logging.cs b/v2rayN/ServiceLib/Common/Logging.cs
index 7031260f..365eab41 100644
--- a/v2rayN/ServiceLib/Common/Logging.cs
+++ b/v2rayN/ServiceLib/Common/Logging.cs
@@ -1,48 +1,50 @@
-using NLog;
+using NLog;
using NLog.Config;
using NLog.Targets;
namespace ServiceLib.Common
{
- public class Logging
- {
- public static void Setup()
- {
- LoggingConfiguration config = new();
- FileTarget fileTarget = new();
- config.AddTarget("file", fileTarget);
- fileTarget.Layout = "${longdate}-${level:uppercase=true} ${message}";
- fileTarget.FileName = Utils.GetLogPath("${shortdate}.txt");
- config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, fileTarget));
- LogManager.Configuration = config;
- }
+ public class Logging
+ {
+ public static void Setup()
+ {
+ LoggingConfiguration config = new();
+ FileTarget fileTarget = new();
+ config.AddTarget("file", fileTarget);
+ fileTarget.Layout = "${longdate}-${level:uppercase=true} ${message}";
+ fileTarget.FileName = Utils.GetLogPath("${shortdate}.txt");
+ config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, fileTarget));
+ LogManager.Configuration = config;
+ }
- public static void LoggingEnabled(bool enable)
- {
- if (!enable)
- {
- LogManager.SuspendLogging();
- }
- }
+ public static void LoggingEnabled(bool enable)
+ {
+ if (!enable)
+ {
+ LogManager.SuspendLogging();
+ }
+ }
- public static void SaveLog(string strContent)
- {
- if (!LogManager.IsLoggingEnabled()) return;
+ public static void SaveLog(string strContent)
+ {
+ if (!LogManager.IsLoggingEnabled())
+ return;
- LogManager.GetLogger("Log1").Info(strContent);
- }
+ LogManager.GetLogger("Log1").Info(strContent);
+ }
- public static void SaveLog(string strTitle, Exception ex)
- {
- if (!LogManager.IsLoggingEnabled()) return;
+ public static void SaveLog(string strTitle, Exception ex)
+ {
+ if (!LogManager.IsLoggingEnabled())
+ return;
- var logger = LogManager.GetLogger("Log2");
- logger.Debug($"{strTitle},{ex.Message}");
- logger.Debug(ex.StackTrace);
- if (ex?.InnerException != null)
- {
- logger.Error(ex.InnerException);
- }
- }
- }
-}
\ No newline at end of file
+ var logger = LogManager.GetLogger("Log2");
+ logger.Debug($"{strTitle},{ex.Message}");
+ logger.Debug(ex.StackTrace);
+ if (ex?.InnerException != null)
+ {
+ logger.Error(ex.InnerException);
+ }
+ }
+ }
+}
diff --git a/v2rayN/ServiceLib/Common/ProcUtils.cs b/v2rayN/ServiceLib/Common/ProcUtils.cs
index b58ca41c..d82d4ebb 100644
--- a/v2rayN/ServiceLib/Common/ProcUtils.cs
+++ b/v2rayN/ServiceLib/Common/ProcUtils.cs
@@ -4,136 +4,147 @@ namespace ServiceLib.Common;
public static class ProcUtils
{
- private static readonly string _tag = "ProcUtils";
+ private static readonly string _tag = "ProcUtils";
- public static void ProcessStart(string? fileName, string arguments = "")
- {
- ProcessStart(fileName, arguments, null);
- }
+ public static void ProcessStart(string? fileName, string arguments = "")
+ {
+ ProcessStart(fileName, arguments, null);
+ }
- public static int? ProcessStart(string? fileName, string arguments, string? dir)
- {
- if (fileName.IsNullOrEmpty())
- {
- return null;
- }
- try
- {
- if (fileName.Contains(' ')) fileName = fileName.AppendQuotes();
- if (arguments.Contains(' ')) arguments = arguments.AppendQuotes();
+ public static int? ProcessStart(string? fileName, string arguments, string? dir)
+ {
+ if (fileName.IsNullOrEmpty())
+ {
+ return null;
+ }
+ try
+ {
+ if (fileName.Contains(' '))
+ fileName = fileName.AppendQuotes();
+ if (arguments.Contains(' '))
+ arguments = arguments.AppendQuotes();
- Process process = new()
- {
- StartInfo = new ProcessStartInfo
- {
- UseShellExecute = true,
- FileName = fileName,
- Arguments = arguments,
- WorkingDirectory = dir
- }
- };
- process.Start();
- return process.Id;
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
- return null;
- }
+ Process process = new()
+ {
+ StartInfo = new ProcessStartInfo
+ {
+ UseShellExecute = true,
+ FileName = fileName,
+ Arguments = arguments,
+ WorkingDirectory = dir
+ }
+ };
+ process.Start();
+ return process.Id;
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+ return null;
+ }
- public static void RebootAsAdmin(bool blAdmin = true)
- {
- try
- {
- ProcessStartInfo startInfo = new()
- {
- UseShellExecute = true,
- Arguments = Global.RebootAs,
- WorkingDirectory = Utils.StartupPath(),
- FileName = Utils.GetExePath().AppendQuotes(),
- Verb = blAdmin ? "runas" : null,
- };
- Process.Start(startInfo);
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
- }
+ public static void RebootAsAdmin(bool blAdmin = true)
+ {
+ try
+ {
+ ProcessStartInfo startInfo = new()
+ {
+ UseShellExecute = true,
+ Arguments = Global.RebootAs,
+ WorkingDirectory = Utils.StartupPath(),
+ FileName = Utils.GetExePath().AppendQuotes(),
+ Verb = blAdmin ? "runas" : null,
+ };
+ Process.Start(startInfo);
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+ }
- public static async Task ProcessKill(int pid)
- {
- try
- {
- await ProcessKill(Process.GetProcessById(pid), false);
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
- }
+ public static async Task ProcessKill(int pid)
+ {
+ try
+ {
+ await ProcessKill(Process.GetProcessById(pid), false);
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+ }
- public static async Task ProcessKill(Process? proc, bool review)
- {
- if (proc is null)
- {
- return;
- }
+ public static async Task ProcessKill(Process? proc, bool review)
+ {
+ if (proc is null)
+ {
+ return;
+ }
- GetProcessKeyInfo(proc, review, out var procId, out var fileName, out var processName);
+ GetProcessKeyInfo(proc, review, out var procId, out var fileName, out var processName);
- try { proc?.Kill(true); } catch (Exception ex) { Logging.SaveLog(_tag, ex); }
- try { proc?.Kill(); } catch (Exception ex) { Logging.SaveLog(_tag, ex); }
- try { proc?.Close(); } catch (Exception ex) { Logging.SaveLog(_tag, ex); }
- try { proc?.Dispose(); } catch (Exception ex) { Logging.SaveLog(_tag, ex); }
+ try
+ { proc?.Kill(true); }
+ catch (Exception ex) { Logging.SaveLog(_tag, ex); }
+ try
+ { proc?.Kill(); }
+ catch (Exception ex) { Logging.SaveLog(_tag, ex); }
+ try
+ { proc?.Close(); }
+ catch (Exception ex) { Logging.SaveLog(_tag, ex); }
+ try
+ { proc?.Dispose(); }
+ catch (Exception ex) { Logging.SaveLog(_tag, ex); }
- await Task.Delay(300);
- await ProcessKillByKeyInfo(review, procId, fileName, processName);
- }
+ await Task.Delay(300);
+ await ProcessKillByKeyInfo(review, procId, fileName, processName);
+ }
- private static void GetProcessKeyInfo(Process? proc, bool review, out int? procId, out string? fileName, out string? processName)
- {
- procId = null;
- fileName = null;
- processName = null;
- if (!review) return;
- try
- {
- procId = proc?.Id;
- fileName = proc?.MainModule?.FileName;
- processName = proc?.ProcessName;
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
- }
+ private static void GetProcessKeyInfo(Process? proc, bool review, out int? procId, out string? fileName, out string? processName)
+ {
+ procId = null;
+ fileName = null;
+ processName = null;
+ if (!review)
+ return;
+ try
+ {
+ procId = proc?.Id;
+ fileName = proc?.MainModule?.FileName;
+ processName = proc?.ProcessName;
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+ }
- private static async Task ProcessKillByKeyInfo(bool review, int? procId, string? fileName, string? processName)
- {
- if (review && procId != null && fileName != null)
- {
- try
- {
- var lstProc = Process.GetProcessesByName(processName);
- foreach (var proc2 in lstProc)
- {
- if (proc2.Id == procId)
- {
- Logging.SaveLog($"{_tag}, KillProcess not completing the job, procId");
- await ProcessKill(proc2, false);
- }
- if (proc2.MainModule != null && proc2.MainModule?.FileName == fileName)
- {
- Logging.SaveLog($"{_tag}, KillProcess not completing the job, fileName");
- }
- }
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
- }
- }
-}
\ No newline at end of file
+ private static async Task ProcessKillByKeyInfo(bool review, int? procId, string? fileName, string? processName)
+ {
+ if (review && procId != null && fileName != null)
+ {
+ try
+ {
+ var lstProc = Process.GetProcessesByName(processName);
+ foreach (var proc2 in lstProc)
+ {
+ if (proc2.Id == procId)
+ {
+ Logging.SaveLog($"{_tag}, KillProcess not completing the job, procId");
+ await ProcessKill(proc2, false);
+ }
+ if (proc2.MainModule != null && proc2.MainModule?.FileName == fileName)
+ {
+ Logging.SaveLog($"{_tag}, KillProcess not completing the job, fileName");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+ }
+ }
+}
diff --git a/v2rayN/ServiceLib/Common/QRCodeHelper.cs b/v2rayN/ServiceLib/Common/QRCodeHelper.cs
index 7a024a3e..b65c93af 100644
--- a/v2rayN/ServiceLib/Common/QRCodeHelper.cs
+++ b/v2rayN/ServiceLib/Common/QRCodeHelper.cs
@@ -1,90 +1,90 @@
-using QRCoder;
+using QRCoder;
using SkiaSharp;
using ZXing.SkiaSharp;
namespace ServiceLib.Common
{
- public class QRCodeHelper
- {
- public static byte[]? GenQRCode(string? url)
- {
- using QRCodeGenerator qrGenerator = new();
- using var qrCodeData = qrGenerator.CreateQrCode(url ?? string.Empty, QRCodeGenerator.ECCLevel.Q);
- using PngByteQRCode qrCode = new(qrCodeData);
- return qrCode.GetGraphic(20);
- }
+ public class QRCodeHelper
+ {
+ public static byte[]? GenQRCode(string? url)
+ {
+ using QRCodeGenerator qrGenerator = new();
+ using var qrCodeData = qrGenerator.CreateQrCode(url ?? string.Empty, QRCodeGenerator.ECCLevel.Q);
+ using PngByteQRCode qrCode = new(qrCodeData);
+ return qrCode.GetGraphic(20);
+ }
- public static string? ParseBarcode(string? fileName)
- {
- if (fileName == null || !File.Exists(fileName))
- {
- return null;
- }
+ public static string? ParseBarcode(string? fileName)
+ {
+ if (fileName == null || !File.Exists(fileName))
+ {
+ return null;
+ }
- try
- {
- var image = SKImage.FromEncodedData(fileName);
- var bitmap = SKBitmap.FromImage(image);
+ try
+ {
+ var image = SKImage.FromEncodedData(fileName);
+ var bitmap = SKBitmap.FromImage(image);
- return ReaderBarcode(bitmap);
- }
- catch
- {
- // ignored
- }
+ return ReaderBarcode(bitmap);
+ }
+ catch
+ {
+ // ignored
+ }
- return null;
- }
+ return null;
+ }
- public static string? ParseBarcode(byte[]? bytes)
- {
- try
- {
- var bitmap = SKBitmap.Decode(bytes);
- //using var stream = new FileStream("test2.png", FileMode.Create, FileAccess.Write);
- //using var image = SKImage.FromBitmap(bitmap);
- //using var encodedImage = image.Encode();
- //encodedImage.SaveTo(stream);
- return ReaderBarcode(bitmap);
- }
- catch
- {
- // ignored
- }
+ public static string? ParseBarcode(byte[]? bytes)
+ {
+ try
+ {
+ var bitmap = SKBitmap.Decode(bytes);
+ //using var stream = new FileStream("test2.png", FileMode.Create, FileAccess.Write);
+ //using var image = SKImage.FromBitmap(bitmap);
+ //using var encodedImage = image.Encode();
+ //encodedImage.SaveTo(stream);
+ return ReaderBarcode(bitmap);
+ }
+ catch
+ {
+ // ignored
+ }
- return null;
- }
+ return null;
+ }
- private static string? ReaderBarcode(SKBitmap? bitmap)
- {
- var reader = new BarcodeReader();
- var result = reader.Decode(bitmap);
+ private static string? ReaderBarcode(SKBitmap? bitmap)
+ {
+ var reader = new BarcodeReader();
+ var result = reader.Decode(bitmap);
- if (result != null && Utils.IsNotEmpty(result.Text))
- {
- return result.Text;
- }
+ if (result != null && Utils.IsNotEmpty(result.Text))
+ {
+ return result.Text;
+ }
- //FlipBitmap
- var result2 = reader.Decode(FlipBitmap(bitmap));
- return result2?.Text;
- }
+ //FlipBitmap
+ var result2 = reader.Decode(FlipBitmap(bitmap));
+ return result2?.Text;
+ }
- private static SKBitmap FlipBitmap(SKBitmap bmp)
- {
- // Create a bitmap (to return)
- var flipped = new SKBitmap(bmp.Width, bmp.Height, bmp.Info.ColorType, bmp.Info.AlphaType);
+ private static SKBitmap FlipBitmap(SKBitmap bmp)
+ {
+ // Create a bitmap (to return)
+ var flipped = new SKBitmap(bmp.Width, bmp.Height, bmp.Info.ColorType, bmp.Info.AlphaType);
- // Create a canvas to draw into the bitmap
- using var canvas = new SKCanvas(flipped);
+ // Create a canvas to draw into the bitmap
+ using var canvas = new SKCanvas(flipped);
- // Set a transform matrix which moves the bitmap to the right,
- // and then "scales" it by -1, which just flips the pixels
- // horizontally
- canvas.Translate(bmp.Width, 0);
- canvas.Scale(-1, 1);
- canvas.DrawBitmap(bmp, 0, 0);
- return flipped;
- }
- }
-}
\ No newline at end of file
+ // Set a transform matrix which moves the bitmap to the right,
+ // and then "scales" it by -1, which just flips the pixels
+ // horizontally
+ canvas.Translate(bmp.Width, 0);
+ canvas.Scale(-1, 1);
+ canvas.DrawBitmap(bmp, 0, 0);
+ return flipped;
+ }
+ }
+}
diff --git a/v2rayN/ServiceLib/Common/SemanticVersion.cs b/v2rayN/ServiceLib/Common/SemanticVersion.cs
index 0a5bd5b9..2ee8922f 100644
--- a/v2rayN/ServiceLib/Common/SemanticVersion.cs
+++ b/v2rayN/ServiceLib/Common/SemanticVersion.cs
@@ -1,187 +1,187 @@
-namespace ServiceLib.Common
+namespace ServiceLib.Common
{
- public class SemanticVersion
- {
- private int major;
- private int minor;
- private int patch;
- private string version;
+ public class SemanticVersion
+ {
+ private int major;
+ private int minor;
+ private int patch;
+ private string version;
- public SemanticVersion(int major, int minor, int patch)
- {
- this.major = major;
- this.minor = minor;
- this.patch = patch;
- this.version = $"{major}.{minor}.{patch}";
- }
+ public SemanticVersion(int major, int minor, int patch)
+ {
+ this.major = major;
+ this.minor = minor;
+ this.patch = patch;
+ this.version = $"{major}.{minor}.{patch}";
+ }
- public SemanticVersion(string? version)
- {
- try
- {
- if (version.IsNullOrEmpty())
- {
- this.major = 0;
- this.minor = 0;
- this.patch = 0;
- return;
- }
- this.version = version.RemovePrefix('v');
+ public SemanticVersion(string? version)
+ {
+ try
+ {
+ if (version.IsNullOrEmpty())
+ {
+ this.major = 0;
+ this.minor = 0;
+ this.patch = 0;
+ return;
+ }
+ this.version = version.RemovePrefix('v');
- var parts = this.version.Split('.');
- if (parts.Length == 2)
- {
- this.major = int.Parse(parts.First());
- this.minor = int.Parse(parts.Last());
- this.patch = 0;
- }
- else if (parts.Length is 3 or 4)
- {
- this.major = int.Parse(parts[0]);
- this.minor = int.Parse(parts[1]);
- this.patch = int.Parse(parts[2]);
- }
- else
- {
- throw new ArgumentException("Invalid version string");
- }
- }
- catch
- {
- this.major = 0;
- this.minor = 0;
- this.patch = 0;
- }
- }
+ var parts = this.version.Split('.');
+ if (parts.Length == 2)
+ {
+ this.major = int.Parse(parts.First());
+ this.minor = int.Parse(parts.Last());
+ this.patch = 0;
+ }
+ else if (parts.Length is 3 or 4)
+ {
+ this.major = int.Parse(parts[0]);
+ this.minor = int.Parse(parts[1]);
+ this.patch = int.Parse(parts[2]);
+ }
+ else
+ {
+ throw new ArgumentException("Invalid version string");
+ }
+ }
+ catch
+ {
+ this.major = 0;
+ this.minor = 0;
+ this.patch = 0;
+ }
+ }
- public override bool Equals(object? obj)
- {
- if (obj is SemanticVersion other)
- {
- return this.major == other.major && this.minor == other.minor && this.patch == other.patch;
- }
- else
- {
- return false;
- }
- }
+ public override bool Equals(object? obj)
+ {
+ if (obj is SemanticVersion other)
+ {
+ return this.major == other.major && this.minor == other.minor && this.patch == other.patch;
+ }
+ else
+ {
+ return false;
+ }
+ }
- public override int GetHashCode()
- {
- return this.major.GetHashCode() ^ this.minor.GetHashCode() ^ this.patch.GetHashCode();
- }
+ public override int GetHashCode()
+ {
+ return this.major.GetHashCode() ^ this.minor.GetHashCode() ^ this.patch.GetHashCode();
+ }
- ///
- /// Use ToVersionString(string? prefix) instead if possible.
- ///
- /// major.minor.patch
- public override string ToString()
- {
- return this.version;
- }
+ ///
+ /// Use ToVersionString(string? prefix) instead if possible.
+ ///
+ /// major.minor.patch
+ public override string ToString()
+ {
+ return this.version;
+ }
- public string ToVersionString(string? prefix = null)
- {
- if (prefix == null)
- {
- return this.version;
- }
- else
- {
- return $"{prefix}{this.version}";
- }
- }
+ public string ToVersionString(string? prefix = null)
+ {
+ if (prefix == null)
+ {
+ return this.version;
+ }
+ else
+ {
+ return $"{prefix}{this.version}";
+ }
+ }
- public static bool operator ==(SemanticVersion v1, SemanticVersion v2)
- { return v1.Equals(v2); }
+ public static bool operator ==(SemanticVersion v1, SemanticVersion v2)
+ { return v1.Equals(v2); }
- public static bool operator !=(SemanticVersion v1, SemanticVersion v2)
- { return !v1.Equals(v2); }
+ public static bool operator !=(SemanticVersion v1, SemanticVersion v2)
+ { return !v1.Equals(v2); }
- public static bool operator >=(SemanticVersion v1, SemanticVersion v2)
- { return v1.GreaterEquals(v2); }
+ public static bool operator >=(SemanticVersion v1, SemanticVersion v2)
+ { return v1.GreaterEquals(v2); }
- public static bool operator <=(SemanticVersion v1, SemanticVersion v2)
- { return v1.LessEquals(v2); }
+ public static bool operator <=(SemanticVersion v1, SemanticVersion v2)
+ { return v1.LessEquals(v2); }
- #region Private
+ #region Private
- private bool GreaterEquals(SemanticVersion other)
- {
- if (this.major < other.major)
- {
- return false;
- }
- else if (this.major > other.major)
- {
- return true;
- }
- else
- {
- if (this.minor < other.minor)
- {
- return false;
- }
- else if (this.minor > other.minor)
- {
- return true;
- }
- else
- {
- if (this.patch < other.patch)
- {
- return false;
- }
- else if (this.patch > other.patch)
- {
- return true;
- }
- else
- {
- return true;
- }
- }
- }
- }
+ private bool GreaterEquals(SemanticVersion other)
+ {
+ if (this.major < other.major)
+ {
+ return false;
+ }
+ else if (this.major > other.major)
+ {
+ return true;
+ }
+ else
+ {
+ if (this.minor < other.minor)
+ {
+ return false;
+ }
+ else if (this.minor > other.minor)
+ {
+ return true;
+ }
+ else
+ {
+ if (this.patch < other.patch)
+ {
+ return false;
+ }
+ else if (this.patch > other.patch)
+ {
+ return true;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ }
+ }
- private bool LessEquals(SemanticVersion other)
- {
- if (this.major < other.major)
- {
- return true;
- }
- else if (this.major > other.major)
- {
- return false;
- }
- else
- {
- if (this.minor < other.minor)
- {
- return true;
- }
- else if (this.minor > other.minor)
- {
- return false;
- }
- else
- {
- if (this.patch < other.patch)
- {
- return true;
- }
- else if (this.patch > other.patch)
- {
- return false;
- }
- else
- {
- return true;
- }
- }
- }
- }
+ private bool LessEquals(SemanticVersion other)
+ {
+ if (this.major < other.major)
+ {
+ return true;
+ }
+ else if (this.major > other.major)
+ {
+ return false;
+ }
+ else
+ {
+ if (this.minor < other.minor)
+ {
+ return true;
+ }
+ else if (this.minor > other.minor)
+ {
+ return false;
+ }
+ else
+ {
+ if (this.patch < other.patch)
+ {
+ return true;
+ }
+ else if (this.patch > other.patch)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ }
+ }
- #endregion Private
- }
-}
\ No newline at end of file
+ #endregion Private
+ }
+}
diff --git a/v2rayN/ServiceLib/Common/SqliteHelper.cs b/v2rayN/ServiceLib/Common/SqliteHelper.cs
index 3a8946bf..6195ed57 100644
--- a/v2rayN/ServiceLib/Common/SqliteHelper.cs
+++ b/v2rayN/ServiceLib/Common/SqliteHelper.cs
@@ -1,91 +1,91 @@
-using SQLite;
using System.Collections;
+using SQLite;
namespace ServiceLib.Common
{
- public sealed class SQLiteHelper
- {
- private static readonly Lazy _instance = new(() => new());
- public static SQLiteHelper Instance => _instance.Value;
- private string _connstr;
- private SQLiteConnection _db;
- private SQLiteAsyncConnection _dbAsync;
- private readonly string _configDB = "guiNDB.db";
+ public sealed class SQLiteHelper
+ {
+ private static readonly Lazy _instance = new(() => new());
+ public static SQLiteHelper Instance => _instance.Value;
+ private string _connstr;
+ private SQLiteConnection _db;
+ private SQLiteAsyncConnection _dbAsync;
+ private readonly string _configDB = "guiNDB.db";
- public SQLiteHelper()
- {
- _connstr = Utils.GetConfigPath(_configDB);
- _db = new SQLiteConnection(_connstr, false);
- _dbAsync = new SQLiteAsyncConnection(_connstr, false);
- }
+ public SQLiteHelper()
+ {
+ _connstr = Utils.GetConfigPath(_configDB);
+ _db = new SQLiteConnection(_connstr, false);
+ _dbAsync = new SQLiteAsyncConnection(_connstr, false);
+ }
- public CreateTableResult CreateTable()
- {
- return _db.CreateTable();
- }
+ public CreateTableResult CreateTable()
+ {
+ return _db.CreateTable();
+ }
- public async Task InsertAllAsync(IEnumerable models)
- {
- return await _dbAsync.InsertAllAsync(models);
- }
+ public async Task InsertAllAsync(IEnumerable models)
+ {
+ return await _dbAsync.InsertAllAsync(models);
+ }
- public async Task InsertAsync(object model)
- {
- return await _dbAsync.InsertAsync(model);
- }
+ public async Task InsertAsync(object model)
+ {
+ return await _dbAsync.InsertAsync(model);
+ }
- public async Task ReplaceAsync(object model)
- {
- return await _dbAsync.InsertOrReplaceAsync(model);
- }
+ public async Task ReplaceAsync(object model)
+ {
+ return await _dbAsync.InsertOrReplaceAsync(model);
+ }
- public async Task UpdateAsync(object model)
- {
- return await _dbAsync.UpdateAsync(model);
- }
+ public async Task UpdateAsync(object model)
+ {
+ return await _dbAsync.UpdateAsync(model);
+ }
- public async Task UpdateAllAsync(IEnumerable models)
- {
- return await _dbAsync.UpdateAllAsync(models);
- }
+ public async Task UpdateAllAsync(IEnumerable models)
+ {
+ return await _dbAsync.UpdateAllAsync(models);
+ }
- public async Task DeleteAsync(object model)
- {
- return await _dbAsync.DeleteAsync(model);
- }
+ public async Task DeleteAsync(object model)
+ {
+ return await _dbAsync.DeleteAsync(model);
+ }
- public async Task DeleteAllAsync()
- {
- return await _dbAsync.DeleteAllAsync();
- }
+ public async Task DeleteAllAsync()
+ {
+ return await _dbAsync.DeleteAllAsync();
+ }
- public async Task ExecuteAsync(string sql)
- {
- return await _dbAsync.ExecuteAsync(sql);
- }
+ public async Task ExecuteAsync(string sql)
+ {
+ return await _dbAsync.ExecuteAsync(sql);
+ }
- public async Task> QueryAsync(string sql) where T : new()
- {
- return await _dbAsync.QueryAsync(sql);
- }
+ public async Task> QueryAsync(string sql) where T : new()
+ {
+ return await _dbAsync.QueryAsync(sql);
+ }
- public AsyncTableQuery TableAsync() where T : new()
- {
- return _dbAsync.Table();
- }
+ public AsyncTableQuery TableAsync() where T : new()
+ {
+ return _dbAsync.Table();
+ }
- public async Task DisposeDbConnectionAsync()
- {
- await Task.Factory.StartNew(() =>
- {
- _db?.Close();
- _db?.Dispose();
- _db = null;
+ public async Task DisposeDbConnectionAsync()
+ {
+ await Task.Factory.StartNew(() =>
+ {
+ _db?.Close();
+ _db?.Dispose();
+ _db = null;
- _dbAsync?.GetConnection()?.Close();
- _dbAsync?.GetConnection()?.Dispose();
- _dbAsync = null;
- });
- }
- }
-}
\ No newline at end of file
+ _dbAsync?.GetConnection()?.Close();
+ _dbAsync?.GetConnection()?.Dispose();
+ _dbAsync = null;
+ });
+ }
+ }
+}
diff --git a/v2rayN/ServiceLib/Common/StringEx.cs b/v2rayN/ServiceLib/Common/StringEx.cs
index c0d0a8cc..a611a215 100644
--- a/v2rayN/ServiceLib/Common/StringEx.cs
+++ b/v2rayN/ServiceLib/Common/StringEx.cs
@@ -1,72 +1,74 @@
-using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.CodeAnalysis;
namespace ServiceLib.Common
{
- public static class StringEx
- {
- public static bool IsNullOrEmpty([NotNullWhen(false)] this string? value)
- {
- return string.IsNullOrEmpty(value);
- }
+ public static class StringEx
+ {
+ public static bool IsNullOrEmpty([NotNullWhen(false)] this string? value)
+ {
+ return string.IsNullOrEmpty(value);
+ }
- public static bool IsNullOrWhiteSpace([NotNullWhen(false)] this string? value)
- {
- return string.IsNullOrWhiteSpace(value);
- }
+ public static bool IsNullOrWhiteSpace([NotNullWhen(false)] this string? value)
+ {
+ return string.IsNullOrWhiteSpace(value);
+ }
- public static bool IsNotEmpty([NotNullWhen(false)] this string? value)
- {
- return !string.IsNullOrEmpty(value);
- }
+ public static bool IsNotEmpty([NotNullWhen(false)] this string? value)
+ {
+ return !string.IsNullOrEmpty(value);
+ }
- public static bool BeginWithAny(this string s, IEnumerable chars)
- {
- if (s.IsNullOrEmpty()) return false;
- return chars.Contains(s.First());
- }
+ public static bool BeginWithAny(this string s, IEnumerable chars)
+ {
+ if (s.IsNullOrEmpty())
+ return false;
+ return chars.Contains(s.First());
+ }
- private static bool IsWhiteSpace(this string value)
- {
- return value.All(char.IsWhiteSpace);
- }
+ private static bool IsWhiteSpace(this string value)
+ {
+ return value.All(char.IsWhiteSpace);
+ }
- public static IEnumerable NonWhiteSpaceLines(this TextReader reader)
- {
- while (reader.ReadLine() is { } line)
- {
- if (line.IsWhiteSpace()) continue;
- yield return line;
- }
- }
+ public static IEnumerable NonWhiteSpaceLines(this TextReader reader)
+ {
+ while (reader.ReadLine() is { } line)
+ {
+ if (line.IsWhiteSpace())
+ continue;
+ yield return line;
+ }
+ }
- public static string TrimEx(this string? value)
- {
- return value == null ? string.Empty : value.Trim();
- }
+ public static string TrimEx(this string? value)
+ {
+ return value == null ? string.Empty : value.Trim();
+ }
- public static string RemovePrefix(this string value, char prefix)
- {
- return value.StartsWith(prefix) ? value[1..] : value;
- }
+ public static string RemovePrefix(this string value, char prefix)
+ {
+ return value.StartsWith(prefix) ? value[1..] : value;
+ }
- public static string RemovePrefix(this string value, string prefix)
- {
- return value.StartsWith(prefix) ? value[prefix.Length..] : value;
- }
+ public static string RemovePrefix(this string value, string prefix)
+ {
+ return value.StartsWith(prefix) ? value[prefix.Length..] : value;
+ }
- public static string UpperFirstChar(this string value)
- {
- if (string.IsNullOrEmpty(value))
- {
- return string.Empty;
- }
+ public static string UpperFirstChar(this string value)
+ {
+ if (string.IsNullOrEmpty(value))
+ {
+ return string.Empty;
+ }
- return char.ToUpper(value.First()) + value[1..];
- }
+ return char.ToUpper(value.First()) + value[1..];
+ }
- public static string AppendQuotes(this string value)
- {
- return string.IsNullOrEmpty(value) ? string.Empty : $"\"{value}\"";
- }
- }
-}
\ No newline at end of file
+ public static string AppendQuotes(this string value)
+ {
+ return string.IsNullOrEmpty(value) ? string.Empty : $"\"{value}\"";
+ }
+ }
+}
diff --git a/v2rayN/ServiceLib/Common/Utils.cs b/v2rayN/ServiceLib/Common/Utils.cs
index f158097b..67a904c6 100644
--- a/v2rayN/ServiceLib/Common/Utils.cs
+++ b/v2rayN/ServiceLib/Common/Utils.cs
@@ -1,5 +1,3 @@
-using CliWrap;
-using CliWrap.Buffered;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Net;
@@ -10,898 +8,909 @@ using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Principal;
using System.Text;
+using CliWrap;
+using CliWrap.Buffered;
namespace ServiceLib.Common
{
- public class Utils
- {
- private static readonly string _tag = "Utils";
-
- #region 资源操作
-
- ///
- /// 获取嵌入文本资源
- ///
- ///
- ///
- public static string GetEmbedText(string res)
- {
- var result = string.Empty;
-
- try
- {
- var assembly = Assembly.GetExecutingAssembly();
- using var stream = assembly.GetManifestResourceStream(res);
- ArgumentNullException.ThrowIfNull(stream);
- using StreamReader reader = new(stream);
- result = reader.ReadToEnd();
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
-
- return result;
- }
-
- ///
- /// 取得存储资源
- ///
- ///
- public static string? LoadResource(string? res)
- {
- try
- {
- if (File.Exists(res))
- {
- return File.ReadAllText(res);
- }
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
-
- return null;
- }
-
- #endregion 资源操作
-
- #region 转换函数
-
- ///
- /// 转逗号分隔的字符串
- ///
- ///
- ///
- ///
- public static string List2String(List? lst, bool wrap = false)
- {
- try
- {
- if (lst == null)
- {
- return string.Empty;
- }
- if (wrap)
- {
- return string.Join("," + Environment.NewLine, lst);
- }
- else
- {
- return string.Join(",", lst);
- }
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
-
- return string.Empty;
- }
-
- ///
- /// 逗号分隔的字符串
- ///
- ///
- ///
- public static List? String2List(string? str)
- {
- try
- {
- if (str == null)
- {
- return null;
- }
-
- str = str.Replace(Environment.NewLine, "");
- return new List(str.Split(',', StringSplitOptions.RemoveEmptyEntries));
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
-
- return null;
- }
-
- ///
- /// 逗号分隔的字符串,先排序后转List
- ///
- ///
- ///
- public static List? String2ListSorted(string str)
- {
- try
- {
- str = str.Replace(Environment.NewLine, "");
- List list = new(str.Split(',', StringSplitOptions.RemoveEmptyEntries));
- list.Sort();
- return list;
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
-
- return null;
- }
-
- ///
- /// Base64编码
- ///
- ///
- ///
- public static string Base64Encode(string plainText)
- {
- try
- {
- var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
- return Convert.ToBase64String(plainTextBytes);
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
-
- return string.Empty;
- }
-
- ///
- /// Base64解码
- ///
- ///
- ///
- public static string Base64Decode(string? plainText)
- {
- try
- {
- if (plainText.IsNullOrEmpty()) return "";
- plainText = plainText.Trim()
- .Replace(Environment.NewLine, "")
- .Replace("\n", "")
- .Replace("\r", "")
- .Replace('_', '/')
- .Replace('-', '+')
- .Replace(" ", "");
-
- if (plainText.Length % 4 > 0)
- {
- plainText = plainText.PadRight(plainText.Length + 4 - (plainText.Length % 4), '=');
- }
-
- var data = Convert.FromBase64String(plainText);
- return Encoding.UTF8.GetString(data);
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
-
- return string.Empty;
- }
-
- public static int ToInt(object? obj)
- {
- try
- {
- return Convert.ToInt32(obj ?? string.Empty);
- }
- catch
- {
- return 0;
- }
- }
-
- public static bool ToBool(object obj)
- {
- try
- {
- return Convert.ToBoolean(obj);
- }
- catch
- {
- return false;
- }
- }
-
- public static string ToString(object? obj)
- {
- try
- {
- return obj?.ToString() ?? string.Empty;
- }
- catch
- {
- return string.Empty;
- }
- }
-
- private static void ToHumanReadable(long amount, out double result, out string unit)
- {
- var factor = 1024u;
- //long KBs = amount / factor;
- var KBs = amount;
- if (KBs > 0)
- {
- // multi KB
- var MBs = KBs / factor;
- if (MBs > 0)
- {
- // multi MB
- var GBs = MBs / factor;
- if (GBs > 0)
- {
- // multi GB
- var TBs = GBs / factor;
- if (TBs > 0)
- {
- result = TBs + ((GBs % factor) / (factor + 0.0));
- unit = "TB";
- return;
- }
-
- result = GBs + ((MBs % factor) / (factor + 0.0));
- unit = "GB";
- return;
- }
-
- result = MBs + ((KBs % factor) / (factor + 0.0));
- unit = "MB";
- return;
- }
-
- result = KBs + ((amount % factor) / (factor + 0.0));
- unit = "KB";
- return;
- }
- else
- {
- result = amount;
- unit = "B";
- }
- }
-
- public static string HumanFy(long amount)
- {
- ToHumanReadable(amount, out var result, out var unit);
- return $"{result:f1} {unit}";
- }
-
- public static string UrlEncode(string url)
- {
- return Uri.EscapeDataString(url);
- }
-
- public static string UrlDecode(string url)
- {
- return Uri.UnescapeDataString(url);
- }
-
- public static NameValueCollection ParseQueryString(string query)
- {
- var result = new NameValueCollection(StringComparer.OrdinalIgnoreCase);
- if (IsNullOrEmpty(query))
- {
- return result;
- }
-
- var parts = query[1..].Split('&', StringSplitOptions.RemoveEmptyEntries);
- foreach (var part in parts)
- {
- var keyValue = part.Split('=');
- if (keyValue.Length != 2)
- {
- continue;
- }
-
- var key = Uri.UnescapeDataString(keyValue.First());
- var val = Uri.UnescapeDataString(keyValue.Last());
-
- if (result[key] is null)
- {
- result.Add(key, val);
- }
- }
-
- return result;
- }
-
- public static string GetMd5(string str)
- {
- var byteOld = Encoding.UTF8.GetBytes(str);
- var byteNew = MD5.HashData(byteOld);
- StringBuilder sb = new(32);
- foreach (var b in byteNew)
- {
- sb.Append(b.ToString("x2"));
- }
-
- return sb.ToString();
- }
-
- ///
- /// idn to idc
- ///
- ///
- ///
- public static string GetPunycode(string url)
- {
- if (Utils.IsNullOrEmpty(url))
- {
- return url;
- }
-
- try
- {
- Uri uri = new(url);
- if (uri.Host == uri.IdnHost || uri.Host == $"[{uri.IdnHost}]")
- {
- return url;
- }
- else
- {
- return url.Replace(uri.Host, uri.IdnHost);
- }
- }
- catch
- {
- return url;
- }
- }
-
- public static bool IsBase64String(string? plainText)
- {
- if (plainText.IsNullOrEmpty()) return false;
- var buffer = new Span(new byte[plainText.Length]);
- return Convert.TryFromBase64String(plainText, buffer, out var _);
- }
-
- public static string Convert2Comma(string text)
- {
- if (IsNullOrEmpty(text))
- {
- return text;
- }
-
- return text.Replace(",", ",").Replace(Environment.NewLine, ",");
- }
-
- #endregion 转换函数
-
- #region 数据检查
-
- ///
- /// 判断输入的是否是数字
- ///
- ///
- ///
- public static bool IsNumeric(string oText)
- {
- return oText.All(char.IsNumber);
- }
-
- public static bool IsNullOrEmpty(string? text)
- {
- if (string.IsNullOrWhiteSpace(text))
- {
- return true;
- }
-
- return text == "null";
- }
-
- public static bool IsNotEmpty(string? text)
- {
- return !string.IsNullOrEmpty(text);
- }
-
- ///
- /// 验证Domain地址是否合法
- ///
- ///
- public static bool IsDomain(string? domain)
- {
- if (IsNullOrEmpty(domain))
- {
- return false;
- }
-
- return Uri.CheckHostName(domain) == UriHostNameType.Dns;
- }
-
- public static bool IsIpv6(string ip)
- {
- if (IPAddress.TryParse(ip, out var address))
- {
- return address.AddressFamily switch
- {
- AddressFamily.InterNetwork => false,
- AddressFamily.InterNetworkV6 => true,
- _ => false,
- };
- }
-
- return false;
- }
-
- public static Uri? TryUri(string url)
- {
- try
- {
- return new Uri(url);
- }
- catch (UriFormatException)
- {
- return null;
- }
- }
-
- public static bool IsPrivateNetwork(string ip)
- {
- if (IPAddress.TryParse(ip, out var address))
- {
- var ipBytes = address.GetAddressBytes();
- if (ipBytes[0] == 10) return true;
- if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31) return true;
- if (ipBytes[0] == 192 && ipBytes[1] == 168) return true;
- }
-
- return false;
- }
-
- #endregion 数据检查
-
- #region 测速
-
- private static bool PortInUse(int port)
- {
- try
- {
- var ipProperties = IPGlobalProperties.GetIPGlobalProperties();
- var ipEndPoints = ipProperties.GetActiveTcpListeners();
- //var lstIpEndPoints = new List(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners());
- return ipEndPoints.Any(endPoint => endPoint.Port == port);
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
-
- return false;
- }
-
- public static int GetFreePort(int defaultPort = 9090)
- {
- try
- {
- if (!Utils.PortInUse(defaultPort))
- {
- return defaultPort;
- }
-
- TcpListener l = new(IPAddress.Loopback, 0);
- l.Start();
- var port = ((IPEndPoint)l.LocalEndpoint).Port;
- l.Stop();
- return port;
- }
- catch
- {
- }
-
- return 59090;
- }
-
- #endregion 测速
-
- #region 杂项
-
- public static bool UpgradeAppExists(out string upgradeFileName)
- {
- upgradeFileName = Path.Combine(GetBaseDirectory(), GetExeName("AmazTool"));
- return File.Exists(upgradeFileName);
- }
-
- ///
- /// 取得版本
- ///
- ///
- public static string GetVersion(bool blFull = true)
- {
- try
- {
- return blFull
- ? $"{Global.AppName} - V{GetVersionInfo()} - {RuntimeInformation.ProcessArchitecture}"
- : $"{Global.AppName}/{GetVersionInfo()}";
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
-
- return Global.AppName;
- }
-
- public static string GetVersionInfo()
- {
- try
- {
- return Assembly.GetExecutingAssembly()?.GetName()?.Version?.ToString(3) ?? "0.0";
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- return "0.0";
- }
- }
-
- public static string GetRuntimeInfo()
- {
- return $"{Utils.GetVersion()} | {Utils.StartupPath()} | {Utils.GetExePath()} | {Environment.OSVersion}";
- }
-
- ///
- /// 取得GUID
- ///
- ///
- public static string GetGuid(bool full = true)
- {
- try
- {
- if (full)
- {
- return Guid.NewGuid().ToString("D");
- }
- else
- {
- return BitConverter.ToInt64(Guid.NewGuid().ToByteArray(), 0).ToString();
- }
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
-
- return string.Empty;
- }
-
- public static bool IsGuidByParse(string strSrc)
- {
- return Guid.TryParse(strSrc, out _);
- }
-
- public static Dictionary GetSystemHosts()
- {
- var systemHosts = new Dictionary();
- var hostFile = @"C:\Windows\System32\drivers\etc\hosts";
- try
- {
- if (File.Exists(hostFile))
- {
- var hosts = File.ReadAllText(hostFile).Replace("\r", "");
- var hostsList = hosts.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
-
- foreach (var host in hostsList)
- {
- if (host.StartsWith("#")) continue;
- var hostItem = host.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
- if (hostItem.Length != 2) continue;
- systemHosts.Add(hostItem.Last(), hostItem.First());
- }
- }
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
-
- return systemHosts;
- }
-
- public static async Task GetCliWrapOutput(string filePath, string? arg)
- {
- return await GetCliWrapOutput(filePath, arg != null ? new List() { arg } : null);
- }
-
- public static async Task GetCliWrapOutput(string filePath, IEnumerable? args)
- {
- try
- {
- var cmd = Cli.Wrap(filePath);
- if (args != null)
- {
- if (args.Count() == 1)
- {
- cmd = cmd.WithArguments(args.First());
- }
- else
- {
- cmd = cmd.WithArguments(args);
- }
- }
-
- var result = await cmd.ExecuteBufferedAsync();
- if (result.IsSuccess)
- {
- return result.StandardOutput.ToString();
- }
-
- Logging.SaveLog(result.ToString() ?? "");
- }
- catch (Exception ex)
- {
- Logging.SaveLog("GetCliWrapOutput", ex);
- }
-
- return null;
- }
-
- #endregion 杂项
-
- #region TempPath
-
- public static bool HasWritePermission()
- {
- try
- {
- //When this file exists, it is equivalent to having no permission to read and write
- if (File.Exists(Path.Combine(GetBaseDirectory(), "NotStoreConfigHere.txt")))
- {
- return false;
- }
-
- var tempPath = Path.Combine(GetBaseDirectory(), "guiTemps");
- if (!Directory.Exists(tempPath))
- {
- Directory.CreateDirectory(tempPath);
- }
- var fileName = Path.Combine(tempPath, GetGuid());
- File.Create(fileName).Close();
- File.Delete(fileName);
- }
- catch (Exception)
- {
- return false;
- }
-
- return true;
- }
-
- public static string GetPath(string fileName)
- {
- var startupPath = StartupPath();
- if (IsNullOrEmpty(fileName))
- {
- return startupPath;
- }
-
- return Path.Combine(startupPath, fileName);
- }
-
- public static string GetBaseDirectory(string fileName = "")
- {
- return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
- }
-
- public static string GetExePath()
- {
- return Environment.ProcessPath ?? Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty;
- }
-
- public static string StartupPath()
- {
- if (Environment.GetEnvironmentVariable(Global.LocalAppData) == "1")
- {
- return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "v2rayN");
- }
-
- return GetBaseDirectory();
- }
-
- public static string GetTempPath(string filename = "")
- {
- var tempPath = Path.Combine(StartupPath(), "guiTemps");
- if (!Directory.Exists(tempPath))
- {
- Directory.CreateDirectory(tempPath);
- }
-
- if (IsNullOrEmpty(filename))
- {
- return tempPath;
- }
- else
- {
- return Path.Combine(tempPath, filename);
- }
- }
-
- public static string GetBackupPath(string filename)
- {
- var tempPath = Path.Combine(StartupPath(), "guiBackups");
- if (!Directory.Exists(tempPath))
- {
- Directory.CreateDirectory(tempPath);
- }
-
- return Path.Combine(tempPath, filename);
- }
-
- public static string GetConfigPath(string filename = "")
- {
- var tempPath = Path.Combine(StartupPath(), "guiConfigs");
- if (!Directory.Exists(tempPath))
- {
- Directory.CreateDirectory(tempPath);
- }
-
- if (Utils.IsNullOrEmpty(filename))
- {
- return tempPath;
- }
- else
- {
- return Path.Combine(tempPath, filename);
- }
- }
-
- public static string GetBinPath(string filename, string? coreType = null)
- {
- var tempPath = Path.Combine(StartupPath(), "bin");
- if (!Directory.Exists(tempPath))
- {
- Directory.CreateDirectory(tempPath);
- }
-
- if (coreType != null)
- {
- tempPath = Path.Combine(tempPath, coreType.ToLower().ToString());
- if (!Directory.Exists(tempPath))
- {
- Directory.CreateDirectory(tempPath);
- }
- }
-
- if (IsNullOrEmpty(filename))
- {
- return tempPath;
- }
- else
- {
- return Path.Combine(tempPath, filename);
- }
- }
-
- public static string GetLogPath(string filename = "")
- {
- var tempPath = Path.Combine(StartupPath(), "guiLogs");
- if (!Directory.Exists(tempPath))
- {
- Directory.CreateDirectory(tempPath);
- }
-
- if (Utils.IsNullOrEmpty(filename))
- {
- return tempPath;
- }
- else
- {
- return Path.Combine(tempPath, filename);
- }
- }
-
- public static string GetFontsPath(string filename = "")
- {
- var tempPath = Path.Combine(StartupPath(), "guiFonts");
- if (!Directory.Exists(tempPath))
- {
- Directory.CreateDirectory(tempPath);
- }
-
- if (Utils.IsNullOrEmpty(filename))
- {
- return tempPath;
- }
- else
- {
- return Path.Combine(tempPath, filename);
- }
- }
-
- #endregion TempPath
-
- #region Platform
-
- public static bool IsWindows() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
-
- public static bool IsLinux() => RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
-
- public static bool IsOSX() => RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
-
- public static bool IsNonWindows() => !RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
-
- public static string GetExeName(string name)
- {
- return IsWindows() ? $"{name}.exe" : name;
- }
-
- public static bool IsAdministrator()
- {
- if (IsWindows())
- {
- return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
- }
- return false;
- //else
- //{
- // var id = GetLinuxUserId().Result ?? "1000";
- // if (int.TryParse(id, out var userId))
- // {
- // return userId == 0;
- // }
- // else
- // {
- // return false;
- // }
- //}
- }
-
- private static async Task GetLinuxUserId()
- {
- var arg = new List() { "-c", "id -u" };
- return await GetCliWrapOutput("/bin/bash", arg);
- }
-
- public static async Task SetLinuxChmod(string? fileName)
- {
- if (fileName.IsNullOrEmpty()) return null;
- if (fileName.Contains(' ')) fileName = fileName.AppendQuotes();
- //File.SetUnixFileMode(fileName, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute);
- var arg = new List() { "-c", $"chmod +x {fileName}" };
- return await GetCliWrapOutput("/bin/bash", arg);
- }
-
- public static async Task GetLinuxFontFamily(string lang)
- {
- // var arg = new List() { "-c", $"fc-list :lang={lang} family" };
- var arg = new List() { "-c", $"fc-list : family" };
- return await GetCliWrapOutput("/bin/bash", arg);
- }
-
- public static string? GetHomePath()
- {
- return IsWindows()
- ? Environment.ExpandEnvironmentVariables("%HOMEDRIVE%%HOMEPATH%")
- : Environment.GetEnvironmentVariable("HOME");
- }
-
- public static async Task GetListNetworkServices()
- {
- var arg = new List() { "-c", $"networksetup -listallnetworkservices" };
- return await GetCliWrapOutput("/bin/bash", arg);
- }
-
- #endregion Platform
- }
-}
\ No newline at end of file
+ public class Utils
+ {
+ private static readonly string _tag = "Utils";
+
+ #region 资源操作
+
+ ///
+ /// 获取嵌入文本资源
+ ///
+ ///
+ ///
+ public static string GetEmbedText(string res)
+ {
+ var result = string.Empty;
+
+ try
+ {
+ var assembly = Assembly.GetExecutingAssembly();
+ using var stream = assembly.GetManifestResourceStream(res);
+ ArgumentNullException.ThrowIfNull(stream);
+ using StreamReader reader = new(stream);
+ result = reader.ReadToEnd();
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+
+ return result;
+ }
+
+ ///
+ /// 取得存储资源
+ ///
+ ///
+ public static string? LoadResource(string? res)
+ {
+ try
+ {
+ if (File.Exists(res))
+ {
+ return File.ReadAllText(res);
+ }
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+
+ return null;
+ }
+
+ #endregion 资源操作
+
+ #region 转换函数
+
+ ///
+ /// 转逗号分隔的字符串
+ ///
+ ///
+ ///
+ ///
+ public static string List2String(List? lst, bool wrap = false)
+ {
+ try
+ {
+ if (lst == null)
+ {
+ return string.Empty;
+ }
+ if (wrap)
+ {
+ return string.Join("," + Environment.NewLine, lst);
+ }
+ else
+ {
+ return string.Join(",", lst);
+ }
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+
+ return string.Empty;
+ }
+
+ ///
+ /// 逗号分隔的字符串
+ ///
+ ///
+ ///
+ public static List? String2List(string? str)
+ {
+ try
+ {
+ if (str == null)
+ {
+ return null;
+ }
+
+ str = str.Replace(Environment.NewLine, "");
+ return new List(str.Split(',', StringSplitOptions.RemoveEmptyEntries));
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+
+ return null;
+ }
+
+ ///
+ /// 逗号分隔的字符串,先排序后转List
+ ///
+ ///
+ ///
+ public static List? String2ListSorted(string str)
+ {
+ try
+ {
+ str = str.Replace(Environment.NewLine, "");
+ List list = new(str.Split(',', StringSplitOptions.RemoveEmptyEntries));
+ list.Sort();
+ return list;
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+
+ return null;
+ }
+
+ ///
+ /// Base64编码
+ ///
+ ///
+ ///
+ public static string Base64Encode(string plainText)
+ {
+ try
+ {
+ var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
+ return Convert.ToBase64String(plainTextBytes);
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+
+ return string.Empty;
+ }
+
+ ///
+ /// Base64解码
+ ///
+ ///
+ ///
+ public static string Base64Decode(string? plainText)
+ {
+ try
+ {
+ if (plainText.IsNullOrEmpty())
+ return "";
+ plainText = plainText.Trim()
+ .Replace(Environment.NewLine, "")
+ .Replace("\n", "")
+ .Replace("\r", "")
+ .Replace('_', '/')
+ .Replace('-', '+')
+ .Replace(" ", "");
+
+ if (plainText.Length % 4 > 0)
+ {
+ plainText = plainText.PadRight(plainText.Length + 4 - (plainText.Length % 4), '=');
+ }
+
+ var data = Convert.FromBase64String(plainText);
+ return Encoding.UTF8.GetString(data);
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+
+ return string.Empty;
+ }
+
+ public static int ToInt(object? obj)
+ {
+ try
+ {
+ return Convert.ToInt32(obj ?? string.Empty);
+ }
+ catch
+ {
+ return 0;
+ }
+ }
+
+ public static bool ToBool(object obj)
+ {
+ try
+ {
+ return Convert.ToBoolean(obj);
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ public static string ToString(object? obj)
+ {
+ try
+ {
+ return obj?.ToString() ?? string.Empty;
+ }
+ catch
+ {
+ return string.Empty;
+ }
+ }
+
+ private static void ToHumanReadable(long amount, out double result, out string unit)
+ {
+ var factor = 1024u;
+ //long KBs = amount / factor;
+ var KBs = amount;
+ if (KBs > 0)
+ {
+ // multi KB
+ var MBs = KBs / factor;
+ if (MBs > 0)
+ {
+ // multi MB
+ var GBs = MBs / factor;
+ if (GBs > 0)
+ {
+ // multi GB
+ var TBs = GBs / factor;
+ if (TBs > 0)
+ {
+ result = TBs + (GBs % factor / (factor + 0.0));
+ unit = "TB";
+ return;
+ }
+
+ result = GBs + (MBs % factor / (factor + 0.0));
+ unit = "GB";
+ return;
+ }
+
+ result = MBs + (KBs % factor / (factor + 0.0));
+ unit = "MB";
+ return;
+ }
+
+ result = KBs + (amount % factor / (factor + 0.0));
+ unit = "KB";
+ return;
+ }
+ else
+ {
+ result = amount;
+ unit = "B";
+ }
+ }
+
+ public static string HumanFy(long amount)
+ {
+ ToHumanReadable(amount, out var result, out var unit);
+ return $"{result:f1} {unit}";
+ }
+
+ public static string UrlEncode(string url)
+ {
+ return Uri.EscapeDataString(url);
+ }
+
+ public static string UrlDecode(string url)
+ {
+ return Uri.UnescapeDataString(url);
+ }
+
+ public static NameValueCollection ParseQueryString(string query)
+ {
+ var result = new NameValueCollection(StringComparer.OrdinalIgnoreCase);
+ if (IsNullOrEmpty(query))
+ {
+ return result;
+ }
+
+ var parts = query[1..].Split('&', StringSplitOptions.RemoveEmptyEntries);
+ foreach (var part in parts)
+ {
+ var keyValue = part.Split('=');
+ if (keyValue.Length != 2)
+ {
+ continue;
+ }
+
+ var key = Uri.UnescapeDataString(keyValue.First());
+ var val = Uri.UnescapeDataString(keyValue.Last());
+
+ if (result[key] is null)
+ {
+ result.Add(key, val);
+ }
+ }
+
+ return result;
+ }
+
+ public static string GetMd5(string str)
+ {
+ var byteOld = Encoding.UTF8.GetBytes(str);
+ var byteNew = MD5.HashData(byteOld);
+ StringBuilder sb = new(32);
+ foreach (var b in byteNew)
+ {
+ sb.Append(b.ToString("x2"));
+ }
+
+ return sb.ToString();
+ }
+
+ ///
+ /// idn to idc
+ ///
+ ///
+ ///
+ public static string GetPunycode(string url)
+ {
+ if (Utils.IsNullOrEmpty(url))
+ {
+ return url;
+ }
+
+ try
+ {
+ Uri uri = new(url);
+ if (uri.Host == uri.IdnHost || uri.Host == $"[{uri.IdnHost}]")
+ {
+ return url;
+ }
+ else
+ {
+ return url.Replace(uri.Host, uri.IdnHost);
+ }
+ }
+ catch
+ {
+ return url;
+ }
+ }
+
+ public static bool IsBase64String(string? plainText)
+ {
+ if (plainText.IsNullOrEmpty())
+ return false;
+ var buffer = new Span(new byte[plainText.Length]);
+ return Convert.TryFromBase64String(plainText, buffer, out var _);
+ }
+
+ public static string Convert2Comma(string text)
+ {
+ if (IsNullOrEmpty(text))
+ {
+ return text;
+ }
+
+ return text.Replace(",", ",").Replace(Environment.NewLine, ",");
+ }
+
+ #endregion 转换函数
+
+ #region 数据检查
+
+ ///
+ /// 判断输入的是否是数字
+ ///
+ ///
+ ///
+ public static bool IsNumeric(string oText)
+ {
+ return oText.All(char.IsNumber);
+ }
+
+ public static bool IsNullOrEmpty(string? text)
+ {
+ if (string.IsNullOrWhiteSpace(text))
+ {
+ return true;
+ }
+
+ return text == "null";
+ }
+
+ public static bool IsNotEmpty(string? text)
+ {
+ return !string.IsNullOrEmpty(text);
+ }
+
+ ///
+ /// 验证Domain地址是否合法
+ ///
+ ///
+ public static bool IsDomain(string? domain)
+ {
+ if (IsNullOrEmpty(domain))
+ {
+ return false;
+ }
+
+ return Uri.CheckHostName(domain) == UriHostNameType.Dns;
+ }
+
+ public static bool IsIpv6(string ip)
+ {
+ if (IPAddress.TryParse(ip, out var address))
+ {
+ return address.AddressFamily switch
+ {
+ AddressFamily.InterNetwork => false,
+ AddressFamily.InterNetworkV6 => true,
+ _ => false,
+ };
+ }
+
+ return false;
+ }
+
+ public static Uri? TryUri(string url)
+ {
+ try
+ {
+ return new Uri(url);
+ }
+ catch (UriFormatException)
+ {
+ return null;
+ }
+ }
+
+ public static bool IsPrivateNetwork(string ip)
+ {
+ if (IPAddress.TryParse(ip, out var address))
+ {
+ var ipBytes = address.GetAddressBytes();
+ if (ipBytes[0] == 10)
+ return true;
+ if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31)
+ return true;
+ if (ipBytes[0] == 192 && ipBytes[1] == 168)
+ return true;
+ }
+
+ return false;
+ }
+
+ #endregion 数据检查
+
+ #region 测速
+
+ private static bool PortInUse(int port)
+ {
+ try
+ {
+ var ipProperties = IPGlobalProperties.GetIPGlobalProperties();
+ var ipEndPoints = ipProperties.GetActiveTcpListeners();
+ //var lstIpEndPoints = new List(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners());
+ return ipEndPoints.Any(endPoint => endPoint.Port == port);
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+
+ return false;
+ }
+
+ public static int GetFreePort(int defaultPort = 9090)
+ {
+ try
+ {
+ if (!Utils.PortInUse(defaultPort))
+ {
+ return defaultPort;
+ }
+
+ TcpListener l = new(IPAddress.Loopback, 0);
+ l.Start();
+ var port = ((IPEndPoint)l.LocalEndpoint).Port;
+ l.Stop();
+ return port;
+ }
+ catch
+ {
+ }
+
+ return 59090;
+ }
+
+ #endregion 测速
+
+ #region 杂项
+
+ public static bool UpgradeAppExists(out string upgradeFileName)
+ {
+ upgradeFileName = Path.Combine(GetBaseDirectory(), GetExeName("AmazTool"));
+ return File.Exists(upgradeFileName);
+ }
+
+ ///
+ /// 取得版本
+ ///
+ ///
+ public static string GetVersion(bool blFull = true)
+ {
+ try
+ {
+ return blFull
+ ? $"{Global.AppName} - V{GetVersionInfo()} - {RuntimeInformation.ProcessArchitecture}"
+ : $"{Global.AppName}/{GetVersionInfo()}";
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+
+ return Global.AppName;
+ }
+
+ public static string GetVersionInfo()
+ {
+ try
+ {
+ return Assembly.GetExecutingAssembly()?.GetName()?.Version?.ToString(3) ?? "0.0";
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ return "0.0";
+ }
+ }
+
+ public static string GetRuntimeInfo()
+ {
+ return $"{Utils.GetVersion()} | {Utils.StartupPath()} | {Utils.GetExePath()} | {Environment.OSVersion}";
+ }
+
+ ///
+ /// 取得GUID
+ ///
+ ///
+ public static string GetGuid(bool full = true)
+ {
+ try
+ {
+ if (full)
+ {
+ return Guid.NewGuid().ToString("D");
+ }
+ else
+ {
+ return BitConverter.ToInt64(Guid.NewGuid().ToByteArray(), 0).ToString();
+ }
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+
+ return string.Empty;
+ }
+
+ public static bool IsGuidByParse(string strSrc)
+ {
+ return Guid.TryParse(strSrc, out _);
+ }
+
+ public static Dictionary GetSystemHosts()
+ {
+ var systemHosts = new Dictionary();
+ var hostFile = @"C:\Windows\System32\drivers\etc\hosts";
+ try
+ {
+ if (File.Exists(hostFile))
+ {
+ var hosts = File.ReadAllText(hostFile).Replace("\r", "");
+ var hostsList = hosts.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
+
+ foreach (var host in hostsList)
+ {
+ if (host.StartsWith("#"))
+ continue;
+ var hostItem = host.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
+ if (hostItem.Length != 2)
+ continue;
+ systemHosts.Add(hostItem.Last(), hostItem.First());
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+
+ return systemHosts;
+ }
+
+ public static async Task GetCliWrapOutput(string filePath, string? arg)
+ {
+ return await GetCliWrapOutput(filePath, arg != null ? new List() { arg } : null);
+ }
+
+ public static async Task GetCliWrapOutput(string filePath, IEnumerable? args)
+ {
+ try
+ {
+ var cmd = Cli.Wrap(filePath);
+ if (args != null)
+ {
+ if (args.Count() == 1)
+ {
+ cmd = cmd.WithArguments(args.First());
+ }
+ else
+ {
+ cmd = cmd.WithArguments(args);
+ }
+ }
+
+ var result = await cmd.ExecuteBufferedAsync();
+ if (result.IsSuccess)
+ {
+ return result.StandardOutput.ToString();
+ }
+
+ Logging.SaveLog(result.ToString() ?? "");
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog("GetCliWrapOutput", ex);
+ }
+
+ return null;
+ }
+
+ #endregion 杂项
+
+ #region TempPath
+
+ public static bool HasWritePermission()
+ {
+ try
+ {
+ //When this file exists, it is equivalent to having no permission to read and write
+ if (File.Exists(Path.Combine(GetBaseDirectory(), "NotStoreConfigHere.txt")))
+ {
+ return false;
+ }
+
+ var tempPath = Path.Combine(GetBaseDirectory(), "guiTemps");
+ if (!Directory.Exists(tempPath))
+ {
+ Directory.CreateDirectory(tempPath);
+ }
+ var fileName = Path.Combine(tempPath, GetGuid());
+ File.Create(fileName).Close();
+ File.Delete(fileName);
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ public static string GetPath(string fileName)
+ {
+ var startupPath = StartupPath();
+ if (IsNullOrEmpty(fileName))
+ {
+ return startupPath;
+ }
+
+ return Path.Combine(startupPath, fileName);
+ }
+
+ public static string GetBaseDirectory(string fileName = "")
+ {
+ return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
+ }
+
+ public static string GetExePath()
+ {
+ return Environment.ProcessPath ?? Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty;
+ }
+
+ public static string StartupPath()
+ {
+ if (Environment.GetEnvironmentVariable(Global.LocalAppData) == "1")
+ {
+ return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "v2rayN");
+ }
+
+ return GetBaseDirectory();
+ }
+
+ public static string GetTempPath(string filename = "")
+ {
+ var tempPath = Path.Combine(StartupPath(), "guiTemps");
+ if (!Directory.Exists(tempPath))
+ {
+ Directory.CreateDirectory(tempPath);
+ }
+
+ if (IsNullOrEmpty(filename))
+ {
+ return tempPath;
+ }
+ else
+ {
+ return Path.Combine(tempPath, filename);
+ }
+ }
+
+ public static string GetBackupPath(string filename)
+ {
+ var tempPath = Path.Combine(StartupPath(), "guiBackups");
+ if (!Directory.Exists(tempPath))
+ {
+ Directory.CreateDirectory(tempPath);
+ }
+
+ return Path.Combine(tempPath, filename);
+ }
+
+ public static string GetConfigPath(string filename = "")
+ {
+ var tempPath = Path.Combine(StartupPath(), "guiConfigs");
+ if (!Directory.Exists(tempPath))
+ {
+ Directory.CreateDirectory(tempPath);
+ }
+
+ if (Utils.IsNullOrEmpty(filename))
+ {
+ return tempPath;
+ }
+ else
+ {
+ return Path.Combine(tempPath, filename);
+ }
+ }
+
+ public static string GetBinPath(string filename, string? coreType = null)
+ {
+ var tempPath = Path.Combine(StartupPath(), "bin");
+ if (!Directory.Exists(tempPath))
+ {
+ Directory.CreateDirectory(tempPath);
+ }
+
+ if (coreType != null)
+ {
+ tempPath = Path.Combine(tempPath, coreType.ToLower().ToString());
+ if (!Directory.Exists(tempPath))
+ {
+ Directory.CreateDirectory(tempPath);
+ }
+ }
+
+ if (IsNullOrEmpty(filename))
+ {
+ return tempPath;
+ }
+ else
+ {
+ return Path.Combine(tempPath, filename);
+ }
+ }
+
+ public static string GetLogPath(string filename = "")
+ {
+ var tempPath = Path.Combine(StartupPath(), "guiLogs");
+ if (!Directory.Exists(tempPath))
+ {
+ Directory.CreateDirectory(tempPath);
+ }
+
+ if (Utils.IsNullOrEmpty(filename))
+ {
+ return tempPath;
+ }
+ else
+ {
+ return Path.Combine(tempPath, filename);
+ }
+ }
+
+ public static string GetFontsPath(string filename = "")
+ {
+ var tempPath = Path.Combine(StartupPath(), "guiFonts");
+ if (!Directory.Exists(tempPath))
+ {
+ Directory.CreateDirectory(tempPath);
+ }
+
+ if (Utils.IsNullOrEmpty(filename))
+ {
+ return tempPath;
+ }
+ else
+ {
+ return Path.Combine(tempPath, filename);
+ }
+ }
+
+ #endregion TempPath
+
+ #region Platform
+
+ public static bool IsWindows() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+
+ public static bool IsLinux() => RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
+
+ public static bool IsOSX() => RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
+
+ public static bool IsNonWindows() => !RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+
+ public static string GetExeName(string name)
+ {
+ return IsWindows() ? $"{name}.exe" : name;
+ }
+
+ public static bool IsAdministrator()
+ {
+ if (IsWindows())
+ {
+ return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
+ }
+ return false;
+ //else
+ //{
+ // var id = GetLinuxUserId().Result ?? "1000";
+ // if (int.TryParse(id, out var userId))
+ // {
+ // return userId == 0;
+ // }
+ // else
+ // {
+ // return false;
+ // }
+ //}
+ }
+
+ private static async Task GetLinuxUserId()
+ {
+ var arg = new List() { "-c", "id -u" };
+ return await GetCliWrapOutput("/bin/bash", arg);
+ }
+
+ public static async Task SetLinuxChmod(string? fileName)
+ {
+ if (fileName.IsNullOrEmpty())
+ return null;
+ if (fileName.Contains(' '))
+ fileName = fileName.AppendQuotes();
+ //File.SetUnixFileMode(fileName, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute);
+ var arg = new List() { "-c", $"chmod +x {fileName}" };
+ return await GetCliWrapOutput("/bin/bash", arg);
+ }
+
+ public static async Task GetLinuxFontFamily(string lang)
+ {
+ // var arg = new List() { "-c", $"fc-list :lang={lang} family" };
+ var arg = new List() { "-c", $"fc-list : family" };
+ return await GetCliWrapOutput("/bin/bash", arg);
+ }
+
+ public static string? GetHomePath()
+ {
+ return IsWindows()
+ ? Environment.ExpandEnvironmentVariables("%HOMEDRIVE%%HOMEPATH%")
+ : Environment.GetEnvironmentVariable("HOME");
+ }
+
+ public static async Task GetListNetworkServices()
+ {
+ var arg = new List() { "-c", $"networksetup -listallnetworkservices" };
+ return await GetCliWrapOutput("/bin/bash", arg);
+ }
+
+ #endregion Platform
+ }
+}
diff --git a/v2rayN/ServiceLib/Common/WindowsUtils.cs b/v2rayN/ServiceLib/Common/WindowsUtils.cs
index 83e2ee57..aa7836ad 100644
--- a/v2rayN/ServiceLib/Common/WindowsUtils.cs
+++ b/v2rayN/ServiceLib/Common/WindowsUtils.cs
@@ -1,54 +1,54 @@
-using Microsoft.Win32;
+using Microsoft.Win32;
namespace ServiceLib.Common
{
- internal static class WindowsUtils
- {
- private static readonly string _tag = "WindowsUtils";
+ internal static class WindowsUtils
+ {
+ private static readonly string _tag = "WindowsUtils";
- public static string? RegReadValue(string path, string name, string def)
- {
- RegistryKey? regKey = null;
- try
- {
- regKey = Registry.CurrentUser.OpenSubKey(path, false);
- var value = regKey?.GetValue(name) as string;
- return Utils.IsNullOrEmpty(value) ? def : value;
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
- finally
- {
- regKey?.Close();
- }
- return def;
- }
+ public static string? RegReadValue(string path, string name, string def)
+ {
+ RegistryKey? regKey = null;
+ try
+ {
+ regKey = Registry.CurrentUser.OpenSubKey(path, false);
+ var value = regKey?.GetValue(name) as string;
+ return Utils.IsNullOrEmpty(value) ? def : value;
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+ finally
+ {
+ regKey?.Close();
+ }
+ return def;
+ }
- public static void RegWriteValue(string path, string name, object value)
- {
- RegistryKey? regKey = null;
- try
- {
- regKey = Registry.CurrentUser.CreateSubKey(path);
- if (Utils.IsNullOrEmpty(value.ToString()))
- {
- regKey?.DeleteValue(name, false);
- }
- else
- {
- regKey?.SetValue(name, value);
- }
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
- finally
- {
- regKey?.Close();
- }
- }
- }
-}
\ No newline at end of file
+ public static void RegWriteValue(string path, string name, object value)
+ {
+ RegistryKey? regKey = null;
+ try
+ {
+ regKey = Registry.CurrentUser.CreateSubKey(path);
+ if (Utils.IsNullOrEmpty(value.ToString()))
+ {
+ regKey?.DeleteValue(name, false);
+ }
+ else
+ {
+ regKey?.SetValue(name, value);
+ }
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+ finally
+ {
+ regKey?.Close();
+ }
+ }
+ }
+}
diff --git a/v2rayN/ServiceLib/Common/YamlUtils.cs b/v2rayN/ServiceLib/Common/YamlUtils.cs
index 13ad2d78..8b7f7bea 100644
--- a/v2rayN/ServiceLib/Common/YamlUtils.cs
+++ b/v2rayN/ServiceLib/Common/YamlUtils.cs
@@ -1,83 +1,83 @@
-using YamlDotNet.Core;
+using YamlDotNet.Core;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
namespace ServiceLib.Common
{
- public class YamlUtils
- {
- private static readonly string _tag = "YamlUtils";
+ public class YamlUtils
+ {
+ private static readonly string _tag = "YamlUtils";
- #region YAML
+ #region YAML
- ///
- /// 反序列化成对象
- ///
- ///
- ///
- ///
- public static T FromYaml(string str)
- {
- var deserializer = new DeserializerBuilder()
- .WithNamingConvention(PascalCaseNamingConvention.Instance)
- .Build();
- try
- {
- var obj = deserializer.Deserialize(str);
- return obj;
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- return deserializer.Deserialize("");
- }
- }
+ ///
+ /// 反序列化成对象
+ ///
+ ///
+ ///
+ ///
+ public static T FromYaml(string str)
+ {
+ var deserializer = new DeserializerBuilder()
+ .WithNamingConvention(PascalCaseNamingConvention.Instance)
+ .Build();
+ try
+ {
+ var obj = deserializer.Deserialize(str);
+ return obj;
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ return deserializer.Deserialize("");
+ }
+ }
- ///
- /// 序列化
- ///
- ///
- ///
- public static string ToYaml(object? obj)
- {
- var result = string.Empty;
- if (obj == null)
- {
- return result;
- }
- var serializer = new SerializerBuilder()
- .WithNamingConvention(HyphenatedNamingConvention.Instance)
- .Build();
+ ///
+ /// 序列化
+ ///
+ ///
+ ///
+ public static string ToYaml(object? obj)
+ {
+ var result = string.Empty;
+ if (obj == null)
+ {
+ return result;
+ }
+ var serializer = new SerializerBuilder()
+ .WithNamingConvention(HyphenatedNamingConvention.Instance)
+ .Build();
- try
- {
- result = serializer.Serialize(obj);
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
- return result;
- }
+ try
+ {
+ result = serializer.Serialize(obj);
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+ return result;
+ }
- public static string? PreprocessYaml(string str)
- {
- var deserializer = new DeserializerBuilder()
- .WithNamingConvention(PascalCaseNamingConvention.Instance)
- .Build();
- try
- {
- var mergingParser = new MergingParser(new Parser(new StringReader(str)));
- var obj = new DeserializerBuilder().Build().Deserialize(mergingParser);
- return ToYaml(obj);
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- return null;
- }
- }
+ public static string? PreprocessYaml(string str)
+ {
+ var deserializer = new DeserializerBuilder()
+ .WithNamingConvention(PascalCaseNamingConvention.Instance)
+ .Build();
+ try
+ {
+ var mergingParser = new MergingParser(new Parser(new StringReader(str)));
+ var obj = new DeserializerBuilder().Build().Deserialize(mergingParser);
+ return ToYaml(obj);
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ return null;
+ }
+ }
- #endregion YAML
- }
-}
\ No newline at end of file
+ #endregion YAML
+ }
+}
diff --git a/v2rayN/ServiceLib/Enums/EConfigType.cs b/v2rayN/ServiceLib/Enums/EConfigType.cs
index 5c73e728..48cc9204 100644
--- a/v2rayN/ServiceLib/Enums/EConfigType.cs
+++ b/v2rayN/ServiceLib/Enums/EConfigType.cs
@@ -1,16 +1,16 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums
{
- public enum EConfigType
- {
- VMess = 1,
- Custom = 2,
- Shadowsocks = 3,
- SOCKS = 4,
- VLESS = 5,
- Trojan = 6,
- Hysteria2 = 7,
- TUIC = 8,
- WireGuard = 9,
- HTTP = 10
- }
-}
\ No newline at end of file
+ public enum EConfigType
+ {
+ VMess = 1,
+ Custom = 2,
+ Shadowsocks = 3,
+ SOCKS = 4,
+ VLESS = 5,
+ Trojan = 6,
+ Hysteria2 = 7,
+ TUIC = 8,
+ WireGuard = 9,
+ HTTP = 10
+ }
+}
diff --git a/v2rayN/ServiceLib/Enums/ECoreType.cs b/v2rayN/ServiceLib/Enums/ECoreType.cs
index cd93e7b9..ce8cf46e 100644
--- a/v2rayN/ServiceLib/Enums/ECoreType.cs
+++ b/v2rayN/ServiceLib/Enums/ECoreType.cs
@@ -1,17 +1,17 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums
{
- public enum ECoreType
- {
- v2fly = 1,
- Xray = 2,
- v2fly_v5 = 4,
- mihomo = 13,
- hysteria = 21,
- naiveproxy = 22,
- tuic = 23,
- sing_box = 24,
- juicity = 25,
- hysteria2 = 26,
- v2rayN = 99
- }
-}
\ No newline at end of file
+ public enum ECoreType
+ {
+ v2fly = 1,
+ Xray = 2,
+ v2fly_v5 = 4,
+ mihomo = 13,
+ hysteria = 21,
+ naiveproxy = 22,
+ tuic = 23,
+ sing_box = 24,
+ juicity = 25,
+ hysteria2 = 26,
+ v2rayN = 99
+ }
+}
diff --git a/v2rayN/ServiceLib/Enums/EGirdOrientation.cs b/v2rayN/ServiceLib/Enums/EGirdOrientation.cs
index 1a62c7bb..0d57b4f9 100644
--- a/v2rayN/ServiceLib/Enums/EGirdOrientation.cs
+++ b/v2rayN/ServiceLib/Enums/EGirdOrientation.cs
@@ -1,9 +1,9 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums
{
- public enum EGirdOrientation
- {
- Horizontal,
- Vertical,
- Tab,
- }
-}
\ No newline at end of file
+ public enum EGirdOrientation
+ {
+ Horizontal,
+ Vertical,
+ Tab,
+ }
+}
diff --git a/v2rayN/ServiceLib/Enums/EGlobalHotkey.cs b/v2rayN/ServiceLib/Enums/EGlobalHotkey.cs
index 328bf36e..b78efd31 100644
--- a/v2rayN/ServiceLib/Enums/EGlobalHotkey.cs
+++ b/v2rayN/ServiceLib/Enums/EGlobalHotkey.cs
@@ -1,11 +1,11 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums
{
- public enum EGlobalHotkey
- {
- ShowForm = 0,
- SystemProxyClear = 1,
- SystemProxySet = 2,
- SystemProxyUnchanged = 3,
- SystemProxyPac = 4,
- }
-}
\ No newline at end of file
+ public enum EGlobalHotkey
+ {
+ ShowForm = 0,
+ SystemProxyClear = 1,
+ SystemProxySet = 2,
+ SystemProxyUnchanged = 3,
+ SystemProxyPac = 4,
+ }
+}
diff --git a/v2rayN/ServiceLib/Enums/EInboundProtocol.cs b/v2rayN/ServiceLib/Enums/EInboundProtocol.cs
index 6da9d1da..75b86f7b 100644
--- a/v2rayN/ServiceLib/Enums/EInboundProtocol.cs
+++ b/v2rayN/ServiceLib/Enums/EInboundProtocol.cs
@@ -1,14 +1,14 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums
{
- public enum EInboundProtocol
- {
- socks = 0,
- socks2,
- socks3,
- pac,
- api,
- api2,
- mixed,
- speedtest = 21
- }
-}
\ No newline at end of file
+ public enum EInboundProtocol
+ {
+ socks = 0,
+ socks2,
+ socks3,
+ pac,
+ api,
+ api2,
+ mixed,
+ speedtest = 21
+ }
+}
diff --git a/v2rayN/ServiceLib/Enums/EMove.cs b/v2rayN/ServiceLib/Enums/EMove.cs
index ced5a4e6..f74d9e5f 100644
--- a/v2rayN/ServiceLib/Enums/EMove.cs
+++ b/v2rayN/ServiceLib/Enums/EMove.cs
@@ -1,11 +1,11 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums
{
- public enum EMove
- {
- Top = 1,
- Up = 2,
- Down = 3,
- Bottom = 4,
- Position = 5
- }
-}
\ No newline at end of file
+ public enum EMove
+ {
+ Top = 1,
+ Up = 2,
+ Down = 3,
+ Bottom = 4,
+ Position = 5
+ }
+}
diff --git a/v2rayN/ServiceLib/Enums/EMsgCommand.cs b/v2rayN/ServiceLib/Enums/EMsgCommand.cs
index 86d5213e..1ddfe512 100644
--- a/v2rayN/ServiceLib/Enums/EMsgCommand.cs
+++ b/v2rayN/ServiceLib/Enums/EMsgCommand.cs
@@ -1,12 +1,12 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums
{
- public enum EMsgCommand
- {
- ClearMsg,
- SendMsgView,
- SendSnackMsg,
- RefreshProfiles,
- StopSpeedtest,
- AppExit
- }
-}
\ No newline at end of file
+ public enum EMsgCommand
+ {
+ ClearMsg,
+ SendMsgView,
+ SendSnackMsg,
+ RefreshProfiles,
+ StopSpeedtest,
+ AppExit
+ }
+}
diff --git a/v2rayN/ServiceLib/Enums/EPresetType.cs b/v2rayN/ServiceLib/Enums/EPresetType.cs
index 855b10a1..55c2c996 100644
--- a/v2rayN/ServiceLib/Enums/EPresetType.cs
+++ b/v2rayN/ServiceLib/Enums/EPresetType.cs
@@ -1,9 +1,9 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums
{
- public enum EPresetType
- {
- Default = 0,
- Russia = 1,
- Iran = 2,
- }
-}
\ No newline at end of file
+ public enum EPresetType
+ {
+ Default = 0,
+ Russia = 1,
+ Iran = 2,
+ }
+}
diff --git a/v2rayN/ServiceLib/Enums/ERuleMode.cs b/v2rayN/ServiceLib/Enums/ERuleMode.cs
index 179384d5..f2534ea8 100644
--- a/v2rayN/ServiceLib/Enums/ERuleMode.cs
+++ b/v2rayN/ServiceLib/Enums/ERuleMode.cs
@@ -1,10 +1,10 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums
{
- public enum ERuleMode
- {
- Rule = 0,
- Global = 1,
- Direct = 2,
- Unchanged = 3
- }
-}
\ No newline at end of file
+ public enum ERuleMode
+ {
+ Rule = 0,
+ Global = 1,
+ Direct = 2,
+ Unchanged = 3
+ }
+}
diff --git a/v2rayN/ServiceLib/Enums/EServerColName.cs b/v2rayN/ServiceLib/Enums/EServerColName.cs
index ef981b74..11cb57f3 100644
--- a/v2rayN/ServiceLib/Enums/EServerColName.cs
+++ b/v2rayN/ServiceLib/Enums/EServerColName.cs
@@ -1,21 +1,21 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums
{
- public enum EServerColName
- {
- Def = 0,
- ConfigType,
- Remarks,
- Address,
- Port,
- Network,
- StreamSecurity,
- SubRemarks,
- DelayVal,
- SpeedVal,
+ public enum EServerColName
+ {
+ Def = 0,
+ ConfigType,
+ Remarks,
+ Address,
+ Port,
+ Network,
+ StreamSecurity,
+ SubRemarks,
+ DelayVal,
+ SpeedVal,
- TodayDown,
- TodayUp,
- TotalDown,
- TotalUp
- }
-}
\ No newline at end of file
+ TodayDown,
+ TodayUp,
+ TotalDown,
+ TotalUp
+ }
+}
diff --git a/v2rayN/ServiceLib/Enums/ESpeedActionType.cs b/v2rayN/ServiceLib/Enums/ESpeedActionType.cs
index 63f13919..200c3595 100644
--- a/v2rayN/ServiceLib/Enums/ESpeedActionType.cs
+++ b/v2rayN/ServiceLib/Enums/ESpeedActionType.cs
@@ -1,10 +1,10 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums
{
- public enum ESpeedActionType
- {
- Tcping,
- Realping,
- Speedtest,
- Mixedtest
- }
-}
\ No newline at end of file
+ public enum ESpeedActionType
+ {
+ Tcping,
+ Realping,
+ Speedtest,
+ Mixedtest
+ }
+}
diff --git a/v2rayN/ServiceLib/Enums/ESysProxyType.cs b/v2rayN/ServiceLib/Enums/ESysProxyType.cs
index 84beaffe..7beb225c 100644
--- a/v2rayN/ServiceLib/Enums/ESysProxyType.cs
+++ b/v2rayN/ServiceLib/Enums/ESysProxyType.cs
@@ -1,10 +1,10 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums
{
- public enum ESysProxyType
- {
- ForcedClear = 0,
- ForcedChange = 1,
- Unchanged = 2,
- Pac = 3
- }
-}
\ No newline at end of file
+ public enum ESysProxyType
+ {
+ ForcedClear = 0,
+ ForcedChange = 1,
+ Unchanged = 2,
+ Pac = 3
+ }
+}
diff --git a/v2rayN/ServiceLib/Enums/ETheme.cs b/v2rayN/ServiceLib/Enums/ETheme.cs
index 7701ae8f..32bb671f 100644
--- a/v2rayN/ServiceLib/Enums/ETheme.cs
+++ b/v2rayN/ServiceLib/Enums/ETheme.cs
@@ -1,13 +1,13 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums
{
- public enum ETheme
- {
- FollowSystem,
- Dark,
- Light,
- Aquatic,
- Desert,
- Dusk,
- NightSky
- }
-}
\ No newline at end of file
+ public enum ETheme
+ {
+ FollowSystem,
+ Dark,
+ Light,
+ Aquatic,
+ Desert,
+ Dusk,
+ NightSky
+ }
+}
diff --git a/v2rayN/ServiceLib/Enums/ETransport.cs b/v2rayN/ServiceLib/Enums/ETransport.cs
index 2cd43821..04c13c73 100644
--- a/v2rayN/ServiceLib/Enums/ETransport.cs
+++ b/v2rayN/ServiceLib/Enums/ETransport.cs
@@ -1,15 +1,15 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums
{
- public enum ETransport
- {
- tcp,
- kcp,
- ws,
- httpupgrade,
- xhttp,
- h2,
- http,
- quic,
- grpc
- }
-}
\ No newline at end of file
+ public enum ETransport
+ {
+ tcp,
+ kcp,
+ ws,
+ httpupgrade,
+ xhttp,
+ h2,
+ http,
+ quic,
+ grpc
+ }
+}
diff --git a/v2rayN/ServiceLib/Enums/EViewAction.cs b/v2rayN/ServiceLib/Enums/EViewAction.cs
index c37e1212..8508ea13 100644
--- a/v2rayN/ServiceLib/Enums/EViewAction.cs
+++ b/v2rayN/ServiceLib/Enums/EViewAction.cs
@@ -1,46 +1,46 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums
{
- public enum EViewAction
- {
- CloseWindow,
- ShowYesNo,
- SaveFileDialog,
- AddBatchRoutingRulesYesNo,
- AdjustMainLvColWidth,
- SetClipboardData,
- AddServerViaClipboard,
- ImportRulesFromClipboard,
- ProfilesFocus,
- ShareSub,
- ShareServer,
- ShowHideWindow,
- ScanScreenTask,
- ScanImageTask,
- Shutdown,
- BrowseServer,
- ImportRulesFromFile,
- InitSettingFont,
- SubEditWindow,
- RoutingRuleSettingWindow,
- RoutingRuleDetailsWindow,
- AddServerWindow,
- AddServer2Window,
- DNSSettingWindow,
- RoutingSettingWindow,
- OptionSettingWindow,
- GlobalHotkeySettingWindow,
- SubSettingWindow,
- DispatcherSpeedTest,
- DispatcherRefreshConnections,
- DispatcherRefreshProxyGroups,
- DispatcherProxiesDelayTest,
- DispatcherStatistics,
- DispatcherServerAvailability,
- DispatcherReload,
- DispatcherRefreshServersBiz,
- DispatcherRefreshIcon,
- DispatcherCheckUpdate,
- DispatcherCheckUpdateFinished,
- DispatcherShowMsg,
- }
-}
\ No newline at end of file
+ public enum EViewAction
+ {
+ CloseWindow,
+ ShowYesNo,
+ SaveFileDialog,
+ AddBatchRoutingRulesYesNo,
+ AdjustMainLvColWidth,
+ SetClipboardData,
+ AddServerViaClipboard,
+ ImportRulesFromClipboard,
+ ProfilesFocus,
+ ShareSub,
+ ShareServer,
+ ShowHideWindow,
+ ScanScreenTask,
+ ScanImageTask,
+ Shutdown,
+ BrowseServer,
+ ImportRulesFromFile,
+ InitSettingFont,
+ SubEditWindow,
+ RoutingRuleSettingWindow,
+ RoutingRuleDetailsWindow,
+ AddServerWindow,
+ AddServer2Window,
+ DNSSettingWindow,
+ RoutingSettingWindow,
+ OptionSettingWindow,
+ GlobalHotkeySettingWindow,
+ SubSettingWindow,
+ DispatcherSpeedTest,
+ DispatcherRefreshConnections,
+ DispatcherRefreshProxyGroups,
+ DispatcherProxiesDelayTest,
+ DispatcherStatistics,
+ DispatcherServerAvailability,
+ DispatcherReload,
+ DispatcherRefreshServersBiz,
+ DispatcherRefreshIcon,
+ DispatcherCheckUpdate,
+ DispatcherCheckUpdateFinished,
+ DispatcherShowMsg,
+ }
+}
diff --git a/v2rayN/ServiceLib/FodyWeavers.xml b/v2rayN/ServiceLib/FodyWeavers.xml
index 63fc1484..af4b7300 100644
--- a/v2rayN/ServiceLib/FodyWeavers.xml
+++ b/v2rayN/ServiceLib/FodyWeavers.xml
@@ -1,3 +1,3 @@
-
-
-
\ No newline at end of file
+
+
+
diff --git a/v2rayN/ServiceLib/Global.cs b/v2rayN/ServiceLib/Global.cs
index 9ea41964..7f7a45b9 100644
--- a/v2rayN/ServiceLib/Global.cs
+++ b/v2rayN/ServiceLib/Global.cs
@@ -1,505 +1,505 @@
-namespace ServiceLib
+namespace ServiceLib
{
- public class Global
- {
- #region const
+ public class Global
+ {
+ #region const
- public const string AppName = "v2rayN";
- public const string GithubUrl = "https://github.com";
- public const string GithubApiUrl = "https://api.github.com/repos";
- public const string V2flyCoreUrl = "https://github.com/v2fly/v2ray-core/releases";
- public const string XrayCoreUrl = "https://github.com/XTLS/Xray-core/releases";
- public const string NUrl = @"https://github.com/2dust/v2rayN/releases";
- public const string MihomoCoreUrl = "https://github.com/MetaCubeX/mihomo/releases";
- public const string HysteriaCoreUrl = "https://github.com/apernet/hysteria/releases";
- public const string NaiveproxyCoreUrl = "https://github.com/klzgrad/naiveproxy/releases";
- public const string TuicCoreUrl = "https://github.com/EAimTY/tuic/releases";
- public const string SingboxCoreUrl = "https://github.com/SagerNet/sing-box/releases";
- public const string GeoUrl = "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/{0}.dat";
- public const string SpeedPingTestUrl = @"https://www.google.com/generate_204";
- public const string JuicityCoreUrl = "https://github.com/juicity/juicity/releases";
- public const string SingboxRulesetUrl = @"https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-{0}/{1}.srs";
- public const string IPAPIUrl = "https://api.ip.sb/geoip";
+ public const string AppName = "v2rayN";
+ public const string GithubUrl = "https://github.com";
+ public const string GithubApiUrl = "https://api.github.com/repos";
+ public const string V2flyCoreUrl = "https://github.com/v2fly/v2ray-core/releases";
+ public const string XrayCoreUrl = "https://github.com/XTLS/Xray-core/releases";
+ public const string NUrl = @"https://github.com/2dust/v2rayN/releases";
+ public const string MihomoCoreUrl = "https://github.com/MetaCubeX/mihomo/releases";
+ public const string HysteriaCoreUrl = "https://github.com/apernet/hysteria/releases";
+ public const string NaiveproxyCoreUrl = "https://github.com/klzgrad/naiveproxy/releases";
+ public const string TuicCoreUrl = "https://github.com/EAimTY/tuic/releases";
+ public const string SingboxCoreUrl = "https://github.com/SagerNet/sing-box/releases";
+ public const string GeoUrl = "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/{0}.dat";
+ public const string SpeedPingTestUrl = @"https://www.google.com/generate_204";
+ public const string JuicityCoreUrl = "https://github.com/juicity/juicity/releases";
+ public const string SingboxRulesetUrl = @"https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-{0}/{1}.srs";
+ public const string IPAPIUrl = "https://api.ip.sb/geoip";
- public const string PromotionUrl = @"aHR0cHM6Ly85LjIzNDQ1Ni54eXovYWJjLmh0bWw=";
- public const string ConfigFileName = "guiNConfig.json";
- public const string CoreConfigFileName = "config.json";
- public const string CorePreConfigFileName = "configPre.json";
- public const string CoreSpeedtestConfigFileName = "configSpeedtest.json";
- public const string CoreMultipleLoadConfigFileName = "configMultipleLoad.json";
- public const string ClashMixinConfigFileName = "Mixin.yaml";
+ public const string PromotionUrl = @"aHR0cHM6Ly85LjIzNDQ1Ni54eXovYWJjLmh0bWw=";
+ public const string ConfigFileName = "guiNConfig.json";
+ public const string CoreConfigFileName = "config.json";
+ public const string CorePreConfigFileName = "configPre.json";
+ public const string CoreSpeedtestConfigFileName = "configSpeedtest.json";
+ public const string CoreMultipleLoadConfigFileName = "configMultipleLoad.json";
+ public const string ClashMixinConfigFileName = "Mixin.yaml";
- public const string NamespaceSample = "ServiceLib.Sample.";
- public const string V2raySampleClient = NamespaceSample + "SampleClientConfig";
- public const string SingboxSampleClient = NamespaceSample + "SingboxSampleClientConfig";
- public const string V2raySampleHttpRequestFileName = NamespaceSample + "SampleHttpRequest";
- public const string V2raySampleHttpResponseFileName = NamespaceSample + "SampleHttpResponse";
- public const string V2raySampleInbound = NamespaceSample + "SampleInbound";
- public const string V2raySampleOutbound = NamespaceSample + "SampleOutbound";
- public const string SingboxSampleOutbound = NamespaceSample + "SingboxSampleOutbound";
- public const string CustomRoutingFileName = NamespaceSample + "custom_routing_";
- public const string TunSingboxDNSFileName = NamespaceSample + "tun_singbox_dns";
- public const string TunSingboxInboundFileName = NamespaceSample + "tun_singbox_inbound";
- public const string TunSingboxRulesFileName = NamespaceSample + "tun_singbox_rules";
- public const string DNSV2rayNormalFileName = NamespaceSample + "dns_v2ray_normal";
- public const string DNSSingboxNormalFileName = NamespaceSample + "dns_singbox_normal";
- public const string ClashMixinYaml = NamespaceSample + "clash_mixin_yaml";
- public const string ClashTunYaml = NamespaceSample + "clash_tun_yaml";
- public const string LinuxAutostartConfig = NamespaceSample + "linux_autostart_config";
- public const string PacFileName = NamespaceSample + "pac";
+ public const string NamespaceSample = "ServiceLib.Sample.";
+ public const string V2raySampleClient = NamespaceSample + "SampleClientConfig";
+ public const string SingboxSampleClient = NamespaceSample + "SingboxSampleClientConfig";
+ public const string V2raySampleHttpRequestFileName = NamespaceSample + "SampleHttpRequest";
+ public const string V2raySampleHttpResponseFileName = NamespaceSample + "SampleHttpResponse";
+ public const string V2raySampleInbound = NamespaceSample + "SampleInbound";
+ public const string V2raySampleOutbound = NamespaceSample + "SampleOutbound";
+ public const string SingboxSampleOutbound = NamespaceSample + "SingboxSampleOutbound";
+ public const string CustomRoutingFileName = NamespaceSample + "custom_routing_";
+ public const string TunSingboxDNSFileName = NamespaceSample + "tun_singbox_dns";
+ public const string TunSingboxInboundFileName = NamespaceSample + "tun_singbox_inbound";
+ public const string TunSingboxRulesFileName = NamespaceSample + "tun_singbox_rules";
+ public const string DNSV2rayNormalFileName = NamespaceSample + "dns_v2ray_normal";
+ public const string DNSSingboxNormalFileName = NamespaceSample + "dns_singbox_normal";
+ public const string ClashMixinYaml = NamespaceSample + "clash_mixin_yaml";
+ public const string ClashTunYaml = NamespaceSample + "clash_tun_yaml";
+ public const string LinuxAutostartConfig = NamespaceSample + "linux_autostart_config";
+ public const string PacFileName = NamespaceSample + "pac";
- public const string DefaultSecurity = "auto";
- public const string DefaultNetwork = "tcp";
- public const string TcpHeaderHttp = "http";
- public const string None = "none";
- public const string ProxyTag = "proxy";
- public const string DirectTag = "direct";
- public const string BlockTag = "block";
- public const string StreamSecurity = "tls";
- public const string StreamSecurityReality = "reality";
- public const string Loopback = "127.0.0.1";
- public const string InboundAPIProtocol = "dokodemo-door";
- public const string HttpProtocol = "http://";
- public const string HttpsProtocol = "https://";
- public const string SocksProtocol = "socks://";
- public const string Socks5Protocol = "socks5://";
+ public const string DefaultSecurity = "auto";
+ public const string DefaultNetwork = "tcp";
+ public const string TcpHeaderHttp = "http";
+ public const string None = "none";
+ public const string ProxyTag = "proxy";
+ public const string DirectTag = "direct";
+ public const string BlockTag = "block";
+ public const string StreamSecurity = "tls";
+ public const string StreamSecurityReality = "reality";
+ public const string Loopback = "127.0.0.1";
+ public const string InboundAPIProtocol = "dokodemo-door";
+ public const string HttpProtocol = "http://";
+ public const string HttpsProtocol = "https://";
+ public const string SocksProtocol = "socks://";
+ public const string Socks5Protocol = "socks5://";
- public const string UserEMail = "t@t.tt";
- public const string AutoRunRegPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
- public const string AutoRunName = "v2rayNAutoRun";
- public const string SystemProxyExceptionsWindows = "localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*";
- public const string SystemProxyExceptionsLinux = "localhost,127.0.0.0/8,::1";
- public const string RoutingRuleComma = "";
- public const string GrpcGunMode = "gun";
- public const string GrpcMultiMode = "multi";
- public const int MaxPort = 65536;
- public const string DelayUnit = "";
- public const string SpeedUnit = "";
- public const int MinFontSize = 8;
- public const string RebootAs = "rebootas";
- public const string AvaAssets = "avares://v2rayN/Assets/";
- public const string LocalAppData = "V2RAYN_LOCAL_APPLICATION_DATA";
- public const string V2RayLocalAsset = "V2RAY_LOCATION_ASSET";
- public const string XrayLocalAsset = "XRAY_LOCATION_ASSET";
+ public const string UserEMail = "t@t.tt";
+ public const string AutoRunRegPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
+ public const string AutoRunName = "v2rayNAutoRun";
+ public const string SystemProxyExceptionsWindows = "localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*";
+ public const string SystemProxyExceptionsLinux = "localhost,127.0.0.0/8,::1";
+ public const string RoutingRuleComma = "";
+ public const string GrpcGunMode = "gun";
+ public const string GrpcMultiMode = "multi";
+ public const int MaxPort = 65536;
+ public const string DelayUnit = "";
+ public const string SpeedUnit = "";
+ public const int MinFontSize = 8;
+ public const string RebootAs = "rebootas";
+ public const string AvaAssets = "avares://v2rayN/Assets/";
+ public const string LocalAppData = "V2RAYN_LOCAL_APPLICATION_DATA";
+ public const string V2RayLocalAsset = "V2RAY_LOCATION_ASSET";
+ public const string XrayLocalAsset = "XRAY_LOCATION_ASSET";
- public static readonly List IEProxyProtocols =
- [
- "{ip}:{http_port}",
- "socks={ip}:{socks_port}",
- "http={ip}:{http_port};https={ip}:{http_port};ftp={ip}:{http_port};socks={ip}:{socks_port}",
- "http=http://{ip}:{http_port};https=http://{ip}:{http_port}",
- ""
- ];
+ public static readonly List IEProxyProtocols =
+ [
+ "{ip}:{http_port}",
+ "socks={ip}:{socks_port}",
+ "http={ip}:{http_port};https={ip}:{http_port};ftp={ip}:{http_port};socks={ip}:{socks_port}",
+ "http=http://{ip}:{http_port};https=http://{ip}:{http_port}",
+ ""
+ ];
- public static readonly List SubConvertUrls =
- [
- @"https://sub.xeton.dev/sub?url={0}",
- @"https://api.dler.io/sub?url={0}",
- @"http://127.0.0.1:25500/sub?url={0}",
- ""
- ];
+ public static readonly List SubConvertUrls =
+ [
+ @"https://sub.xeton.dev/sub?url={0}",
+ @"https://api.dler.io/sub?url={0}",
+ @"http://127.0.0.1:25500/sub?url={0}",
+ ""
+ ];
- public static readonly List SubConvertConfig =
- [@"https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online.ini"];
+ public static readonly List SubConvertConfig =
+ [@"https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online.ini"];
- public static readonly List SubConvertTargets =
- [
- "",
- "mixed",
- "v2ray",
- "clash",
- "ss"
- ];
+ public static readonly List SubConvertTargets =
+ [
+ "",
+ "mixed",
+ "v2ray",
+ "clash",
+ "ss"
+ ];
- public static readonly List SpeedTestUrls =
- [
- @"https://speed.cloudflare.com/__down?bytes=100000000",
- @"https://speed.cloudflare.com/__down?bytes=50000000",
- @"https://speed.cloudflare.com/__down?bytes=10000000",
- @"https://cachefly.cachefly.net/50mb.test"
- ];
+ public static readonly List SpeedTestUrls =
+ [
+ @"https://speed.cloudflare.com/__down?bytes=100000000",
+ @"https://speed.cloudflare.com/__down?bytes=50000000",
+ @"https://speed.cloudflare.com/__down?bytes=10000000",
+ @"https://cachefly.cachefly.net/50mb.test"
+ ];
- public static readonly List SpeedPingTestUrls =
- [
- @"https://www.google.com/generate_204",
- @"https://www.gstatic.com/generate_204",
- @"https://www.apple.com/library/test/success.html",
- @"http://www.msftconnecttest.com/connecttest.txt"
- ];
+ public static readonly List SpeedPingTestUrls =
+ [
+ @"https://www.google.com/generate_204",
+ @"https://www.gstatic.com/generate_204",
+ @"https://www.apple.com/library/test/success.html",
+ @"http://www.msftconnecttest.com/connecttest.txt"
+ ];
- public static readonly List GeoFilesSources =
- [
- "",
- @"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/{0}.dat",
- @"https://cdn.jsdelivr.net/gh/chocolate4u/Iran-v2ray-rules@release/{0}.dat"
- ];
+ public static readonly List GeoFilesSources =
+ [
+ "",
+ @"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/{0}.dat",
+ @"https://cdn.jsdelivr.net/gh/chocolate4u/Iran-v2ray-rules@release/{0}.dat"
+ ];
- public static readonly List SingboxRulesetSources =
- [
- "",
- @"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-rules-dat@release/sing-box/rule-set-{0}/{1}.srs",
- @"https://cdn.jsdelivr.net/gh/chocolate4u/Iran-sing-box-rules@rule-set/{1}.srs"
- ];
+ public static readonly List SingboxRulesetSources =
+ [
+ "",
+ @"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-rules-dat@release/sing-box/rule-set-{0}/{1}.srs",
+ @"https://cdn.jsdelivr.net/gh/chocolate4u/Iran-sing-box-rules@rule-set/{1}.srs"
+ ];
- public static readonly List RoutingRulesSources =
- [
- "",
- @"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/template.json",
- @"https://cdn.jsdelivr.net/gh/Chocolate4U/Iran-v2ray-rules@main/v2rayN/template.json"
- ];
+ public static readonly List RoutingRulesSources =
+ [
+ "",
+ @"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/template.json",
+ @"https://cdn.jsdelivr.net/gh/Chocolate4U/Iran-v2ray-rules@main/v2rayN/template.json"
+ ];
- public static readonly List DNSTemplateSources =
- [
- "",
- @"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/",
- @"https://cdn.jsdelivr.net/gh/Chocolate4U/Iran-v2ray-rules@main/v2rayN/"
- ];
+ public static readonly List DNSTemplateSources =
+ [
+ "",
+ @"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/",
+ @"https://cdn.jsdelivr.net/gh/Chocolate4U/Iran-v2ray-rules@main/v2rayN/"
+ ];
- public static readonly Dictionary UserAgentTexts = new()
- {
- {"chrome","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36" },
- {"firefox","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0" },
- {"safari","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15" },
- {"edge","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.70" },
- {"none",""}
- };
+ public static readonly Dictionary UserAgentTexts = new()
+ {
+ {"chrome","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36" },
+ {"firefox","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0" },
+ {"safari","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15" },
+ {"edge","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.70" },
+ {"none",""}
+ };
- public const string Hysteria2ProtocolShare = "hy2://";
+ public const string Hysteria2ProtocolShare = "hy2://";
- public static readonly Dictionary ProtocolShares = new()
- {
- {EConfigType.VMess,"vmess://"},
- {EConfigType.Shadowsocks,"ss://"},
- {EConfigType.SOCKS,"socks://"},
- {EConfigType.VLESS,"vless://"},
- {EConfigType.Trojan,"trojan://"},
- {EConfigType.Hysteria2,"hysteria2://"},
- {EConfigType.TUIC,"tuic://"},
- {EConfigType.WireGuard,"wireguard://"}
- };
+ public static readonly Dictionary ProtocolShares = new()
+ {
+ {EConfigType.VMess,"vmess://"},
+ {EConfigType.Shadowsocks,"ss://"},
+ {EConfigType.SOCKS,"socks://"},
+ {EConfigType.VLESS,"vless://"},
+ {EConfigType.Trojan,"trojan://"},
+ {EConfigType.Hysteria2,"hysteria2://"},
+ {EConfigType.TUIC,"tuic://"},
+ {EConfigType.WireGuard,"wireguard://"}
+ };
- public static readonly Dictionary ProtocolTypes = new()
- {
- {EConfigType.VMess,"vmess"},
- {EConfigType.Shadowsocks,"shadowsocks"},
- {EConfigType.SOCKS,"socks"},
- {EConfigType.HTTP,"http"},
- {EConfigType.VLESS,"vless"},
- {EConfigType.Trojan,"trojan"},
- {EConfigType.Hysteria2,"hysteria2"},
- {EConfigType.TUIC,"tuic"},
- {EConfigType.WireGuard,"wireguard"}
- };
+ public static readonly Dictionary ProtocolTypes = new()
+ {
+ {EConfigType.VMess,"vmess"},
+ {EConfigType.Shadowsocks,"shadowsocks"},
+ {EConfigType.SOCKS,"socks"},
+ {EConfigType.HTTP,"http"},
+ {EConfigType.VLESS,"vless"},
+ {EConfigType.Trojan,"trojan"},
+ {EConfigType.Hysteria2,"hysteria2"},
+ {EConfigType.TUIC,"tuic"},
+ {EConfigType.WireGuard,"wireguard"}
+ };
- public static readonly List VmessSecurities =
- [
- "aes-128-gcm",
- "chacha20-poly1305",
- "auto",
- "none",
- "zero"
- ];
+ public static readonly List VmessSecurities =
+ [
+ "aes-128-gcm",
+ "chacha20-poly1305",
+ "auto",
+ "none",
+ "zero"
+ ];
- public static readonly List SsSecurities =
- [
- "aes-256-gcm",
- "aes-128-gcm",
- "chacha20-poly1305",
- "chacha20-ietf-poly1305",
- "none",
- "plain"
- ];
+ public static readonly List SsSecurities =
+ [
+ "aes-256-gcm",
+ "aes-128-gcm",
+ "chacha20-poly1305",
+ "chacha20-ietf-poly1305",
+ "none",
+ "plain"
+ ];
- public static readonly List SsSecuritiesInXray =
- [
- "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 SsSecuritiesInXray =
+ [
+ "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 SsSecuritiesInSingbox =
- [
- "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 SsSecuritiesInSingbox =
+ [
+ "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 Flows =
- [
- "",
- "xtls-rprx-vision",
- "xtls-rprx-vision-udp443"
- ];
+ public static readonly List Flows =
+ [
+ "",
+ "xtls-rprx-vision",
+ "xtls-rprx-vision-udp443"
+ ];
- public static readonly List Networks =
- [
- "tcp",
- "kcp",
- "ws",
- "httpupgrade",
- "xhttp",
- "h2",
- "quic",
- "grpc"
- ];
+ public static readonly List Networks =
+ [
+ "tcp",
+ "kcp",
+ "ws",
+ "httpupgrade",
+ "xhttp",
+ "h2",
+ "quic",
+ "grpc"
+ ];
- public static readonly List KcpHeaderTypes =
- [
- "srtp",
- "utp",
- "wechat-video",
- "dtls",
- "wireguard"
- ];
+ public static readonly List KcpHeaderTypes =
+ [
+ "srtp",
+ "utp",
+ "wechat-video",
+ "dtls",
+ "wireguard"
+ ];
- public static readonly List CoreTypes =
- [
- "Xray",
- "sing_box"
- ];
+ public static readonly List CoreTypes =
+ [
+ "Xray",
+ "sing_box"
+ ];
- public static readonly List DomainStrategies =
- [
- "AsIs",
- "IPIfNonMatch",
- "IPOnDemand"
- ];
+ public static readonly List DomainStrategies =
+ [
+ "AsIs",
+ "IPIfNonMatch",
+ "IPOnDemand"
+ ];
- public static readonly List DomainStrategies4Singbox =
- [
- "ipv4_only",
- "ipv6_only",
- "prefer_ipv4",
- "prefer_ipv6",
- ""
- ];
+ public static readonly List DomainStrategies4Singbox =
+ [
+ "ipv4_only",
+ "ipv6_only",
+ "prefer_ipv4",
+ "prefer_ipv6",
+ ""
+ ];
- public static readonly List DomainMatchers =
- [
- "linear",
- "mph",
- ""
- ];
+ public static readonly List DomainMatchers =
+ [
+ "linear",
+ "mph",
+ ""
+ ];
- public static readonly List Fingerprints =
- [
- "chrome",
- "firefox",
- "safari",
- "ios",
- "android",
- "edge",
- "360",
- "qq",
- "random",
- "randomized",
- ""
- ];
+ public static readonly List Fingerprints =
+ [
+ "chrome",
+ "firefox",
+ "safari",
+ "ios",
+ "android",
+ "edge",
+ "360",
+ "qq",
+ "random",
+ "randomized",
+ ""
+ ];
- public static readonly List UserAgent =
- [
- "chrome",
- "firefox",
- "safari",
- "edge",
- "none"
- ];
+ public static readonly List UserAgent =
+ [
+ "chrome",
+ "firefox",
+ "safari",
+ "edge",
+ "none"
+ ];
- public static readonly List XhttpMode =
- [
- "auto",
- "packet-up",
- "stream-up",
- "stream-one"
- ];
+ public static readonly List XhttpMode =
+ [
+ "auto",
+ "packet-up",
+ "stream-up",
+ "stream-one"
+ ];
- public static readonly List AllowInsecure =
- [
- "true",
- "false",
- ""
- ];
+ public static readonly List AllowInsecure =
+ [
+ "true",
+ "false",
+ ""
+ ];
- public static readonly List DomainStrategy4Freedoms =
- [
- "AsIs",
- "UseIP",
- "UseIPv4",
- "UseIPv6",
- ""
- ];
+ public static readonly List DomainStrategy4Freedoms =
+ [
+ "AsIs",
+ "UseIP",
+ "UseIPv4",
+ "UseIPv6",
+ ""
+ ];
- public static readonly List SingboxDomainStrategy4Out =
- [
- "ipv4_only",
- "prefer_ipv4",
- "prefer_ipv6",
- "ipv6_only",
- ""
- ];
+ public static readonly List SingboxDomainStrategy4Out =
+ [
+ "ipv4_only",
+ "prefer_ipv4",
+ "prefer_ipv6",
+ "ipv6_only",
+ ""
+ ];
- public static readonly List DomainDNSAddress =
- [
- "223.5.5.5",
- "223.6.6.6",
- "localhost"
- ];
+ public static readonly List DomainDNSAddress =
+ [
+ "223.5.5.5",
+ "223.6.6.6",
+ "localhost"
+ ];
- public static readonly List SingboxDomainDNSAddress =
- [
- "223.5.5.5",
- "223.6.6.6",
- "dhcp://auto"
- ];
+ public static readonly List SingboxDomainDNSAddress =
+ [
+ "223.5.5.5",
+ "223.6.6.6",
+ "dhcp://auto"
+ ];
- public static readonly List Languages =
- [
- "zh-Hans",
- "zh-Hant",
- "en",
- "fa-Ir",
- "ru",
- "hu"
- ];
+ public static readonly List Languages =
+ [
+ "zh-Hans",
+ "zh-Hant",
+ "en",
+ "fa-Ir",
+ "ru",
+ "hu"
+ ];
- public static readonly List Alpns =
- [
- "h3",
- "h2",
- "http/1.1",
- "h3,h2",
- "h2,http/1.1",
- "h3,h2,http/1.1",
- ""
- ];
+ public static readonly List Alpns =
+ [
+ "h3",
+ "h2",
+ "http/1.1",
+ "h3,h2",
+ "h2,http/1.1",
+ "h3,h2,http/1.1",
+ ""
+ ];
- public static readonly List LogLevels =
- [
- "debug",
- "info",
- "warning",
- "error",
- "none"
- ];
+ public static readonly List LogLevels =
+ [
+ "debug",
+ "info",
+ "warning",
+ "error",
+ "none"
+ ];
- public static readonly List InboundTags =
- [
- "socks",
- "socks2",
- "socks3"
- ];
+ public static readonly List InboundTags =
+ [
+ "socks",
+ "socks2",
+ "socks3"
+ ];
- public static readonly List RuleProtocols =
- [
- "http",
- "tls",
- "bittorrent"
- ];
+ public static readonly List RuleProtocols =
+ [
+ "http",
+ "tls",
+ "bittorrent"
+ ];
- public static readonly List RuleNetworks =
- [
- "",
- "tcp",
- "udp",
- "tcp,udp"
- ];
+ public static readonly List RuleNetworks =
+ [
+ "",
+ "tcp",
+ "udp",
+ "tcp,udp"
+ ];
- public static readonly List destOverrideProtocols =
- [
- "http",
- "tls",
- "quic",
- "fakedns",
- "fakedns+others"
- ];
+ public static readonly List destOverrideProtocols =
+ [
+ "http",
+ "tls",
+ "quic",
+ "fakedns",
+ "fakedns+others"
+ ];
- public static readonly List TunMtus =
- [
- "1280",
- "1408",
- "1500",
- "9000"
- ];
+ public static readonly List TunMtus =
+ [
+ "1280",
+ "1408",
+ "1500",
+ "9000"
+ ];
- public static readonly List TunStacks =
- [
- "gvisor",
- "system",
- "mixed"
- ];
+ public static readonly List TunStacks =
+ [
+ "gvisor",
+ "system",
+ "mixed"
+ ];
- public static readonly List PresetMsgFilters =
- [
- "proxy",
- "direct",
- "block",
- ""
- ];
+ public static readonly List PresetMsgFilters =
+ [
+ "proxy",
+ "direct",
+ "block",
+ ""
+ ];
- public static readonly List SingboxMuxs =
- [
- "h2mux",
- "smux",
- "yamux",
- ""
- ];
+ public static readonly List SingboxMuxs =
+ [
+ "h2mux",
+ "smux",
+ "yamux",
+ ""
+ ];
- public static readonly List TuicCongestionControls =
- [
- "cubic",
- "new_reno",
- "bbr"
- ];
+ public static readonly List TuicCongestionControls =
+ [
+ "cubic",
+ "new_reno",
+ "bbr"
+ ];
- public static readonly List allowSelectType =
- [
- "selector",
- "urltest",
- "loadbalance",
- "fallback"
- ];
+ public static readonly List allowSelectType =
+ [
+ "selector",
+ "urltest",
+ "loadbalance",
+ "fallback"
+ ];
- public static readonly List notAllowTestType =
- [
- "selector",
- "urltest",
- "direct",
- "reject",
- "compatible",
- "pass",
- "loadbalance",
- "fallback"
- ];
+ public static readonly List notAllowTestType =
+ [
+ "selector",
+ "urltest",
+ "direct",
+ "reject",
+ "compatible",
+ "pass",
+ "loadbalance",
+ "fallback"
+ ];
- public static readonly List proxyVehicleType =
- [
- "file",
- "http"
- ];
+ public static readonly List proxyVehicleType =
+ [
+ "file",
+ "http"
+ ];
- #endregion const
- }
-}
\ No newline at end of file
+ #endregion const
+ }
+}
diff --git a/v2rayN/ServiceLib/GlobalUsings.cs b/v2rayN/ServiceLib/GlobalUsings.cs
index a4bf3ccd..98014d8e 100644
--- a/v2rayN/ServiceLib/GlobalUsings.cs
+++ b/v2rayN/ServiceLib/GlobalUsings.cs
@@ -1,11 +1,11 @@
-global using ServiceLib.Base;
+global using ServiceLib.Base;
global using ServiceLib.Common;
global using ServiceLib.Enums;
global using ServiceLib.Handler;
global using ServiceLib.Handler.Fmt;
-global using ServiceLib.Services;
-global using ServiceLib.Services.Statistics;
-global using ServiceLib.Services.CoreConfig;
+global using ServiceLib.Handler.SysProxy;
global using ServiceLib.Models;
global using ServiceLib.Resx;
-global using ServiceLib.Handler.SysProxy;
\ No newline at end of file
+global using ServiceLib.Services;
+global using ServiceLib.Services.CoreConfig;
+global using ServiceLib.Services.Statistics;
diff --git a/v2rayN/ServiceLib/Handler/AppHandler.cs b/v2rayN/ServiceLib/Handler/AppHandler.cs
index 72a080e8..33ef61c7 100644
--- a/v2rayN/ServiceLib/Handler/AppHandler.cs
+++ b/v2rayN/ServiceLib/Handler/AppHandler.cs
@@ -1,255 +1,255 @@
-namespace ServiceLib.Handler
+namespace ServiceLib.Handler
{
- public sealed class AppHandler
- {
- #region Property
+ public sealed class AppHandler
+ {
+ #region Property
- private static readonly Lazy _instance = new(() => new());
- private Config _config;
- private int? _statePort;
- private int? _statePort2;
- private Job? _processJob;
- private bool? _isAdministrator;
- public static AppHandler Instance => _instance.Value;
- public Config Config => _config;
+ private static readonly Lazy _instance = new(() => new());
+ private Config _config;
+ private int? _statePort;
+ private int? _statePort2;
+ private Job? _processJob;
+ private bool? _isAdministrator;
+ public static AppHandler Instance => _instance.Value;
+ public Config Config => _config;
- public int StatePort
- {
- get
- {
- _statePort ??= Utils.GetFreePort(GetLocalPort(EInboundProtocol.api));
- return _statePort.Value;
- }
- }
+ public int StatePort
+ {
+ get
+ {
+ _statePort ??= Utils.GetFreePort(GetLocalPort(EInboundProtocol.api));
+ return _statePort.Value;
+ }
+ }
- public int StatePort2
- {
- get
- {
- _statePort2 ??= Utils.GetFreePort(GetLocalPort(EInboundProtocol.api2));
- return _statePort2.Value + (_config.TunModeItem.EnableTun ? 1 : 0);
- }
- }
+ public int StatePort2
+ {
+ get
+ {
+ _statePort2 ??= Utils.GetFreePort(GetLocalPort(EInboundProtocol.api2));
+ return _statePort2.Value + (_config.TunModeItem.EnableTun ? 1 : 0);
+ }
+ }
- public bool IsAdministrator
- {
- get
- {
- _isAdministrator ??= Utils.IsAdministrator();
- return _isAdministrator.Value;
- }
- }
+ public bool IsAdministrator
+ {
+ get
+ {
+ _isAdministrator ??= Utils.IsAdministrator();
+ return _isAdministrator.Value;
+ }
+ }
- #endregion Property
+ #endregion Property
- #region Init
+ #region Init
- public bool InitApp()
- {
- if (Utils.HasWritePermission() == false)
- {
- Environment.SetEnvironmentVariable(Global.LocalAppData, "1", EnvironmentVariableTarget.Process);
- }
+ public bool InitApp()
+ {
+ if (Utils.HasWritePermission() == false)
+ {
+ Environment.SetEnvironmentVariable(Global.LocalAppData, "1", EnvironmentVariableTarget.Process);
+ }
- Logging.Setup();
- var config = ConfigHandler.LoadConfig();
- if (config == null)
- {
- return false;
- }
- _config = config;
- Thread.CurrentThread.CurrentUICulture = new(_config.UiItem.CurrentLanguage);
+ Logging.Setup();
+ var config = ConfigHandler.LoadConfig();
+ if (config == null)
+ {
+ return false;
+ }
+ _config = config;
+ Thread.CurrentThread.CurrentUICulture = new(_config.UiItem.CurrentLanguage);
- //Under Win10
- if (Utils.IsWindows() && Environment.OSVersion.Version.Major < 10)
- {
- Environment.SetEnvironmentVariable("DOTNET_EnableWriteXorExecute", "0", EnvironmentVariableTarget.User);
- }
+ //Under Win10
+ if (Utils.IsWindows() && Environment.OSVersion.Version.Major < 10)
+ {
+ Environment.SetEnvironmentVariable("DOTNET_EnableWriteXorExecute", "0", EnvironmentVariableTarget.User);
+ }
- SQLiteHelper.Instance.CreateTable();
- SQLiteHelper.Instance.CreateTable();
- SQLiteHelper.Instance.CreateTable();
- SQLiteHelper.Instance.CreateTable();
- SQLiteHelper.Instance.CreateTable();
- SQLiteHelper.Instance.CreateTable();
- return true;
- }
+ SQLiteHelper.Instance.CreateTable();
+ SQLiteHelper.Instance.CreateTable();
+ SQLiteHelper.Instance.CreateTable();
+ SQLiteHelper.Instance.CreateTable();
+ SQLiteHelper.Instance.CreateTable();
+ SQLiteHelper.Instance.CreateTable();
+ return true;
+ }
- public bool InitComponents()
- {
- Logging.SaveLog($"v2rayN start up | {Utils.GetRuntimeInfo()}");
- Logging.LoggingEnabled(_config.GuiItem.EnableLog);
+ public bool InitComponents()
+ {
+ Logging.SaveLog($"v2rayN start up | {Utils.GetRuntimeInfo()}");
+ Logging.LoggingEnabled(_config.GuiItem.EnableLog);
- ClearExpiredFiles();
+ ClearExpiredFiles();
- return true;
- }
+ return true;
+ }
- public bool Reset()
- {
- _statePort = null;
- _statePort2 = null;
- return true;
- }
+ public bool Reset()
+ {
+ _statePort = null;
+ _statePort2 = null;
+ return true;
+ }
- private void ClearExpiredFiles()
- {
- Task.Run(() =>
- {
- FileManager.DeleteExpiredFiles(Utils.GetLogPath(), DateTime.Now.AddMonths(-1));
- FileManager.DeleteExpiredFiles(Utils.GetTempPath(), DateTime.Now.AddMonths(-1));
- });
- }
+ private void ClearExpiredFiles()
+ {
+ Task.Run(() =>
+ {
+ FileManager.DeleteExpiredFiles(Utils.GetLogPath(), DateTime.Now.AddMonths(-1));
+ FileManager.DeleteExpiredFiles(Utils.GetTempPath(), DateTime.Now.AddMonths(-1));
+ });
+ }
- #endregion Init
+ #endregion Init
- #region Config
+ #region Config
- public int GetLocalPort(EInboundProtocol protocol)
- {
- var localPort = _config.Inbound.FirstOrDefault(t => t.Protocol == nameof(EInboundProtocol.socks))?.LocalPort ?? 10808;
- return localPort + (int)protocol;
- }
+ public int GetLocalPort(EInboundProtocol protocol)
+ {
+ var localPort = _config.Inbound.FirstOrDefault(t => t.Protocol == nameof(EInboundProtocol.socks))?.LocalPort ?? 10808;
+ return localPort + (int)protocol;
+ }
- public void AddProcess(IntPtr processHandle)
- {
- if (Utils.IsWindows())
- {
- _processJob ??= new();
- try
- {
- _processJob?.AddProcess(processHandle);
- }
- catch
- {
- }
- }
- }
+ public void AddProcess(IntPtr processHandle)
+ {
+ if (Utils.IsWindows())
+ {
+ _processJob ??= new();
+ try
+ {
+ _processJob?.AddProcess(processHandle);
+ }
+ catch
+ {
+ }
+ }
+ }
- #endregion Config
+ #endregion Config
- #region SqliteHelper
+ #region SqliteHelper
- public async Task?> SubItems()
- {
- return await SQLiteHelper.Instance.TableAsync().OrderBy(t => t.Sort).ToListAsync();
- }
+ public async Task?> SubItems()
+ {
+ return await SQLiteHelper.Instance.TableAsync().OrderBy(t => t.Sort).ToListAsync();
+ }
- public async Task GetSubItem(string? subid)
- {
- return await SQLiteHelper.Instance.TableAsync().FirstOrDefaultAsync(t => t.Id == subid);
- }
+ public async Task GetSubItem(string? subid)
+ {
+ return await SQLiteHelper.Instance.TableAsync().FirstOrDefaultAsync(t => t.Id == subid);
+ }
- public async Task?> ProfileItems(string subid)
- {
- if (Utils.IsNullOrEmpty(subid))
- {
- return await SQLiteHelper.Instance.TableAsync().ToListAsync();
- }
- else
- {
- return await SQLiteHelper.Instance.TableAsync().Where(t => t.Subid == subid).ToListAsync();
- }
- }
+ public async Task?> ProfileItems(string subid)
+ {
+ if (Utils.IsNullOrEmpty(subid))
+ {
+ return await SQLiteHelper.Instance.TableAsync().ToListAsync();
+ }
+ else
+ {
+ return await SQLiteHelper.Instance.TableAsync().Where(t => t.Subid == subid).ToListAsync();
+ }
+ }
- public async Task?> ProfileItemIndexes(string subid)
- {
- return (await ProfileItems(subid))?.Select(t => t.IndexId)?.ToList();
- }
+ public async Task