|
|
@@ -34,8 +34,7 @@ namespace Shadowsocks.Controller |
|
|
|
|
|
|
|
private static readonly string DATABASE_PATH = Utils.GetTempPath("dlc.dat"); |
|
|
|
|
|
|
|
// temporary workaround |
|
|
|
private static readonly string GEOSITE_URL = "https://github.com/v2ray/domain-list-community/releases/download/202005010407/dlc.dat"; |
|
|
|
private static readonly string GEOSITE_URL = "https://github.com/v2ray/domain-list-community/raw/release/dlc.dat"; |
|
|
|
|
|
|
|
public static readonly Dictionary<string, IList<DomainObject>> Geosites = new Dictionary<string, IList<DomainObject>>(); |
|
|
|
|
|
|
@@ -66,13 +65,21 @@ namespace Shadowsocks.Controller |
|
|
|
|
|
|
|
public static void UpdatePACFromGeosite(Configuration config) |
|
|
|
{ |
|
|
|
string gfwListUrl = GEOSITE_URL; |
|
|
|
if (!string.IsNullOrWhiteSpace(config.gfwListUrl)) |
|
|
|
string geositeUrl = GEOSITE_URL; |
|
|
|
string group = "geolocation-!cn"; |
|
|
|
bool blacklist = true; |
|
|
|
if (!string.IsNullOrWhiteSpace(config.geositeGroup)) |
|
|
|
{ |
|
|
|
logger.Info("Found custom GFWListURL in config file"); |
|
|
|
gfwListUrl = config.gfwListUrl; |
|
|
|
group = config.geositeGroup; |
|
|
|
blacklist = config.geositeBlacklistMode; |
|
|
|
} |
|
|
|
logger.Info($"Checking GFWList from {gfwListUrl}"); |
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(config.geositeUrl)) |
|
|
|
{ |
|
|
|
logger.Info("Found custom Geosite URL in config file"); |
|
|
|
geositeUrl = config.geositeUrl; |
|
|
|
} |
|
|
|
logger.Info($"Checking Geosite from {geositeUrl}"); |
|
|
|
WebClient http = new WebClient(); |
|
|
|
if (config.enabled) |
|
|
|
{ |
|
|
@@ -89,7 +96,7 @@ namespace Shadowsocks.Controller |
|
|
|
File.WriteAllBytes(DATABASE_PATH, e.Result); |
|
|
|
LoadGeositeList(); |
|
|
|
|
|
|
|
bool pacFileChanged = MergeAndWritePACFile(); |
|
|
|
bool pacFileChanged = MergeAndWritePACFile(group, blacklist); |
|
|
|
UpdateCompleted?.Invoke(null, new GeositeResultEventArgs(pacFileChanged)); |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
@@ -97,18 +104,13 @@ namespace Shadowsocks.Controller |
|
|
|
Error?.Invoke(null, new ErrorEventArgs(ex)); |
|
|
|
} |
|
|
|
}; |
|
|
|
http.DownloadDataAsync(new Uri(gfwListUrl)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static bool MergeAndWritePACFile() |
|
|
|
{ |
|
|
|
return MergeAndWritePACFile(Geosites["cn"]); |
|
|
|
http.DownloadDataAsync(new Uri(geositeUrl)); |
|
|
|
} |
|
|
|
|
|
|
|
private static bool MergeAndWritePACFile(IList<DomainObject> domains) |
|
|
|
public static bool MergeAndWritePACFile(string group, bool blacklist) |
|
|
|
{ |
|
|
|
string abpContent = MergePACFile(domains); |
|
|
|
IList<DomainObject> domains = Geosites[group]; |
|
|
|
string abpContent = MergePACFile(domains, blacklist); |
|
|
|
if (File.Exists(PACDaemon.PAC_FILE)) |
|
|
|
{ |
|
|
|
string original = FileManager.NonExclusiveReadAllText(PACDaemon.PAC_FILE, Encoding.UTF8); |
|
|
@@ -121,7 +123,7 @@ namespace Shadowsocks.Controller |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
private static string MergePACFile(IList<DomainObject> domains) |
|
|
|
private static string MergePACFile(IList<DomainObject> domains, bool blacklist) |
|
|
|
{ |
|
|
|
string abpContent; |
|
|
|
if (File.Exists(PACDaemon.USER_ABP_FILE)) |
|
|
@@ -137,10 +139,10 @@ namespace Shadowsocks.Controller |
|
|
|
if (File.Exists(PACDaemon.USER_RULE_FILE)) |
|
|
|
{ |
|
|
|
string userrulesString = FileManager.NonExclusiveReadAllText(PACDaemon.USER_RULE_FILE, Encoding.UTF8); |
|
|
|
userruleLines = ParseToValidList(userrulesString); |
|
|
|
userruleLines = PreProcessGFWList(userrulesString); |
|
|
|
} |
|
|
|
|
|
|
|
List<string> gfwLines = ParseToValidList(domains); |
|
|
|
List<string> gfwLines = GeositeToGFWList(domains, blacklist); |
|
|
|
abpContent = |
|
|
|
$@"var __USERRULES__ = {JsonConvert.SerializeObject(userruleLines, Formatting.Indented)}; |
|
|
|
var __RULES__ = {JsonConvert.SerializeObject(gfwLines, Formatting.Indented)}; |
|
|
@@ -150,7 +152,7 @@ var __RULES__ = {JsonConvert.SerializeObject(gfwLines, Formatting.Indented)}; |
|
|
|
|
|
|
|
private static readonly IEnumerable<char> IgnoredLineBegins = new[] { '!', '[' }; |
|
|
|
|
|
|
|
private static List<string> ParseToValidList(string content) |
|
|
|
private static List<string> PreProcessGFWList(string content) |
|
|
|
{ |
|
|
|
List<string> valid_lines = new List<string>(); |
|
|
|
using (var sr = new StringReader(content)) |
|
|
@@ -165,12 +167,15 @@ var __RULES__ = {JsonConvert.SerializeObject(gfwLines, Formatting.Indented)}; |
|
|
|
return valid_lines; |
|
|
|
} |
|
|
|
|
|
|
|
private static List<string> ParseToValidList(IList<DomainObject> domains) |
|
|
|
private static List<string> GeositeToGFWList(IList<DomainObject> domains, bool blacklist) |
|
|
|
{ |
|
|
|
List<string> ret = new List<string>(domains.Count + 100)// 100 overhead |
|
|
|
{ |
|
|
|
"/.*/" // match any domain, so all non-cn domain go through proxy |
|
|
|
}; |
|
|
|
return blacklist ? GeositeToGFWListBlack(domains) : GeositeToGFWListWhite(domains); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
private static List<string> GeositeToGFWListBlack(IList<DomainObject> domains) |
|
|
|
{ |
|
|
|
List<string> ret = new List<string>(domains.Count + 100);// 100 overhead |
|
|
|
foreach (var d in domains) |
|
|
|
{ |
|
|
|
string domain = d.Value; |
|
|
@@ -178,22 +183,29 @@ var __RULES__ = {JsonConvert.SerializeObject(gfwLines, Formatting.Indented)}; |
|
|
|
switch (d.Type) |
|
|
|
{ |
|
|
|
case DomainObject.Types.Type.Plain: |
|
|
|
ret.Add($"@@{domain}"); |
|
|
|
ret.Add(domain); |
|
|
|
break; |
|
|
|
case DomainObject.Types.Type.Regex: |
|
|
|
ret.Add($"@@/{domain}/"); |
|
|
|
ret.Add($"/{domain}/"); |
|
|
|
break; |
|
|
|
case DomainObject.Types.Type.Domain: |
|
|
|
ret.Add($"@@||{domain}"); |
|
|
|
ret.Add($"||{domain}"); |
|
|
|
break; |
|
|
|
case DomainObject.Types.Type.Full: |
|
|
|
ret.Add($"@@|http://{domain}"); |
|
|
|
ret.Add($"@@|https://{domain}"); |
|
|
|
ret.Add($"|http://{domain}"); |
|
|
|
ret.Add($"|https://{domain}"); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
private static List<string> GeositeToGFWListWhite(IList<DomainObject> domains) |
|
|
|
{ |
|
|
|
return GeositeToGFWListBlack(domains) |
|
|
|
.Select(r => $"@@{r}") // convert to whitelist |
|
|
|
.Prepend("/.*/") // blacklist all other site |
|
|
|
.ToList(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |