183 lines
4.3 KiB
C#
183 lines
4.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using PureCrack.Util;
|
|
|
|
namespace PureCrack.Setup;
|
|
|
|
public static class HostsManager
|
|
{
|
|
private const string HostsPath = "C:\\Windows\\System32\\drivers\\etc\\hosts";
|
|
|
|
private const string BackupSuffix = ".purecrack-backup";
|
|
|
|
public static readonly string[] Domains = new string[3] { "api.purecoder.io", "api1.purecoder.io", "api2.purecoder.io" };
|
|
|
|
public static string Path => "C:\\Windows\\System32\\drivers\\etc\\hosts";
|
|
|
|
public static string BackupPath => "C:\\Windows\\System32\\drivers\\etc\\hosts.purecrack-backup";
|
|
|
|
public static bool Ensure()
|
|
{
|
|
if (!File.Exists("C:\\Windows\\System32\\drivers\\etc\\hosts"))
|
|
{
|
|
throw new FileNotFoundException("C:\\Windows\\System32\\drivers\\etc\\hosts missing — Windows install looks broken");
|
|
}
|
|
string content = File.ReadAllText("C:\\Windows\\System32\\drivers\\etc\\hosts");
|
|
HashSet<string> present = ScanPresent(content);
|
|
List<string> list = Domains.Where((string d) => !present.Contains(d)).ToList();
|
|
if (list.Count == 0)
|
|
{
|
|
Log.Info($"hosts: all {Domains.Length} entries already present");
|
|
return false;
|
|
}
|
|
if (!File.Exists(BackupPath))
|
|
{
|
|
File.Copy("C:\\Windows\\System32\\drivers\\etc\\hosts", BackupPath);
|
|
Log.Bullet("hosts: backup saved to " + BackupPath);
|
|
}
|
|
string text = EnsureTrailingNewline(content);
|
|
foreach (string item in list)
|
|
{
|
|
text = text + "127.0.0.1 " + item + "\n";
|
|
Log.Bullet("hosts: add 127.0.0.1 " + item);
|
|
}
|
|
File.WriteAllText("C:\\Windows\\System32\\drivers\\etc\\hosts", text);
|
|
FlushDns();
|
|
return true;
|
|
}
|
|
|
|
public static void Remove()
|
|
{
|
|
if (!File.Exists("C:\\Windows\\System32\\drivers\\etc\\hosts"))
|
|
{
|
|
return;
|
|
}
|
|
string[] array = File.ReadAllLines("C:\\Windows\\System32\\drivers\\etc\\hosts");
|
|
List<string> list = new List<string>(array.Length);
|
|
int num = 0;
|
|
string[] array2 = array;
|
|
foreach (string text in array2)
|
|
{
|
|
string trimmed = text.Trim();
|
|
if (trimmed.StartsWith("#") || trimmed.Length == 0)
|
|
{
|
|
list.Add(text);
|
|
}
|
|
else if (Domains.Any((string d) => LineMapsDomainToLoopback(trimmed, d)))
|
|
{
|
|
num++;
|
|
}
|
|
else
|
|
{
|
|
list.Add(text);
|
|
}
|
|
}
|
|
if (num > 0)
|
|
{
|
|
File.WriteAllText("C:\\Windows\\System32\\drivers\\etc\\hosts", string.Join("\n", list));
|
|
Log.Ok($"hosts: removed {num} entries");
|
|
FlushDns();
|
|
}
|
|
}
|
|
|
|
public static bool IsWritable()
|
|
{
|
|
try
|
|
{
|
|
using (File.Open("C:\\Windows\\System32\\drivers\\etc\\hosts", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
catch (UnauthorizedAccessException)
|
|
{
|
|
return false;
|
|
}
|
|
catch (IOException)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static HashSet<string> ScanPresent(string content)
|
|
{
|
|
HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
string[] array = content.Split(new char[1] { '\n' });
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
string text = array[i].Trim();
|
|
if (text.Length == 0 || text.StartsWith("#"))
|
|
{
|
|
continue;
|
|
}
|
|
string[] domains = Domains;
|
|
foreach (string text2 in domains)
|
|
{
|
|
if (LineMapsDomainToLoopback(text, text2))
|
|
{
|
|
hashSet.Add(text2);
|
|
}
|
|
}
|
|
}
|
|
return hashSet;
|
|
}
|
|
|
|
private static bool LineMapsDomainToLoopback(string line, string domain)
|
|
{
|
|
string[] array = line.Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
|
|
if (array.Length < 2)
|
|
{
|
|
return false;
|
|
}
|
|
if (!array[0].StartsWith("127."))
|
|
{
|
|
return false;
|
|
}
|
|
for (int i = 1; i < array.Length; i++)
|
|
{
|
|
string text = array[i];
|
|
if (text.StartsWith("#"))
|
|
{
|
|
break;
|
|
}
|
|
if (string.Equals(text, domain, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static string EnsureTrailingNewline(string content)
|
|
{
|
|
if (content.Length != 0 && content[content.Length - 1] != '\n')
|
|
{
|
|
return content + "\n";
|
|
}
|
|
return content;
|
|
}
|
|
|
|
private static void FlushDns()
|
|
{
|
|
try
|
|
{
|
|
using Process process = Process.Start(new ProcessStartInfo("ipconfig", "/flushdns")
|
|
{
|
|
UseShellExecute = false,
|
|
CreateNoWindow = true,
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true
|
|
});
|
|
process?.WaitForExit(5000);
|
|
Log.Bullet("hosts: dns cache flushed");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Warn("ipconfig /flushdns failed (non-fatal): " + ex.Message);
|
|
}
|
|
}
|
|
}
|