From 4d3db5606581aa6051c52b233159d3fae905f95e Mon Sep 17 00:00:00 2001
From: 2dust <31833384+2dust@users.noreply.github.com>
Date: Wed, 2 Apr 2025 11:44:23 +0800
Subject: [PATCH] csharp_style_namespace_declarations = file_scoped
---
v2rayN/AmazTool/Program.cs | 39 +-
v2rayN/AmazTool/UpgradeApp.cs | 183 +-
v2rayN/AmazTool/Utils.cs | 75 +-
v2rayN/Directory.Build.props | 2 +-
v2rayN/ServiceLib/Base/MyReactiveObject.cs | 15 +-
v2rayN/ServiceLib/Common/AesUtils.cs | 181 +-
v2rayN/ServiceLib/Common/DesUtils.cs | 133 +-
v2rayN/ServiceLib/Common/DownloaderHelper.cs | 313 +-
v2rayN/ServiceLib/Common/FileManager.cs | 395 +-
v2rayN/ServiceLib/Common/HttpClientHelper.cs | 333 +-
v2rayN/ServiceLib/Common/Job.cs | 5 +-
v2rayN/ServiceLib/Common/JsonUtils.cs | 223 +-
v2rayN/ServiceLib/Common/Logging.cs | 77 +-
v2rayN/ServiceLib/Common/QRCodeHelper.cs | 167 +-
v2rayN/ServiceLib/Common/SemanticVersion.cs | 321 +-
v2rayN/ServiceLib/Common/SqliteHelper.cs | 161 +-
v2rayN/ServiceLib/Common/StringEx.cs | 139 +-
v2rayN/ServiceLib/Common/Utils.cs | 1635 ++++----
v2rayN/ServiceLib/Common/WindowsUtils.cs | 109 +-
v2rayN/ServiceLib/Common/YamlUtils.cs | 125 +-
v2rayN/ServiceLib/Enums/EConfigType.cs | 29 +-
v2rayN/ServiceLib/Enums/ECoreType.cs | 33 +-
v2rayN/ServiceLib/Enums/EGirdOrientation.cs | 15 +-
v2rayN/ServiceLib/Enums/EGlobalHotkey.cs | 19 +-
v2rayN/ServiceLib/Enums/EInboundProtocol.cs | 25 +-
v2rayN/ServiceLib/Enums/EMove.cs | 19 +-
v2rayN/ServiceLib/Enums/EMsgCommand.cs | 17 +-
v2rayN/ServiceLib/Enums/EMultipleLoad.cs | 15 +-
v2rayN/ServiceLib/Enums/EPresetType.cs | 15 +-
v2rayN/ServiceLib/Enums/ERuleMode.cs | 17 +-
v2rayN/ServiceLib/Enums/EServerColName.cs | 39 +-
v2rayN/ServiceLib/Enums/ESpeedActionType.cs | 17 +-
v2rayN/ServiceLib/Enums/ESysProxyType.cs | 17 +-
v2rayN/ServiceLib/Enums/ETheme.cs | 23 +-
v2rayN/ServiceLib/Enums/ETransport.cs | 27 +-
v2rayN/ServiceLib/Enums/EViewAction.cs | 89 +-
v2rayN/ServiceLib/Global.cs | 509 ++-
v2rayN/ServiceLib/Handler/AppHandler.cs | 441 +-
.../ServiceLib/Handler/AutoStartupHandler.cs | 367 +-
v2rayN/ServiceLib/Handler/ClashApiHandler.cs | 295 +-
v2rayN/ServiceLib/Handler/ConfigHandler.cs | 3615 ++++++++---------
.../ServiceLib/Handler/CoreConfigHandler.cs | 275 +-
v2rayN/ServiceLib/Handler/CoreHandler.cs | 679 ++--
v2rayN/ServiceLib/Handler/CoreInfoHandler.cs | 111 +-
v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs | 425 +-
v2rayN/ServiceLib/Handler/Fmt/ClashFmt.cs | 33 +-
v2rayN/ServiceLib/Handler/Fmt/FmtHandler.cs | 153 +-
v2rayN/ServiceLib/Handler/Fmt/Hysteria2Fmt.cs | 175 +-
.../ServiceLib/Handler/Fmt/NaiveproxyFmt.cs | 33 +-
.../ServiceLib/Handler/Fmt/ShadowsocksFmt.cs | 295 +-
v2rayN/ServiceLib/Handler/Fmt/SingboxFmt.cs | 73 +-
v2rayN/ServiceLib/Handler/Fmt/SocksFmt.cs | 189 +-
v2rayN/ServiceLib/Handler/Fmt/TrojanFmt.cs | 75 +-
v2rayN/ServiceLib/Handler/Fmt/TuicFmt.cs | 107 +-
v2rayN/ServiceLib/Handler/Fmt/V2rayFmt.cs | 75 +-
v2rayN/ServiceLib/Handler/Fmt/VLESSFmt.cs | 99 +-
v2rayN/ServiceLib/Handler/Fmt/VmessFmt.cs | 219 +-
v2rayN/ServiceLib/Handler/Fmt/WireguardFmt.cs | 115 +-
v2rayN/ServiceLib/Handler/NoticeHandler.cs | 75 +-
v2rayN/ServiceLib/Handler/PacHandler.cs | 177 +-
v2rayN/ServiceLib/Handler/ProfileExHandler.cs | 287 +-
.../ServiceLib/Handler/StatisticsHandler.cs | 315 +-
.../Handler/SysProxy/ProxySettingLinux.cs | 49 +-
.../Handler/SysProxy/ProxySettingOSX.cs | 55 +-
.../Handler/SysProxy/ProxySettingWindows.cs | 679 ++--
.../Handler/SysProxy/SysProxyHandler.cs | 165 +-
v2rayN/ServiceLib/Handler/TaskHandler.cs | 165 +-
v2rayN/ServiceLib/Handler/WebDavHandler.cs | 315 +-
v2rayN/ServiceLib/Models/CheckUpdateModel.cs | 19 +-
.../ServiceLib/Models/ClashConnectionModel.cs | 31 +-
v2rayN/ServiceLib/Models/ClashConnections.cs | 67 +-
v2rayN/ServiceLib/Models/ClashProviders.cs | 25 +-
v2rayN/ServiceLib/Models/ClashProxies.cs | 41 +-
v2rayN/ServiceLib/Models/ClashProxyModel.cs | 23 +-
v2rayN/ServiceLib/Models/CmdItem.cs | 13 +-
v2rayN/ServiceLib/Models/ComboItem.cs | 25 +-
v2rayN/ServiceLib/Models/Config.cs | 101 +-
v2rayN/ServiceLib/Models/ConfigItems.cs | 477 ++-
v2rayN/ServiceLib/Models/CoreInfo.cs | 37 +-
v2rayN/ServiceLib/Models/DNSItem.cs | 33 +-
v2rayN/ServiceLib/Models/GitHubRelease.cs | 75 +-
v2rayN/ServiceLib/Models/IPAPIInfo.cs | 23 +-
v2rayN/ServiceLib/Models/ProfileExItem.cs | 23 +-
v2rayN/ServiceLib/Models/ProfileItem.cs | 180 +-
v2rayN/ServiceLib/Models/ProfileItemModel.cs | 33 +-
v2rayN/ServiceLib/Models/RetResult.cs | 47 +-
v2rayN/ServiceLib/Models/RoutingItem.cs | 39 +-
v2rayN/ServiceLib/Models/RoutingItemModel.cs | 13 +-
v2rayN/ServiceLib/Models/RoutingTemplate.cs | 15 +-
v2rayN/ServiceLib/Models/RulesItem.cs | 35 +-
v2rayN/ServiceLib/Models/RulesItemModel.cs | 19 +-
v2rayN/ServiceLib/Models/ServerSpeedItem.cs | 31 +-
v2rayN/ServiceLib/Models/ServerStatItem.cs | 27 +-
v2rayN/ServiceLib/Models/ServerTestItem.cs | 21 +-
v2rayN/ServiceLib/Models/SingboxConfig.cs | 509 ++-
v2rayN/ServiceLib/Models/SpeedTestResult.cs | 17 +-
v2rayN/ServiceLib/Models/SsSIP008.cs | 33 +-
v2rayN/ServiceLib/Models/SubItem.cs | 45 +-
v2rayN/ServiceLib/Models/V2rayConfig.cs | 865 ++--
v2rayN/ServiceLib/Models/V2rayMetricsVars.cs | 13 +-
v2rayN/ServiceLib/Models/V2rayTcpRequest.cs | 33 +-
v2rayN/ServiceLib/Models/VmessQRCode.cs | 55 +-
.../CoreConfig/CoreConfigClashService.cs | 459 ++-
.../CoreConfig/CoreConfigSingboxService.cs | 2677 ++++++------
.../CoreConfig/CoreConfigV2rayService.cs | 2455 ++++++-----
v2rayN/ServiceLib/Services/DownloadService.cs | 575 ++-
.../ServiceLib/Services/SpeedtestService.cs | 663 ++-
.../Statistics/StatisticsSingboxService.cs | 185 +-
.../Statistics/StatisticsXrayService.cs | 177 +-
v2rayN/ServiceLib/Services/UpdateService.cs | 1043 +++--
.../ViewModels/AddServer2ViewModel.cs | 207 +-
.../ViewModels/AddServerViewModel.cs | 151 +-
.../ViewModels/BackupAndRestoreViewModel.cs | 329 +-
.../ViewModels/CheckUpdateViewModel.cs | 551 ++-
.../ViewModels/ClashConnectionsViewModel.cs | 225 +-
.../ViewModels/ClashProxiesViewModel.cs | 745 ++--
.../ViewModels/DNSSettingViewModel.cs | 189 +-
.../GlobalHotkeySettingViewModel.cs | 91 +-
.../ViewModels/MainWindowViewModel.cs | 1129 +++--
v2rayN/ServiceLib/ViewModels/MsgViewModel.cs | 185 +-
.../ViewModels/OptionSettingViewModel.cs | 743 ++--
.../ViewModels/ProfilesViewModel.cs | 1461 ++++---
.../ViewModels/RoutingRuleDetailsViewModel.cs | 155 +-
.../ViewModels/RoutingRuleSettingViewModel.cs | 617 ++-
.../ViewModels/RoutingSettingViewModel.cs | 321 +-
.../ViewModels/StatusBarViewModel.cs | 969 +++--
.../ServiceLib/ViewModels/SubEditViewModel.cs | 87 +-
.../ViewModels/SubSettingViewModel.cs | 161 +-
.../Common/AppBuilderExtension.cs | 19 +-
v2rayN/v2rayN.Desktop/Common/AvaUtils.cs | 87 +-
v2rayN/v2rayN.Desktop/Common/UI.cs | 73 +-
.../Converters/DelayColorConverter.cs | 31 +-
.../v2rayN.Desktop/Handler/HotkeyHandler.cs | 137 +-
.../ViewModels/ThemeSettingViewModel.cs | 257 +-
.../Views/AddServer2Window.axaml.cs | 115 +-
.../Views/AddServerWindow.axaml.cs | 609 ++-
.../Views/BackupAndRestoreView.axaml.cs | 105 +-
.../Views/CheckUpdateView.axaml.cs | 67 +-
.../Views/ClashConnectionsView.axaml.cs | 89 +-
.../Views/ClashProxiesView.axaml.cs | 117 +-
.../Views/DNSSettingWindow.axaml.cs | 121 +-
.../Views/GlobalHotkeySettingWindow.axaml.cs | 201 +-
.../v2rayN.Desktop/Views/MainWindow.axaml.cs | 855 ++--
v2rayN/v2rayN.Desktop/Views/MsgView.axaml.cs | 121 +-
.../Views/OptionSettingWindow.axaml.cs | 439 +-
.../Views/ProfilesView.axaml.cs | 913 +++--
.../v2rayN.Desktop/Views/QrcodeView.axaml.cs | 59 +-
.../Views/RoutingRuleDetailsWindow.axaml.cs | 157 +-
.../Views/RoutingRuleSettingWindow.axaml.cs | 383 +-
.../Views/RoutingSettingWindow.axaml.cs | 241 +-
.../Views/StatusBarView.axaml.cs | 165 +-
.../Views/SubEditWindow.axaml.cs | 95 +-
.../Views/SubSettingWindow.axaml.cs | 171 +-
.../Views/ThemeSettingView.axaml.cs | 59 +-
v2rayN/v2rayN/App.xaml.cs | 111 +-
v2rayN/v2rayN/Base/MyDGTextColumn.cs | 13 +-
v2rayN/v2rayN/Common/QRCodeHelper.cs | 113 +-
v2rayN/v2rayN/Common/UI.cs | 93 +-
v2rayN/v2rayN/Common/WindowsUtils.cs | 173 +-
.../v2rayN/Converters/DelayColorConverter.cs | 37 +-
.../Converters/InverseBooleanConverter.cs | 31 +-
.../v2rayN/Converters/MaterialDesignFonts.cs | 35 +-
v2rayN/v2rayN/Handler/HotkeyHandler.cs | 337 +-
v2rayN/v2rayN/Handler/WindowsHandler.cs | 183 +-
.../ViewModels/ThemeSettingViewModel.cs | 331 +-
v2rayN/v2rayN/Views/AddServer2Window.xaml.cs | 97 +-
v2rayN/v2rayN/Views/AddServerWindow.xaml.cs | 597 ++-
.../v2rayN/Views/BackupAndRestoreView.xaml.cs | 73 +-
v2rayN/v2rayN/Views/CheckUpdateView.xaml.cs | 71 +-
.../v2rayN/Views/ClashConnectionsView.xaml.cs | 97 +-
v2rayN/v2rayN/Views/ClashProxiesView.xaml.cs | 127 +-
v2rayN/v2rayN/Views/DNSSettingWindow.xaml.cs | 125 +-
.../Views/GlobalHotkeySettingWindow.xaml.cs | 205 +-
v2rayN/v2rayN/Views/MainWindow.xaml.cs | 759 ++--
v2rayN/v2rayN/Views/MsgView.xaml.cs | 135 +-
.../v2rayN/Views/OptionSettingWindow.xaml.cs | 465 ++-
v2rayN/v2rayN/Views/ProfilesView.xaml.cs | 861 ++--
v2rayN/v2rayN/Views/QrcodeView.xaml.cs | 15 +-
.../Views/RoutingRuleDetailsWindow.xaml.cs | 151 +-
.../Views/RoutingRuleSettingWindow.xaml.cs | 353 +-
.../v2rayN/Views/RoutingSettingWindow.xaml.cs | 235 +-
v2rayN/v2rayN/Views/StatusBarView.xaml.cs | 191 +-
v2rayN/v2rayN/Views/SubEditWindow.xaml.cs | 91 +-
v2rayN/v2rayN/Views/SubSettingWindow.xaml | 10 +-
v2rayN/v2rayN/Views/SubSettingWindow.xaml.cs | 187 +-
v2rayN/v2rayN/Views/ThemeSettingView.xaml.cs | 65 +-
186 files changed, 23574 insertions(+), 23759 deletions(-)
diff --git a/v2rayN/AmazTool/Program.cs b/v2rayN/AmazTool/Program.cs
index 07f151cf..d71c25c2 100644
--- a/v2rayN/AmazTool/Program.cs
+++ b/v2rayN/AmazTool/Program.cs
@@ -1,26 +1,25 @@
-namespace AmazTool
+namespace AmazTool;
+
+internal static class Program
{
- internal static class Program
+ [STAThread]
+ private static void Main(string[] args)
{
- [STAThread]
- private static void Main(string[] args)
+ if (args.Length == 0)
{
- 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;
- }
-
- UpgradeApp.Upgrade(argData);
+ 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;
+ }
+
+ UpgradeApp.Upgrade(argData);
}
}
diff --git a/v2rayN/AmazTool/UpgradeApp.cs b/v2rayN/AmazTool/UpgradeApp.cs
index e1a76c3a..a4eb288c 100644
--- a/v2rayN/AmazTool/UpgradeApp.cs
+++ b/v2rayN/AmazTool/UpgradeApp.cs
@@ -2,116 +2,115 @@ using System.Diagnostics;
using System.IO.Compression;
using System.Text;
-namespace AmazTool
+namespace AmazTool;
+
+internal class UpgradeApp
{
- internal class UpgradeApp
+ public static void Upgrade(string fileName)
{
- public static void Upgrade(string fileName)
+ Console.WriteLine($"{Resx.Resource.StartUnzipping}\n{fileName}");
+
+ Utils.Waiting(5);
+
+ if (!File.Exists(fileName))
{
- Console.WriteLine($"{Resx.Resource.StartUnzipping}\n{fileName}");
+ Console.WriteLine(Resx.Resource.UpgradeFileNotFound);
+ return;
+ }
- Utils.Waiting(5);
-
- if (!File.Exists(fileName))
+ Console.WriteLine(Resx.Resource.TryTerminateProcess);
+ try
+ {
+ var existing = Process.GetProcessesByName(Utils.V2rayN);
+ foreach (var pp in existing)
{
- 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)))
{
- var path = pp.MainModule?.FileName ?? "";
- if (path.StartsWith(Utils.GetPath(Utils.V2rayN)))
- {
- pp?.Kill();
- pp?.WaitForExit(1000);
- }
+ 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);
- }
+ }
+ 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)
+ using var archive = ZipFile.OpenRead(fileName);
+ foreach (var entry in archive.Entries)
+ {
+ try
{
+ if (entry.Length == 0)
+ {
+ continue;
+ }
+
+ Console.WriteLine(entry.FullName);
+
+ 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);
+ }
+
+ 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;
+ }
+
try
{
- if (entry.Length == 0)
- {
- continue;
- }
-
- Console.WriteLine(entry.FullName);
-
- 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);
- }
-
- 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;
- }
-
- try
- {
- entry.ExtractToFile(entryOutputPath, true);
- }
- catch
- {
- Thread.Sleep(1000);
- entry.ExtractToFile(entryOutputPath, true);
- }
-
- Console.WriteLine(entryOutputPath);
+ entry.ExtractToFile(entryOutputPath, true);
}
- catch (Exception ex)
+ catch
{
- sb.Append(ex.StackTrace);
+ Thread.Sleep(1000);
+ 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(Resx.Resource.Restartv2rayN);
- Utils.Waiting(2);
-
- Utils.StartV2RayN();
}
+ 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);
+
+ Utils.StartV2RayN();
}
}
diff --git a/v2rayN/AmazTool/Utils.cs b/v2rayN/AmazTool/Utils.cs
index d206f898..df13ecf6 100644
--- a/v2rayN/AmazTool/Utils.cs
+++ b/v2rayN/AmazTool/Utils.cs
@@ -1,52 +1,51 @@
using System.Diagnostics;
-namespace AmazTool
+namespace AmazTool;
+
+internal class Utils
{
- internal class Utils
+ public static string GetExePath()
{
- public static string GetExePath()
- {
- return Environment.ProcessPath ?? Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty;
- }
+ 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)
+ public static string GetPath(string fileName)
+ {
+ var startupPath = StartupPath();
+ if (string.IsNullOrEmpty(fileName))
{
- var startupPath = StartupPath();
- if (string.IsNullOrEmpty(fileName))
+ return startupPath;
+ }
+ return Path.Combine(startupPath, fileName);
+ }
+
+ public static string V2rayN => "v2rayN";
+
+ public static void StartV2RayN()
+ {
+ Process process = new()
+ {
+ StartInfo = new()
{
- return startupPath;
+ UseShellExecute = true,
+ FileName = V2rayN,
+ WorkingDirectory = StartupPath()
}
- return Path.Combine(startupPath, fileName);
- }
+ };
+ process.Start();
+ }
- public static string V2rayN => "v2rayN";
-
- public static void StartV2RayN()
+ public static void Waiting(int second)
+ {
+ for (var i = second; i > 0; i--)
{
- 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);
- }
+ Console.WriteLine(i);
+ Thread.Sleep(1000);
}
}
}
diff --git a/v2rayN/Directory.Build.props b/v2rayN/Directory.Build.props
index 4a689310..3ad760a3 100644
--- a/v2rayN/Directory.Build.props
+++ b/v2rayN/Directory.Build.props
@@ -8,7 +8,7 @@
net8.0
true
true
- CA1031;CS1591;NU1507;CA1416
+ CA1031;CS1591;NU1507;CA1416;IDE0058
annotations
enable
2dust
diff --git a/v2rayN/ServiceLib/Base/MyReactiveObject.cs b/v2rayN/ServiceLib/Base/MyReactiveObject.cs
index 0049429d..0172faad 100644
--- a/v2rayN/ServiceLib/Base/MyReactiveObject.cs
+++ b/v2rayN/ServiceLib/Base/MyReactiveObject.cs
@@ -1,10 +1,9 @@
-using ReactiveUI;
+using ReactiveUI;
-namespace ServiceLib.Base
+namespace ServiceLib.Base;
+
+public class MyReactiveObject : ReactiveObject
{
- public class MyReactiveObject : ReactiveObject
- {
- protected static Config? _config;
- protected Func>? _updateView;
- }
-}
\ No newline at end of file
+ protected static Config? _config;
+ protected Func>? _updateView;
+}
diff --git a/v2rayN/ServiceLib/Common/AesUtils.cs b/v2rayN/ServiceLib/Common/AesUtils.cs
index dcd4ac2a..c32c3bff 100644
--- a/v2rayN/ServiceLib/Common/AesUtils.cs
+++ b/v2rayN/ServiceLib/Common/AesUtils.cs
@@ -1,101 +1,100 @@
using System.Security.Cryptography;
using System.Text;
-namespace ServiceLib.Common
+namespace ServiceLib.Common;
+
+public class 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)
{
- 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");
+ 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)
+ 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 ms = new MemoryStream();
+ ms.Write(iv, 0, iv.Length);
+
+ using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
- if (string.IsNullOrEmpty(text))
- return string.Empty;
-
- 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 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();
- }
-
- var cipherTextWithIv = ms.ToArray();
- return Convert.ToBase64String(cipherTextWithIv);
+ cs.Write(plaintext, 0, plaintext.Length);
+ cs.FlushFinalBlock();
}
- ///
- /// 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 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);
-
- 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();
- }
-
- var plainText = ms.ToArray();
- return Encoding.UTF8.GetString(plainText);
- }
-
- 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);
- }
-
- private static byte[] GenerateIv()
- {
- var randomNumber = new byte[IvSize];
-
- using var rng = RandomNumberGenerator.Create();
- rng.GetBytes(randomNumber);
- return randomNumber;
- }
+ var cipherTextWithIv = ms.ToArray();
+ return Convert.ToBase64String(cipherTextWithIv);
}
-}
\ No newline at end of file
+
+ ///
+ /// 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 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);
+
+ 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();
+ }
+
+ var plainText = ms.ToArray();
+ return Encoding.UTF8.GetString(plainText);
+ }
+
+ 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);
+ }
+
+ private static byte[] GenerateIv()
+ {
+ var randomNumber = new byte[IvSize];
+
+ 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..aae02206 100644
--- a/v2rayN/ServiceLib/Common/DesUtils.cs
+++ b/v2rayN/ServiceLib/Common/DesUtils.cs
@@ -1,75 +1,74 @@
using System.Security.Cryptography;
using System.Text;
-namespace ServiceLib.Common
+namespace ServiceLib.Common;
+
+public class DesUtils
{
- public class DesUtils
+ ///
+ /// Encrypt
+ ///
+ ///
+ /// ///
+ ///
+ public static string Encrypt(string? text, string? key = null)
{
- ///
- /// Encrypt
- ///
- ///
- /// ///
- ///
- public static string Encrypt(string? text, string? key = null)
+ if (text.IsNullOrEmpty())
{
- 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);
-
- 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.");
- }
-
- 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");
+ 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);
}
-}
\ No newline at end of file
+
+ ///
+ /// 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());
+ }
+
+ 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));
+ }
+
+ 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 03dcf8e3..0c4cde0c 100644
--- a/v2rayN/ServiceLib/Common/DownloaderHelper.cs
+++ b/v2rayN/ServiceLib/Common/DownloaderHelper.cs
@@ -1,181 +1,180 @@
using System.Net;
using Downloader;
-namespace ServiceLib.Common
+namespace ServiceLib.Common;
+
+public class DownloaderHelper
{
- 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)
{
- 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 (url.IsNullOrEmpty())
{
- if (url.IsNullOrEmpty())
- {
- return null;
- }
+ return null;
+ }
- Uri uri = new(url);
- //Authorization Header
- var headers = new WebHeaderCollection();
- if (uri.UserInfo.IsNotEmpty())
- {
- headers.Add(HttpRequestHeader.Authorization, "Basic " + Utils.Base64Encode(uri.UserInfo));
- }
+ Uri uri = new(url);
+ //Authorization Header
+ var headers = new WebHeaderCollection();
+ if (uri.UserInfo.IsNotEmpty())
+ {
+ headers.Add(HttpRequestHeader.Authorization, "Basic " + Utils.Base64Encode(uri.UserInfo));
+ }
- var downloadOpt = new DownloadConfiguration()
- {
- Timeout = timeout * 1000,
- MaxTryAgainOnFailover = 2,
- RequestConfiguration =
+ 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) =>
+ await using var downloader = new Downloader.DownloadService(downloadOpt);
+ downloader.DownloadFileCompleted += (sender, value) =>
+ {
+ if (value.Error != null)
{
- 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);
+
+ downloadOpt = null;
+
+ return await reader.ReadToEndAsync(cts.Token);
+ }
+
+ public async Task DownloadDataAsync4Speed(IWebProxy webProxy, string url, IProgress progress, int timeout)
+ {
+ if (url.IsNullOrEmpty())
+ {
+ throw new ArgumentNullException(nameof(url));
+ }
+
+ 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);
+
+ downloadOpt = null;
+ }
+
+ public async Task DownloadFileAsync(IWebProxy? webProxy, string url, string fileName, IProgress progress, int timeout)
+ {
+ if (url.IsNullOrEmpty())
+ {
+ throw new ArgumentNullException(nameof(url));
+ }
+ if (fileName.IsNullOrEmpty())
+ {
+ 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 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 using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token);
- using StreamReader reader = new(stream);
-
- downloadOpt = null;
-
- return await reader.ReadToEndAsync(cts.Token);
- }
-
- public async Task DownloadDataAsync4Speed(IWebProxy webProxy, string url, IProgress progress, int timeout)
- {
- if (url.IsNullOrEmpty())
- {
- throw new ArgumentNullException(nameof(url));
}
+ };
- var downloadOpt = new DownloadConfiguration()
- {
- Timeout = timeout * 1000,
- MaxTryAgainOnFailover = 2,
- RequestConfiguration =
- {
- Timeout= timeout * 1000,
- Proxy = webProxy
- }
- };
+ using var cts = new CancellationTokenSource();
+ await downloader.DownloadFileTaskAsync(url, fileName, 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;
- }
-
- public async Task DownloadFileAsync(IWebProxy? webProxy, string url, string fileName, IProgress progress, int timeout)
- {
- if (url.IsNullOrEmpty())
- {
- throw new ArgumentNullException(nameof(url));
- }
- if (fileName.IsNullOrEmpty())
- {
- 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 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);
-
- downloadOpt = null;
- }
+ downloadOpt = null;
}
}
diff --git a/v2rayN/ServiceLib/Common/FileManager.cs b/v2rayN/ServiceLib/Common/FileManager.cs
index 2f452899..d988c702 100644
--- a/v2rayN/ServiceLib/Common/FileManager.cs
+++ b/v2rayN/ServiceLib/Common/FileManager.cs
@@ -2,226 +2,225 @@ using System.Formats.Tar;
using System.IO.Compression;
using System.Text;
-namespace ServiceLib.Common
-{
- public static class FileManager
- {
- private static readonly string _tag = "FileManager";
+namespace ServiceLib.Common;
- public static bool ByteArrayToFile(string fileName, byte[] content)
+public static class FileManager
+{
+ private static readonly string _tag = "FileManager";
+
+ public static bool ByteArrayToFile(string fileName, byte[] content)
+ {
+ try
{
- 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, 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 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;
+ }
+ }
+
+ public static bool ZipExtractToFile(string fileName, string toPath, string ignoredName)
+ {
+ try
+ {
+ using var archive = ZipFile.OpenRead(fileName);
+ foreach (var entry in archive.Entries)
{
- File.WriteAllBytes(fileName, content);
- return true;
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
+ if (entry.Length == 0)
+ {
+ continue;
+ }
+ try
+ {
+ if (ignoredName.IsNotEmpty() && 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 void DecompressFile(string fileName, byte[] content)
+ public static List? GetFilesFromZip(string fileName)
+ {
+ if (!File.Exists(fileName))
{
- try
+ 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))
{
- 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);
+ File.Delete(destinationArchiveFileName);
}
+
+ 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);
+
+ // Check if the source directory exists
+ if (!dir.Exists)
+ {
+ throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}");
}
- public static void DecompressFile(string fileName, string toPath, string? toName)
+ // Cache directories before we start copying
+ var dirs = dir.GetDirectories();
+
+ // 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())
{
- try
+ if (ignoredName.IsNotEmpty() && file.Name.Contains(ignoredName))
{
- 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);
+ continue;
}
- catch (Exception ex)
+ if (file.Extension == file.Name)
{
- Logging.SaveLog(_tag, ex);
+ continue;
}
+ var targetFilePath = Path.Combine(destinationDir, file.Name);
+ if (!overwrite && File.Exists(targetFilePath))
+ {
+ continue;
+ }
+ _ = file.CopyTo(targetFilePath, overwrite);
}
- public static void DecompressTarFile(string fileName, string toPath)
+ // If recursive and copying subdirectories, recursively call this method
+ if (recursive)
{
- try
+ foreach (var subDir in dirs)
{
- 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);
- }
-
- 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 (ignoredName.IsNotEmpty() && 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 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;
- }
-
- 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}");
- }
-
- // Cache directories before we start copying
- var dirs = dir.GetDirectories();
-
- // 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 (ignoredName.IsNotEmpty() && 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);
- }
- }
- }
-
- 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
+ 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
+ }
+ }
}
diff --git a/v2rayN/ServiceLib/Common/HttpClientHelper.cs b/v2rayN/ServiceLib/Common/HttpClientHelper.cs
index f532062e..8bc1384a 100644
--- a/v2rayN/ServiceLib/Common/HttpClientHelper.cs
+++ b/v2rayN/ServiceLib/Common/HttpClientHelper.cs
@@ -2,205 +2,204 @@ using System.Net.Http.Headers;
using System.Net.Mime;
using System.Text;
-namespace ServiceLib.Common
+namespace ServiceLib.Common;
+
+///
+///
+public class HttpClientHelper
{
- ///
- ///
- public class HttpClientHelper
+ private static readonly Lazy _instance = new(() =>
{
- private static readonly Lazy _instance = new(() =>
- {
- SocketsHttpHandler handler = new() { UseCookies = false };
- HttpClientHelper helper = new(new HttpClient(handler));
- return helper;
- });
+ 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)
+ private HttpClientHelper(HttpClient httpClient)
+ {
+ this.httpClient = httpClient;
+ }
+
+ public async Task TryGetAsync(string url)
+ {
+ if (url.IsNullOrEmpty())
{
- this.httpClient = httpClient;
+ return null;
}
- public async Task TryGetAsync(string url)
+ try
{
- if (url.IsNullOrEmpty())
- {
- return null;
- }
+ 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 (url.IsNullOrEmpty())
+ {
+ return null;
+ }
+ return await httpClient.GetStringAsync(url);
+ }
+
+ public async Task GetAsync(HttpClient client, string url, CancellationToken token = default)
+ {
+ if (url.IsNullOrEmpty())
+ {
+ 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);
+
+ await httpClient.PutAsync(url, content);
+ }
+
+ public async Task PatchAsync(string url, Dictionary headers)
+ {
+ var myContent = JsonUtils.Serialize(headers);
+ var buffer = Encoding.UTF8.GetBytes(myContent);
+ var byteContent = new ByteArrayContent(buffer);
+ byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
+
+ await httpClient.PatchAsync(url, byteContent);
+ }
+
+ 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 async Task GetAsync(string url)
+ using var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
+
+ if (!response.IsSuccessStatusCode)
{
- if (url.IsNullOrEmpty())
- {
- return null;
- }
- return await httpClient.GetStringAsync(url);
+ throw new Exception(response.StatusCode.ToString());
}
- public async Task GetAsync(HttpClient client, string url, CancellationToken token = default)
+ 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;
+
+ while (true)
{
- if (url.IsNullOrEmpty())
+ token.ThrowIfCancellationRequested();
+
+ var read = await stream.ReadAsync(buffer, token);
+ totalRead += read;
+
+ if (read == 0)
{
- return null;
+ break;
}
- return await client.GetStringAsync(url, token);
- }
+ await file.WriteAsync(buffer.AsMemory(0, read), token);
- public async Task PutAsync(string url, Dictionary headers)
- {
- var jsonContent = JsonUtils.Serialize(headers);
- var content = new StringContent(jsonContent, Encoding.UTF8, MediaTypeNames.Application.Json);
-
- await httpClient.PutAsync(url, content);
- }
-
- public async Task PatchAsync(string url, Dictionary headers)
- {
- var myContent = JsonUtils.Serialize(headers);
- var buffer = Encoding.UTF8.GetBytes(myContent);
- var byteContent = new ByteArrayContent(buffer);
- byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
-
- await httpClient.PatchAsync(url, byteContent);
- }
-
- 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);
- }
-
- using var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
-
- if (!response.IsSuccessStatusCode)
- {
- throw new Exception(response.StatusCode.ToString());
- }
-
- 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;
-
- while (true)
- {
- token.ThrowIfCancellationRequested();
-
- var read = await stream.ReadAsync(buffer, token);
- totalRead += read;
-
- 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);
+ var percent = (int)(100.0 * totalRead / total);
+ //if (progressPercentage != percent && percent % 10 == 0)
+ {
+ progressPercentage = percent;
+ progress?.Report(percent);
+ }
}
}
-
- public async Task DownloadDataAsync4Speed(HttpClient client, string url, IProgress progress, CancellationToken token = default)
+ if (canReportProgress)
{
- if (url.IsNullOrEmpty())
+ progress?.Report(101);
+ }
+ }
+
+ public async Task DownloadDataAsync4Speed(HttpClient client, string url, IProgress progress, CancellationToken token = default)
+ {
+ if (url.IsNullOrEmpty())
+ {
+ throw new ArgumentNullException(nameof(url));
+ }
+
+ var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
+
+ 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;
+
+ 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)
{
- throw new ArgumentNullException(nameof(url));
- }
-
- var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
-
- 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;
-
- 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)
{
- if (totalRead > 0)
- {
- return;
- }
- else
- {
- token.ThrowIfCancellationRequested();
- }
- }
-
- var read = await stream.ReadAsync(buffer, token);
-
- if (read == 0)
- {
- isMoreToRead = false;
+ return;
}
else
{
- var data = new byte[read];
- buffer.ToList().CopyTo(0, data, 0, read);
+ token.ThrowIfCancellationRequested();
+ }
+ }
- totalRead += read;
+ var read = await stream.ReadAsync(buffer, token);
- var ts = DateTime.Now - totalDatetime;
- if (progress != null && ts.Seconds > totalSecond)
+ if (read == 0)
+ {
+ isMoreToRead = false;
+ }
+ else
+ {
+ var data = new byte[read];
+ buffer.ToList().CopyTo(0, data, 0, 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)
{
- totalSecond = ts.Seconds;
- var speed = (totalRead * 1d / ts.TotalMilliseconds / 1000).ToString("#0.0");
- if (progressSpeed != speed)
- {
- progressSpeed = speed;
- progress.Report(speed);
- }
+ progressSpeed = speed;
+ progress.Report(speed);
}
}
- } while (isMoreToRead);
- }
+ }
+ } while (isMoreToRead);
}
}
diff --git a/v2rayN/ServiceLib/Common/Job.cs b/v2rayN/ServiceLib/Common/Job.cs
index fdbc8dbf..fe968d2d 100644
--- a/v2rayN/ServiceLib/Common/Job.cs
+++ b/v2rayN/ServiceLib/Common/Job.cs
@@ -1,8 +1,7 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
-namespace ServiceLib.Common
-{
+namespace ServiceLib.Common;
/*
* See:
* http://stackoverflow.com/questions/6266820/working-example-of-createjobobject-setinformationjobobject-pinvoke-in-net
@@ -178,4 +177,4 @@ namespace ServiceLib.Common
}
#endregion Helper classes
-}
+
diff --git a/v2rayN/ServiceLib/Common/JsonUtils.cs b/v2rayN/ServiceLib/Common/JsonUtils.cs
index 7d427f74..9ffa00ca 100644
--- a/v2rayN/ServiceLib/Common/JsonUtils.cs
+++ b/v2rayN/ServiceLib/Common/JsonUtils.cs
@@ -1,131 +1,130 @@
-using System.Text.Json;
+using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
-namespace ServiceLib.Common
+namespace ServiceLib.Common;
+
+public class JsonUtils
{
- public class JsonUtils
+ private static readonly string _tag = "JsonUtils";
+
+ ///
+ /// DeepCopy
+ ///
+ ///
+ ///
+ ///
+ public static T DeepCopy(T obj)
{
- private static readonly string _tag = "JsonUtils";
+ return Deserialize(Serialize(obj, false))!;
+ }
- ///
- /// DeepCopy
- ///
- ///
- ///
- ///
- public static T DeepCopy(T obj)
+ ///
+ /// Deserialize to object
+ ///
+ ///
+ ///
+ ///
+ public static T? Deserialize(string? strJson)
+ {
+ try
{
- 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
+ if (string.IsNullOrWhiteSpace(strJson))
{
return default;
}
+ var options = new JsonSerializerOptions
+ {
+ PropertyNameCaseInsensitive = true
+ };
+ return JsonSerializer.Deserialize(strJson, options);
}
-
- ///
- /// parse
- ///
- ///
- ///
- public static JsonNode? ParseJson(string strJson)
+ catch
{
- try
+ return default;
+ }
+ }
+
+ ///
+ /// parse
+ ///
+ ///
+ ///
+ public static JsonNode? ParseJson(string strJson)
+ {
+ try
+ {
+ if (string.IsNullOrWhiteSpace(strJson))
{
- if (string.IsNullOrWhiteSpace(strJson))
- {
- return null;
- }
- return JsonNode.Parse(strJson);
- }
- catch
- {
- //SaveLog(ex.Message, ex);
return null;
}
+ return JsonNode.Parse(strJson);
}
-
- ///
- /// Serialize Object to Json string
- ///
- ///
- ///
- ///
- ///
- public static string Serialize(object? obj, bool indented = true, bool nullValue = false)
+ catch
{
- 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;
+ //SaveLog(ex.Message, ex);
+ return null;
}
-
- ///
- /// 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
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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 7f7089b7..fdd49f5c 100644
--- a/v2rayN/ServiceLib/Common/Logging.cs
+++ b/v2rayN/ServiceLib/Common/Logging.cs
@@ -2,53 +2,54 @@ using NLog;
using NLog.Config;
using NLog.Targets;
-namespace ServiceLib.Common
+namespace ServiceLib.Common;
+
+public class Logging
{
- public class Logging
+ private static readonly Logger _logger1 = LogManager.GetLogger("Log1");
+ private static readonly Logger _logger2 = LogManager.GetLogger("Log2");
+
+ public static void Setup()
{
- 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)
{
- 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;
+ LogManager.SuspendLogging();
+ }
+ }
+
+ public static void SaveLog(string strContent)
+ {
+ if (!LogManager.IsLoggingEnabled())
+ {
+ return;
}
- public static void LoggingEnabled(bool enable)
+ _logger1.Info(strContent);
+ }
+
+ public static void SaveLog(string strTitle, Exception ex)
+ {
+ if (!LogManager.IsLoggingEnabled())
{
- if (!enable)
- {
- LogManager.SuspendLogging();
- }
+ return;
}
- public static void SaveLog(string strContent)
+ _logger2.Debug($"{strTitle},{ex.Message}");
+ _logger2.Debug(ex.StackTrace);
+ if (ex?.InnerException != null)
{
- if (!LogManager.IsLoggingEnabled())
- {
- return;
- }
-
- LogManager.GetLogger("Log1").Info(strContent);
- }
-
- 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);
- }
+ _logger2.Error(ex.InnerException);
}
}
}
diff --git a/v2rayN/ServiceLib/Common/QRCodeHelper.cs b/v2rayN/ServiceLib/Common/QRCodeHelper.cs
index 5cd5ac25..9938eadd 100644
--- a/v2rayN/ServiceLib/Common/QRCodeHelper.cs
+++ b/v2rayN/ServiceLib/Common/QRCodeHelper.cs
@@ -1,90 +1,89 @@
-using QRCoder;
+using QRCoder;
using SkiaSharp;
using ZXing.SkiaSharp;
-namespace ServiceLib.Common
+namespace ServiceLib.Common;
+
+public class QRCodeHelper
{
- public class QRCodeHelper
+ public static byte[]? GenQRCode(string? url)
{
- 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;
- }
-
- try
- {
- var image = SKImage.FromEncodedData(fileName);
- var bitmap = SKBitmap.FromImage(image);
-
- return ReaderBarcode(bitmap);
- }
- catch
- {
- // ignored
- }
-
- 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
- }
-
- return null;
- }
-
- private static string? ReaderBarcode(SKBitmap? bitmap)
- {
- var reader = new BarcodeReader();
- var result = reader.Decode(bitmap);
-
- if (result != null && result.Text.IsNotEmpty())
- {
- return result.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);
-
- // 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;
- }
+ using QRCodeGenerator qrGenerator = new();
+ using var qrCodeData = qrGenerator.CreateQrCode(url ?? string.Empty, QRCodeGenerator.ECCLevel.Q);
+ using PngByteQRCode qrCode = new(qrCodeData);
+ return qrCode.GetGraphic(20);
}
-}
\ No newline at end of file
+
+ 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);
+
+ return ReaderBarcode(bitmap);
+ }
+ catch
+ {
+ // ignored
+ }
+
+ 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
+ }
+
+ return null;
+ }
+
+ private static string? ReaderBarcode(SKBitmap? bitmap)
+ {
+ var reader = new BarcodeReader();
+ var result = reader.Decode(bitmap);
+
+ if (result != null && result.Text.IsNotEmpty())
+ {
+ return result.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);
+
+ // 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;
+ }
+}
diff --git a/v2rayN/ServiceLib/Common/SemanticVersion.cs b/v2rayN/ServiceLib/Common/SemanticVersion.cs
index 5bfc9692..64167084 100644
--- a/v2rayN/ServiceLib/Common/SemanticVersion.cs
+++ b/v2rayN/ServiceLib/Common/SemanticVersion.cs
@@ -1,187 +1,186 @@
-namespace ServiceLib.Common
+namespace ServiceLib.Common;
+
+public class SemanticVersion
{
- public class SemanticVersion
+ private readonly int major;
+ private readonly int minor;
+ private readonly int patch;
+ private readonly string version;
+
+ public SemanticVersion(int major, int minor, int patch)
{
- private readonly int major;
- private readonly int minor;
- private readonly int patch;
- private readonly string version;
+ this.major = major;
+ this.minor = minor;
+ this.patch = patch;
+ version = $"{major}.{minor}.{patch}";
+ }
- public SemanticVersion(int major, int minor, int patch)
+ public SemanticVersion(string? version)
+ {
+ try
{
- this.major = major;
- this.minor = minor;
- this.patch = patch;
- version = $"{major}.{minor}.{patch}";
- }
-
- public SemanticVersion(string? version)
- {
- try
- {
- if (string.IsNullOrEmpty(version))
- {
- major = 0;
- minor = 0;
- patch = 0;
- return;
- }
- this.version = version.RemovePrefix('v');
-
- var parts = this.version.Split('.');
- if (parts.Length == 2)
- {
- major = int.Parse(parts.First());
- minor = int.Parse(parts.Last());
- patch = 0;
- }
- else if (parts.Length is 3 or 4)
- {
- major = int.Parse(parts[0]);
- minor = int.Parse(parts[1]);
- patch = int.Parse(parts[2]);
- }
- else
- {
- throw new ArgumentException("Invalid version string");
- }
- }
- catch
+ if (string.IsNullOrEmpty(version))
{
major = 0;
minor = 0;
patch = 0;
+ return;
}
- }
+ this.version = version.RemovePrefix('v');
- public override bool Equals(object? obj)
- {
- if (obj is SemanticVersion other)
+ var parts = this.version.Split('.');
+ if (parts.Length == 2)
{
- return major == other.major && minor == other.minor && patch == other.patch;
+ major = int.Parse(parts.First());
+ minor = int.Parse(parts.Last());
+ patch = 0;
+ }
+ else if (parts.Length is 3 or 4)
+ {
+ major = int.Parse(parts[0]);
+ minor = int.Parse(parts[1]);
+ patch = int.Parse(parts[2]);
}
else
{
- return false;
+ throw new ArgumentException("Invalid version string");
}
}
-
- public override int GetHashCode()
+ catch
{
- return major.GetHashCode() ^ minor.GetHashCode() ^ patch.GetHashCode();
+ major = 0;
+ minor = 0;
+ patch = 0;
}
+ }
- ///
- /// Use ToVersionString(string? prefix) instead if possible.
- ///
- /// major.minor.patch
- public override string ToString()
+ public override bool Equals(object? obj)
+ {
+ if (obj is SemanticVersion other)
+ {
+ return major == other.major && minor == other.minor && patch == other.patch;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ return major.GetHashCode() ^ minor.GetHashCode() ^ patch.GetHashCode();
+ }
+
+ ///
+ /// Use ToVersionString(string? prefix) instead if possible.
+ ///
+ /// major.minor.patch
+ public override string ToString()
+ {
+ return version;
+ }
+
+ public string ToVersionString(string? prefix = null)
+ {
+ if (prefix == null)
{
return version;
}
-
- public string ToVersionString(string? prefix = null)
+ else
{
- if (prefix == null)
- {
- return version;
- }
- else
- {
- return $"{prefix}{version}";
- }
+ return $"{prefix}{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.GreaterEquals(v2); }
-
- public static bool operator <=(SemanticVersion v1, SemanticVersion v2)
- { return v1.LessEquals(v2); }
-
- #region Private
-
- private bool GreaterEquals(SemanticVersion other)
- {
- if (major < other.major)
- {
- return false;
- }
- else if (major > other.major)
- {
- return true;
- }
- else
- {
- if (minor < other.minor)
- {
- return false;
- }
- else if (minor > other.minor)
- {
- return true;
- }
- else
- {
- if (patch < other.patch)
- {
- return false;
- }
- else if (patch > other.patch)
- {
- return true;
- }
- else
- {
- return true;
- }
- }
- }
- }
-
- private bool LessEquals(SemanticVersion other)
- {
- if (major < other.major)
- {
- return true;
- }
- else if (major > other.major)
- {
- return false;
- }
- else
- {
- if (minor < other.minor)
- {
- return true;
- }
- else if (minor > other.minor)
- {
- return false;
- }
- else
- {
- if (patch < other.patch)
- {
- return true;
- }
- else if (patch > other.patch)
- {
- return false;
- }
- else
- {
- return true;
- }
- }
- }
- }
-
- #endregion Private
}
+
+ 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.LessEquals(v2); }
+
+ #region Private
+
+ private bool GreaterEquals(SemanticVersion other)
+ {
+ if (major < other.major)
+ {
+ return false;
+ }
+ else if (major > other.major)
+ {
+ return true;
+ }
+ else
+ {
+ if (minor < other.minor)
+ {
+ return false;
+ }
+ else if (minor > other.minor)
+ {
+ return true;
+ }
+ else
+ {
+ if (patch < other.patch)
+ {
+ return false;
+ }
+ else if (patch > other.patch)
+ {
+ return true;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ private bool LessEquals(SemanticVersion other)
+ {
+ if (major < other.major)
+ {
+ return true;
+ }
+ else if (major > other.major)
+ {
+ return false;
+ }
+ else
+ {
+ if (minor < other.minor)
+ {
+ return true;
+ }
+ else if (minor > other.minor)
+ {
+ return false;
+ }
+ else
+ {
+ if (patch < other.patch)
+ {
+ return true;
+ }
+ else if (patch > other.patch)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ #endregion Private
}
diff --git a/v2rayN/ServiceLib/Common/SqliteHelper.cs b/v2rayN/ServiceLib/Common/SqliteHelper.cs
index dca10c57..62b0a830 100644
--- a/v2rayN/ServiceLib/Common/SqliteHelper.cs
+++ b/v2rayN/ServiceLib/Common/SqliteHelper.cs
@@ -1,91 +1,90 @@
using System.Collections;
using SQLite;
-namespace ServiceLib.Common
+namespace ServiceLib.Common;
+
+public sealed class SQLiteHelper
{
- public sealed class SQLiteHelper
+ private static readonly Lazy _instance = new(() => new());
+ public static SQLiteHelper Instance => _instance.Value;
+ private readonly string _connstr;
+ private SQLiteConnection _db;
+ private SQLiteAsyncConnection _dbAsync;
+ private readonly string _configDB = "guiNDB.db";
+
+ public SQLiteHelper()
{
- private static readonly Lazy _instance = new(() => new());
- public static SQLiteHelper Instance => _instance.Value;
- private readonly string _connstr;
- private SQLiteConnection _db;
- private SQLiteAsyncConnection _dbAsync;
- private readonly string _configDB = "guiNDB.db";
+ _connstr = Utils.GetConfigPath(_configDB);
+ _db = new SQLiteConnection(_connstr, false);
+ _dbAsync = new SQLiteAsyncConnection(_connstr, false);
+ }
- public SQLiteHelper()
+ public CreateTableResult CreateTable()
+ {
+ return _db.CreateTable();
+ }
+
+ 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 ReplaceAsync(object model)
+ {
+ return await _dbAsync.InsertOrReplaceAsync(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 DeleteAsync(object model)
+ {
+ return await _dbAsync.DeleteAsync(model);
+ }
+
+ public async Task DeleteAllAsync()
+ {
+ return await _dbAsync.DeleteAllAsync();
+ }
+
+ 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 AsyncTableQuery TableAsync() where T : new()
+ {
+ return _dbAsync.Table();
+ }
+
+ public async Task DisposeDbConnectionAsync()
+ {
+ await Task.Factory.StartNew(() =>
{
- _connstr = Utils.GetConfigPath(_configDB);
- _db = new SQLiteConnection(_connstr, false);
- _dbAsync = new SQLiteAsyncConnection(_connstr, false);
- }
+ _db?.Close();
+ _db?.Dispose();
+ _db = null;
- public CreateTableResult CreateTable()
- {
- return _db.CreateTable();
- }
-
- 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 ReplaceAsync(object model)
- {
- return await _dbAsync.InsertOrReplaceAsync(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 DeleteAsync(object model)
- {
- return await _dbAsync.DeleteAsync(model);
- }
-
- public async Task DeleteAllAsync()
- {
- return await _dbAsync.DeleteAllAsync();
- }
-
- 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 AsyncTableQuery TableAsync() where T : new()
- {
- return _dbAsync.Table();
- }
-
- public async Task DisposeDbConnectionAsync()
- {
- await Task.Factory.StartNew(() =>
- {
- _db?.Close();
- _db?.Dispose();
- _db = null;
-
- _dbAsync?.GetConnection()?.Close();
- _dbAsync?.GetConnection()?.Dispose();
- _dbAsync = null;
- });
- }
+ _dbAsync?.GetConnection()?.Close();
+ _dbAsync?.GetConnection()?.Dispose();
+ _dbAsync = null;
+ });
}
}
diff --git a/v2rayN/ServiceLib/Common/StringEx.cs b/v2rayN/ServiceLib/Common/StringEx.cs
index ab5b808a..1b880b74 100644
--- a/v2rayN/ServiceLib/Common/StringEx.cs
+++ b/v2rayN/ServiceLib/Common/StringEx.cs
@@ -1,83 +1,82 @@
using System.Diagnostics.CodeAnalysis;
-namespace ServiceLib.Common
+namespace ServiceLib.Common;
+
+public static class StringEx
{
- public static class StringEx
+ public static bool IsNullOrEmpty([NotNullWhen(false)] this string? value)
{
- public static bool IsNullOrEmpty([NotNullWhen(false)] this string? value)
- {
- return string.IsNullOrEmpty(value) || string.IsNullOrWhiteSpace(value);
- }
+ return string.IsNullOrEmpty(value) || string.IsNullOrWhiteSpace(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)
+ public static bool BeginWithAny(this string s, IEnumerable chars)
+ {
+ if (s.IsNullOrEmpty())
{
- if (s.IsNullOrEmpty())
+ return false;
+ }
+ return chars.Contains(s.First());
+ }
+
+ 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())
{
- return false;
+ continue;
}
- return chars.Contains(s.First());
- }
-
- 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 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, string prefix)
- {
- return value.StartsWith(prefix) ? value[prefix.Length..] : value;
- }
-
- public static string UpperFirstChar(this string value)
- {
- if (string.IsNullOrEmpty(value))
- {
- return string.Empty;
- }
-
- return char.ToUpper(value.First()) + value[1..];
- }
-
- public static string AppendQuotes(this string value)
- {
- return string.IsNullOrEmpty(value) ? string.Empty : $"\"{value}\"";
- }
-
- public static int ToInt(this string? value, int defaultValue = 0)
- {
- return int.TryParse(value, out var result) ? result : defaultValue;
+ yield return line;
}
}
+
+ 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, string prefix)
+ {
+ return value.StartsWith(prefix) ? value[prefix.Length..] : value;
+ }
+
+ public static string UpperFirstChar(this string value)
+ {
+ if (string.IsNullOrEmpty(value))
+ {
+ return string.Empty;
+ }
+
+ return char.ToUpper(value.First()) + value[1..];
+ }
+
+ public static string AppendQuotes(this string value)
+ {
+ return string.IsNullOrEmpty(value) ? string.Empty : $"\"{value}\"";
+ }
+
+ public static int ToInt(this string? value, int defaultValue = 0)
+ {
+ return int.TryParse(value, out var result) ? result : defaultValue;
+ }
}
diff --git a/v2rayN/ServiceLib/Common/Utils.cs b/v2rayN/ServiceLib/Common/Utils.cs
index 8b75e2cd..03a1a860 100644
--- a/v2rayN/ServiceLib/Common/Utils.cs
+++ b/v2rayN/ServiceLib/Common/Utils.cs
@@ -11,856 +11,855 @@ using System.Text;
using CliWrap;
using CliWrap.Buffered;
-namespace ServiceLib.Common
+namespace ServiceLib.Common;
+
+public class Utils
{
- public class Utils
+ private static readonly string _tag = "Utils";
+
+ #region 转换函数
+
+ ///
+ /// Convert to comma-separated string
+ ///
+ ///
+ ///
+ ///
+ public static string List2String(List? lst, bool wrap = false)
{
- private static readonly string _tag = "Utils";
-
- #region 转换函数
-
- ///
- /// Convert to comma-separated string
- ///
- ///
- ///
- ///
- public static string List2String(List? lst, bool wrap = false)
+ if (lst == null || lst.Count == 0)
{
- if (lst == null || lst.Count == 0)
- {
- return string.Empty;
- }
-
- var separator = wrap ? "," + Environment.NewLine : ",";
-
- try
- {
- return string.Join(separator, lst);
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- return string.Empty;
- }
- }
-
- ///
- /// Comma-separated string
- ///
- ///
- ///
- public static List? String2List(string? str)
- {
- if (string.IsNullOrWhiteSpace(str))
- {
- return null;
- }
-
- try
- {
- str = str.Replace(Environment.NewLine, string.Empty);
- return new List(str.Split(',', StringSplitOptions.RemoveEmptyEntries));
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- return null;
- }
- }
-
- ///
- /// Comma-separated string, sorted and then converted to List
- ///
- ///
- ///
- public static List? String2ListSorted(string str)
- {
- var lst = String2List(str);
- lst?.Sort();
- return lst;
- }
-
- ///
- /// Base64 Encode
- ///
- ///
- ///
- 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 Decode
- ///
- ///
- ///
- public static string Base64Decode(string? plainText)
+ var separator = wrap ? "," + Environment.NewLine : ",";
+
+ try
{
- 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.Join(separator, lst);
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
return string.Empty;
}
+ }
- public static bool ToBool(object obj)
+ ///
+ /// Comma-separated string
+ ///
+ ///
+ ///
+ public static List? String2List(string? str)
+ {
+ if (string.IsNullOrWhiteSpace(str))
{
- try
- {
- return Convert.ToBoolean(obj);
- }
- catch
- {
- return false;
- }
- }
-
- public static string ToString(object? obj)
- {
- try
- {
- return obj?.ToString() ?? string.Empty;
- }
- catch
- {
- return string.Empty;
- }
- }
-
- public static string HumanFy(long amount)
- {
- if (amount <= 0)
- {
- return $"{amount:f1} B";
- }
-
- string[] units = ["KB", "MB", "GB", "TB", "PB"];
- var unitIndex = 0;
- double size = amount;
-
- // Loop and divide by 1024 until a suitable unit is found
- while (size >= 1024 && unitIndex < units.Length - 1)
- {
- size /= 1024;
- unitIndex++;
- }
-
- return $"{size:f1} {units[unitIndex]}";
- }
-
- 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 (query.IsNullOrEmpty())
- {
- 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)
- {
- if (string.IsNullOrEmpty(str))
- {
- return string.Empty;
- }
-
- try
- {
- 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();
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- return string.Empty;
- }
- }
-
- public static string GetFileHash(string filePath)
- {
- if (string.IsNullOrEmpty(filePath))
- {
- return string.Empty;
- }
-
- if (!File.Exists(filePath))
- {
- return string.Empty;
- }
-
- try
- {
- using var md5 = MD5.Create();
- using var stream = File.OpenRead(filePath);
- var hash = md5.ComputeHash(stream);
- return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- return string.Empty;
- }
- }
-
- ///
- /// idn to idc
- ///
- ///
- ///
- public static string GetPunycode(string url)
- {
- if (url.IsNullOrEmpty())
- {
- 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 (text.IsNullOrEmpty())
- {
- return text;
- }
-
- return text.Replace(",", ",").Replace(Environment.NewLine, ",");
- }
-
- #endregion 转换函数
-
- #region 数据检查
-
- ///
- /// Determine if the input is a number
- ///
- ///
- ///
- public static bool IsNumeric(string oText)
- {
- return oText.All(char.IsNumber);
- }
-
- ///
- /// Validate if the domain address is valid
- ///
- ///
- public static bool IsDomain(string? domain)
- {
- if (domain.IsNullOrEmpty())
- {
- 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
- {
- List lstIpEndPoints = new();
- List lstTcpConns = new();
-
- lstIpEndPoints.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners());
- lstIpEndPoints.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners());
- lstTcpConns.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections());
-
- if (lstIpEndPoints?.FindIndex(it => it.Port == port) >= 0)
- {
- return true;
- }
-
- if (lstTcpConns?.FindIndex(it => it.LocalEndPoint.Port == port) >= 0)
- {
- return true;
- }
- }
- 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);
- }
-
- ///
- /// Get version
- ///
- ///
- 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
{
- try
+ str = str.Replace(Environment.NewLine, string.Empty);
+ return new List(str.Split(',', StringSplitOptions.RemoveEmptyEntries));
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ return null;
+ }
+ }
+
+ ///
+ /// Comma-separated string, sorted and then converted to List
+ ///
+ ///
+ ///
+ public static List? String2ListSorted(string str)
+ {
+ var lst = String2List(str);
+ lst?.Sort();
+ return lst;
+ }
+
+ ///
+ /// Base64 Encode
+ ///
+ ///
+ ///
+ 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 Decode
+ ///
+ ///
+ ///
+ public static string Base64Decode(string? plainText)
+ {
+ try
+ {
+ if (plainText.IsNullOrEmpty())
{
- var basePath = GetBaseDirectory();
- //When this file exists, it is equivalent to having no permission to read and write
- if (File.Exists(Path.Combine(basePath, "NotStoreConfigHere.txt")))
- {
- return false;
- }
-
- //Check if it is installed by Windows WinGet
- if (IsWindows() && basePath.Contains("Users") && basePath.Contains("WinGet"))
- {
- return false;
- }
-
- var tempPath = Path.Combine(basePath, "guiTemps");
- if (!Directory.Exists(tempPath))
- {
- Directory.CreateDirectory(tempPath);
- }
- var fileName = Path.Combine(tempPath, GetGuid());
- File.Create(fileName).Close();
- File.Delete(fileName);
+ return "";
}
- catch (Exception)
+
+ 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 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;
+ }
+ }
+
+ public static string HumanFy(long amount)
+ {
+ if (amount <= 0)
+ {
+ return $"{amount:f1} B";
+ }
+
+ string[] units = ["KB", "MB", "GB", "TB", "PB"];
+ var unitIndex = 0;
+ double size = amount;
+
+ // Loop and divide by 1024 until a suitable unit is found
+ while (size >= 1024 && unitIndex < units.Length - 1)
+ {
+ size /= 1024;
+ unitIndex++;
+ }
+
+ return $"{size:f1} {units[unitIndex]}";
+ }
+
+ 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 (query.IsNullOrEmpty())
+ {
+ 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)
+ {
+ if (string.IsNullOrEmpty(str))
+ {
+ return string.Empty;
+ }
+
+ try
+ {
+ 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();
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ return string.Empty;
+ }
+ }
+
+ public static string GetFileHash(string filePath)
+ {
+ if (string.IsNullOrEmpty(filePath))
+ {
+ return string.Empty;
+ }
+
+ if (!File.Exists(filePath))
+ {
+ return string.Empty;
+ }
+
+ try
+ {
+ using var md5 = MD5.Create();
+ using var stream = File.OpenRead(filePath);
+ var hash = md5.ComputeHash(stream);
+ return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ return string.Empty;
+ }
+ }
+
+ ///
+ /// idn to idc
+ ///
+ ///
+ ///
+ public static string GetPunycode(string url)
+ {
+ if (url.IsNullOrEmpty())
+ {
+ 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 (text.IsNullOrEmpty())
+ {
+ return text;
+ }
+
+ return text.Replace(",", ",").Replace(Environment.NewLine, ",");
+ }
+
+ #endregion 转换函数
+
+ #region 数据检查
+
+ ///
+ /// Determine if the input is a number
+ ///
+ ///
+ ///
+ public static bool IsNumeric(string oText)
+ {
+ return oText.All(char.IsNumber);
+ }
+
+ ///
+ /// Validate if the domain address is valid
+ ///
+ ///
+ public static bool IsDomain(string? domain)
+ {
+ if (domain.IsNullOrEmpty())
+ {
+ 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
+ {
+ List lstIpEndPoints = new();
+ List lstTcpConns = new();
+
+ lstIpEndPoints.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners());
+ lstIpEndPoints.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners());
+ lstTcpConns.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections());
+
+ if (lstIpEndPoints?.FindIndex(it => it.Port == port) >= 0)
+ {
+ return true;
+ }
+
+ if (lstTcpConns?.FindIndex(it => it.LocalEndPoint.Port == port) >= 0)
+ {
+ return true;
+ }
+ }
+ 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);
+ }
+
+ ///
+ /// Get version
+ ///
+ ///
+ 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
+ {
+ var basePath = GetBaseDirectory();
+ //When this file exists, it is equivalent to having no permission to read and write
+ if (File.Exists(Path.Combine(basePath, "NotStoreConfigHere.txt")))
{
return false;
}
- return true;
- }
-
- public static string GetPath(string fileName)
- {
- var startupPath = StartupPath();
- if (fileName.IsNullOrEmpty())
+ //Check if it is installed by Windows WinGet
+ if (IsWindows() && basePath.Contains("Users") && basePath.Contains("WinGet"))
{
- return startupPath;
+ return false;
}
- 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");
+ var tempPath = Path.Combine(basePath, "guiTemps");
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(tempPath);
}
-
- if (filename.IsNullOrEmpty())
- {
- return tempPath;
- }
- else
- {
- return Path.Combine(tempPath, filename);
- }
+ var fileName = Path.Combine(tempPath, GetGuid());
+ File.Create(fileName).Close();
+ File.Delete(fileName);
+ }
+ catch (Exception)
+ {
+ return false;
}
- public static string GetBackupPath(string filename)
- {
- var tempPath = Path.Combine(StartupPath(), "guiBackups");
- if (!Directory.Exists(tempPath))
- {
- Directory.CreateDirectory(tempPath);
- }
+ return true;
+ }
+ public static string GetPath(string fileName)
+ {
+ var startupPath = StartupPath();
+ if (fileName.IsNullOrEmpty())
+ {
+ 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 (filename.IsNullOrEmpty())
+ {
+ return tempPath;
+ }
+ else
+ {
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 (filename.IsNullOrEmpty())
- {
- 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 (filename.IsNullOrEmpty())
- {
- 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 (filename.IsNullOrEmpty())
- {
- 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 (filename.IsNullOrEmpty())
- {
- return tempPath;
- }
- else
- {
- return Path.Combine(tempPath, filename);
- }
- }
-
- public static string GetBinConfigPath(string filename = "")
- {
- var tempPath = Path.Combine(StartupPath(), "binConfigs");
- if (!Directory.Exists(tempPath))
- {
- Directory.CreateDirectory(tempPath);
- }
-
- if (filename.IsNullOrEmpty())
- {
- 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(Global.LinuxBash, 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(Global.LinuxBash, 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(Global.LinuxBash, arg);
- }
-
- public static string? GetHomePath()
- {
- return IsWindows()
- ? Environment.ExpandEnvironmentVariables("%HOMEDRIVE%%HOMEPATH%")
- : Environment.GetEnvironmentVariable("HOME");
- }
-
- #endregion Platform
}
+
+ 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 (filename.IsNullOrEmpty())
+ {
+ 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 (filename.IsNullOrEmpty())
+ {
+ 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 (filename.IsNullOrEmpty())
+ {
+ 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 (filename.IsNullOrEmpty())
+ {
+ return tempPath;
+ }
+ else
+ {
+ return Path.Combine(tempPath, filename);
+ }
+ }
+
+ public static string GetBinConfigPath(string filename = "")
+ {
+ var tempPath = Path.Combine(StartupPath(), "binConfigs");
+ if (!Directory.Exists(tempPath))
+ {
+ Directory.CreateDirectory(tempPath);
+ }
+
+ if (filename.IsNullOrEmpty())
+ {
+ 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(Global.LinuxBash, 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(Global.LinuxBash, 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(Global.LinuxBash, arg);
+ }
+
+ public static string? GetHomePath()
+ {
+ return IsWindows()
+ ? Environment.ExpandEnvironmentVariables("%HOMEDRIVE%%HOMEPATH%")
+ : Environment.GetEnvironmentVariable("HOME");
+ }
+
+ #endregion Platform
}
diff --git a/v2rayN/ServiceLib/Common/WindowsUtils.cs b/v2rayN/ServiceLib/Common/WindowsUtils.cs
index 1d4740c3..6c6f7be1 100644
--- a/v2rayN/ServiceLib/Common/WindowsUtils.cs
+++ b/v2rayN/ServiceLib/Common/WindowsUtils.cs
@@ -2,73 +2,72 @@ using System.Security.Cryptography;
using System.Text;
using Microsoft.Win32;
-namespace ServiceLib.Common
+namespace ServiceLib.Common;
+
+internal static class WindowsUtils
{
- internal static class WindowsUtils
+ private static readonly string _tag = "WindowsUtils";
+
+ public static string? RegReadValue(string path, string name, string def)
{
- private static readonly string _tag = "WindowsUtils";
-
- public static string? RegReadValue(string path, string name, string def)
+ RegistryKey? regKey = null;
+ try
{
- RegistryKey? regKey = null;
- try
- {
- regKey = Registry.CurrentUser.OpenSubKey(path, false);
- var value = regKey?.GetValue(name) as string;
- return value.IsNullOrEmpty() ? def : value;
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
- finally
- {
- regKey?.Close();
- }
- return def;
+ regKey = Registry.CurrentUser.OpenSubKey(path, false);
+ var value = regKey?.GetValue(name) as string;
+ return value.IsNullOrEmpty() ? def : value;
}
-
- public static void RegWriteValue(string path, string name, object value)
+ catch (Exception ex)
{
- RegistryKey? regKey = null;
- try
+ 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 (value.ToString().IsNullOrEmpty())
{
- regKey = Registry.CurrentUser.CreateSubKey(path);
- if (value.ToString().IsNullOrEmpty())
- {
- regKey?.DeleteValue(name, false);
- }
- else
- {
- regKey?.SetValue(name, value);
- }
+ regKey?.DeleteValue(name, false);
}
- catch (Exception ex)
+ else
{
- Logging.SaveLog(_tag, ex);
- }
- finally
- {
- regKey?.Close();
+ regKey?.SetValue(name, value);
}
}
-
- public static async Task RemoveTunDevice()
+ catch (Exception ex)
{
- try
- {
- var sum = MD5.HashData(Encoding.UTF8.GetBytes("wintunsingbox_tun"));
- var guid = new Guid(sum);
- var pnpUtilPath = @"C:\Windows\System32\pnputil.exe";
- var arg = $$""" /remove-device "SWD\Wintun\{{{guid}}}" """;
+ Logging.SaveLog(_tag, ex);
+ }
+ finally
+ {
+ regKey?.Close();
+ }
+ }
- // Try to remove the device
- _ = await Utils.GetCliWrapOutput(pnpUtilPath, arg);
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
+ public static async Task RemoveTunDevice()
+ {
+ try
+ {
+ var sum = MD5.HashData(Encoding.UTF8.GetBytes("wintunsingbox_tun"));
+ var guid = new Guid(sum);
+ var pnpUtilPath = @"C:\Windows\System32\pnputil.exe";
+ var arg = $$""" /remove-device "SWD\Wintun\{{{guid}}}" """;
+
+ // Try to remove the device
+ _ = await Utils.GetCliWrapOutput(pnpUtilPath, arg);
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
}
}
}
diff --git a/v2rayN/ServiceLib/Common/YamlUtils.cs b/v2rayN/ServiceLib/Common/YamlUtils.cs
index 511e41e5..e9be015f 100644
--- a/v2rayN/ServiceLib/Common/YamlUtils.cs
+++ b/v2rayN/ServiceLib/Common/YamlUtils.cs
@@ -2,79 +2,78 @@ using YamlDotNet.Core;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
-namespace ServiceLib.Common
+namespace ServiceLib.Common;
+
+public class YamlUtils
{
- public class YamlUtils
+ private static readonly string _tag = "YamlUtils";
+
+ #region YAML
+
+ ///
+ /// 反序列化成对象
+ ///
+ ///
+ ///
+ ///
+ public static T FromYaml(string str)
{
- private static readonly string _tag = "YamlUtils";
-
- #region YAML
-
- ///
- /// 反序列化成对象
- ///
- ///
- ///
- ///
- public static T FromYaml(string str)
+ var deserializer = new DeserializerBuilder()
+ .WithNamingConvention(PascalCaseNamingConvention.Instance)
+ .Build();
+ try
{
- 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("");
- }
+ var obj = deserializer.Deserialize(str);
+ return obj;
}
-
- ///
- /// 序列化
- ///
- ///
- ///
- public static string ToYaml(object? obj)
+ catch (Exception ex)
{
- var result = string.Empty;
- if (obj == null)
- {
- return result;
- }
- var serializer = new SerializerBuilder()
- .WithNamingConvention(HyphenatedNamingConvention.Instance)
- .Build();
+ Logging.SaveLog(_tag, ex);
+ return deserializer.Deserialize("");
+ }
+ }
- try
- {
- result = serializer.Serialize(obj);
- }
- catch (Exception ex)
- {
- Logging.SaveLog(_tag, ex);
- }
+ ///
+ /// 序列化
+ ///
+ ///
+ ///
+ 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? PreprocessYaml(string str)
+ try
{
- 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;
- }
+ result = serializer.Serialize(obj);
}
-
- #endregion YAML
+ catch (Exception ex)
+ {
+ Logging.SaveLog(_tag, ex);
+ }
+ return result;
}
+
+ public static string? PreprocessYaml(string str)
+ {
+ 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
}
diff --git a/v2rayN/ServiceLib/Enums/EConfigType.cs b/v2rayN/ServiceLib/Enums/EConfigType.cs
index 5c73e728..f56d0e0f 100644
--- a/v2rayN/ServiceLib/Enums/EConfigType.cs
+++ b/v2rayN/ServiceLib/Enums/EConfigType.cs
@@ -1,16 +1,15 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums;
+
+public enum EConfigType
{
- 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
+ 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 d2252078..6700fe44 100644
--- a/v2rayN/ServiceLib/Enums/ECoreType.cs
+++ b/v2rayN/ServiceLib/Enums/ECoreType.cs
@@ -1,19 +1,18 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums;
+
+public enum ECoreType
{
- 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,
- brook = 27,
- overtls = 28,
- v2rayN = 99
- }
+ v2fly = 1,
+ Xray = 2,
+ v2fly_v5 = 4,
+ mihomo = 13,
+ hysteria = 21,
+ naiveproxy = 22,
+ tuic = 23,
+ sing_box = 24,
+ juicity = 25,
+ hysteria2 = 26,
+ brook = 27,
+ overtls = 28,
+ v2rayN = 99
}
diff --git a/v2rayN/ServiceLib/Enums/EGirdOrientation.cs b/v2rayN/ServiceLib/Enums/EGirdOrientation.cs
index 1a62c7bb..e45d3b71 100644
--- a/v2rayN/ServiceLib/Enums/EGirdOrientation.cs
+++ b/v2rayN/ServiceLib/Enums/EGirdOrientation.cs
@@ -1,9 +1,8 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums;
+
+public enum EGirdOrientation
{
- public enum EGirdOrientation
- {
- Horizontal,
- Vertical,
- Tab,
- }
-}
\ No newline at end of file
+ Horizontal,
+ Vertical,
+ Tab,
+}
diff --git a/v2rayN/ServiceLib/Enums/EGlobalHotkey.cs b/v2rayN/ServiceLib/Enums/EGlobalHotkey.cs
index 328bf36e..3ec982aa 100644
--- a/v2rayN/ServiceLib/Enums/EGlobalHotkey.cs
+++ b/v2rayN/ServiceLib/Enums/EGlobalHotkey.cs
@@ -1,11 +1,10 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums;
+
+public enum EGlobalHotkey
{
- public enum EGlobalHotkey
- {
- ShowForm = 0,
- SystemProxyClear = 1,
- SystemProxySet = 2,
- SystemProxyUnchanged = 3,
- SystemProxyPac = 4,
- }
-}
\ No newline at end of file
+ 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..768a428b 100644
--- a/v2rayN/ServiceLib/Enums/EInboundProtocol.cs
+++ b/v2rayN/ServiceLib/Enums/EInboundProtocol.cs
@@ -1,14 +1,13 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums;
+
+public enum EInboundProtocol
{
- public enum EInboundProtocol
- {
- socks = 0,
- socks2,
- socks3,
- pac,
- api,
- api2,
- mixed,
- speedtest = 21
- }
-}
\ No newline at end of file
+ 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..86b14c75 100644
--- a/v2rayN/ServiceLib/Enums/EMove.cs
+++ b/v2rayN/ServiceLib/Enums/EMove.cs
@@ -1,11 +1,10 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums;
+
+public enum EMove
{
- public enum EMove
- {
- Top = 1,
- Up = 2,
- Down = 3,
- Bottom = 4,
- Position = 5
- }
-}
\ No newline at end of file
+ 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 9bf844ff..23be4ac1 100644
--- a/v2rayN/ServiceLib/Enums/EMsgCommand.cs
+++ b/v2rayN/ServiceLib/Enums/EMsgCommand.cs
@@ -1,11 +1,10 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums;
+
+public enum EMsgCommand
{
- public enum EMsgCommand
- {
- ClearMsg,
- SendMsgView,
- SendSnackMsg,
- RefreshProfiles,
- AppExit
- }
+ ClearMsg,
+ SendMsgView,
+ SendSnackMsg,
+ RefreshProfiles,
+ AppExit
}
diff --git a/v2rayN/ServiceLib/Enums/EMultipleLoad.cs b/v2rayN/ServiceLib/Enums/EMultipleLoad.cs
index a5541f91..42be7a5b 100644
--- a/v2rayN/ServiceLib/Enums/EMultipleLoad.cs
+++ b/v2rayN/ServiceLib/Enums/EMultipleLoad.cs
@@ -1,10 +1,9 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums;
+
+public enum EMultipleLoad
{
- public enum EMultipleLoad
- {
- Random,
- RoundRobin,
- LeastPing,
- LeastLoad
- }
+ Random,
+ RoundRobin,
+ LeastPing,
+ LeastLoad
}
diff --git a/v2rayN/ServiceLib/Enums/EPresetType.cs b/v2rayN/ServiceLib/Enums/EPresetType.cs
index 855b10a1..a1763b33 100644
--- a/v2rayN/ServiceLib/Enums/EPresetType.cs
+++ b/v2rayN/ServiceLib/Enums/EPresetType.cs
@@ -1,9 +1,8 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums;
+
+public enum EPresetType
{
- public enum EPresetType
- {
- Default = 0,
- Russia = 1,
- Iran = 2,
- }
-}
\ No newline at end of file
+ Default = 0,
+ Russia = 1,
+ Iran = 2,
+}
diff --git a/v2rayN/ServiceLib/Enums/ERuleMode.cs b/v2rayN/ServiceLib/Enums/ERuleMode.cs
index 179384d5..fd89449d 100644
--- a/v2rayN/ServiceLib/Enums/ERuleMode.cs
+++ b/v2rayN/ServiceLib/Enums/ERuleMode.cs
@@ -1,10 +1,9 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums;
+
+public enum ERuleMode
{
- public enum ERuleMode
- {
- Rule = 0,
- Global = 1,
- Direct = 2,
- Unchanged = 3
- }
-}
\ No newline at end of file
+ Rule = 0,
+ Global = 1,
+ Direct = 2,
+ Unchanged = 3
+}
diff --git a/v2rayN/ServiceLib/Enums/EServerColName.cs b/v2rayN/ServiceLib/Enums/EServerColName.cs
index ef981b74..9f50f4df 100644
--- a/v2rayN/ServiceLib/Enums/EServerColName.cs
+++ b/v2rayN/ServiceLib/Enums/EServerColName.cs
@@ -1,21 +1,20 @@
-namespace ServiceLib.Enums
-{
- public enum EServerColName
- {
- Def = 0,
- ConfigType,
- Remarks,
- Address,
- Port,
- Network,
- StreamSecurity,
- SubRemarks,
- DelayVal,
- SpeedVal,
+namespace ServiceLib.Enums;
- TodayDown,
- TodayUp,
- TotalDown,
- TotalUp
- }
-}
\ No newline at end of file
+public enum EServerColName
+{
+ Def = 0,
+ ConfigType,
+ Remarks,
+ Address,
+ Port,
+ Network,
+ StreamSecurity,
+ SubRemarks,
+ DelayVal,
+ SpeedVal,
+
+ TodayDown,
+ TodayUp,
+ TotalDown,
+ TotalUp
+}
diff --git a/v2rayN/ServiceLib/Enums/ESpeedActionType.cs b/v2rayN/ServiceLib/Enums/ESpeedActionType.cs
index 63f13919..0478bcc0 100644
--- a/v2rayN/ServiceLib/Enums/ESpeedActionType.cs
+++ b/v2rayN/ServiceLib/Enums/ESpeedActionType.cs
@@ -1,10 +1,9 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums;
+
+public enum ESpeedActionType
{
- public enum ESpeedActionType
- {
- Tcping,
- Realping,
- Speedtest,
- Mixedtest
- }
-}
\ No newline at end of file
+ Tcping,
+ Realping,
+ Speedtest,
+ Mixedtest
+}
diff --git a/v2rayN/ServiceLib/Enums/ESysProxyType.cs b/v2rayN/ServiceLib/Enums/ESysProxyType.cs
index 84beaffe..39816d42 100644
--- a/v2rayN/ServiceLib/Enums/ESysProxyType.cs
+++ b/v2rayN/ServiceLib/Enums/ESysProxyType.cs
@@ -1,10 +1,9 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums;
+
+public enum ESysProxyType
{
- public enum ESysProxyType
- {
- ForcedClear = 0,
- ForcedChange = 1,
- Unchanged = 2,
- Pac = 3
- }
-}
\ No newline at end of file
+ ForcedClear = 0,
+ ForcedChange = 1,
+ Unchanged = 2,
+ Pac = 3
+}
diff --git a/v2rayN/ServiceLib/Enums/ETheme.cs b/v2rayN/ServiceLib/Enums/ETheme.cs
index 7701ae8f..6ea1e4f1 100644
--- a/v2rayN/ServiceLib/Enums/ETheme.cs
+++ b/v2rayN/ServiceLib/Enums/ETheme.cs
@@ -1,13 +1,12 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums;
+
+public enum ETheme
{
- public enum ETheme
- {
- FollowSystem,
- Dark,
- Light,
- Aquatic,
- Desert,
- Dusk,
- NightSky
- }
-}
\ No newline at end of file
+ FollowSystem,
+ Dark,
+ Light,
+ Aquatic,
+ Desert,
+ Dusk,
+ NightSky
+}
diff --git a/v2rayN/ServiceLib/Enums/ETransport.cs b/v2rayN/ServiceLib/Enums/ETransport.cs
index 2cd43821..b1166608 100644
--- a/v2rayN/ServiceLib/Enums/ETransport.cs
+++ b/v2rayN/ServiceLib/Enums/ETransport.cs
@@ -1,15 +1,14 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums;
+
+public enum ETransport
{
- public enum ETransport
- {
- tcp,
- kcp,
- ws,
- httpupgrade,
- xhttp,
- h2,
- http,
- quic,
- grpc
- }
-}
\ No newline at end of file
+ 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..75142925 100644
--- a/v2rayN/ServiceLib/Enums/EViewAction.cs
+++ b/v2rayN/ServiceLib/Enums/EViewAction.cs
@@ -1,46 +1,45 @@
-namespace ServiceLib.Enums
+namespace ServiceLib.Enums;
+
+public enum EViewAction
{
- 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
+ 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/Global.cs b/v2rayN/ServiceLib/Global.cs
index da70326b..50b2cd2e 100644
--- a/v2rayN/ServiceLib/Global.cs
+++ b/v2rayN/ServiceLib/Global.cs
@@ -1,155 +1,155 @@
-namespace ServiceLib
+namespace ServiceLib;
+
+public class Global
{
- public class Global
- {
- #region const
+ #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 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 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 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 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 = "configTest{0}.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 = "configTest{0}.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 ProxySetOSXShellFileName = NamespaceSample + "proxy_set_osx_sh";
- public const string ProxySetLinuxShellFileName = NamespaceSample + "proxy_set_linux_sh";
+ 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 ProxySetOSXShellFileName = NamespaceSample + "proxy_set_osx_sh";
+ public const string ProxySetLinuxShellFileName = NamespaceSample + "proxy_set_linux_sh";
- 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 int MinFontSize = 8;
- public const string RebootAs = "rebootas";
- public const string AvaAssets = "avares://v2rayN/Assets/";
- public const string LocalAppData = "V2RAYN_LOCAL_APPLICATION_DATA_V2";
- public const string V2RayLocalAsset = "V2RAY_LOCATION_ASSET";
- public const string XrayLocalAsset = "XRAY_LOCATION_ASSET";
- public const string XrayLocalCert = "XRAY_LOCATION_CERT";
- public const int SpeedTestPageSize = 1000;
- public const string LinuxBash = "/bin/bash";
+ 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 int MinFontSize = 8;
+ public const string RebootAs = "rebootas";
+ public const string AvaAssets = "avares://v2rayN/Assets/";
+ public const string LocalAppData = "V2RAYN_LOCAL_APPLICATION_DATA_V2";
+ public const string V2RayLocalAsset = "V2RAY_LOCATION_ASSET";
+ public const string XrayLocalAsset = "XRAY_LOCATION_ASSET";
+ public const string XrayLocalCert = "XRAY_LOCATION_CERT";
+ public const int SpeedTestPageSize = 1000;
+ public const string LinuxBash = "/bin/bash";
- public static readonly List IEProxyProtocols =
- [
- "{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}",
+ 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 =
- [
- "",
+ public static readonly List SubConvertTargets =
+ [
+ "",
"mixed",
"v2ray",
"clash",
"ss"
- ];
+ ];
- public static readonly List SpeedTestUrls =
- [
- @"https://cachefly.cachefly.net/50mb.test",
+ public static readonly List SpeedTestUrls =
+ [
+ @"https://cachefly.cachefly.net/50mb.test",
@"https://speed.cloudflare.com/__down?bytes=10000000",
@"https://speed.cloudflare.com/__down?bytes=50000000",
@"https://speed.cloudflare.com/__down?bytes=100000000",
];
- public static readonly List SpeedPingTestUrls =
- [
- @"https://www.google.com/generate_204",
+ 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 =
- [
- "",
+ 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 =
- [
- "",
+ 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 =
- [
- "",
+ 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 =
- [
- "",
+ 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()
+ 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" },
@@ -158,9 +158,9 @@ namespace ServiceLib
{"none",""}
};
- public const string Hysteria2ProtocolShare = "hy2://";
+ public const string Hysteria2ProtocolShare = "hy2://";
- public static readonly Dictionary ProtocolShares = new()
+ public static readonly Dictionary ProtocolShares = new()
{
{ EConfigType.VMess, "vmess://" },
{ EConfigType.Shadowsocks, "ss://" },
@@ -172,7 +172,7 @@ namespace ServiceLib
{ EConfigType.WireGuard, "wireguard://" }
};
- public static readonly Dictionary ProtocolTypes = new()
+ public static readonly Dictionary ProtocolTypes = new()
{
{ EConfigType.VMess, "vmess" },
{ EConfigType.Shadowsocks, "shadowsocks" },
@@ -185,28 +185,28 @@ namespace ServiceLib
{ EConfigType.WireGuard, "wireguard" }
};
- public static readonly List VmessSecurities =
- [
- "aes-128-gcm",
+ public static readonly List VmessSecurities =
+ [
+ "aes-128-gcm",
"chacha20-poly1305",
"auto",
"none",
"zero"
- ];
+ ];
- public static readonly List SsSecurities =
- [
- "aes-256-gcm",
+ 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",
+ public static readonly List SsSecuritiesInXray =
+ [
+ "aes-256-gcm",
"aes-128-gcm",
"chacha20-poly1305",
"chacha20-ietf-poly1305",
@@ -217,11 +217,11 @@ namespace ServiceLib
"2022-blake3-aes-128-gcm",
"2022-blake3-aes-256-gcm",
"2022-blake3-chacha20-poly1305"
- ];
+ ];
- public static readonly List SsSecuritiesInSingbox =
- [
- "aes-256-gcm",
+ public static readonly List SsSecuritiesInSingbox =
+ [
+ "aes-256-gcm",
"aes-192-gcm",
"aes-128-gcm",
"chacha20-ietf-poly1305",
@@ -239,18 +239,18 @@ namespace ServiceLib
"rc4-md5",
"chacha20-ietf",
"xchacha20"
- ];
+ ];
- public static readonly List Flows =
- [
- "",
+ public static readonly List Flows =
+ [
+ "",
"xtls-rprx-vision",
"xtls-rprx-vision-udp443"
- ];
+ ];
- public static readonly List Networks =
- [
- "tcp",
+ public static readonly List Networks =
+ [
+ "tcp",
"kcp",
"ws",
"httpupgrade",
@@ -258,50 +258,50 @@ namespace ServiceLib
"h2",
"quic",
"grpc"
- ];
+ ];
- public static readonly List KcpHeaderTypes =
- [
- "srtp",
+ public static readonly List KcpHeaderTypes =
+ [
+ "srtp",
"utp",
"wechat-video",
"dtls",
"wireguard",
"dns"
- ];
+ ];
- public static readonly List CoreTypes =
- [
- "Xray",
+ public static readonly List CoreTypes =
+ [
+ "Xray",
"sing_box"
- ];
+ ];
- public static readonly List DomainStrategies =
- [
- "AsIs",
+ public static readonly List DomainStrategies =
+ [
+ "AsIs",
"IPIfNonMatch",
"IPOnDemand"
- ];
+ ];
- public static readonly List DomainStrategies4Singbox =
- [
- "ipv4_only",
+ public static readonly List DomainStrategies4Singbox =
+ [
+ "ipv4_only",
"ipv6_only",
"prefer_ipv4",
"prefer_ipv6",
""
- ];
+ ];
- public static readonly List DomainMatchers =
- [
- "linear",
+ public static readonly List DomainMatchers =
+ [
+ "linear",
"mph",
""
- ];
+ ];
- public static readonly List Fingerprints =
- [
- "chrome",
+ public static readonly List Fingerprints =
+ [
+ "chrome",
"firefox",
"safari",
"ios",
@@ -312,174 +312,174 @@ namespace ServiceLib
"random",
"randomized",
""
- ];
+ ];
- public static readonly List UserAgent =
- [
- "chrome",
+ public static readonly List UserAgent =
+ [
+ "chrome",
"firefox",
"safari",
"edge",
"none"
- ];
+ ];
- public static readonly List XhttpMode =
- [
- "auto",
+ public static readonly List XhttpMode =
+ [
+ "auto",
"packet-up",
"stream-up",
"stream-one"
- ];
+ ];
- public static readonly List AllowInsecure =
- [
- "true",
+ public static readonly List AllowInsecure =
+ [
+ "true",
"false",
""
- ];
+ ];
- public static readonly List DomainStrategy4Freedoms =
- [
- "AsIs",
+ public static readonly List DomainStrategy4Freedoms =
+ [
+ "AsIs",
"UseIP",
"UseIPv4",
"UseIPv6",
""
- ];
+ ];
- public static readonly List SingboxDomainStrategy4Out =
- [
- "ipv4_only",
+ public static readonly List SingboxDomainStrategy4Out =
+ [
+ "ipv4_only",
"prefer_ipv4",
"prefer_ipv6",
"ipv6_only",
""
- ];
+ ];
- public static readonly List DomainDNSAddress =
- [
- "223.5.5.5",
+ public static readonly List DomainDNSAddress =
+ [
+ "223.5.5.5",
"223.6.6.6",
"localhost"
- ];
+ ];
- public static readonly List SingboxDomainDNSAddress =
- [
- "223.5.5.5",
+ public static readonly List SingboxDomainDNSAddress =
+ [
+ "223.5.5.5",
"223.6.6.6",
"dhcp://auto"
- ];
+ ];
- public static readonly List Languages =
- [
- "zh-Hans",
+ public static readonly List Languages =
+ [
+ "zh-Hans",
"zh-Hant",
"en",
"fa-Ir",
"ru",
"hu"
- ];
+ ];
- public static readonly List Alpns =
- [
- "h3",
+ 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",
+ public static readonly List LogLevels =
+ [
+ "debug",
"info",
"warning",
"error",
"none"
- ];
+ ];
- public static readonly List InboundTags =
- [
- "socks",
+ public static readonly List InboundTags =
+ [
+ "socks",
"socks2",
"socks3"
- ];
+ ];
- public static readonly List RuleProtocols =
- [
- "http",
+ public static readonly List RuleProtocols =
+ [
+ "http",
"tls",
"bittorrent"
- ];
+ ];
- public static readonly List RuleNetworks =
- [
- "",
+ public static readonly List RuleNetworks =
+ [
+ "",
"tcp",
"udp",
"tcp,udp"
- ];
+ ];
- public static readonly List destOverrideProtocols =
- [
- "http",
+ public static readonly List destOverrideProtocols =
+ [
+ "http",
"tls",
"quic",
"fakedns",
"fakedns+others"
- ];
+ ];
- public static readonly List TunMtus =
- [
- 1280,
+ public static readonly List TunMtus =
+ [
+ 1280,
1408,
1500,
9000
- ];
+ ];
- public static readonly List TunStacks =
- [
- "gvisor",
+ public static readonly List TunStacks =
+ [
+ "gvisor",
"system",
"mixed"
- ];
+ ];
- public static readonly List PresetMsgFilters =
- [
- "proxy",
+ public static readonly List PresetMsgFilters =
+ [
+ "proxy",
"direct",
"block",
""
- ];
+ ];
- public static readonly List SingboxMuxs =
- [
- "h2mux",
+ public static readonly List SingboxMuxs =
+ [
+ "h2mux",
"smux",
"yamux",
""
- ];
+ ];
- public static readonly List TuicCongestionControls =
- [
- "cubic",
+ public static readonly List TuicCongestionControls =
+ [
+ "cubic",
"new_reno",
"bbr"
- ];
+ ];
- public static readonly List allowSelectType =
- [
- "selector",
+ public static readonly List allowSelectType =
+ [
+ "selector",
"urltest",
"loadbalance",
"fallback"
- ];
+ ];
- public static readonly List notAllowTestType =
- [
- "selector",
+ public static readonly List notAllowTestType =
+ [
+ "selector",
"urltest",
"direct",
"reject",
@@ -487,15 +487,15 @@ namespace ServiceLib
"pass",
"loadbalance",
"fallback"
- ];
+ ];
- public static readonly List proxyVehicleType =
- [
- "file",
+ public static readonly List proxyVehicleType =
+ [
+ "file",
"http"
- ];
+ ];
- public static readonly Dictionary CoreUrls = new()
+ public static readonly Dictionary CoreUrls = new()
{
{ ECoreType.v2fly, "v2fly/v2ray-core" },
{ ECoreType.v2fly_v5, "v2fly/v2ray-core" },
@@ -512,13 +512,12 @@ namespace ServiceLib
{ ECoreType.v2rayN, "2dust/v2rayN" },
};
- public static readonly List OtherGeoUrls =
- [
- @"https://raw.githubusercontent.com/Loyalsoldier/geoip/release/geoip-only-cn-private.dat",
+ public static readonly List OtherGeoUrls =
+ [
+ @"https://raw.githubusercontent.com/Loyalsoldier/geoip/release/geoip-only-cn-private.dat",
@"https://raw.githubusercontent.com/Loyalsoldier/geoip/release/Country.mmdb",
@"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb"
- ];
+ ];
- #endregion const
- }
+ #endregion const
}
diff --git a/v2rayN/ServiceLib/Handler/AppHandler.cs b/v2rayN/ServiceLib/Handler/AppHandler.cs
index 0ac794ac..ae46a47d 100644
--- a/v2rayN/ServiceLib/Handler/AppHandler.cs
+++ b/v2rayN/ServiceLib/Handler/AppHandler.cs
@@ -1,244 +1,243 @@
-namespace ServiceLib.Handler
+namespace ServiceLib.Handler;
+
+public sealed class AppHandler
{
- 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;
+
+ public int StatePort
{
- #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;
-
- public int StatePort
+ get
{
- 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 bool IsAdministrator
+ {
+ get
+ {
+ _isAdministrator ??= Utils.IsAdministrator();
+ return _isAdministrator.Value;
+ }
+ }
+
+ #endregion Property
+
+ #region Init
+
+ 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);
+
+ //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;
+ }
+
+ public bool InitComponents()
+ {
+ Logging.SaveLog($"v2rayN start up | {Utils.GetRuntimeInfo()}");
+ Logging.LoggingEnabled(_config.GuiItem.EnableLog);
+
+ return true;
+ }
+
+ public bool Reset()
+ {
+ _statePort = null;
+ _statePort2 = null;
+ return true;
+ }
+
+ #endregion Init
+
+ #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 void AddProcess(IntPtr processHandle)
+ {
+ if (Utils.IsWindows())
+ {
+ _processJob ??= new();
+ try
+ {
+ _processJob?.AddProcess(processHandle);
+ }
+ catch
{
- _statePort ??= Utils.GetFreePort(GetLocalPort(EInboundProtocol.api));
- return _statePort.Value;
}
}
+ }
- public int StatePort2
+ #endregion Config
+
+ #region SqliteHelper
+
+ 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?> ProfileItems(string subid)
+ {
+ if (subid.IsNullOrEmpty())
{
- get
- {
- _statePort2 ??= Utils.GetFreePort(GetLocalPort(EInboundProtocol.api2));
- return _statePort2.Value + (_config.TunModeItem.EnableTun ? 1 : 0);
- }
+ return await SQLiteHelper.Instance.TableAsync().ToListAsync();
}
-
- public bool IsAdministrator
+ else
{
- get
- {
- _isAdministrator ??= Utils.IsAdministrator();
- return _isAdministrator.Value;
- }
+ return await SQLiteHelper.Instance.TableAsync().Where(t => t.Subid == subid).ToListAsync();
}
+ }
- #endregion Property
+ public async Task?> ProfileItemIndexes(string subid)
+ {
+ return (await ProfileItems(subid))?.Select(t => t.IndexId)?.ToList();
+ }
- #region Init
-
- 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);
-
- //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;
- }
-
- public bool InitComponents()
- {
- Logging.SaveLog($"v2rayN start up | {Utils.GetRuntimeInfo()}");
- Logging.LoggingEnabled(_config.GuiItem.EnableLog);
-
- return true;
- }
-
- public bool Reset()
- {
- _statePort = null;
- _statePort2 = null;
- return true;
- }
-
- #endregion Init
-
- #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 void AddProcess(IntPtr processHandle)
- {
- if (Utils.IsWindows())
- {
- _processJob ??= new();
- try
- {
- _processJob?.AddProcess(processHandle);
- }
- catch
- {
- }
- }
- }
-
- #endregion Config
-
- #region SqliteHelper
-
- 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?> ProfileItems(string subid)
- {
- if (subid.IsNullOrEmpty())
- {
- 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