HostsConflictSolver.cs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. using FastGithub.Configuration;
  2. using System;
  3. using System.IO;
  4. using System.Runtime.Versioning;
  5. using System.Text;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. namespace FastGithub.PacketIntercept.Dns
  9. {
  10. /// <summary>
  11. /// host文件冲解决者
  12. /// </summary>
  13. [SupportedOSPlatform("windows")]
  14. sealed class HostsConflictSolver : IDnsConflictSolver
  15. {
  16. private readonly FastGithubConfig fastGithubConfig;
  17. /// <summary>
  18. /// host文件冲解决者
  19. /// </summary>
  20. /// <param name="fastGithubConfig"></param>
  21. public HostsConflictSolver(FastGithubConfig fastGithubConfig)
  22. {
  23. this.fastGithubConfig = fastGithubConfig;
  24. }
  25. /// <summary>
  26. /// 解决冲突
  27. /// </summary>
  28. /// <param name="cancellationToken"></param>
  29. /// <returns></returns>
  30. public async Task SolveAsync(CancellationToken cancellationToken)
  31. {
  32. var hostsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "drivers/etc/hosts");
  33. if (File.Exists(hostsPath) == false)
  34. {
  35. return;
  36. }
  37. var hasConflicting = false;
  38. var hostsBuilder = new StringBuilder();
  39. var lines = await File.ReadAllLinesAsync(hostsPath, cancellationToken);
  40. foreach (var line in lines)
  41. {
  42. if (this.IsConflictingLine(line))
  43. {
  44. hasConflicting = true;
  45. hostsBuilder.AppendLine($"# {line}");
  46. }
  47. else
  48. {
  49. hostsBuilder.AppendLine(line);
  50. }
  51. }
  52. if (hasConflicting == true)
  53. {
  54. File.SetAttributes(hostsPath, FileAttributes.Normal);
  55. await File.WriteAllTextAsync(hostsPath, hostsBuilder.ToString(), cancellationToken);
  56. }
  57. }
  58. /// <summary>
  59. /// 恢复冲突
  60. /// </summary>
  61. /// <param name="cancellationToken"></param>
  62. /// <returns></returns>
  63. public Task RestoreAsync(CancellationToken cancellationToken)
  64. {
  65. return Task.CompletedTask;
  66. }
  67. /// <summary>
  68. /// 是否为冲突的行
  69. /// </summary>
  70. /// <param name="line"></param>
  71. /// <returns></returns>
  72. private bool IsConflictingLine(string line)
  73. {
  74. if (line.TrimStart().StartsWith("#"))
  75. {
  76. return false;
  77. }
  78. var items = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
  79. if (items.Length < 2)
  80. {
  81. return false;
  82. }
  83. var domain = items[1];
  84. return this.fastGithubConfig.IsMatch(domain);
  85. }
  86. }
  87. }