diff --git a/Netch/Controllers/HTTPController.cs b/Netch/Controllers/HTTPController.cs index a4c774fc..bce820ae 100644 --- a/Netch/Controllers/HTTPController.cs +++ b/Netch/Controllers/HTTPController.cs @@ -6,6 +6,7 @@ using Microsoft.Win32; using Netch.Models; using Netch.Utils; using WindowsProxy; +using Netch.Utils.HttpProxyHandler; namespace Netch.Controllers { @@ -36,7 +37,23 @@ namespace Netch.Controllers Global.Job.AddProcess(pPrivoxyController.Instance); } - //if (mode.Type == 3) NativeMethods.SetGlobal($"127.0.0.1:{Global.Settings.HTTPLocalPort}", IEProxyExceptions); + if (mode.Type == 3) + { + if (mode.BypassChina) + { + //启动PAC服务器 + PACServerHandle.InitPACServer("127.0.0.1"); + } + else + { + using var service = new ProxyService + { + Server = $"127.0.0.1:{Global.Settings.HTTPLocalPort}", + Bypass = IEProxyExceptions + }; + service.Global(); + } + } } catch (Exception e) { @@ -88,6 +105,7 @@ namespace Netch.Controllers Task.Factory.StartNew(pPrivoxyController.Stop), Task.Factory.StartNew(() => { + PACServerHandle.Stop(); if (prevEnabled) { if (prevHTTP != "") @@ -97,6 +115,7 @@ namespace Netch.Controllers Server = prevHTTP, Bypass = prevBypass }; + service.Global(); } if (prevPAC != "") { diff --git a/Netch/Controllers/PrivoxyController.cs b/Netch/Controllers/PrivoxyController.cs index 8b2de3b4..d43c053b 100644 --- a/Netch/Controllers/PrivoxyController.cs +++ b/Netch/Controllers/PrivoxyController.cs @@ -35,15 +35,11 @@ namespace Netch.Controllers File.WriteAllText("data\\privoxy.conf", text.ToString()); - //启动PAC服务器 - PACServerHandle.InitPACServer("127.0.0.1"); - return StartInstanceAuto("..\\data\\privoxy.conf"); } public override void Stop() { - PACServerHandle.Stop(); StopInstance(); } } diff --git a/Netch/Forms/MainForm.Designer.cs b/Netch/Forms/MainForm.Designer.cs index 7decdcb6..888ef85d 100644 --- a/Netch/Forms/MainForm.Designer.cs +++ b/Netch/Forms/MainForm.Designer.cs @@ -87,6 +87,7 @@ this.ProfileTable = new System.Windows.Forms.TableLayoutPanel(); this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); this.ButtomControlContainerControl = new System.Windows.Forms.ContainerControl(); + this.updatePACToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.MenuStrip.SuspendLayout(); this.ConfigurationGroupBox.SuspendLayout(); this.configLayoutPanel.SuspendLayout(); @@ -196,6 +197,7 @@ this.CleanDNSCacheToolStripMenuItem, this.UpdateACLToolStripMenuItem, this.updateACLWithProxyToolStripMenuItem, + this.updatePACToolStripMenuItem, this.UninstallServiceToolStripMenuItem, this.UninstallTapDriverToolStripMenuItem}); this.OptionsToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1); @@ -697,6 +699,13 @@ this.ButtomControlContainerControl.TabStop = false; this.ButtomControlContainerControl.Text = "groupBox1"; // + // updatePACToolStripMenuItem + // + this.updatePACToolStripMenuItem.Name = "updatePACToolStripMenuItem"; + this.updatePACToolStripMenuItem.Size = new System.Drawing.Size(220, 22); + this.updatePACToolStripMenuItem.Text = "Update PAC"; + this.updatePACToolStripMenuItem.Click += new System.EventHandler(this.updatePACToolStripMenuItem_Click); + // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); @@ -803,5 +812,6 @@ private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; private System.Windows.Forms.ContainerControl ButtomControlContainerControl; + private System.Windows.Forms.ToolStripMenuItem updatePACToolStripMenuItem; } } \ No newline at end of file diff --git a/Netch/Forms/MainForm.MenuStrip.cs b/Netch/Forms/MainForm.MenuStrip.cs index 9cb1660e..bb5a4ef5 100644 --- a/Netch/Forms/MainForm.MenuStrip.cs +++ b/Netch/Forms/MainForm.MenuStrip.cs @@ -3,12 +3,16 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; +using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Netch.Controllers; using Netch.Forms.Mode; using Netch.Models; +using Netch.Properties; using Netch.Utils; +using Netch.Utils.HttpProxyHandler; +using Newtonsoft.Json; namespace Netch.Forms { @@ -274,6 +278,39 @@ namespace Netch.Forms } } + private async void updatePACToolStripMenuItem_Click(object sender, EventArgs eventArgs) + { + Enabled = false; + + NotifyTip(i18N.Translate("Updating in the background")); + try + { + var req = WebUtil.CreateRequest(Global.Settings.GFWLIST); + + string gfwlist = Path.Combine(Global.NetchDir, $"bin\\gfwlist"); + string pac = Path.Combine(Global.NetchDir, $"bin\\pac.txt"); + + await WebUtil.DownloadFileAsync(req, gfwlist); + + var gfwContent = File.ReadAllText(gfwlist); + List lines = PACUtil.ParseResult(gfwContent); + string abpContent = PACUtil.UnGzip(Resources.abp_js); + abpContent = abpContent.Replace("__RULES__", JsonConvert.SerializeObject(lines, Formatting.Indented)); + File.WriteAllText(pac, abpContent, Encoding.UTF8); + + NotifyTip(i18N.Translate("PAC updated successfully")); + } + catch (Exception e) + { + NotifyTip(i18N.Translate("PAC update failed") + "\n" + e.Message, info: false); + Logging.Error("更新 PAC 失败!" + e); + } + finally + { + Enabled = true; + } + } + private async void UninstallServiceToolStripMenuItem_Click(object sender, EventArgs e) { Enabled = false; diff --git a/Netch/Models/Setting.cs b/Netch/Models/Setting.cs index 0ba2c1a2..ad08da51 100644 --- a/Netch/Models/Setting.cs +++ b/Netch/Models/Setting.cs @@ -250,6 +250,11 @@ namespace Netch.Models /// public string ACL = "https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/banAD.acl"; + /// + /// GFWList + /// + public string GFWLIST = "https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt"; + /// /// 是否使用DLL启动Shadowsocks /// diff --git a/Netch/Properties/Resources.Designer.cs b/Netch/Properties/Resources.Designer.cs index 4917d0c3..432c445e 100644 --- a/Netch/Properties/Resources.Designer.cs +++ b/Netch/Properties/Resources.Designer.cs @@ -60,6 +60,16 @@ namespace Netch.Properties { } } + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] abp_js { + get { + object obj = ResourceManager.GetObject("abp_js", resourceCulture); + return ((byte[])(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/Netch/Properties/Resources.resx b/Netch/Properties/Resources.resx index 79ba3a16..ed8ebd4e 100644 --- a/Netch/Properties/Resources.resx +++ b/Netch/Properties/Resources.resx @@ -1,145 +1,172 @@  - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, + PublicKeyToken=b77a5c561934e089 + + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, + PublicKeyToken=b77a5c561934e089 + + + + + ..\Resources\defaultTUNTAP;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, + PublicKeyToken=b77a5c561934e089 + - - [base64 mime encoded string representing a byte array form of the .NET Framework object] - This is a comment + + ..\Resources\zh-CN;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, + PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\speed.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, + PublicKeyToken=b03f5f7f11d50a3a + + + + ..\Resources\delete.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, + PublicKeyToken=b03f5f7f11d50a3a + + + + ..\Resources\edit.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, + PublicKeyToken=b03f5f7f11d50a3a + + + + ..\Resources\Netch.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, + PublicKeyToken=b03f5f7f11d50a3a + + + + ..\Resources\Sponsor.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, + PublicKeyToken=b03f5f7f11d50a3a + + + + ..\Resources\CopyLink.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, + PublicKeyToken=b03f5f7f11d50a3a + + + + ..\Resources\abp.js.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, + PublicKeyToken=b03f5f7f11d50a3a + - - There are any number of "resheader" rows that contain simple - name/value pairs. - - Each data row contains a name, and value. The row also contains a - type or mimetype. Type corresponds to a .NET class that support - text/value conversion through the TypeConverter architecture. - Classes that don't support this are serialized and stored with the - mimetype set. - - The mimetype is used for serialized objects, and tells the - ResXResourceReader how to depersist the object. This is currently not - extensible. For a given mimetype the value must be set accordingly: - - Note - application/x-microsoft.net.object.binary.base64 is the format - that the ResXResourceWriter will generate, however the reader can - read any of the formats listed below. - - mimetype: application/x-microsoft.net.object.binary.base64 - value : The object must be serialized with - : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter - : and then encoded with base64 encoding. - - mimetype: application/x-microsoft.net.object.soap.base64 - value : The object must be serialized with - : System.Runtime.Serialization.Formatters.Soap.SoapFormatter - : and then encoded with base64 encoding. - - mimetype: application/x-microsoft.net.object.bytearray.base64 - value : The object must be serialized into a byte array - : using a System.ComponentModel.TypeConverter - : and then encoded with base64 encoding. - --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - ..\Resources\defaultTUNTAP;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\zh-CN;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\speed.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\delete.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\edit.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\Netch.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\Sponsor.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\CopyLink.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - \ No newline at end of file diff --git a/Netch/Resources/abp.js.gz b/Netch/Resources/abp.js.gz new file mode 100644 index 00000000..0577c7f5 Binary files /dev/null and b/Netch/Resources/abp.js.gz differ diff --git a/Netch/Resources/zh-CN b/Netch/Resources/zh-CN index b4d9f263..93a3af2a 100644 --- a/Netch/Resources/zh-CN +++ b/Netch/Resources/zh-CN @@ -81,10 +81,16 @@ "Modes have been reload": "模式已重载", "Clean DNS Cache": "清理 DNS 缓存", "DNS cache cleanup succeeded": "DNS 缓存清理成功", + + "Update PAC": "更新 PAC", + "PAC updated successfully": "PAC 更新成功", + "PAC update failed": "PAC 更新失败", + "Update ACL": "更新 ACL 规则", "Update ACL with proxy": "使用代理更新 ACL 规则", "ACL updated successfully": "ACL 更新成功", "ACL update failed": "ACL 更新失败", + "Open Directory": "打开目录", "About": "关于", diff --git a/Netch/Utils/HttpProxyHandler/HttpWebServer.cs b/Netch/Utils/HttpProxyHandler/HttpWebServer.cs index 5605faa7..23749580 100644 --- a/Netch/Utils/HttpProxyHandler/HttpWebServer.cs +++ b/Netch/Utils/HttpProxyHandler/HttpWebServer.cs @@ -34,7 +34,6 @@ namespace Netch.Utils.HttpProxyHandler _responderMethod = method; _listener.Start(); - } catch (Exception ex) { @@ -43,7 +42,9 @@ namespace Netch.Utils.HttpProxyHandler } public HttpWebServer(Func method, params string[] prefixes) - : this(prefixes, method) { } + : this(prefixes, method) + { + } public void Run() { @@ -68,7 +69,7 @@ namespace Netch.Utils.HttpProxyHandler } catch { - } // suppress any exceptions + } // suppress any exceptions finally { // always close the stream @@ -94,6 +95,5 @@ namespace Netch.Utils.HttpProxyHandler _listener = null; } } - } -} +} \ No newline at end of file diff --git a/Netch/Utils/HttpProxyHandler/PACListHandle.cs b/Netch/Utils/HttpProxyHandler/PACListHandle.cs deleted file mode 100644 index f8842e29..00000000 --- a/Netch/Utils/HttpProxyHandler/PACListHandle.cs +++ /dev/null @@ -1,75 +0,0 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Text; - -namespace Netch.Utils.HttpProxyHandler -{ - /// - /// 提供PAC功能支持 - /// - class PACListHandle - { - public event EventHandler UpdateCompleted; - - public class ResultEventArgs : EventArgs - { - public bool Success; - - public ResultEventArgs(bool success) - { - Success = success; - } - } - - private const string GFWLIST_URL = "https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt"; - - private static readonly IEnumerable IgnoredLineBegins = new[] { '!', '[' }; - - /// - /// 更新PAC文件(GFWList) - /// - //public void UpdatePACFromGFWList() - //{ - // WebClient http = new WebClient(); - // http.DownloadStringCompleted += http_DownloadStringCompleted; - // http.DownloadStringAsync(new Uri(GFWLIST_URL)); - //} - - //private void http_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) - //{ - // try - // { - // File.WriteAllText(NUtils.GetTempPath("gfwlist.txt"), e.Result, Encoding.UTF8); - // List lines = ParseResult(e.Result); - // string abpContent = NUtils.UnGzip(Resources.abp_js); - // abpContent = abpContent.Replace("__RULES__", JsonConvert.SerializeObject(lines, Formatting.Indented)); - // File.WriteAllText(NUtils.GetPath("pac.txt"), abpContent, Encoding.UTF8); - // if (UpdateCompleted != null) UpdateCompleted(this, new ResultEventArgs(true)); - // } - // catch (Exception ex) - // { - // Logging.Error("http_DownloadStringCompleted():" + ex.Message); - // } - //} - - //public static List ParseResult(string response) - //{ - // byte[] bytes = Convert.FromBase64String(response); - // string content = Encoding.ASCII.GetString(bytes); - // List valid_lines = new List(); - // using (var sr = new StringReader(content)) - // { - // foreach (var line in sr.NonWhiteSpaceLines()) - // { - // if (line.BeginWithAny(IgnoredLineBegins)) - // continue; - // valid_lines.Add(line); - // } - // } - // return valid_lines; - //} - } -} diff --git a/Netch/Utils/HttpProxyHandler/PACUtil.cs b/Netch/Utils/HttpProxyHandler/PACUtil.cs new file mode 100644 index 00000000..791dd601 --- /dev/null +++ b/Netch/Utils/HttpProxyHandler/PACUtil.cs @@ -0,0 +1,56 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Net; +using System.Text; +using Netch.Forms; +using Netch.Properties; + +namespace Netch.Utils.HttpProxyHandler +{ + /// + /// 提供PAC功能支持 + /// + class PACUtil + { + private static readonly IEnumerable IgnoredLineBegins = new[] {'!', '['}; + + public static List ParseResult(string response) + { + byte[] bytes = Convert.FromBase64String(response); + string content = Encoding.ASCII.GetString(bytes); + List valid_lines = new List(); + using (var sr = new StringReader(content)) + { + foreach (var line in sr.NonWhiteSpaceLines()) + { + if (line.BeginWithAny(IgnoredLineBegins)) + continue; + valid_lines.Add(line); + } + } + return valid_lines; + } + + 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()); + } + } + } +} \ No newline at end of file diff --git a/Netch/Utils/StringEx.cs b/Netch/Utils/StringEx.cs new file mode 100644 index 00000000..c655c9c0 --- /dev/null +++ b/Netch/Utils/StringEx.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Netch.Utils +{ + static class StringEx + { + public static bool IsNullOrEmpty(this string value) + { + return string.IsNullOrEmpty(value); + } + + public static bool IsNullOrWhiteSpace(this string value) + { + return string.IsNullOrWhiteSpace(value); + } + + public static bool BeginWithAny(this string s, IEnumerable chars) + { + if (s.IsNullOrEmpty()) return false; + return chars.Contains(s[0]); + } + + public static bool IsWhiteSpace(this string value) + { + foreach (var c in value) + { + if (char.IsWhiteSpace(c)) continue; + + return false; + } + return true; + } + + public static IEnumerable NonWhiteSpaceLines(this TextReader reader) + { + string line; + while ((line = reader.ReadLine()) != null) + { + if (line.IsWhiteSpace()) continue; + yield return line; + } + } + } +}