You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

GfwListUpdater.cs 4.4 kB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
9 years ago
9 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Net;
  5. using System.Text;
  6. using Newtonsoft.Json;
  7. using Shadowsocks.Model;
  8. using Shadowsocks.Properties;
  9. using Shadowsocks.Util;
  10. namespace Shadowsocks.Controller
  11. {
  12. public class GFWListUpdater
  13. {
  14. private const string GFWLIST_URL = "https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt";
  15. public event EventHandler<ResultEventArgs> UpdateCompleted;
  16. public event ErrorEventHandler Error;
  17. public class ResultEventArgs : EventArgs
  18. {
  19. public bool Success;
  20. public ResultEventArgs(bool success)
  21. {
  22. this.Success = success;
  23. }
  24. }
  25. private static readonly IEnumerable<char> IgnoredLineBegins = new[] { '!', '[' };
  26. private void http_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
  27. {
  28. try
  29. {
  30. File.WriteAllText(Utils.GetTempPath("gfwlist.txt"), e.Result, Encoding.UTF8);
  31. bool pacFileChanged = MergeAndWritePACFile(e.Result);
  32. UpdateCompleted?.Invoke(this, new ResultEventArgs(pacFileChanged));
  33. }
  34. catch (Exception ex)
  35. {
  36. Error?.Invoke(this, new ErrorEventArgs(ex));
  37. }
  38. }
  39. public static bool MergeAndWritePACFile(string gfwListResult)
  40. {
  41. string abpContent = MergePACFile(gfwListResult);
  42. if (File.Exists(PACServer.PAC_FILE))
  43. {
  44. string original = FileManager.NonExclusiveReadAllText(PACServer.PAC_FILE, Encoding.UTF8);
  45. if (original == abpContent)
  46. {
  47. return false;
  48. }
  49. }
  50. File.WriteAllText(PACServer.PAC_FILE, abpContent, Encoding.UTF8);
  51. return true;
  52. }
  53. private static string MergePACFile(string gfwListResult)
  54. {
  55. string abpContent;
  56. if (File.Exists(PACServer.USER_ABP_FILE))
  57. {
  58. abpContent = FileManager.NonExclusiveReadAllText(PACServer.USER_ABP_FILE, Encoding.UTF8);
  59. }
  60. else
  61. {
  62. abpContent = Utils.UnGzip(Resources.abp_js);
  63. }
  64. List<string> userruleLines = new List<string>();
  65. if (File.Exists(PACServer.USER_RULE_FILE))
  66. {
  67. string userrulesString = FileManager.NonExclusiveReadAllText(PACServer.USER_RULE_FILE, Encoding.UTF8);
  68. userruleLines = ParseToValidList(userrulesString);
  69. }
  70. List<string> gfwLines = new List<string>();
  71. gfwLines = ParseBase64ToValidList(gfwListResult);
  72. abpContent = abpContent.Replace("__USERRULES__", JsonConvert.SerializeObject(userruleLines, Formatting.Indented))
  73. .Replace("__RULES__", JsonConvert.SerializeObject(gfwLines, Formatting.Indented));
  74. return abpContent;
  75. }
  76. public void UpdatePACFromGFWList(Configuration config)
  77. {
  78. Logging.Info($"Checking GFWList from {GFWLIST_URL}");
  79. WebClient http = new WebClient();
  80. if (config.enabled)
  81. {
  82. http.Proxy = new WebProxy(IPAddress.Loopback.ToString(), config.localPort);
  83. }
  84. http.DownloadStringCompleted += http_DownloadStringCompleted;
  85. http.DownloadStringAsync(new Uri(GFWLIST_URL));
  86. }
  87. public static List<string> ParseBase64ToValidList(string response)
  88. {
  89. byte[] bytes = Convert.FromBase64String(response);
  90. string content = Encoding.ASCII.GetString(bytes);
  91. return ParseToValidList(content);
  92. }
  93. private static List<string> ParseToValidList(string content)
  94. {
  95. List<string> valid_lines = new List<string>();
  96. using (var sr = new StringReader(content))
  97. {
  98. foreach (var line in sr.NonWhiteSpaceLines())
  99. {
  100. if (line.BeginWithAny(IgnoredLineBegins))
  101. continue;
  102. valid_lines.Add(line);
  103. }
  104. }
  105. return valid_lines;
  106. }
  107. }
  108. }