mirror of
				https://github.com/2dust/v2rayN.git
				synced 2025-10-27 10:40:08 +00:00 
			
		
		
		
	Compare commits
	
		
			20 commits
		
	
	
		
			78fde575d7
			...
			3f0f895424
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 3f0f895424 | ||
|   | 07a3bdc618 | ||
|   | 7e348c196e | ||
|   | 51e5885e76 | ||
|   | 50d7912f62 | ||
|   | 3869148fc8 | ||
|   | a0af4fb30c | ||
|   | c374b8565b | ||
|   | 7e8b405555 | ||
|   | c3439c5abe | ||
|   | d4a8787356 | ||
|   | 23b27575a0 | ||
|   | 8d8a887c42 | ||
|   | 1229c967ba | ||
|   | d35f65f86d | ||
|   | 0a8ce0f961 | ||
|   | 8092481d26 | ||
|   | 764014e49a | ||
|   | 71cc6d7a88 | ||
|   | f3af831cf2 | 
					 83 changed files with 765 additions and 793 deletions
				
			
		|  | @ -1,7 +1,7 @@ | ||||||
| <Project> | <Project> | ||||||
| 
 | 
 | ||||||
|     <PropertyGroup> |     <PropertyGroup> | ||||||
|         <Version>7.10.3</Version> |         <Version>7.10.4</Version> | ||||||
|     </PropertyGroup> |     </PropertyGroup> | ||||||
| 
 | 
 | ||||||
|     <PropertyGroup> |     <PropertyGroup> | ||||||
|  |  | ||||||
|  | @ -1 +1 @@ | ||||||
| Subproject commit b3b635ef46b7aed3ee9e27abe7ec1f2688695bfb | Subproject commit ef73fa22c46cfc7d1ec192ffe8497f6e61b4f0db | ||||||
|  | @ -10,7 +10,7 @@ namespace ServiceLib.Common | ||||||
| 
 | 
 | ||||||
|         public async Task<string?> DownloadStringAsync(IWebProxy? webProxy, string url, string? userAgent, int timeout) |         public async Task<string?> DownloadStringAsync(IWebProxy? webProxy, string url, string? userAgent, int timeout) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(url)) |             if (url.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return null; |                 return null; | ||||||
|             } |             } | ||||||
|  | @ -18,7 +18,7 @@ namespace ServiceLib.Common | ||||||
|             Uri uri = new(url); |             Uri uri = new(url); | ||||||
|             //Authorization Header |             //Authorization Header | ||||||
|             var headers = new WebHeaderCollection(); |             var headers = new WebHeaderCollection(); | ||||||
|             if (Utils.IsNotEmpty(uri.UserInfo)) |             if (uri.UserInfo.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 headers.Add(HttpRequestHeader.Authorization, "Basic " + Utils.Base64Encode(uri.UserInfo)); |                 headers.Add(HttpRequestHeader.Authorization, "Basic " + Utils.Base64Encode(uri.UserInfo)); | ||||||
|             } |             } | ||||||
|  | @ -56,7 +56,7 @@ namespace ServiceLib.Common | ||||||
| 
 | 
 | ||||||
