diff --git a/v2rayN/ServiceLib/Common/Utils.cs b/v2rayN/ServiceLib/Common/Utils.cs
index fc273dbe..c482d149 100644
--- a/v2rayN/ServiceLib/Common/Utils.cs
+++ b/v2rayN/ServiceLib/Common/Utils.cs
@@ -479,6 +479,12 @@ namespace ServiceLib.Common
#region 杂项
+ public static bool UpgradeAppExists(out string fileName)
+ {
+ fileName = Path.Combine(Utils.StartupPath(), GetExeName("AmazTool"));
+ return File.Exists(fileName);
+ }
+
///
/// 取得版本
///
diff --git a/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs b/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs
index fc1bcda6..8f7c319f 100644
--- a/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs
+++ b/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs
@@ -201,5 +201,14 @@ namespace ServiceLib.Handler.Fmt
File.WriteAllText(fileName, strData);
return fileName;
}
+ protected static string ToUri(EConfigType eConfigType, string address, object port, string userInfo, Dictionary? dicQuery, string? remark)
+ {
+ var query = dicQuery != null
+ ? ("?" + string.Join("&", dicQuery.Select(x => x.Key + "=" + x.Value).ToArray()))
+ : string.Empty;
+
+ var url = $"{Utils.UrlEncode(userInfo)}@{GetIpv6(address)}:{port}";
+ return $"{Global.ProtocolShares[eConfigType]}{url}{query}{remark}";
+ }
}
}
\ No newline at end of file
diff --git a/v2rayN/ServiceLib/Handler/Fmt/Hysteria2Fmt.cs b/v2rayN/ServiceLib/Handler/Fmt/Hysteria2Fmt.cs
index 5f877858..146d2d74 100644
--- a/v2rayN/ServiceLib/Handler/Fmt/Hysteria2Fmt.cs
+++ b/v2rayN/ServiceLib/Handler/Fmt/Hysteria2Fmt.cs
@@ -51,14 +51,7 @@
}
dicQuery.Add("insecure", item.allowInsecure.ToLower() == "true" ? "1" : "0");
- string query = "?" + string.Join("&", dicQuery.Select(x => x.Key + "=" + x.Value).ToArray());
-
- url = string.Format("{0}@{1}:{2}",
- item.id,
- GetIpv6(item.address),
- item.port);
- url = $"{Global.ProtocolShares[EConfigType.Hysteria2]}{url}/{query}{remark}";
- return url;
+ return ToUri(EConfigType.Hysteria2, item.address, item.port, item.id, dicQuery, remark);
}
public static ProfileItem? ResolveFull(string strData, string? subRemarks)
diff --git a/v2rayN/ServiceLib/Handler/Fmt/ShadowsocksFmt.cs b/v2rayN/ServiceLib/Handler/Fmt/ShadowsocksFmt.cs
index 93c387f6..57f8e1bc 100644
--- a/v2rayN/ServiceLib/Handler/Fmt/ShadowsocksFmt.cs
+++ b/v2rayN/ServiceLib/Handler/Fmt/ShadowsocksFmt.cs
@@ -42,9 +42,7 @@ namespace ServiceLib.Handler.Fmt
//url = Utile.Base64Encode(url);
//new Sip002
var pw = Utils.Base64Encode($"{item.security}:{item.id}");
- url = $"{pw}@{GetIpv6(item.address)}:{item.port}";
- url = $"{Global.ProtocolShares[EConfigType.Shadowsocks]}{url}{remark}";
- return url;
+ return ToUri(EConfigType.Shadowsocks, item.address, item.port, pw, null, remark);
}
private static readonly Regex UrlFinder = new(@"ss://(?[A-Za-z0-9+-/=_]+)(?:#(?\S+))?", RegexOptions.IgnoreCase | RegexOptions.Compiled);
@@ -98,7 +96,7 @@ namespace ServiceLib.Handler.Fmt
address = parsedUrl.IdnHost,
port = parsedUrl.Port,
};
- string rawUserInfo = parsedUrl.GetComponents(UriComponents.UserInfo, UriFormat.UriEscaped);
+ var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo);
//2022-blake3
if (rawUserInfo.Contains(':'))
{
diff --git a/v2rayN/ServiceLib/Handler/Fmt/SocksFmt.cs b/v2rayN/ServiceLib/Handler/Fmt/SocksFmt.cs
index 0f0df5fb..cbf24fcc 100644
--- a/v2rayN/ServiceLib/Handler/Fmt/SocksFmt.cs
+++ b/v2rayN/ServiceLib/Handler/Fmt/SocksFmt.cs
@@ -40,9 +40,7 @@
//url = Utile.Base64Encode(url);
//new
var pw = Utils.Base64Encode($"{item.security}:{item.id}");
- url = $"{pw}@{GetIpv6(item.address)}:{item.port}";
- url = $"{Global.ProtocolShares[EConfigType.SOCKS]}{url}{remark}";
- return url;
+ return ToUri(EConfigType.SOCKS, item.address, item.port, pw, null, remark);
}
private static ProfileItem? ResolveSocks(string result)
@@ -112,9 +110,9 @@
};
// parse base64 UserInfo
- string rawUserInfo = parsedUrl.GetComponents(UriComponents.UserInfo, UriFormat.Unescaped);
- string userInfo = Utils.Base64Decode(rawUserInfo);
- string[] userInfoParts = userInfo.Split(new[] { ':' }, 2);
+ var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo);
+ var userInfo = Utils.Base64Decode(rawUserInfo);
+ var userInfoParts = userInfo.Split(new[] { ':' }, 2);
if (userInfoParts.Length == 2)
{
item.security = userInfoParts[0];
diff --git a/v2rayN/ServiceLib/Handler/Fmt/TrojanFmt.cs b/v2rayN/ServiceLib/Handler/Fmt/TrojanFmt.cs
index 51f08524..129ba9f3 100644
--- a/v2rayN/ServiceLib/Handler/Fmt/TrojanFmt.cs
+++ b/v2rayN/ServiceLib/Handler/Fmt/TrojanFmt.cs
@@ -36,14 +36,8 @@
}
var dicQuery = new Dictionary();
GetStdTransport(item, null, ref dicQuery);
- string query = "?" + string.Join("&", dicQuery.Select(x => x.Key + "=" + x.Value).ToArray());
- url = string.Format("{0}@{1}:{2}",
- item.id,
- GetIpv6(item.address),
- item.port);
- url = $"{Global.ProtocolShares[EConfigType.Trojan]}{url}{query}{remark}";
- return url;
+ return ToUri(EConfigType.Trojan, item.address, item.port, item.id, dicQuery, remark);
}
}
}
\ No newline at end of file
diff --git a/v2rayN/ServiceLib/Handler/Fmt/TuicFmt.cs b/v2rayN/ServiceLib/Handler/Fmt/TuicFmt.cs
index bdfdce91..e8da3ada 100644
--- a/v2rayN/ServiceLib/Handler/Fmt/TuicFmt.cs
+++ b/v2rayN/ServiceLib/Handler/Fmt/TuicFmt.cs
@@ -16,7 +16,8 @@
item.address = url.IdnHost;
item.port = url.Port;
item.remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
- var userInfoParts = url.UserInfo.Split(new[] { ':' }, 2);
+ var rawUserInfo = Utils.UrlDecode(url.UserInfo);
+ var userInfoParts = rawUserInfo.Split(new[] { ':' }, 2);
if (userInfoParts.Length == 2)
{
item.id = userInfoParts[0];
@@ -51,14 +52,7 @@
}
dicQuery.Add("congestion_control", item.headerType);
- string query = "?" + string.Join("&", dicQuery.Select(x => x.Key + "=" + x.Value).ToArray());
-
- url = string.Format("{0}@{1}:{2}",
- $"{item.id}:{item.security}",
- GetIpv6(item.address),
- item.port);
- url = $"{Global.ProtocolShares[EConfigType.TUIC]}{url}{query}{remark}";
- return url;
+ return ToUri(EConfigType.TUIC, item.address, item.port, $"{item.id}:{item.security}", dicQuery, remark);
}
}
}
\ No newline at end of file
diff --git a/v2rayN/ServiceLib/Handler/Fmt/VLESSFmt.cs b/v2rayN/ServiceLib/Handler/Fmt/VLESSFmt.cs
index fdcc34d3..aa26af15 100644
--- a/v2rayN/ServiceLib/Handler/Fmt/VLESSFmt.cs
+++ b/v2rayN/ServiceLib/Handler/Fmt/VLESSFmt.cs
@@ -47,14 +47,8 @@
dicQuery.Add("encryption", Global.None);
}
GetStdTransport(item, Global.None, ref dicQuery);
- string query = "?" + string.Join("&", dicQuery.Select(x => x.Key + "=" + x.Value).ToArray());
- url = string.Format("{0}@{1}:{2}",
- item.id,
- GetIpv6(item.address),
- item.port);
- url = $"{Global.ProtocolShares[EConfigType.VLESS]}{url}{query}{remark}";
- return url;
+ return ToUri(EConfigType.VLESS, item.address, item.port, item.id, dicQuery, remark);
}
}
}
\ No newline at end of file
diff --git a/v2rayN/ServiceLib/Handler/Fmt/WireguardFmt.cs b/v2rayN/ServiceLib/Handler/Fmt/WireguardFmt.cs
index 743a82be..b6c980a0 100644
--- a/v2rayN/ServiceLib/Handler/Fmt/WireguardFmt.cs
+++ b/v2rayN/ServiceLib/Handler/Fmt/WireguardFmt.cs
@@ -56,14 +56,7 @@
{
dicQuery.Add("mtu", Utils.UrlEncode(item.shortId));
}
- string query = "?" + string.Join("&", dicQuery.Select(x => x.Key + "=" + x.Value).ToArray());
-
- url = string.Format("{0}@{1}:{2}",
- Utils.UrlEncode(item.id),
- GetIpv6(item.address),
- item.port);
- url = $"{Global.ProtocolShares[EConfigType.WireGuard]}{url}/{query}{remark}";
- return url;
+ return ToUri(EConfigType.WireGuard, item.address, item.port, item.id, dicQuery, remark);
}
}
}
\ No newline at end of file
diff --git a/v2rayN/ServiceLib/Handler/WebDavHandler.cs b/v2rayN/ServiceLib/Handler/WebDavHandler.cs
index 81386cc2..3eda381c 100644
--- a/v2rayN/ServiceLib/Handler/WebDavHandler.cs
+++ b/v2rayN/ServiceLib/Handler/WebDavHandler.cs
@@ -12,7 +12,7 @@ namespace ServiceLib.Handler
private WebDavClient? _client;
private string? _lastDescription;
private string _webDir = Global.AppName + "_backup";
- private string _webFileName = "backup.zip";
+ private readonly string _webFileName = "backup.zip";
private string _logTitle = "WebDav--";
public WebDavHandler()
@@ -130,7 +130,7 @@ namespace ServiceLib.Handler
try
{
- using var fs = File.OpenRead(fileName);
+ await using var fs = File.OpenRead(fileName);
var result = await _client.PutFile($"{_webDir}/{_webFileName}", fs); // upload a resource
if (result.IsSuccessful)
{
@@ -162,8 +162,9 @@ namespace ServiceLib.Handler
SaveLog(response.Description);
return false;
}
- using var outputFileStream = new FileStream(fileName, FileMode.Create);
- response.Stream.CopyTo(outputFileStream);
+
+ await using var outputFileStream = new FileStream(fileName, FileMode.Create);
+ await response.Stream.CopyToAsync(outputFileStream);
return true;
}
catch (Exception ex)
diff --git a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs
index 90f5a643..15f1d568 100644
--- a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs
+++ b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs
@@ -3707,5 +3707,14 @@ namespace ServiceLib.Resx {
return ResourceManager.GetString("UpdateStandalonePackageTip", resourceCulture);
}
}
+
+ ///
+ /// 查找类似 UpgradeApp does not exist 的本地化字符串。
+ ///
+ public static string UpgradeAppNotExistTip {
+ get {
+ return ResourceManager.GetString("UpgradeAppNotExistTip", resourceCulture);
+ }
+ }
}
}
diff --git a/v2rayN/ServiceLib/Resx/ResUI.resx b/v2rayN/ServiceLib/Resx/ResUI.resx
index c852e7a1..95053d3a 100644
--- a/v2rayN/ServiceLib/Resx/ResUI.resx
+++ b/v2rayN/ServiceLib/Resx/ResUI.resx
@@ -1332,5 +1332,7 @@
Sing-box srs files source (optional)
+
+ UpgradeApp does not exist
\ No newline at end of file
diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx
index e2355650..59cba9c2 100644
--- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx
+++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx
@@ -1327,4 +1327,7 @@
Geo文件来源(可选)
+
+ 升级工具App不存在
+
\ No newline at end of file
diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx
index b85c239d..b53aa888 100644
--- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx
+++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx
@@ -1207,4 +1207,7 @@
Geo文件來源(可選)
+
+ 升级工具App不存在
+
\ No newline at end of file
diff --git a/v2rayN/ServiceLib/ServiceLib.csproj b/v2rayN/ServiceLib/ServiceLib.csproj
index 3a598909..d9b47d73 100644
--- a/v2rayN/ServiceLib/ServiceLib.csproj
+++ b/v2rayN/ServiceLib/ServiceLib.csproj
@@ -4,7 +4,7 @@
net8.0
enable
enable
- 6.60.0
+ 6.10.0
diff --git a/v2rayN/ServiceLib/Services/DownloadService.cs b/v2rayN/ServiceLib/Services/DownloadService.cs
index 887ef88a..0a6c5ec7 100644
--- a/v2rayN/ServiceLib/Services/DownloadService.cs
+++ b/v2rayN/ServiceLib/Services/DownloadService.cs
@@ -100,7 +100,7 @@ namespace ServiceLib.Services
};
HttpClient client = new(webRequestHandler);
- HttpResponseMessage response = await client.GetAsync(url);
+ var response = await client.GetAsync(url);
if (response.StatusCode == HttpStatusCode.Redirect && response.Headers.Location is not null)
{
return response.Headers.Location.ToString();
@@ -253,15 +253,12 @@ namespace ServiceLib.Services
{
try
{
- if (webProxy == null)
- {
- webProxy = GetWebProxy(true);
- }
+ webProxy ??= GetWebProxy(true);
try
{
var config = AppHandler.Instance.Config;
- int responseTime = await GetRealPingTime(config.speedTestItem.speedPingTestUrl, webProxy, 10);
+ var responseTime = await GetRealPingTime(config.speedTestItem.speedPingTestUrl, webProxy, 10);
return responseTime;
}
catch (Exception ex)
@@ -279,7 +276,7 @@ namespace ServiceLib.Services
public async Task GetRealPingTime(string url, IWebProxy? webProxy, int downloadTimeout)
{
- int responseTime = -1;
+ var responseTime = -1;
try
{
using var cts = new CancellationTokenSource();
@@ -290,8 +287,8 @@ namespace ServiceLib.Services
UseProxy = webProxy != null
});
- List oneTime = [];
- for (int i = 0; i < 2; i++)
+ List oneTime = new();
+ for (var i = 0; i < 2; i++)
{
var timer = Stopwatch.StartNew();
await client.GetAsync(url, cts.Token);
diff --git a/v2rayN/ServiceLib/Services/UpdateService.cs b/v2rayN/ServiceLib/Services/UpdateService.cs
index 97ac42c6..f25548ce 100644
--- a/v2rayN/ServiceLib/Services/UpdateService.cs
+++ b/v2rayN/ServiceLib/Services/UpdateService.cs
@@ -423,7 +423,7 @@ namespace ServiceLib.Services
&& File.Exists(Path.Combine(Utils.StartupPath(), "D3DCompiler_47_cor3.dll"))
)
{
- return coreInfo?.DownloadUrlWin64?.Replace("v2rayN.zip", "zz_v2rayN-SelfContained.zip");
+ return coreInfo?.DownloadUrlWin64?.Replace(".zip", "-SelfContained.zip");
}
return RuntimeInformation.ProcessArchitecture switch
diff --git a/v2rayN/ServiceLib/ViewModels/BackupAndRestoreViewModel.cs b/v2rayN/ServiceLib/ViewModels/BackupAndRestoreViewModel.cs
index 3b96c3da..7deececd 100644
--- a/v2rayN/ServiceLib/ViewModels/BackupAndRestoreViewModel.cs
+++ b/v2rayN/ServiceLib/ViewModels/BackupAndRestoreViewModel.cs
@@ -126,11 +126,16 @@ namespace ServiceLib.ViewModels
}
//check
var lstFiles = FileManager.GetFilesFromZip(fileName);
- if (lstFiles is null || !lstFiles.Where(t => t.Contains(_guiConfigs)).Any())
+ if (lstFiles is null || !lstFiles.Any(t => t.Contains(_guiConfigs)))
{
DisplayOperationMsg(ResUI.LocalRestoreInvalidZipTips);
return;
}
+ if (!Utils.UpgradeAppExists(out _))
+ {
+ DisplayOperationMsg(ResUI.UpgradeAppNotExistTip);
+ return;
+ }
//backup first
var fileBackup = Utils.GetBackupPath(BackupFileName);
diff --git a/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs b/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs
index f7800ad8..aac02973 100644
--- a/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs
+++ b/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs
@@ -235,6 +235,11 @@ namespace ServiceLib.ViewModels
{
return;
}
+ if (!Utils.UpgradeAppExists(out _))
+ {
+ UpdateView(_v2rayN, ResUI.UpgradeAppNotExistTip);
+ return;
+ }
Locator.Current.GetService()?.UpgradeApp(fileName);
}
catch (Exception ex)
diff --git a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs
index a691647e..084e0f86 100644
--- a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs
+++ b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs
@@ -280,14 +280,21 @@ namespace ServiceLib.ViewModels
}
}
- public async Task UpgradeApp(string fileName)
+ public async Task UpgradeApp(string arg)
{
+ if (!Utils.UpgradeAppExists(out var fileName))
+ {
+ NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.UpgradeAppNotExistTip);
+ Logging.SaveLog("UpgradeApp does not exist");
+ return;
+ }
+
Process process = new()
{
StartInfo = new ProcessStartInfo
{
- FileName = "AmazTool",
- Arguments = fileName.AppendQuotes(),
+ FileName = fileName,
+ Arguments = arg.AppendQuotes(),
WorkingDirectory = Utils.StartupPath()
}
};