mirror of
https://github.com/2dust/v2rayN.git
synced 2025-10-13 20:09:12 +00:00
Add Naive etc. uri share
URI sharing is not compatible with other clients. Compatibility was not part of the original design and it is intended solely for internal sharing and copying within the application.
This commit is contained in:
parent
37a5b7f3b4
commit
8e177a9851
6 changed files with 257 additions and 2 deletions
|
@ -170,7 +170,11 @@ public class Global
|
||||||
{ EConfigType.Hysteria2, "hysteria2://" },
|
{ EConfigType.Hysteria2, "hysteria2://" },
|
||||||
{ EConfigType.TUIC, "tuic://" },
|
{ EConfigType.TUIC, "tuic://" },
|
||||||
{ EConfigType.WireGuard, "wireguard://" },
|
{ EConfigType.WireGuard, "wireguard://" },
|
||||||
{ EConfigType.Anytls, "anytls://" }
|
{ EConfigType.Anytls, "anytls://" },
|
||||||
|
{ EConfigType.NaiveProxy, "naive://" },
|
||||||
|
{ EConfigType.Juicity, "juicity://" },
|
||||||
|
{ EConfigType.Brook, "brook://" },
|
||||||
|
{ EConfigType.Shadowquic, "shadowquic://" }
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly Dictionary<EConfigType, string> ProtocolTypes = new()
|
public static readonly Dictionary<EConfigType, string> ProtocolTypes = new()
|
||||||
|
@ -184,7 +188,11 @@ public class Global
|
||||||
{ EConfigType.Hysteria2, "hysteria2" },
|
{ EConfigType.Hysteria2, "hysteria2" },
|
||||||
{ EConfigType.TUIC, "tuic" },
|
{ EConfigType.TUIC, "tuic" },
|
||||||
{ EConfigType.WireGuard, "wireguard" },
|
{ EConfigType.WireGuard, "wireguard" },
|
||||||
{ EConfigType.Anytls, "anytls" }
|
{ EConfigType.Anytls, "anytls" },
|
||||||
|
{ EConfigType.NaiveProxy, "naiveproxy" },
|
||||||
|
{ EConfigType.Juicity, "juicity" },
|
||||||
|
{ EConfigType.Brook, "brook" },
|
||||||
|
{ EConfigType.Shadowquic, "shadowquic" }
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly List<string> VmessSecurities =
|
public static readonly List<string> VmessSecurities =
|
||||||
|
|
49
v2rayN/ServiceLib/Handler/Fmt/BrookFmt.cs
Normal file
49
v2rayN/ServiceLib/Handler/Fmt/BrookFmt.cs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
using static QRCoder.PayloadGenerator;
|
||||||
|
|
||||||
|
namespace ServiceLib.Handler.Fmt;
|
||||||
|
public class BrookFmt : BaseFmt
|
||||||
|
{
|
||||||
|
public static ProfileItem? Resolve(string str, out string msg)
|
||||||
|
{
|
||||||
|
msg = ResUI.ConfigurationFormatIncorrect;
|
||||||
|
|
||||||
|
var parsedUrl = Utils.TryUri(str);
|
||||||
|
if (parsedUrl == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfileItem item = new()
|
||||||
|
{
|
||||||
|
ConfigType = EConfigType.Brook,
|
||||||
|
Remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),
|
||||||
|
Address = parsedUrl.IdnHost,
|
||||||
|
Port = parsedUrl.Port,
|
||||||
|
};
|
||||||
|
var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo);
|
||||||
|
item.Id = rawUserInfo;
|
||||||
|
|
||||||
|
var query = Utils.ParseQueryString(parsedUrl.Query);
|
||||||
|
_ = ResolveStdTransport(query, ref item);
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string? ToUri(ProfileItem? item)
|
||||||
|
{
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var remark = string.Empty;
|
||||||
|
if (item.Remarks.IsNotEmpty())
|
||||||
|
{
|
||||||
|
remark = "#" + Utils.UrlEncode(item.Remarks);
|
||||||
|
}
|
||||||
|
var pw = item.Id;
|
||||||
|
var dicQuery = new Dictionary<string, string>();
|
||||||
|
_ = GetStdTransport(item, Global.None, ref dicQuery);
|
||||||
|
|
||||||
|
return ToUri(EConfigType.Brook, item.Address, item.Port, pw, dicQuery, remark);
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,10 @@ public class FmtHandler
|
||||||
EConfigType.TUIC => TuicFmt.ToUri(item),
|
EConfigType.TUIC => TuicFmt.ToUri(item),
|
||||||
EConfigType.WireGuard => WireguardFmt.ToUri(item),
|
EConfigType.WireGuard => WireguardFmt.ToUri(item),
|
||||||
EConfigType.Anytls => AnytlsFmt.ToUri(item),
|
EConfigType.Anytls => AnytlsFmt.ToUri(item),
|
||||||
|
EConfigType.NaiveProxy => NaiveFmt.ToUri(item),
|
||||||
|
EConfigType.Juicity => JuicityFmt.ToUri(item),
|
||||||
|
EConfigType.Brook => BrookFmt.ToUri(item),
|
||||||
|
EConfigType.Shadowquic => ShadowquicFmt.ToUri(item),
|
||||||
_ => null,
|
_ => null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -80,6 +84,22 @@ public class FmtHandler
|
||||||
{
|
{
|
||||||
return AnytlsFmt.Resolve(str, out msg);
|
return AnytlsFmt.Resolve(str, out msg);
|
||||||
}
|
}
|
||||||
|
else if (str.StartsWith(Global.ProtocolShares[EConfigType.NaiveProxy]))
|
||||||
|
{
|
||||||
|
return NaiveFmt.Resolve(str, out msg);
|
||||||
|
}
|
||||||
|
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Juicity]))
|
||||||
|
{
|
||||||
|
return JuicityFmt.Resolve(str, out msg);
|
||||||
|
}
|
||||||
|
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Brook]))
|
||||||
|
{
|
||||||
|
return BrookFmt.Resolve(str, out msg);
|
||||||
|
}
|
||||||
|
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Shadowquic]))
|
||||||
|
{
|
||||||
|
return ShadowquicFmt.Resolve(str, out msg);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
msg = ResUI.NonvmessOrssProtocol;
|
msg = ResUI.NonvmessOrssProtocol;
|
||||||
|
|
63
v2rayN/ServiceLib/Handler/Fmt/JuicityFmt.cs
Normal file
63
v2rayN/ServiceLib/Handler/Fmt/JuicityFmt.cs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
namespace ServiceLib.Handler.Fmt;
|
||||||
|
|
||||||
|
public class JuicityFmt : BaseFmt
|
||||||
|
{
|
||||||
|
public static ProfileItem? Resolve(string str, out string msg)
|
||||||
|
{
|
||||||
|
msg = ResUI.ConfigurationFormatIncorrect;
|
||||||
|
|
||||||
|
ProfileItem item = new()
|
||||||
|
{
|
||||||
|
ConfigType = EConfigType.Juicity
|
||||||
|
};
|
||||||
|
|
||||||
|
var url = Utils.TryUri(str);
|
||||||
|
if (url == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
item.Address = url.IdnHost;
|
||||||
|
item.Port = url.Port;
|
||||||
|
item.Remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
|
||||||
|
var rawUserInfo = Utils.UrlDecode(url.UserInfo);
|
||||||
|
var userInfoParts = rawUserInfo.Split(new[] { ':' }, 2);
|
||||||
|
if (userInfoParts.Length == 2)
|
||||||
|
{
|
||||||
|
item.Id = userInfoParts.First();
|
||||||
|
item.Security = userInfoParts.Last();
|
||||||
|
}
|
||||||
|
|
||||||
|
var query = Utils.ParseQueryString(url.Query);
|
||||||
|
ResolveStdTransport(query, ref item);
|
||||||
|
item.HeaderType = query["congestion_control"] ?? "";
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string? ToUri(ProfileItem? item)
|
||||||
|
{
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var remark = string.Empty;
|
||||||
|
if (item.Remarks.IsNotEmpty())
|
||||||
|
{
|
||||||
|
remark = "#" + Utils.UrlEncode(item.Remarks);
|
||||||
|
}
|
||||||
|
var dicQuery = new Dictionary<string, string>();
|
||||||
|
if (item.Sni.IsNotEmpty())
|
||||||
|
{
|
||||||
|
dicQuery.Add("sni", item.Sni);
|
||||||
|
}
|
||||||
|
if (item.Alpn.IsNotEmpty())
|
||||||
|
{
|
||||||
|
dicQuery.Add("alpn", Utils.UrlEncode(item.Alpn));
|
||||||
|
}
|
||||||
|
dicQuery.Add("congestion_control", item.HeaderType);
|
||||||
|
|
||||||
|
return ToUri(EConfigType.Juicity, item.Address, item.Port, $"{item.Id}:{item.Security}", dicQuery, remark);
|
||||||
|
}
|
||||||
|
}
|
52
v2rayN/ServiceLib/Handler/Fmt/NaiveFmt.cs
Normal file
52
v2rayN/ServiceLib/Handler/Fmt/NaiveFmt.cs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
using static QRCoder.PayloadGenerator;
|
||||||
|
|
||||||
|
namespace ServiceLib.Handler.Fmt;
|
||||||
|
public class NaiveFmt : BaseFmt
|
||||||
|
{
|
||||||
|
public static ProfileItem? Resolve(string str, out string msg)
|
||||||
|
{
|
||||||
|
msg = ResUI.ConfigurationFormatIncorrect;
|
||||||
|
|
||||||
|
var parsedUrl = Utils.TryUri(str);
|
||||||
|
if (parsedUrl == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfileItem item = new()
|
||||||
|
{
|
||||||
|
ConfigType = EConfigType.NaiveProxy,
|
||||||
|
Remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),
|
||||||
|
Address = parsedUrl.IdnHost,
|
||||||
|
Port = parsedUrl.Port,
|
||||||
|
};
|
||||||
|
var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo);
|
||||||
|
item.Id = rawUserInfo;
|
||||||
|
|
||||||
|
var query = Utils.ParseQueryString(parsedUrl.Query);
|
||||||
|
_ = ResolveStdTransport(query, ref item);
|
||||||
|
|
||||||
|
item.HeaderType = query["protocol"] ?? "";
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string? ToUri(ProfileItem? item)
|
||||||
|
{
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var remark = string.Empty;
|
||||||
|
if (item.Remarks.IsNotEmpty())
|
||||||
|
{
|
||||||
|
remark = "#" + Utils.UrlEncode(item.Remarks);
|
||||||
|
}
|
||||||
|
var pw = item.Id;
|
||||||
|
var dicQuery = new Dictionary<string, string>();
|
||||||
|
_ = GetStdTransport(item, Global.None, ref dicQuery);
|
||||||
|
dicQuery.Add("protocol", item.HeaderType);
|
||||||
|
|
||||||
|
return ToUri(EConfigType.NaiveProxy, item.Address, item.Port, pw, dicQuery, remark);
|
||||||
|
}
|
||||||
|
}
|
63
v2rayN/ServiceLib/Handler/Fmt/ShadowquicFmt.cs
Normal file
63
v2rayN/ServiceLib/Handler/Fmt/ShadowquicFmt.cs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
namespace ServiceLib.Handler.Fmt;
|
||||||
|
|
||||||
|
public class ShadowquicFmt : BaseFmt
|
||||||
|
{
|
||||||
|
public static ProfileItem? Resolve(string str, out string msg)
|
||||||
|
{
|
||||||
|
msg = ResUI.ConfigurationFormatIncorrect;
|
||||||
|
|
||||||
|
ProfileItem item = new()
|
||||||
|
{
|
||||||
|
ConfigType = EConfigType.Shadowquic
|
||||||
|
};
|
||||||
|
|
||||||
|
var url = Utils.TryUri(str);
|
||||||
|
if (url == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
item.Address = url.IdnHost;
|
||||||
|
item.Port = url.Port;
|
||||||
|
item.Remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
|
||||||
|
var rawUserInfo = Utils.UrlDecode(url.UserInfo);
|
||||||
|
var userInfoParts = rawUserInfo.Split(new[] { ':' }, 2);
|
||||||
|
if (userInfoParts.Length == 2)
|
||||||
|
{
|
||||||
|
item.Id = userInfoParts.First();
|
||||||
|
item.Security = userInfoParts.Last();
|
||||||
|
}
|
||||||
|
|
||||||
|
var query = Utils.ParseQueryString(url.Query);
|
||||||
|
ResolveStdTransport(query, ref item);
|
||||||
|
item.HeaderType = query["congestion_control"] ?? "";
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string? ToUri(ProfileItem? item)
|
||||||
|
{
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var remark = string.Empty;
|
||||||
|
if (item.Remarks.IsNotEmpty())
|
||||||
|
{
|
||||||
|
remark = "#" + Utils.UrlEncode(item.Remarks);
|
||||||
|
}
|
||||||
|
var dicQuery = new Dictionary<string, string>();
|
||||||
|
if (item.Sni.IsNotEmpty())
|
||||||
|
{
|
||||||
|
dicQuery.Add("sni", item.Sni);
|
||||||
|
}
|
||||||
|
if (item.Alpn.IsNotEmpty())
|
||||||
|
{
|
||||||
|
dicQuery.Add("alpn", Utils.UrlEncode(item.Alpn));
|
||||||
|
}
|
||||||
|
dicQuery.Add("congestion_control", item.HeaderType);
|
||||||
|
|
||||||
|
return ToUri(EConfigType.Shadowquic, item.Address, item.Port, $"{item.Id}:{item.Security}", dicQuery, remark);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue