@@ -14,21 +14,22 @@ using System.Net; | |||||
namespace Shadowsocks.Controller | namespace Shadowsocks.Controller | ||||
{ | { | ||||
static class GeositeUpdater | |||||
public class GeositeResultEventArgs : EventArgs | |||||
{ | { | ||||
private static Logger logger = LogManager.GetCurrentClassLogger(); | |||||
public static event EventHandler<ResultEventArgs> UpdateCompleted; | |||||
public bool Success; | |||||
public class ResultEventArgs : EventArgs | |||||
public GeositeResultEventArgs(bool success) | |||||
{ | { | ||||
public bool Success; | |||||
public ResultEventArgs(bool success) | |||||
{ | |||||
this.Success = success; | |||||
} | |||||
this.Success = success; | |||||
} | } | ||||
} | |||||
public static class GeositeUpdater | |||||
{ | |||||
private static Logger logger = LogManager.GetCurrentClassLogger(); | |||||
public static event EventHandler<GeositeResultEventArgs> UpdateCompleted; | |||||
public static event ErrorEventHandler Error; | public static event ErrorEventHandler Error; | ||||
private static readonly string DATABASE_PATH = Utils.GetTempPath("dlc.dat"); | private static readonly string DATABASE_PATH = Utils.GetTempPath("dlc.dat"); | ||||
@@ -57,6 +58,12 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
} | } | ||||
public static void ResetEvent() | |||||
{ | |||||
UpdateCompleted = null; | |||||
Error = null; | |||||
} | |||||
public static void UpdatePACFromGeosite(Configuration config) | public static void UpdatePACFromGeosite(Configuration config) | ||||
{ | { | ||||
string gfwListUrl = GEOSITE_URL; | string gfwListUrl = GEOSITE_URL; | ||||
@@ -83,7 +90,7 @@ namespace Shadowsocks.Controller | |||||
LoadGeositeList(); | LoadGeositeList(); | ||||
bool pacFileChanged = MergeAndWritePACFile(); | bool pacFileChanged = MergeAndWritePACFile(); | ||||
UpdateCompleted?.Invoke(null, new ResultEventArgs(pacFileChanged)); | |||||
UpdateCompleted?.Invoke(null, new GeositeResultEventArgs(pacFileChanged)); | |||||
} | } | ||||
catch (Exception ex) | catch (Exception ex) | ||||
{ | { | ||||
@@ -1,137 +0,0 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.IO; | |||||
using System.Net; | |||||
using System.Text; | |||||
using Newtonsoft.Json; | |||||
using NLog; | |||||
using Shadowsocks.Model; | |||||
using Shadowsocks.Properties; | |||||
using Shadowsocks.Util; | |||||
namespace Shadowsocks.Controller | |||||
{ | |||||
public class GFWListUpdater | |||||
{ | |||||
private static Logger logger = LogManager.GetCurrentClassLogger(); | |||||
private const string GFWLIST_URL = "https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt"; | |||||
public event EventHandler<ResultEventArgs> UpdateCompleted; | |||||
public event ErrorEventHandler Error; | |||||
public class ResultEventArgs : EventArgs | |||||
{ | |||||
public bool Success; | |||||
public ResultEventArgs(bool success) | |||||
{ | |||||
this.Success = success; | |||||
} | |||||
} | |||||
private static readonly IEnumerable<char> IgnoredLineBegins = new[] { '!', '[' }; | |||||
private void http_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) | |||||
{ | |||||
try | |||||
{ | |||||
File.WriteAllText(Utils.GetTempPath("gfwlist.txt"), e.Result, Encoding.UTF8); | |||||
bool pacFileChanged = MergeAndWritePACFile(e.Result); | |||||
UpdateCompleted?.Invoke(this, new ResultEventArgs(pacFileChanged)); | |||||
} | |||||
catch (Exception ex) | |||||
{ | |||||
Error?.Invoke(this, new ErrorEventArgs(ex)); | |||||
} | |||||
} | |||||
public static bool MergeAndWritePACFile(string gfwListResult) | |||||
{ | |||||
string abpContent = MergePACFile(gfwListResult); | |||||
if (File.Exists(PACDaemon.PAC_FILE)) | |||||
{ | |||||
string original = FileManager.NonExclusiveReadAllText(PACDaemon.PAC_FILE, Encoding.UTF8); | |||||
if (original == abpContent) | |||||
{ | |||||
return false; | |||||
} | |||||
} | |||||
File.WriteAllText(PACDaemon.PAC_FILE, abpContent, Encoding.UTF8); | |||||
return true; | |||||
} | |||||
private static string MergePACFile(string gfwListResult) | |||||
{ | |||||
string abpContent; | |||||
if (File.Exists(PACDaemon.USER_ABP_FILE)) | |||||
{ | |||||
abpContent = FileManager.NonExclusiveReadAllText(PACDaemon.USER_ABP_FILE, Encoding.UTF8); | |||||
} | |||||
else | |||||
{ | |||||
abpContent = Resources.abp_js; | |||||
} | |||||
List<string> userruleLines = new List<string>(); | |||||
if (File.Exists(PACDaemon.USER_RULE_FILE)) | |||||
{ | |||||
string userrulesString = FileManager.NonExclusiveReadAllText(PACDaemon.USER_RULE_FILE, Encoding.UTF8); | |||||
userruleLines = ParseToValidList(userrulesString); | |||||
} | |||||
List<string> gfwLines = new List<string>(); | |||||
gfwLines = ParseBase64ToValidList(gfwListResult); | |||||
abpContent = | |||||
$@"var __USERRULES__ = {JsonConvert.SerializeObject(userruleLines, Formatting.Indented)}; | |||||
var __RULES__ = {JsonConvert.SerializeObject(gfwLines, Formatting.Indented)}; | |||||
{abpContent}"; | |||||
return abpContent; | |||||
} | |||||
public void UpdatePACFromGFWList(Configuration config) | |||||
{ | |||||
string gfwListUrl = GFWLIST_URL; | |||||
if (!string.IsNullOrWhiteSpace(config.gfwListUrl)) | |||||
{ | |||||
logger.Info("Found custom GFWListURL in config file"); | |||||
gfwListUrl = config.gfwListUrl; | |||||
} | |||||
logger.Info($"Checking GFWList from {gfwListUrl}"); | |||||
WebClient http = new WebClient(); | |||||
if (config.enabled) | |||||
{ | |||||
http.Proxy = new WebProxy( | |||||
config.isIPv6Enabled | |||||
? $"[{IPAddress.IPv6Loopback.ToString()}]" | |||||
: IPAddress.Loopback.ToString(), | |||||
config.localPort); | |||||
} | |||||
http.DownloadStringCompleted += http_DownloadStringCompleted; | |||||
http.DownloadStringAsync(new Uri(gfwListUrl)); | |||||
} | |||||
public static List<string> ParseBase64ToValidList(string response) | |||||
{ | |||||
byte[] bytes = Convert.FromBase64String(response); | |||||
string content = Encoding.ASCII.GetString(bytes); | |||||
return ParseToValidList(content); | |||||
} | |||||
private static List<string> ParseToValidList(string content) | |||||
{ | |||||
List<string> valid_lines = new List<string>(); | |||||
using (var sr = new StringReader(content)) | |||||
{ | |||||
foreach (var line in sr.NonWhiteSpaceLines()) | |||||
{ | |||||
if (line.BeginWithAny(IgnoredLineBegins)) | |||||
continue; | |||||
valid_lines.Add(line); | |||||
} | |||||
} | |||||
return valid_lines; | |||||
} | |||||
} | |||||
} |
@@ -35,7 +35,6 @@ namespace Shadowsocks.Controller | |||||
private Configuration _config; | private Configuration _config; | ||||
private StrategyManager _strategyManager; | private StrategyManager _strategyManager; | ||||
private PrivoxyRunner privoxyRunner; | private PrivoxyRunner privoxyRunner; | ||||
private GFWListUpdater gfwListUpdater; | |||||
private readonly ConcurrentDictionary<Server, Sip003Plugin> _pluginsByServer; | private readonly ConcurrentDictionary<Server, Sip003Plugin> _pluginsByServer; | ||||
public AvailabilityStatistics availabilityStatistics = AvailabilityStatistics.Instance; | public AvailabilityStatistics availabilityStatistics = AvailabilityStatistics.Instance; | ||||
@@ -80,7 +79,7 @@ namespace Shadowsocks.Controller | |||||
public event EventHandler<PathEventArgs> PACFileReadyToOpen; | public event EventHandler<PathEventArgs> PACFileReadyToOpen; | ||||
public event EventHandler<PathEventArgs> UserRuleFileReadyToOpen; | public event EventHandler<PathEventArgs> UserRuleFileReadyToOpen; | ||||
public event EventHandler<GFWListUpdater.ResultEventArgs> UpdatePACFromGFWListCompleted; | |||||
public event EventHandler<GeositeResultEventArgs> UpdatePACFromGFWListCompleted; | |||||
public event ErrorEventHandler UpdatePACFromGFWListError; | public event ErrorEventHandler UpdatePACFromGFWListError; | ||||
@@ -418,10 +417,7 @@ namespace Shadowsocks.Controller | |||||
public void UpdatePACFromGFWList() | public void UpdatePACFromGFWList() | ||||
{ | { | ||||
if (gfwListUpdater != null) | |||||
{ | |||||
gfwListUpdater.UpdatePACFromGFWList(_config); | |||||
} | |||||
GeositeUpdater.UpdatePACFromGeosite(_config); | |||||
} | } | ||||
public void UpdateStatisticsConfiguration(bool enabled) | public void UpdateStatisticsConfiguration(bool enabled) | ||||
@@ -534,9 +530,9 @@ namespace Shadowsocks.Controller | |||||
_pacServer = _pacServer ?? new PACServer(_pacDaemon); | _pacServer = _pacServer ?? new PACServer(_pacDaemon); | ||||
_pacServer.UpdatePACURL(_config); // So PACServer works when system proxy disabled. | _pacServer.UpdatePACURL(_config); // So PACServer works when system proxy disabled. | ||||
gfwListUpdater = gfwListUpdater ?? new GFWListUpdater(); | |||||
gfwListUpdater.UpdateCompleted += PacServer_PACUpdateCompleted; | |||||
gfwListUpdater.Error += PacServer_PACUpdateError; | |||||
GeositeUpdater.ResetEvent(); | |||||
GeositeUpdater.UpdateCompleted += PacServer_PACUpdateCompleted; | |||||
GeositeUpdater.Error += PacServer_PACUpdateError; | |||||
availabilityStatistics.UpdateConfiguration(this); | availabilityStatistics.UpdateConfiguration(this); | ||||
_listener?.Stop(); | _listener?.Stop(); | ||||
@@ -613,7 +609,7 @@ namespace Shadowsocks.Controller | |||||
UpdateSystemProxy(); | UpdateSystemProxy(); | ||||
} | } | ||||
private void PacServer_PACUpdateCompleted(object sender, GFWListUpdater.ResultEventArgs e) | |||||
private void PacServer_PACUpdateCompleted(object sender, GeositeResultEventArgs e) | |||||
{ | { | ||||
UpdatePACFromGFWListCompleted?.Invoke(this, e); | UpdatePACFromGFWListCompleted?.Invoke(this, e); | ||||
} | } | ||||
@@ -632,7 +628,7 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
GFWListUpdater.MergeAndWritePACFile(FileManager.NonExclusiveReadAllText(Utils.GetTempPath("gfwlist.txt"))); | |||||
GeositeUpdater.MergeAndWritePACFile(); | |||||
} | } | ||||
UpdateSystemProxy(); | UpdateSystemProxy(); | ||||
} | } | ||||
@@ -393,7 +393,7 @@ namespace Shadowsocks.View | |||||
logger.LogUsefulException(e.GetException()); | logger.LogUsefulException(e.GetException()); | ||||
} | } | ||||
void controller_UpdatePACFromGFWListCompleted(object sender, GFWListUpdater.ResultEventArgs e) | |||||
void controller_UpdatePACFromGFWListCompleted(object sender, GeositeResultEventArgs e) | |||||
{ | { | ||||
string result = e.Success | string result = e.Success | ||||
? I18N.GetString("PAC updated") | ? I18N.GetString("PAC updated") | ||||
@@ -173,7 +173,6 @@ | |||||
<Compile Include="Controller\Strategy\StatisticsStrategy.cs" /> | <Compile Include="Controller\Strategy\StatisticsStrategy.cs" /> | ||||
<Compile Include="Controller\System\AutoStartup.cs" /> | <Compile Include="Controller\System\AutoStartup.cs" /> | ||||
<Compile Include="Controller\FileManager.cs" /> | <Compile Include="Controller\FileManager.cs" /> | ||||
<Compile Include="Controller\Service\GFWListUpdater.cs" /> | |||||
<Compile Include="Controller\I18N.cs" /> | <Compile Include="Controller\I18N.cs" /> | ||||
<Compile Include="Controller\Service\Listener.cs" /> | <Compile Include="Controller\Service\Listener.cs" /> | ||||
<Compile Include="Controller\Service\PortForwarder.cs" /> | <Compile Include="Controller\Service\PortForwarder.cs" /> | ||||