|         public async Task DownloadDataAsync4Speed(IWebProxy webProxy, string url, IProgress<string> progress, int timeout) |         public async Task DownloadDataAsync4Speed(IWebProxy webProxy, string url, IProgress<string> progress, int timeout) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(url)) |             if (url.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 throw new ArgumentNullException(nameof(url)); |                 throw new ArgumentNullException(nameof(url)); | ||||||
|             } |             } | ||||||
|  | @ -86,7 +86,7 @@ namespace ServiceLib.Common | ||||||
|             //}; |             //}; | ||||||
|             downloader.DownloadProgressChanged += (sender, value) => |             downloader.DownloadProgressChanged += (sender, value) => | ||||||
|             { |             { | ||||||
|                 var ts = (DateTime.Now - totalDatetime); |                 var ts = DateTime.Now - totalDatetime; | ||||||
|                 if (progress != null && ts.Seconds > totalSecond) |                 if (progress != null && ts.Seconds > totalSecond) | ||||||
|                 { |                 { | ||||||
|                     hasValue = true; |                     hasValue = true; | ||||||
|  | @ -119,11 +119,11 @@ namespace ServiceLib.Common | ||||||
| 
 | 
 | ||||||
|         public async Task DownloadFileAsync(IWebProxy? webProxy, string url, string fileName, IProgress<double> progress, int timeout) |         public async Task DownloadFileAsync(IWebProxy? webProxy, string url, string fileName, IProgress<double> progress, int timeout) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(url)) |             if (url.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 throw new ArgumentNullException(nameof(url)); |                 throw new ArgumentNullException(nameof(url)); | ||||||
|             } |             } | ||||||
|             if (Utils.IsNullOrEmpty(fileName)) |             if (fileName.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 throw new ArgumentNullException(nameof(fileName)); |                 throw new ArgumentNullException(nameof(fileName)); | ||||||
|             } |             } | ||||||
|  | @ -146,10 +146,7 @@ namespace ServiceLib.Common | ||||||
|             var progressPercentage = 0; |             var progressPercentage = 0; | ||||||
|             var hasValue = false; |             var hasValue = false; | ||||||
|             await using var downloader = new Downloader.DownloadService(downloadOpt); |             await using var downloader = new Downloader.DownloadService(downloadOpt); | ||||||
|             downloader.DownloadStarted += (sender, value) => |             downloader.DownloadStarted += (sender, value) => progress?.Report(0); | ||||||
|             { |  | ||||||
|                 progress?.Report(0); |  | ||||||
|             }; |  | ||||||
|             downloader.DownloadProgressChanged += (sender, value) => |             downloader.DownloadProgressChanged += (sender, value) => | ||||||
|             { |             { | ||||||
|                 hasValue = true; |                 hasValue = true; | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| using System.Formats.Tar; | using System.Formats.Tar; | ||||||
| using System.IO.Compression; | using System.IO.Compression; | ||||||
| using System.Text; | using System.Text; | ||||||
| 
 | 
 | ||||||
|  | @ -99,7 +99,7 @@ namespace ServiceLib.Common | ||||||
|                     } |                     } | ||||||
|                     try |                     try | ||||||
|                     { |                     { | ||||||
|                         if (Utils.IsNotEmpty(ignoredName) && entry.Name.Contains(ignoredName)) |                         if (ignoredName.IsNotEmpty() && entry.Name.Contains(ignoredName)) | ||||||
|                         { |                         { | ||||||
|                             continue; |                             continue; | ||||||
|                         } |                         } | ||||||
|  | @ -163,18 +163,20 @@ namespace ServiceLib.Common | ||||||
| 
 | 
 | ||||||
|             // Check if the source directory exists |             // Check if the source directory exists | ||||||
|             if (!dir.Exists) |             if (!dir.Exists) | ||||||
|  |             { | ||||||
|                 throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}"); |                 throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}"); | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             // Cache directories before we start copying |             // Cache directories before we start copying | ||||||
|             var dirs = dir.GetDirectories(); |             var dirs = dir.GetDirectories(); | ||||||
| 
 | 
 | ||||||
|             // Create the destination directory |             // Create the destination directory | ||||||
|             Directory.CreateDirectory(destinationDir); |             _ = Directory.CreateDirectory(destinationDir); | ||||||
| 
 | 
 | ||||||
|             // Get the files in the source directory and copy to the destination directory |             // Get the files in the source directory and copy to the destination directory | ||||||
|             foreach (var file in dir.GetFiles()) |             foreach (var file in dir.GetFiles()) | ||||||
|             { |             { | ||||||
|                 if (Utils.IsNotEmpty(ignoredName) && file.Name.Contains(ignoredName)) |                 if (ignoredName.IsNotEmpty() && file.Name.Contains(ignoredName)) | ||||||
|                 { |                 { | ||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
|  | @ -187,7 +189,7 @@ namespace ServiceLib.Common | ||||||
|                 { |                 { | ||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
|                 file.CopyTo(targetFilePath, overwrite); |                 _ = file.CopyTo(targetFilePath, overwrite); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // If recursive and copying subdirectories, recursively call this method |             // If recursive and copying subdirectories, recursively call this method | ||||||
|  |  | ||||||
|  | @ -18,12 +18,17 @@ namespace ServiceLib.Common | ||||||
|         public static HttpClientHelper Instance => _instance.Value; |         public static HttpClientHelper Instance => _instance.Value; | ||||||
|         private readonly HttpClient httpClient; |         private readonly HttpClient httpClient; | ||||||
| 
 | 
 | ||||||
|         private HttpClientHelper(HttpClient httpClient) => this.httpClient = httpClient; |         private HttpClientHelper(HttpClient httpClient) | ||||||
|  |         { | ||||||
|  |             this.httpClient = httpClient; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         public async Task<string?> TryGetAsync(string url) |         public async Task<string?> TryGetAsync(string url) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(url)) |             if (url.IsNullOrEmpty()) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|  | @ -38,15 +43,19 @@ namespace ServiceLib.Common | ||||||
| 
 | 
 | ||||||
|         public async Task<string?> GetAsync(string url) |         public async Task<string?> GetAsync(string url) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(url)) |             if (url.IsNullOrEmpty()) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|  |             } | ||||||
|             return await httpClient.GetStringAsync(url); |             return await httpClient.GetStringAsync(url); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public async Task<string?> GetAsync(HttpClient client, string url, CancellationToken token = default) |         public async Task<string?> GetAsync(HttpClient client, string url, CancellationToken token = default) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(url)) |             if (url.IsNullOrEmpty()) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|  |             } | ||||||
|             return await client.GetStringAsync(url, token); |             return await client.GetStringAsync(url, token); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -55,13 +64,13 @@ namespace ServiceLib.Common | ||||||
|             var jsonContent = JsonUtils.Serialize(headers); |             var jsonContent = JsonUtils.Serialize(headers); | ||||||
|             var content = new StringContent(jsonContent, Encoding.UTF8, MediaTypeNames.Application.Json); |             var content = new StringContent(jsonContent, Encoding.UTF8, MediaTypeNames.Application.Json); | ||||||
| 
 | 
 | ||||||
|             var result = await httpClient.PutAsync(url, content); |             await httpClient.PutAsync(url, content); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public async Task PatchAsync(string url, Dictionary<string, string> headers) |         public async Task PatchAsync(string url, Dictionary<string, string> headers) | ||||||
|         { |         { | ||||||
|             var myContent = JsonUtils.Serialize(headers); |             var myContent = JsonUtils.Serialize(headers); | ||||||
|             var buffer = System.Text.Encoding.UTF8.GetBytes(myContent); |             var buffer = Encoding.UTF8.GetBytes(myContent); | ||||||
|             var byteContent = new ByteArrayContent(buffer); |             var byteContent = new ByteArrayContent(buffer); | ||||||
|             byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); |             byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); | ||||||
| 
 | 
 | ||||||
|  | @ -78,12 +87,16 @@ namespace ServiceLib.Common | ||||||
|             ArgumentNullException.ThrowIfNull(url); |             ArgumentNullException.ThrowIfNull(url); | ||||||
|             ArgumentNullException.ThrowIfNull(fileName); |             ArgumentNullException.ThrowIfNull(fileName); | ||||||
|             if (File.Exists(fileName)) |             if (File.Exists(fileName)) | ||||||
|  |             { | ||||||
|                 File.Delete(fileName); |                 File.Delete(fileName); | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             using var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token); |             using var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token); | ||||||
| 
 | 
 | ||||||
|             if (!response.IsSuccessStatusCode) |             if (!response.IsSuccessStatusCode) | ||||||
|  |             { | ||||||
|                 throw new Exception(response.StatusCode.ToString()); |                 throw new Exception(response.StatusCode.ToString()); | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             var total = response.Content.Headers.ContentLength ?? -1L; |             var total = response.Content.Headers.ContentLength ?? -1L; | ||||||
|             var canReportProgress = total != -1 && progress != null; |             var canReportProgress = total != -1 && progress != null; | ||||||
|  | @ -102,7 +115,9 @@ namespace ServiceLib.Common | ||||||
|                 totalRead += read; |                 totalRead += read; | ||||||
| 
 | 
 | ||||||
|                 if (read == 0) |                 if (read == 0) | ||||||
|  |                 { | ||||||
|                     break; |                     break; | ||||||
|  |                 } | ||||||
|                 await file.WriteAsync(buffer.AsMemory(0, read), token); |                 await file.WriteAsync(buffer.AsMemory(0, read), token); | ||||||
| 
 | 
 | ||||||
|                 if (canReportProgress) |                 if (canReportProgress) | ||||||
|  | @ -123,7 +138,7 @@ namespace ServiceLib.Common | ||||||
| 
 | 
 | ||||||
|         public async Task DownloadDataAsync4Speed(HttpClient client, string url, IProgress<string> progress, CancellationToken token = default) |         public async Task DownloadDataAsync4Speed(HttpClient client, string url, IProgress<string> progress, CancellationToken token = default) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(url)) |             if (url.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 throw new ArgumentNullException(nameof(url)); |                 throw new ArgumentNullException(nameof(url)); | ||||||
|             } |             } | ||||||
|  | @ -173,7 +188,7 @@ namespace ServiceLib.Common | ||||||
| 
 | 
 | ||||||
|                     totalRead += read; |                     totalRead += read; | ||||||
| 
 | 
 | ||||||
|                     var ts = (DateTime.Now - totalDatetime); |                     var ts = DateTime.Now - totalDatetime; | ||||||
|                     if (progress != null && ts.Seconds > totalSecond) |                     if (progress != null && ts.Seconds > totalSecond) | ||||||
|                     { |                     { | ||||||
|                         totalSecond = ts.Seconds; |                         totalSecond = ts.Seconds; | ||||||
|  |  | ||||||
|  | @ -15,28 +15,30 @@ namespace ServiceLib.Common | ||||||
|         public Job() |         public Job() | ||||||
|         { |         { | ||||||
|             handle = CreateJobObject(IntPtr.Zero, null); |             handle = CreateJobObject(IntPtr.Zero, null); | ||||||
|             IntPtr extendedInfoPtr = IntPtr.Zero; |             var extendedInfoPtr = IntPtr.Zero; | ||||||
|             JOBOBJECT_BASIC_LIMIT_INFORMATION info = new() |             var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION | ||||||
|             { |             { | ||||||
|                 LimitFlags = 0x2000 |                 LimitFlags = 0x2000 | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|             JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new() |             var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION | ||||||
|             { |             { | ||||||
|                 BasicLimitInformation = info |                 BasicLimitInformation = info | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); |                 var length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); | ||||||
|                 extendedInfoPtr = Marshal.AllocHGlobal(length); |                 extendedInfoPtr = Marshal.AllocHGlobal(length); | ||||||
|                 Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); |                 Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); | ||||||
| 
 | 
 | ||||||
|                 if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, |                 if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, | ||||||
|                         (uint)length)) |                         (uint)length)) | ||||||
|  |                 { | ||||||
|                     throw new Exception(string.Format("Unable to set information.  Error: {0}", |                     throw new Exception(string.Format("Unable to set information.  Error: {0}", | ||||||
|                         Marshal.GetLastWin32Error())); |                         Marshal.GetLastWin32Error())); | ||||||
|                 } |                 } | ||||||
|  |             } | ||||||
|             finally |             finally | ||||||
|             { |             { | ||||||
|                 if (extendedInfoPtr != IntPtr.Zero) |                 if (extendedInfoPtr != IntPtr.Zero) | ||||||
|  | @ -48,7 +50,7 @@ namespace ServiceLib.Common | ||||||
| 
 | 
 | ||||||
|         public bool AddProcess(IntPtr processHandle) |         public bool AddProcess(IntPtr processHandle) | ||||||
|         { |         { | ||||||
|             bool succ = AssignProcessToJobObject(handle, processHandle); |             var succ = AssignProcessToJobObject(handle, processHandle); | ||||||
| 
 | 
 | ||||||
|             if (!succ) |             if (!succ) | ||||||
|             { |             { | ||||||
|  | @ -76,7 +78,9 @@ namespace ServiceLib.Common | ||||||
|         private void Dispose(bool disposing) |         private void Dispose(bool disposing) | ||||||
|         { |         { | ||||||
|             if (disposed) |             if (disposed) | ||||||
|  |             { | ||||||
|                 return; |                 return; | ||||||
|  |             } | ||||||
|             disposed = true; |             disposed = true; | ||||||
| 
 | 
 | ||||||
|             if (disposing) |             if (disposing) | ||||||
|  | @ -104,7 +108,7 @@ namespace ServiceLib.Common | ||||||
|         private static extern IntPtr CreateJobObject(IntPtr a, string? lpName); |         private static extern IntPtr CreateJobObject(IntPtr a, string? lpName); | ||||||
| 
 | 
 | ||||||
|         [DllImport("kernel32.dll", SetLastError = true)] |         [DllImport("kernel32.dll", SetLastError = true)] | ||||||
|         private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, UInt32 cbJobObjectInfoLength); |         private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength); | ||||||
| 
 | 
 | ||||||
|         [DllImport("kernel32.dll", SetLastError = true)] |         [DllImport("kernel32.dll", SetLastError = true)] | ||||||
|         private static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process); |         private static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process); | ||||||
|  | @ -121,34 +125,34 @@ namespace ServiceLib.Common | ||||||
|     [StructLayout(LayoutKind.Sequential)] |     [StructLayout(LayoutKind.Sequential)] | ||||||
|     internal struct IO_COUNTERS |     internal struct IO_COUNTERS | ||||||
|     { |     { | ||||||
|         public UInt64 ReadOperationCount; |         public ulong ReadOperationCount; | ||||||
|         public UInt64 WriteOperationCount; |         public ulong WriteOperationCount; | ||||||
|         public UInt64 OtherOperationCount; |         public ulong OtherOperationCount; | ||||||
|         public UInt64 ReadTransferCount; |         public ulong ReadTransferCount; | ||||||
|         public UInt64 WriteTransferCount; |         public ulong WriteTransferCount; | ||||||
|         public UInt64 OtherTransferCount; |         public ulong OtherTransferCount; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     [StructLayout(LayoutKind.Sequential)] |     [StructLayout(LayoutKind.Sequential)] | ||||||
|     internal struct JOBOBJECT_BASIC_LIMIT_INFORMATION |     internal struct JOBOBJECT_BASIC_LIMIT_INFORMATION | ||||||
|     { |     { | ||||||
|         public Int64 PerProcessUserTimeLimit; |         public long PerProcessUserTimeLimit; | ||||||
|         public Int64 PerJobUserTimeLimit; |         public long PerJobUserTimeLimit; | ||||||
|         public UInt32 LimitFlags; |         public uint LimitFlags; | ||||||
|         public UIntPtr MinimumWorkingSetSize; |         public UIntPtr MinimumWorkingSetSize; | ||||||
|         public UIntPtr MaximumWorkingSetSize; |         public UIntPtr MaximumWorkingSetSize; | ||||||
|         public UInt32 ActiveProcessLimit; |         public uint ActiveProcessLimit; | ||||||
|         public UIntPtr Affinity; |         public UIntPtr Affinity; | ||||||
|         public UInt32 PriorityClass; |         public uint PriorityClass; | ||||||
|         public UInt32 SchedulingClass; |         public uint SchedulingClass; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     [StructLayout(LayoutKind.Sequential)] |     [StructLayout(LayoutKind.Sequential)] | ||||||
|     public struct SECURITY_ATTRIBUTES |     public struct SECURITY_ATTRIBUTES | ||||||
|     { |     { | ||||||
|         public UInt32 nLength; |         public uint nLength; | ||||||
|         public IntPtr lpSecurityDescriptor; |         public IntPtr lpSecurityDescriptor; | ||||||
|         public Int32 bInheritHandle; |         public int bInheritHandle; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     [StructLayout(LayoutKind.Sequential)] |     [StructLayout(LayoutKind.Sequential)] | ||||||
|  |  | ||||||
|  | @ -28,7 +28,9 @@ namespace ServiceLib.Common | ||||||
|         public static void SaveLog(string strContent) |         public static void SaveLog(string strContent) | ||||||
|         { |         { | ||||||
|             if (!LogManager.IsLoggingEnabled()) |             if (!LogManager.IsLoggingEnabled()) | ||||||
|  |             { | ||||||
|                 return; |                 return; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             LogManager.GetLogger("Log1").Info(strContent); |             LogManager.GetLogger("Log1").Info(strContent); | ||||||
|         } |         } | ||||||
|  | @ -36,7 +38,9 @@ namespace ServiceLib.Common | ||||||
|         public static void SaveLog(string strTitle, Exception ex) |         public static void SaveLog(string strTitle, Exception ex) | ||||||
|         { |         { | ||||||
|             if (!LogManager.IsLoggingEnabled()) |             if (!LogManager.IsLoggingEnabled()) | ||||||
|  |             { | ||||||
|                 return; |                 return; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             var logger = LogManager.GetLogger("Log2"); |             var logger = LogManager.GetLogger("Log2"); | ||||||
|             logger.Debug($"{strTitle},{ex.Message}"); |             logger.Debug($"{strTitle},{ex.Message}"); | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ public static class ProcUtils | ||||||
| 
 | 
 | ||||||
|     public static void ProcessStart(string? fileName, string arguments = "") |     public static void ProcessStart(string? fileName, string arguments = "") | ||||||
|     { |     { | ||||||
|         ProcessStart(fileName, arguments, null); |         _ = ProcessStart(fileName, arguments, null); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static int? ProcessStart(string? fileName, string arguments, string? dir) |     public static int? ProcessStart(string? fileName, string arguments, string? dir) | ||||||
|  | @ -38,7 +38,7 @@ public static class ProcUtils | ||||||
|                     WorkingDirectory = dir ?? string.Empty |                     WorkingDirectory = dir ?? string.Empty | ||||||
|                 } |                 } | ||||||
|             }; |             }; | ||||||
|             proc.Start(); |             _ = proc.Start(); | ||||||
|             return dir is null ? null : proc.Id; |             return dir is null ? null : proc.Id; | ||||||
|         } |         } | ||||||
|         catch (Exception ex) |         catch (Exception ex) | ||||||
|  | @ -60,7 +60,7 @@ public static class ProcUtils | ||||||
|                 FileName = Utils.GetExePath().AppendQuotes(), |                 FileName = Utils.GetExePath().AppendQuotes(), | ||||||
|                 Verb = blAdmin ? "runas" : null, |                 Verb = blAdmin ? "runas" : null, | ||||||
|             }; |             }; | ||||||
|             Process.Start(startInfo); |             _ = Process.Start(startInfo); | ||||||
|         } |         } | ||||||
|         catch (Exception ex) |         catch (Exception ex) | ||||||
|         { |         { | ||||||
|  | @ -138,7 +138,9 @@ public static class ProcUtils | ||||||
|         fileName = null; |         fileName = null; | ||||||
|         processName = null; |         processName = null; | ||||||
|         if (!review) |         if (!review) | ||||||
|  |         { | ||||||
|             return; |             return; | ||||||
|  |         } | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             procId = proc?.Id; |             procId = proc?.Id; | ||||||
|  |  | ||||||
|  | @ -60,7 +60,7 @@ namespace ServiceLib.Common | ||||||
|             var reader = new BarcodeReader(); |             var reader = new BarcodeReader(); | ||||||
|             var result = reader.Decode(bitmap); |             var result = reader.Decode(bitmap); | ||||||
| 
 | 
 | ||||||
|             if (result != null && Utils.IsNotEmpty(result.Text)) |             if (result != null && result.Text.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 return result.Text; |                 return result.Text; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -1,29 +1,29 @@ | ||||||
| namespace ServiceLib.Common | namespace ServiceLib.Common | ||||||
| { | { | ||||||
|     public class SemanticVersion |     public class SemanticVersion | ||||||
|     { |     { | ||||||
|         private int major; |         private readonly int major; | ||||||
|         private int minor; |         private readonly int minor; | ||||||
|         private int patch; |         private readonly int patch; | ||||||
|         private string version; |         private readonly string version; | ||||||
| 
 | 
 | ||||||
|         public SemanticVersion(int major, int minor, int patch) |         public SemanticVersion(int major, int minor, int patch) | ||||||
|         { |         { | ||||||
|             this.major = major; |             this.major = major; | ||||||
|             this.minor = minor; |             this.minor = minor; | ||||||
|             this.patch = patch; |             this.patch = patch; | ||||||
|             this.version = $"{major}.{minor}.{patch}"; |             version = $"{major}.{minor}.{patch}"; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public SemanticVersion(string? version) |         public SemanticVersion(string? version) | ||||||
|         { |         { | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 if (version.IsNullOrEmpty()) |                 if (string.IsNullOrEmpty(version)) | ||||||
|                 { |                 { | ||||||
|                     this.major = 0; |                     major = 0; | ||||||
|                     this.minor = 0; |                     minor = 0; | ||||||
|                     this.patch = 0; |                     patch = 0; | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|                 this.version = version.RemovePrefix('v'); |                 this.version = version.RemovePrefix('v'); | ||||||
|  | @ -31,15 +31,15 @@ | ||||||
|                 var parts = this.version.Split('.'); |                 var parts = this.version.Split('.'); | ||||||
|                 if (parts.Length == 2) |                 if (parts.Length == 2) | ||||||
|                 { |                 { | ||||||
|                     this.major = int.Parse(parts.First()); |                     major = int.Parse(parts.First()); | ||||||
|                     this.minor = int.Parse(parts.Last()); |                     minor = int.Parse(parts.Last()); | ||||||
|                     this.patch = 0; |                     patch = 0; | ||||||
|                 } |                 } | ||||||
|                 else if (parts.Length is 3 or 4) |                 else if (parts.Length is 3 or 4) | ||||||
|                 { |                 { | ||||||
|                     this.major = int.Parse(parts[0]); |                     major = int.Parse(parts[0]); | ||||||
|                     this.minor = int.Parse(parts[1]); |                     minor = int.Parse(parts[1]); | ||||||
|                     this.patch = int.Parse(parts[2]); |                     patch = int.Parse(parts[2]); | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
|  | @ -48,9 +48,9 @@ | ||||||
|             } |             } | ||||||
|             catch |             catch | ||||||
|             { |             { | ||||||
|                 this.major = 0; |                 major = 0; | ||||||
|                 this.minor = 0; |                 minor = 0; | ||||||
|                 this.patch = 0; |                 patch = 0; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -58,7 +58,7 @@ | ||||||
|         { |         { | ||||||
|             if (obj is SemanticVersion other) |             if (obj is SemanticVersion other) | ||||||
|             { |             { | ||||||
|                 return this.major == other.major && this.minor == other.minor && this.patch == other.patch; |                 return major == other.major && minor == other.minor && patch == other.patch; | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|  | @ -68,7 +68,7 @@ | ||||||
| 
 | 
 | ||||||
|         public override int GetHashCode() |         public override int GetHashCode() | ||||||
|         { |         { | ||||||
|             return this.major.GetHashCode() ^ this.minor.GetHashCode() ^ this.patch.GetHashCode(); |             return major.GetHashCode() ^ minor.GetHashCode() ^ patch.GetHashCode(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|  | @ -77,18 +77,18 @@ | ||||||
|         /// <returns>major.minor.patch</returns> |         /// <returns>major.minor.patch</returns> | ||||||
|         public override string ToString() |         public override string ToString() | ||||||
|         { |         { | ||||||
|             return this.version; |             return version; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public string ToVersionString(string? prefix = null) |         public string ToVersionString(string? prefix = null) | ||||||
|         { |         { | ||||||
|             if (prefix == null) |             if (prefix == null) | ||||||
|             { |             { | ||||||
|                 return this.version; |                 return version; | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 return $"{prefix}{this.version}"; |                 return $"{prefix}{version}"; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -108,31 +108,31 @@ | ||||||
| 
 | 
 | ||||||
|         private bool GreaterEquals(SemanticVersion other) |         private bool GreaterEquals(SemanticVersion other) | ||||||
|         { |         { | ||||||
|             if (this.major < other.major) |             if (major < other.major) | ||||||
|             { |             { | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|             else if (this.major > other.major) |             else if (major > other.major) | ||||||
|             { |             { | ||||||
|                 return true; |                 return true; | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 if (this.minor < other.minor) |                 if (minor < other.minor) | ||||||
|                 { |                 { | ||||||
|                     return false; |                     return false; | ||||||
|                 } |                 } | ||||||
|                 else if (this.minor > other.minor) |                 else if (minor > other.minor) | ||||||
|                 { |                 { | ||||||
|                     return true; |                     return true; | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
|                     if (this.patch < other.patch) |                     if (patch < other.patch) | ||||||
|                     { |                     { | ||||||
|                         return false; |                         return false; | ||||||
|                     } |                     } | ||||||
|                     else if (this.patch > other.patch) |                     else if (patch > other.patch) | ||||||
|                     { |                     { | ||||||
|                         return true; |                         return true; | ||||||
|                     } |                     } | ||||||
|  | @ -146,31 +146,31 @@ | ||||||
| 
 | 
 | ||||||
|         private bool LessEquals(SemanticVersion other) |         private bool LessEquals(SemanticVersion other) | ||||||
|         { |         { | ||||||
|             if (this.major < other.major) |             if (major < other.major) | ||||||
|             { |             { | ||||||
|                 return true; |                 return true; | ||||||
|             } |             } | ||||||
|             else if (this.major > other.major) |             else if (major > other.major) | ||||||
|             { |             { | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 if (this.minor < other.minor) |                 if (minor < other.minor) | ||||||
|                 { |                 { | ||||||
|                     return true; |                     return true; | ||||||
|                 } |                 } | ||||||
|                 else if (this.minor > other.minor) |                 else if (minor > other.minor) | ||||||
|                 { |                 { | ||||||
|                     return false; |                     return false; | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
|                     if (this.patch < other.patch) |                     if (patch < other.patch) | ||||||
|                     { |                     { | ||||||
|                         return true; |                         return true; | ||||||
|                     } |                     } | ||||||
|                     else if (this.patch > other.patch) |                     else if (patch > other.patch) | ||||||
|                     { |                     { | ||||||
|                         return false; |                         return false; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ namespace ServiceLib.Common | ||||||
|     { |     { | ||||||
|         private static readonly Lazy<SQLiteHelper> _instance = new(() => new()); |         private static readonly Lazy<SQLiteHelper> _instance = new(() => new()); | ||||||
|         public static SQLiteHelper Instance => _instance.Value; |         public static SQLiteHelper Instance => _instance.Value; | ||||||
|         private string _connstr; |         private readonly string _connstr; | ||||||
|         private SQLiteConnection _db; |         private SQLiteConnection _db; | ||||||
|         private SQLiteAsyncConnection _dbAsync; |         private SQLiteAsyncConnection _dbAsync; | ||||||
|         private readonly string _configDB = "guiNDB.db"; |         private readonly string _configDB = "guiNDB.db"; | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ namespace ServiceLib.Common | ||||||
|     { |     { | ||||||
|         public static bool IsNullOrEmpty([NotNullWhen(false)] this string? value) |         public static bool IsNullOrEmpty([NotNullWhen(false)] this string? value) | ||||||
|         { |         { | ||||||
|             return string.IsNullOrEmpty(value); |             return string.IsNullOrEmpty(value) || string.IsNullOrWhiteSpace(value); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static bool IsNullOrWhiteSpace([NotNullWhen(false)] this string? value) |         public static bool IsNullOrWhiteSpace([NotNullWhen(false)] this string? value) | ||||||
|  | @ -22,7 +22,9 @@ namespace ServiceLib.Common | ||||||
|         public static bool BeginWithAny(this string s, IEnumerable<char> chars) |         public static bool BeginWithAny(this string s, IEnumerable<char> chars) | ||||||
|         { |         { | ||||||
|             if (s.IsNullOrEmpty()) |             if (s.IsNullOrEmpty()) | ||||||
|  |             { | ||||||
|                 return false; |                 return false; | ||||||
|  |             } | ||||||
|             return chars.Contains(s.First()); |             return chars.Contains(s.First()); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -36,7 +38,9 @@ namespace ServiceLib.Common | ||||||
|             while (reader.ReadLine() is { } line) |             while (reader.ReadLine() is { } line) | ||||||
|             { |             { | ||||||
|                 if (line.IsWhiteSpace()) |                 if (line.IsWhiteSpace()) | ||||||
|  |                 { | ||||||
|                     continue; |                     continue; | ||||||
|  |                 } | ||||||
|                 yield return line; |                 yield return line; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -70,5 +74,10 @@ namespace ServiceLib.Common | ||||||
|         { |         { | ||||||
|             return string.IsNullOrEmpty(value) ? string.Empty : $"\"{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; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -20,85 +20,69 @@ namespace ServiceLib.Common | ||||||
|         #region 转换函数 |         #region 转换函数 | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 转逗号分隔的字符串 |         /// Convert to comma-separated string | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="lst"></param> |         /// <param name="lst"></param> | ||||||
|         /// <param name="wrap"></param> |         /// <param name="wrap"></param> | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public static string List2String(List<string>? lst, bool wrap = false) |         public static string List2String(List<string>? lst, bool wrap = false) | ||||||
|         { |         { | ||||||
|             try |             if (lst == null || lst.Count == 0) | ||||||
|             { |  | ||||||
|                 if (lst == null) |  | ||||||
|             { |             { | ||||||
|                 return string.Empty; |                 return string.Empty; | ||||||
|             } |             } | ||||||
|                 if (wrap) | 
 | ||||||
|  |             var separator = wrap ? "," + Environment.NewLine : ","; | ||||||
|  | 
 | ||||||
|  |             try | ||||||
|             { |             { | ||||||
|                     return string.Join("," + Environment.NewLine, lst); |                 return string.Join(separator, lst); | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     return string.Join(",", lst); |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|             catch (Exception ex) |             catch (Exception ex) | ||||||
|             { |             { | ||||||
|                 Logging.SaveLog(_tag, ex); |                 Logging.SaveLog(_tag, ex); | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|                 return string.Empty; |                 return string.Empty; | ||||||
|             } |             } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 逗号分隔的字符串 |         /// Comma-separated string | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="str"></param> |         /// <param name="str"></param> | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public static List<string>? String2List(string? str) |         public static List<string>? String2List(string? str) | ||||||
|         { |         { | ||||||
|             try |             if (string.IsNullOrWhiteSpace(str)) | ||||||
|             { |  | ||||||
|                 if (str == null) |  | ||||||
|             { |             { | ||||||
|                 return null; |                 return null; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|                 str = str.Replace(Environment.NewLine, ""); |             try | ||||||
|  |             { | ||||||
|  |                 str = str.Replace(Environment.NewLine, string.Empty); | ||||||
|                 return new List<string>(str.Split(',', StringSplitOptions.RemoveEmptyEntries)); |                 return new List<string>(str.Split(',', StringSplitOptions.RemoveEmptyEntries)); | ||||||
|             } |             } | ||||||
|             catch (Exception ex) |             catch (Exception ex) | ||||||
|             { |             { | ||||||
|                 Logging.SaveLog(_tag, ex); |                 Logging.SaveLog(_tag, ex); | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|                 return null; |                 return null; | ||||||
|             } |             } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 逗号分隔的字符串,先排序后转List |         /// Comma-separated string, sorted and then converted to List | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="str"></param> |         /// <param name="str"></param> | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public static List<string>? String2ListSorted(string str) |         public static List<string>? String2ListSorted(string str) | ||||||
|         { |         { | ||||||
|             try |             var lst = String2List(str); | ||||||
|             { |             lst?.Sort(); | ||||||
|                 str = str.Replace(Environment.NewLine, ""); |             return lst; | ||||||
|                 List<string> list = new(str.Split(',', StringSplitOptions.RemoveEmptyEntries)); |  | ||||||
|                 list.Sort(); |  | ||||||
|                 return list; |  | ||||||
|             } |  | ||||||
|             catch (Exception ex) |  | ||||||
|             { |  | ||||||
|                 Logging.SaveLog(_tag, ex); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return null; |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Base64编码 |         /// Base64 Encode | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="plainText"></param> |         /// <param name="plainText"></param> | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|  | @ -118,7 +102,7 @@ namespace ServiceLib.Common | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Base64解码 |         /// Base64 Decode | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="plainText"></param> |         /// <param name="plainText"></param> | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|  | @ -127,7 +111,10 @@ namespace ServiceLib.Common | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 if (plainText.IsNullOrEmpty()) |                 if (plainText.IsNullOrEmpty()) | ||||||
|  |                 { | ||||||
|                     return ""; |                     return ""; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|                 plainText = plainText.Trim() |                 plainText = plainText.Trim() | ||||||
|                     .Replace(Environment.NewLine, "") |                     .Replace(Environment.NewLine, "") | ||||||
|                     .Replace("\n", "") |                     .Replace("\n", "") | ||||||
|  | @ -152,18 +139,6 @@ namespace ServiceLib.Common | ||||||
|             return string.Empty; |             return string.Empty; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static int ToInt(object? obj) |  | ||||||
|         { |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 return Convert.ToInt32(obj ?? string.Empty); |  | ||||||
|             } |  | ||||||
|             catch |  | ||||||
|             { |  | ||||||
|                 return 0; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public static bool ToBool(object obj) |         public static bool ToBool(object obj) | ||||||
|         { |         { | ||||||
|             try |             try | ||||||
|  | @ -188,55 +163,25 @@ namespace ServiceLib.Common | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private static void ToHumanReadable(long amount, out double result, out string unit) |  | ||||||
|         { |  | ||||||
|             var factor = 1024u; |  | ||||||
|             //long KBs = amount / factor; |  | ||||||
|             var KBs = amount; |  | ||||||
|             if (KBs > 0) |  | ||||||
|             { |  | ||||||
|                 // multi KB |  | ||||||
|                 var MBs = KBs / factor; |  | ||||||
|                 if (MBs > 0) |  | ||||||
|                 { |  | ||||||
|                     // multi MB |  | ||||||
|                     var GBs = MBs / factor; |  | ||||||
|                     if (GBs > 0) |  | ||||||
|                     { |  | ||||||
|                         // multi GB |  | ||||||
|                         var TBs = GBs / factor; |  | ||||||
|                         if (TBs > 0) |  | ||||||
|                         { |  | ||||||
|                             result = TBs + ((GBs % factor) / (factor + 0.0)); |  | ||||||
|                             unit = "TB"; |  | ||||||
|                             return; |  | ||||||
|                         } |  | ||||||
| 
 |  | ||||||
|                         result = GBs + ((MBs % factor) / (factor + 0.0)); |  | ||||||
|                         unit = "GB"; |  | ||||||
|                         return; |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     result = MBs + ((KBs % factor) / (factor + 0.0)); |  | ||||||
|                     unit = "MB"; |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 result = KBs + ((amount % factor) / (factor + 0.0)); |  | ||||||
|                 unit = "KB"; |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 result = amount; |  | ||||||
|                 unit = "B"; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public static string HumanFy(long amount) |         public static string HumanFy(long amount) | ||||||
|         { |         { | ||||||
|             ToHumanReadable(amount, out var result, out var unit); |             if (amount <= 0) | ||||||
|             return $"{result:f1} {unit}"; |             { | ||||||
|  |                 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) |         public static string UrlEncode(string url) | ||||||
|  | @ -252,7 +197,7 @@ namespace ServiceLib.Common | ||||||
|         public static NameValueCollection ParseQueryString(string query) |         public static NameValueCollection ParseQueryString(string query) | ||||||
|         { |         { | ||||||
|             var result = new NameValueCollection(StringComparer.OrdinalIgnoreCase); |             var result = new NameValueCollection(StringComparer.OrdinalIgnoreCase); | ||||||
|             if (IsNullOrEmpty(query)) |             if (query.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return result; |                 return result; | ||||||
|             } |             } | ||||||
|  | @ -298,7 +243,7 @@ namespace ServiceLib.Common | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public static string GetPunycode(string url) |         public static string GetPunycode(string url) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(url)) |             if (url.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return url; |                 return url; | ||||||
|             } |             } | ||||||
|  | @ -331,7 +276,7 @@ namespace ServiceLib.Common | ||||||
| 
 | 
 | ||||||
|         public static string Convert2Comma(string text) |         public static string Convert2Comma(string text) | ||||||
|         { |         { | ||||||
|             if (IsNullOrEmpty(text)) |             if (text.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return text; |                 return text; | ||||||
|             } |             } | ||||||
|  | @ -344,7 +289,7 @@ namespace ServiceLib.Common | ||||||
|         #region 数据检查 |         #region 数据检查 | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 判断输入的是否是数字 |         /// Determine if the input is a number | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="oText"></param> |         /// <param name="oText"></param> | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|  | @ -353,28 +298,13 @@ namespace ServiceLib.Common | ||||||
|             return oText.All(char.IsNumber); |             return oText.All(char.IsNumber); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static bool IsNullOrEmpty(string? text) |  | ||||||
|         { |  | ||||||
|             if (string.IsNullOrWhiteSpace(text)) |  | ||||||
|             { |  | ||||||
|                 return true; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return text == "null"; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public static bool IsNotEmpty(string? text) |  | ||||||
|         { |  | ||||||
|             return !string.IsNullOrEmpty(text); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 验证Domain地址是否合法 |         /// Validate if the domain address is valid | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="domain"></param> |         /// <param name="domain"></param> | ||||||
|         public static bool IsDomain(string? domain) |         public static bool IsDomain(string? domain) | ||||||
|         { |         { | ||||||
|             if (IsNullOrEmpty(domain)) |             if (domain.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|  | @ -491,7 +421,7 @@ namespace ServiceLib.Common | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 取得版本 |         /// Get version | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public static string GetVersion(bool blFull = true) |         public static string GetVersion(bool blFull = true) | ||||||
|  | @ -529,7 +459,7 @@ namespace ServiceLib.Common | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 取得GUID |         /// GUID | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public static string GetGuid(bool full = true) |         public static string GetGuid(bool full = true) | ||||||
|  | @ -660,7 +590,7 @@ namespace ServiceLib.Common | ||||||
|         public static string GetPath(string fileName) |         public static string GetPath(string fileName) | ||||||
|         { |         { | ||||||
|             var startupPath = StartupPath(); |             var startupPath = StartupPath(); | ||||||
|             if (IsNullOrEmpty(fileName)) |             if (fileName.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return startupPath; |                 return startupPath; | ||||||
|             } |             } | ||||||
|  | @ -696,7 +626,7 @@ namespace ServiceLib.Common | ||||||
|                 Directory.CreateDirectory(tempPath); |                 Directory.CreateDirectory(tempPath); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (IsNullOrEmpty(filename)) |             if (filename.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return tempPath; |                 return tempPath; | ||||||
|             } |             } | ||||||
|  | @ -725,7 +655,7 @@ namespace ServiceLib.Common | ||||||
|                 Directory.CreateDirectory(tempPath); |                 Directory.CreateDirectory(tempPath); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (Utils.IsNullOrEmpty(filename)) |             if (filename.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return tempPath; |                 return tempPath; | ||||||
|             } |             } | ||||||
|  | @ -752,7 +682,7 @@ namespace ServiceLib.Common | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (IsNullOrEmpty(filename)) |             if (filename.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return tempPath; |                 return tempPath; | ||||||
|             } |             } | ||||||
|  | @ -770,7 +700,7 @@ namespace ServiceLib.Common | ||||||
|                 Directory.CreateDirectory(tempPath); |                 Directory.CreateDirectory(tempPath); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (Utils.IsNullOrEmpty(filename)) |             if (filename.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return tempPath; |                 return tempPath; | ||||||
|             } |             } | ||||||
|  | @ -788,7 +718,7 @@ namespace ServiceLib.Common | ||||||
|                 Directory.CreateDirectory(tempPath); |                 Directory.CreateDirectory(tempPath); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (Utils.IsNullOrEmpty(filename)) |             if (filename.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return tempPath; |                 return tempPath; | ||||||
|             } |             } | ||||||
|  | @ -806,7 +736,7 @@ namespace ServiceLib.Common | ||||||
|                 Directory.CreateDirectory(tempPath); |                 Directory.CreateDirectory(tempPath); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (Utils.IsNullOrEmpty(filename)) |             if (filename.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return tempPath; |                 return tempPath; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -15,7 +15,7 @@ namespace ServiceLib.Common | ||||||
|             { |             { | ||||||
|                 regKey = Registry.CurrentUser.OpenSubKey(path, false); |                 regKey = Registry.CurrentUser.OpenSubKey(path, false); | ||||||
|                 var value = regKey?.GetValue(name) as string; |                 var value = regKey?.GetValue(name) as string; | ||||||
|                 return Utils.IsNullOrEmpty(value) ? def : value; |                 return value.IsNullOrEmpty() ? def : value; | ||||||
|             } |             } | ||||||
|             catch (Exception ex) |             catch (Exception ex) | ||||||
|             { |             { | ||||||
|  | @ -34,7 +34,7 @@ namespace ServiceLib.Common | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 regKey = Registry.CurrentUser.CreateSubKey(path); |                 regKey = Registry.CurrentUser.CreateSubKey(path); | ||||||
|                 if (Utils.IsNullOrEmpty(value.ToString())) |                 if (value.ToString().IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     regKey?.DeleteValue(name, false); |                     regKey?.DeleteValue(name, false); | ||||||
|                 } |                 } | ||||||
|  | @ -63,7 +63,7 @@ namespace ServiceLib.Common | ||||||
|                 var arg = $$""" /remove-device  "SWD\Wintun\{{{guid}}}" """; |                 var arg = $$""" /remove-device  "SWD\Wintun\{{{guid}}}" """; | ||||||
| 
 | 
 | ||||||
|                 // Try to remove the device |                 // Try to remove the device | ||||||
|                 await Utils.GetCliWrapOutput(pnpUtilPath, arg); |                 _ = await Utils.GetCliWrapOutput(pnpUtilPath, arg); | ||||||
|             } |             } | ||||||
|             catch (Exception ex) |             catch (Exception ex) | ||||||
|             { |             { | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| using YamlDotNet.Core; | using YamlDotNet.Core; | ||||||
| using YamlDotNet.Serialization; | using YamlDotNet.Serialization; | ||||||
| using YamlDotNet.Serialization.NamingConventions; | using YamlDotNet.Serialization.NamingConventions; | ||||||
| 
 | 
 | ||||||
|  | @ -62,9 +62,6 @@ namespace ServiceLib.Common | ||||||
| 
 | 
 | ||||||
|         public static string? PreprocessYaml(string str) |         public static string? PreprocessYaml(string str) | ||||||
|         { |         { | ||||||
|             var deserializer = new DeserializerBuilder() |  | ||||||
|                 .WithNamingConvention(PascalCaseNamingConvention.Instance) |  | ||||||
|                 .Build(); |  | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 var mergingParser = new MergingParser(new Parser(new StringReader(str))); |                 var mergingParser = new MergingParser(new Parser(new StringReader(str))); | ||||||
|  |  | ||||||
|  | @ -131,7 +131,7 @@ namespace ServiceLib.Handler | ||||||
| 
 | 
 | ||||||
|         public async Task<List<ProfileItem>?> ProfileItems(string subid) |         public async Task<List<ProfileItem>?> ProfileItems(string subid) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(subid)) |             if (subid.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return await SQLiteHelper.Instance.TableAsync<ProfileItem>().ToListAsync(); |                 return await SQLiteHelper.Instance.TableAsync<ProfileItem>().ToListAsync(); | ||||||
|             } |             } | ||||||
|  | @ -153,11 +153,11 @@ namespace ServiceLib.Handler | ||||||
|                         from ProfileItem a |                         from ProfileItem a | ||||||
|                         left join SubItem b on a.subid = b.id |                         left join SubItem b on a.subid = b.id | ||||||
|                         where 1=1 ";
 |                         where 1=1 ";
 | ||||||
|             if (Utils.IsNotEmpty(subid)) |             if (subid.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 sql += $" and a.subid = '{subid}'"; |                 sql += $" and a.subid = '{subid}'"; | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(filter)) |             if (filter.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 if (filter.Contains('\'')) |                 if (filter.Contains('\'')) | ||||||
|                 { |                 { | ||||||
|  | @ -171,7 +171,7 @@ namespace ServiceLib.Handler | ||||||
| 
 | 
 | ||||||
|         public async Task<ProfileItem?> GetProfileItem(string indexId) |         public async Task<ProfileItem?> GetProfileItem(string indexId) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(indexId)) |             if (indexId.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return null; |                 return null; | ||||||
|             } |             } | ||||||
|  | @ -180,7 +180,7 @@ namespace ServiceLib.Handler | ||||||
| 
 | 
 | ||||||
|         public async Task<ProfileItem?> GetProfileItemViaRemarks(string? remarks) |         public async Task<ProfileItem?> GetProfileItemViaRemarks(string? remarks) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(remarks)) |             if (remarks.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return null; |                 return null; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -85,7 +85,7 @@ namespace ServiceLib.Handler | ||||||
|         /// <exception cref="ArgumentNullException"></exception> |         /// <exception cref="ArgumentNullException"></exception> | ||||||
|         public static void AutoStartTaskService(string taskName, string fileName, string description) |         public static void AutoStartTaskService(string taskName, string fileName, string description) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(taskName)) |             if (taskName.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  | @ -93,7 +93,7 @@ namespace ServiceLib.Handler | ||||||
|             var logonUser = WindowsIdentity.GetCurrent().Name; |             var logonUser = WindowsIdentity.GetCurrent().Name; | ||||||
|             using var taskService = new Microsoft.Win32.TaskScheduler.TaskService(); |             using var taskService = new Microsoft.Win32.TaskScheduler.TaskService(); | ||||||
|             var tasks = taskService.RootFolder.GetTasks(new Regex(taskName)); |             var tasks = taskService.RootFolder.GetTasks(new Regex(taskName)); | ||||||
|             if (Utils.IsNullOrEmpty(fileName)) |             if (fileName.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 foreach (var t in tasks) |                 foreach (var t in tasks) | ||||||
|                 { |                 { | ||||||
|  |  | ||||||
|  | @ -37,7 +37,7 @@ namespace ServiceLib.Handler | ||||||
| 
 | 
 | ||||||
|         public void ClashProxiesDelayTest(bool blAll, List<ClashProxyModel> lstProxy, Action<ClashProxyModel?, string> updateFunc) |         public void ClashProxiesDelayTest(bool blAll, List<ClashProxyModel> lstProxy, Action<ClashProxyModel?, string> updateFunc) | ||||||
|         { |         { | ||||||
|             Task.Run(() => |             Task.Run(async () => | ||||||
|             { |             { | ||||||
|                 if (blAll) |                 if (blAll) | ||||||
|                 { |                 { | ||||||
|  | @ -47,7 +47,7 @@ namespace ServiceLib.Handler | ||||||
|                         { |                         { | ||||||
|                             break; |                             break; | ||||||
|                         } |                         } | ||||||
|                         Task.Delay(5000).Wait(); |                         await Task.Delay(5000); | ||||||
|                     } |                     } | ||||||
|                     if (_proxies == null) |                     if (_proxies == null) | ||||||
|                     { |                     { | ||||||
|  | @ -90,9 +90,8 @@ namespace ServiceLib.Handler | ||||||
|                         updateFunc?.Invoke(it, result); |                         updateFunc?.Invoke(it, result); | ||||||
|                     })); |                     })); | ||||||
|                 } |                 } | ||||||
|                 Task.WaitAll(tasks.ToArray()); |                 await Task.WhenAll(tasks); | ||||||
| 
 |                 await Task.Delay(1000); | ||||||
|                 Task.Delay(1000).Wait(); |  | ||||||
|                 updateFunc?.Invoke(null, ""); |                 updateFunc?.Invoke(null, ""); | ||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -22,7 +22,7 @@ namespace ServiceLib.Handler | ||||||
|         { |         { | ||||||
|             Config? config = null; |             Config? config = null; | ||||||
|             var result = EmbedUtils.LoadResource(Utils.GetConfigPath(_configRes)); |             var result = EmbedUtils.LoadResource(Utils.GetConfigPath(_configRes)); | ||||||
|             if (Utils.IsNotEmpty(result)) |             if (result.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 config = JsonUtils.Deserialize<Config>(result); |                 config = JsonUtils.Deserialize<Config>(result); | ||||||
|             } |             } | ||||||
|  | @ -67,7 +67,7 @@ namespace ServiceLib.Handler | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             config.RoutingBasicItem ??= new(); |             config.RoutingBasicItem ??= new(); | ||||||
|             if (Utils.IsNullOrEmpty(config.RoutingBasicItem.DomainStrategy)) |             if (config.RoutingBasicItem.DomainStrategy.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 config.RoutingBasicItem.DomainStrategy = Global.DomainStrategies.First(); |                 config.RoutingBasicItem.DomainStrategy = Global.DomainStrategies.First(); | ||||||
|             } |             } | ||||||
|  | @ -103,7 +103,7 @@ namespace ServiceLib.Handler | ||||||
|             }; |             }; | ||||||
|             config.UiItem.MainColumnItem ??= new(); |             config.UiItem.MainColumnItem ??= new(); | ||||||
| 
 | 
 | ||||||
|             if (Utils.IsNullOrEmpty(config.UiItem.CurrentLanguage)) |             if (config.UiItem.CurrentLanguage.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 config.UiItem.CurrentLanguage = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName.Equals("zh", StringComparison.CurrentCultureIgnoreCase) |                 config.UiItem.CurrentLanguage = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName.Equals("zh", StringComparison.CurrentCultureIgnoreCase) | ||||||
|                     ? Global.Languages.First() |                     ? Global.Languages.First() | ||||||
|  | @ -117,11 +117,11 @@ namespace ServiceLib.Handler | ||||||
|             { |             { | ||||||
|                 config.SpeedTestItem.SpeedTestTimeout = 10; |                 config.SpeedTestItem.SpeedTestTimeout = 10; | ||||||
|             } |             } | ||||||
|             if (Utils.IsNullOrEmpty(config.SpeedTestItem.SpeedTestUrl)) |             if (config.SpeedTestItem.SpeedTestUrl.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 config.SpeedTestItem.SpeedTestUrl = Global.SpeedTestUrls.First(); |                 config.SpeedTestItem.SpeedTestUrl = Global.SpeedTestUrls.First(); | ||||||
|             } |             } | ||||||
|             if (Utils.IsNullOrEmpty(config.SpeedTestItem.SpeedPingTestUrl)) |             if (config.SpeedTestItem.SpeedPingTestUrl.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 config.SpeedTestItem.SpeedPingTestUrl = Global.SpeedPingTestUrl; |                 config.SpeedTestItem.SpeedPingTestUrl = Global.SpeedPingTestUrl; | ||||||
|             } |             } | ||||||
|  | @ -354,7 +354,7 @@ namespace ServiceLib.Handler | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public static async Task<int> SetDefaultServerIndex(Config config, string? indexId) |         public static async Task<int> SetDefaultServerIndex(Config config, string? indexId) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(indexId)) |             if (indexId.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return -1; |                 return -1; | ||||||
|             } |             } | ||||||
|  | @ -506,7 +506,7 @@ namespace ServiceLib.Handler | ||||||
| 
 | 
 | ||||||
|             profileItem.Address = newFileName; |             profileItem.Address = newFileName; | ||||||
|             profileItem.ConfigType = EConfigType.Custom; |             profileItem.ConfigType = EConfigType.Custom; | ||||||
|             if (Utils.IsNullOrEmpty(profileItem.Remarks)) |             if (profileItem.Remarks.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 profileItem.Remarks = $"import custom@{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")}"; |                 profileItem.Remarks = $"import custom@{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")}"; | ||||||
|             } |             } | ||||||
|  | @ -624,7 +624,7 @@ namespace ServiceLib.Handler | ||||||
| 
 | 
 | ||||||
|             profileItem.Address = profileItem.Address.TrimEx(); |             profileItem.Address = profileItem.Address.TrimEx(); | ||||||
|             profileItem.Id = profileItem.Id.TrimEx(); |             profileItem.Id = profileItem.Id.TrimEx(); | ||||||
|             if (Utils.IsNullOrEmpty(profileItem.StreamSecurity)) |             if (profileItem.StreamSecurity.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 profileItem.StreamSecurity = Global.StreamSecurity; |                 profileItem.StreamSecurity = Global.StreamSecurity; | ||||||
|             } |             } | ||||||
|  | @ -654,7 +654,7 @@ namespace ServiceLib.Handler | ||||||
|             profileItem.Path = profileItem.Path.TrimEx(); |             profileItem.Path = profileItem.Path.TrimEx(); | ||||||
|             profileItem.Network = string.Empty; |             profileItem.Network = string.Empty; | ||||||
| 
 | 
 | ||||||
|             if (Utils.IsNullOrEmpty(profileItem.StreamSecurity)) |             if (profileItem.StreamSecurity.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 profileItem.StreamSecurity = Global.StreamSecurity; |                 profileItem.StreamSecurity = Global.StreamSecurity; | ||||||
|             } |             } | ||||||
|  | @ -689,11 +689,11 @@ namespace ServiceLib.Handler | ||||||
|                 profileItem.HeaderType = Global.TuicCongestionControls.FirstOrDefault()!; |                 profileItem.HeaderType = Global.TuicCongestionControls.FirstOrDefault()!; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (Utils.IsNullOrEmpty(profileItem.StreamSecurity)) |             if (profileItem.StreamSecurity.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 profileItem.StreamSecurity = Global.StreamSecurity; |                 profileItem.StreamSecurity = Global.StreamSecurity; | ||||||
|             } |             } | ||||||
|             if (Utils.IsNullOrEmpty(profileItem.Alpn)) |             if (profileItem.Alpn.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 profileItem.Alpn = "h3"; |                 profileItem.Alpn = "h3"; | ||||||
|             } |             } | ||||||
|  | @ -858,7 +858,7 @@ namespace ServiceLib.Handler | ||||||
|             { |             { | ||||||
|                 return -1; |                 return -1; | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(profileItem.Security) && profileItem.Security != Global.None) |             if (profileItem.Security.IsNotEmpty() && profileItem.Security != Global.None) | ||||||
|             { |             { | ||||||
|                 profileItem.Security = Global.None; |                 profileItem.Security = Global.None; | ||||||
|             } |             } | ||||||
|  | @ -897,7 +897,7 @@ namespace ServiceLib.Handler | ||||||
|         { |         { | ||||||
|             profileItem.ConfigVersion = 2; |             profileItem.ConfigVersion = 2; | ||||||
| 
 | 
 | ||||||
|             if (Utils.IsNotEmpty(profileItem.StreamSecurity)) |             if (profileItem.StreamSecurity.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 if (profileItem.StreamSecurity != Global.StreamSecurity |                 if (profileItem.StreamSecurity != Global.StreamSecurity | ||||||
|                      && profileItem.StreamSecurity != Global.StreamSecurityReality) |                      && profileItem.StreamSecurity != Global.StreamSecurityReality) | ||||||
|  | @ -906,24 +906,24 @@ namespace ServiceLib.Handler | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
|                     if (Utils.IsNullOrEmpty(profileItem.AllowInsecure)) |                     if (profileItem.AllowInsecure.IsNullOrEmpty()) | ||||||
|                     { |                     { | ||||||
|                         profileItem.AllowInsecure = config.CoreBasicItem.DefAllowInsecure.ToString().ToLower(); |                         profileItem.AllowInsecure = config.CoreBasicItem.DefAllowInsecure.ToString().ToLower(); | ||||||
|                     } |                     } | ||||||
|                     if (Utils.IsNullOrEmpty(profileItem.Fingerprint) && profileItem.StreamSecurity == Global.StreamSecurityReality) |                     if (profileItem.Fingerprint.IsNullOrEmpty() && profileItem.StreamSecurity == Global.StreamSecurityReality) | ||||||
|                     { |                     { | ||||||
|                         profileItem.Fingerprint = config.CoreBasicItem.DefFingerprint; |                         profileItem.Fingerprint = config.CoreBasicItem.DefFingerprint; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (Utils.IsNotEmpty(profileItem.Network) && !Global.Networks.Contains(profileItem.Network)) |             if (profileItem.Network.IsNotEmpty() && !Global.Networks.Contains(profileItem.Network)) | ||||||
|             { |             { | ||||||
|                 profileItem.Network = Global.DefaultNetwork; |                 profileItem.Network = Global.DefaultNetwork; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             var maxSort = -1; |             var maxSort = -1; | ||||||
|             if (Utils.IsNullOrEmpty(profileItem.IndexId)) |             if (profileItem.IndexId.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 profileItem.IndexId = Utils.GetGuid(false); |                 profileItem.IndexId = Utils.GetGuid(false); | ||||||
|                 maxSort = ProfileExHandler.Instance.GetMaxSort(); |                 maxSort = ProfileExHandler.Instance.GetMaxSort(); | ||||||
|  | @ -1084,14 +1084,14 @@ namespace ServiceLib.Handler | ||||||
|         /// <returns>成功导入的数量</returns> |         /// <returns>成功导入的数量</returns> | ||||||
|         private static async Task<int> AddBatchServersCommon(Config config, string strData, string subid, bool isSub) |         private static async Task<int> AddBatchServersCommon(Config config, string strData, string subid, bool isSub) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(strData)) |             if (strData.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return -1; |                 return -1; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             var subFilter = string.Empty; |             var subFilter = string.Empty; | ||||||
|             //remove sub items |             //remove sub items | ||||||
|             if (isSub && Utils.IsNotEmpty(subid)) |             if (isSub && subid.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 await RemoveServersViaSubid(config, subid, isSub); |                 await RemoveServersViaSubid(config, subid, isSub); | ||||||
|                 subFilter = (await AppHandler.Instance.GetSubItem(subid))?.Filter ?? ""; |                 subFilter = (await AppHandler.Instance.GetSubItem(subid))?.Filter ?? ""; | ||||||
|  | @ -1122,7 +1122,7 @@ namespace ServiceLib.Handler | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 //exist sub items //filter |                 //exist sub items //filter | ||||||
|                 if (isSub && Utils.IsNotEmpty(subid) && Utils.IsNotEmpty(subFilter)) |                 if (isSub && subid.IsNotEmpty() && subFilter.IsNotEmpty()) | ||||||
|                 { |                 { | ||||||
|                     if (!Regex.IsMatch(profileItem.Remarks, subFilter)) |                     if (!Regex.IsMatch(profileItem.Remarks, subFilter)) | ||||||
|                     { |                     { | ||||||
|  | @ -1163,7 +1163,7 @@ namespace ServiceLib.Handler | ||||||
| 
 | 
 | ||||||
|         private static async Task<int> AddBatchServers4Custom(Config config, string strData, string subid, bool isSub) |         private static async Task<int> AddBatchServers4Custom(Config config, string strData, string subid, bool isSub) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(strData)) |             if (strData.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return -1; |                 return -1; | ||||||
|             } |             } | ||||||
|  | @ -1185,7 +1185,7 @@ namespace ServiceLib.Handler | ||||||
|             } |             } | ||||||
|             if (lstProfiles != null && lstProfiles.Count > 0) |             if (lstProfiles != null && lstProfiles.Count > 0) | ||||||
|             { |             { | ||||||
|                 if (isSub && Utils.IsNotEmpty(subid)) |                 if (isSub && subid.IsNotEmpty()) | ||||||
|                 { |                 { | ||||||
|                     await RemoveServersViaSubid(config, subid, isSub); |                     await RemoveServersViaSubid(config, subid, isSub); | ||||||
|                 } |                 } | ||||||
|  | @ -1236,12 +1236,12 @@ namespace ServiceLib.Handler | ||||||
|             { |             { | ||||||
|                 profileItem = NaiveproxyFmt.ResolveFull(strData, subRemarks); |                 profileItem = NaiveproxyFmt.ResolveFull(strData, subRemarks); | ||||||
|             } |             } | ||||||
|             if (profileItem is null || Utils.IsNullOrEmpty(profileItem.Address)) |             if (profileItem is null || profileItem.Address.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return -1; |                 return -1; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (isSub && Utils.IsNotEmpty(subid)) |             if (isSub && subid.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 await RemoveServersViaSubid(config, subid, isSub); |                 await RemoveServersViaSubid(config, subid, isSub); | ||||||
|             } |             } | ||||||
|  | @ -1261,12 +1261,12 @@ namespace ServiceLib.Handler | ||||||
| 
 | 
 | ||||||
|         private static async Task<int> AddBatchServers4SsSIP008(Config config, string strData, string subid, bool isSub) |         private static async Task<int> AddBatchServers4SsSIP008(Config config, string strData, string subid, bool isSub) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(strData)) |             if (strData.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return -1; |                 return -1; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (isSub && Utils.IsNotEmpty(subid)) |             if (isSub && subid.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 await RemoveServersViaSubid(config, subid, isSub); |                 await RemoveServersViaSubid(config, subid, isSub); | ||||||
|             } |             } | ||||||
|  | @ -1293,13 +1293,13 @@ namespace ServiceLib.Handler | ||||||
| 
 | 
 | ||||||
|         public static async Task<int> AddBatchServers(Config config, string strData, string subid, bool isSub) |         public static async Task<int> AddBatchServers(Config config, string strData, string subid, bool isSub) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(strData)) |             if (strData.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return -1; |                 return -1; | ||||||
|             } |             } | ||||||
|             List<ProfileItem>? lstOriSub = null; |             List<ProfileItem>? lstOriSub = null; | ||||||
|             ProfileItem? activeProfile = null; |             ProfileItem? activeProfile = null; | ||||||
|             if (isSub && Utils.IsNotEmpty(subid)) |             if (isSub && subid.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 lstOriSub = await AppHandler.Instance.ProfileItems(subid); |                 lstOriSub = await AppHandler.Instance.ProfileItems(subid); | ||||||
|                 activeProfile = lstOriSub?.FirstOrDefault(t => t.IndexId == config.IndexId); |                 activeProfile = lstOriSub?.FirstOrDefault(t => t.IndexId == config.IndexId); | ||||||
|  | @ -1424,7 +1424,7 @@ namespace ServiceLib.Handler | ||||||
|                 item.Memo = subItem.Memo; |                 item.Memo = subItem.Memo; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (Utils.IsNullOrEmpty(item.Id)) |             if (item.Id.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 item.Id = Utils.GetGuid(false); |                 item.Id = Utils.GetGuid(false); | ||||||
| 
 | 
 | ||||||
|  | @ -1457,7 +1457,7 @@ namespace ServiceLib.Handler | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public static async Task<int> RemoveServersViaSubid(Config config, string subid, bool isSub) |         public static async Task<int> RemoveServersViaSubid(Config config, string subid, bool isSub) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(subid)) |             if (subid.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return -1; |                 return -1; | ||||||
|             } |             } | ||||||
|  | @ -1508,7 +1508,7 @@ namespace ServiceLib.Handler | ||||||
| 
 | 
 | ||||||
|         public static async Task<int> SaveRoutingItem(Config config, RoutingItem item) |         public static async Task<int> SaveRoutingItem(Config config, RoutingItem item) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(item.Id)) |             if (item.Id.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 item.Id = Utils.GetGuid(false); |                 item.Id = Utils.GetGuid(false); | ||||||
|             } |             } | ||||||
|  | @ -1531,7 +1531,7 @@ namespace ServiceLib.Handler | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public static async Task<int> AddBatchRoutingRules(RoutingItem routingItem, string strData) |         public static async Task<int> AddBatchRoutingRules(RoutingItem routingItem, string strData) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(strData)) |             if (strData.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return -1; |                 return -1; | ||||||
|             } |             } | ||||||
|  | @ -1549,7 +1549,7 @@ namespace ServiceLib.Handler | ||||||
|             routingItem.RuleNum = lstRules.Count; |             routingItem.RuleNum = lstRules.Count; | ||||||
|             routingItem.RuleSet = JsonUtils.Serialize(lstRules, false); |             routingItem.RuleSet = JsonUtils.Serialize(lstRules, false); | ||||||
| 
 | 
 | ||||||
|             if (Utils.IsNullOrEmpty(routingItem.Id)) |             if (routingItem.Id.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 routingItem.Id = Utils.GetGuid(false); |                 routingItem.Id = Utils.GetGuid(false); | ||||||
|             } |             } | ||||||
|  | @ -1668,7 +1668,7 @@ namespace ServiceLib.Handler | ||||||
| 
 | 
 | ||||||
|         public static async Task<int> InitRouting(Config config, bool blImportAdvancedRules = false) |         public static async Task<int> InitRouting(Config config, bool blImportAdvancedRules = false) | ||||||
|         { |         { | ||||||
|             if (string.IsNullOrEmpty(config.ConstItem.RouteRulesTemplateSourceUrl)) |             if (config.ConstItem.RouteRulesTemplateSourceUrl.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 await InitBuiltinRouting(config, blImportAdvancedRules); |                 await InitBuiltinRouting(config, blImportAdvancedRules); | ||||||
|             } |             } | ||||||
|  | @ -1684,7 +1684,7 @@ namespace ServiceLib.Handler | ||||||
|         { |         { | ||||||
|             var downloadHandle = new DownloadService(); |             var downloadHandle = new DownloadService(); | ||||||
|             var templateContent = await downloadHandle.TryDownloadString(config.ConstItem.RouteRulesTemplateSourceUrl, true, ""); |             var templateContent = await downloadHandle.TryDownloadString(config.ConstItem.RouteRulesTemplateSourceUrl, true, ""); | ||||||
|             if (string.IsNullOrEmpty(templateContent)) |             if (templateContent.IsNullOrEmpty()) | ||||||
|                 return await InitBuiltinRouting(config, blImportAdvancedRules); // fallback |                 return await InitBuiltinRouting(config, blImportAdvancedRules); // fallback | ||||||
| 
 | 
 | ||||||
|             var template = JsonUtils.Deserialize<RoutingTemplate>(templateContent); |             var template = JsonUtils.Deserialize<RoutingTemplate>(templateContent); | ||||||
|  | @ -1701,14 +1701,14 @@ namespace ServiceLib.Handler | ||||||
|             { |             { | ||||||
|                 var item = template.RoutingItems[i]; |                 var item = template.RoutingItems[i]; | ||||||
| 
 | 
 | ||||||
|                 if (string.IsNullOrEmpty(item.Url) && string.IsNullOrEmpty(item.RuleSet)) |                 if (item.Url.IsNullOrEmpty() && item.RuleSet.IsNullOrEmpty()) | ||||||
|                     continue; |                     continue; | ||||||
| 
 | 
 | ||||||
|                 var ruleSetsString = !string.IsNullOrEmpty(item.RuleSet) |                 var ruleSetsString = !item.RuleSet.IsNullOrEmpty() | ||||||
|                     ? item.RuleSet |                     ? item.RuleSet | ||||||
|                     : await downloadHandle.TryDownloadString(item.Url, true, ""); |                     : await downloadHandle.TryDownloadString(item.Url, true, ""); | ||||||
| 
 | 
 | ||||||
|                 if (string.IsNullOrEmpty(ruleSetsString)) |                 if (ruleSetsString.IsNullOrEmpty()) | ||||||
|                     continue; |                     continue; | ||||||
| 
 | 
 | ||||||
|                 item.Remarks = $"{template.Version}-{item.Remarks}"; |                 item.Remarks = $"{template.Version}-{item.Remarks}"; | ||||||
|  | @ -1820,7 +1820,7 @@ namespace ServiceLib.Handler | ||||||
|                 return -1; |                 return -1; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (Utils.IsNullOrEmpty(item.Id)) |             if (item.Id.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 item.Id = Utils.GetGuid(false); |                 item.Id = Utils.GetGuid(false); | ||||||
|             } |             } | ||||||
|  | @ -1841,17 +1841,17 @@ namespace ServiceLib.Handler | ||||||
| 
 | 
 | ||||||
|             var downloadHandle = new DownloadService(); |             var downloadHandle = new DownloadService(); | ||||||
|             var templateContent = await downloadHandle.TryDownloadString(url, true, ""); |             var templateContent = await downloadHandle.TryDownloadString(url, true, ""); | ||||||
|             if (string.IsNullOrEmpty(templateContent)) |             if (templateContent.IsNullOrEmpty()) | ||||||
|                 return currentItem; |                 return currentItem; | ||||||
| 
 | 
 | ||||||
|             var template = JsonUtils.Deserialize<DNSItem>(templateContent); |             var template = JsonUtils.Deserialize<DNSItem>(templateContent); | ||||||
|             if (template == null) |             if (template == null) | ||||||
|                 return currentItem; |                 return currentItem; | ||||||
| 
 | 
 | ||||||
|             if (!string.IsNullOrEmpty(template.NormalDNS)) |             if (!template.NormalDNS.IsNullOrEmpty()) | ||||||
|                 template.NormalDNS = await downloadHandle.TryDownloadString(template.NormalDNS, true, ""); |                 template.NormalDNS = await downloadHandle.TryDownloadString(template.NormalDNS, true, ""); | ||||||
| 
 | 
 | ||||||
|             if (!string.IsNullOrEmpty(template.TunDNS)) |             if (!template.TunDNS.IsNullOrEmpty()) | ||||||
|                 template.TunDNS = await downloadHandle.TryDownloadString(template.TunDNS, true, ""); |                 template.TunDNS = await downloadHandle.TryDownloadString(template.TunDNS, true, ""); | ||||||
| 
 | 
 | ||||||
|             template.Id = currentItem.Id; |             template.Id = currentItem.Id; | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ namespace ServiceLib.Handler | ||||||
|             { |             { | ||||||
|                 return result; |                 return result; | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(fileName) && result.Data != null) |             if (fileName.IsNotEmpty() && result.Data != null) | ||||||
|             { |             { | ||||||
|                 await File.WriteAllTextAsync(fileName, result.Data.ToString()); |                 await File.WriteAllTextAsync(fileName, result.Data.ToString()); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -240,7 +240,7 @@ namespace ServiceLib.Handler | ||||||
|         private async Task<Process?> RunProcess(CoreInfo? coreInfo, string configPath, bool displayLog, bool mayNeedSudo) |         private async Task<Process?> RunProcess(CoreInfo? coreInfo, string configPath, bool displayLog, bool mayNeedSudo) | ||||||
|         { |         { | ||||||
|             var fileName = CoreInfoHandler.Instance.GetCoreExecFile(coreInfo, out var msg); |             var fileName = CoreInfoHandler.Instance.GetCoreExecFile(coreInfo, out var msg); | ||||||
|             if (Utils.IsNullOrEmpty(fileName)) |             if (fileName.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 UpdateFunc(false, msg); |                 UpdateFunc(false, msg); | ||||||
|                 return null; |                 return null; | ||||||
|  | @ -274,13 +274,13 @@ namespace ServiceLib.Handler | ||||||
|                 { |                 { | ||||||
|                     proc.OutputDataReceived += (sender, e) => |                     proc.OutputDataReceived += (sender, e) => | ||||||
|                     { |                     { | ||||||
|                         if (Utils.IsNullOrEmpty(e.Data)) |                         if (e.Data.IsNullOrEmpty()) | ||||||
|                             return; |                             return; | ||||||
|                         UpdateFunc(false, e.Data + Environment.NewLine); |                         UpdateFunc(false, e.Data + Environment.NewLine); | ||||||
|                     }; |                     }; | ||||||
|                     proc.ErrorDataReceived += (sender, e) => |                     proc.ErrorDataReceived += (sender, e) => | ||||||
|                     { |                     { | ||||||
|                         if (Utils.IsNullOrEmpty(e.Data)) |                         if (e.Data.IsNullOrEmpty()) | ||||||
|                             return; |                             return; | ||||||
|                         UpdateFunc(false, e.Data + Environment.NewLine); |                         UpdateFunc(false, e.Data + Environment.NewLine); | ||||||
|                     }; |                     }; | ||||||
|  |  | ||||||
|  | @ -16,12 +16,12 @@ namespace ServiceLib.Handler.Fmt | ||||||
| 
 | 
 | ||||||
|         protected static int GetStdTransport(ProfileItem item, string? securityDef, ref Dictionary<string, string> dicQuery) |         protected static int GetStdTransport(ProfileItem item, string? securityDef, ref Dictionary<string, string> dicQuery) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNotEmpty(item.Flow)) |             if (item.Flow.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("flow", item.Flow); |                 dicQuery.Add("flow", item.Flow); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (Utils.IsNotEmpty(item.StreamSecurity)) |             if (item.StreamSecurity.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("security", item.StreamSecurity); |                 dicQuery.Add("security", item.StreamSecurity); | ||||||
|             } |             } | ||||||
|  | @ -32,27 +32,27 @@ namespace ServiceLib.Handler.Fmt | ||||||
|                     dicQuery.Add("security", securityDef); |                     dicQuery.Add("security", securityDef); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(item.Sni)) |             if (item.Sni.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("sni", item.Sni); |                 dicQuery.Add("sni", item.Sni); | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(item.Alpn)) |             if (item.Alpn.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("alpn", Utils.UrlEncode(item.Alpn)); |                 dicQuery.Add("alpn", Utils.UrlEncode(item.Alpn)); | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(item.Fingerprint)) |             if (item.Fingerprint.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("fp", Utils.UrlEncode(item.Fingerprint)); |                 dicQuery.Add("fp", Utils.UrlEncode(item.Fingerprint)); | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(item.PublicKey)) |             if (item.PublicKey.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("pbk", Utils.UrlEncode(item.PublicKey)); |                 dicQuery.Add("pbk", Utils.UrlEncode(item.PublicKey)); | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(item.ShortId)) |             if (item.ShortId.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("sid", Utils.UrlEncode(item.ShortId)); |                 dicQuery.Add("sid", Utils.UrlEncode(item.ShortId)); | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(item.SpiderX)) |             if (item.SpiderX.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("spx", Utils.UrlEncode(item.SpiderX)); |                 dicQuery.Add("spx", Utils.UrlEncode(item.SpiderX)); | ||||||
|             } |             } | ||||||
|  | @ -61,21 +61,21 @@ namespace ServiceLib.Handler.Fmt | ||||||
|                 dicQuery.Add("allowInsecure", "1"); |                 dicQuery.Add("allowInsecure", "1"); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             dicQuery.Add("type", Utils.IsNotEmpty(item.Network) ? item.Network : nameof(ETransport.tcp)); |             dicQuery.Add("type", item.Network.IsNotEmpty() ? item.Network : nameof(ETransport.tcp)); | ||||||
| 
 | 
 | ||||||
|             switch (item.Network) |             switch (item.Network) | ||||||
|             { |             { | ||||||
|                 case nameof(ETransport.tcp): |                 case nameof(ETransport.tcp): | ||||||
|                     dicQuery.Add("headerType", Utils.IsNotEmpty(item.HeaderType) ? item.HeaderType : Global.None); |                     dicQuery.Add("headerType", item.HeaderType.IsNotEmpty() ? item.HeaderType : Global.None); | ||||||
|                     if (Utils.IsNotEmpty(item.RequestHost)) |                     if (item.RequestHost.IsNotEmpty()) | ||||||
|                     { |                     { | ||||||
|                         dicQuery.Add("host", Utils.UrlEncode(item.RequestHost)); |                         dicQuery.Add("host", Utils.UrlEncode(item.RequestHost)); | ||||||
|                     } |                     } | ||||||
|                     break; |                     break; | ||||||
| 
 | 
 | ||||||
|                 case nameof(ETransport.kcp): |                 case nameof(ETransport.kcp): | ||||||
|                     dicQuery.Add("headerType", Utils.IsNotEmpty(item.HeaderType) ? item.HeaderType : Global.None); |                     dicQuery.Add("headerType", item.HeaderType.IsNotEmpty() ? item.HeaderType : Global.None); | ||||||
|                     if (Utils.IsNotEmpty(item.Path)) |                     if (item.Path.IsNotEmpty()) | ||||||
|                     { |                     { | ||||||
|                         dicQuery.Add("seed", Utils.UrlEncode(item.Path)); |                         dicQuery.Add("seed", Utils.UrlEncode(item.Path)); | ||||||
|                     } |                     } | ||||||
|  | @ -83,30 +83,30 @@ namespace ServiceLib.Handler.Fmt | ||||||
| 
 | 
 | ||||||
|                 case nameof(ETransport.ws): |                 case nameof(ETransport.ws): | ||||||
|                 case nameof(ETransport.httpupgrade): |                 case nameof(ETransport.httpupgrade): | ||||||
|                     if (Utils.IsNotEmpty(item.RequestHost)) |                     if (item.RequestHost.IsNotEmpty()) | ||||||
|                     { |                     { | ||||||
|                         dicQuery.Add("host", Utils.UrlEncode(item.RequestHost)); |                         dicQuery.Add("host", Utils.UrlEncode(item.RequestHost)); | ||||||
|                     } |                     } | ||||||
|                     if (Utils.IsNotEmpty(item.Path)) |                     if (item.Path.IsNotEmpty()) | ||||||
|                     { |                     { | ||||||
|                         dicQuery.Add("path", Utils.UrlEncode(item.Path)); |                         dicQuery.Add("path", Utils.UrlEncode(item.Path)); | ||||||
|                     } |                     } | ||||||
|                     break; |                     break; | ||||||
| 
 | 
 | ||||||
|                 case nameof(ETransport.xhttp): |                 case nameof(ETransport.xhttp): | ||||||
|                     if (Utils.IsNotEmpty(item.RequestHost)) |                     if (item.RequestHost.IsNotEmpty()) | ||||||
|                     { |                     { | ||||||
|                         dicQuery.Add("host", Utils.UrlEncode(item.RequestHost)); |                         dicQuery.Add("host", Utils.UrlEncode(item.RequestHost)); | ||||||
|                     } |                     } | ||||||
|                     if (Utils.IsNotEmpty(item.Path)) |                     if (item.Path.IsNotEmpty()) | ||||||
|                     { |                     { | ||||||
|                         dicQuery.Add("path", Utils.UrlEncode(item.Path)); |                         dicQuery.Add("path", Utils.UrlEncode(item.Path)); | ||||||
|                     } |                     } | ||||||
|                     if (Utils.IsNotEmpty(item.HeaderType) && Global.XhttpMode.Contains(item.HeaderType)) |                     if (item.HeaderType.IsNotEmpty() && Global.XhttpMode.Contains(item.HeaderType)) | ||||||
|                     { |                     { | ||||||
|                         dicQuery.Add("mode", Utils.UrlEncode(item.HeaderType)); |                         dicQuery.Add("mode", Utils.UrlEncode(item.HeaderType)); | ||||||
|                     } |                     } | ||||||
|                     if (Utils.IsNotEmpty(item.Extra)) |                     if (item.Extra.IsNotEmpty()) | ||||||
|                     { |                     { | ||||||
|                         dicQuery.Add("extra", Utils.UrlEncode(item.Extra)); |                         dicQuery.Add("extra", Utils.UrlEncode(item.Extra)); | ||||||
|                     } |                     } | ||||||
|  | @ -115,24 +115,24 @@ namespace ServiceLib.Handler.Fmt | ||||||
|                 case nameof(ETransport.http): |                 case nameof(ETransport.http): | ||||||
|                 case nameof(ETransport.h2): |                 case nameof(ETransport.h2): | ||||||
|                     dicQuery["type"] = nameof(ETransport.http); |                     dicQuery["type"] = nameof(ETransport.http); | ||||||
|                     if (Utils.IsNotEmpty(item.RequestHost)) |                     if (item.RequestHost.IsNotEmpty()) | ||||||
|                     { |                     { | ||||||
|                         dicQuery.Add("host", Utils.UrlEncode(item.RequestHost)); |                         dicQuery.Add("host", Utils.UrlEncode(item.RequestHost)); | ||||||
|                     } |                     } | ||||||
|                     if (Utils.IsNotEmpty(item.Path)) |                     if (item.Path.IsNotEmpty()) | ||||||
|                     { |                     { | ||||||
|                         dicQuery.Add("path", Utils.UrlEncode(item.Path)); |                         dicQuery.Add("path", Utils.UrlEncode(item.Path)); | ||||||
|                     } |                     } | ||||||
|                     break; |                     break; | ||||||
| 
 | 
 | ||||||
|                 case nameof(ETransport.quic): |                 case nameof(ETransport.quic): | ||||||
|                     dicQuery.Add("headerType", Utils.IsNotEmpty(item.HeaderType) ? item.HeaderType : Global.None); |                     dicQuery.Add("headerType", item.HeaderType.IsNotEmpty() ? item.HeaderType : Global.None); | ||||||
|                     dicQuery.Add("quicSecurity", Utils.UrlEncode(item.RequestHost)); |                     dicQuery.Add("quicSecurity", Utils.UrlEncode(item.RequestHost)); | ||||||
|                     dicQuery.Add("key", Utils.UrlEncode(item.Path)); |                     dicQuery.Add("key", Utils.UrlEncode(item.Path)); | ||||||
|                     break; |                     break; | ||||||
| 
 | 
 | ||||||
|                 case nameof(ETransport.grpc): |                 case nameof(ETransport.grpc): | ||||||
|                     if (Utils.IsNotEmpty(item.Path)) |                     if (item.Path.IsNotEmpty()) | ||||||
|                     { |                     { | ||||||
|                         dicQuery.Add("authority", Utils.UrlEncode(item.RequestHost)); |                         dicQuery.Add("authority", Utils.UrlEncode(item.RequestHost)); | ||||||
|                         dicQuery.Add("serviceName", Utils.UrlEncode(item.Path)); |                         dicQuery.Add("serviceName", Utils.UrlEncode(item.Path)); | ||||||
|  | @ -215,8 +215,10 @@ namespace ServiceLib.Handler.Fmt | ||||||
|             foreach (var item in s) |             foreach (var item in s) | ||||||
|             { |             { | ||||||
|                 if (str.Contains(item, StringComparison.OrdinalIgnoreCase)) |                 if (str.Contains(item, StringComparison.OrdinalIgnoreCase)) | ||||||
|  |                 { | ||||||
|                     return true; |                     return true; | ||||||
|                 } |                 } | ||||||
|  |             } | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -37,7 +37,7 @@ | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 string str = config.TrimEx(); |                 string str = config.TrimEx(); | ||||||
|                 if (Utils.IsNullOrEmpty(str)) |                 if (str.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     msg = ResUI.FailedReadConfiguration; |                     msg = ResUI.FailedReadConfiguration; | ||||||
|                     return null; |                     return null; | ||||||
|  |  | ||||||
|  | @ -36,26 +36,26 @@ namespace ServiceLib.Handler.Fmt | ||||||
|             string url = string.Empty; |             string url = string.Empty; | ||||||
| 
 | 
 | ||||||
|             string remark = string.Empty; |             string remark = string.Empty; | ||||||
|             if (Utils.IsNotEmpty(item.Remarks)) |             if (item.Remarks.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 remark = "#" + Utils.UrlEncode(item.Remarks); |                 remark = "#" + Utils.UrlEncode(item.Remarks); | ||||||
|             } |             } | ||||||
|             var dicQuery = new Dictionary<string, string>(); |             var dicQuery = new Dictionary<string, string>(); | ||||||
|             if (Utils.IsNotEmpty(item.Sni)) |             if (item.Sni.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("sni", item.Sni); |                 dicQuery.Add("sni", item.Sni); | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(item.Alpn)) |             if (item.Alpn.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("alpn", Utils.UrlEncode(item.Alpn)); |                 dicQuery.Add("alpn", Utils.UrlEncode(item.Alpn)); | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(item.Path)) |             if (item.Path.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("obfs", "salamander"); |                 dicQuery.Add("obfs", "salamander"); | ||||||
|                 dicQuery.Add("obfs-password", Utils.UrlEncode(item.Path)); |                 dicQuery.Add("obfs-password", Utils.UrlEncode(item.Path)); | ||||||
|             } |             } | ||||||
|             dicQuery.Add("insecure", item.AllowInsecure.ToLower() == "true" ? "1" : "0"); |             dicQuery.Add("insecure", item.AllowInsecure.ToLower() == "true" ? "1" : "0"); | ||||||
|             if (Utils.IsNotEmpty(item.Ports)) |             if (item.Ports.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("mport", Utils.UrlEncode(item.Ports.Replace(':', '-'))); |                 dicQuery.Add("mport", Utils.UrlEncode(item.Ports.Replace(':', '-'))); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -27,11 +27,11 @@ namespace ServiceLib.Handler.Fmt | ||||||
|         public static string? ToUri(ProfileItem? item) |         public static string? ToUri(ProfileItem? item) | ||||||
|         { |         { | ||||||
|             if (item == null) |             if (item == null) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|             string url = string.Empty; |             } | ||||||
| 
 |             var remark = string.Empty; | ||||||
|             string remark = string.Empty; |             if (item.Remarks.IsNotEmpty()) | ||||||
|             if (Utils.IsNotEmpty(item.Remarks)) |  | ||||||
|             { |             { | ||||||
|                 remark = "#" + Utils.UrlEncode(item.Remarks); |                 remark = "#" + Utils.UrlEncode(item.Remarks); | ||||||
|             } |             } | ||||||
|  | @ -53,12 +53,14 @@ namespace ServiceLib.Handler.Fmt | ||||||
|         { |         { | ||||||
|             var match = UrlFinder.Match(result); |             var match = UrlFinder.Match(result); | ||||||
|             if (!match.Success) |             if (!match.Success) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             ProfileItem item = new(); |             ProfileItem item = new(); | ||||||
|             var base64 = match.Groups["base64"].Value.TrimEnd('/'); |             var base64 = match.Groups["base64"].Value.TrimEnd('/'); | ||||||
|             var tag = match.Groups["tag"].Value; |             var tag = match.Groups["tag"].Value; | ||||||
|             if (Utils.IsNotEmpty(tag)) |             if (tag.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 item.Remarks = Utils.UrlDecode(tag); |                 item.Remarks = Utils.UrlDecode(tag); | ||||||
|             } |             } | ||||||
|  | @ -72,11 +74,13 @@ namespace ServiceLib.Handler.Fmt | ||||||
|                 return null; |                 return null; | ||||||
|             } |             } | ||||||
|             if (!details.Success) |             if (!details.Success) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|  |             } | ||||||
|             item.Security = details.Groups["method"].Value; |             item.Security = details.Groups["method"].Value; | ||||||
|             item.Id = details.Groups["password"].Value; |             item.Id = details.Groups["password"].Value; | ||||||
|             item.Address = details.Groups["hostname"].Value; |             item.Address = details.Groups["hostname"].Value; | ||||||
|             item.Port = Utils.ToInt(details.Groups["port"].Value); |             item.Port = details.Groups["port"].Value.ToInt(); | ||||||
|             return item; |             return item; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -84,7 +88,9 @@ namespace ServiceLib.Handler.Fmt | ||||||
|         { |         { | ||||||
|             var parsedUrl = Utils.TryUri(result); |             var parsedUrl = Utils.TryUri(result); | ||||||
|             if (parsedUrl == null) |             if (parsedUrl == null) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             ProfileItem item = new() |             ProfileItem item = new() | ||||||
|             { |             { | ||||||
|  | @ -96,7 +102,7 @@ namespace ServiceLib.Handler.Fmt | ||||||
|             //2022-blake3 |             //2022-blake3 | ||||||
|             if (rawUserInfo.Contains(':')) |             if (rawUserInfo.Contains(':')) | ||||||
|             { |             { | ||||||
|                 string[] userInfoParts = rawUserInfo.Split(new[] { ':' }, 2); |                 var userInfoParts = rawUserInfo.Split(new[] { ':' }, 2); | ||||||
|                 if (userInfoParts.Length != 2) |                 if (userInfoParts.Length != 2) | ||||||
|                 { |                 { | ||||||
|                     return null; |                     return null; | ||||||
|  | @ -107,8 +113,8 @@ namespace ServiceLib.Handler.Fmt | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 // parse base64 UserInfo |                 // parse base64 UserInfo | ||||||
|                 string userInfo = Utils.Base64Decode(rawUserInfo); |                 var userInfo = Utils.Base64Decode(rawUserInfo); | ||||||
|                 string[] userInfoParts = userInfo.Split(new[] { ':' }, 2); |                 var userInfoParts = userInfo.Split(new[] { ':' }, 2); | ||||||
|                 if (userInfoParts.Length != 2) |                 if (userInfoParts.Length != 2) | ||||||
|                 { |                 { | ||||||
|                     return null; |                     return null; | ||||||
|  | @ -122,7 +128,7 @@ namespace ServiceLib.Handler.Fmt | ||||||
|             { |             { | ||||||
|                 //obfs-host exists |                 //obfs-host exists | ||||||
|                 var obfsHost = queryParameters["plugin"]?.Split(';').FirstOrDefault(t => t.Contains("obfs-host")); |                 var obfsHost = queryParameters["plugin"]?.Split(';').FirstOrDefault(t => t.Contains("obfs-host")); | ||||||
|                 if (queryParameters["plugin"].Contains("obfs=http") && Utils.IsNotEmpty(obfsHost)) |                 if (queryParameters["plugin"].Contains("obfs=http") && obfsHost.IsNotEmpty()) | ||||||
|                 { |                 { | ||||||
|                     obfsHost = obfsHost?.Replace("obfs-host=", ""); |                     obfsHost = obfsHost?.Replace("obfs-host=", ""); | ||||||
|                     item.Network = Global.DefaultNetwork; |                     item.Network = Global.DefaultNetwork; | ||||||
|  | @ -162,7 +168,7 @@ namespace ServiceLib.Handler.Fmt | ||||||
|                         Security = it.method, |                         Security = it.method, | ||||||
|                         Id = it.password, |                         Id = it.password, | ||||||
|                         Address = it.server, |                         Address = it.server, | ||||||
|                         Port = Utils.ToInt(it.server_port) |                         Port = it.server_port.ToInt() | ||||||
|                     }; |                     }; | ||||||
|                     lst.Add(ssItem); |                     lst.Add(ssItem); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| namespace ServiceLib.Handler.Fmt | namespace ServiceLib.Handler.Fmt | ||||||
| { | { | ||||||
|     public class SingboxFmt : BaseFmt |     public class SingboxFmt : BaseFmt | ||||||
|     { |     { | ||||||
|         public static List<ProfileItem>? ResolveFullArray(string strData, string? subRemarks) |         public static List<ProfileItem>? ResolveFullArray(string strData, string? subRemarks) | ||||||
|         { |         { | ||||||
|             var configObjects = JsonUtils.Deserialize<Object[]>(strData); |             var configObjects = JsonUtils.Deserialize<object[]>(strData); | ||||||
|             if (configObjects != null && configObjects.Length > 0) |             if (configObjects != null && configObjects.Length > 0) | ||||||
|             { |             { | ||||||
|                 List<ProfileItem> lstResult = []; |                 List<ProfileItem> lstResult = []; | ||||||
|  |  | ||||||
|  | @ -24,11 +24,11 @@ namespace ServiceLib.Handler.Fmt | ||||||
|         public static string? ToUri(ProfileItem? item) |         public static string? ToUri(ProfileItem? item) | ||||||
|         { |         { | ||||||
|             if (item == null) |             if (item == null) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|             var url = string.Empty; |             } | ||||||
| 
 |  | ||||||
|             var remark = string.Empty; |             var remark = string.Empty; | ||||||
|             if (Utils.IsNotEmpty(item.Remarks)) |             if (item.Remarks.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 remark = "#" + Utils.UrlEncode(item.Remarks); |                 remark = "#" + Utils.UrlEncode(item.Remarks); | ||||||
|             } |             } | ||||||
|  | @ -77,7 +77,7 @@ namespace ServiceLib.Handler.Fmt | ||||||
|                 return null; |                 return null; | ||||||
|             } |             } | ||||||
|             item.Address = arr1[1][..indexPort]; |             item.Address = arr1[1][..indexPort]; | ||||||
|             item.Port = Utils.ToInt(arr1[1][(indexPort + 1)..]); |             item.Port = arr1[1][(indexPort + 1)..].ToInt(); | ||||||
|             item.Security = arr21.First(); |             item.Security = arr21.First(); | ||||||
|             item.Id = arr21[1]; |             item.Id = arr21[1]; | ||||||
| 
 | 
 | ||||||
|  | @ -88,7 +88,9 @@ namespace ServiceLib.Handler.Fmt | ||||||
|         { |         { | ||||||
|             var parsedUrl = Utils.TryUri(result); |             var parsedUrl = Utils.TryUri(result); | ||||||
|             if (parsedUrl == null) |             if (parsedUrl == null) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             ProfileItem item = new() |             ProfileItem item = new() | ||||||
|             { |             { | ||||||
|  |  | ||||||
|  | @ -13,7 +13,9 @@ namespace ServiceLib.Handler.Fmt | ||||||
| 
 | 
 | ||||||
|             var url = Utils.TryUri(str); |             var url = Utils.TryUri(str); | ||||||
|             if (url == null) |             if (url == null) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             item.Address = url.IdnHost; |             item.Address = url.IdnHost; | ||||||
|             item.Port = url.Port; |             item.Port = url.Port; | ||||||
|  | @ -21,7 +23,7 @@ namespace ServiceLib.Handler.Fmt | ||||||
|             item.Id = Utils.UrlDecode(url.UserInfo); |             item.Id = Utils.UrlDecode(url.UserInfo); | ||||||
| 
 | 
 | ||||||
|             var query = Utils.ParseQueryString(url.Query); |             var query = Utils.ParseQueryString(url.Query); | ||||||
|             ResolveStdTransport(query, ref item); |             _ = ResolveStdTransport(query, ref item); | ||||||
| 
 | 
 | ||||||
|             return item; |             return item; | ||||||
|         } |         } | ||||||
|  | @ -29,16 +31,16 @@ namespace ServiceLib.Handler.Fmt | ||||||
|         public static string? ToUri(ProfileItem? item) |         public static string? ToUri(ProfileItem? item) | ||||||
|         { |         { | ||||||
|             if (item == null) |             if (item == null) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|             string url = string.Empty; |             } | ||||||
| 
 |             var remark = string.Empty; | ||||||
|             string remark = string.Empty; |             if (item.Remarks.IsNotEmpty()) | ||||||
|             if (Utils.IsNotEmpty(item.Remarks)) |  | ||||||
|             { |             { | ||||||
|                 remark = "#" + Utils.UrlEncode(item.Remarks); |                 remark = "#" + Utils.UrlEncode(item.Remarks); | ||||||
|             } |             } | ||||||
|             var dicQuery = new Dictionary<string, string>(); |             var dicQuery = new Dictionary<string, string>(); | ||||||
|             GetStdTransport(item, null, ref dicQuery); |             _ = GetStdTransport(item, null, ref dicQuery); | ||||||
| 
 | 
 | ||||||
|             return ToUri(EConfigType.Trojan, item.Address, item.Port, item.Id, dicQuery, remark); |             return ToUri(EConfigType.Trojan, item.Address, item.Port, item.Id, dicQuery, remark); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -13,7 +13,9 @@ namespace ServiceLib.Handler.Fmt | ||||||
| 
 | 
 | ||||||
|             var url = Utils.TryUri(str); |             var url = Utils.TryUri(str); | ||||||
|             if (url == null) |             if (url == null) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             item.Address = url.IdnHost; |             item.Address = url.IdnHost; | ||||||
|             item.Port = url.Port; |             item.Port = url.Port; | ||||||
|  | @ -36,20 +38,21 @@ namespace ServiceLib.Handler.Fmt | ||||||
|         public static string? ToUri(ProfileItem? item) |         public static string? ToUri(ProfileItem? item) | ||||||
|         { |         { | ||||||
|             if (item == null) |             if (item == null) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|             string url = string.Empty; |             } | ||||||
| 
 | 
 | ||||||
|             string remark = string.Empty; |             var remark = string.Empty; | ||||||
|             if (Utils.IsNotEmpty(item.Remarks)) |             if (item.Remarks.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 remark = "#" + Utils.UrlEncode(item.Remarks); |                 remark = "#" + Utils.UrlEncode(item.Remarks); | ||||||
|             } |             } | ||||||
|             var dicQuery = new Dictionary<string, string>(); |             var dicQuery = new Dictionary<string, string>(); | ||||||
|             if (Utils.IsNotEmpty(item.Sni)) |             if (item.Sni.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("sni", item.Sni); |                 dicQuery.Add("sni", item.Sni); | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(item.Alpn)) |             if (item.Alpn.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("alpn", Utils.UrlEncode(item.Alpn)); |                 dicQuery.Add("alpn", Utils.UrlEncode(item.Alpn)); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| namespace ServiceLib.Handler.Fmt | namespace ServiceLib.Handler.Fmt | ||||||
| { | { | ||||||
|     public class V2rayFmt : BaseFmt |     public class V2rayFmt : BaseFmt | ||||||
|     { |     { | ||||||
|         public static List<ProfileItem>? ResolveFullArray(string strData, string? subRemarks) |         public static List<ProfileItem>? ResolveFullArray(string strData, string? subRemarks) | ||||||
|         { |         { | ||||||
|             var configObjects = JsonUtils.Deserialize<Object[]>(strData); |             var configObjects = JsonUtils.Deserialize<object[]>(strData); | ||||||
|             if (configObjects != null && configObjects.Length > 0) |             if (configObjects != null && configObjects.Length > 0) | ||||||
|             { |             { | ||||||
|                 List<ProfileItem> lstResult = []; |                 List<ProfileItem> lstResult = []; | ||||||
|  |  | ||||||
|  | @ -14,7 +14,9 @@ namespace ServiceLib.Handler.Fmt | ||||||
| 
 | 
 | ||||||
|             var url = Utils.TryUri(str); |             var url = Utils.TryUri(str); | ||||||
|             if (url == null) |             if (url == null) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             item.Address = url.IdnHost; |             item.Address = url.IdnHost; | ||||||
|             item.Port = url.Port; |             item.Port = url.Port; | ||||||
|  | @ -24,7 +26,7 @@ namespace ServiceLib.Handler.Fmt | ||||||
|             var query = Utils.ParseQueryString(url.Query); |             var query = Utils.ParseQueryString(url.Query); | ||||||
|             item.Security = query["encryption"] ?? Global.None; |             item.Security = query["encryption"] ?? Global.None; | ||||||
|             item.StreamSecurity = query["security"] ?? ""; |             item.StreamSecurity = query["security"] ?? ""; | ||||||
|             ResolveStdTransport(query, ref item); |             _ = ResolveStdTransport(query, ref item); | ||||||
| 
 | 
 | ||||||
|             return item; |             return item; | ||||||
|         } |         } | ||||||
|  | @ -32,16 +34,17 @@ namespace ServiceLib.Handler.Fmt | ||||||
|         public static string? ToUri(ProfileItem? item) |         public static string? ToUri(ProfileItem? item) | ||||||
|         { |         { | ||||||
|             if (item == null) |             if (item == null) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|             string url = string.Empty; |             } | ||||||
| 
 | 
 | ||||||
|             string remark = string.Empty; |             var remark = string.Empty; | ||||||
|             if (Utils.IsNotEmpty(item.Remarks)) |             if (item.Remarks.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 remark = "#" + Utils.UrlEncode(item.Remarks); |                 remark = "#" + Utils.UrlEncode(item.Remarks); | ||||||
|             } |             } | ||||||
|             var dicQuery = new Dictionary<string, string>(); |             var dicQuery = new Dictionary<string, string>(); | ||||||
|             if (Utils.IsNotEmpty(item.Security)) |             if (item.Security.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("encryption", item.Security); |                 dicQuery.Add("encryption", item.Security); | ||||||
|             } |             } | ||||||
|  | @ -49,7 +52,7 @@ namespace ServiceLib.Handler.Fmt | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("encryption", Global.None); |                 dicQuery.Add("encryption", Global.None); | ||||||
|             } |             } | ||||||
|             GetStdTransport(item, Global.None, ref dicQuery); |             _ = GetStdTransport(item, Global.None, ref dicQuery); | ||||||
| 
 | 
 | ||||||
|             return ToUri(EConfigType.VLESS, item.Address, item.Port, item.Id, dicQuery, remark); |             return ToUri(EConfigType.VLESS, item.Address, item.Port, item.Id, dicQuery, remark); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -20,10 +20,10 @@ namespace ServiceLib.Handler.Fmt | ||||||
|         public static string? ToUri(ProfileItem? item) |         public static string? ToUri(ProfileItem? item) | ||||||
|         { |         { | ||||||
|             if (item == null) |             if (item == null) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|             string url = string.Empty; |             } | ||||||
| 
 |             var vmessQRCode = new VmessQRCode | ||||||
|             VmessQRCode vmessQRCode = new() |  | ||||||
|             { |             { | ||||||
|                 v = item.ConfigVersion, |                 v = item.ConfigVersion, | ||||||
|                 ps = item.Remarks.TrimEx(), |                 ps = item.Remarks.TrimEx(), | ||||||
|  | @ -42,7 +42,7 @@ namespace ServiceLib.Handler.Fmt | ||||||
|                 fp = item.Fingerprint |                 fp = item.Fingerprint | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|             url = JsonUtils.Serialize(vmessQRCode); |             var url = JsonUtils.Serialize(vmessQRCode); | ||||||
|             url = Utils.Base64Encode(url); |             url = Utils.Base64Encode(url); | ||||||
|             url = $"{Global.ProtocolShares[EConfigType.VMess]}{url}"; |             url = $"{Global.ProtocolShares[EConfigType.VMess]}{url}"; | ||||||
| 
 | 
 | ||||||
|  | @ -60,7 +60,7 @@ namespace ServiceLib.Handler.Fmt | ||||||
|             result = result[Global.ProtocolShares[EConfigType.VMess].Length..]; |             result = result[Global.ProtocolShares[EConfigType.VMess].Length..]; | ||||||
|             result = Utils.Base64Decode(result); |             result = Utils.Base64Decode(result); | ||||||
| 
 | 
 | ||||||
|             VmessQRCode? vmessQRCode = JsonUtils.Deserialize<VmessQRCode>(result); |             var vmessQRCode = JsonUtils.Deserialize<VmessQRCode>(result); | ||||||
|             if (vmessQRCode == null) |             if (vmessQRCode == null) | ||||||
|             { |             { | ||||||
|                 msg = ResUI.FailedConversionConfiguration; |                 msg = ResUI.FailedConversionConfiguration; | ||||||
|  | @ -78,12 +78,12 @@ namespace ServiceLib.Handler.Fmt | ||||||
|             item.AlterId = vmessQRCode.aid; |             item.AlterId = vmessQRCode.aid; | ||||||
|             item.Security = Utils.ToString(vmessQRCode.scy); |             item.Security = Utils.ToString(vmessQRCode.scy); | ||||||
| 
 | 
 | ||||||
|             item.Security = Utils.IsNotEmpty(vmessQRCode.scy) ? vmessQRCode.scy : Global.DefaultSecurity; |             item.Security = vmessQRCode.scy.IsNotEmpty() ? vmessQRCode.scy : Global.DefaultSecurity; | ||||||
|             if (Utils.IsNotEmpty(vmessQRCode.net)) |             if (vmessQRCode.net.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 item.Network = vmessQRCode.net; |                 item.Network = vmessQRCode.net; | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(vmessQRCode.type)) |             if (vmessQRCode.type.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 item.HeaderType = vmessQRCode.type; |                 item.HeaderType = vmessQRCode.type; | ||||||
|             } |             } | ||||||
|  | @ -100,7 +100,7 @@ namespace ServiceLib.Handler.Fmt | ||||||
| 
 | 
 | ||||||
|         public static ProfileItem? ResolveStdVmess(string str) |         public static ProfileItem? ResolveStdVmess(string str) | ||||||
|         { |         { | ||||||
|             ProfileItem item = new() |             var item = new ProfileItem | ||||||
|             { |             { | ||||||
|                 ConfigType = EConfigType.VMess, |                 ConfigType = EConfigType.VMess, | ||||||
|                 Security = "auto" |                 Security = "auto" | ||||||
|  | @ -108,7 +108,9 @@ namespace ServiceLib.Handler.Fmt | ||||||
| 
 | 
 | ||||||
|             var url = Utils.TryUri(str); |             var url = Utils.TryUri(str); | ||||||
|             if (url == null) |             if (url == null) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             item.Address = url.IdnHost; |             item.Address = url.IdnHost; | ||||||
|             item.Port = url.Port; |             item.Port = url.Port; | ||||||
|  |  | ||||||
|  | @ -13,7 +13,9 @@ namespace ServiceLib.Handler.Fmt | ||||||
| 
 | 
 | ||||||
|             var url = Utils.TryUri(str); |             var url = Utils.TryUri(str); | ||||||
|             if (url == null) |             if (url == null) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             item.Address = url.IdnHost; |             item.Address = url.IdnHost; | ||||||
|             item.Port = url.Port; |             item.Port = url.Port; | ||||||
|  | @ -33,29 +35,30 @@ namespace ServiceLib.Handler.Fmt | ||||||
|         public static string? ToUri(ProfileItem? item) |         public static string? ToUri(ProfileItem? item) | ||||||
|         { |         { | ||||||
|             if (item == null) |             if (item == null) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|             string url = string.Empty; |             } | ||||||
| 
 | 
 | ||||||
|             string remark = string.Empty; |             var remark = string.Empty; | ||||||
|             if (Utils.IsNotEmpty(item.Remarks)) |             if (item.Remarks.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 remark = "#" + Utils.UrlEncode(item.Remarks); |                 remark = "#" + Utils.UrlEncode(item.Remarks); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             var dicQuery = new Dictionary<string, string>(); |             var dicQuery = new Dictionary<string, string>(); | ||||||
|             if (Utils.IsNotEmpty(item.PublicKey)) |             if (item.PublicKey.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("publickey", Utils.UrlEncode(item.PublicKey)); |                 dicQuery.Add("publickey", Utils.UrlEncode(item.PublicKey)); | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(item.Path)) |             if (item.Path.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("reserved", Utils.UrlEncode(item.Path)); |                 dicQuery.Add("reserved", Utils.UrlEncode(item.Path)); | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(item.RequestHost)) |             if (item.RequestHost.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("address", Utils.UrlEncode(item.RequestHost)); |                 dicQuery.Add("address", Utils.UrlEncode(item.RequestHost)); | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(item.ShortId)) |             if (item.ShortId.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 dicQuery.Add("mtu", Utils.UrlEncode(item.ShortId)); |                 dicQuery.Add("mtu", Utils.UrlEncode(item.ShortId)); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -15,7 +15,7 @@ namespace ServiceLib.Handler | ||||||
| 
 | 
 | ||||||
|         public static async Task Start(string configPath, int httpPort, int pacPort) |         public static async Task Start(string configPath, int httpPort, int pacPort) | ||||||
|         { |         { | ||||||
|             _needRestart = (configPath != _configPath || httpPort != _httpPort || pacPort != _pacPort || !_isRunning); |             _needRestart = configPath != _configPath || httpPort != _httpPort || pacPort != _pacPort || !_isRunning; | ||||||
| 
 | 
 | ||||||
|             _configPath = configPath; |             _configPath = configPath; | ||||||
|             _httpPort = httpPort; |             _httpPort = httpPort; | ||||||
|  | @ -70,7 +70,7 @@ namespace ServiceLib.Handler | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
|                         var client = await _tcpListener.AcceptTcpClientAsync(); |                         var client = await _tcpListener.AcceptTcpClientAsync(); | ||||||
|                         await Task.Run(() => { WriteContent(client); }); |                         await Task.Run(() => WriteContent(client)); | ||||||
|                     } |                     } | ||||||
|                     catch |                     catch | ||||||
|                     { |                     { | ||||||
|  | @ -90,7 +90,9 @@ namespace ServiceLib.Handler | ||||||
|         public static void Stop() |         public static void Stop() | ||||||
|         { |         { | ||||||
|             if (_tcpListener == null) |             if (_tcpListener == null) | ||||||
|  |             { | ||||||
|                 return; |                 return; | ||||||
|  |             } | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 _isRunning = false; |                 _isRunning = false; | ||||||
|  |  | ||||||
|  | @ -36,7 +36,7 @@ namespace ServiceLib.Handler | ||||||
| 
 | 
 | ||||||
|         private void IndexIdEnqueue(string indexId) |         private void IndexIdEnqueue(string indexId) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNotEmpty(indexId) && !_queIndexIds.Contains(indexId)) |             if (indexId.IsNotEmpty() && !_queIndexIds.Contains(indexId)) | ||||||
|             { |             { | ||||||
|                 _queIndexIds.Enqueue(indexId); |                 _queIndexIds.Enqueue(indexId); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -60,7 +60,7 @@ namespace ServiceLib.Handler.SysProxy | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 // set proxy for LAN |                 // set proxy for LAN | ||||||
|                 bool result = SetConnectionProxy(null, strProxy, exceptions, type); |                 var result = SetConnectionProxy(null, strProxy, exceptions, type); | ||||||
|                 // set proxy for dial up connections |                 // set proxy for dial up connections | ||||||
|                 var connections = EnumerateRasEntries(); |                 var connections = EnumerateRasEntries(); | ||||||
|                 foreach (var connection in connections) |                 foreach (var connection in connections) | ||||||
|  | @ -71,27 +71,27 @@ namespace ServiceLib.Handler.SysProxy | ||||||
|             } |             } | ||||||
|             catch |             catch | ||||||
|             { |             { | ||||||
|                 SetProxyFallback(strProxy, exceptions, type); |                 _ = SetProxyFallback(strProxy, exceptions, type); | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private static bool SetConnectionProxy(string? connectionName, string? strProxy, string? exceptions, int type) |         private static bool SetConnectionProxy(string? connectionName, string? strProxy, string? exceptions, int type) | ||||||
|         { |         { | ||||||
|             InternetPerConnOptionList list = new(); |             var list = new InternetPerConnOptionList(); | ||||||
| 
 | 
 | ||||||
|             int optionCount = 1; |             var optionCount = 1; | ||||||
|             if (type == 1) // No proxy |             if (type == 1) // No proxy | ||||||
|             { |             { | ||||||
|                 optionCount = 1; |                 optionCount = 1; | ||||||
|             } |             } | ||||||
|             else if (type is 2 or 4) // named proxy or autoproxy script URL |             else if (type is 2 or 4) // named proxy or autoproxy script URL | ||||||
|             { |             { | ||||||
|                 optionCount = string.IsNullOrEmpty(exceptions) ? 2 : 3; |                 optionCount = exceptions.IsNullOrEmpty() ? 2 : 3; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             int m_Int = (int)PerConnFlags.PROXY_TYPE_DIRECT; |             var m_Int = (int)PerConnFlags.PROXY_TYPE_DIRECT; | ||||||
|             PerConnOption m_Option = PerConnOption.INTERNET_PER_CONN_FLAGS; |             var m_Option = PerConnOption.INTERNET_PER_CONN_FLAGS; | ||||||
|             if (type == 2) // named proxy |             if (type == 2) // named proxy | ||||||
|             { |             { | ||||||
|                 m_Int = (int)(PerConnFlags.PROXY_TYPE_DIRECT | PerConnFlags.PROXY_TYPE_PROXY); |                 m_Int = (int)(PerConnFlags.PROXY_TYPE_DIRECT | PerConnFlags.PROXY_TYPE_PROXY); | ||||||
|  | @ -103,11 +103,9 @@ namespace ServiceLib.Handler.SysProxy | ||||||
|                 m_Option = PerConnOption.INTERNET_PER_CONN_AUTOCONFIG_URL; |                 m_Option = PerConnOption.INTERNET_PER_CONN_AUTOCONFIG_URL; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             //int optionCount = Utile.IsNullOrEmpty(strProxy) ? 1 : (Utile.IsNullOrEmpty(exceptions) ? 2 : 3); |             var options = new InternetConnectionOption[optionCount]; | ||||||
|             InternetConnectionOption[] options = new InternetConnectionOption[optionCount]; |  | ||||||
|             // USE a proxy server ... |             // USE a proxy server ... | ||||||
|             options[0].m_Option = PerConnOption.INTERNET_PER_CONN_FLAGS; |             options[0].m_Option = PerConnOption.INTERNET_PER_CONN_FLAGS; | ||||||
|             //options[0].m_Value.m_Int = (int)((optionCount < 2) ? PerConnFlags.PROXY_TYPE_DIRECT : (PerConnFlags.PROXY_TYPE_DIRECT | PerConnFlags.PROXY_TYPE_PROXY)); |  | ||||||
|             options[0].m_Value.m_Int = m_Int; |             options[0].m_Value.m_Int = m_Int; | ||||||
|             // use THIS proxy server |             // use THIS proxy server | ||||||
|             if (optionCount > 1) |             if (optionCount > 1) | ||||||
|  | @ -135,20 +133,20 @@ namespace ServiceLib.Handler.SysProxy | ||||||
|             list.dwOptionCount = options.Length; |             list.dwOptionCount = options.Length; | ||||||
|             list.dwOptionError = 0; |             list.dwOptionError = 0; | ||||||
| 
 | 
 | ||||||
|             int optSize = Marshal.SizeOf(typeof(InternetConnectionOption)); |             var optSize = Marshal.SizeOf(typeof(InternetConnectionOption)); | ||||||
|             // make a pointer out of all that ... |             // make a pointer out of all that ... | ||||||
|             nint optionsPtr = Marshal.AllocCoTaskMem(optSize * options.Length); // !! remember to deallocate memory 4 |             var optionsPtr = Marshal.AllocCoTaskMem(optSize * options.Length); // !! remember to deallocate memory 4 | ||||||
|             // copy the array over into that spot in memory ... |             // copy the array over into that spot in memory ... | ||||||
|             for (int i = 0; i < options.Length; ++i) |             for (var i = 0; i < options.Length; ++i) | ||||||
|             { |             { | ||||||
|                 if (Environment.Is64BitOperatingSystem) |                 if (Environment.Is64BitOperatingSystem) | ||||||
|                 { |                 { | ||||||
|                     nint opt = new(optionsPtr.ToInt64() + (i * optSize)); |                     var opt = new nint(optionsPtr.ToInt64() + (i * optSize)); | ||||||
|                     Marshal.StructureToPtr(options[i], opt, false); |                     Marshal.StructureToPtr(options[i], opt, false); | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
|                     nint opt = new(optionsPtr.ToInt32() + (i * optSize)); |                     var opt = new nint(optionsPtr.ToInt32() + (i * optSize)); | ||||||
|                     Marshal.StructureToPtr(options[i], opt, false); |                     Marshal.StructureToPtr(options[i], opt, false); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | @ -156,14 +154,14 @@ namespace ServiceLib.Handler.SysProxy | ||||||
|             list.options = optionsPtr; |             list.options = optionsPtr; | ||||||
| 
 | 
 | ||||||
|             // and then make a pointer out of the whole list |             // and then make a pointer out of the whole list | ||||||
|             nint ipcoListPtr = Marshal.AllocCoTaskMem(list.dwSize); // !! remember to deallocate memory 5 |             var ipcoListPtr = Marshal.AllocCoTaskMem(list.dwSize); // !! remember to deallocate memory 5 | ||||||
|             Marshal.StructureToPtr(list, ipcoListPtr, false); |             Marshal.StructureToPtr(list, ipcoListPtr, false); | ||||||
| 
 | 
 | ||||||
|             // and finally, call the API method! |             // and finally, call the API method! | ||||||
|             bool isSuccess = NativeMethods.InternetSetOption(nint.Zero, |             var isSuccess = NativeMethods.InternetSetOption(nint.Zero, | ||||||
|                InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION, |                InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION, | ||||||
|                ipcoListPtr, list.dwSize); |                ipcoListPtr, list.dwSize); | ||||||
|             int returnvalue = 0; // ERROR_SUCCESS |             var returnvalue = 0; // ERROR_SUCCESS | ||||||
|             if (!isSuccess) |             if (!isSuccess) | ||||||
|             {  // get the error codes, they might be helpful |             {  // get the error codes, they might be helpful | ||||||
|                 returnvalue = Marshal.GetLastPInvokeError(); |                 returnvalue = Marshal.GetLastPInvokeError(); | ||||||
|  | @ -171,13 +169,15 @@ namespace ServiceLib.Handler.SysProxy | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 // Notify the system that the registry settings have been changed and cause them to be refreshed |                 // Notify the system that the registry settings have been changed and cause them to be refreshed | ||||||
|                 NativeMethods.InternetSetOption(nint.Zero, InternetOption.INTERNET_OPTION_SETTINGS_CHANGED, nint.Zero, 0); |                 _ = NativeMethods.InternetSetOption(nint.Zero, InternetOption.INTERNET_OPTION_SETTINGS_CHANGED, nint.Zero, 0); | ||||||
|                 NativeMethods.InternetSetOption(nint.Zero, InternetOption.INTERNET_OPTION_REFRESH, nint.Zero, 0); |                 _ = NativeMethods.InternetSetOption(nint.Zero, InternetOption.INTERNET_OPTION_REFRESH, nint.Zero, 0); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // FREE the data ASAP |             // FREE the data ASAP | ||||||
|             if (list.szConnection != nint.Zero) |             if (list.szConnection != nint.Zero) | ||||||
|  |             { | ||||||
|                 Marshal.FreeHGlobal(list.szConnection); // release mem 3 |                 Marshal.FreeHGlobal(list.szConnection); // release mem 3 | ||||||
|  |             } | ||||||
|             if (optionCount > 1) |             if (optionCount > 1) | ||||||
|             { |             { | ||||||
|                 Marshal.FreeHGlobal(options[1].m_Value.m_StringPtr); // release mem 1 |                 Marshal.FreeHGlobal(options[1].m_Value.m_StringPtr); // release mem 1 | ||||||
|  | @ -204,18 +204,18 @@ namespace ServiceLib.Handler.SysProxy | ||||||
|         /// <exception cref="ApplicationException">Error message with win32 error code</exception> |         /// <exception cref="ApplicationException">Error message with win32 error code</exception> | ||||||
|         private static IEnumerable<string> EnumerateRasEntries() |         private static IEnumerable<string> EnumerateRasEntries() | ||||||
|         { |         { | ||||||
|             int entries = 0; |             var entries = 0; | ||||||
|             // attempt to query with 1 entry buffer |             // attempt to query with 1 entry buffer | ||||||
|             RASENTRYNAME[] rasEntryNames = new RASENTRYNAME[1]; |             var rasEntryNames = new RASENTRYNAME[1]; | ||||||
|             int bufferSize = Marshal.SizeOf(typeof(RASENTRYNAME)); |             var bufferSize = Marshal.SizeOf(typeof(RASENTRYNAME)); | ||||||
|             rasEntryNames[0].dwSize = Marshal.SizeOf(typeof(RASENTRYNAME)); |             rasEntryNames[0].dwSize = Marshal.SizeOf(typeof(RASENTRYNAME)); | ||||||
| 
 | 
 | ||||||
|             uint result = NativeMethods.RasEnumEntries(null, null, rasEntryNames, ref bufferSize, ref entries); |             var result = NativeMethods.RasEnumEntries(null, null, rasEntryNames, ref bufferSize, ref entries); | ||||||
|             // increase buffer if the buffer is not large enough |             // increase buffer if the buffer is not large enough | ||||||
|             if (result == (uint)ErrorCode.ERROR_BUFFER_TOO_SMALL) |             if (result == (uint)ErrorCode.ERROR_BUFFER_TOO_SMALL) | ||||||
|             { |             { | ||||||
|                 rasEntryNames = new RASENTRYNAME[bufferSize / Marshal.SizeOf(typeof(RASENTRYNAME))]; |                 rasEntryNames = new RASENTRYNAME[bufferSize / Marshal.SizeOf(typeof(RASENTRYNAME))]; | ||||||
|                 for (int i = 0; i < rasEntryNames.Length; i++) |                 for (var i = 0; i < rasEntryNames.Length; i++) | ||||||
|                 { |                 { | ||||||
|                     rasEntryNames[i].dwSize = Marshal.SizeOf(typeof(RASENTRYNAME)); |                     rasEntryNames[i].dwSize = Marshal.SizeOf(typeof(RASENTRYNAME)); | ||||||
|                 } |                 } | ||||||
|  | @ -225,7 +225,7 @@ namespace ServiceLib.Handler.SysProxy | ||||||
|             if (result == 0) |             if (result == 0) | ||||||
|             { |             { | ||||||
|                 var entryNames = new List<string>(); |                 var entryNames = new List<string>(); | ||||||
|                 for (int i = 0; i < entries; i++) |                 for (var i = 0; i < entries; i++) | ||||||
|                 { |                 { | ||||||
|                     entryNames.Add(rasEntryNames[i].szEntryName); |                     entryNames.Add(rasEntryNames[i].szEntryName); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  | @ -75,7 +75,7 @@ | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             strProxy = string.Empty; |             strProxy = string.Empty; | ||||||
|             if (Utils.IsNullOrEmpty(config.SystemProxyItem.SystemProxyAdvancedProtocol)) |             if (config.SystemProxyItem.SystemProxyAdvancedProtocol.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 strProxy = $"{Global.Loopback}:{port}"; |                 strProxy = $"{Global.Loopback}:{port}"; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ namespace ServiceLib.Handler | ||||||
|         private static readonly Lazy<WebDavHandler> _instance = new(() => new()); |         private static readonly Lazy<WebDavHandler> _instance = new(() => new()); | ||||||
|         public static WebDavHandler Instance => _instance.Value; |         public static WebDavHandler Instance => _instance.Value; | ||||||
| 
 | 
 | ||||||
|         private Config? _config; |         private readonly Config? _config; | ||||||
|         private WebDavClient? _client; |         private WebDavClient? _client; | ||||||
|         private string? _lastDescription; |         private string? _lastDescription; | ||||||
|         private string _webDir = Global.AppName + "_backup"; |         private string _webDir = Global.AppName + "_backup"; | ||||||
|  | @ -62,7 +62,9 @@ namespace ServiceLib.Handler | ||||||
|         private async Task<bool> TryCreateDir() |         private async Task<bool> TryCreateDir() | ||||||
|         { |         { | ||||||
|             if (_client is null) |             if (_client is null) | ||||||
|  |             { | ||||||
|                 return false; |                 return false; | ||||||
|  |             } | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 var result2 = await _client.Mkcol(_webDir); |                 var result2 = await _client.Mkcol(_webDir); | ||||||
|  |  | ||||||
|  | @ -48,12 +48,12 @@ namespace ServiceLib.Models | ||||||
| 
 | 
 | ||||||
|         public List<string>? GetAlpn() |         public List<string>? GetAlpn() | ||||||
|         { |         { | ||||||
|             return Utils.IsNullOrEmpty(Alpn) ? null : Utils.String2List(Alpn); |             return Alpn.IsNullOrEmpty() ? null : Utils.String2List(Alpn); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public string GetNetwork() |         public string GetNetwork() | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(Network) || !Global.Networks.Contains(Network)) |             if (Network.IsNullOrEmpty() || !Global.Networks.Contains(Network)) | ||||||
|             { |             { | ||||||
|                 return Global.DefaultNetwork; |                 return Global.DefaultNetwork; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -44,8 +44,8 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                     File.Delete(fileName); |                     File.Delete(fileName); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 string addressFileName = node.Address; |                 var addressFileName = node.Address; | ||||||
|                 if (Utils.IsNullOrEmpty(addressFileName)) |                 if (addressFileName.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     ret.Msg = ResUI.FailedGetDefaultConfiguration; |                     ret.Msg = ResUI.FailedGetDefaultConfiguration; | ||||||
|                     return ret; |                     return ret; | ||||||
|  | @ -60,9 +60,9 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                     return ret; |                     return ret; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 string tagYamlStr1 = "!<str>"; |                 var tagYamlStr1 = "!<str>"; | ||||||
|                 string tagYamlStr2 = "__strn__"; |                 var tagYamlStr2 = "__strn__"; | ||||||
|                 string tagYamlStr3 = "!!str"; |                 var tagYamlStr3 = "!!str"; | ||||||
|                 var txtFile = File.ReadAllText(addressFileName); |                 var txtFile = File.ReadAllText(addressFileName); | ||||||
|                 txtFile = txtFile.Replace(tagYamlStr1, tagYamlStr2); |                 txtFile = txtFile.Replace(tagYamlStr1, tagYamlStr2); | ||||||
| 
 | 
 | ||||||
|  | @ -117,13 +117,15 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                 if (_config.TunModeItem.EnableTun) |                 if (_config.TunModeItem.EnableTun) | ||||||
|                 { |                 { | ||||||
|                     var tun = EmbedUtils.GetEmbedText(Global.ClashTunYaml); |                     var tun = EmbedUtils.GetEmbedText(Global.ClashTunYaml); | ||||||
|                     if (Utils.IsNotEmpty(tun)) |                     if (tun.IsNotEmpty()) | ||||||
|                     { |                     { | ||||||
|                         var tunContent = YamlUtils.FromYaml<Dictionary<string, object>>(tun); |                         var tunContent = YamlUtils.FromYaml<Dictionary<string, object>>(tun); | ||||||
|                         if (tunContent != null) |                         if (tunContent != null) | ||||||
|  |                         { | ||||||
|                             fileContent["tun"] = tunContent["tun"]; |                             fileContent["tun"] = tunContent["tun"]; | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|  |                 } | ||||||
| 
 | 
 | ||||||
|                 //Mixin |                 //Mixin | ||||||
|                 try |                 try | ||||||
|  | @ -202,8 +204,8 @@ namespace ServiceLib.Services.CoreConfig | ||||||
| 
 | 
 | ||||||
|         private void ModifyContentMerge(Dictionary<string, object> fileContent, string key, object value) |         private void ModifyContentMerge(Dictionary<string, object> fileContent, string key, object value) | ||||||
|         { |         { | ||||||
|             bool blPrepend = false; |             var blPrepend = false; | ||||||
|             bool blRemoved = false; |             var blRemoved = false; | ||||||
|             if (key.StartsWith("prepend-")) |             if (key.StartsWith("prepend-")) | ||||||
|             { |             { | ||||||
|                 blPrepend = true; |                 blPrepend = true; | ||||||
|  | @ -244,17 +246,11 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|             if (blPrepend) |             if (blPrepend) | ||||||
|             { |             { | ||||||
|                 lstValue.Reverse(); |                 lstValue.Reverse(); | ||||||
|                 foreach (var item in lstValue) |                 lstValue.ForEach(item => lstOri.Insert(0, item)); | ||||||
|                 { |  | ||||||
|                     lstOri.Insert(0, item); |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 foreach (var item in lstValue) |                 lstValue.ForEach(item => lstOri.Add(item)); | ||||||
|                 { |  | ||||||
|                     lstOri.Add(item); |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -36,7 +36,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                 ret.Msg = ResUI.InitialConfiguration; |                 ret.Msg = ResUI.InitialConfiguration; | ||||||
| 
 | 
 | ||||||
|                 string result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient); |                 string result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient); | ||||||
|                 if (Utils.IsNullOrEmpty(result)) |                 if (result.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     ret.Msg = ResUI.FailedGetDefaultConfiguration; |                     ret.Msg = ResUI.FailedGetDefaultConfiguration; | ||||||
|                     return ret; |                     return ret; | ||||||
|  | @ -93,7 +93,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
| 
 | 
 | ||||||
|                 var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient); |                 var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient); | ||||||
|                 var txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound); |                 var txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound); | ||||||
|                 if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty()) |                 if (result.IsNullOrEmpty() || txtOutbound.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     ret.Msg = ResUI.FailedGetDefaultConfiguration; |                     ret.Msg = ResUI.FailedGetDefaultConfiguration; | ||||||
|                     return ret; |                     return ret; | ||||||
|  | @ -138,7 +138,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                     var item = await AppHandler.Instance.GetProfileItem(it.IndexId); |                     var item = await AppHandler.Instance.GetProfileItem(it.IndexId); | ||||||
|                     if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS) |                     if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS) | ||||||
|                     { |                     { | ||||||
|                         if (item is null || Utils.IsNullOrEmpty(item.Id) || !Utils.IsGuidByParse(item.Id)) |                         if (item is null || item.Id.IsNullOrEmpty() || !Utils.IsGuidByParse(item.Id)) | ||||||
|                         { |                         { | ||||||
|                             continue; |                             continue; | ||||||
|                         } |                         } | ||||||
|  | @ -261,7 +261,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                 ret.Msg = ResUI.InitialConfiguration; |                 ret.Msg = ResUI.InitialConfiguration; | ||||||
| 
 | 
 | ||||||
|                 var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient); |                 var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient); | ||||||
|                 if (Utils.IsNullOrEmpty(result)) |                 if (result.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     ret.Msg = ResUI.FailedGetDefaultConfiguration; |                     ret.Msg = ResUI.FailedGetDefaultConfiguration; | ||||||
|                     return ret; |                     return ret; | ||||||
|  | @ -317,7 +317,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
| 
 | 
 | ||||||
|                 string result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient); |                 string result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient); | ||||||
|                 string txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound); |                 string txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound); | ||||||
|                 if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty()) |                 if (result.IsNullOrEmpty() || txtOutbound.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     ret.Msg = ResUI.FailedGetDefaultConfiguration; |                     ret.Msg = ResUI.FailedGetDefaultConfiguration; | ||||||
|                     return ret; |                     return ret; | ||||||
|  | @ -354,7 +354,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                     } |                     } | ||||||
|                     if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS) |                     if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS) | ||||||
|                     { |                     { | ||||||
|                         if (Utils.IsNullOrEmpty(item.Id) || !Utils.IsGuidByParse(item.Id)) |                         if (item.Id.IsNullOrEmpty() || !Utils.IsGuidByParse(item.Id)) | ||||||
|                         { |                         { | ||||||
|                             continue; |                             continue; | ||||||
|                         } |                         } | ||||||
|  | @ -443,7 +443,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 string addressFileName = node.Address; |                 string addressFileName = node.Address; | ||||||
|                 if (Utils.IsNullOrEmpty(addressFileName)) |                 if (addressFileName.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     ret.Msg = ResUI.FailedGetDefaultConfiguration; |                     ret.Msg = ResUI.FailedGetDefaultConfiguration; | ||||||
|                     return ret; |                     return ret; | ||||||
|  | @ -560,10 +560,10 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                     inbound.listen_port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks); |                     inbound.listen_port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks); | ||||||
|                     inbound.sniff = _config.Inbound.First().SniffingEnabled; |                     inbound.sniff = _config.Inbound.First().SniffingEnabled; | ||||||
|                     inbound.sniff_override_destination = _config.Inbound.First().RouteOnly ? false : _config.Inbound.First().SniffingEnabled; |                     inbound.sniff_override_destination = _config.Inbound.First().RouteOnly ? false : _config.Inbound.First().SniffingEnabled; | ||||||
|                     inbound.domain_strategy = Utils.IsNullOrEmpty(_config.RoutingBasicItem.DomainStrategy4Singbox) ? null : _config.RoutingBasicItem.DomainStrategy4Singbox; |                     inbound.domain_strategy = _config.RoutingBasicItem.DomainStrategy4Singbox.IsNullOrEmpty() ? null : _config.RoutingBasicItem.DomainStrategy4Singbox; | ||||||
| 
 | 
 | ||||||
|                     var routing = await ConfigHandler.GetDefaultRouting(_config); |                     var routing = await ConfigHandler.GetDefaultRouting(_config); | ||||||
|                     if (Utils.IsNotEmpty(routing.DomainStrategy4Singbox)) |                     if (routing.DomainStrategy4Singbox.IsNotEmpty()) | ||||||
|                     { |                     { | ||||||
|                         inbound.domain_strategy = routing.DomainStrategy4Singbox; |                         inbound.domain_strategy = routing.DomainStrategy4Singbox; | ||||||
|                     } |                     } | ||||||
|  | @ -583,7 +583,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                             singboxConfig.inbounds.Add(inbound3); |                             singboxConfig.inbounds.Add(inbound3); | ||||||
| 
 | 
 | ||||||
|                             //auth |                             //auth | ||||||
|                             if (Utils.IsNotEmpty(_config.Inbound.First().User) && Utils.IsNotEmpty(_config.Inbound.First().Pass)) |                             if (_config.Inbound.First().User.IsNotEmpty() && _config.Inbound.First().Pass.IsNotEmpty()) | ||||||
|                             { |                             { | ||||||
|                                 inbound3.users = new() { new() { username = _config.Inbound.First().User, password = _config.Inbound.First().Pass } }; |                                 inbound3.users = new() { new() { username = _config.Inbound.First().User, password = _config.Inbound.First().Pass } }; | ||||||
|                             } |                             } | ||||||
|  | @ -601,7 +601,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                     { |                     { | ||||||
|                         _config.TunModeItem.Mtu = Global.TunMtus.First(); |                         _config.TunModeItem.Mtu = Global.TunMtus.First(); | ||||||
|                     } |                     } | ||||||
|                     if (Utils.IsNullOrEmpty(_config.TunModeItem.Stack)) |                     if (_config.TunModeItem.Stack.IsNullOrEmpty()) | ||||||
|                     { |                     { | ||||||
|                         _config.TunModeItem.Stack = Global.TunStacks.First(); |                         _config.TunModeItem.Stack = Global.TunStacks.First(); | ||||||
|                     } |                     } | ||||||
|  | @ -674,8 +674,8 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                     case EConfigType.SOCKS: |                     case EConfigType.SOCKS: | ||||||
|                         { |                         { | ||||||
|                             outbound.version = "5"; |                             outbound.version = "5"; | ||||||
|                             if (Utils.IsNotEmpty(node.Security) |                             if (node.Security.IsNotEmpty() | ||||||
|                               && Utils.IsNotEmpty(node.Id)) |                               && node.Id.IsNotEmpty()) | ||||||
|                             { |                             { | ||||||
|                                 outbound.username = node.Security; |                                 outbound.username = node.Security; | ||||||
|                                 outbound.password = node.Id; |                                 outbound.password = node.Id; | ||||||
|  | @ -684,8 +684,8 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                         } |                         } | ||||||
|                     case EConfigType.HTTP: |                     case EConfigType.HTTP: | ||||||
|                         { |                         { | ||||||
|                             if (Utils.IsNotEmpty(node.Security) |                             if (node.Security.IsNotEmpty() | ||||||
|                               && Utils.IsNotEmpty(node.Id)) |                               && node.Id.IsNotEmpty()) | ||||||
|                             { |                             { | ||||||
|                                 outbound.username = node.Security; |                                 outbound.username = node.Security; | ||||||
|                                 outbound.password = node.Id; |                                 outbound.password = node.Id; | ||||||
|  | @ -698,7 +698,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
| 
 | 
 | ||||||
|                             outbound.packet_encoding = "xudp"; |                             outbound.packet_encoding = "xudp"; | ||||||
| 
 | 
 | ||||||
|                             if (Utils.IsNullOrEmpty(node.Flow)) |                             if (node.Flow.IsNullOrEmpty()) | ||||||
|                             { |                             { | ||||||
|                                 await GenOutboundMux(node, outbound); |                                 await GenOutboundMux(node, outbound); | ||||||
|                             } |                             } | ||||||
|  | @ -719,7 +719,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                         { |                         { | ||||||
|                             outbound.password = node.Id; |                             outbound.password = node.Id; | ||||||
| 
 | 
 | ||||||
|                             if (Utils.IsNotEmpty(node.Path)) |                             if (node.Path.IsNotEmpty()) | ||||||
|                             { |                             { | ||||||
|                                 outbound.obfs = new() |                                 outbound.obfs = new() | ||||||
|                                 { |                                 { | ||||||
|  | @ -755,7 +755,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                             outbound.peer_public_key = node.PublicKey; |                             outbound.peer_public_key = node.PublicKey; | ||||||
|                             outbound.reserved = Utils.String2List(node.Path)?.Select(int.Parse).ToList(); |                             outbound.reserved = Utils.String2List(node.Path)?.Select(int.Parse).ToList(); | ||||||
|                             outbound.local_address = Utils.String2List(node.RequestHost); |                             outbound.local_address = Utils.String2List(node.RequestHost); | ||||||
|                             outbound.mtu = Utils.ToInt(node.ShortId.IsNullOrEmpty() ? Global.TunMtus.First() : node.ShortId); |                             outbound.mtu = node.ShortId.IsNullOrEmpty() ? Global.TunMtus.First() : node.ShortId.ToInt(); | ||||||
|                             break; |                             break; | ||||||
|                         } |                         } | ||||||
|                 } |                 } | ||||||
|  | @ -775,7 +775,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|         { |         { | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 if (_config.CoreBasicItem.MuxEnabled && Utils.IsNotEmpty(_config.Mux4SboxItem.Protocol)) |                 if (_config.CoreBasicItem.MuxEnabled && _config.Mux4SboxItem.Protocol.IsNotEmpty()) | ||||||
|                 { |                 { | ||||||
|                     var mux = new Multiplex4Sbox() |                     var mux = new Multiplex4Sbox() | ||||||
|                     { |                     { | ||||||
|  | @ -801,11 +801,11 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                 if (node.StreamSecurity == Global.StreamSecurityReality || node.StreamSecurity == Global.StreamSecurity) |                 if (node.StreamSecurity == Global.StreamSecurityReality || node.StreamSecurity == Global.StreamSecurity) | ||||||
|                 { |                 { | ||||||
|                     var server_name = string.Empty; |                     var server_name = string.Empty; | ||||||
|                     if (Utils.IsNotEmpty(node.Sni)) |                     if (node.Sni.IsNotEmpty()) | ||||||
|                     { |                     { | ||||||
|                         server_name = node.Sni; |                         server_name = node.Sni; | ||||||
|                     } |                     } | ||||||
|                     else if (Utils.IsNotEmpty(node.RequestHost)) |                     else if (node.RequestHost.IsNotEmpty()) | ||||||
|                     { |                     { | ||||||
|                         server_name = Utils.String2List(node.RequestHost)?.First(); |                         server_name = Utils.String2List(node.RequestHost)?.First(); | ||||||
|                     } |                     } | ||||||
|  | @ -816,7 +816,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                         insecure = Utils.ToBool(node.AllowInsecure.IsNullOrEmpty() ? _config.CoreBasicItem.DefAllowInsecure.ToString().ToLower() : node.AllowInsecure), |                         insecure = Utils.ToBool(node.AllowInsecure.IsNullOrEmpty() ? _config.CoreBasicItem.DefAllowInsecure.ToString().ToLower() : node.AllowInsecure), | ||||||
|                         alpn = node.GetAlpn(), |                         alpn = node.GetAlpn(), | ||||||
|                     }; |                     }; | ||||||
|                     if (Utils.IsNotEmpty(node.Fingerprint)) |                     if (node.Fingerprint.IsNotEmpty()) | ||||||
|                     { |                     { | ||||||
|                         tls.utls = new Utls4Sbox() |                         tls.utls = new Utls4Sbox() | ||||||
|                         { |                         { | ||||||
|  | @ -854,8 +854,8 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                 { |                 { | ||||||
|                     case nameof(ETransport.h2): |                     case nameof(ETransport.h2): | ||||||
|                         transport.type = nameof(ETransport.http); |                         transport.type = nameof(ETransport.http); | ||||||
|                         transport.host = Utils.IsNullOrEmpty(node.RequestHost) ? null : Utils.String2List(node.RequestHost); |                         transport.host = node.RequestHost.IsNullOrEmpty() ? null : Utils.String2List(node.RequestHost); | ||||||
|                         transport.path = Utils.IsNullOrEmpty(node.Path) ? null : node.Path; |                         transport.path = node.Path.IsNullOrEmpty() ? null : node.Path; | ||||||
|                         break; |                         break; | ||||||
| 
 | 
 | ||||||
|                     case nameof(ETransport.tcp):   //http |                     case nameof(ETransport.tcp):   //http | ||||||
|  | @ -869,16 +869,16 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                             else |                             else | ||||||
|                             { |                             { | ||||||
|                                 transport.type = nameof(ETransport.http); |                                 transport.type = nameof(ETransport.http); | ||||||
|                                 transport.host = Utils.IsNullOrEmpty(node.RequestHost) ? null : Utils.String2List(node.RequestHost); |                                 transport.host = node.RequestHost.IsNullOrEmpty() ? null : Utils.String2List(node.RequestHost); | ||||||
|                                 transport.path = Utils.IsNullOrEmpty(node.Path) ? null : node.Path; |                                 transport.path = node.Path.IsNullOrEmpty() ? null : node.Path; | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                         break; |                         break; | ||||||
| 
 | 
 | ||||||
|                     case nameof(ETransport.ws): |                     case nameof(ETransport.ws): | ||||||
|                         transport.type = nameof(ETransport.ws); |                         transport.type = nameof(ETransport.ws); | ||||||
|                         transport.path = Utils.IsNullOrEmpty(node.Path) ? null : node.Path; |                         transport.path = node.Path.IsNullOrEmpty() ? null : node.Path; | ||||||
|                         if (Utils.IsNotEmpty(node.RequestHost)) |                         if (node.RequestHost.IsNotEmpty()) | ||||||
|                         { |                         { | ||||||
|                             transport.headers = new() |                             transport.headers = new() | ||||||
|                             { |                             { | ||||||
|  | @ -889,8 +889,8 @@ namespace ServiceLib.Services.CoreConfig | ||||||
| 
 | 
 | ||||||
|                     case nameof(ETransport.httpupgrade): |                     case nameof(ETransport.httpupgrade): | ||||||
|                         transport.type = nameof(ETransport.httpupgrade); |                         transport.type = nameof(ETransport.httpupgrade); | ||||||
|                         transport.path = Utils.IsNullOrEmpty(node.Path) ? null : node.Path; |                         transport.path = node.Path.IsNullOrEmpty() ? null : node.Path; | ||||||
|                         transport.host = Utils.IsNullOrEmpty(node.RequestHost) ? null : node.RequestHost; |                         transport.host = node.RequestHost.IsNullOrEmpty() ? null : node.RequestHost; | ||||||
| 
 | 
 | ||||||
|                         break; |                         break; | ||||||
| 
 | 
 | ||||||
|  | @ -1085,7 +1085,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                     outbound = item.OutboundTag, |                     outbound = item.OutboundTag, | ||||||
|                 }; |                 }; | ||||||
| 
 | 
 | ||||||
|                 if (Utils.IsNotEmpty(item.Port)) |                 if (item.Port.IsNotEmpty()) | ||||||
|                 { |                 { | ||||||
|                     if (item.Port.Contains("-")) |                     if (item.Port.Contains("-")) | ||||||
|                     { |                     { | ||||||
|  | @ -1093,10 +1093,10 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                     } |                     } | ||||||
|                     else |                     else | ||||||
|                     { |                     { | ||||||
|                         rule.port = new List<int> { Utils.ToInt(item.Port) }; |                         rule.port = new List<int> { item.Port.ToInt() }; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 if (Utils.IsNotEmpty(item.Network)) |                 if (item.Network.IsNotEmpty()) | ||||||
|                 { |                 { | ||||||
|                     rule.network = Utils.String2List(item.Network); |                     rule.network = Utils.String2List(item.Network); | ||||||
|                 } |                 } | ||||||
|  | @ -1241,11 +1241,11 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                 var strDNS = string.Empty; |                 var strDNS = string.Empty; | ||||||
|                 if (_config.TunModeItem.EnableTun) |                 if (_config.TunModeItem.EnableTun) | ||||||
|                 { |                 { | ||||||
|                     strDNS = Utils.IsNullOrEmpty(item?.TunDNS) ? EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName) : item?.TunDNS; |                     strDNS = string.IsNullOrEmpty(item?.TunDNS) ? EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName) : item?.TunDNS; | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
|                     strDNS = Utils.IsNullOrEmpty(item?.NormalDNS) ? EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName) : item?.NormalDNS; |                     strDNS = string.IsNullOrEmpty(item?.NormalDNS) ? EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName) : item?.NormalDNS; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 var dns4Sbox = JsonUtils.Deserialize<Dns4Sbox>(strDNS); |                 var dns4Sbox = JsonUtils.Deserialize<Dns4Sbox>(strDNS); | ||||||
|  | @ -1274,9 +1274,9 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|             dns4Sbox.servers.Add(new() |             dns4Sbox.servers.Add(new() | ||||||
|             { |             { | ||||||
|                 tag = tag, |                 tag = tag, | ||||||
|                 address = Utils.IsNullOrEmpty(dNSItem?.DomainDNSAddress) ? Global.SingboxDomainDNSAddress.FirstOrDefault() : dNSItem?.DomainDNSAddress, |                 address = string.IsNullOrEmpty(dNSItem?.DomainDNSAddress) ? Global.SingboxDomainDNSAddress.FirstOrDefault() : dNSItem?.DomainDNSAddress, | ||||||
|                 detour = Global.DirectTag, |                 detour = Global.DirectTag, | ||||||
|                 strategy = Utils.IsNullOrEmpty(dNSItem?.DomainStrategy4Freedom) ? null : dNSItem?.DomainStrategy4Freedom, |                 strategy = string.IsNullOrEmpty(dNSItem?.DomainStrategy4Freedom) ? null : dNSItem?.DomainStrategy4Freedom, | ||||||
|             }); |             }); | ||||||
|             dns4Sbox.rules.Insert(0, new() |             dns4Sbox.rules.Insert(0, new() | ||||||
|             { |             { | ||||||
|  | @ -1290,7 +1290,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|             var lstDomain = singboxConfig.outbounds |             var lstDomain = singboxConfig.outbounds | ||||||
|                            .Where(t => Utils.IsNotEmpty(t.server) && Utils.IsDomain(t.server)) |                            .Where(t => t.server.IsNotEmpty() && Utils.IsDomain(t.server)) | ||||||
|                            .Select(t => t.server) |                            .Select(t => t.server) | ||||||
|                            .Distinct() |                            .Distinct() | ||||||
|                            .ToList(); |                            .ToList(); | ||||||
|  | @ -1394,10 +1394,10 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|             List<Ruleset4Sbox> customRulesets = []; |             List<Ruleset4Sbox> customRulesets = []; | ||||||
| 
 | 
 | ||||||
|             var routing = await ConfigHandler.GetDefaultRouting(_config); |             var routing = await ConfigHandler.GetDefaultRouting(_config); | ||||||
|             if (Utils.IsNotEmpty(routing.CustomRulesetPath4Singbox)) |             if (routing.CustomRulesetPath4Singbox.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 var result = EmbedUtils.LoadResource(routing.CustomRulesetPath4Singbox); |                 var result = EmbedUtils.LoadResource(routing.CustomRulesetPath4Singbox); | ||||||
|                 if (Utils.IsNotEmpty(result)) |                 if (result.IsNotEmpty()) | ||||||
|                 { |                 { | ||||||
|                     customRulesets = (JsonUtils.Deserialize<List<Ruleset4Sbox>>(result) ?? []) |                     customRulesets = (JsonUtils.Deserialize<List<Ruleset4Sbox>>(result) ?? []) | ||||||
|                         .Where(t => t.tag != null) |                         .Where(t => t.tag != null) | ||||||
|  | @ -1414,7 +1414,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|             singboxConfig.route.rule_set = []; |             singboxConfig.route.rule_set = []; | ||||||
|             foreach (var item in new HashSet<string>(ruleSets)) |             foreach (var item in new HashSet<string>(ruleSets)) | ||||||
|             { |             { | ||||||
|                 if (Utils.IsNullOrEmpty(item)) |                 if (item.IsNullOrEmpty()) | ||||||
|                 { continue; } |                 { continue; } | ||||||
|                 var customRuleset = customRulesets.FirstOrDefault(t => t.tag != null && t.tag.Equals(item)); |                 var customRuleset = customRulesets.FirstOrDefault(t => t.tag != null && t.tag.Equals(item)); | ||||||
|                 if (customRuleset is null) |                 if (customRuleset is null) | ||||||
|  |  | ||||||
|  | @ -37,7 +37,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                 ret.Msg = ResUI.InitialConfiguration; |                 ret.Msg = ResUI.InitialConfiguration; | ||||||
| 
 | 
 | ||||||
|                 var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient); |                 var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient); | ||||||
|                 if (Utils.IsNullOrEmpty(result)) |                 if (result.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     ret.Msg = ResUI.FailedGetDefaultConfiguration; |                     ret.Msg = ResUI.FailedGetDefaultConfiguration; | ||||||
|                     return ret; |                     return ret; | ||||||
|  | @ -93,7 +93,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
| 
 | 
 | ||||||
|                 string result = EmbedUtils.GetEmbedText(Global.V2raySampleClient); |                 string result = EmbedUtils.GetEmbedText(Global.V2raySampleClient); | ||||||
|                 string txtOutbound = EmbedUtils.GetEmbedText(Global.V2raySampleOutbound); |                 string txtOutbound = EmbedUtils.GetEmbedText(Global.V2raySampleOutbound); | ||||||
|                 if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty()) |                 if (result.IsNullOrEmpty() || txtOutbound.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     ret.Msg = ResUI.FailedGetDefaultConfiguration; |                     ret.Msg = ResUI.FailedGetDefaultConfiguration; | ||||||
|                     return ret; |                     return ret; | ||||||
|  | @ -135,7 +135,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                     } |                     } | ||||||
|                     if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS) |                     if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS) | ||||||
|                     { |                     { | ||||||
|                         if (Utils.IsNullOrEmpty(item.Id) || !Utils.IsGuidByParse(item.Id)) |                         if (item.Id.IsNullOrEmpty() || !Utils.IsGuidByParse(item.Id)) | ||||||
|                         { |                         { | ||||||
|                             continue; |                             continue; | ||||||
|                         } |                         } | ||||||
|  | @ -216,7 +216,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
| 
 | 
 | ||||||
|                 var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient); |                 var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient); | ||||||
|                 var txtOutbound = EmbedUtils.GetEmbedText(Global.V2raySampleOutbound); |                 var txtOutbound = EmbedUtils.GetEmbedText(Global.V2raySampleOutbound); | ||||||
|                 if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty()) |                 if (result.IsNullOrEmpty() || txtOutbound.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     ret.Msg = ResUI.FailedGetDefaultConfiguration; |                     ret.Msg = ResUI.FailedGetDefaultConfiguration; | ||||||
|                     return ret; |                     return ret; | ||||||
|  | @ -261,7 +261,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                     var item = await AppHandler.Instance.GetProfileItem(it.IndexId); |                     var item = await AppHandler.Instance.GetProfileItem(it.IndexId); | ||||||
|                     if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS) |                     if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS) | ||||||
|                     { |                     { | ||||||
|                         if (item is null || Utils.IsNullOrEmpty(item.Id) || !Utils.IsGuidByParse(item.Id)) |                         if (item is null || item.Id.IsNullOrEmpty() || !Utils.IsGuidByParse(item.Id)) | ||||||
|                         { |                         { | ||||||
|                             continue; |                             continue; | ||||||
|                         } |                         } | ||||||
|  | @ -371,7 +371,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient); |                 var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient); | ||||||
|                 if (Utils.IsNullOrEmpty(result)) |                 if (result.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     ret.Msg = ResUI.FailedGetDefaultConfiguration; |                     ret.Msg = ResUI.FailedGetDefaultConfiguration; | ||||||
|                     return ret; |                     return ret; | ||||||
|  | @ -465,7 +465,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                         v2rayConfig.inbounds.Add(inbound3); |                         v2rayConfig.inbounds.Add(inbound3); | ||||||
| 
 | 
 | ||||||
|                         //auth |                         //auth | ||||||
|                         if (Utils.IsNotEmpty(_config.Inbound.First().User) && Utils.IsNotEmpty(_config.Inbound.First().Pass)) |                         if (_config.Inbound.First().User.IsNotEmpty() && _config.Inbound.First().Pass.IsNotEmpty()) | ||||||
|                         { |                         { | ||||||
|                             inbound3.settings.auth = "password"; |                             inbound3.settings.auth = "password"; | ||||||
|                             inbound3.settings.accounts = new List<AccountsItem4Ray> { new AccountsItem4Ray() { user = _config.Inbound.First().User, pass = _config.Inbound.First().Pass } }; |                             inbound3.settings.accounts = new List<AccountsItem4Ray> { new AccountsItem4Ray() { user = _config.Inbound.First().User, pass = _config.Inbound.First().Pass } }; | ||||||
|  | @ -487,7 +487,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|         private Inbounds4Ray GetInbound(InItem inItem, EInboundProtocol protocol, bool bSocks) |         private Inbounds4Ray GetInbound(InItem inItem, EInboundProtocol protocol, bool bSocks) | ||||||
|         { |         { | ||||||
|             string result = EmbedUtils.GetEmbedText(Global.V2raySampleInbound); |             string result = EmbedUtils.GetEmbedText(Global.V2raySampleInbound); | ||||||
|             if (Utils.IsNullOrEmpty(result)) |             if (result.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return new(); |                 return new(); | ||||||
|             } |             } | ||||||
|  | @ -515,12 +515,12 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                 if (v2rayConfig.routing?.rules != null) |                 if (v2rayConfig.routing?.rules != null) | ||||||
|                 { |                 { | ||||||
|                     v2rayConfig.routing.domainStrategy = _config.RoutingBasicItem.DomainStrategy; |                     v2rayConfig.routing.domainStrategy = _config.RoutingBasicItem.DomainStrategy; | ||||||
|                     v2rayConfig.routing.domainMatcher = Utils.IsNullOrEmpty(_config.RoutingBasicItem.DomainMatcher) ? null : _config.RoutingBasicItem.DomainMatcher; |                     v2rayConfig.routing.domainMatcher = _config.RoutingBasicItem.DomainMatcher.IsNullOrEmpty() ? null : _config.RoutingBasicItem.DomainMatcher; | ||||||
| 
 | 
 | ||||||
|                     var routing = await ConfigHandler.GetDefaultRouting(_config); |                     var routing = await ConfigHandler.GetDefaultRouting(_config); | ||||||
|                     if (routing != null) |                     if (routing != null) | ||||||
|                     { |                     { | ||||||
|                         if (Utils.IsNotEmpty(routing.DomainStrategy)) |                         if (routing.DomainStrategy.IsNotEmpty()) | ||||||
|                         { |                         { | ||||||
|                             v2rayConfig.routing.domainStrategy = routing.DomainStrategy; |                             v2rayConfig.routing.domainStrategy = routing.DomainStrategy; | ||||||
|                         } |                         } | ||||||
|  | @ -551,11 +551,11 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                 { |                 { | ||||||
|                     return 0; |                     return 0; | ||||||
|                 } |                 } | ||||||
|                 if (Utils.IsNullOrEmpty(rule.port)) |                 if (rule.port.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     rule.port = null; |                     rule.port = null; | ||||||
|                 } |                 } | ||||||
|                 if (Utils.IsNullOrEmpty(rule.network)) |                 if (rule.network.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     rule.network = null; |                     rule.network = null; | ||||||
|                 } |                 } | ||||||
|  | @ -603,7 +603,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                 } |                 } | ||||||
|                 if (!hasDomainIp) |                 if (!hasDomainIp) | ||||||
|                 { |                 { | ||||||
|                     if (Utils.IsNotEmpty(rule.port) |                     if (rule.port.IsNotEmpty() | ||||||
|                         || rule.protocol?.Count > 0 |                         || rule.protocol?.Count > 0 | ||||||
|                         || rule.inboundTag?.Count > 0 |                         || rule.inboundTag?.Count > 0 | ||||||
|                         ) |                         ) | ||||||
|  | @ -714,8 +714,8 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                             serversItem.method = null; |                             serversItem.method = null; | ||||||
|                             serversItem.password = null; |                             serversItem.password = null; | ||||||
| 
 | 
 | ||||||
|                             if (Utils.IsNotEmpty(node.Security) |                             if (node.Security.IsNotEmpty() | ||||||
|                                 && Utils.IsNotEmpty(node.Id)) |                                 && node.Id.IsNotEmpty()) | ||||||
|                             { |                             { | ||||||
|                                 SocksUsersItem4Ray socksUsersItem = new() |                                 SocksUsersItem4Ray socksUsersItem = new() | ||||||
|                                 { |                                 { | ||||||
|  | @ -868,11 +868,11 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                         alpn = node.GetAlpn(), |                         alpn = node.GetAlpn(), | ||||||
|                         fingerprint = node.Fingerprint.IsNullOrEmpty() ? _config.CoreBasicItem.DefFingerprint : node.Fingerprint |                         fingerprint = node.Fingerprint.IsNullOrEmpty() ? _config.CoreBasicItem.DefFingerprint : node.Fingerprint | ||||||
|                     }; |                     }; | ||||||
|                     if (Utils.IsNotEmpty(sni)) |                     if (sni.IsNotEmpty()) | ||||||
|                     { |                     { | ||||||
|                         tlsSettings.serverName = sni; |                         tlsSettings.serverName = sni; | ||||||
|                     } |                     } | ||||||
|                     else if (Utils.IsNotEmpty(host)) |                     else if (host.IsNotEmpty()) | ||||||
|                     { |                     { | ||||||
|                         tlsSettings.serverName = Utils.String2List(host)?.First(); |                         tlsSettings.serverName = Utils.String2List(host)?.First(); | ||||||
|                     } |                     } | ||||||
|  | @ -918,7 +918,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                             type = node.HeaderType, |                             type = node.HeaderType, | ||||||
|                             domain = host.IsNullOrEmpty() ? null : host |                             domain = host.IsNullOrEmpty() ? null : host | ||||||
|                         }; |                         }; | ||||||
|                         if (Utils.IsNotEmpty(path)) |                         if (path.IsNotEmpty()) | ||||||
|                         { |                         { | ||||||
|                             kcpSettings.seed = path; |                             kcpSettings.seed = path; | ||||||
|                         } |                         } | ||||||
|  | @ -929,16 +929,16 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                         WsSettings4Ray wsSettings = new(); |                         WsSettings4Ray wsSettings = new(); | ||||||
|                         wsSettings.headers = new Headers4Ray(); |                         wsSettings.headers = new Headers4Ray(); | ||||||
| 
 | 
 | ||||||
|                         if (Utils.IsNotEmpty(host)) |                         if (host.IsNotEmpty()) | ||||||
|                         { |                         { | ||||||
|                             wsSettings.host = host; |                             wsSettings.host = host; | ||||||
|                             wsSettings.headers.Host = host; |                             wsSettings.headers.Host = host; | ||||||
|                         } |                         } | ||||||
|                         if (Utils.IsNotEmpty(path)) |                         if (path.IsNotEmpty()) | ||||||
|                         { |                         { | ||||||
|                             wsSettings.path = path; |                             wsSettings.path = path; | ||||||
|                         } |                         } | ||||||
|                         if (Utils.IsNotEmpty(useragent)) |                         if (useragent.IsNotEmpty()) | ||||||
|                         { |                         { | ||||||
|                             wsSettings.headers.UserAgent = useragent; |                             wsSettings.headers.UserAgent = useragent; | ||||||
|                         } |                         } | ||||||
|  | @ -949,11 +949,11 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                     case nameof(ETransport.httpupgrade): |                     case nameof(ETransport.httpupgrade): | ||||||
|                         HttpupgradeSettings4Ray httpupgradeSettings = new(); |                         HttpupgradeSettings4Ray httpupgradeSettings = new(); | ||||||
| 
 | 
 | ||||||
|                         if (Utils.IsNotEmpty(path)) |                         if (path.IsNotEmpty()) | ||||||
|                         { |                         { | ||||||
|                             httpupgradeSettings.path = path; |                             httpupgradeSettings.path = path; | ||||||
|                         } |                         } | ||||||
|                         if (Utils.IsNotEmpty(host)) |                         if (host.IsNotEmpty()) | ||||||
|                         { |                         { | ||||||
|                             httpupgradeSettings.host = host; |                             httpupgradeSettings.host = host; | ||||||
|                         } |                         } | ||||||
|  | @ -965,19 +965,19 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                         streamSettings.network = ETransport.xhttp.ToString(); |                         streamSettings.network = ETransport.xhttp.ToString(); | ||||||
|                         XhttpSettings4Ray xhttpSettings = new(); |                         XhttpSettings4Ray xhttpSettings = new(); | ||||||
| 
 | 
 | ||||||
|                         if (Utils.IsNotEmpty(path)) |                         if (path.IsNotEmpty()) | ||||||
|                         { |                         { | ||||||
|                             xhttpSettings.path = path; |                             xhttpSettings.path = path; | ||||||
|                         } |                         } | ||||||
|                         if (Utils.IsNotEmpty(host)) |                         if (host.IsNotEmpty()) | ||||||
|                         { |                         { | ||||||
|                             xhttpSettings.host = host; |                             xhttpSettings.host = host; | ||||||
|                         } |                         } | ||||||
|                         if (Utils.IsNotEmpty(node.HeaderType) && Global.XhttpMode.Contains(node.HeaderType)) |                         if (node.HeaderType.IsNotEmpty() && Global.XhttpMode.Contains(node.HeaderType)) | ||||||
|                         { |                         { | ||||||
|                             xhttpSettings.mode = node.HeaderType; |                             xhttpSettings.mode = node.HeaderType; | ||||||
|                         } |                         } | ||||||
|                         if (Utils.IsNotEmpty(node.Extra)) |                         if (node.Extra.IsNotEmpty()) | ||||||
|                         { |                         { | ||||||
|                             xhttpSettings.extra = JsonUtils.ParseJson(node.Extra); |                             xhttpSettings.extra = JsonUtils.ParseJson(node.Extra); | ||||||
|                         } |                         } | ||||||
|  | @ -990,7 +990,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                     case nameof(ETransport.h2): |                     case nameof(ETransport.h2): | ||||||
|                         HttpSettings4Ray httpSettings = new(); |                         HttpSettings4Ray httpSettings = new(); | ||||||
| 
 | 
 | ||||||
|                         if (Utils.IsNotEmpty(host)) |                         if (host.IsNotEmpty()) | ||||||
|                         { |                         { | ||||||
|                             httpSettings.host = Utils.String2List(host); |                             httpSettings.host = Utils.String2List(host); | ||||||
|                         } |                         } | ||||||
|  | @ -1013,7 +1013,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                         streamSettings.quicSettings = quicsettings; |                         streamSettings.quicSettings = quicsettings; | ||||||
|                         if (node.StreamSecurity == Global.StreamSecurity) |                         if (node.StreamSecurity == Global.StreamSecurity) | ||||||
|                         { |                         { | ||||||
|                             if (Utils.IsNotEmpty(sni)) |                             if (sni.IsNotEmpty()) | ||||||
|                             { |                             { | ||||||
|                                 streamSettings.tlsSettings.serverName = sni; |                                 streamSettings.tlsSettings.serverName = sni; | ||||||
|                             } |                             } | ||||||
|  | @ -1027,7 +1027,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                     case nameof(ETransport.grpc): |                     case nameof(ETransport.grpc): | ||||||
|                         GrpcSettings4Ray grpcSettings = new() |                         GrpcSettings4Ray grpcSettings = new() | ||||||
|                         { |                         { | ||||||
|                             authority = Utils.IsNullOrEmpty(host) ? null : host, |                             authority = host.IsNullOrEmpty() ? null : host, | ||||||
|                             serviceName = path, |                             serviceName = path, | ||||||
|                             multiMode = node.HeaderType == Global.GrpcMultiMode, |                             multiMode = node.HeaderType == Global.GrpcMultiMode, | ||||||
|                             idle_timeout = _config.GrpcItem.IdleTimeout, |                             idle_timeout = _config.GrpcItem.IdleTimeout, | ||||||
|  | @ -1058,7 +1058,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                             request = request.Replace("$requestUserAgent$", $"{useragent.AppendQuotes()}"); |                             request = request.Replace("$requestUserAgent$", $"{useragent.AppendQuotes()}"); | ||||||
|                             //Path |                             //Path | ||||||
|                             string pathHttp = @"/"; |                             string pathHttp = @"/"; | ||||||
|                             if (Utils.IsNotEmpty(path)) |                             if (path.IsNotEmpty()) | ||||||
|                             { |                             { | ||||||
|                                 string[] arrPath = path.Split(','); |                                 string[] arrPath = path.Split(','); | ||||||
|                                 pathHttp = string.Join(",".AppendQuotes(), arrPath); |                                 pathHttp = string.Join(",".AppendQuotes(), arrPath); | ||||||
|  | @ -1085,13 +1085,13 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                 var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray); |                 var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray); | ||||||
|                 var normalDNS = item?.NormalDNS; |                 var normalDNS = item?.NormalDNS; | ||||||
|                 var domainStrategy4Freedom = item?.DomainStrategy4Freedom; |                 var domainStrategy4Freedom = item?.DomainStrategy4Freedom; | ||||||
|                 if (Utils.IsNullOrEmpty(normalDNS)) |                 if (normalDNS.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     normalDNS = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName); |                     normalDNS = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 //Outbound Freedom domainStrategy |                 //Outbound Freedom domainStrategy | ||||||
|                 if (Utils.IsNotEmpty(domainStrategy4Freedom)) |                 if (domainStrategy4Freedom.IsNotEmpty()) | ||||||
|                 { |                 { | ||||||
|                     var outbound = v2rayConfig.outbounds.FirstOrDefault(t => t is { protocol: "freedom", tag: Global.DirectTag }); |                     var outbound = v2rayConfig.outbounds.FirstOrDefault(t => t is { protocol: "freedom", tag: Global.DirectTag }); | ||||||
|                     if (outbound != null) |                     if (outbound != null) | ||||||
|  | @ -1156,7 +1156,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|                 { |                 { | ||||||
|                     var dnsServer = new DnsServer4Ray() |                     var dnsServer = new DnsServer4Ray() | ||||||
|                     { |                     { | ||||||
|                         address = Utils.IsNullOrEmpty(dNSItem?.DomainDNSAddress) ? Global.DomainDNSAddress.FirstOrDefault() : dNSItem?.DomainDNSAddress, |                         address = string.IsNullOrEmpty(dNSItem?.DomainDNSAddress) ? Global.DomainDNSAddress.FirstOrDefault() : dNSItem?.DomainDNSAddress, | ||||||
|                         domains = [node.Address] |                         domains = [node.Address] | ||||||
|                     }; |                     }; | ||||||
|                     servers.AsArray().Add(JsonUtils.SerializeToNode(dnsServer)); |                     servers.AsArray().Add(JsonUtils.SerializeToNode(dnsServer)); | ||||||
|  | @ -1216,7 +1216,7 @@ namespace ServiceLib.Services.CoreConfig | ||||||
|         { |         { | ||||||
|             //fragment proxy |             //fragment proxy | ||||||
|             if (_config.CoreBasicItem.EnableFragment |             if (_config.CoreBasicItem.EnableFragment | ||||||
|                 && Utils.IsNotEmpty(v2rayConfig.outbounds.First().streamSettings?.security)) |                 && v2rayConfig.outbounds.First().streamSettings?.security.IsNullOrEmpty() == false) | ||||||
|             { |             { | ||||||
|                 var fragmentOutbound = new Outbounds4Ray |                 var fragmentOutbound = new Outbounds4Ray | ||||||
|                 { |                 { | ||||||
|  |  | ||||||
|  | @ -23,14 +23,7 @@ namespace ServiceLib.Services | ||||||
|                 SetSecurityProtocol(AppHandler.Instance.Config.GuiItem.EnableSecurityProtocolTls13); |                 SetSecurityProtocol(AppHandler.Instance.Config.GuiItem.EnableSecurityProtocolTls13); | ||||||
| 
 | 
 | ||||||
|                 var progress = new Progress<string>(); |                 var progress = new Progress<string>(); | ||||||
|                 progress.ProgressChanged += (sender, value) => |                 progress.ProgressChanged += (sender, value) => updateFunc?.Invoke(false, $"{value}"); | ||||||
|                 { |  | ||||||
|                     if (updateFunc != null) |  | ||||||
|                     { |  | ||||||
|                         string msg = $"{value}"; |  | ||||||
|                         updateFunc?.Invoke(false, msg); |  | ||||||
|                     } |  | ||||||
|                 }; |  | ||||||
| 
 | 
 | ||||||
|                 await DownloaderHelper.Instance.DownloadDataAsync4Speed(webProxy, |                 await DownloaderHelper.Instance.DownloadDataAsync4Speed(webProxy, | ||||||
|                       url, |                       url, | ||||||
|  | @ -56,10 +49,7 @@ namespace ServiceLib.Services | ||||||
|                 UpdateCompleted?.Invoke(this, new RetResult(false, $"{ResUI.Downloading}   {url}")); |                 UpdateCompleted?.Invoke(this, new RetResult(false, $"{ResUI.Downloading}   {url}")); | ||||||
| 
 | 
 | ||||||
|                 var progress = new Progress<double>(); |                 var progress = new Progress<double>(); | ||||||
|                 progress.ProgressChanged += (sender, value) => |                 progress.ProgressChanged += (sender, value) => UpdateCompleted?.Invoke(this, new RetResult(value > 100, $"...{value}%")); | ||||||
|                 { |  | ||||||
|                     UpdateCompleted?.Invoke(this, new RetResult(value > 100, $"...{value}%")); |  | ||||||
|                 }; |  | ||||||
| 
 | 
 | ||||||
|                 var webProxy = await GetWebProxy(blProxy); |                 var webProxy = await GetWebProxy(blProxy); | ||||||
|                 await DownloaderHelper.Instance.DownloadFileAsync(webProxy, |                 await DownloaderHelper.Instance.DownloadFileAsync(webProxy, | ||||||
|  | @ -108,7 +98,7 @@ namespace ServiceLib.Services | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 var result1 = await DownloadStringAsync(url, blProxy, userAgent, 15); |                 var result1 = await DownloadStringAsync(url, blProxy, userAgent, 15); | ||||||
|                 if (Utils.IsNotEmpty(result1)) |                 if (result1.IsNotEmpty()) | ||||||
|                 { |                 { | ||||||
|                     return result1; |                     return result1; | ||||||
|                 } |                 } | ||||||
|  | @ -126,7 +116,7 @@ namespace ServiceLib.Services | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 var result2 = await DownloadStringViaDownloader(url, blProxy, userAgent, 15); |                 var result2 = await DownloadStringViaDownloader(url, blProxy, userAgent, 15); | ||||||
|                 if (Utils.IsNotEmpty(result2)) |                 if (result2.IsNotEmpty()) | ||||||
|                 { |                 { | ||||||
|                     return result2; |                     return result2; | ||||||
|                 } |                 } | ||||||
|  | @ -160,7 +150,7 @@ namespace ServiceLib.Services | ||||||
|                     UseProxy = webProxy != null |                     UseProxy = webProxy != null | ||||||
|                 }); |                 }); | ||||||
| 
 | 
 | ||||||
|                 if (Utils.IsNullOrEmpty(userAgent)) |                 if (userAgent.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     userAgent = Utils.GetVersion(false); |                     userAgent = Utils.GetVersion(false); | ||||||
|                 } |                 } | ||||||
|  | @ -168,7 +158,7 @@ namespace ServiceLib.Services | ||||||
| 
 | 
 | ||||||
|                 Uri uri = new(url); |                 Uri uri = new(url); | ||||||
|                 //Authorization Header |                 //Authorization Header | ||||||
|                 if (Utils.IsNotEmpty(uri.UserInfo)) |                 if (uri.UserInfo.IsNotEmpty()) | ||||||
|                 { |                 { | ||||||
|                     client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Utils.Base64Encode(uri.UserInfo)); |                     client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Utils.Base64Encode(uri.UserInfo)); | ||||||
|                 } |                 } | ||||||
|  | @ -201,7 +191,7 @@ namespace ServiceLib.Services | ||||||
| 
 | 
 | ||||||
|                 var webProxy = await GetWebProxy(blProxy); |                 var webProxy = await GetWebProxy(blProxy); | ||||||
| 
 | 
 | ||||||
|                 if (Utils.IsNullOrEmpty(userAgent)) |                 if (userAgent.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     userAgent = Utils.GetVersion(false); |                     userAgent = Utils.GetVersion(false); | ||||||
|                 } |                 } | ||||||
|  | @ -263,7 +253,7 @@ namespace ServiceLib.Services | ||||||
|                 for (var i = 0; i < 2; i++) |                 for (var i = 0; i < 2; i++) | ||||||
|                 { |                 { | ||||||
|                     var timer = Stopwatch.StartNew(); |                     var timer = Stopwatch.StartNew(); | ||||||
|                     await client.GetAsync(url, cts.Token); |                     await client.GetAsync(url, cts.Token).ConfigureAwait(false); | ||||||
|                     timer.Stop(); |                     timer.Stop(); | ||||||
|                     oneTime.Add((int)timer.Elapsed.TotalMilliseconds); |                     oneTime.Add((int)timer.Elapsed.TotalMilliseconds); | ||||||
|                     await Task.Delay(100); |                     await Task.Delay(100); | ||||||
|  |  | ||||||
|  | @ -141,8 +141,7 @@ namespace ServiceLib.Services | ||||||
|                     } |                     } | ||||||
|                 })); |                 })); | ||||||
|             } |             } | ||||||
|             Task.WaitAll([.. tasks]); |             await Task.WhenAll(tasks); | ||||||
|             await Task.CompletedTask; |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private async Task RunRealPingBatchAsync(List<ServerTestItem> lstSelected, string exitLoopKey, int pageSize = 0) |         private async Task RunRealPingBatchAsync(List<ServerTestItem> lstSelected, string exitLoopKey, int pageSize = 0) | ||||||
|  | @ -216,7 +215,7 @@ namespace ServiceLib.Services | ||||||
|                         await DoRealPing(downloadHandle, it); |                         await DoRealPing(downloadHandle, it); | ||||||
|                     })); |                     })); | ||||||
|                 } |                 } | ||||||
|                 Task.WaitAll(tasks.ToArray()); |                 await Task.WhenAll(tasks); | ||||||
|             } |             } | ||||||
|             catch (Exception ex) |             catch (Exception ex) | ||||||
|             { |             { | ||||||
|  | @ -291,7 +290,7 @@ namespace ServiceLib.Services | ||||||
|                     } |                     } | ||||||
|                 })); |                 })); | ||||||
|             } |             } | ||||||
|             Task.WaitAll(tasks.ToArray()); |             await Task.WhenAll(tasks); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private async Task<int> DoRealPing(DownloadService downloadHandle, ServerTestItem it) |         private async Task<int> DoRealPing(DownloadService downloadHandle, ServerTestItem it) | ||||||
|  |  | ||||||
|  | @ -5,7 +5,7 @@ namespace ServiceLib.Services.Statistics | ||||||
| { | { | ||||||
|     public class StatisticsSingboxService |     public class StatisticsSingboxService | ||||||
|     { |     { | ||||||
|         private Config _config; |         private readonly Config _config; | ||||||
|         private bool _exitFlag; |         private bool _exitFlag; | ||||||
|         private ClientWebSocket? webSocket; |         private ClientWebSocket? webSocket; | ||||||
|         private Action<ServerSpeedItem>? _updateFunc; |         private Action<ServerSpeedItem>? _updateFunc; | ||||||
|  | @ -18,7 +18,7 @@ namespace ServiceLib.Services.Statistics | ||||||
|             _updateFunc = updateFunc; |             _updateFunc = updateFunc; | ||||||
|             _exitFlag = false; |             _exitFlag = false; | ||||||
| 
 | 
 | ||||||
|             Task.Run(Run); |             _ = Task.Run(Run); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private async Task Init() |         private async Task Init() | ||||||
|  | @ -68,8 +68,7 @@ namespace ServiceLib.Services.Statistics | ||||||
|                     } |                     } | ||||||
|                     if (webSocket != null) |                     if (webSocket != null) | ||||||
|                     { |                     { | ||||||
|                         if (webSocket.State == WebSocketState.Aborted |                         if (webSocket.State is WebSocketState.Aborted or WebSocketState.Closed) | ||||||
|                             || webSocket.State == WebSocketState.Closed) |  | ||||||
|                         { |                         { | ||||||
|                             webSocket.Abort(); |                             webSocket.Abort(); | ||||||
|                             webSocket = null; |                             webSocket = null; | ||||||
|  | @ -87,9 +86,9 @@ namespace ServiceLib.Services.Statistics | ||||||
|                         while (!res.CloseStatus.HasValue) |                         while (!res.CloseStatus.HasValue) | ||||||
|                         { |                         { | ||||||
|                             var result = Encoding.UTF8.GetString(buffer, 0, res.Count); |                             var result = Encoding.UTF8.GetString(buffer, 0, res.Count); | ||||||
|                             if (Utils.IsNotEmpty(result)) |                             if (result.IsNotEmpty()) | ||||||
|                             { |                             { | ||||||
|                                 ParseOutput(result, out ulong up, out ulong down); |                                 ParseOutput(result, out var up, out var down); | ||||||
| 
 | 
 | ||||||
|                                 _updateFunc?.Invoke(new ServerSpeedItem() |                                 _updateFunc?.Invoke(new ServerSpeedItem() | ||||||
|                                 { |                                 { | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ namespace ServiceLib.Services.Statistics | ||||||
|     { |     { | ||||||
|         private const long linkBase = 1024; |         private const long linkBase = 1024; | ||||||
|         private ServerSpeedItem _serverSpeedItem = new(); |         private ServerSpeedItem _serverSpeedItem = new(); | ||||||
|         private Config _config; |         private readonly Config _config; | ||||||
|         private bool _exitFlag; |         private bool _exitFlag; | ||||||
|         private Action<ServerSpeedItem>? _updateFunc; |         private Action<ServerSpeedItem>? _updateFunc; | ||||||
|         private string Url => $"{Global.HttpProtocol}{Global.Loopback}:{AppHandler.Instance.StatePort}/debug/vars"; |         private string Url => $"{Global.HttpProtocol}{Global.Loopback}:{AppHandler.Instance.StatePort}/debug/vars"; | ||||||
|  | @ -15,7 +15,7 @@ namespace ServiceLib.Services.Statistics | ||||||
|             _updateFunc = updateFunc; |             _updateFunc = updateFunc; | ||||||
|             _exitFlag = false; |             _exitFlag = false; | ||||||
| 
 | 
 | ||||||
|             Task.Run(Run); |             _ = Task.Run(Run); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public void Close() |         public void Close() | ||||||
|  | @ -60,11 +60,13 @@ namespace ServiceLib.Services.Statistics | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 ServerSpeedItem server = new(); |                 ServerSpeedItem server = new(); | ||||||
|                 foreach (string key in source.stats.outbound.Keys) |                 foreach (var key in source.stats.outbound.Keys.Cast<string>()) | ||||||
|                 { |                 { | ||||||
|                     var value = source.stats.outbound[key]; |                     var value = source.stats.outbound[key]; | ||||||
|                     if (value == null) |                     if (value == null) | ||||||
|  |                     { | ||||||
|                         continue; |                         continue; | ||||||
|  |                     } | ||||||
|                     var state = JsonUtils.Deserialize<V2rayMetricsVarsLink>(value.ToString()); |                     var state = JsonUtils.Deserialize<V2rayMetricsVarsLink>(value.ToString()); | ||||||
| 
 | 
 | ||||||
|                     if (key.StartsWith(Global.ProxyTag)) |                     if (key.StartsWith(Global.ProxyTag)) | ||||||
|  |  | ||||||
|  | @ -123,7 +123,7 @@ namespace ServiceLib.Services | ||||||
|                 var url = item.Url.TrimEx(); |                 var url = item.Url.TrimEx(); | ||||||
|                 var userAgent = item.UserAgent.TrimEx(); |                 var userAgent = item.UserAgent.TrimEx(); | ||||||
|                 var hashCode = $"{item.Remarks}->"; |                 var hashCode = $"{item.Remarks}->"; | ||||||
|                 if (Utils.IsNullOrEmpty(id) || Utils.IsNullOrEmpty(url) || (Utils.IsNotEmpty(subId) && item.Id != subId)) |                 if (id.IsNullOrEmpty() || url.IsNullOrEmpty() || (subId.IsNotEmpty() && item.Id != subId)) | ||||||
|                 { |                 { | ||||||
|                     //_updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgNoValidSubscription}"); |                     //_updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgNoValidSubscription}"); | ||||||
|                     continue; |                     continue; | ||||||
|  | @ -149,9 +149,9 @@ namespace ServiceLib.Services | ||||||
|                 //one url |                 //one url | ||||||
|                 url = Utils.GetPunycode(url); |                 url = Utils.GetPunycode(url); | ||||||
|                 //convert |                 //convert | ||||||
|                 if (Utils.IsNotEmpty(item.ConvertTarget)) |                 if (item.ConvertTarget.IsNotEmpty()) | ||||||
|                 { |                 { | ||||||
|                     var subConvertUrl = Utils.IsNullOrEmpty(config.ConstItem.SubConvertUrl) ? Global.SubConvertUrls.FirstOrDefault() : config.ConstItem.SubConvertUrl; |                     var subConvertUrl = config.ConstItem.SubConvertUrl.IsNullOrEmpty() ? Global.SubConvertUrls.FirstOrDefault() : config.ConstItem.SubConvertUrl; | ||||||
|                     url = string.Format(subConvertUrl!, Utils.UrlEncode(url)); |                     url = string.Format(subConvertUrl!, Utils.UrlEncode(url)); | ||||||
|                     if (!url.Contains("target=")) |                     if (!url.Contains("target=")) | ||||||
|                     { |                     { | ||||||
|  | @ -163,15 +163,15 @@ namespace ServiceLib.Services | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 var result = await downloadHandle.TryDownloadString(url, blProxy, userAgent); |                 var result = await downloadHandle.TryDownloadString(url, blProxy, userAgent); | ||||||
|                 if (blProxy && Utils.IsNullOrEmpty(result)) |                 if (blProxy && result.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     result = await downloadHandle.TryDownloadString(url, false, userAgent); |                     result = await downloadHandle.TryDownloadString(url, false, userAgent); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 //more url |                 //more url | ||||||
|                 if (Utils.IsNullOrEmpty(item.ConvertTarget) && Utils.IsNotEmpty(item.MoreUrl.TrimEx())) |                 if (item.ConvertTarget.IsNullOrEmpty() && item.MoreUrl.TrimEx().IsNotEmpty()) | ||||||
|                 { |                 { | ||||||
|                     if (Utils.IsNotEmpty(result) && Utils.IsBase64String(result)) |                     if (result.IsNotEmpty() && Utils.IsBase64String(result)) | ||||||
|                     { |                     { | ||||||
|                         result = Utils.Base64Decode(result); |                         result = Utils.Base64Decode(result); | ||||||
|                     } |                     } | ||||||
|  | @ -180,17 +180,17 @@ namespace ServiceLib.Services | ||||||
|                     foreach (var it in lstUrl) |                     foreach (var it in lstUrl) | ||||||
|                     { |                     { | ||||||
|                         var url2 = Utils.GetPunycode(it); |                         var url2 = Utils.GetPunycode(it); | ||||||
|                         if (Utils.IsNullOrEmpty(url2)) |                         if (url2.IsNullOrEmpty()) | ||||||
|                         { |                         { | ||||||
|                             continue; |                             continue; | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
|                         var result2 = await downloadHandle.TryDownloadString(url2, blProxy, userAgent); |                         var result2 = await downloadHandle.TryDownloadString(url2, blProxy, userAgent); | ||||||
|                         if (blProxy && Utils.IsNullOrEmpty(result2)) |                         if (blProxy && result2.IsNullOrEmpty()) | ||||||
|                         { |                         { | ||||||
|                             result2 = await downloadHandle.TryDownloadString(url2, false, userAgent); |                             result2 = await downloadHandle.TryDownloadString(url2, false, userAgent); | ||||||
|                         } |                         } | ||||||
|                         if (Utils.IsNotEmpty(result2)) |                         if (result2.IsNotEmpty()) | ||||||
|                         { |                         { | ||||||
|                             if (Utils.IsBase64String(result2)) |                             if (Utils.IsBase64String(result2)) | ||||||
|                             { |                             { | ||||||
|  | @ -204,7 +204,7 @@ namespace ServiceLib.Services | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 if (Utils.IsNullOrEmpty(result)) |                 if (result.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     _updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgSubscriptionDecodingFailed}"); |                     _updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgSubscriptionDecodingFailed}"); | ||||||
|                 } |                 } | ||||||
|  | @ -287,7 +287,7 @@ namespace ServiceLib.Services | ||||||
|             { |             { | ||||||
|                 var url = coreInfo?.ReleaseApiUrl; |                 var url = coreInfo?.ReleaseApiUrl; | ||||||
|                 var result = await downloadHandle.TryDownloadString(url, true, Global.AppName); |                 var result = await downloadHandle.TryDownloadString(url, true, Global.AppName); | ||||||
|                 if (Utils.IsNullOrEmpty(result)) |                 if (result.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     return new RetResult(false, ""); |                     return new RetResult(false, ""); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  | @ -42,14 +42,14 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|         private async Task SaveServerAsync() |         private async Task SaveServerAsync() | ||||||
|         { |         { | ||||||
|             string remarks = SelectedSource.Remarks; |             var remarks = SelectedSource.Remarks; | ||||||
|             if (Utils.IsNullOrEmpty(remarks)) |             if (remarks.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 NoticeHandler.Instance.Enqueue(ResUI.PleaseFillRemarks); |                 NoticeHandler.Instance.Enqueue(ResUI.PleaseFillRemarks); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (Utils.IsNullOrEmpty(SelectedSource.Address)) |             if (SelectedSource.Address.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 NoticeHandler.Instance.Enqueue(ResUI.FillServerAddressCustom); |                 NoticeHandler.Instance.Enqueue(ResUI.FillServerAddressCustom); | ||||||
|                 return; |                 return; | ||||||
|  | @ -69,7 +69,7 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|         public async Task BrowseServer(string fileName) |         public async Task BrowseServer(string fileName) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(fileName)) |             if (fileName.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  | @ -80,7 +80,7 @@ namespace ServiceLib.ViewModels | ||||||
|             if (await ConfigHandler.AddCustomServer(_config, item, false) == 0) |             if (await ConfigHandler.AddCustomServer(_config, item, false) == 0) | ||||||
|             { |             { | ||||||
|                 NoticeHandler.Instance.Enqueue(ResUI.SuccessfullyImportedCustomServer); |                 NoticeHandler.Instance.Enqueue(ResUI.SuccessfullyImportedCustomServer); | ||||||
|                 if (Utils.IsNotEmpty(item.IndexId)) |                 if (item.IndexId.IsNotEmpty()) | ||||||
|                 { |                 { | ||||||
|                     SelectedSource = JsonUtils.DeepCopy(item); |                     SelectedSource = JsonUtils.DeepCopy(item); | ||||||
|                 } |                 } | ||||||
|  | @ -95,7 +95,7 @@ namespace ServiceLib.ViewModels | ||||||
|         private async Task EditServer() |         private async Task EditServer() | ||||||
|         { |         { | ||||||
|             var address = SelectedSource.Address; |             var address = SelectedSource.Address; | ||||||
|             if (Utils.IsNullOrEmpty(address)) |             if (address.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 NoticeHandler.Instance.Enqueue(ResUI.FillServerAddressCustom); |                 NoticeHandler.Instance.Enqueue(ResUI.FillServerAddressCustom); | ||||||
|                 return; |                 return; | ||||||
|  |  | ||||||
|  | @ -41,19 +41,19 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|         private async Task SaveServerAsync() |         private async Task SaveServerAsync() | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(SelectedSource.Remarks)) |             if (SelectedSource.Remarks.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 NoticeHandler.Instance.Enqueue(ResUI.PleaseFillRemarks); |                 NoticeHandler.Instance.Enqueue(ResUI.PleaseFillRemarks); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (Utils.IsNullOrEmpty(SelectedSource.Address)) |             if (SelectedSource.Address.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 NoticeHandler.Instance.Enqueue(ResUI.FillServerAddress); |                 NoticeHandler.Instance.Enqueue(ResUI.FillServerAddress); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             var port = SelectedSource.Port.ToString(); |             var port = SelectedSource.Port.ToString(); | ||||||
|             if (Utils.IsNullOrEmpty(port) || !Utils.IsNumeric(port) |             if (port.IsNullOrEmpty() || !Utils.IsNumeric(port) | ||||||
|                 || SelectedSource.Port <= 0 || SelectedSource.Port >= Global.MaxPort) |                 || SelectedSource.Port <= 0 || SelectedSource.Port >= Global.MaxPort) | ||||||
|             { |             { | ||||||
|                 NoticeHandler.Instance.Enqueue(ResUI.FillCorrectServerPort); |                 NoticeHandler.Instance.Enqueue(ResUI.FillCorrectServerPort); | ||||||
|  | @ -61,21 +61,20 @@ namespace ServiceLib.ViewModels | ||||||
|             } |             } | ||||||
|             if (SelectedSource.ConfigType == EConfigType.Shadowsocks) |             if (SelectedSource.ConfigType == EConfigType.Shadowsocks) | ||||||
|             { |             { | ||||||
|                 if (Utils.IsNullOrEmpty(SelectedSource.Id)) |                 if (SelectedSource.Id.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     NoticeHandler.Instance.Enqueue(ResUI.FillPassword); |                     NoticeHandler.Instance.Enqueue(ResUI.FillPassword); | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|                 if (Utils.IsNullOrEmpty(SelectedSource.Security)) |                 if (SelectedSource.Security.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     NoticeHandler.Instance.Enqueue(ResUI.PleaseSelectEncryption); |                     NoticeHandler.Instance.Enqueue(ResUI.PleaseSelectEncryption); | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             if (SelectedSource.ConfigType != EConfigType.SOCKS |             if (SelectedSource.ConfigType is not EConfigType.SOCKS and not EConfigType.HTTP) | ||||||
|                 && SelectedSource.ConfigType != EConfigType.HTTP) |  | ||||||
|             { |             { | ||||||
|                 if (Utils.IsNullOrEmpty(SelectedSource.Id)) |                 if (SelectedSource.Id.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     NoticeHandler.Instance.Enqueue(ResUI.FillUUID); |                     NoticeHandler.Instance.Enqueue(ResUI.FillUUID); | ||||||
|                     return; |                     return; | ||||||
|  |  | ||||||
|  | @ -50,7 +50,7 @@ namespace ServiceLib.ViewModels | ||||||
|         { |         { | ||||||
|             DisplayOperationMsg(); |             DisplayOperationMsg(); | ||||||
|             _config.WebDavItem = SelectedSource; |             _config.WebDavItem = SelectedSource; | ||||||
|             await ConfigHandler.SaveConfig(_config); |             _ = await ConfigHandler.SaveConfig(_config); | ||||||
| 
 | 
 | ||||||
|             var result = await WebDavHandler.Instance.CheckConnection(); |             var result = await WebDavHandler.Instance.CheckConnection(); | ||||||
|             if (result) |             if (result) | ||||||
|  | @ -114,7 +114,7 @@ namespace ServiceLib.ViewModels | ||||||
|         public async Task LocalRestore(string fileName) |         public async Task LocalRestore(string fileName) | ||||||
|         { |         { | ||||||
|             DisplayOperationMsg(); |             DisplayOperationMsg(); | ||||||
|             if (Utils.IsNullOrEmpty(fileName)) |             if (fileName.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  | @ -151,7 +151,7 @@ namespace ServiceLib.ViewModels | ||||||
|                 { |                 { | ||||||
|                     if (Utils.UpgradeAppExists(out var upgradeFileName)) |                     if (Utils.UpgradeAppExists(out var upgradeFileName)) | ||||||
|                     { |                     { | ||||||
|                         ProcUtils.ProcessStart(upgradeFileName, Global.RebootAs, Utils.StartupPath()); |                         _ = ProcUtils.ProcessStart(upgradeFileName, Global.RebootAs, Utils.StartupPath()); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 service?.Shutdown(true); |                 service?.Shutdown(true); | ||||||
|  | @ -164,7 +164,7 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|         private async Task<bool> CreateZipFileFromDirectory(string fileName) |         private async Task<bool> CreateZipFileFromDirectory(string fileName) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(fileName)) |             if (fileName.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -32,7 +32,7 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|             var canEditRemove = this.WhenAnyValue( |             var canEditRemove = this.WhenAnyValue( | ||||||
|              x => x.SelectedSource, |              x => x.SelectedSource, | ||||||
|              selectedSource => selectedSource != null && Utils.IsNotEmpty(selectedSource.Id)); |              selectedSource => selectedSource != null && selectedSource.Id.IsNotEmpty()); | ||||||
| 
 | 
 | ||||||
|             this.WhenAnyValue( |             this.WhenAnyValue( | ||||||
|                x => x.AutoRefresh, |                x => x.AutoRefresh, | ||||||
|  | @ -53,7 +53,78 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|         private async Task Init() |         private async Task Init() | ||||||
|         { |         { | ||||||
|             Task.Run(async () => |             _ = DelayTestTask(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private async Task GetClashConnections() | ||||||
|  |         { | ||||||
|  |             var ret = await ClashApiHandler.Instance.GetClashConnectionsAsync(_config); | ||||||
|  |             if (ret == null) | ||||||
|  |             { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             _ = _updateView?.Invoke(EViewAction.DispatcherRefreshConnections, ret?.connections); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void RefreshConnections(List<ConnectionItem>? connections) | ||||||
|  |         { | ||||||
|  |             _connectionItems.Clear(); | ||||||
|  | 
 | ||||||
|  |             var dtNow = DateTime.Now; | ||||||
|  |             var lstModel = new List<ClashConnectionModel>(); | ||||||
|  |             foreach (var item in connections ?? new()) | ||||||
|  |             { | ||||||
|  |                 var host = $"{(item.metadata.host.IsNullOrEmpty() ? item.metadata.destinationIP : item.metadata.host)}:{item.metadata.destinationPort}"; | ||||||
|  |                 if (HostFilter.IsNotEmpty() && !host.Contains(HostFilter)) | ||||||
|  |                 { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 var model = new ClashConnectionModel | ||||||
|  |                 { | ||||||
|  |                     Id = item.id, | ||||||
|  |                     Network = item.metadata.network, | ||||||
|  |                     Type = item.metadata.type, | ||||||
|  |                     Host = host, | ||||||
|  |                     Time = (dtNow - item.start).TotalSeconds < 0 ? 1 : (dtNow - item.start).TotalSeconds, | ||||||
|  |                     Elapsed = (dtNow - item.start).ToString(@"hh\:mm\:ss"), | ||||||
|  |                     Chain = $"{item.rule} , {string.Join("->", item.chains ?? new())}" | ||||||
|  |                 }; | ||||||
|  | 
 | ||||||
|  |                 lstModel.Add(model); | ||||||
|  |             } | ||||||
|  |             if (lstModel.Count <= 0) | ||||||
|  |             { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             _connectionItems.AddRange(lstModel); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public async Task ClashConnectionClose(bool all) | ||||||
|  |         { | ||||||
|  |             var id = string.Empty; | ||||||
|  |             if (!all) | ||||||
|  |             { | ||||||
|  |                 var item = SelectedSource; | ||||||
|  |                 if (item is null) | ||||||
|  |                 { | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 id = item.Id; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 _connectionItems.Clear(); | ||||||
|  |             } | ||||||
|  |             await ClashApiHandler.Instance.ClashConnectionClose(id); | ||||||
|  |             await GetClashConnections(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public async Task DelayTestTask() | ||||||
|  |         { | ||||||
|  |             _ = Task.Run(async () => | ||||||
|             { |             { | ||||||
|                 var numOfExecuted = 1; |                 var numOfExecuted = 1; | ||||||
|                 while (true) |                 while (true) | ||||||
|  | @ -80,70 +151,5 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|             await Task.CompletedTask; |             await Task.CompletedTask; | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         private async Task GetClashConnections() |  | ||||||
|         { |  | ||||||
|             var ret = await ClashApiHandler.Instance.GetClashConnectionsAsync(_config); |  | ||||||
|             if (ret == null) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             _updateView?.Invoke(EViewAction.DispatcherRefreshConnections, ret?.connections); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public void RefreshConnections(List<ConnectionItem>? connections) |  | ||||||
|         { |  | ||||||
|             _connectionItems.Clear(); |  | ||||||
| 
 |  | ||||||
|             var dtNow = DateTime.Now; |  | ||||||
|             var lstModel = new List<ClashConnectionModel>(); |  | ||||||
|             foreach (var item in connections ?? new()) |  | ||||||
|             { |  | ||||||
|                 var host = $"{(Utils.IsNullOrEmpty(item.metadata.host) ? item.metadata.destinationIP : item.metadata.host)}:{item.metadata.destinationPort}"; |  | ||||||
|                 if (HostFilter.IsNotEmpty() && !host.Contains(HostFilter)) |  | ||||||
|                 { |  | ||||||
|                     continue; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 ClashConnectionModel model = new(); |  | ||||||
| 
 |  | ||||||
|                 model.Id = item.id; |  | ||||||
|                 model.Network = item.metadata.network; |  | ||||||
|                 model.Type = item.metadata.type; |  | ||||||
|                 model.Host = host; |  | ||||||
|                 var sp = (dtNow - item.start); |  | ||||||
|                 model.Time = sp.TotalSeconds < 0 ? 1 : sp.TotalSeconds; |  | ||||||
|                 model.Elapsed = sp.ToString(@"hh\:mm\:ss"); |  | ||||||
|                 item.chains?.Reverse(); |  | ||||||
|                 model.Chain = $"{item.rule} , {string.Join("->", item.chains ?? new())}"; |  | ||||||
| 
 |  | ||||||
|                 lstModel.Add(model); |  | ||||||
|             } |  | ||||||
|             if (lstModel.Count <= 0) |  | ||||||
|             { return; } |  | ||||||
| 
 |  | ||||||
|             _connectionItems.AddRange(lstModel); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public async Task ClashConnectionClose(bool all) |  | ||||||
|         { |  | ||||||
|             var id = string.Empty; |  | ||||||
|             if (!all) |  | ||||||
|             { |  | ||||||
|                 var item = SelectedSource; |  | ||||||
|                 if (item is null) |  | ||||||
|                 { |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|                 id = item.Id; |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 _connectionItems.Clear(); |  | ||||||
|             } |  | ||||||
|             await ClashApiHandler.Instance.ClashConnectionClose(id); |  | ||||||
|             await GetClashConnections(); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -72,7 +72,7 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|             this.WhenAnyValue( |             this.WhenAnyValue( | ||||||
|                x => x.SelectedGroup, |                x => x.SelectedGroup, | ||||||
|                y => y != null && Utils.IsNotEmpty(y.Name)) |                y => y != null && y.Name.IsNotEmpty()) | ||||||
|                    .Subscribe(c => RefreshProxyDetails(c)); |                    .Subscribe(c => RefreshProxyDetails(c)); | ||||||
| 
 | 
 | ||||||
|             this.WhenAnyValue( |             this.WhenAnyValue( | ||||||
|  | @ -96,7 +96,6 @@ namespace ServiceLib.ViewModels | ||||||
|         private async Task Init() |         private async Task Init() | ||||||
|         { |         { | ||||||
|             _ = DelayTestTask(); |             _ = DelayTestTask(); | ||||||
|             await ProxiesReload(); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private async Task DoRulemodeSelected(bool c) |         private async Task DoRulemodeSelected(bool c) | ||||||
|  | @ -135,22 +134,12 @@ namespace ServiceLib.ViewModels | ||||||
|             RefreshProxyDetails(c); |             RefreshProxyDetails(c); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private void UpdateHandler(bool notify, string msg) |  | ||||||
|         { |  | ||||||
|             NoticeHandler.Instance.SendMessageEx(msg); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public async Task ProxiesReload() |         public async Task ProxiesReload() | ||||||
|         { |         { | ||||||
|             await GetClashProxies(true); |             await GetClashProxies(true); | ||||||
|             await ProxiesDelayTest(); |             await ProxiesDelayTest(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public async Task ProxiesDelayTest() |  | ||||||
|         { |  | ||||||
|             await ProxiesDelayTest(true); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #region proxy function |         #region proxy function | ||||||
| 
 | 
 | ||||||
|         private async Task SetRuleMode(ERuleMode mode) |         private async Task SetRuleMode(ERuleMode mode) | ||||||
|  | @ -193,7 +182,7 @@ namespace ServiceLib.ViewModels | ||||||
|             { |             { | ||||||
|                 foreach (var it in proxyGroups) |                 foreach (var it in proxyGroups) | ||||||
|                 { |                 { | ||||||
|                     if (Utils.IsNullOrEmpty(it.name) || !_proxies.ContainsKey(it.name)) |                     if (it.name.IsNullOrEmpty() || !_proxies.ContainsKey(it.name)) | ||||||
|                     { |                     { | ||||||
|                         continue; |                         continue; | ||||||
|                     } |                     } | ||||||
|  | @ -218,8 +207,8 @@ namespace ServiceLib.ViewModels | ||||||
|                 { |                 { | ||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
|                 var item = _proxyGroups.Where(t => t.Name == kv.Key).FirstOrDefault(); |                 var item = _proxyGroups.FirstOrDefault(t => t.Name == kv.Key); | ||||||
|                 if (item != null && Utils.IsNotEmpty(item.Name)) |                 if (item != null && item.Name.IsNotEmpty()) | ||||||
|                 { |                 { | ||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
|  | @ -256,7 +245,7 @@ namespace ServiceLib.ViewModels | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             var name = SelectedGroup?.Name; |             var name = SelectedGroup?.Name; | ||||||
|             if (Utils.IsNullOrEmpty(name)) |             if (name.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  | @ -341,21 +330,21 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|         public async Task SetActiveProxy() |         public async Task SetActiveProxy() | ||||||
|         { |         { | ||||||
|             if (SelectedGroup == null || Utils.IsNullOrEmpty(SelectedGroup.Name)) |             if (SelectedGroup == null || SelectedGroup.Name.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             if (SelectedDetail == null || Utils.IsNullOrEmpty(SelectedDetail.Name)) |             if (SelectedDetail == null || SelectedDetail.Name.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             var name = SelectedGroup.Name; |             var name = SelectedGroup.Name; | ||||||
|             if (Utils.IsNullOrEmpty(name)) |             if (name.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             var nameNode = SelectedDetail.Name; |             var nameNode = SelectedDetail.Name; | ||||||
|             if (Utils.IsNullOrEmpty(nameNode)) |             if (nameNode.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  | @ -369,7 +358,7 @@ namespace ServiceLib.ViewModels | ||||||
|             await ClashApiHandler.Instance.ClashSetActiveProxy(name, nameNode); |             await ClashApiHandler.Instance.ClashSetActiveProxy(name, nameNode); | ||||||
| 
 | 
 | ||||||
|             selectedProxy.now = nameNode; |             selectedProxy.now = nameNode; | ||||||
|             var group = _proxyGroups.Where(it => it.Name == SelectedGroup.Name).FirstOrDefault(); |             var group = _proxyGroups.FirstOrDefault(it => it.Name == SelectedGroup.Name); | ||||||
|             if (group != null) |             if (group != null) | ||||||
|             { |             { | ||||||
|                 group.Now = nameNode; |                 group.Now = nameNode; | ||||||
|  | @ -381,7 +370,7 @@ namespace ServiceLib.ViewModels | ||||||
|             NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess); |             NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private async Task ProxiesDelayTest(bool blAll) |         private async Task ProxiesDelayTest(bool blAll = true) | ||||||
|         { |         { | ||||||
|             ClashApiHandler.Instance.ClashProxiesDelayTest(blAll, _proxyDetails.ToList(), async (item, result) => |             ClashApiHandler.Instance.ClashProxiesDelayTest(blAll, _proxyDetails.ToList(), async (item, result) => | ||||||
|             { |             { | ||||||
|  | @ -390,7 +379,7 @@ namespace ServiceLib.ViewModels | ||||||
|                     await GetClashProxies(true); |                     await GetClashProxies(true); | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|                 if (Utils.IsNullOrEmpty(result)) |                 if (result.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|  | @ -403,19 +392,19 @@ namespace ServiceLib.ViewModels | ||||||
|         public void ProxiesDelayTestResult(SpeedTestResult result) |         public void ProxiesDelayTestResult(SpeedTestResult result) | ||||||
|         { |         { | ||||||
|             //UpdateHandler(false, $"{item.name}={result}"); |             //UpdateHandler(false, $"{item.name}={result}"); | ||||||
|             var detail = _proxyDetails.Where(it => it.Name == result.IndexId).FirstOrDefault(); |             var detail = _proxyDetails.FirstOrDefault(it => it.Name == result.IndexId); | ||||||
|             if (detail != null) |             if (detail != null) | ||||||
|             { |             { | ||||||
|                 var dicResult = JsonUtils.Deserialize<Dictionary<string, object>>(result.Delay); |                 var dicResult = JsonUtils.Deserialize<Dictionary<string, object>>(result.Delay); | ||||||
|                 if (dicResult != null && dicResult.ContainsKey("delay")) |                 if (dicResult != null && dicResult.TryGetValue("delay", out var value)) | ||||||
|                 { |                 { | ||||||
|                     detail.Delay = Convert.ToInt32(dicResult["delay"].ToString()); |                     detail.Delay = Convert.ToInt32(value.ToString()); | ||||||
|                     detail.DelayName = $"{detail.Delay}ms"; |                     detail.DelayName = $"{detail.Delay}ms"; | ||||||
|                 } |                 } | ||||||
|                 else if (dicResult != null && dicResult.ContainsKey("message")) |                 else if (dicResult != null && dicResult.TryGetValue("message", out var value1)) | ||||||
|                 { |                 { | ||||||
|                     detail.Delay = _delayTimeout; |                     detail.Delay = _delayTimeout; | ||||||
|                     detail.DelayName = $"{dicResult["message"]}"; |                     detail.DelayName = $"{value1}"; | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
|  | @ -432,7 +421,7 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|         public async Task DelayTestTask() |         public async Task DelayTestTask() | ||||||
|         { |         { | ||||||
|             Task.Run(async () => |             _ = Task.Run(async () => | ||||||
|               { |               { | ||||||
|                   var numOfExecuted = 1; |                   var numOfExecuted = 1; | ||||||
|                   while (true) |                   while (true) | ||||||
|  |  | ||||||
|  | @ -6,15 +6,15 @@ namespace ServiceLib.ViewModels | ||||||
| { | { | ||||||
|     public class DNSSettingViewModel : MyReactiveObject |     public class DNSSettingViewModel : MyReactiveObject | ||||||
|     { |     { | ||||||
|         [Reactive] public bool useSystemHosts { get; set; } |         [Reactive] public bool UseSystemHosts { get; set; } | ||||||
|         [Reactive] public string domainStrategy4Freedom { get; set; } |         [Reactive] public string DomainStrategy4Freedom { get; set; } | ||||||
|         [Reactive] public string domainDNSAddress { get; set; } |         [Reactive] public string DomainDNSAddress { get; set; } | ||||||
|         [Reactive] public string normalDNS { get; set; } |         [Reactive] public string NormalDNS { get; set; } | ||||||
| 
 | 
 | ||||||
|         [Reactive] public string domainStrategy4Freedom2 { get; set; } |         [Reactive] public string DomainStrategy4Freedom2 { get; set; } | ||||||
|         [Reactive] public string domainDNSAddress2 { get; set; } |         [Reactive] public string DomainDNSAddress2 { get; set; } | ||||||
|         [Reactive] public string normalDNS2 { get; set; } |         [Reactive] public string NormalDNS2 { get; set; } | ||||||
|         [Reactive] public string tunDNS2 { get; set; } |         [Reactive] public string TunDNS2 { get; set; } | ||||||
| 
 | 
 | ||||||
|         public ReactiveCommand<Unit, Unit> SaveCmd { get; } |         public ReactiveCommand<Unit, Unit> SaveCmd { get; } | ||||||
|         public ReactiveCommand<Unit, Unit> ImportDefConfig4V2rayCmd { get; } |         public ReactiveCommand<Unit, Unit> ImportDefConfig4V2rayCmd { get; } | ||||||
|  | @ -31,14 +31,14 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|             ImportDefConfig4V2rayCmd = ReactiveCommand.CreateFromTask(async () => |             ImportDefConfig4V2rayCmd = ReactiveCommand.CreateFromTask(async () => | ||||||
|             { |             { | ||||||
|                 normalDNS = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName); |                 NormalDNS = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName); | ||||||
|                 await Task.CompletedTask; |                 await Task.CompletedTask; | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|             ImportDefConfig4SingboxCmd = ReactiveCommand.CreateFromTask(async () => |             ImportDefConfig4SingboxCmd = ReactiveCommand.CreateFromTask(async () => | ||||||
|             { |             { | ||||||
|                 normalDNS2 = EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName); |                 NormalDNS2 = EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName); | ||||||
|                 tunDNS2 = EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName); |                 TunDNS2 = EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName); | ||||||
|                 await Task.CompletedTask; |                 await Task.CompletedTask; | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|  | @ -48,47 +48,47 @@ namespace ServiceLib.ViewModels | ||||||
|         private async Task Init() |         private async Task Init() | ||||||
|         { |         { | ||||||
|             var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray); |             var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray); | ||||||
|             useSystemHosts = item.UseSystemHosts; |             UseSystemHosts = item.UseSystemHosts; | ||||||
|             domainStrategy4Freedom = item?.DomainStrategy4Freedom ?? string.Empty; |             DomainStrategy4Freedom = item?.DomainStrategy4Freedom ?? string.Empty; | ||||||
|             domainDNSAddress = item?.DomainDNSAddress ?? string.Empty; |             DomainDNSAddress = item?.DomainDNSAddress ?? string.Empty; | ||||||
|             normalDNS = item?.NormalDNS ?? string.Empty; |             NormalDNS = item?.NormalDNS ?? string.Empty; | ||||||
| 
 | 
 | ||||||
|             var item2 = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box); |             var item2 = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box); | ||||||
|             domainStrategy4Freedom2 = item2?.DomainStrategy4Freedom ?? string.Empty; |             DomainStrategy4Freedom2 = item2?.DomainStrategy4Freedom ?? string.Empty; | ||||||
|             domainDNSAddress2 = item2?.DomainDNSAddress ?? string.Empty; |             DomainDNSAddress2 = item2?.DomainDNSAddress ?? string.Empty; | ||||||
|             normalDNS2 = item2?.NormalDNS ?? string.Empty; |             NormalDNS2 = item2?.NormalDNS ?? string.Empty; | ||||||
|             tunDNS2 = item2?.TunDNS ?? string.Empty; |             TunDNS2 = item2?.TunDNS ?? string.Empty; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private async Task SaveSettingAsync() |         private async Task SaveSettingAsync() | ||||||
|         { |         { | ||||||
|             if (Utils.IsNotEmpty(normalDNS)) |             if (NormalDNS.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 var obj = JsonUtils.ParseJson(normalDNS); |                 var obj = JsonUtils.ParseJson(NormalDNS); | ||||||
|                 if (obj != null && obj["servers"] != null) |                 if (obj != null && obj["servers"] != null) | ||||||
|                 { |                 { | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
|                     if (normalDNS.Contains('{') || normalDNS.Contains('}')) |                     if (NormalDNS.Contains('{') || NormalDNS.Contains('}')) | ||||||
|                     { |                     { | ||||||
|                         NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText); |                         NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText); | ||||||
|                         return; |                         return; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(normalDNS2)) |             if (NormalDNS2.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 var obj2 = JsonUtils.Deserialize<Dns4Sbox>(normalDNS2); |                 var obj2 = JsonUtils.Deserialize<Dns4Sbox>(NormalDNS2); | ||||||
|                 if (obj2 == null) |                 if (obj2 == null) | ||||||
|                 { |                 { | ||||||
|                     NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText); |                     NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText); | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(tunDNS2)) |             if (TunDNS2.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 var obj2 = JsonUtils.Deserialize<Dns4Sbox>(tunDNS2); |                 var obj2 = JsonUtils.Deserialize<Dns4Sbox>(TunDNS2); | ||||||
|                 if (obj2 == null) |                 if (obj2 == null) | ||||||
|                 { |                 { | ||||||
|                     NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText); |                     NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText); | ||||||
|  | @ -97,21 +97,21 @@ namespace ServiceLib.ViewModels | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray); |             var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray); | ||||||
|             item.DomainStrategy4Freedom = domainStrategy4Freedom; |             item.DomainStrategy4Freedom = DomainStrategy4Freedom; | ||||||
|             item.DomainDNSAddress = domainDNSAddress; |             item.DomainDNSAddress = DomainDNSAddress; | ||||||
|             item.UseSystemHosts = useSystemHosts; |             item.UseSystemHosts = UseSystemHosts; | ||||||
|             item.NormalDNS = normalDNS; |             item.NormalDNS = NormalDNS; | ||||||
|             await ConfigHandler.SaveDNSItems(_config, item); |             await ConfigHandler.SaveDNSItems(_config, item); | ||||||
| 
 | 
 | ||||||
|             var item2 = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box); |             var item2 = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box); | ||||||
|             item2.DomainStrategy4Freedom = domainStrategy4Freedom2; |             item2.DomainStrategy4Freedom = DomainStrategy4Freedom2; | ||||||
|             item2.DomainDNSAddress = domainDNSAddress2; |             item2.DomainDNSAddress = DomainDNSAddress2; | ||||||
|             item2.NormalDNS = JsonUtils.Serialize(JsonUtils.ParseJson(normalDNS2)); |             item2.NormalDNS = JsonUtils.Serialize(JsonUtils.ParseJson(NormalDNS2)); | ||||||
|             item2.TunDNS = JsonUtils.Serialize(JsonUtils.ParseJson(tunDNS2)); |             item2.TunDNS = JsonUtils.Serialize(JsonUtils.ParseJson(TunDNS2)); | ||||||
|             await ConfigHandler.SaveDNSItems(_config, item2); |             await ConfigHandler.SaveDNSItems(_config, item2); | ||||||
| 
 | 
 | ||||||
|             NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess); |             NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess); | ||||||
|             _updateView?.Invoke(EViewAction.CloseWindow, null); |             _ = _updateView?.Invoke(EViewAction.CloseWindow, null); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -421,7 +421,7 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|         public async Task ScanImageResult(string fileName) |         public async Task ScanImageResult(string fileName) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(fileName)) |             if (fileName.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  | @ -432,7 +432,7 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|         private async Task AddScanResultAsync(string? result) |         private async Task AddScanResultAsync(string? result) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(result)) |             if (result.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 NoticeHandler.Instance.Enqueue(ResUI.NoValidQRcodeFound); |                 NoticeHandler.Instance.Enqueue(ResUI.NoValidQRcodeFound); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -266,7 +266,7 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|         private async Task SaveSettingAsync() |         private async Task SaveSettingAsync() | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(localPort.ToString()) || !Utils.IsNumeric(localPort.ToString()) |             if (localPort.ToString().IsNullOrEmpty() || !Utils.IsNumeric(localPort.ToString()) | ||||||
|                || localPort <= 0 || localPort >= Global.MaxPort) |                || localPort <= 0 || localPort >= Global.MaxPort) | ||||||
|             { |             { | ||||||
|                 NoticeHandler.Instance.Enqueue(ResUI.FillLocalListeningPort); |                 NoticeHandler.Instance.Enqueue(ResUI.FillLocalListeningPort); | ||||||
|  |  | ||||||
|  | @ -267,7 +267,7 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|         public void SetSpeedTestResult(SpeedTestResult result) |         public void SetSpeedTestResult(SpeedTestResult result) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(result.IndexId)) |             if (result.IndexId.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 NoticeHandler.Instance.SendMessageEx(result.Delay); |                 NoticeHandler.Instance.SendMessageEx(result.Delay); | ||||||
|                 NoticeHandler.Instance.Enqueue(result.Delay); |                 NoticeHandler.Instance.Enqueue(result.Delay); | ||||||
|  | @ -279,13 +279,13 @@ namespace ServiceLib.ViewModels | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (Utils.IsNotEmpty(result.Delay)) |             if (result.Delay.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 int.TryParse(result.Delay, out var temp); |                 int.TryParse(result.Delay, out var temp); | ||||||
|                 item.Delay = temp; |                 item.Delay = temp; | ||||||
|                 item.DelayVal = result.Delay ?? string.Empty; |                 item.DelayVal = result.Delay ?? string.Empty; | ||||||
|             } |             } | ||||||
|             if (Utils.IsNotEmpty(result.Speed)) |             if (result.Speed.IsNotEmpty()) | ||||||
|             { |             { | ||||||
|                 item.SpeedVal = result.Speed ?? string.Empty; |                 item.SpeedVal = result.Speed ?? string.Empty; | ||||||
|             } |             } | ||||||
|  | @ -350,7 +350,7 @@ namespace ServiceLib.ViewModels | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             _serverFilter = ServerFilter; |             _serverFilter = ServerFilter; | ||||||
|             if (Utils.IsNullOrEmpty(_serverFilter)) |             if (_serverFilter.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 RefreshServers(); |                 RefreshServers(); | ||||||
|             } |             } | ||||||
|  | @ -476,7 +476,7 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|         public async Task EditServerAsync(EConfigType eConfigType) |         public async Task EditServerAsync(EConfigType eConfigType) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(SelectedProfile?.IndexId)) |             if (string.IsNullOrEmpty(SelectedProfile?.IndexId)) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  | @ -557,7 +557,7 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|         public async Task SetDefaultServer() |         public async Task SetDefaultServer() | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(SelectedProfile?.IndexId)) |             if (string.IsNullOrEmpty(SelectedProfile?.IndexId)) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  | @ -566,7 +566,7 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|         public async Task SetDefaultServer(string indexId) |         public async Task SetDefaultServer(string indexId) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(indexId)) |             if (indexId.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  | @ -598,7 +598,7 @@ namespace ServiceLib.ViewModels | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             if (Utils.IsNullOrEmpty(SelectedServer.ID)) |             if (SelectedServer.ID.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  | @ -614,7 +614,7 @@ namespace ServiceLib.ViewModels | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             var url = FmtHandler.GetShareUri(item); |             var url = FmtHandler.GetShareUri(item); | ||||||
|             if (Utils.IsNullOrEmpty(url)) |             if (url.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  | @ -649,7 +649,7 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|         public async Task SortServer(string colName) |         public async Task SortServer(string colName) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(colName)) |             if (colName.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  | @ -776,7 +776,7 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|         public async Task Export2ClientConfigResult(string fileName, ProfileItem item) |         public async Task Export2ClientConfigResult(string fileName, ProfileItem item) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(fileName)) |             if (fileName.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  | @ -803,7 +803,7 @@ namespace ServiceLib.ViewModels | ||||||
|             foreach (var it in lstSelecteds) |             foreach (var it in lstSelecteds) | ||||||
|             { |             { | ||||||
|                 var url = FmtHandler.GetShareUri(it); |                 var url = FmtHandler.GetShareUri(it); | ||||||
|                 if (Utils.IsNullOrEmpty(url)) |                 if (url.IsNullOrEmpty()) | ||||||
|                 { |                 { | ||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  | @ -78,8 +78,8 @@ namespace ServiceLib.ViewModels | ||||||
|               || SelectedSource.Ip?.Count > 0 |               || SelectedSource.Ip?.Count > 0 | ||||||
|               || SelectedSource.Protocol?.Count > 0 |               || SelectedSource.Protocol?.Count > 0 | ||||||
|               || SelectedSource.Process?.Count > 0 |               || SelectedSource.Process?.Count > 0 | ||||||
|               || Utils.IsNotEmpty(SelectedSource.Port) |               || SelectedSource.Port.IsNotEmpty() | ||||||
|               || Utils.IsNotEmpty(SelectedSource.Network); |               || SelectedSource.Network.IsNotEmpty(); | ||||||
| 
 | 
 | ||||||
|             if (!hasRule) |             if (!hasRule) | ||||||
|             { |             { | ||||||
|  |  | ||||||
|  | @ -224,7 +224,7 @@ namespace ServiceLib.ViewModels | ||||||
|         private async Task SaveRoutingAsync() |         private async Task SaveRoutingAsync() | ||||||
|         { |         { | ||||||
|             string remarks = SelectedRouting.Remarks; |             string remarks = SelectedRouting.Remarks; | ||||||
|             if (Utils.IsNullOrEmpty(remarks)) |             if (remarks.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 NoticeHandler.Instance.Enqueue(ResUI.PleaseFillRemarks); |                 NoticeHandler.Instance.Enqueue(ResUI.PleaseFillRemarks); | ||||||
|                 return; |                 return; | ||||||
|  | @ -252,13 +252,13 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|         public async Task ImportRulesFromFileAsync(string fileName) |         public async Task ImportRulesFromFileAsync(string fileName) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(fileName)) |             if (fileName.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             var result = EmbedUtils.LoadResource(fileName); |             var result = EmbedUtils.LoadResource(fileName); | ||||||
|             if (Utils.IsNullOrEmpty(result)) |             if (result.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  | @ -288,7 +288,7 @@ namespace ServiceLib.ViewModels | ||||||
|         private async Task ImportRulesFromUrl() |         private async Task ImportRulesFromUrl() | ||||||
|         { |         { | ||||||
|             var url = SelectedRouting.Url; |             var url = SelectedRouting.Url; | ||||||
|             if (Utils.IsNullOrEmpty(url)) |             if (url.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 NoticeHandler.Instance.Enqueue(ResUI.MsgNeedUrl); |                 NoticeHandler.Instance.Enqueue(ResUI.MsgNeedUrl); | ||||||
|                 return; |                 return; | ||||||
|  | @ -311,7 +311,7 @@ namespace ServiceLib.ViewModels | ||||||
|             { |             { | ||||||
|                 blReplace = true; |                 blReplace = true; | ||||||
|             } |             } | ||||||
|             if (Utils.IsNullOrEmpty(clipboardData)) |             if (clipboardData.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return -1; |                 return -1; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -18,13 +18,13 @@ namespace ServiceLib.ViewModels | ||||||
|         public IList<RoutingItemModel> SelectedSources { get; set; } |         public IList<RoutingItemModel> SelectedSources { get; set; } | ||||||
| 
 | 
 | ||||||
|         [Reactive] |         [Reactive] | ||||||
|         public string domainStrategy { get; set; } |         public string DomainStrategy { get; set; } | ||||||
| 
 | 
 | ||||||
|         [Reactive] |         [Reactive] | ||||||
|         public string domainMatcher { get; set; } |         public string DomainMatcher { get; set; } | ||||||
| 
 | 
 | ||||||
|         [Reactive] |         [Reactive] | ||||||
|         public string domainStrategy4Singbox { get; set; } |         public string DomainStrategy4Singbox { get; set; } | ||||||
| 
 | 
 | ||||||
|         public ReactiveCommand<Unit, Unit> RoutingAdvancedAddCmd { get; } |         public ReactiveCommand<Unit, Unit> RoutingAdvancedAddCmd { get; } | ||||||
|         public ReactiveCommand<Unit, Unit> RoutingAdvancedRemoveCmd { get; } |         public ReactiveCommand<Unit, Unit> RoutingAdvancedRemoveCmd { get; } | ||||||
|  | @ -74,9 +74,9 @@ namespace ServiceLib.ViewModels | ||||||
|         { |         { | ||||||
|             SelectedSource = new(); |             SelectedSource = new(); | ||||||
| 
 | 
 | ||||||
|             domainStrategy = _config.RoutingBasicItem.DomainStrategy; |             DomainStrategy = _config.RoutingBasicItem.DomainStrategy; | ||||||
|             domainMatcher = _config.RoutingBasicItem.DomainMatcher; |             DomainMatcher = _config.RoutingBasicItem.DomainMatcher; | ||||||
|             domainStrategy4Singbox = _config.RoutingBasicItem.DomainStrategy4Singbox; |             DomainStrategy4Singbox = _config.RoutingBasicItem.DomainStrategy4Singbox; | ||||||
| 
 | 
 | ||||||
|             await ConfigHandler.InitBuiltinRouting(_config); |             await ConfigHandler.InitBuiltinRouting(_config); | ||||||
|             await RefreshRoutingItems(); |             await RefreshRoutingItems(); | ||||||
|  | @ -91,11 +91,7 @@ namespace ServiceLib.ViewModels | ||||||
|             var routings = await AppHandler.Instance.RoutingItems(); |             var routings = await AppHandler.Instance.RoutingItems(); | ||||||
|             foreach (var item in routings) |             foreach (var item in routings) | ||||||
|             { |             { | ||||||
|                 bool def = false; |                 var def = item.Id == _config.RoutingBasicItem.RoutingIndexId; | ||||||
|                 if (item.Id == _config.RoutingBasicItem.RoutingIndexId) |  | ||||||
|                 { |  | ||||||
|                     def = true; |  | ||||||
|                 } |  | ||||||
| 
 | 
 | ||||||
|                 var it = new RoutingItemModel() |                 var it = new RoutingItemModel() | ||||||
|                 { |                 { | ||||||
|  | @ -114,9 +110,9 @@ namespace ServiceLib.ViewModels | ||||||
| 
 | 
 | ||||||
|         private async Task SaveRoutingAsync() |         private async Task SaveRoutingAsync() | ||||||
|         { |         { | ||||||
|             _config.RoutingBasicItem.DomainStrategy = domainStrategy; |             _config.RoutingBasicItem.DomainStrategy = DomainStrategy; | ||||||
|             _config.RoutingBasicItem.DomainMatcher = domainMatcher; |             _config.RoutingBasicItem.DomainMatcher = DomainMatcher; | ||||||
|             _config.RoutingBasicItem.DomainStrategy4Singbox = domainStrategy4Singbox; |             _config.RoutingBasicItem.DomainStrategy4Singbox = DomainStrategy4Singbox; | ||||||
| 
 | 
 | ||||||
|             if (await ConfigHandler.SaveConfig(_config) == 0) |             if (await ConfigHandler.SaveConfig(_config) == 0) | ||||||
|             { |             { | ||||||
|  |  | ||||||
|  | @ -301,7 +301,7 @@ namespace ServiceLib.ViewModels | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             if (Utils.IsNullOrEmpty(SelectedServer.ID)) |             if (SelectedServer.ID.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ namespace ServiceLib.ViewModels | ||||||
|         private async Task SaveSubAsync() |         private async Task SaveSubAsync() | ||||||
|         { |         { | ||||||
|             var remarks = SelectedSource.Remarks; |             var remarks = SelectedSource.Remarks; | ||||||
|             if (Utils.IsNullOrEmpty(remarks)) |             if (remarks.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 NoticeHandler.Instance.Enqueue(ResUI.PleaseFillRemarks); |                 NoticeHandler.Instance.Enqueue(ResUI.PleaseFillRemarks); | ||||||
|                 return; |                 return; | ||||||
|  |  | ||||||
|  | @ -23,7 +23,7 @@ public partial class App : Application | ||||||
| 
 | 
 | ||||||
|         var ViewModel = new StatusBarViewModel(null); |         var ViewModel = new StatusBarViewModel(null); | ||||||
|         Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(StatusBarViewModel)); |         Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(StatusBarViewModel)); | ||||||
|         this.DataContext = ViewModel; |         DataContext = ViewModel; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public override void OnFrameworkInitializationCompleted() |     public override void OnFrameworkInitializationCompleted() | ||||||
|  | @ -65,16 +65,20 @@ public partial class App : Application | ||||||
|                 var clipboardData = await AvaUtils.GetClipboardData(desktop.MainWindow); |                 var clipboardData = await AvaUtils.GetClipboardData(desktop.MainWindow); | ||||||
|                 var service = Locator.Current.GetService<MainWindowViewModel>(); |                 var service = Locator.Current.GetService<MainWindowViewModel>(); | ||||||
|                 if (service != null) |                 if (service != null) | ||||||
|  |                 { | ||||||
|                     _ = service.AddServerViaClipboardAsync(clipboardData); |                     _ = service.AddServerViaClipboardAsync(clipboardData); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     private async void MenuExit_Click(object? sender, EventArgs e) |     private async void MenuExit_Click(object? sender, EventArgs e) | ||||||
|     { |     { | ||||||
|         var service = Locator.Current.GetService<MainWindowViewModel>(); |         var service = Locator.Current.GetService<MainWindowViewModel>(); | ||||||
|         if (service != null) |         if (service != null) | ||||||
|  |         { | ||||||
|             await service.MyAppExitAsync(true); |             await service.MyAppExitAsync(true); | ||||||
|  |         } | ||||||
|         service?.Shutdown(true); |         service?.Shutdown(true); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -19,7 +19,9 @@ namespace v2rayN.Desktop.Common | ||||||
|         { |         { | ||||||
|             var sp = GetStorageProvider(owner); |             var sp = GetStorageProvider(owner); | ||||||
|             if (sp is null) |             if (sp is null) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             // Start async operation to open the dialog. |             // Start async operation to open the dialog. | ||||||
|             var files = await sp.OpenFilePickerAsync(new FilePickerOpenOptions |             var files = await sp.OpenFilePickerAsync(new FilePickerOpenOptions | ||||||
|  | @ -35,7 +37,9 @@ namespace v2rayN.Desktop.Common | ||||||
|         { |         { | ||||||
|             var sp = GetStorageProvider(owner); |             var sp = GetStorageProvider(owner); | ||||||
|             if (sp is null) |             if (sp is null) | ||||||
|  |             { | ||||||
|                 return null; |                 return null; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             // Start async operation to open the dialog. |             // Start async operation to open the dialog. | ||||||
|             var files = await sp.SaveFilePickerAsync(new FilePickerSaveOptions |             var files = await sp.SaveFilePickerAsync(new FilePickerSaveOptions | ||||||
|  |  | ||||||
|  | @ -27,7 +27,9 @@ public class AutoCompleteBox : Avalonia.Controls.AutoCompleteBox | ||||||
|     { |     { | ||||||
|         base.OnGotFocus(e); |         base.OnGotFocus(e); | ||||||
|         if (IsDropDownOpen) |         if (IsDropDownOpen) | ||||||
|  |         { | ||||||
|             return; |             return; | ||||||
|  |         } | ||||||
|         SetCurrentValue(IsDropDownOpenProperty, true); |         SetCurrentValue(IsDropDownOpenProperty, true); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,14 +8,14 @@ namespace v2rayN.Desktop.Converters | ||||||
|     { |     { | ||||||
|         public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) |         public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) | ||||||
|         { |         { | ||||||
|             int.TryParse(value?.ToString(), out var delay); |             _ = int.TryParse(value?.ToString(), out var delay); | ||||||
| 
 | 
 | ||||||
|             if (delay <= 0) |             return delay switch | ||||||
|                 return new SolidColorBrush(Colors.Red); |             { | ||||||
|             if (delay <= 500) |                 <= 0 => new SolidColorBrush(Colors.Red), | ||||||
|                 return new SolidColorBrush(Colors.Green); |                 <= 500 => new SolidColorBrush(Colors.Green), | ||||||
|             else |                 _ => new SolidColorBrush(Colors.IndianRed) | ||||||
|                 return new SolidColorBrush(Colors.IndianRed); |             }; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) |         public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) | ||||||
|  |  | ||||||
|  | @ -25,8 +25,8 @@ internal class Program | ||||||
|         if (Utils.IsWindows()) |         if (Utils.IsWindows()) | ||||||
|         { |         { | ||||||
|             var exePathKey = Utils.GetMd5(Utils.GetExePath()); |             var exePathKey = Utils.GetMd5(Utils.GetExePath()); | ||||||
|             var rebootas = (Args ?? Array.Empty<string>()).Any(t => t == Global.RebootAs); |             var rebootas = (Args ?? []).Any(t => t == Global.RebootAs); | ||||||
|             ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, exePathKey, out bool bCreatedNew); |             ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, exePathKey, out var bCreatedNew); | ||||||
|             if (!rebootas && !bCreatedNew) |             if (!rebootas && !bCreatedNew) | ||||||
|             { |             { | ||||||
|                 ProgramStarted.Set(); |                 ProgramStarted.Set(); | ||||||
|  |  | ||||||
|  | @ -69,7 +69,7 @@ namespace v2rayN.Desktop.ViewModels | ||||||
|                     y => y != null && !y.IsNullOrEmpty()) |                     y => y != null && !y.IsNullOrEmpty()) | ||||||
|                 .Subscribe(c => |                 .Subscribe(c => | ||||||
|                 { |                 { | ||||||
|                     if (Utils.IsNotEmpty(CurrentLanguage) && _config.UiItem.CurrentLanguage != CurrentLanguage) |                     if (CurrentLanguage.IsNotEmpty() && _config.UiItem.CurrentLanguage != CurrentLanguage) | ||||||
|                     { |                     { | ||||||
|                         _config.UiItem.CurrentLanguage = CurrentLanguage; |                         _config.UiItem.CurrentLanguage = CurrentLanguage; | ||||||
|                         Thread.CurrentThread.CurrentUICulture = new(CurrentLanguage); |                         Thread.CurrentThread.CurrentUICulture = new(CurrentLanguage); | ||||||
|  |  | ||||||
|  | @ -272,7 +272,7 @@ namespace v2rayN.Desktop.Views | ||||||
|             cmbHeaderType.Items.Clear(); |             cmbHeaderType.Items.Clear(); | ||||||
| 
 | 
 | ||||||
|             var network = cmbNetwork.SelectedItem.ToString(); |             var network = cmbNetwork.SelectedItem.ToString(); | ||||||
|             if (Utils.IsNullOrEmpty(network)) |             if (network.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 cmbHeaderType.Items.Add(Global.None); |                 cmbHeaderType.Items.Add(Global.None); | ||||||
|                 return; |                 return; | ||||||
|  | @ -313,7 +313,7 @@ namespace v2rayN.Desktop.Views | ||||||
|         private void SetTips() |         private void SetTips() | ||||||
|         { |         { | ||||||
|             var network = cmbNetwork.SelectedItem.ToString(); |             var network = cmbNetwork.SelectedItem.ToString(); | ||||||
|             if (Utils.IsNullOrEmpty(network)) |             if (network.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 network = Global.DefaultNetwork; |                 network = Global.DefaultNetwork; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -36,15 +36,15 @@ namespace v2rayN.Desktop.Views | ||||||
| 
 | 
 | ||||||
|             this.WhenActivated(disposables => |             this.WhenActivated(disposables => | ||||||
|             { |             { | ||||||
|                 this.Bind(ViewModel, vm => vm.useSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.UseSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(disposables); | ||||||
|                 this.Bind(ViewModel, vm => vm.domainStrategy4Freedom, v => v.cmbdomainStrategy4Freedom.SelectedValue).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom, v => v.cmbdomainStrategy4Freedom.SelectedValue).DisposeWith(disposables); | ||||||
|                 this.Bind(ViewModel, vm => vm.domainDNSAddress, v => v.cmbdomainDNSAddress.SelectedValue).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.DomainDNSAddress, v => v.cmbdomainDNSAddress.SelectedValue).DisposeWith(disposables); | ||||||
|                 this.Bind(ViewModel, vm => vm.normalDNS, v => v.txtnormalDNS.Text).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.NormalDNS, v => v.txtnormalDNS.Text).DisposeWith(disposables); | ||||||
| 
 | 
 | ||||||
|                 this.Bind(ViewModel, vm => vm.domainStrategy4Freedom2, v => v.cmbdomainStrategy4Out.SelectedValue).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom2, v => v.cmbdomainStrategy4Out.SelectedValue).DisposeWith(disposables); | ||||||
|                 this.Bind(ViewModel, vm => vm.domainDNSAddress2, v => v.cmbdomainDNSAddress2.SelectedValue).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.DomainDNSAddress2, v => v.cmbdomainDNSAddress2.SelectedValue).DisposeWith(disposables); | ||||||
|                 this.Bind(ViewModel, vm => vm.normalDNS2, v => v.txtnormalDNS2.Text).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.NormalDNS2, v => v.txtnormalDNS2.Text).DisposeWith(disposables); | ||||||
|                 this.Bind(ViewModel, vm => vm.tunDNS2, v => v.txttunDNS2.Text).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.TunDNS2, v => v.txttunDNS2.Text).DisposeWith(disposables); | ||||||
| 
 | 
 | ||||||
|                 this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables); |                 this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables); | ||||||
|                 this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCmd, v => v.btnImportDefConfig4V2ray).DisposeWith(disposables); |                 this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCmd, v => v.btnImportDefConfig4V2ray).DisposeWith(disposables); | ||||||
|  |  | ||||||
|  | @ -461,8 +461,8 @@ namespace v2rayN.Desktop.Views | ||||||
| 
 | 
 | ||||||
|         private void StorageUI(string? n = null) |         private void StorageUI(string? n = null) | ||||||
|         { |         { | ||||||
|             _config.UiItem.MainWidth = Utils.ToInt(this.Width); |             _config.UiItem.MainWidth = this.Width; | ||||||
|             _config.UiItem.MainHeight = Utils.ToInt(this.Height); |             _config.UiItem.MainHeight = this.Height; | ||||||
| 
 | 
 | ||||||
|             if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Horizontal) |             if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Horizontal) | ||||||
|             { |             { | ||||||
|  |  | ||||||
|  | @ -196,7 +196,7 @@ namespace v2rayN.Desktop.Views | ||||||
| 
 | 
 | ||||||
|         public async Task ShareServer(string url) |         public async Task ShareServer(string url) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(url)) |             if (url.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  | @ -404,7 +404,7 @@ namespace v2rayN.Desktop.Views | ||||||
|                 lvColumnItem.Add(new() |                 lvColumnItem.Add(new() | ||||||
|                 { |                 { | ||||||
|                     Name = (string)item2.Tag, |                     Name = (string)item2.Tag, | ||||||
|                     Width = item2.IsVisible == true ? Utils.ToInt(item2.ActualWidth) : -1, |                     Width = (int)(item2.IsVisible == true ? item2.ActualWidth : -1), | ||||||
|                     Index = item2.DisplayIndex |                     Index = item2.DisplayIndex | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -44,9 +44,9 @@ namespace v2rayN.Desktop.Views | ||||||
|                 this.OneWayBind(ViewModel, vm => vm.RoutingItems, v => v.lstRoutings.ItemsSource).DisposeWith(disposables); |                 this.OneWayBind(ViewModel, vm => vm.RoutingItems, v => v.lstRoutings.ItemsSource).DisposeWith(disposables); | ||||||
|                 this.Bind(ViewModel, vm => vm.SelectedSource, v => v.lstRoutings.SelectedItem).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.SelectedSource, v => v.lstRoutings.SelectedItem).DisposeWith(disposables); | ||||||
| 
 | 
 | ||||||
|                 this.Bind(ViewModel, vm => vm.domainStrategy, v => v.cmbdomainStrategy.SelectedValue).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.DomainStrategy, v => v.cmbdomainStrategy.SelectedValue).DisposeWith(disposables); | ||||||
|                 this.Bind(ViewModel, vm => vm.domainMatcher, v => v.cmbdomainMatcher.SelectedValue).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.DomainMatcher, v => v.cmbdomainMatcher.SelectedValue).DisposeWith(disposables); | ||||||
|                 this.Bind(ViewModel, vm => vm.domainStrategy4Singbox, v => v.cmbdomainStrategy4Singbox.SelectedValue).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.DomainStrategy4Singbox, v => v.cmbdomainStrategy4Singbox.SelectedValue).DisposeWith(disposables); | ||||||
| 
 | 
 | ||||||
|                 this.BindCommand(ViewModel, vm => vm.RoutingAdvancedAddCmd, v => v.menuRoutingAdvancedAdd).DisposeWith(disposables); |                 this.BindCommand(ViewModel, vm => vm.RoutingAdvancedAddCmd, v => v.menuRoutingAdvancedAdd).DisposeWith(disposables); | ||||||
|                 this.BindCommand(ViewModel, vm => vm.RoutingAdvancedAddCmd, v => v.menuRoutingAdvancedAdd2).DisposeWith(disposables); |                 this.BindCommand(ViewModel, vm => vm.RoutingAdvancedAddCmd, v => v.menuRoutingAdvancedAdd2).DisposeWith(disposables); | ||||||
|  |  | ||||||
|  | @ -69,7 +69,7 @@ namespace v2rayN.Desktop.Views | ||||||
| 
 | 
 | ||||||
|         private async Task ShareSub(string url) |         private async Task ShareSub(string url) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(url)) |             if (url.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ namespace v2rayN.Converters | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 var fontFamily = AppHandler.Instance.Config.UiItem.CurrentFontFamily; |                 var fontFamily = AppHandler.Instance.Config.UiItem.CurrentFontFamily; | ||||||
|                 if (Utils.IsNotEmpty(fontFamily)) |                 if (fontFamily.IsNotEmpty()) | ||||||
|                 { |                 { | ||||||
|                     var fontPath = Utils.GetFontsPath(); |                     var fontPath = Utils.GetFontsPath(); | ||||||
|                     MyFont = new FontFamily(new Uri(@$"file:///{fontPath}\"), $"./#{fontFamily}"); |                     MyFont = new FontFamily(new Uri(@$"file:///{fontPath}\"), $"./#{fontFamily}"); | ||||||
|  |  | ||||||
|  | @ -56,7 +56,7 @@ namespace v2rayN.Handler | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 var item = await ConfigHandler.GetDefaultRouting(config); |                 var item = await ConfigHandler.GetDefaultRouting(config); | ||||||
|                 if (item == null || Utils.IsNullOrEmpty(item.CustomIcon) || !File.Exists(item.CustomIcon)) |                 if (item == null || item.CustomIcon.IsNullOrEmpty() || !File.Exists(item.CustomIcon)) | ||||||
|                 { |                 { | ||||||
|                     return null; |                     return null; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  | @ -116,7 +116,7 @@ namespace v2rayN.ViewModels | ||||||
|              y => y != null && !y.IsNullOrEmpty()) |              y => y != null && !y.IsNullOrEmpty()) | ||||||
|                 .Subscribe(c => |                 .Subscribe(c => | ||||||
|                 { |                 { | ||||||
|                     if (Utils.IsNotEmpty(CurrentLanguage) && _config.UiItem.CurrentLanguage != CurrentLanguage) |                     if (CurrentLanguage.IsNotEmpty() && _config.UiItem.CurrentLanguage != CurrentLanguage) | ||||||
|                     { |                     { | ||||||
|                         _config.UiItem.CurrentLanguage = CurrentLanguage; |                         _config.UiItem.CurrentLanguage = CurrentLanguage; | ||||||
|                         Thread.CurrentThread.CurrentUICulture = new(CurrentLanguage); |                         Thread.CurrentThread.CurrentUICulture = new(CurrentLanguage); | ||||||
|  |  | ||||||
|  | @ -267,7 +267,7 @@ namespace v2rayN.Views | ||||||
|             cmbHeaderType.Items.Clear(); |             cmbHeaderType.Items.Clear(); | ||||||
| 
 | 
 | ||||||
|             var network = cmbNetwork.SelectedItem.ToString(); |             var network = cmbNetwork.SelectedItem.ToString(); | ||||||
|             if (Utils.IsNullOrEmpty(network)) |             if (network.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 cmbHeaderType.Items.Add(Global.None); |                 cmbHeaderType.Items.Add(Global.None); | ||||||
|                 return; |                 return; | ||||||
|  | @ -308,7 +308,7 @@ namespace v2rayN.Views | ||||||
|         private void SetTips() |         private void SetTips() | ||||||
|         { |         { | ||||||
|             var network = cmbNetwork.SelectedItem.ToString(); |             var network = cmbNetwork.SelectedItem.ToString(); | ||||||
|             if (Utils.IsNullOrEmpty(network)) |             if (network.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 network = Global.DefaultNetwork; |                 network = Global.DefaultNetwork; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -36,15 +36,15 @@ namespace v2rayN.Views | ||||||
| 
 | 
 | ||||||
|             this.WhenActivated(disposables => |             this.WhenActivated(disposables => | ||||||
|             { |             { | ||||||
|                 this.Bind(ViewModel, vm => vm.useSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.UseSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(disposables); | ||||||
|                 this.Bind(ViewModel, vm => vm.domainStrategy4Freedom, v => v.cmbdomainStrategy4Freedom.Text).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom, v => v.cmbdomainStrategy4Freedom.Text).DisposeWith(disposables); | ||||||
|                 this.Bind(ViewModel, vm => vm.domainDNSAddress, v => v.cmbdomainDNSAddress.Text).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.DomainDNSAddress, v => v.cmbdomainDNSAddress.Text).DisposeWith(disposables); | ||||||
|                 this.Bind(ViewModel, vm => vm.normalDNS, v => v.txtnormalDNS.Text).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.NormalDNS, v => v.txtnormalDNS.Text).DisposeWith(disposables); | ||||||
| 
 | 
 | ||||||
|                 this.Bind(ViewModel, vm => vm.domainStrategy4Freedom2, v => v.cmbdomainStrategy4Out.Text).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom2, v => v.cmbdomainStrategy4Out.Text).DisposeWith(disposables); | ||||||
|                 this.Bind(ViewModel, vm => vm.domainDNSAddress2, v => v.cmbdomainDNSAddress2.Text).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.DomainDNSAddress2, v => v.cmbdomainDNSAddress2.Text).DisposeWith(disposables); | ||||||
|                 this.Bind(ViewModel, vm => vm.normalDNS2, v => v.txtnormalDNS2.Text).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.NormalDNS2, v => v.txtnormalDNS2.Text).DisposeWith(disposables); | ||||||
|                 this.Bind(ViewModel, vm => vm.tunDNS2, v => v.txttunDNS2.Text).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.TunDNS2, v => v.txttunDNS2.Text).DisposeWith(disposables); | ||||||
| 
 | 
 | ||||||
|                 this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables); |                 this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables); | ||||||
|                 this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCmd, v => v.btnImportDefConfig4V2ray).DisposeWith(disposables); |                 this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCmd, v => v.btnImportDefConfig4V2ray).DisposeWith(disposables); | ||||||
|  |  | ||||||
|  | @ -414,8 +414,8 @@ namespace v2rayN.Views | ||||||
| 
 | 
 | ||||||
|         private void StorageUI(string? n = null) |         private void StorageUI(string? n = null) | ||||||
|         { |         { | ||||||
|             _config.UiItem.MainWidth = Utils.ToInt(this.Width); |             _config.UiItem.MainWidth = this.Width; | ||||||
|             _config.UiItem.MainHeight = Utils.ToInt(this.Height); |             _config.UiItem.MainHeight = this.Height; | ||||||
| 
 | 
 | ||||||
|             if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Horizontal) |             if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Horizontal) | ||||||
|             { |             { | ||||||
|  |  | ||||||
|  | @ -234,10 +234,10 @@ namespace v2rayN.Views | ||||||
|                             //    continue; |                             //    continue; | ||||||
|                             //} |                             //} | ||||||
|                             var fontFamily = glyph.Win32FamilyNames[new CultureInfo(culture)]; |                             var fontFamily = glyph.Win32FamilyNames[new CultureInfo(culture)]; | ||||||
|                             if (Utils.IsNullOrEmpty(fontFamily)) |                             if (fontFamily.IsNullOrEmpty()) | ||||||
|                             { |                             { | ||||||
|                                 fontFamily = glyph.Win32FamilyNames[new CultureInfo(culture2)]; |                                 fontFamily = glyph.Win32FamilyNames[new CultureInfo(culture2)]; | ||||||
|                                 if (Utils.IsNullOrEmpty(fontFamily)) |                                 if (fontFamily.IsNullOrEmpty()) | ||||||
|                                 { |                                 { | ||||||
|                                     continue; |                                     continue; | ||||||
|                                 } |                                 } | ||||||
|  |  | ||||||
|  | @ -375,7 +375,7 @@ namespace v2rayN.Views | ||||||
|                 lvColumnItem.Add(new() |                 lvColumnItem.Add(new() | ||||||
|                 { |                 { | ||||||
|                     Name = item2.ExName, |                     Name = item2.ExName, | ||||||
|                     Width = item2.Visibility == Visibility.Visible ? Utils.ToInt(item2.ActualWidth) : -1, |                     Width = (int)(item2.Visibility == Visibility.Visible ? item2.ActualWidth : -1), | ||||||
|                     Index = item2.DisplayIndex |                     Index = item2.DisplayIndex | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -39,9 +39,9 @@ namespace v2rayN.Views | ||||||
|                 this.OneWayBind(ViewModel, vm => vm.RoutingItems, v => v.lstRoutings.ItemsSource).DisposeWith(disposables); |                 this.OneWayBind(ViewModel, vm => vm.RoutingItems, v => v.lstRoutings.ItemsSource).DisposeWith(disposables); | ||||||
|                 this.Bind(ViewModel, vm => vm.SelectedSource, v => v.lstRoutings.SelectedItem).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.SelectedSource, v => v.lstRoutings.SelectedItem).DisposeWith(disposables); | ||||||
| 
 | 
 | ||||||
|                 this.Bind(ViewModel, vm => vm.domainStrategy, v => v.cmbdomainStrategy.Text).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.DomainStrategy, v => v.cmbdomainStrategy.Text).DisposeWith(disposables); | ||||||
|                 this.Bind(ViewModel, vm => vm.domainMatcher, v => v.cmbdomainMatcher.Text).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.DomainMatcher, v => v.cmbdomainMatcher.Text).DisposeWith(disposables); | ||||||
|                 this.Bind(ViewModel, vm => vm.domainStrategy4Singbox, v => v.cmbdomainStrategy4Singbox.Text).DisposeWith(disposables); |                 this.Bind(ViewModel, vm => vm.DomainStrategy4Singbox, v => v.cmbdomainStrategy4Singbox.Text).DisposeWith(disposables); | ||||||
| 
 | 
 | ||||||
|                 this.BindCommand(ViewModel, vm => vm.RoutingAdvancedAddCmd, v => v.menuRoutingAdvancedAdd).DisposeWith(disposables); |                 this.BindCommand(ViewModel, vm => vm.RoutingAdvancedAddCmd, v => v.menuRoutingAdvancedAdd).DisposeWith(disposables); | ||||||
|                 this.BindCommand(ViewModel, vm => vm.RoutingAdvancedAddCmd, v => v.menuRoutingAdvancedAdd2).DisposeWith(disposables); |                 this.BindCommand(ViewModel, vm => vm.RoutingAdvancedAddCmd, v => v.menuRoutingAdvancedAdd2).DisposeWith(disposables); | ||||||
|  |  | ||||||
|  | @ -65,7 +65,7 @@ namespace v2rayN.Views | ||||||
| 
 | 
 | ||||||
|         private async void ShareSub(string url) |         private async void ShareSub(string url) | ||||||
|         { |         { | ||||||
|             if (Utils.IsNullOrEmpty(url)) |             if (url.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue