Browse Source

Merge branch 'feature/gfwlist2pac' into develop

pull/220/head^2
everyx 10 years ago
parent
commit
4f5115107e
11 changed files with 249 additions and 51 deletions
  1. +1
    -1
      .gitignore
  2. +146
    -18
      shadowsocks-csharp/Controller/GfwListUpdater.cs
  3. +10
    -0
      shadowsocks-csharp/Controller/ShadowsocksController.cs
  4. BIN
      shadowsocks-csharp/Data/builtin.txt.gz
  5. +2
    -0
      shadowsocks-csharp/Data/cn.txt
  6. BIN
      shadowsocks-csharp/Data/proxy.pac.gz
  7. +1
    -0
      shadowsocks-csharp/Model/Configuration.cs
  8. +44
    -28
      shadowsocks-csharp/Properties/Resources.Designer.cs
  9. +9
    -3
      shadowsocks-csharp/Properties/Resources.resx
  10. +31
    -0
      shadowsocks-csharp/View/MenuViewController.cs
  11. +5
    -1
      shadowsocks-csharp/shadowsocks-csharp.csproj

+ 1
- 1
.gitignore View File

@@ -4,4 +4,4 @@ obj/
shadowsocks-csharp/shadowsocks-csharp.csproj.user
TestResults
*.suo
*Thumbs.db

+ 146
- 18
shadowsocks-csharp/Controller/GfwListUpdater.cs View File

@@ -7,6 +7,8 @@ using Shadowsocks.Properties;
using SimpleJson;
using Shadowsocks.Util;
using Shadowsocks.Model;
using System.Linq;
using System.Text.RegularExpressions;
namespace Shadowsocks.Controller
{
@@ -32,34 +34,20 @@ namespace Shadowsocks.Controller
}
}
private void http_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
private void savePacFile(string pacContent)
{
try
{
List<string> lines = ParseResult(e.Result);
if (File.Exists(USER_RULE_FILE))
{
string local = File.ReadAllText(USER_RULE_FILE, Encoding.UTF8);
string[] rules = local.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
foreach(string rule in rules)
{
if (rule.StartsWith("!") || rule.StartsWith("["))
continue;
lines.Add(rule);
}
}
string abpContent = Utils.UnGzip(Resources.abp_js);
abpContent = abpContent.Replace("__RULES__", SimpleJson.SimpleJson.SerializeObject(lines));
if (File.Exists(PAC_FILE))
{
string original = File.ReadAllText(PAC_FILE, Encoding.UTF8);
if (original == abpContent)
if (original == pacContent)
{
UpdateCompleted(this, new ResultEventArgs(false));
return;
}
}
File.WriteAllText(PAC_FILE, abpContent, Encoding.UTF8);
File.WriteAllText(PAC_FILE, pacContent, Encoding.UTF8);
if (UpdateCompleted != null)
{
UpdateCompleted(this, new ResultEventArgs(true));
@@ -74,12 +62,152 @@ namespace Shadowsocks.Controller
}
}
private string getHostname(string domain)
{
string host = null;
if (!(domain.StartsWith("http:") || domain.StartsWith("https:")))
domain = "http://" + domain;
Uri hostUri;
if (Uri.TryCreate(domain, UriKind.Absolute, out hostUri))
host = hostUri.Host;
return host;
}
private void addDomainToList(List<string> list, string domain)
{
string hostname = getHostname(domain);
if (hostname != null)
list.Add(hostname);
}
private List<string> parseGfwlist(List<string> lines)
{
List<string> domains = new List<string>();
lines.ForEach(delegate(string line)
{
if (line.StartsWith("@@") || line.StartsWith("/") || Regex.IsMatch(line, "^(\\d+\\.){3}\\d+$") || !line.Contains("."))
return;
if (line.Contains("//*"))
line = line.Replace("//*", "//");
else if (line.Contains("*/") || line.Contains("*."))
line = line.Replace("*", "");
else if (line.Contains("*"))
line = line.Replace("*", "/");
if (line.StartsWith("|"))
line = line.TrimStart('|');
else if (line.StartsWith("."))
line = line.TrimStart('.');
addDomainToList(domains, line);
});
return domains;
}
private List<string> reduceDomains(List<string> domains)
{
HashSet<string> uniDomains = new HashSet<string>();
foreach (var domain in domains)
{
var domainParts = domain.Split('.');
bool isContainRootDomain = false;
for (var i = 0; i <= domainParts.Length - 2; i++)
{
var domainPartsArray = new ArraySegment<string>(domainParts, domainParts.Length - i - 2, i + 2);
var rootDomain = string.Join(".", domainPartsArray);
if (domains.Contains(rootDomain))
{
uniDomains.Add(rootDomain);
isContainRootDomain = true;
break;
}
}
if (!isContainRootDomain)
uniDomains.Add(domain);
}
return uniDomains.ToList();
}
private void generatePacFast(List<string> lines)
{
List<string> domains = parseGfwlist(lines);
domains = reduceDomains(domains).Distinct().ToList();
var fastContent = Utils.UnGzip(Resources.proxy_pac);
var domainsJsonStr = "{\n " +
string.Join(",\n ", domains.Select(d=>string.Format("\"{0}\": 1", d))) +
"\n}";
fastContent = fastContent.Replace("__DOMAINS__", domainsJsonStr);
savePacFile(fastContent);
}
private void generatePacPrecise(List<string> lines)
{
string abpContent = Utils.UnGzip(Resources.abp_js);
abpContent = abpContent.Replace("__RULES__", SimpleJson.SimpleJson.SerializeObject(lines));
savePacFile(abpContent);
}
private void parsePacStr(string pacStr, List<string> lines)
{
string[] rules = pacStr.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string rule in rules)
{
if (rule.StartsWith("!") || rule.StartsWith("["))
continue;
lines.Add(rule);
}
}
private void http_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
try
{
List<string> lines = ParseResult(e.Result);
string local = "";
if (File.Exists(USER_RULE_FILE))
{
local = File.ReadAllText(USER_RULE_FILE, Encoding.UTF8);
}
bool usePreciseMode = (bool) e.UserState;
if (!usePreciseMode)
{
local += Utils.UnGzip(Resources.builtin_txt);
}
parsePacStr(local, lines);
if (usePreciseMode)
{
generatePacPrecise(lines);
}
else
{
generatePacFast(lines);
}
}
catch (Exception ex)
{
if (Error != null)
{
Error(this, new ErrorEventArgs(ex));
}
}
}
public void UpdatePACFromGFWList(Configuration config)
{
WebClient http = new WebClient();
http.Proxy = new WebProxy(IPAddress.Loopback.ToString(), config.localPort);
http.DownloadStringCompleted += http_DownloadStringCompleted;
http.DownloadStringAsync(new Uri(GFWLIST_URL));
http.DownloadStringAsync(new Uri(GFWLIST_URL), config.usePreciseMode);
}
public List<string> ParseResult(string response)


+ 10
- 0
shadowsocks-csharp/Controller/ShadowsocksController.cs View File

@@ -214,6 +214,16 @@ namespace Shadowsocks.Controller
}
}
public void UsePreciseMode(bool usePreciseMode)
{
_config.usePreciseMode = usePreciseMode;
SaveConfig(_config);
if (ConfigChanged != null)
{
ConfigChanged(this, new EventArgs());
}
}
protected void Reload()
{
// some logic in configuration updated the config when saving, we need to read it again


BIN
shadowsocks-csharp/Data/builtin.txt.gz View File


+ 2
- 0
shadowsocks-csharp/Data/cn.txt View File

@@ -14,6 +14,8 @@ Start on Boot=开机启动
Allow Clients from LAN=允许来自局域网的连接
Local PAC=使用本地 PAC
Online PAC=使用在线 PAC
Fast Mode=快速模式
Precise Mode=精确模式
Edit Local PAC File...=编辑本地 PAC 文件...
Update Local PAC from GFWList=从 GFWList 更新本地 PAC
Edit User Rule for GFWList...=编辑 GFWList 的用户规则...


BIN
shadowsocks-csharp/Data/proxy.pac.gz View File


+ 1
- 0
shadowsocks-csharp/Model/Configuration.cs View File

@@ -19,6 +19,7 @@ namespace Shadowsocks.Model
public int localPort;
public string pacUrl;
public bool useOnlinePac;
public bool usePreciseMode;
private static string CONFIG_FILE = "gui-config.json";


+ 44
- 28
shadowsocks-csharp/Properties/Resources.Designer.cs View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.34209
// Runtime Version:4.0.30319.34014
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -71,33 +71,39 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized string similar to Shadowsocks=Shadowsocks
///Enable System Proxy=启用系统代理
///Mode=系统代理模式
///PAC=PAC 模式
///Global=全局模式
///Servers=服务器
///Edit Servers...=编辑服务器...
///Start on Boot=开机启动
///Allow Clients from LAN=允许来自局域网的连接
///Edit PAC File...=编辑 PAC 文件...
///Edit User Rule for GFWList...=编辑 GFWList 的用户规则...
///Show QRCode...=显示二维码...
///Scan QRCode from Screen...=扫描屏幕上的二维码...
///Show Logs...=显示日志...
///About...=关于...
///Quit=退出
///Edit Servers=编辑服务器
///&amp;Add=添加(&amp;A)
///&amp;Delete=删除(&amp;D)
///Server=服务器
///Server IP=服务器 IP
///Server Port=服务器端口
///Password=密码
///Encryption=加密
///Proxy Port=代理端口
///Remarks=备注
///OK= [rest of string was truncated]&quot;;.
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] builtin_txt {
get {
object obj = ResourceManager.GetObject("builtin_txt", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized string similar to # translation for Simplified Chinese
///
///Shadowsocks=Shadowsocks
///
///# Menu items
///
///Enable System Proxy=启用系统代理
///Mode=系统代理模式
///PAC=PAC 模式
///Global=全局模式
///Servers=服务器
///Edit Servers...=编辑服务器...
///Start on Boot=开机启动
///Allow Clients from LAN=允许来自局域网的连接
///Local PAC=使用本地 PAC
///Online PAC=使用在线 PAC
///Fast Mode=快速模式
///Precise Mode=精确模式
///Edit Local PAC File...=编辑本地 PAC 文件...
///Update Local PAC from GFWList=从 GFWList 更新本地 PAC
///Edit User Rule for GFWList...=编辑 GFWList 的用户规则...
///Show QRCode...=显示二维码...
///Scan QRCode from Screen...=扫 [rest of string was truncated]&quot;;.
/// </summary>
internal static string cn {
get {
@@ -146,6 +152,16 @@ namespace Shadowsocks.Properties {
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] proxy_pac {
get {
object obj = ResourceManager.GetObject("proxy_pac", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] proxy_pac_txt {
get {
object obj = ResourceManager.GetObject("proxy_pac_txt", resourceCulture);


+ 9
- 3
shadowsocks-csharp/Properties/Resources.resx View File

@@ -112,15 +112,18 @@
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="abp_js" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Data\abp.js.gz;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="builtin_txt" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Data\builtin.txt.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="cn" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\data\cn.txt;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
@@ -133,6 +136,9 @@
<data name="polipo_exe" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Data\polipo.exe.gz;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="proxy_pac" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Data\proxy.pac.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="proxy_pac_txt" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Data\proxy.pac.txt.gz;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>


+ 31
- 0
shadowsocks-csharp/View/MenuViewController.cs View File

@@ -37,6 +37,8 @@ namespace Shadowsocks.View
private MenuItem PACModeItem;
private MenuItem localPACItem;
private MenuItem onlinePACItem;
private MenuItem fastModeItem;
private MenuItem preciseModeItem;
private MenuItem editLocalPACItem;
private MenuItem updateFromGFWListItem;
private MenuItem editGFWUserRuleItem;
@@ -161,6 +163,9 @@ namespace Shadowsocks.View
this.localPACItem = CreateMenuItem("Local PAC", new EventHandler(this.LocalPACItem_Click)),
this.onlinePACItem = CreateMenuItem("Online PAC", new EventHandler(this.OnlinePACItem_Click)),
new MenuItem("-"),
this.fastModeItem = CreateMenuItem("Fast Mode", new EventHandler(this.fastModeItem_Click)),
this.preciseModeItem = CreateMenuItem("Precise Mode", new EventHandler(this.preciseModeItem_Click)),
new MenuItem("-"),
this.editLocalPACItem = CreateMenuItem("Edit Local PAC File...", new EventHandler(this.EditPACFileItem_Click)),
this.updateFromGFWListItem = CreateMenuItem("Update Local PAC from GFWList", new EventHandler(this.UpdatePACFromGFWListItem_Click)),
this.editGFWUserRuleItem = CreateMenuItem("Edit User Rule for GFWList...", new EventHandler(this.EditUserRuleFileForGFWListItem_Click)),
@@ -253,6 +258,8 @@ namespace Shadowsocks.View
AutoStartupItem.Checked = AutoStartup.Check();
onlinePACItem.Checked = onlinePACItem.Enabled && config.useOnlinePac;
localPACItem.Checked = !onlinePACItem.Checked;
fastModeItem.Checked = !config.usePreciseMode;
preciseModeItem.Checked = config.usePreciseMode;
UpdatePACItemsEnabledStatus();
}
@@ -525,6 +532,26 @@ namespace Shadowsocks.View
}
}
private void fastModeItem_Click(object sender, EventArgs e)
{
if (!fastModeItem.Checked)
{
fastModeItem.Checked = true;
preciseModeItem.Checked = false;
controller.UsePreciseMode(false);
}
}
private void preciseModeItem_Click(object sender, EventArgs e)
{
if (!preciseModeItem.Checked)
{
fastModeItem.Checked = false;
preciseModeItem.Checked = true;
controller.UsePreciseMode(true);
}
}
private void UpdateOnlinePACURLItem_Click(object sender, EventArgs e)
{
string origPacUrl = controller.GetConfiguration().pacUrl;
@@ -544,6 +571,8 @@ namespace Shadowsocks.View
{
this.editLocalPACItem.Enabled = true;
this.updateFromGFWListItem.Enabled = true;
this.fastModeItem.Enabled = true;
this.preciseModeItem.Enabled = true;
this.editGFWUserRuleItem.Enabled = true;
this.editOnlinePACItem.Enabled = false;
}
@@ -551,6 +580,8 @@ namespace Shadowsocks.View
{
this.editLocalPACItem.Enabled = false;
this.updateFromGFWListItem.Enabled = false;
this.fastModeItem.Enabled = false;
this.preciseModeItem.Enabled = false;
this.editGFWUserRuleItem.Enabled = false;
this.editOnlinePACItem.Enabled = true;
}


+ 5
- 1
shadowsocks-csharp/shadowsocks-csharp.csproj View File

@@ -10,7 +10,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Shadowsocks</RootNamespace>
<AssemblyName>Shadowsocks</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<StartupObject>
</StartupObject>
@@ -189,11 +189,15 @@
<SubType>Designer</SubType>
</None>
<None Include="Data\abp.js.gz" />
<None Include="Data\builtin.txt.gz" />
<None Include="Data\libsscrypto.dll.gz" />
<None Include="Data\polipo.exe.gz" />
<None Include="Data\proxy.pac.gz" />
<None Include="Data\proxy.pac.txt.gz" />
</ItemGroup>
<ItemGroup>
<None Include="Data\tld.txt.gz" />
<None Include="Resources\proxy.pac.gz" />
<None Include="Resources\ss20.png" />
<None Include="Resources\ss16.png" />
<None Include="Resources\ss24.png" />


Loading…
Cancel
Save