diff --git a/shadowsocks-csharp/3rd/SimpleJson.cs b/shadowsocks-csharp/3rd/SimpleJson.cs index 2850137d..6581e84b 100644 --- a/shadowsocks-csharp/3rd/SimpleJson.cs +++ b/shadowsocks-csharp/3rd/SimpleJson.cs @@ -1035,13 +1035,13 @@ namespace SimpleJson protected static bool SerializeArray(IJsonSerializerStrategy jsonSerializerStrategy, IEnumerable anArray, StringBuilder builder) { - builder.Append("["); + builder.Append("[\r\n "); bool first = true; foreach (object value in anArray) { if (!first) - builder.Append(","); + builder.Append(",\r\n "); if (!SerializeValue(jsonSerializerStrategy, value, builder)) return false; @@ -1049,7 +1049,7 @@ namespace SimpleJson first = false; } - builder.Append("]"); + builder.Append("\r\n]"); return true; } diff --git a/shadowsocks-csharp/Controller/GfwListUpdater.cs b/shadowsocks-csharp/Controller/GfwListUpdater.cs index 2b3db383..fded3a59 100644 --- a/shadowsocks-csharp/Controller/GfwListUpdater.cs +++ b/shadowsocks-csharp/Controller/GfwListUpdater.cs @@ -3,88 +3,70 @@ using System.Collections.Generic; using System.Text; using System.Net; using System.IO; +using Shadowsocks.Properties; +using System.IO.Compression; +using System.Text.RegularExpressions; +using SimpleJson; +using Shadowsocks.Util; namespace Shadowsocks.Controller { - public class GfwListUpdater + public class GFWListUpdater { private const string GFWLIST_URL = "https://autoproxy-gfwlist.googlecode.com/svn/trunk/gfwlist.txt"; - public IWebProxy proxy = null; + private static string PAC_FILE = PACServer.PAC_FILE; - public class GfwListDownloadCompletedArgs : EventArgs - { - public string Content; - } - - public event EventHandler DownloadCompleted; + public event EventHandler UpdateCompleted; public event ErrorEventHandler Error; - public void Download() - { - WebClient http = new WebClient(); - http.Proxy = proxy; - http.DownloadStringCompleted += http_DownloadStringCompleted; - http.DownloadStringAsync(new Uri(GFWLIST_URL)); - } - - protected void ReportError(Exception e) - { - if (Error != null) - { - Error(this, new ErrorEventArgs(e)); - } - } - private void http_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { try { - string response = e.Result; - if (DownloadCompleted != null) + string[] lines = ParseResult(e.Result); + + JsonArray rules = new JsonArray(); + rules.AddRange(lines); + string abpContent = Utils.UnGzip(Resources.abp_js); + abpContent = abpContent.Replace("__RULES__", rules.ToString()); + File.WriteAllText(PAC_FILE, abpContent, Encoding.UTF8); + if (UpdateCompleted != null) { - DownloadCompleted(this, new GfwListDownloadCompletedArgs - { - Content = response - }); + UpdateCompleted(this, new EventArgs()); } } catch (Exception ex) { - ReportError(ex); + if (Error != null) + { + Error(this, new ErrorEventArgs(ex)); + } } } - public class Parser - { - private string _Content; - - public string Content - { - get { return _Content; } - } - public Parser(string response) - { - byte[] bytes = Convert.FromBase64String(response); - this._Content = Encoding.ASCII.GetString(bytes); - } + public void UpdatePACFromGFWList() + { + WebClient http = new WebClient(); + http.DownloadStringCompleted += http_DownloadStringCompleted; + http.DownloadStringAsync(new Uri(GFWLIST_URL)); + } - public string[] GetValidLines() + public string[] ParseResult(string response) + { + byte[] bytes = Convert.FromBase64String(response); + string content = Encoding.ASCII.GetString(bytes); + string[] lines = content.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + List valid_lines = new List(lines.Length); + foreach (string line in lines) { - string[] lines = Content.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); - List valid_lines = new List(lines.Length); - foreach (string line in lines) - { - if (line.StartsWith("!") || line.StartsWith("[")) - continue; - valid_lines.Add(line); - } - return valid_lines.ToArray(); + if (line.StartsWith("!") || line.StartsWith("[")) + continue; + valid_lines.Add(line); } - + return valid_lines.ToArray(); } - } } diff --git a/shadowsocks-csharp/Controller/PACServer.cs b/shadowsocks-csharp/Controller/PACServer.cs index fbd1989b..b2456e18 100755 --- a/shadowsocks-csharp/Controller/PACServer.cs +++ b/shadowsocks-csharp/Controller/PACServer.cs @@ -1,5 +1,6 @@ using Shadowsocks.Model; using Shadowsocks.Properties; +using Shadowsocks.Util; using System; using System.Collections.Generic; using System.Diagnostics; @@ -8,14 +9,13 @@ using System.IO.Compression; using System.Net; using System.Net.Sockets; using System.Text; -using System.Text.RegularExpressions; namespace Shadowsocks.Controller { class PACServer { private static int PORT = 8093; - private static string PAC_FILE = "pac.txt"; + public static string PAC_FILE = "pac.txt"; private static Configuration config; Socket _listener; @@ -23,10 +23,6 @@ namespace Shadowsocks.Controller public event EventHandler PACFileChanged; - public event EventHandler UpdatePACFromGFWListCompleted; - - public event ErrorEventHandler UpdatePACFromGFWListError; - public void Start(Configuration configuration) { try @@ -135,19 +131,7 @@ namespace Shadowsocks.Controller } else { - byte[] pacGZ = Resources.proxy_pac_txt; - byte[] buffer = new byte[1024]; // builtin pac gzip size: maximum 100K - MemoryStream sb = new MemoryStream(); - int n; - using (GZipStream input = new GZipStream(new MemoryStream(pacGZ), - CompressionMode.Decompress, false)) - { - while ((n = input.Read(buffer, 0, buffer.Length)) > 0) - { - sb.Write(buffer, 0, n); - } - return System.Text.Encoding.UTF8.GetString(sb.ToArray()); - } + return Utils.UnGzip(Resources.proxy_pac_txt); } } @@ -180,7 +164,7 @@ Connection: Close ", System.Text.Encoding.UTF8.GetBytes(pac).Length) + pac; byte[] response = System.Text.Encoding.UTF8.GetBytes(text); conn.BeginSend(response, 0, response.Length, 0, new AsyncCallback(SendCallback), conn); - Util.Util.ReleaseMemory(); + Util.Utils.ReleaseMemory(); } else { @@ -247,117 +231,5 @@ Connection: Close //} return proxy; } - - public void UpdatePACFromGFWList() - { - GfwListUpdater gfwlist = new GfwListUpdater(); - gfwlist.DownloadCompleted += gfwlist_DownloadCompleted; - gfwlist.Error += gfwlist_Error; - gfwlist.proxy = new WebProxy(IPAddress.Loopback.ToString(), 8123); /* use polipo proxy*/ - gfwlist.Download(); - } - - private void gfwlist_DownloadCompleted(object sender, GfwListUpdater.GfwListDownloadCompletedArgs e) - { - GfwListUpdater.Parser parser = new GfwListUpdater.Parser(e.Content); - string[] lines = parser.GetValidLines(); - StringBuilder rules = new StringBuilder(lines.Length * 16); - SerializeRules(lines, rules); - string abpContent = GetAbpContent(); - abpContent = abpContent.Replace("__RULES__", rules.ToString()); - File.WriteAllText(PAC_FILE, abpContent, Encoding.UTF8); - if (UpdatePACFromGFWListCompleted != null) - { - UpdatePACFromGFWListCompleted(this, new EventArgs()); - } - } - - private void gfwlist_Error(object sender, ErrorEventArgs e) - { - if (UpdatePACFromGFWListError != null) - { - UpdatePACFromGFWListError(this, e); - } - } - - private string GetAbpContent() - { - string content; - if (File.Exists(PAC_FILE)) - { - content = File.ReadAllText(PAC_FILE, Encoding.UTF8); - Regex regex = new Regex("var\\s+rules\\s*=\\s*(\\[(\\s*\"[^\"]*\"\\s*,)*(\\s*\"[^\"]*\")\\s*\\])", RegexOptions.Singleline); - Match m = regex.Match(content); - if (m.Success) - { - content = regex.Replace(content, "var rules = __RULES__"); - return content; - } - } - byte[] abpGZ = Resources.abp_js; - byte[] buffer = new byte[1024]; // builtin pac gzip size: maximum 100K - int n; - using (MemoryStream sb = new MemoryStream()) - { - using (GZipStream input = new GZipStream(new MemoryStream(abpGZ), - CompressionMode.Decompress, false)) - { - while ((n = input.Read(buffer, 0, buffer.Length)) > 0) - { - sb.Write(buffer, 0, n); - } - } - content = System.Text.Encoding.UTF8.GetString(sb.ToArray()); - } - return content; - } - - private static void SerializeRules(string[] rules, StringBuilder builder) - { - builder.Append("[\n"); - - bool first = true; - foreach (string rule in rules) - { - if (!first) - builder.Append(",\n"); - - SerializeString(rule, builder); - - first = false; - } - - builder.Append("\n]"); - } - - private static void SerializeString(string aString, StringBuilder builder) - { - builder.Append("\t\""); - - char[] charArray = aString.ToCharArray(); - for (int i = 0; i < charArray.Length; i++) - { - char c = charArray[i]; - if (c == '"') - builder.Append("\\\""); - else if (c == '\\') - builder.Append("\\\\"); - else if (c == '\b') - builder.Append("\\b"); - else if (c == '\f') - builder.Append("\\f"); - else if (c == '\n') - builder.Append("\\n"); - else if (c == '\r') - builder.Append("\\r"); - else if (c == '\t') - builder.Append("\\t"); - else - builder.Append(c); - } - - builder.Append("\""); - } - } } diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index 2610bbab..1e193158 100755 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -21,6 +21,7 @@ namespace Shadowsocks.Controller private PACServer pacServer; private Configuration _config; private PolipoRunner polipoRunner; + private GFWListUpdater gfwListUpdater; private bool stopped = false; private bool _systemProxyIsDirty = false; @@ -157,13 +158,9 @@ namespace Shadowsocks.Controller public void UpdatePACFromGFWList() { - if (pacServer != null) + if (gfwListUpdater != null) { - pacServer.UpdatePACFromGFWList(); - } - else if (UpdatePACFromGFWListError != null) - { - UpdatePACFromGFWListError(this, new ErrorEventArgs(new Exception("The PACServer is not run."))); + gfwListUpdater.UpdatePACFromGFWList(); } } @@ -180,8 +177,12 @@ namespace Shadowsocks.Controller { pacServer = new PACServer(); pacServer.PACFileChanged += pacServer_PACFileChanged; - pacServer.UpdatePACFromGFWListCompleted += pacServer_UpdatePACFromGFWListCompleted; - pacServer.UpdatePACFromGFWListError += pacServer_UpdatePACFromGFWListError; + } + if (gfwListUpdater == null) + { + gfwListUpdater = new GFWListUpdater(); + gfwListUpdater.UpdateCompleted += pacServer_PACUpdateCompleted; + gfwListUpdater.Error += pacServer_PACUpdateError; } pacServer.Stop(); @@ -226,7 +227,7 @@ namespace Shadowsocks.Controller } UpdateSystemProxy(); - Util.Util.ReleaseMemory(); + Util.Utils.ReleaseMemory(); } @@ -260,13 +261,13 @@ namespace Shadowsocks.Controller UpdateSystemProxy(); } - private void pacServer_UpdatePACFromGFWListCompleted(object sender, EventArgs e) + private void pacServer_PACUpdateCompleted(object sender, EventArgs e) { if (UpdatePACFromGFWListCompleted != null) UpdatePACFromGFWListCompleted(this, e); } - private void pacServer_UpdatePACFromGFWListError(object sender, ErrorEventArgs e) + private void pacServer_PACUpdateError(object sender, ErrorEventArgs e) { if (UpdatePACFromGFWListError != null) UpdatePACFromGFWListError(this, e); @@ -283,7 +284,7 @@ namespace Shadowsocks.Controller { while (true) { - Util.Util.ReleaseMemory(); + Util.Utils.ReleaseMemory(); Thread.Sleep(30 * 1000); } } diff --git a/shadowsocks-csharp/Data/abp.js.gz b/shadowsocks-csharp/Data/abp.js.gz old mode 100644 new mode 100755 index d265cfd6..e049c0a4 Binary files a/shadowsocks-csharp/Data/abp.js.gz and b/shadowsocks-csharp/Data/abp.js.gz differ diff --git a/shadowsocks-csharp/Data/cn.txt b/shadowsocks-csharp/Data/cn.txt index f67af0d2..9f8c6da1 100644 --- a/shadowsocks-csharp/Data/cn.txt +++ b/shadowsocks-csharp/Data/cn.txt @@ -39,6 +39,6 @@ Shadowsocks is here=Shadowsocks 在这里 You can turn on/off Shadowsocks in the context menu=可以在右键菜单中开关 Shadowsocks Enabled=已启用代理 Disabled=已禁用代理 -Update PAC File via GFWList...=从 GFWList 更新 PAC 文件... +Update PAC from GFWList=从 GFWList 更新 PAC Failed to update PAC file =更新 PAC 文件失败 PAC updated=更新 PAC 成功 diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs index 716e0df7..8ca485d7 100755 --- a/shadowsocks-csharp/Program.cs +++ b/shadowsocks-csharp/Program.cs @@ -18,7 +18,7 @@ namespace Shadowsocks [STAThread] static void Main() { - Util.Util.ReleaseMemory(); + Util.Utils.ReleaseMemory(); using (Mutex mutex = new Mutex(false, "Global\\" + "71981632-A427-497F-AB91-241CD227EC1F")) { Application.EnableVisualStyles(); diff --git a/shadowsocks-csharp/Util/Util.cs b/shadowsocks-csharp/Util/Util.cs index afb5539a..15463a3a 100755 --- a/shadowsocks-csharp/Util/Util.cs +++ b/shadowsocks-csharp/Util/Util.cs @@ -1,12 +1,14 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; +using System.IO.Compression; using System.Runtime.InteropServices; using System.Text; namespace Shadowsocks.Util { - public class Util + public class Utils { public static void ReleaseMemory() { @@ -22,6 +24,24 @@ namespace Shadowsocks.Util (UIntPtr)0xFFFFFFFF, (UIntPtr)0xFFFFFFFF); } + public static string UnGzip(byte[] buf) + { + byte[] buffer = new byte[1024]; + int n; + using (MemoryStream sb = new MemoryStream()) + { + using (GZipStream input = new GZipStream(new MemoryStream(buf), + CompressionMode.Decompress, false)) + { + while ((n = input.Read(buffer, 0, buffer.Length)) > 0) + { + sb.Write(buffer, 0, n); + } + } + return System.Text.Encoding.UTF8.GetString(sb.ToArray()); + } + } + [DllImport("kernel32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool SetProcessWorkingSetSize(IntPtr process, diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 1ab517f9..76da6036 100755 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -141,7 +141,7 @@ namespace Shadowsocks.View this.AutoStartupItem = CreateMenuItem("Start on Boot", new EventHandler(this.AutoStartupItem_Click)), this.ShareOverLANItem = CreateMenuItem("Share over LAN", new EventHandler(this.ShareOverLANItem_Click)), CreateMenuItem("Edit PAC File...", new EventHandler(this.EditPACFileItem_Click)), - CreateMenuItem("Update PAC File via gfwlist...", new EventHandler(this.UpdatePACFromGFWListItem_Click)), + CreateMenuItem("Update PAC from GFWList", new EventHandler(this.UpdatePACFromGFWListItem_Click)), new MenuItem("-"), CreateMenuItem("Show QRCode...", new EventHandler(this.QRCodeItem_Click)), CreateMenuItem("Show Logs...", new EventHandler(this.ShowLogItem_Click)), @@ -265,7 +265,7 @@ namespace Shadowsocks.View void configForm_FormClosed(object sender, FormClosedEventArgs e) { configForm = null; - Util.Util.ReleaseMemory(); + Util.Utils.ReleaseMemory(); ShowFirstTimeBalloon(); } diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 1848edd9..d14d7287 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -86,7 +86,7 @@ - +