diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index 13c6650d..643d68ab 100755 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -252,7 +252,9 @@ namespace Shadowsocks.Controller public static string GetQRCode(Server server) { - string parts = server.method + ":" + server.password + "@" + server.server + ":" + server.server_port; + string parts = server.method; + if (server.auth) parts += "-auth"; + parts += ":" + server.password + "@" + server.server + ":" + server.server_port; string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts)); return "ss://" + base64; } diff --git a/shadowsocks-csharp/Model/Server.cs b/shadowsocks-csharp/Model/Server.cs index a42cbbf3..6ba1559d 100755 --- a/shadowsocks-csharp/Model/Server.cs +++ b/shadowsocks-csharp/Model/Server.cs @@ -9,6 +9,12 @@ namespace Shadowsocks.Model [Serializable] public class Server { + public static readonly Regex + UrlFinder = new Regex("^ss://((?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?)$", + RegexOptions.Compiled | RegexOptions.IgnoreCase), + DetailsParser = new Regex("^((?.+?)(?-auth)??:(?.*)@(?.+?)" + + ":(?\\d+?))$", RegexOptions.Compiled | RegexOptions.IgnoreCase); + public string server; public int server_port; public string password; @@ -55,45 +61,16 @@ namespace Shadowsocks.Model public Server(string ssURL) : this() { - string[] r1 = Regex.Split(ssURL, "ss://", RegexOptions.IgnoreCase); - string base64 = r1[1].ToString(); - byte[] bytes = null; - for (var i = 0; i < 3; i++) - { - try - { - bytes = Convert.FromBase64String(base64); - } - catch (FormatException) - { - base64 += "="; - } - } - if (bytes == null) - { - throw new FormatException(); - } - try - { - string data = Encoding.UTF8.GetString(bytes); - int indexLastAt = data.LastIndexOf('@'); - - string afterAt = data.Substring(indexLastAt + 1); - int indexLastColon = afterAt.LastIndexOf(':'); - server_port = int.Parse(afterAt.Substring(indexLastColon + 1)); - server = afterAt.Substring(0, indexLastColon); - - string beforeAt = data.Substring(0, indexLastAt); - string[] parts = beforeAt.Split(new[] { ':' }); - method = parts[0]; - password = parts[1]; - - //TODO: read one_time_auth - } - catch (IndexOutOfRangeException) - { - throw new FormatException(); - } + var match = UrlFinder.Match(ssURL); + if (!match.Success) throw new FormatException(); + var base64 = match.Groups[1].Value; + match = DetailsParser.Match(Encoding.UTF8.GetString(Convert.FromBase64String( + base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '=')))); + method = match.Groups["method"].Value; + auth = match.Groups["auth"].Success; + password = match.Groups["password"].Value; + server = match.Groups["hostname"].Value; + server_port = int.Parse(match.Groups["port"].Value); } public string Identifier()