diff --git a/v2rayN/v2rayN/Forms/AddServer3Form.cs b/v2rayN/v2rayN/Forms/AddServer3Form.cs
index 8113a784..d1a4a858 100644
--- a/v2rayN/v2rayN/Forms/AddServer3Form.cs
+++ b/v2rayN/v2rayN/Forms/AddServer3Form.cs
@@ -119,7 +119,7 @@ namespace v2rayN.Forms
{
ClearServer();
- VmessItem vmessItem = V2rayConfigHandler.ImportFromClipboardConfig(Utils.GetClipboardData(), out string msg);
+ VmessItem vmessItem = ShareHandler.ImportFromClipboardConfig(Utils.GetClipboardData(), out string msg);
if (vmessItem == null)
{
UI.ShowWarning(msg);
diff --git a/v2rayN/v2rayN/Forms/AddServer4Form.cs b/v2rayN/v2rayN/Forms/AddServer4Form.cs
index 23ec6aaa..29102347 100644
--- a/v2rayN/v2rayN/Forms/AddServer4Form.cs
+++ b/v2rayN/v2rayN/Forms/AddServer4Form.cs
@@ -108,7 +108,7 @@ namespace v2rayN.Forms
{
ClearServer();
- VmessItem vmessItem = V2rayConfigHandler.ImportFromClipboardConfig(Utils.GetClipboardData(), out string msg);
+ VmessItem vmessItem = ShareHandler.ImportFromClipboardConfig(Utils.GetClipboardData(), out string msg);
if (vmessItem == null)
{
UI.ShowWarning(msg);
diff --git a/v2rayN/v2rayN/Forms/AddServer5Form.cs b/v2rayN/v2rayN/Forms/AddServer5Form.cs
index d426e5c6..32c7e48c 100644
--- a/v2rayN/v2rayN/Forms/AddServer5Form.cs
+++ b/v2rayN/v2rayN/Forms/AddServer5Form.cs
@@ -263,7 +263,7 @@ namespace v2rayN.Forms
{
ClearServer();
- VmessItem vmessItem = V2rayConfigHandler.ImportFromClipboardConfig(Utils.GetClipboardData(), out string msg);
+ VmessItem vmessItem = ShareHandler.ImportFromClipboardConfig(Utils.GetClipboardData(), out string msg);
if (vmessItem == null)
{
UI.ShowWarning(msg);
diff --git a/v2rayN/v2rayN/Forms/AddServerForm.cs b/v2rayN/v2rayN/Forms/AddServerForm.cs
index bd80867b..ab54fd9b 100644
--- a/v2rayN/v2rayN/Forms/AddServerForm.cs
+++ b/v2rayN/v2rayN/Forms/AddServerForm.cs
@@ -268,7 +268,7 @@ namespace v2rayN.Forms
{
ClearServer();
- VmessItem vmessItem = V2rayConfigHandler.ImportFromClipboardConfig(Utils.GetClipboardData(), out string msg);
+ VmessItem vmessItem = ShareHandler.ImportFromClipboardConfig(Utils.GetClipboardData(), out string msg);
if (vmessItem == null)
{
UI.ShowWarning(msg);
diff --git a/v2rayN/v2rayN/Forms/MainForm.cs b/v2rayN/v2rayN/Forms/MainForm.cs
index 96e6819e..67b78ee5 100644
--- a/v2rayN/v2rayN/Forms/MainForm.cs
+++ b/v2rayN/v2rayN/Forms/MainForm.cs
@@ -685,7 +685,7 @@ namespace v2rayN.Forms
StringBuilder sb = new StringBuilder();
foreach (int v in lvSelecteds)
{
- string url = ConfigHandler.GetVmessQRCode(config, v);
+ string url = ShareHandler.GetShareUrl(config, v);
if (Utils.IsNullOrEmpty(url))
{
continue;
@@ -708,7 +708,7 @@ namespace v2rayN.Forms
StringBuilder sb = new StringBuilder();
foreach (int v in lvSelecteds)
{
- string url = ConfigHandler.GetVmessQRCode(config, v);
+ string url = ShareHandler.GetShareUrl(config, v);
if (Utils.IsNullOrEmpty(url))
{
continue;
diff --git a/v2rayN/v2rayN/Forms/QRCodeControl.cs b/v2rayN/v2rayN/Forms/QRCodeControl.cs
index 02d59b48..855db30d 100644
--- a/v2rayN/v2rayN/Forms/QRCodeControl.cs
+++ b/v2rayN/v2rayN/Forms/QRCodeControl.cs
@@ -24,7 +24,7 @@ namespace v2rayN.Forms
{
if (Index >= 0)
{
- string url = ConfigHandler.GetVmessQRCode(config, Index);
+ string url = ShareHandler.GetShareUrl(config, Index);
if (Utils.IsNullOrEmpty(url))
{
picQRCode.Image = null;
diff --git a/v2rayN/v2rayN/Forms/RoutingSettingDetailsForm.Designer.cs b/v2rayN/v2rayN/Forms/RoutingSettingDetailsForm.Designer.cs
index ee40a2d0..43d2de45 100644
--- a/v2rayN/v2rayN/Forms/RoutingSettingDetailsForm.Designer.cs
+++ b/v2rayN/v2rayN/Forms/RoutingSettingDetailsForm.Designer.cs
@@ -31,6 +31,8 @@
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RoutingSettingDetailsForm));
this.panel1 = new System.Windows.Forms.Panel();
this.panel3 = new System.Windows.Forms.Panel();
+ this.clbProtocol = new System.Windows.Forms.CheckedListBox();
+ this.label3 = new System.Windows.Forms.Label();
this.txtPort = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.labRoutingTips = new System.Windows.Forms.Label();
@@ -46,8 +48,6 @@
this.txtIP = new System.Windows.Forms.TextBox();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.txtDomain = new System.Windows.Forms.TextBox();
- this.label3 = new System.Windows.Forms.Label();
- this.clbProtocol = new System.Windows.Forms.CheckedListBox();
this.panel3.SuspendLayout();
this.panel4.SuspendLayout();
this.panel2.SuspendLayout();
@@ -74,6 +74,23 @@
resources.ApplyResources(this.panel3, "panel3");
this.panel3.Name = "panel3";
//
+ // clbProtocol
+ //
+ this.clbProtocol.CheckOnClick = true;
+ resources.ApplyResources(this.clbProtocol, "clbProtocol");
+ this.clbProtocol.FormattingEnabled = true;
+ this.clbProtocol.Items.AddRange(new object[] {
+ resources.GetString("clbProtocol.Items"),
+ resources.GetString("clbProtocol.Items1"),
+ resources.GetString("clbProtocol.Items2")});
+ this.clbProtocol.MultiColumn = true;
+ this.clbProtocol.Name = "clbProtocol";
+ //
+ // label3
+ //
+ resources.ApplyResources(this.label3, "label3");
+ this.label3.Name = "label3";
+ //
// txtPort
//
resources.ApplyResources(this.txtPort, "txtPort");
@@ -169,23 +186,6 @@
resources.ApplyResources(this.txtDomain, "txtDomain");
this.txtDomain.Name = "txtDomain";
//
- // label3
- //
- resources.ApplyResources(this.label3, "label3");
- this.label3.Name = "label3";
- //
- // clbProtocol
- //
- this.clbProtocol.CheckOnClick = true;
- resources.ApplyResources(this.clbProtocol, "clbProtocol");
- this.clbProtocol.FormattingEnabled = true;
- this.clbProtocol.Items.AddRange(new object[] {
- resources.GetString("clbProtocol.Items"),
- resources.GetString("clbProtocol.Items1"),
- resources.GetString("clbProtocol.Items2")});
- this.clbProtocol.MultiColumn = true;
- this.clbProtocol.Name = "clbProtocol";
- //
// RoutingSettingDetailsForm
//
resources.ApplyResources(this, "$this");
diff --git a/v2rayN/v2rayN/Forms/RoutingSettingDetailsForm.cs b/v2rayN/v2rayN/Forms/RoutingSettingDetailsForm.cs
index a0511439..65fe6a8f 100644
--- a/v2rayN/v2rayN/Forms/RoutingSettingDetailsForm.cs
+++ b/v2rayN/v2rayN/Forms/RoutingSettingDetailsForm.cs
@@ -88,6 +88,29 @@ namespace v2rayN.Forms
private void btnOK_Click(object sender, EventArgs e)
{
EndBindingData();
+ var hasRule = false;
+ if (routingItem.domain != null && routingItem.domain.Count > 0)
+ {
+ hasRule = true;
+ }
+ if (routingItem.ip != null && routingItem.ip.Count > 0)
+ {
+ hasRule = true;
+ }
+ if (routingItem.protocol != null && routingItem.protocol.Count > 0)
+ {
+ hasRule = true;
+ }
+ if (!Utils.IsNullOrEmpty(routingItem.port))
+ {
+ hasRule = true;
+ }
+ if (!hasRule)
+ {
+ UI.ShowWarning(string.Format(UIRes.I18N("RoutingRuleDetailRequiredTips"), "Port/Protocol/Domain/IP"));
+ return;
+ }
+
if (ConfigHandler.AddRoutingRule(ref config, routingItem, EditIndex) == 0)
{
this.DialogResult = DialogResult.OK;
diff --git a/v2rayN/v2rayN/Forms/RoutingSettingDetailsForm.resx b/v2rayN/v2rayN/Forms/RoutingSettingDetailsForm.resx
index 0481d1dd..855817b0 100644
--- a/v2rayN/v2rayN/Forms/RoutingSettingDetailsForm.resx
+++ b/v2rayN/v2rayN/Forms/RoutingSettingDetailsForm.resx
@@ -193,7 +193,7 @@
36
- protocol
+ Protocol
label3
@@ -420,54 +420,6 @@
2
-
- btnClose
-
-
- System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- panel4
-
-
- 0
-
-
- btnOK
-
-
- System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- panel4
-
-
- 1
-
-
- Bottom
-
-
- 0, 516
-
-
- 742, 60
-
-
- 10
-
-
- panel4
-
-
- System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- $this
-
-
- 1
-
NoControl
@@ -522,53 +474,44 @@
1
-
- groupBox2
+
+ Bottom
-
- System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ 0, 516
-
- panel2
+
+ 742, 60
-
- 0
+
+ 10
-
- groupBox1
+
+ panel4
-
- System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- panel2
-
-
- 1
-
-
- Fill
-
-
- 0, 121
-
-
- 742, 395
-
-
- 11
-
-
- panel2
-
-
+
System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
$this
-
- 0
+
+ 1
+
+
+ Fill
+
+
+ 3, 17
+
+
+ True
+
+
+ 344, 375
+
+
+ 25
txtIP
@@ -609,32 +552,20 @@
0
-
+
Fill
-
+
3, 17
-
+
True
-
- 344, 375
+
+ 386, 375
-
- 25
-
-
- txtIP
-
-
- System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- groupBox2
-
-
- 0
+
+ 24
txtDomain
@@ -675,31 +606,28 @@
1
-
+
Fill
-
- 3, 17
+
+ 0, 121
-
- True
+
+ 742, 395
-
- 386, 375
+
+ 11
-
- 24
+
+ panel2
-
- txtDomain
+
+ System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
- System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ $this
-
- groupBox1
-
-
+
0
diff --git a/v2rayN/v2rayN/Handler/ConfigHandler.cs b/v2rayN/v2rayN/Handler/ConfigHandler.cs
index cfdd2281..abdd02f5 100644
--- a/v2rayN/v2rayN/Handler/ConfigHandler.cs
+++ b/v2rayN/v2rayN/Handler/ConfigHandler.cs
@@ -339,100 +339,6 @@ namespace v2rayN.Handler
Utils.ToJsonFile(config, Utils.GetPath(configRes));
}
- ///
- /// 取得服务器QRCode配置
- ///
- ///
- ///
- ///
- public static string GetVmessQRCode(Config config, int index)
- {
- try
- {
- string url = string.Empty;
-
- VmessItem vmessItem = config.vmess[index];
- if (vmessItem.configType == (int)EConfigType.Vmess)
- {
- VmessQRCode vmessQRCode = new VmessQRCode
- {
- v = vmessItem.configVersion.ToString(),
- ps = vmessItem.remarks.TrimEx(), //备注也许很长 ;
- add = vmessItem.address,
- port = vmessItem.port.ToString(),
- id = vmessItem.id,
- aid = vmessItem.alterId.ToString(),
- net = vmessItem.network,
- type = vmessItem.headerType,
- host = vmessItem.requestHost,
- path = vmessItem.path,
- tls = vmessItem.streamSecurity
- };
-
- url = Utils.ToJson(vmessQRCode);
- url = Utils.Base64Encode(url);
- url = string.Format("{0}{1}", Global.vmessProtocol, url);
-
- }
- else if (vmessItem.configType == (int)EConfigType.Shadowsocks)
- {
- string remark = string.Empty;
- if (!Utils.IsNullOrEmpty(vmessItem.remarks))
- {
- remark = "#" + WebUtility.UrlEncode(vmessItem.remarks);
- }
- url = string.Format("{0}:{1}@{2}:{3}",
- vmessItem.security,
- vmessItem.id,
- vmessItem.address,
- vmessItem.port);
- url = Utils.Base64Encode(url);
- url = string.Format("{0}{1}{2}", Global.ssProtocol, url, remark);
- }
- else if (vmessItem.configType == (int)EConfigType.Socks)
- {
- string remark = string.Empty;
- if (!Utils.IsNullOrEmpty(vmessItem.remarks))
- {
- remark = "#" + WebUtility.UrlEncode(vmessItem.remarks);
- }
- url = string.Format("{0}:{1}@{2}:{3}",
- vmessItem.security,
- vmessItem.id,
- vmessItem.address,
- vmessItem.port);
- url = Utils.Base64Encode(url);
- url = string.Format("{0}{1}{2}", Global.socksProtocol, url, remark);
- }
- else if (vmessItem.configType == (int)EConfigType.Trojan)
- {
- string remark = string.Empty;
- if (!Utils.IsNullOrEmpty(vmessItem.remarks))
- {
- remark = "#" + WebUtility.UrlEncode(vmessItem.remarks);
- }
- string query = string.Empty;
- if (!Utils.IsNullOrEmpty(vmessItem.requestHost))
- {
- query = string.Format("?sni={0}", vmessItem.requestHost);
- }
- url = string.Format("{0}@{1}:{2}",
- vmessItem.id,
- vmessItem.address,
- vmessItem.port);
- url = string.Format("{0}{1}{2}{3}", Global.trojanProtocol, url, query, remark);
- }
- else
- {
- }
- return url;
- }
- catch
- {
- return "";
- }
- }
-
///
/// 移动服务器
///
@@ -824,7 +730,7 @@ namespace v2rayN.Handler
}
continue;
}
- VmessItem vmessItem = V2rayConfigHandler.ImportFromClipboardConfig(str, out string msg);
+ VmessItem vmessItem = ShareHandler.ImportFromClipboardConfig(str, out string msg);
if (vmessItem == null)
{
continue;
@@ -858,6 +764,13 @@ namespace v2rayN.Handler
countServers++;
}
}
+ else if (vmessItem.configType == (int)EConfigType.VLESS)
+ {
+ if (AddVlessServer(ref config, vmessItem, -1) == 0)
+ {
+ countServers++;
+ }
+ }
}
return countServers;
}
diff --git a/v2rayN/v2rayN/Handler/ShareHandler.cs b/v2rayN/v2rayN/Handler/ShareHandler.cs
new file mode 100644
index 00000000..766f16e0
--- /dev/null
+++ b/v2rayN/v2rayN/Handler/ShareHandler.cs
@@ -0,0 +1,683 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using System.Web;
+using v2rayN.Base;
+using v2rayN.Mode;
+
+namespace v2rayN.Handler
+{
+ class ShareHandler
+ {
+
+ #region GetShareUrl
+
+ ///
+ /// GetShareUrl
+ ///
+ ///
+ ///
+ ///
+ public static string GetShareUrl(Config config, int index)
+ {
+ try
+ {
+ string url = string.Empty;
+
+ VmessItem item = config.vmess[index];
+ if (item.configType == (int)EConfigType.Vmess)
+ {
+ VmessQRCode vmessQRCode = new VmessQRCode
+ {
+ v = item.configVersion.ToString(),
+ ps = item.remarks.TrimEx(), //备注也许很长 ;
+ add = item.address,
+ port = item.port.ToString(),
+ id = item.id,
+ aid = item.alterId.ToString(),
+ net = item.network,
+ type = item.headerType,
+ host = item.requestHost,
+ path = item.path,
+ tls = item.streamSecurity
+ };
+
+ url = Utils.ToJson(vmessQRCode);
+ url = Utils.Base64Encode(url);
+ url = string.Format("{0}{1}", Global.vmessProtocol, url);
+
+ }
+ else if (item.configType == (int)EConfigType.Shadowsocks)
+ {
+ string remark = string.Empty;
+ if (!Utils.IsNullOrEmpty(item.remarks))
+ {
+ remark = "#" + WebUtility.UrlEncode(item.remarks);
+ }
+ url = string.Format("{0}:{1}@{2}:{3}",
+ item.security,
+ item.id,
+ item.address,
+ item.port);
+ url = Utils.Base64Encode(url);
+ url = string.Format("{0}{1}{2}", Global.ssProtocol, url, remark);
+ }
+ else if (item.configType == (int)EConfigType.Socks)
+ {
+ string remark = string.Empty;
+ if (!Utils.IsNullOrEmpty(item.remarks))
+ {
+ remark = "#" + WebUtility.UrlEncode(item.remarks);
+ }
+ url = string.Format("{0}:{1}@{2}:{3}",
+ item.security,
+ item.id,
+ item.address,
+ item.port);
+ url = Utils.Base64Encode(url);
+ url = string.Format("{0}{1}{2}", Global.socksProtocol, url, remark);
+ }
+ else if (item.configType == (int)EConfigType.Trojan)
+ {
+ string remark = string.Empty;
+ if (!Utils.IsNullOrEmpty(item.remarks))
+ {
+ remark = "#" + WebUtility.UrlEncode(item.remarks);
+ }
+ string query = string.Empty;
+ if (!Utils.IsNullOrEmpty(item.requestHost))
+ {
+ query = string.Format("?sni={0}", item.requestHost);
+ }
+ url = string.Format("{0}@{1}:{2}",
+ item.id,
+ item.address,
+ item.port);
+ url = string.Format("{0}{1}{2}{3}", Global.trojanProtocol, url, query, remark);
+ }
+ else if (item.configType == (int)EConfigType.VLESS)
+ {
+ string remark = string.Empty;
+ if (!Utils.IsNullOrEmpty(item.remarks))
+ {
+ remark = "#" + WebUtility.UrlEncode(item.remarks);
+ }
+ var dicQuery = new Dictionary();
+ if (!Utils.IsNullOrEmpty(item.flow))
+ {
+ dicQuery.Add("flow", item.flow);
+ }
+ if (!Utils.IsNullOrEmpty(item.security))
+ {
+ dicQuery.Add("encryption", item.security);
+ }
+ else
+ {
+ dicQuery.Add("encryption", "none");
+ }
+ if (!Utils.IsNullOrEmpty(item.streamSecurity))
+ {
+ dicQuery.Add("security", item.streamSecurity);
+ }
+ else
+ {
+ dicQuery.Add("security", "none");
+ }
+ if (!Utils.IsNullOrEmpty(item.network))
+ {
+ dicQuery.Add("type", item.network);
+ }
+ else
+ {
+ dicQuery.Add("type", "tcp");
+ }
+
+ switch (item.network)
+ {
+ case "tcp":
+ if (!Utils.IsNullOrEmpty(item.headerType))
+ {
+ dicQuery.Add("headerType", item.headerType);
+ }
+ else
+ {
+ dicQuery.Add("headerType", "none");
+ }
+ if (!Utils.IsNullOrEmpty(item.requestHost))
+ {
+ dicQuery.Add("host", item.requestHost);
+ }
+ break;
+ case "kcp":
+ if (!Utils.IsNullOrEmpty(item.headerType))
+ {
+ dicQuery.Add("headerType", item.headerType);
+ }
+ else
+ {
+ dicQuery.Add("headerType", "none");
+ }
+ if (!Utils.IsNullOrEmpty(item.path))
+ {
+ dicQuery.Add("seed", item.path);
+ }
+ break;
+
+ case "ws":
+ if (!Utils.IsNullOrEmpty(item.requestHost))
+ {
+ dicQuery.Add("host", item.requestHost);
+ }
+ if (!Utils.IsNullOrEmpty(item.path))
+ {
+ dicQuery.Add("path", item.path);
+ }
+ break;
+
+ case "http":
+ case "h2":
+ dicQuery["type"] = "http";
+ if (!Utils.IsNullOrEmpty(item.requestHost))
+ {
+ dicQuery.Add("host", item.requestHost);
+ }
+ if (!Utils.IsNullOrEmpty(item.path))
+ {
+ dicQuery.Add("path", item.path);
+ }
+ break;
+
+ case "quic":
+ if (!Utils.IsNullOrEmpty(item.headerType))
+ {
+ dicQuery.Add("headerType", item.headerType);
+ }
+ else
+ {
+ dicQuery.Add("headerType", "none");
+ }
+ dicQuery.Add("quicSecurity", item.requestHost);
+ dicQuery.Add("key", item.path);
+ break;
+ }
+ string query = "?" + string.Join("&", dicQuery.Select(x => x.Key + "=" + x.Value).ToArray());
+
+ url = string.Format("{0}@{1}:{2}",
+ item.id,
+ item.address,
+ item.port);
+ url = string.Format("{0}{1}{2}{3}", Global.vlessProtocol, url, query, remark);
+ }
+ else
+ {
+ }
+ return url;
+ }
+ catch
+ {
+ return "";
+ }
+ }
+
+ #endregion
+
+ #region ImportShareUrl
+
+
+ ///
+ /// 从剪贴板导入URL
+ ///
+ ///
+ ///
+ ///
+ public static VmessItem ImportFromClipboardConfig(string clipboardData, out string msg)
+ {
+ msg = string.Empty;
+ VmessItem vmessItem = new VmessItem();
+
+ try
+ {
+ //载入配置文件
+ string result = clipboardData.TrimEx();// Utils.GetClipboardData();
+ if (Utils.IsNullOrEmpty(result))
+ {
+ msg = UIRes.I18N("FailedReadConfiguration");
+ return null;
+ }
+
+ if (result.StartsWith(Global.vmessProtocol))
+ {
+ int indexSplit = result.IndexOf("?");
+ if (indexSplit > 0)
+ {
+ vmessItem = ResolveStdVmess(result) ?? ResolveVmess4Kitsunebi(result);
+ }
+ else
+ {
+ vmessItem.configType = (int)EConfigType.Vmess;
+ result = result.Substring(Global.vmessProtocol.Length);
+ result = Utils.Base64Decode(result);
+
+ //转成Json
+ VmessQRCode vmessQRCode = Utils.FromJson(result);
+ if (vmessQRCode == null)
+ {
+ msg = UIRes.I18N("FailedConversionConfiguration");
+ return null;
+ }
+ vmessItem.security = Global.DefaultSecurity;
+ vmessItem.network = Global.DefaultNetwork;
+ vmessItem.headerType = Global.None;
+
+
+ vmessItem.configVersion = Utils.ToInt(vmessQRCode.v);
+ vmessItem.remarks = Utils.ToString(vmessQRCode.ps);
+ vmessItem.address = Utils.ToString(vmessQRCode.add);
+ vmessItem.port = Utils.ToInt(vmessQRCode.port);
+ vmessItem.id = Utils.ToString(vmessQRCode.id);
+ vmessItem.alterId = Utils.ToInt(vmessQRCode.aid);
+
+ if (!Utils.IsNullOrEmpty(vmessQRCode.net))
+ {
+ vmessItem.network = vmessQRCode.net;
+ }
+ if (!Utils.IsNullOrEmpty(vmessQRCode.type))
+ {
+ vmessItem.headerType = vmessQRCode.type;
+ }
+
+ vmessItem.requestHost = Utils.ToString(vmessQRCode.host);
+ vmessItem.path = Utils.ToString(vmessQRCode.path);
+ vmessItem.streamSecurity = Utils.ToString(vmessQRCode.tls);
+ }
+
+ ConfigHandler.UpgradeServerVersion(ref vmessItem);
+ }
+ else if (result.StartsWith(Global.ssProtocol))
+ {
+ msg = UIRes.I18N("ConfigurationFormatIncorrect");
+
+ vmessItem = ResolveSSLegacy(result);
+ if (vmessItem == null)
+ {
+ vmessItem = ResolveSip002(result);
+ }
+ if (vmessItem == null)
+ {
+ return null;
+ }
+ if (vmessItem.address.Length == 0 || vmessItem.port == 0 || vmessItem.security.Length == 0 || vmessItem.id.Length == 0)
+ {
+ return null;
+ }
+
+ vmessItem.configType = (int)EConfigType.Shadowsocks;
+ }
+ else if (result.StartsWith(Global.socksProtocol))
+ {
+ msg = UIRes.I18N("ConfigurationFormatIncorrect");
+
+ vmessItem.configType = (int)EConfigType.Socks;
+ result = result.Substring(Global.socksProtocol.Length);
+ //remark
+ int indexRemark = result.IndexOf("#");
+ if (indexRemark > 0)
+ {
+ try
+ {
+ vmessItem.remarks = WebUtility.UrlDecode(result.Substring(indexRemark + 1, result.Length - indexRemark - 1));
+ }
+ catch { }
+ result = result.Substring(0, indexRemark);
+ }
+ //part decode
+ int indexS = result.IndexOf("@");
+ if (indexS > 0)
+ {
+ }
+ else
+ {
+ result = Utils.Base64Decode(result);
+ }
+
+ string[] arr1 = result.Split('@');
+ if (arr1.Length != 2)
+ {
+ return null;
+ }
+ string[] arr21 = arr1[0].Split(':');
+ //string[] arr22 = arr1[1].Split(':');
+ int indexPort = arr1[1].LastIndexOf(":");
+ if (arr21.Length != 2 || indexPort < 0)
+ {
+ return null;
+ }
+ vmessItem.address = arr1[1].Substring(0, indexPort);
+ vmessItem.port = Utils.ToInt(arr1[1].Substring(indexPort + 1, arr1[1].Length - (indexPort + 1)));
+ vmessItem.security = arr21[0];
+ vmessItem.id = arr21[1];
+ }
+ else if (result.StartsWith(Global.trojanProtocol))
+ {
+ msg = UIRes.I18N("ConfigurationFormatIncorrect");
+
+ vmessItem.configType = (int)EConfigType.Trojan;
+
+ Uri uri = new Uri(result);
+ vmessItem.address = uri.IdnHost;
+ vmessItem.port = uri.Port;
+ vmessItem.id = uri.UserInfo;
+
+ var qurery = HttpUtility.ParseQueryString(uri.Query);
+ vmessItem.requestHost = qurery["sni"] ?? "";
+
+ var remarks = uri.Fragment.Replace("#", "");
+ if (Utils.IsNullOrEmpty(remarks))
+ {
+ vmessItem.remarks = "NONE";
+ }
+ else
+ {
+ vmessItem.remarks = WebUtility.UrlDecode(remarks);
+ }
+ }
+ else if (result.StartsWith(Global.vlessProtocol))
+ {
+ vmessItem = ResolveStdVLESS(result);
+
+ ConfigHandler.UpgradeServerVersion(ref vmessItem);
+ }
+ else
+ {
+ msg = UIRes.I18N("NonvmessOrssProtocol");
+ return null;
+ }
+ }
+ catch
+ {
+ msg = UIRes.I18N("Incorrectconfiguration");
+ return null;
+ }
+
+ return vmessItem;
+ }
+
+
+ private static VmessItem ResolveVmess4Kitsunebi(string result)
+ {
+ VmessItem vmessItem = new VmessItem
+ {
+ configType = (int)EConfigType.Vmess
+ };
+ result = result.Substring(Global.vmessProtocol.Length);
+ int indexSplit = result.IndexOf("?");
+ if (indexSplit > 0)
+ {
+ result = result.Substring(0, indexSplit);
+ }
+ result = Utils.Base64Decode(result);
+
+ string[] arr1 = result.Split('@');
+ if (arr1.Length != 2)
+ {
+ return null;
+ }
+ string[] arr21 = arr1[0].Split(':');
+ string[] arr22 = arr1[1].Split(':');
+ if (arr21.Length != 2 || arr21.Length != 2)
+ {
+ return null;
+ }
+
+ vmessItem.address = arr22[0];
+ vmessItem.port = Utils.ToInt(arr22[1]);
+ vmessItem.security = arr21[0];
+ vmessItem.id = arr21[1];
+
+ vmessItem.network = Global.DefaultNetwork;
+ vmessItem.headerType = Global.None;
+ vmessItem.remarks = "Alien";
+ vmessItem.alterId = 0;
+
+ return vmessItem;
+ }
+
+ private static VmessItem ResolveSip002(string result)
+ {
+ Uri parsedUrl;
+ try
+ {
+ parsedUrl = new Uri(result);
+ }
+ catch (UriFormatException)
+ {
+ return null;
+ }
+ VmessItem server = new VmessItem
+ {
+ remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),
+ address = parsedUrl.IdnHost,
+ port = parsedUrl.Port,
+ };
+
+ // parse base64 UserInfo
+ string rawUserInfo = parsedUrl.GetComponents(UriComponents.UserInfo, UriFormat.Unescaped);
+ string base64 = rawUserInfo.Replace('-', '+').Replace('_', '/'); // Web-safe base64 to normal base64
+ string userInfo;
+ try
+ {
+ userInfo = Encoding.UTF8.GetString(Convert.FromBase64String(
+ base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '=')));
+ }
+ catch (FormatException)
+ {
+ return null;
+ }
+ string[] userInfoParts = userInfo.Split(new char[] { ':' }, 2);
+ if (userInfoParts.Length != 2)
+ {
+ return null;
+ }
+ server.security = userInfoParts[0];
+ server.id = userInfoParts[1];
+
+ NameValueCollection queryParameters = HttpUtility.ParseQueryString(parsedUrl.Query);
+ if (queryParameters["plugin"] != null)
+ {
+ return null;
+ }
+
+ return server;
+ }
+
+ private static readonly Regex UrlFinder = new Regex(@"ss://(?[A-Za-z0-9+-/=_]+)(?:#(?\S+))?", RegexOptions.IgnoreCase);
+ private static readonly Regex DetailsParser = new Regex(@"^((?.+?):(?.*)@(?.+?):(?\d+?))$", RegexOptions.IgnoreCase);
+
+ private static VmessItem ResolveSSLegacy(string result)
+ {
+ var match = UrlFinder.Match(result);
+ if (!match.Success)
+ return null;
+
+ VmessItem server = new VmessItem();
+ var base64 = match.Groups["base64"].Value.TrimEnd('/');
+ var tag = match.Groups["tag"].Value;
+ if (!Utils.IsNullOrEmpty(tag))
+ {
+ server.remarks = HttpUtility.UrlDecode(tag, Encoding.UTF8);
+ }
+ Match details;
+ try
+ {
+ details = DetailsParser.Match(Encoding.UTF8.GetString(Convert.FromBase64String(
+ base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '='))));
+ }
+ catch (FormatException)
+ {
+ return null;
+ }
+ if (!details.Success)
+ return null;
+ server.security = details.Groups["method"].Value;
+ server.id = details.Groups["password"].Value;
+ server.address = details.Groups["hostname"].Value;
+ server.port = int.Parse(details.Groups["port"].Value);
+ return server;
+ }
+
+
+ private static readonly Regex StdVmessUserInfo = new Regex(
+ @"^(?[a-z]+)(\+(?[a-z]+))?:(?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})-(?[0-9]+)$");
+
+ private static VmessItem ResolveStdVmess(string result)
+ {
+ VmessItem i = new VmessItem
+ {
+ configType = (int)EConfigType.Vmess,
+ security = "auto"
+ };
+
+ Uri u = new Uri(result);
+
+ i.address = u.IdnHost;
+ i.port = u.Port;
+ i.remarks = u.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
+ var q = HttpUtility.ParseQueryString(u.Query);
+
+ var m = StdVmessUserInfo.Match(u.UserInfo);
+ if (!m.Success) return null;
+
+ i.id = m.Groups["id"].Value;
+ if (!int.TryParse(m.Groups["alterId"].Value, out int aid))
+ {
+ return null;
+ }
+ i.alterId = aid;
+
+ if (m.Groups["streamSecurity"].Success)
+ {
+ i.streamSecurity = m.Groups["streamSecurity"].Value;
+ }
+ switch (i.streamSecurity)
+ {
+ case "tls":
+ // TODO tls config
+ break;
+ default:
+ if (!string.IsNullOrWhiteSpace(i.streamSecurity))
+ return null;
+ break;
+ }
+
+ i.network = m.Groups["network"].Value;
+ switch (i.network)
+ {
+ case "tcp":
+ string t1 = q["type"] ?? "none";
+ i.headerType = t1;
+ // TODO http option
+
+ break;
+ case "kcp":
+ i.headerType = q["type"] ?? "none";
+ // TODO kcp seed
+ break;
+
+ case "ws":
+ string p1 = q["path"] ?? "/";
+ string h1 = q["host"] ?? "";
+ i.requestHost = h1;
+ i.path = p1;
+ break;
+
+ case "http":
+ case "h2":
+ i.network = "h2";
+ string p2 = q["path"] ?? "/";
+ string h2 = q["host"] ?? "";
+ i.requestHost = h2;
+ i.path = p2;
+ break;
+
+ case "quic":
+ string s = q["security"] ?? "none";
+ string k = q["key"] ?? "";
+ string t3 = q["type"] ?? "none";
+ i.headerType = t3;
+ i.requestHost = s;
+ i.path = k;
+ break;
+
+ default:
+ return null;
+ }
+
+ return i;
+ }
+
+ private static VmessItem ResolveStdVLESS(string result)
+ {
+ VmessItem item = new VmessItem
+ {
+ configType = (int)EConfigType.VLESS,
+ security = "none"
+ };
+
+ Uri url = new Uri(result);
+
+ item.address = url.IdnHost;
+ item.port = url.Port;
+ item.remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
+ item.id = url.UserInfo;
+
+ var query = HttpUtility.ParseQueryString(url.Query);
+
+ item.flow = query["flow"] ?? "";
+ item.security = query["encryption"] ?? "none";
+ item.streamSecurity = query["security"] ?? "";
+ item.network = query["type"] ?? "tcp";
+ switch (item.network)
+ {
+ case "tcp":
+ item.headerType = query["headerType"] ?? "none";
+ item.requestHost = query["host"] ?? "";
+
+ break;
+ case "kcp":
+ item.headerType = query["headerType"] ?? "none";
+ item.path = query["seed"] ?? "";
+ break;
+
+ case "ws":
+ item.requestHost = query["host"] ?? "";
+ item.path = query["path"] ?? "/";
+ break;
+
+ case "http":
+ case "h2":
+ item.network = "h2";
+ item.requestHost = query["host"] ?? "";
+ item.path = query["path"] ?? "/";
+ break;
+
+ case "quic":
+ item.headerType = query["headerType"] ?? "none";
+ item.requestHost = query["quicSecurity"] ?? "none";
+ item.path = query["key"] ?? "";
+ break;
+
+ default:
+ return null;
+ }
+
+ return item;
+ }
+
+ #endregion
+ }
+}
diff --git a/v2rayN/v2rayN/Handler/V2rayConfigHandler.cs b/v2rayN/v2rayN/Handler/V2rayConfigHandler.cs
index 473400c3..6fa3ecb6 100644
--- a/v2rayN/v2rayN/Handler/V2rayConfigHandler.cs
+++ b/v2rayN/v2rayN/Handler/V2rayConfigHandler.cs
@@ -1,13 +1,7 @@
using System;
using System.Collections.Generic;
-using System.Collections.Specialized;
using System.IO;
using System.Linq;
-using System.Net;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Web;
-using v2rayN.Base;
using v2rayN.Mode;
namespace v2rayN.Handler
@@ -467,7 +461,7 @@ namespace v2rayN.Handler
}
else
{
- usersItem.flow = config.flow();
+ usersItem.flow = config.flow().Replace("splice", "direct");
}
outbound.mux.enabled = false;
@@ -1283,179 +1277,6 @@ namespace v2rayN.Handler
return vmessItem;
}
- ///
- /// 从剪贴板导入URL
- ///
- ///
- ///
- ///
- public static VmessItem ImportFromClipboardConfig(string clipboardData, out string msg)
- {
- msg = string.Empty;
- VmessItem vmessItem = new VmessItem();
-
- try
- {
- //载入配置文件
- string result = clipboardData.TrimEx();// Utils.GetClipboardData();
- if (Utils.IsNullOrEmpty(result))
- {
- msg = UIRes.I18N("FailedReadConfiguration");
- return null;
- }
-
- if (result.StartsWith(Global.vmessProtocol))
- {
- int indexSplit = result.IndexOf("?");
- if (indexSplit > 0)
- {
- vmessItem = ResolveStdVmess(result) ?? ResolveVmess4Kitsunebi(result);
- }
- else
- {
- vmessItem.configType = (int)EConfigType.Vmess;
- result = result.Substring(Global.vmessProtocol.Length);
- result = Utils.Base64Decode(result);
-
- //转成Json
- VmessQRCode vmessQRCode = Utils.FromJson(result);
- if (vmessQRCode == null)
- {
- msg = UIRes.I18N("FailedConversionConfiguration");
- return null;
- }
- vmessItem.security = Global.DefaultSecurity;
- vmessItem.network = Global.DefaultNetwork;
- vmessItem.headerType = Global.None;
-
-
- vmessItem.configVersion = Utils.ToInt(vmessQRCode.v);
- vmessItem.remarks = Utils.ToString(vmessQRCode.ps);
- vmessItem.address = Utils.ToString(vmessQRCode.add);
- vmessItem.port = Utils.ToInt(vmessQRCode.port);
- vmessItem.id = Utils.ToString(vmessQRCode.id);
- vmessItem.alterId = Utils.ToInt(vmessQRCode.aid);
-
- if (!Utils.IsNullOrEmpty(vmessQRCode.net))
- {
- vmessItem.network = vmessQRCode.net;
- }
- if (!Utils.IsNullOrEmpty(vmessQRCode.type))
- {
- vmessItem.headerType = vmessQRCode.type;
- }
-
- vmessItem.requestHost = Utils.ToString(vmessQRCode.host);
- vmessItem.path = Utils.ToString(vmessQRCode.path);
- vmessItem.streamSecurity = Utils.ToString(vmessQRCode.tls);
- }
-
- ConfigHandler.UpgradeServerVersion(ref vmessItem);
- }
- else if (result.StartsWith(Global.ssProtocol))
- {
- msg = UIRes.I18N("ConfigurationFormatIncorrect");
-
- vmessItem = ResolveSSLegacy(result);
- if (vmessItem == null)
- {
- vmessItem = ResolveSip002(result);
- }
- if (vmessItem == null)
- {
- return null;
- }
- if (vmessItem.address.Length == 0 || vmessItem.port == 0 || vmessItem.security.Length == 0 || vmessItem.id.Length == 0)
- {
- return null;
- }
-
- vmessItem.configType = (int)EConfigType.Shadowsocks;
- }
- else if (result.StartsWith(Global.socksProtocol))
- {
- msg = UIRes.I18N("ConfigurationFormatIncorrect");
-
- vmessItem.configType = (int)EConfigType.Socks;
- result = result.Substring(Global.socksProtocol.Length);
- //remark
- int indexRemark = result.IndexOf("#");
- if (indexRemark > 0)
- {
- try
- {
- vmessItem.remarks = WebUtility.UrlDecode(result.Substring(indexRemark + 1, result.Length - indexRemark - 1));
- }
- catch { }
- result = result.Substring(0, indexRemark);
- }
- //part decode
- int indexS = result.IndexOf("@");
- if (indexS > 0)
- {
- }
- else
- {
- result = Utils.Base64Decode(result);
- }
-
- string[] arr1 = result.Split('@');
- if (arr1.Length != 2)
- {
- return null;
- }
- string[] arr21 = arr1[0].Split(':');
- //string[] arr22 = arr1[1].Split(':');
- int indexPort = arr1[1].LastIndexOf(":");
- if (arr21.Length != 2 || indexPort < 0)
- {
- return null;
- }
- vmessItem.address = arr1[1].Substring(0, indexPort);
- vmessItem.port = Utils.ToInt(arr1[1].Substring(indexPort + 1, arr1[1].Length - (indexPort + 1)));
- vmessItem.security = arr21[0];
- vmessItem.id = arr21[1];
- }
- else if (result.StartsWith(Global.trojanProtocol))
- {
- msg = UIRes.I18N("ConfigurationFormatIncorrect");
-
- vmessItem.configType = (int)EConfigType.Trojan;
-
- Uri uri = new Uri(result);
- vmessItem.address = uri.IdnHost;
- vmessItem.port = uri.Port;
- vmessItem.id = uri.UserInfo;
-
- var qurery = HttpUtility.ParseQueryString(uri.Query);
- vmessItem.requestHost = qurery["sni"] ?? "";
-
- var remarks = uri.Fragment.Replace("#", "");
- if (Utils.IsNullOrEmpty(remarks))
- {
- vmessItem.remarks = "NONE";
- }
- else
- {
- vmessItem.remarks = WebUtility.UrlDecode(remarks);
- }
- }
- else
- {
- msg = UIRes.I18N("NonvmessOrssProtocol");
- return null;
- }
- }
- catch
- {
- msg = UIRes.I18N("Incorrectconfiguration");
- return null;
- }
-
- return vmessItem;
- }
-
-
///
/// 导出为客户端配置
///
@@ -1480,216 +1301,6 @@ namespace v2rayN.Handler
return GenerateServerConfig(config, fileName, out msg);
}
- private static VmessItem ResolveVmess4Kitsunebi(string result)
- {
- VmessItem vmessItem = new VmessItem
- {
- configType = (int)EConfigType.Vmess
- };
- result = result.Substring(Global.vmessProtocol.Length);
- int indexSplit = result.IndexOf("?");
- if (indexSplit > 0)
- {
- result = result.Substring(0, indexSplit);
- }
- result = Utils.Base64Decode(result);
-
- string[] arr1 = result.Split('@');
- if (arr1.Length != 2)
- {
- return null;
- }
- string[] arr21 = arr1[0].Split(':');
- string[] arr22 = arr1[1].Split(':');
- if (arr21.Length != 2 || arr21.Length != 2)
- {
- return null;
- }
-
- vmessItem.address = arr22[0];
- vmessItem.port = Utils.ToInt(arr22[1]);
- vmessItem.security = arr21[0];
- vmessItem.id = arr21[1];
-
- vmessItem.network = Global.DefaultNetwork;
- vmessItem.headerType = Global.None;
- vmessItem.remarks = "Alien";
- vmessItem.alterId = 0;
-
- return vmessItem;
- }
-
- private static VmessItem ResolveSip002(string result)
- {
- Uri parsedUrl;
- try
- {
- parsedUrl = new Uri(result);
- }
- catch (UriFormatException)
- {
- return null;
- }
- VmessItem server = new VmessItem
- {
- remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),
- address = parsedUrl.IdnHost,
- port = parsedUrl.Port,
- };
-
- // parse base64 UserInfo
- string rawUserInfo = parsedUrl.GetComponents(UriComponents.UserInfo, UriFormat.Unescaped);
- string base64 = rawUserInfo.Replace('-', '+').Replace('_', '/'); // Web-safe base64 to normal base64
- string userInfo;
- try
- {
- userInfo = Encoding.UTF8.GetString(Convert.FromBase64String(
- base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '=')));
- }
- catch (FormatException)
- {
- return null;
- }
- string[] userInfoParts = userInfo.Split(new char[] { ':' }, 2);
- if (userInfoParts.Length != 2)
- {
- return null;
- }
- server.security = userInfoParts[0];
- server.id = userInfoParts[1];
-
- NameValueCollection queryParameters = HttpUtility.ParseQueryString(parsedUrl.Query);
- if (queryParameters["plugin"] != null)
- {
- return null;
- }
-
- return server;
- }
-
- private static readonly Regex UrlFinder = new Regex(@"ss://(?[A-Za-z0-9+-/=_]+)(?:#(?\S+))?", RegexOptions.IgnoreCase);
- private static readonly Regex DetailsParser = new Regex(@"^((?.+?):(?.*)@(?.+?):(?\d+?))$", RegexOptions.IgnoreCase);
-
- private static VmessItem ResolveSSLegacy(string result)
- {
- var match = UrlFinder.Match(result);
- if (!match.Success)
- return null;
-
- VmessItem server = new VmessItem();
- var base64 = match.Groups["base64"].Value.TrimEnd('/');
- var tag = match.Groups["tag"].Value;
- if (!tag.IsNullOrEmpty())
- {
- server.remarks = HttpUtility.UrlDecode(tag, Encoding.UTF8);
- }
- Match details;
- try
- {
- details = DetailsParser.Match(Encoding.UTF8.GetString(Convert.FromBase64String(
- base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '='))));
- }
- catch (FormatException)
- {
- return null;
- }
- if (!details.Success)
- return null;
- server.security = details.Groups["method"].Value;
- server.id = details.Groups["password"].Value;
- server.address = details.Groups["hostname"].Value;
- server.port = int.Parse(details.Groups["port"].Value);
- return server;
- }
-
-
- private static readonly Regex StdVmessUserInfo = new Regex(
- @"^(?[a-z]+)(\+(?[a-z]+))?:(?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})-(?[0-9]+)$");
-
- private static VmessItem ResolveStdVmess(string result)
- {
- VmessItem i = new VmessItem
- {
- configType = (int)EConfigType.Vmess,
- security = "auto"
- };
-
- Uri u = new Uri(result);
-
- i.address = u.IdnHost;
- i.port = u.Port;
- i.remarks = u.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
- var q = HttpUtility.ParseQueryString(u.Query);
-
- var m = StdVmessUserInfo.Match(u.UserInfo);
- if (!m.Success) return null;
-
- i.id = m.Groups["id"].Value;
- if (!int.TryParse(m.Groups["alterId"].Value, out int aid))
- {
- return null;
- }
- i.alterId = aid;
-
- if (m.Groups["streamSecurity"].Success)
- {
- i.streamSecurity = m.Groups["streamSecurity"].Value;
- }
- switch (i.streamSecurity)
- {
- case "tls":
- // TODO tls config
- break;
- default:
- if (!string.IsNullOrWhiteSpace(i.streamSecurity))
- return null;
- break;
- }
-
- i.network = m.Groups["network"].Value;
- switch (i.network)
- {
- case "tcp":
- string t1 = q["type"] ?? "none";
- i.headerType = t1;
- // TODO http option
-
- break;
- case "kcp":
- i.headerType = q["type"] ?? "none";
- // TODO kcp seed
- break;
-
- case "ws":
- string p1 = q["path"] ?? "/";
- string h1 = q["host"] ?? "";
- i.requestHost = h1;
- i.path = p1;
- break;
-
- case "http":
- i.network = "h2";
- string p2 = q["path"] ?? "/";
- string h2 = q["host"] ?? "";
- i.requestHost = h2;
- i.path = p2;
- break;
-
- case "quic":
- string s = q["security"] ?? "none";
- string k = q["key"] ?? "";
- string t3 = q["type"] ?? "none";
- i.headerType = t3;
- i.requestHost = s;
- i.path = k;
- break;
-
- default:
- return null;
- }
-
- return i;
- }
#endregion
#region Gen speedtest config
diff --git a/v2rayN/v2rayN/Properties/AssemblyInfo.cs b/v2rayN/v2rayN/Properties/AssemblyInfo.cs
index 82cf7900..66a0322b 100644
--- a/v2rayN/v2rayN/Properties/AssemblyInfo.cs
+++ b/v2rayN/v2rayN/Properties/AssemblyInfo.cs
@@ -32,4 +32,4 @@ using System.Runtime.InteropServices;
// 方法是按如下所示使用“*”:
//[assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyVersion("1.0.0")]
-[assembly: AssemblyFileVersion("4.2")]
+[assembly: AssemblyFileVersion("4.3")]
diff --git a/v2rayN/v2rayN/Resx/ResUI.Designer.cs b/v2rayN/v2rayN/Resx/ResUI.Designer.cs
index 91bf3499..a92b8267 100644
--- a/v2rayN/v2rayN/Resx/ResUI.Designer.cs
+++ b/v2rayN/v2rayN/Resx/ResUI.Designer.cs
@@ -19,7 +19,7 @@ namespace v2rayN.Resx {
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class ResUI {
@@ -717,6 +717,15 @@ namespace v2rayN.Resx {
}
}
+ ///
+ /// 查找类似 {0},One of the required. 的本地化字符串。
+ ///
+ internal static string RoutingRuleDetailRequiredTips {
+ get {
+ return ResourceManager.GetString("RoutingRuleDetailRequiredTips", resourceCulture);
+ }
+ }
+
///
/// 查找类似 The client configuration file is saved at: {0} 的本地化字符串。
///
diff --git a/v2rayN/v2rayN/Resx/ResUI.resx b/v2rayN/v2rayN/Resx/ResUI.resx
index d934df5b..21747ecc 100644
--- a/v2rayN/v2rayN/Resx/ResUI.resx
+++ b/v2rayN/v2rayN/Resx/ResUI.resx
@@ -370,4 +370,7 @@
Are you sure to remove the rules?
+
+ {0},One of the required.
+
\ No newline at end of file
diff --git a/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx b/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx
index 3346ab6a..59b4f18b 100644
--- a/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx
+++ b/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx
@@ -370,4 +370,7 @@
是否确定移除规则?
+
+ {0},必填其中一项.
+
\ No newline at end of file
diff --git a/v2rayN/v2rayN/v2rayN.csproj b/v2rayN/v2rayN/v2rayN.csproj
index f6d76a16..ea9c4b89 100644
--- a/v2rayN/v2rayN/v2rayN.csproj
+++ b/v2rayN/v2rayN/v2rayN.csproj
@@ -131,6 +131,7 @@
RoutingSettingDetailsForm.cs
+
Form