Browse Source

allow to add multiple servers via ss url

invalid URLs will be ignored
tags/4.0.1
Syrone Wong 7 years ago
parent
commit
43672a8bda
2 changed files with 38 additions and 20 deletions
  1. +7
    -2
      shadowsocks-csharp/Controller/ShadowsocksController.cs
  2. +31
    -18
      shadowsocks-csharp/Model/Server.cs

+ 7
- 2
shadowsocks-csharp/Controller/ShadowsocksController.cs View File

@@ -163,8 +163,13 @@ namespace Shadowsocks.Controller
{
try
{
var server = new Server(ssURL);
_config.configs.Add(server);
if (ssURL.IsNullOrEmpty() || ssURL.IsWhiteSpace()) return false;
var servers = Server.GetServers(ssURL);
if (servers == null) return false;
foreach (var server in servers)
{
_config.configs.Add(server);
}
_config.index = _config.configs.Count - 1;
SaveConfig(_config);
return true;


+ 31
- 18
shadowsocks-csharp/Model/Server.cs View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
@@ -10,9 +11,8 @@ namespace Shadowsocks.Model
public class Server
{
public static readonly Regex
UrlFinder = new Regex("^(?i)ss://([A-Za-z0-9+-/=_]+)(#(.+))?$", RegexOptions.IgnoreCase),
DetailsParser = new Regex("^((?<method>.+?):(?<password>.*)@(?<hostname>.+?)" +
":(?<port>\\d+?))$", RegexOptions.IgnoreCase);
UrlFinder = new Regex(@"ss://(?<base64>[A-Za-z0-9+-/=_]+)(?:#(?<tag>.+))?", RegexOptions.IgnoreCase),
DetailsParser = new Regex(@"^((?<method>.+?):(?<password>.*)@(?<hostname>.+?):(?<port>\d+?))$", RegexOptions.IgnoreCase);
private const int DefaultServerTimeoutSec = 5;
public const int MaxServerTimeoutSec = 20;
@@ -43,9 +43,10 @@ namespace Shadowsocks.Model
}
string serverStr;
// CheckHostName() won't do a real DNS lookup
var hostType = Uri.CheckHostName( server );
var hostType = Uri.CheckHostName(server);
switch ( hostType ) {
switch (hostType)
{
case UriHostNameType.IPv6:
serverStr = $"[{server}]:{server_port}";
break;
@@ -69,20 +70,32 @@ namespace Shadowsocks.Model
timeout = DefaultServerTimeoutSec;
}
public Server(string ssURL) : this()
public static List<Server> GetServers(string ssURL)
{
var match = UrlFinder.Match(ssURL);
if (!match.Success) throw new FormatException();
var base64 = match.Groups[1].Value;
var tag = match.Groups[3].Value;
if (!tag.IsNullOrEmpty())
remarks = HttpUtility.UrlDecode(tag, Encoding.UTF8);
match = DetailsParser.Match(Encoding.UTF8.GetString(Convert.FromBase64String(
base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '='))));
method = match.Groups["method"].Value;
password = match.Groups["password"].Value;
server = match.Groups["hostname"].Value;
server_port = int.Parse(match.Groups["port"].Value);
var matches = UrlFinder.Matches(ssURL);
if (matches.Count <= 0) return null;
List<Server> servers = new List<Server>();
foreach (Match match in matches)
{
Server tmp = new Server();
var base64 = match.Groups["base64"].Value;
var tag = match.Groups["tag"].Value;
if (!tag.IsNullOrEmpty())
{
tmp.remarks = HttpUtility.UrlDecode(tag, Encoding.UTF8);
}
Match details = DetailsParser.Match(Encoding.UTF8.GetString(Convert.FromBase64String(
base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '='))));
if (!details.Success)
continue;
tmp.method = details.Groups["method"].Value;
tmp.password = details.Groups["password"].Value;
tmp.server = details.Groups["hostname"].Value;
tmp.server_port = int.Parse(details.Groups["port"].Value);
servers.Add(tmp);
}
return servers;
}
public string Identifier()


Loading…
Cancel
Save