@@ -371,48 +371,7 @@ namespace Shadowsocks.Controller | |||
public string GetServerURLForCurrentServer() | |||
{ | |||
Server server = GetCurrentServer(); | |||
return GetServerURL(server); | |||
} | |||
public static string GetServerURL(Server server) | |||
{ | |||
string tag = string.Empty; | |||
string url = string.Empty; | |||
if (string.IsNullOrWhiteSpace(server.plugin)) | |||
{ | |||
// For backwards compatiblity, if no plugin, use old url format | |||
string parts = $"{server.method}:{server.password}@{server.server}:{server.server_port}"; | |||
string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts)); | |||
url = base64; | |||
} | |||
else | |||
{ | |||
// SIP002 | |||
string parts = $"{server.method}:{server.password}"; | |||
string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts)); | |||
string websafeBase64 = base64.Replace('+', '-').Replace('/', '_').TrimEnd('='); | |||
string pluginPart = server.plugin; | |||
if (!string.IsNullOrWhiteSpace(server.plugin_opts)) | |||
{ | |||
pluginPart += ";" + server.plugin_opts; | |||
} | |||
url = string.Format( | |||
"{0}@{1}:{2}/?plugin={3}", | |||
websafeBase64, | |||
server.FormatHostName(server.server), | |||
server.server_port, | |||
HttpUtility.UrlEncode(pluginPart, Encoding.UTF8)); | |||
} | |||
if (!server.remarks.IsNullOrEmpty()) | |||
{ | |||
tag = $"#{HttpUtility.UrlEncode(server.remarks, Encoding.UTF8)}"; | |||
} | |||
return $"ss://{url}{tag}"; | |||
return GetCurrentServer().URL; | |||
} | |||
public void UpdatePACFromGeosite() | |||
@@ -50,21 +50,67 @@ namespace Shadowsocks.Model | |||
return I18N.GetString("New server"); | |||
} | |||
string serverStr = $"{FormatHostName(server)}:{server_port}"; | |||
string serverStr = $"{FormalHostName}:{server_port}"; | |||
return remarks.IsNullOrEmpty() | |||
? serverStr | |||
: $"{remarks} ({serverStr})"; | |||
} | |||
public string FormatHostName(string hostName) | |||
public string URL | |||
{ | |||
// CheckHostName() won't do a real DNS lookup | |||
switch (Uri.CheckHostName(hostName)) | |||
get | |||
{ | |||
case UriHostNameType.IPv6: // Add square bracket when IPv6 (RFC3986) | |||
return $"[{hostName}]"; | |||
default: // IPv4 or domain name | |||
return hostName; | |||
string tag = string.Empty; | |||
string url = string.Empty; | |||
if (string.IsNullOrWhiteSpace(plugin)) | |||
{ | |||
// For backwards compatiblity, if no plugin, use old url format | |||
string parts = $"{method}:{password}@{server}:{server_port}"; | |||
string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts)); | |||
url = base64; | |||
} | |||
else | |||
{ | |||
// SIP002 | |||
string parts = $"{method}:{password}"; | |||
string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts)); | |||
string websafeBase64 = base64.Replace('+', '-').Replace('/', '_').TrimEnd('='); | |||
string pluginPart = plugin; | |||
if (!string.IsNullOrWhiteSpace(plugin_opts)) | |||
{ | |||
pluginPart += ";" + plugin_opts; | |||
} | |||
url = string.Format( | |||
"{0}@{1}:{2}/?plugin={3}", | |||
websafeBase64, | |||
FormalHostName, | |||
server_port, | |||
HttpUtility.UrlEncode(pluginPart, Encoding.UTF8)); | |||
} | |||
if (!remarks.IsNullOrEmpty()) | |||
{ | |||
tag = $"#{HttpUtility.UrlEncode(remarks, Encoding.UTF8)}"; | |||
} | |||
return $"ss://{url}{tag}"; | |||
} | |||
} | |||
public string FormalHostName | |||
{ | |||
get | |||
{ | |||
// CheckHostName() won't do a real DNS lookup | |||
switch (Uri.CheckHostName(server)) | |||
{ | |||
case UriHostNameType.IPv6: // Add square bracket when IPv6 (RFC3986) | |||
return $"[{server}]"; | |||
default: // IPv4 or domain name | |||
return server; | |||
} | |||
} | |||
} | |||
@@ -67,7 +67,7 @@ namespace Shadowsocks.View | |||
var servers = Configuration.Load(); | |||
var serverDatas = servers.configs.Select( | |||
server => | |||
new KeyValuePair<string, string>(ShadowsocksController.GetServerURL(server), server.ToString()) | |||
new KeyValuePair<string, string>(server.URL, server.ToString()) | |||
).ToList(); | |||
listBox1.DataSource = serverDatas; | |||
@@ -243,7 +243,7 @@ namespace Shadowsocks.Test | |||
string expected = testCase.Key; | |||
Server config = testCase.Value; | |||
var actual = ShadowsocksController.GetServerURL(config); | |||
var actual = config.URL; | |||
Assert.AreEqual(expected, actual); | |||
} | |||
} | |||