Compare commits

..

34 Commits
1.8.8 ... 1.9.3

Author SHA1 Message Date
ChsBuffer
7f82cac1d6 Bump version to 1.9.3 2021-11-05 00:14:01 +08:00
ChsBuffer
2d295a1449 [Features] Json Format Mode
New ModeEditForm
Refactors and Cleanup
Update nuget packages
2021-11-04 17:43:33 +08:00
ChsBuffer
5826d1a1a6 Fix TUNMode not bypass socks5 proxy remote address 2021-10-30 17:01:17 +08:00
ChsBuffer
072f2d16e6 Fix stop error when using socks5 proxy 2021-10-19 17:36:14 +08:00
ChsBuffer
ecaab55934 Revert default build SelfContained 2021-10-19 17:32:35 +08:00
Connection Refused
3c93aff15d [GitHub CI] Update build.yml 2021-10-18 19:15:00 +08:00
Connection Refused
de856dd2ec [Scripts] Update build.ps1 2021-10-18 19:09:32 +08:00
Connection Refused
a4a221ef2f [Netch] Compatible with the latest ss-rust 2021-10-18 19:03:27 +08:00
Connection Refused
1dbda9cbf9 [Netch] Compatible with the latest aiodns 2021-10-18 18:51:04 +08:00
Connection Refused
cecae73c03 [Netch] Compatible with the latest Redirector 2021-10-18 18:50:54 +08:00
ChsBuffer
0d535aa27e Bump version to 1.9.2 2021-10-15 20:44:50 +08:00
ChsBuffer
03c3c151bf Update CI 2021-10-15 20:44:07 +08:00
ChsBuffer
7a3b5ff487 Update Redirector settings
Update Redirector interop
Update NFController
Create Netch.JsonConverter namespace
2021-10-15 20:23:10 +08:00
ChsBuffer
598ff19535 Nice properties reuse, v2rayN. 2021-10-14 20:26:11 +08:00
ChsBuffer
d02135f31b Bump version to 1.9.1 2021-10-01 12:39:57 +08:00
ChsBuffer
a7756dabc1 Fix GetReservedPortRange 2021-10-01 12:39:46 +08:00
ChsBuffer
7ce1127006 Move bin folder check before create directories exist.
cleanup Core.bin strings
2021-10-01 12:30:57 +08:00
ChsBuffer
fec84a4952 Update NFController
Update ICMPDelay setting
Update WebUtil Default UserAgent
Hide unimplemented features' settings
Remove unused HTTP Port setting
2021-10-01 12:11:45 +08:00
ChsBuffer
d335c69fab Fix Import Server from Clipboard not set default group 2021-09-28 18:11:52 +08:00
ChsBuffer
1228a565c1 Update texts
rename Subscribe Link (WTF??) to Subscription
Full English log
Remove Debug Logging Sink
Add Console Logging Sink
2021-09-23 20:17:45 +08:00
ChsBuffer
dc904c9c0b Fix start failed deadlock 2021-09-21 17:16:40 +08:00
ChsBuffer
d829e347d3 Bump version to 1.9.0 2021-09-21 10:30:04 +08:00
ChsBuffer
a01761d2e2 Bump version to 1.8.9 2021-09-20 20:35:28 +08:00
ChsBuffer
68d87e2ff2 Remove Resolve Server Hostname setting 2021-09-20 20:34:23 +08:00
ChsBuffer
04d6933319 Rename TcpStatusLabel to HTTPStatusLabel 2021-09-20 19:08:01 +08:00
ChsBuffer
e46eef17d0 Create scripts\download\pcap2socks.ps1 2021-09-20 18:54:49 +08:00
ChsBuffer
d3c3958dab fix a typo 2021-09-20 18:20:59 +08:00
ChsBuffer
5ec8d38fd1 Fix build 2021-09-14 09:47:43 +08:00
ChsBuffer
2a8754ecfb Update build 2021-09-14 09:42:00 +08:00
ChsBuffer
cbc6822bff Refactor Cancel Connectivity Test 2021-09-14 08:49:37 +08:00
ChsBuffer
96bd7473ca Refactor AsyncLock 2021-09-14 08:41:30 +08:00
ChsBuffer
54b2b87dec Update Socks5ServerTestUtils.GetSimpleResult() 2021-09-12 03:18:35 +08:00
ChsBuffer
42baed8b8f Catch HttpConnectAsync's exception 2021-09-12 01:34:12 +08:00
ChsBuffer
f68aae6795 Update Setting.cs
- TUNTAP.UseCustomDNS true->false
- V2rayConfig.XrayCone false->true
- JsonIgnore Redirector.ChildProcessHandle
2021-09-12 01:32:48 +08:00
84 changed files with 2678 additions and 1774 deletions

View File

@@ -1,13 +1,18 @@
name: Netch Build CI
on: [push, pull_request]
on:
push:
branches: [ master ]
pull_request:
jobs:
build:
name: Build
runs-on: windows-latest
runs-on: windows-2022
steps:
- name: MSBuild
uses: microsoft/setup-msbuild@v1.0.2
uses: microsoft/setup-msbuild@v1.0.3
with:
vs-prerelease: true
- name: Checkout
uses: actions/checkout@v2

View File

@@ -7,10 +7,12 @@ on:
jobs:
build:
name: Build
runs-on: windows-latest
runs-on: windows-2022
steps:
- name: MSBuild
uses: microsoft/setup-msbuild@v1.0.2
uses: microsoft/setup-msbuild@v1.0.3
with:
vs-prerelease: true
- name: Checkout
uses: actions/checkout@v2
@@ -41,6 +43,9 @@ jobs:
Netch.7z
body: |
[![](https://img.shields.io/badge/Telegram-Channel-blue)](https://t.me/netch_channel) [![](https://img.shields.io/badge/Telegram-Group-green)](https://t.me/netch_group)
[**第一次使用请务必先安装 .NET 5.0 运行库**](https://aka.ms/dotnet/5.0/windowsdesktop-runtime-win-x64.exe)
## Changelogs
* This is an automated deployment of GitHub Actions, the change log should be updated manually soon

View File

@@ -29,8 +29,8 @@ Global
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.Build.0 = Release|x64
{38240783-9AD2-4A01-84C1-1A3E5F05720F}.Debug|x64.ActiveCfg = Debug|x64
{38240783-9AD2-4A01-84C1-1A3E5F05720F}.Debug|x64.Build.0 = Debug|x64
{38240783-9AD2-4A01-84C1-1A3E5F05720F}.Release|x64.ActiveCfg = Release|Any CPU
{38240783-9AD2-4A01-84C1-1A3E5F05720F}.Release|x64.Build.0 = Release|Any CPU
{38240783-9AD2-4A01-84C1-1A3E5F05720F}.Release|x64.ActiveCfg = Release|x64
{38240783-9AD2-4A01-84C1-1A3E5F05720F}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -7,7 +7,6 @@
public const string AioDnsRuleFile = "bin\\aiodns.conf";
public const string NFDriver = "bin\\nfdriver.sys";
public const string NFCore = "bin\\core.bin";
public const string STUNServersFile = "bin\\stun.txt";
public const string LogFile = "logging\\application.log";
@@ -24,5 +23,9 @@
}
public const string WintunDllFile = "bin\\wintun.dll";
public const string DisableModeDirectoryFileName = "disabled";
public const string DefaultPrimaryDNS = "1.1.1.1:53";
public const string DefaultCNPrimaryDNS = "223.5.5.5:53";
}
}

View File

@@ -23,8 +23,8 @@ namespace Netch.Controllers
var listenAddress = Global.Settings.LocalAddress;
Dial(NameList.TYPE_REST, "");
Dial(NameList.TYPE_ADDR, $"{listenAddress}:{aioDnsConfig.ListenPort}");
Dial(NameList.TYPE_LIST, Path.GetFullPath(Constants.AioDnsRuleFile));
Dial(NameList.TYPE_LISN, $"{listenAddress}:{aioDnsConfig.ListenPort}");
Dial(NameList.TYPE_CDNS, $"{aioDnsConfig.ChinaDNS}");
Dial(NameList.TYPE_ODNS, $"{aioDnsConfig.OtherDNS}");

View File

@@ -157,7 +157,7 @@ namespace Netch.Controllers
}
catch (Win32Exception e)
{
Log.Error(e, "停止 {Name} 异常", Instance.ProcessName);
Log.Error(e, "Stop {Name} failed", Instance.ProcessName);
}
catch
{

View File

@@ -4,13 +4,13 @@ using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Threading;
using Netch.Enums;
using Netch.Interfaces;
using Netch.Models;
using Netch.Models.Modes;
using Netch.Servers;
using Netch.Services;
using Netch.Utils;
using Serilog;
using Serilog.Events;
namespace Netch.Controllers
{
@@ -26,15 +26,17 @@ namespace Netch.Controllers
public static IModeController? ModeController { get; private set; }
public static ModeFeature ModeFeatures { get; private set; }
private static readonly AsyncSemaphore Lock = new(1);
public static async Task StartAsync(Server server, Mode mode)
{
using var releaser = await Lock.EnterAsync();
Log.Information("Start MainController: {Server} {Mode}", $"{server.Type}", $"[{(int)mode.Type}]{mode.Remark}");
if (await DnsUtils.LookupAsync(server.Hostname) == null)
throw new MessageException(i18N.Translate("Lookup Server hostname failed"));
// TODO Disable NAT Type Test setting
// cache STUN Server ip to prevent "Wrong STUN Server"
DnsUtils.LookupAsync(Global.Settings.STUN_Server).Forget();
@@ -44,52 +46,40 @@ namespace Netch.Controllers
await Task.WhenAll(Task.Run(NativeMethods.RefreshDNSCache), Task.Run(Firewall.AddNetchFwRules));
if (Log.IsEnabled(LogEventLevel.Debug))
Task.Run(() =>
{
// TODO log level setting
Log.Debug("Running Processes: \n{Processes}", string.Join("\n", SystemInfo.Processes(false)));
})
.Forget();
try
{
(ModeController, ModeFeatures) = ModeHelper.GetModeControllerByType(mode.Type, out var modePort, out var portName);
ModeController = ModeService.GetModeControllerByType(mode.Type, out var modePort, out var portName);
if (modePort != null)
TryReleaseTcpPort((ushort)modePort, portName);
switch (Server)
if (Server is Socks5Server socks5 && (!socks5.Auth() || ModeController.Features.HasFlag(ModeFeature.SupportSocks5Auth)))
{
case Socks5Server socks5 when !socks5.Auth():
case Socks5Server socks5B when socks5B.Auth() && ModeFeatures.HasFlag(ModeFeature.SupportSocks5Auth):
// Directly Start ModeController
Socks5Server = (Socks5Server)Server;
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
await ModeController.StartAsync(Socks5Server, mode);
break;
default:
// Start Server Controller to get a local socks5 server
Log.Debug("Server Information: {Data}", $"{server.Type} {server.MaskedData()}");
ServerController = ServerHelper.GetUtilByTypeName(server.Type).GetController();
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ServerController.Name));
TryReleaseTcpPort(ServerController.Socks5LocalPort(), "Socks5");
Socks5Server = await ServerController.StartAsync(server);
StatusPortInfoText.Socks5Port = Socks5Server.Port;
StatusPortInfoText.UpdateShareLan();
// Start Mode Controller
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
await ModeController.StartAsync(Socks5Server, mode);
break;
Socks5Server = socks5;
}
else
{
// Start Server Controller to get a local socks5 server
Log.Debug("Server Information: {Data}", $"{server.Type} {server.MaskedData()}");
ServerController = ServerHelper.GetUtilByTypeName(server.Type).GetController();
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ServerController.Name));
TryReleaseTcpPort(ServerController.Socks5LocalPort(), "Socks5");
Socks5Server = await ServerController.StartAsync(server);
StatusPortInfoText.Socks5Port = Socks5Server.Port;
StatusPortInfoText.UpdateShareLan();
}
// Start Mode Controller
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
await ModeController.StartAsync(Socks5Server, mode);
}
catch (Exception e)
{
releaser.Dispose();
await StopAsync();
switch (e)
@@ -109,6 +99,14 @@ namespace Netch.Controllers
public static async Task StopAsync()
{
if (Lock.CurrentCount == 0)
{
(await Lock.EnterAsync()).Dispose();
return;
}
using var _ = await Lock.EnterAsync();
if (ServerController == null && ModeController == null)
return;
@@ -117,8 +115,8 @@ namespace Netch.Controllers
var tasks = new[]
{
Task.Run(() => ServerController?.StopAsync()),
Task.Run(() => ModeController?.StopAsync())
ServerController?.StopAsync() ?? Task.CompletedTask,
ModeController?.StopAsync() ?? Task.CompletedTask
};
try
@@ -132,7 +130,6 @@ namespace Netch.Controllers
ServerController = null;
ModeController = null;
ModeFeatures = 0;
}
public static void PortCheck(ushort port, string portName, PortType portType = PortType.Both)
@@ -182,7 +179,20 @@ namespace Netch.Controllers
public static async Task<int?> HttpConnectAsync(CancellationToken ctx = default)
{
Debug.Assert(Socks5Server != null, nameof(Socks5Server) + " != null");
return await Socks5ServerTestUtils.HttpConnectAsync(Socks5Server, ctx);
try
{
return await Socks5ServerTestUtils.HttpConnectAsync(Socks5Server, ctx);
}
catch (OperationCanceledException)
{
// ignored
}
catch (Exception e)
{
Log.Warning(e, "Unhandled Socks5ServerTestUtils.HttpConnectAsync Exception");
}
return null;
}
}
}

View File

@@ -1,13 +1,14 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.ServiceProcess;
using System.Threading.Tasks;
using Netch.Interfaces;
using Netch.Interops;
using Netch.Models;
using Netch.Models.Modes;
using Netch.Models.Modes.ProcessMode;
using Netch.Servers;
using Netch.Utils;
using Serilog;
@@ -18,7 +19,7 @@ namespace Netch.Controllers
public class NFController : IModeController
{
private Server? _server;
private Mode? _mode;
private Redirector _mode = null!;
private RedirectorConfig _rdrConfig = null!;
private static readonly ServiceController NFService = new("netfilter2");
@@ -27,30 +28,55 @@ namespace Netch.Controllers
public string Name => "Redirector";
public ModeFeature Features => ModeFeature.SupportIPv6 | ModeFeature.SupportSocks5Auth;
public async Task StartAsync(Socks5Server server, Mode mode)
{
_server = server;
_mode = mode;
_rdrConfig = Global.Settings.Redirector;
CheckDriver();
CheckCore();
if (mode is not Redirector processMode)
throw new InvalidOperationException();
Dial(NameList.TYPE_FILTERLOOPBACK, "false");
Dial(NameList.TYPE_FILTERICMP, "true");
var p = PortHelper.GetAvailablePort();
Dial(NameList.TYPE_TCPLISN, p.ToString());
Dial(NameList.TYPE_UDPLISN, p.ToString());
_server = server;
_mode = processMode;
_rdrConfig = Global.Settings.Redirector;
CheckDriver();
Dial(NameList.AIO_FILTERLOOPBACK, _mode.FilterLoopback);
Dial(NameList.AIO_FILTERINTRANET, _mode.FilterIntranet);
Dial(NameList.AIO_FILTERPARENT, _mode.FilterParent ?? _rdrConfig.HandleOnlyDNS);
Dial(NameList.AIO_FILTERICMP, _mode.FilterICMP ?? _rdrConfig.FilterICMP);
if (_mode.FilterICMP ?? _rdrConfig.FilterICMP)
Dial(NameList.AIO_ICMPING, (_mode.FilterICMP != null ? _mode.ICMPDelay ?? 10 : _rdrConfig.ICMPDelay).ToString());
Dial(NameList.AIO_FILTERTCP, _mode.FilterTCP ?? _rdrConfig.FilterTCP);
Dial(NameList.AIO_FILTERUDP, _mode.FilterUDP ?? _rdrConfig.FilterUDP);
// DNS
Dial(NameList.AIO_FILTERDNS, _mode.FilterDNS ?? _rdrConfig.FilterDNS);
Dial(NameList.AIO_DNSONLY, _mode.HandleOnlyDNS ?? _rdrConfig.HandleOnlyDNS);
Dial(NameList.AIO_DNSPROX, _mode.DNSProxy ?? _rdrConfig.DNSProxy);
if (_mode.FilterDNS ?? _rdrConfig.FilterDNS)
{
var dnsStr = _mode.FilterDNS != null ? _mode.DNSHost : _rdrConfig.DNSHost;
dnsStr = dnsStr.ValueOrDefault() ?? Constants.DefaultPrimaryDNS;
var dns = IPEndPoint.Parse(dnsStr);
if (dns.Port == 0)
dns.Port = 53;
Dial(NameList.AIO_DNSHOST, dns.Address.ToString());
Dial(NameList.AIO_DNSPORT, dns.Port.ToString());
}
// Server
Dial(NameList.TYPE_FILTERUDP, _rdrConfig.FilterProtocol.HasFlag(PortType.UDP).ToString().ToLower());
Dial(NameList.TYPE_FILTERTCP, _rdrConfig.FilterProtocol.HasFlag(PortType.TCP).ToString().ToLower());
await DialServerAsync(_rdrConfig.FilterProtocol, _server);
Dial(NameList.AIO_TGTHOST, await server.AutoResolveHostnameAsync());
Dial(NameList.AIO_TGTPORT, server.Port.ToString());
Dial(NameList.AIO_TGTUSER, server.Username ?? string.Empty);
Dial(NameList.AIO_TGTPASS, server.Password ?? string.Empty);
// Mode Rule
dial_Name(_mode);
// Features
Dial(NameList.TYPE_DNSHOST, _rdrConfig.DNSHijack ? _rdrConfig.DNSHijackHost : "");
DialRule();
if (!await InitAsync())
throw new MessageException("Redirector start failed.");
@@ -73,14 +99,14 @@ namespace Netch.Controllers
try
{
if (r.StartsWith("!"))
return Dial(NameList.TYPE_ADDNAME, r.Substring(1));
return Dial(NameList.AIO_ADDNAME, r.Substring(1));
return Dial(NameList.TYPE_ADDNAME, r);
return Dial(NameList.AIO_ADDNAME, r);
}
finally
{
if (clear)
Dial(NameList.TYPE_CLRNAME, "");
Dial(NameList.AIO_CLRNAME, "");
}
}
@@ -92,71 +118,38 @@ namespace Netch.Controllers
public static bool CheckRules(IEnumerable<string> rules, out IEnumerable<string> results)
{
results = rules.Where(r => !CheckCppRegex(r, false));
Dial(NameList.TYPE_CLRNAME, "");
Dial(NameList.AIO_CLRNAME, "");
return !results.Any();
}
public static string GenerateInvalidRulesMessage(IEnumerable<string> rules)
{
return $"{string.Join("\n", rules)}\nAbove rules does not conform to C++ regular expression syntax";
return $"{string.Join("\n", rules)}\n" + i18N.Translate("Above rules does not conform to C++ regular expression syntax");
}
#endregion
private async Task DialServerAsync(PortType portType, Server server)
private void DialRule()
{
if (portType == PortType.Both)
{
await DialServerAsync(PortType.TCP, server);
await DialServerAsync(PortType.UDP, server);
return;
}
var offset = portType == PortType.UDP ? UdpNameListOffset : 0;
if (server is Socks5Server socks5)
{
Dial(NameList.TYPE_TCPTYPE + offset, "Socks5");
Dial(NameList.TYPE_TCPHOST + offset, $"{await socks5.AutoResolveHostnameAsync()}:{socks5.Port}");
Dial(NameList.TYPE_TCPUSER + offset, socks5.Username ?? string.Empty);
Dial(NameList.TYPE_TCPPASS + offset, socks5.Password ?? string.Empty);
Dial(NameList.TYPE_TCPMETH + offset, string.Empty);
}
else
{
Trace.Assert(false);
}
}
private void dial_Name(Mode mode)
{
Dial(NameList.TYPE_CLRNAME, "");
Dial(NameList.AIO_CLRNAME, "");
var invalidList = new List<string>();
foreach (var s in mode.GetRules())
foreach (var s in _mode.Bypass)
{
if (s.StartsWith("!"))
{
if (!Dial(NameList.TYPE_BYPNAME, s.Substring(1)))
invalidList.Add(s);
if (!Dial(NameList.AIO_BYPNAME, s))
invalidList.Add(s);
}
continue;
}
if (!Dial(NameList.TYPE_ADDNAME, s))
foreach (var s in _mode.Handle)
{
if (!Dial(NameList.AIO_ADDNAME, s))
invalidList.Add(s);
}
if (invalidList.Any())
throw new MessageException(GenerateInvalidRulesMessage(invalidList));
Dial(NameList.TYPE_ADDNAME, @"NTT\.exe");
Dial(NameList.TYPE_BYPNAME, "^" + Global.NetchDir.ToRegexString() + @"((?!NTT\.exe).)*$");
}
private void CheckCore()
{
if (!File.Exists(Constants.NFCore))
throw new MessageException(i18N.Translate("\"Core.bin\" is missing. Please check your Antivirus software"));
// Bypass Self
Dial(NameList.AIO_BYPNAME, "^" + Global.NetchDir.ToRegexString());
}
#region DriverUtil
@@ -166,8 +159,8 @@ namespace Netch.Controllers
var binFileVersion = Utils.Utils.GetFileVersion(Constants.NFDriver);
var systemFileVersion = Utils.Utils.GetFileVersion(SystemDriver);
Log.Information("内置驱动版本: {Name}", binFileVersion);
Log.Information("系统驱动版本: {Name}", systemFileVersion);
Log.Information("Built-in netfilter2 driver version: {Name}", binFileVersion);
Log.Information("Installed netfilter2 driver version: {Name}", systemFileVersion);
if (!File.Exists(SystemDriver))
{
@@ -197,7 +190,7 @@ namespace Netch.Controllers
if (!reinstall)
return;
Log.Information("更新驱动");
Log.Information("Update netfilter2 driver");
UninstallDriver();
InstallDriver();
}
@@ -208,7 +201,8 @@ namespace Netch.Controllers
/// <returns>驱动是否安装成功</returns>
private static void InstallDriver()
{
Log.Information("安装 NF 驱动");
Log.Information("Install netfilter2 driver");
Global.MainForm.StatusText(i18N.Translate("Installing netfilter2 driver"));
if (!File.Exists(Constants.NFDriver))
throw new MessageException(i18N.Translate("builtin driver files missing, can't install NF driver"));
@@ -219,21 +213,18 @@ namespace Netch.Controllers
}
catch (Exception e)
{
Log.Error(e, "驱动复制失败\n");
throw new MessageException($"Copy NF driver file failed\n{e.Message}");
Log.Error(e, "Copy netfilter2.sys failed\n");
throw new MessageException($"Copy netfilter2.sys failed\n{e.Message}");
}
Global.MainForm.StatusText(i18N.Translate("Register driver"));
// 注册驱动文件
var result = NFAPI.nf_registerDriver("netfilter2");
if (result == NF_STATUS.NF_STATUS_SUCCESS)
if (Interops.Redirector.aio_register("netfilter2"))
{
Log.Information("驱动安装成功");
Log.Information("Install netfilter2 driver finished");
}
else
{
Log.Error("注册驱动失败: {Result}", result);
throw new MessageException($"Register NF driver failed\n{result}");
Log.Error("Register netfilter2 failed");
}
}
@@ -243,7 +234,7 @@ namespace Netch.Controllers
/// <returns>是否成功卸载</returns>
public static bool UninstallDriver()
{
Log.Information("卸载 NF 驱动");
Log.Information("Uninstall netfilter2");
try
{
if (NFService.Status == ServiceControllerStatus.Running)
@@ -260,7 +251,7 @@ namespace Netch.Controllers
if (!File.Exists(SystemDriver))
return true;
NFAPI.nf_unRegisterDriver("netfilter2");
Interops.Redirector.aio_unregister("netfilter2");
File.Delete(SystemDriver);
return true;

View File

@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -10,6 +8,8 @@ using Microsoft.VisualStudio.Threading;
using Netch.Forms;
using Netch.Interfaces;
using Netch.Models;
using Netch.Models.Modes;
using Netch.Models.Modes.ShareMode;
using Netch.Servers;
using Netch.Utils;
@@ -18,8 +18,8 @@ namespace Netch.Controllers
public class PcapController : Guard, IModeController
{
private readonly LogForm _form;
private Mode? _mode;
private Server? _server;
private ShareMode _mode = null!;
private Socks5Server _server = null!;
public PcapController() : base("pcap2socks.exe", encoding: Encoding.UTF8)
{
@@ -31,20 +31,25 @@ namespace Netch.Controllers
public override string Name => "pcap2socks";
public ModeFeature Features => 0;
public async Task StartAsync(Socks5Server server, Mode mode)
{
if (mode is not ShareMode shareMode)
throw new InvalidOperationException();
_server = server;
_mode = mode;
_mode = shareMode;
var outboundNetworkInterface = NetworkInterfaceUtils.GetBest();
var argument = new StringBuilder($@"-i \Device\NPF_{outboundNetworkInterface.Id}");
if (_server is Socks5Server socks5 && !socks5.Auth())
argument.Append($" --destination {await socks5.AutoResolveHostnameAsync()}:{socks5.Port}");
if (!_server.Auth())
argument.Append($" --destination {await _server.AutoResolveHostnameAsync()}:{_server.Port}");
else
Trace.Assert(false);
throw new InvalidOperationException();
argument.Append($" {_mode.GetRules().FirstOrDefault() ?? "-P n"}");
argument.Append($" {_mode.Argument}");
await StartGuardAsync(argument.ToString());
}

View File

@@ -1,13 +1,13 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using Netch.Enums;
using Netch.Interfaces;
using Netch.Interops;
using Netch.Models;
using Netch.Models.Modes;
using Netch.Models.Modes.TunMode;
using Netch.Servers;
using Netch.Utils;
using Serilog;
@@ -21,7 +21,7 @@ namespace Netch.Controllers
private readonly DNSController _aioDnsController = new();
private Mode _mode = null!;
private TunMode _mode = null!;
private IPAddress? _serverRemoteAddress;
private TUNConfig _tunConfig = null!;
@@ -30,13 +30,20 @@ namespace Netch.Controllers
public string Name => "tun2socks";
public ModeFeature Features => ModeFeature.SupportSocks5Auth;
public async Task StartAsync(Socks5Server server, Mode mode)
{
_mode = mode;
if (mode is not TunMode tunMode)
throw new InvalidOperationException();
_mode = tunMode;
_tunConfig = Global.Settings.TUNTAP;
if (server is Socks5LocalServer socks5Bridge)
_serverRemoteAddress = await DnsUtils.LookupAsync(socks5Bridge.RemoteHostname);
else
_serverRemoteAddress = await DnsUtils.LookupAsync(server.Hostname);
if (_serverRemoteAddress != null && IPAddress.IsLoopback(_serverRemoteAddress))
_serverRemoteAddress = null;
@@ -56,24 +63,17 @@ namespace Netch.Controllers
Dial(NameList.TYPE_UDPREST, "");
Dial(NameList.TYPE_UDPTYPE, "Socks5");
if (server is Socks5Server socks5)
Dial(NameList.TYPE_TCPHOST, $"{await server.AutoResolveHostnameAsync()}:{server.Port}");
Dial(NameList.TYPE_UDPHOST, $"{await server.AutoResolveHostnameAsync()}:{server.Port}");
if (server.Auth())
{
Dial(NameList.TYPE_TCPHOST, $"{await socks5.AutoResolveHostnameAsync()}:{socks5.Port}");
Dial(NameList.TYPE_TCPUSER, server.Username!);
Dial(NameList.TYPE_TCPPASS, server.Password!);
Dial(NameList.TYPE_UDPHOST, $"{await socks5.AutoResolveHostnameAsync()}:{socks5.Port}");
if (socks5.Auth())
{
Dial(NameList.TYPE_TCPUSER, socks5.Username!);
Dial(NameList.TYPE_TCPPASS, socks5.Password!);
Dial(NameList.TYPE_UDPUSER, socks5.Username!);
Dial(NameList.TYPE_UDPPASS, socks5.Password!);
}
}
else
{
Trace.Assert(false);
Dial(NameList.TYPE_UDPUSER, server.Username!);
Dial(NameList.TYPE_UDPPASS, server.Password!);
}
#endregion
@@ -125,8 +125,8 @@ namespace Netch.Controllers
var binHash = Utils.Utils.SHA256CheckSum(binDriver);
var sysHash = Utils.Utils.SHA256CheckSum(sysDriver);
Log.Information("自带 wintun.dll Hash: {Hash}", binHash);
Log.Information("系统 wintun.dll Hash: {Hash}", sysHash);
Log.Information("Built-in wintun.dll Hash: {Hash}", binHash);
Log.Information("Installed wintun.dll Hash: {Hash}", sysHash);
if (binHash == sysHash)
return;
@@ -137,7 +137,7 @@ namespace Netch.Controllers
}
catch (Exception e)
{
Log.Error(e, "复制 wintun.dll 异常");
Log.Error(e, "Copy wintun.dll failed");
throw new MessageException($"Failed to copy wintun.dll to system directory: {e.Message}");
}
}
@@ -148,6 +148,7 @@ namespace Netch.Controllers
{
Global.MainForm.StatusText(i18N.Translate("Setup Route Table Rule"));
var tunNetworkInterface = NetworkInterfaceUtils.Get(_tun.InterfaceIndex);
// Server Address
if (_serverRemoteAddress != null)
RouteUtils.CreateRoute(_outbound.FillTemplate(_serverRemoteAddress.ToString(), 32));
@@ -155,38 +156,22 @@ namespace Netch.Controllers
// Global Bypass IPs
RouteUtils.CreateRouteFill(_outbound, _tunConfig.BypassIPs);
var tunNetworkInterface = NetworkInterfaceUtils.Get(_tun.InterfaceIndex);
switch (_mode.Type)
// rule
RouteUtils.CreateRouteFill(_tun, _mode.Handle);
RouteUtils.CreateRouteFill(_outbound, _mode.Bypass);
// dns
// NOTICE: DNS metric is network interface metric
tunNetworkInterface.SetDns(DummyDns);
RouteUtils.CreateRoute(_tun.FillTemplate(DummyDns, 32));
if (!_tunConfig.UseCustomDNS)
{
case ModeType.ProxyRuleIPs:
// rules
RouteUtils.CreateRouteFill(_tun, _mode.GetRules());
if (_tunConfig.ProxyDNS)
{
tunNetworkInterface.SetDns(DummyDns);
// proxy dummy dns
RouteUtils.CreateRoute(_tun.FillTemplate(DummyDns, 32));
if (!_tunConfig.UseCustomDNS)
// proxy AioDNS other dns
RouteUtils.CreateRoute(_tun.FillTemplate(Utils.Utils.GetHostFromUri(Global.Settings.AioDNS.OtherDNS), 32));
}
break;
case ModeType.BypassRuleIPs:
RouteUtils.CreateRouteFill(_outbound, _mode.GetRules());
tunNetworkInterface.SetDns(DummyDns);
if (!_tunConfig.UseCustomDNS)
// bypass AioDNS other dns
RouteUtils.CreateRoute(_outbound.FillTemplate(Utils.Utils.GetHostFromUri(Global.Settings.AioDNS.ChinaDNS), 32));
NetworkInterfaceUtils.SetInterfaceMetric(_tun.InterfaceIndex, 0);
RouteUtils.CreateRoute(_tun.FillTemplate("0.0.0.0", 0));
break;
RouteUtils.CreateRoute(_outbound.FillTemplate(Utils.Utils.GetHostFromUri(Global.Settings.AioDNS.ChinaDNS), 32));
RouteUtils.CreateRoute(_tun.FillTemplate(Utils.Utils.GetHostFromUri(Global.Settings.AioDNS.OtherDNS), 32));
}
NetworkInterfaceUtils.SetInterfaceMetric(_tun.InterfaceIndex, 0);
}
private void ClearRouteTable()
@@ -196,13 +181,11 @@ namespace Netch.Controllers
RouteUtils.DeleteRouteFill(_outbound, Global.Settings.TUNTAP.BypassIPs);
switch (_mode.Type)
{
case ModeType.BypassRuleIPs:
RouteUtils.DeleteRouteFill(_outbound, _mode.GetRules());
NetworkInterfaceUtils.SetInterfaceMetric(_outbound.InterfaceIndex);
break;
}
RouteUtils.DeleteRouteFill(_outbound, _mode.Bypass);
RouteUtils.DeleteRoute(_outbound.FillTemplate(Utils.Utils.GetHostFromUri(Global.Settings.AioDNS.ChinaDNS), 32));
NetworkInterfaceUtils.SetInterfaceMetric(_outbound.InterfaceIndex);
}
#endregion

View File

@@ -20,7 +20,7 @@ namespace Netch.Controllers
public const string Name = @"Netch";
public const string Copyright = @"Copyright © 2019 - 2021";
public const string AssemblyVersion = @"1.8.8";
public const string AssemblyVersion = @"1.9.3";
private const string Suffix = @"";
public static readonly string Version = $"{AssemblyVersion}{(string.IsNullOrEmpty(Suffix) ? "" : $"-{Suffix}")}";
@@ -48,24 +48,24 @@ namespace Netch.Controllers
var releases = JsonSerializer.Deserialize<List<Release>>(json)!;
LatestRelease = GetLatestRelease(releases, isPreRelease);
Log.Information("Github 最新发布版本: {Version}", LatestRelease.tag_name);
Log.Information("Github latest release: {Version}", LatestRelease.tag_name);
if (VersionUtil.CompareVersion(LatestRelease.tag_name, Version) > 0)
{
Log.Information("发现新版本");
Log.Information("Found newer version");
NewVersionFound?.Invoke(null, EventArgs.Empty);
}
else
{
Log.Information("目前是最新版本");
Log.Information("Already the latest version");
NewVersionNotFound?.Invoke(null, EventArgs.Empty);
}
}
catch (Exception e)
{
if (e is WebException)
Log.Warning(e, "获取新版本失败");
Log.Warning(e, "Get releases failed");
else
Log.Error(e, "获取新版本异常");
Log.Error(e, "Get releases error");
NewVersionFoundFailed?.Invoke(null, EventArgs.Empty);
}

View File

@@ -1,10 +0,0 @@
namespace Netch.Enums
{
public enum ModeType
{
Process = 0,
ProxyRuleIPs = 1,
BypassRuleIPs = 2,
Pcap2Socks = 6
}
}

View File

@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Netch.Models;
namespace Netch.Forms
{
public class BindingForm : Form
{
private readonly Dictionary<Control, Func<string, bool>> _checkActions = new();
private readonly Dictionary<Control, Action<Control>> _saveActions = new();
protected void BindTextBox(TextBoxBase control, Func<string, bool> check, Action<string> save, object value)
{
BindTextBox<string>(control, check, save, value);
}
protected void BindTextBox<T>(TextBoxBase control, Func<T, bool> check, Action<T> save, object value)
{
control.Text = value.ToString();
_checkActions.Add(control,
s =>
{
try
{
return check.Invoke((T)Convert.ChangeType(s, typeof(T)));
}
catch
{
return false;
}
});
_saveActions.Add(control, c => save.Invoke((T)Convert.ChangeType(((TextBoxBase)c).Text, typeof(T))));
}
protected void BindCheckBox(CheckBox control, Action<bool> save, bool value)
{
control.Checked = value;
_saveActions.Add(control, c => save(((CheckBox)c).Checked));
}
protected void BindSyncGlobalCheckBox(SyncGlobalCheckBox control, Action<bool?> save, bool? value, bool globalValue)
{
control.Value = value;
control.GlobalValue = globalValue;
_saveActions.Add(control, c => save(((SyncGlobalCheckBox)c).Value));
}
protected void BindRadioBox(RadioButton control, Action<bool> save, bool value)
{
control.Checked = value;
_saveActions.Add(control, c => save.Invoke(((RadioButton)c).Checked));
}
protected void BindListComboBox<T>(ComboBox comboBox, Action<T> save, IEnumerable<T> values, T value) where T : notnull
{
if (comboBox.DropDownStyle != ComboBoxStyle.DropDownList)
throw new ArgumentOutOfRangeException();
var tagItems = values.Select(o => new TagItem<T>(o, o.ToString()!)).ToArray();
comboBox.Items.AddRange(tagItems.Cast<object>().ToArray());
comboBox.ValueMember = nameof(TagItem<T>.Value);
comboBox.DisplayMember = nameof(TagItem<T>.Text);
_saveActions.Add(comboBox, c => save.Invoke(((TagItem<T>)((ComboBox)c).SelectedItem).Value));
Load += (_, _) => { comboBox.SelectedItem = tagItems.SingleOrDefault(t => t.Value.Equals(value)); };
}
protected void BindComboBox(ComboBox control, Func<string, bool> check, Action<string> save, string value, object[]? values = null)
{
if (values != null)
control.Items.AddRange(values);
_saveActions.Add(control, c => save.Invoke(((ComboBox)c).Text));
_checkActions.Add(control, check.Invoke);
Load += (_, _) => { control.Text = value; };
}
protected List<Control> GetCheckFailedControls()
{
return _checkActions.Where(pair => !pair.Value.Invoke(pair.Key.Text)).Select(pair => pair.Key).ToList();
}
protected void SaveBinds()
{
foreach (var pair in _saveActions)
pair.Value.Invoke(pair.Key);
}
}
}

View File

@@ -35,19 +35,19 @@
this.ModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CreateProcessModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CreateRouteTableRuleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.SubscribeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ManageSubscribeLinksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.UpdateServersFromSubscribeLinksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.SubscriptionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ManageSubscriptionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.UpdateServersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.OptionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.OpenDirectoryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ShowHideConsoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CleanDNSCacheToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.UninstallServiceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.removeNetchFirewallRulesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.RemoveNetchFirewallRulesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.HelpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CheckForUpdatesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.fAQToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CheckForUpdateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.FAQToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ForceExitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.AboutToolStripButton = new System.Windows.Forms.ToolStripButton();
this.NewVersionLabel = new System.Windows.Forms.ToolStripLabel();
this.VersionLabel = new System.Windows.Forms.ToolStripLabel();
@@ -73,7 +73,7 @@
this.DownloadSpeedLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.UploadSpeedLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.blankToolStripStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.TcpStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.HttpStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.NatTypeStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.NatTypeStatusLightLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.ControlButton = new System.Windows.Forms.Button();
@@ -86,6 +86,7 @@
this.ProfileTable = new System.Windows.Forms.TableLayoutPanel();
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
this.ButtomControlContainerControl = new System.Windows.Forms.ContainerControl();
this.ReloadModesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.MenuStrip.SuspendLayout();
this.ConfigurationGroupBox.SuspendLayout();
this.configLayoutPanel.SuspendLayout();
@@ -111,10 +112,10 @@
this.MenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.ServerToolStripMenuItem,
this.ModeToolStripMenuItem,
this.SubscribeToolStripMenuItem,
this.SubscriptionToolStripMenuItem,
this.OptionsToolStripMenuItem,
this.HelpToolStripMenuItem,
this.exitToolStripMenuItem,
this.ForceExitToolStripMenuItem,
this.AboutToolStripButton,
this.NewVersionLabel,
this.VersionLabel});
@@ -144,7 +145,8 @@
//
this.ModeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.CreateProcessModeToolStripMenuItem,
this.CreateRouteTableRuleToolStripMenuItem});
this.CreateRouteTableRuleToolStripMenuItem,
this.ReloadModesToolStripMenuItem});
this.ModeToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
this.ModeToolStripMenuItem.Name = "ModeToolStripMenuItem";
this.ModeToolStripMenuItem.Size = new System.Drawing.Size(55, 21);
@@ -164,29 +166,29 @@
this.CreateRouteTableRuleToolStripMenuItem.Text = "Create Route Table Rule";
this.CreateRouteTableRuleToolStripMenuItem.Click += new System.EventHandler(this.createRouteTableModeToolStripMenuItem_Click);
//
// SubscribeToolStripMenuItem
// SubscriptionToolStripMenuItem
//
this.SubscribeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.ManageSubscribeLinksToolStripMenuItem,
this.UpdateServersFromSubscribeLinksToolStripMenuItem});
this.SubscribeToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
this.SubscribeToolStripMenuItem.Name = "SubscribeToolStripMenuItem";
this.SubscribeToolStripMenuItem.Size = new System.Drawing.Size(77, 21);
this.SubscribeToolStripMenuItem.Text = "Subscribe";
this.SubscriptionToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.ManageSubscriptionsToolStripMenuItem,
this.UpdateServersToolStripMenuItem});
this.SubscriptionToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
this.SubscriptionToolStripMenuItem.Name = "SubscriptionToolStripMenuItem";
this.SubscriptionToolStripMenuItem.Size = new System.Drawing.Size(92, 21);
this.SubscriptionToolStripMenuItem.Text = "Subscription";
//
// ManageSubscribeLinksToolStripMenuItem
// ManageSubscriptionsToolStripMenuItem
//
this.ManageSubscribeLinksToolStripMenuItem.Name = "ManageSubscribeLinksToolStripMenuItem";
this.ManageSubscribeLinksToolStripMenuItem.Size = new System.Drawing.Size(294, 22);
this.ManageSubscribeLinksToolStripMenuItem.Text = "Manage Subscribe Links";
this.ManageSubscribeLinksToolStripMenuItem.Click += new System.EventHandler(this.ManageSubscribeLinksToolStripMenuItem_Click);
this.ManageSubscriptionsToolStripMenuItem.Name = "ManageSubscriptionsToolStripMenuItem";
this.ManageSubscriptionsToolStripMenuItem.Size = new System.Drawing.Size(206, 22);
this.ManageSubscriptionsToolStripMenuItem.Text = "Manage Subscriptions";
this.ManageSubscriptionsToolStripMenuItem.Click += new System.EventHandler(this.ManageSubscriptionLinksToolStripMenuItem_Click);
//
// UpdateServersFromSubscribeLinksToolStripMenuItem
// UpdateServersToolStripMenuItem
//
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Name = "UpdateServersFromSubscribeLinksToolStripMenuItem";
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Size = new System.Drawing.Size(294, 22);
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Text = "Update Servers From Subscribe Links";
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Click += new System.EventHandler(this.UpdateServersFromSubscribeLinksToolStripMenuItem_Click);
this.UpdateServersToolStripMenuItem.Name = "UpdateServersToolStripMenuItem";
this.UpdateServersToolStripMenuItem.Size = new System.Drawing.Size(206, 22);
this.UpdateServersToolStripMenuItem.Text = "Update Servers";
this.UpdateServersToolStripMenuItem.Click += new System.EventHandler(this.UpdateServersFromSubscriptionLinksToolStripMenuItem_Click);
//
// OptionsToolStripMenuItem
//
@@ -195,7 +197,7 @@
this.ShowHideConsoleToolStripMenuItem,
this.CleanDNSCacheToolStripMenuItem,
this.UninstallServiceToolStripMenuItem,
this.removeNetchFirewallRulesToolStripMenuItem});
this.RemoveNetchFirewallRulesToolStripMenuItem});
this.OptionsToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
this.OptionsToolStripMenuItem.Name = "OptionsToolStripMenuItem";
this.OptionsToolStripMenuItem.Size = new System.Drawing.Size(66, 21);
@@ -229,43 +231,43 @@
this.UninstallServiceToolStripMenuItem.Text = "Uninstall NF Service";
this.UninstallServiceToolStripMenuItem.Click += new System.EventHandler(this.UninstallServiceToolStripMenuItem_Click);
//
// removeNetchFirewallRulesToolStripMenuItem
// RemoveNetchFirewallRulesToolStripMenuItem
//
this.removeNetchFirewallRulesToolStripMenuItem.Name = "removeNetchFirewallRulesToolStripMenuItem";
this.removeNetchFirewallRulesToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
this.removeNetchFirewallRulesToolStripMenuItem.Text = "Remove Netch Firewall Rules";
this.removeNetchFirewallRulesToolStripMenuItem.Click += new System.EventHandler(this.RemoveNetchFirewallRulesToolStripMenuItem_Click);
this.RemoveNetchFirewallRulesToolStripMenuItem.Name = "RemoveNetchFirewallRulesToolStripMenuItem";
this.RemoveNetchFirewallRulesToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
this.RemoveNetchFirewallRulesToolStripMenuItem.Text = "Remove Netch Firewall Rules";
this.RemoveNetchFirewallRulesToolStripMenuItem.Click += new System.EventHandler(this.RemoveNetchFirewallRulesToolStripMenuItem_Click);
//
// HelpToolStripMenuItem
//
this.HelpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.CheckForUpdatesToolStripMenuItem,
this.fAQToolStripMenuItem});
this.CheckForUpdateToolStripMenuItem,
this.FAQToolStripMenuItem});
this.HelpToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
this.HelpToolStripMenuItem.Name = "HelpToolStripMenuItem";
this.HelpToolStripMenuItem.Size = new System.Drawing.Size(47, 21);
this.HelpToolStripMenuItem.Text = "Help";
//
// CheckForUpdatesToolStripMenuItem
// CheckForUpdateToolStripMenuItem
//
this.CheckForUpdatesToolStripMenuItem.Name = "CheckForUpdatesToolStripMenuItem";
this.CheckForUpdatesToolStripMenuItem.Size = new System.Drawing.Size(183, 22);
this.CheckForUpdatesToolStripMenuItem.Text = "Check for updates";
this.CheckForUpdatesToolStripMenuItem.Click += new System.EventHandler(this.CheckForUpdatesToolStripMenuItem_Click);
this.CheckForUpdateToolStripMenuItem.Name = "CheckForUpdateToolStripMenuItem";
this.CheckForUpdateToolStripMenuItem.Size = new System.Drawing.Size(177, 22);
this.CheckForUpdateToolStripMenuItem.Text = "Check for update";
this.CheckForUpdateToolStripMenuItem.Click += new System.EventHandler(this.CheckForUpdatesToolStripMenuItem_Click);
//
// fAQToolStripMenuItem
// FAQToolStripMenuItem
//
this.fAQToolStripMenuItem.Name = "fAQToolStripMenuItem";
this.fAQToolStripMenuItem.Size = new System.Drawing.Size(183, 22);
this.fAQToolStripMenuItem.Text = "FAQ";
this.fAQToolStripMenuItem.Click += new System.EventHandler(this.fAQToolStripMenuItem_Click);
this.FAQToolStripMenuItem.Name = "FAQToolStripMenuItem";
this.FAQToolStripMenuItem.Size = new System.Drawing.Size(177, 22);
this.FAQToolStripMenuItem.Text = "FAQ";
this.FAQToolStripMenuItem.Click += new System.EventHandler(this.fAQToolStripMenuItem_Click);
//
// exitToolStripMenuItem
// ForceExitToolStripMenuItem
//
this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
this.exitToolStripMenuItem.Size = new System.Drawing.Size(40, 22);
this.exitToolStripMenuItem.Text = "Exit";
this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
this.ForceExitToolStripMenuItem.Name = "ForceExitToolStripMenuItem";
this.ForceExitToolStripMenuItem.Size = new System.Drawing.Size(40, 22);
this.ForceExitToolStripMenuItem.Text = "Exit";
this.ForceExitToolStripMenuItem.Click += new System.EventHandler(this.ForceExitToolStripMenuItem_Click);
//
// AboutToolStripButton
//
@@ -522,7 +524,7 @@
this.DownloadSpeedLabel,
this.UploadSpeedLabel,
this.blankToolStripStatusLabel,
this.TcpStatusLabel,
this.HttpStatusLabel,
this.NatTypeStatusLabel,
this.NatTypeStatusLightLabel});
this.StatusStrip.Location = new System.Drawing.Point(0, 272);
@@ -562,17 +564,17 @@
// blankToolStripStatusLabel
//
this.blankToolStripStatusLabel.Name = "blankToolStripStatusLabel";
this.blankToolStripStatusLabel.Size = new System.Drawing.Size(240, 17);
this.blankToolStripStatusLabel.Size = new System.Drawing.Size(494, 17);
this.blankToolStripStatusLabel.Spring = true;
//
// TcpStatusLabel
// HttpStatusLabel
//
this.TcpStatusLabel.Name = "TcpStatusLabel";
this.TcpStatusLabel.Size = new System.Drawing.Size(33, 17);
this.TcpStatusLabel.Text = "TCP:";
this.TcpStatusLabel.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
this.TcpStatusLabel.Visible = false;
this.TcpStatusLabel.Click += new System.EventHandler(this.TcpStatusLabel_Click);
this.HttpStatusLabel.Name = "HttpStatusLabel";
this.HttpStatusLabel.Size = new System.Drawing.Size(41, 17);
this.HttpStatusLabel.Text = "HTTP:";
this.HttpStatusLabel.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
this.HttpStatusLabel.Visible = false;
this.HttpStatusLabel.Click += new System.EventHandler(this.TcpStatusLabel_Click);
//
// NatTypeStatusLabel
//
@@ -697,6 +699,13 @@
this.ButtomControlContainerControl.TabStop = false;
this.ButtomControlContainerControl.Text = "groupBox1";
//
// ReloadModesToolStripMenuItem
//
this.ReloadModesToolStripMenuItem.Name = "ReloadModesToolStripMenuItem";
this.ReloadModesToolStripMenuItem.Size = new System.Drawing.Size(217, 22);
this.ReloadModesToolStripMenuItem.Text = "Reload Modes";
this.ReloadModesToolStripMenuItem.Click += new System.EventHandler(this.ReloadModesToolStripMenuItem_Click);
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
@@ -744,7 +753,7 @@
private System.Windows.Forms.ToolStripMenuItem CreateRouteTableRuleToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem removeNetchFirewallRulesToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem RemoveNetchFirewallRulesToolStripMenuItem;
private System.Windows.Forms.ToolStripButton AboutToolStripButton;
private System.Windows.Forms.ToolStripMenuItem CleanDNSCacheToolStripMenuItem;
@@ -759,9 +768,9 @@
private System.Windows.Forms.PictureBox EditModePictureBox;
private System.Windows.Forms.PictureBox EditServerPictureBox;
private System.Windows.Forms.ToolStripMenuItem ExitToolStripButton;
private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem ForceExitToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem ImportServersFromClipboardToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem ManageSubscribeLinksToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem ManageSubscriptionsToolStripMenuItem;
private System.Windows.Forms.MenuStrip MenuStrip;
public System.Windows.Forms.ComboBox ModeComboBox;
private System.Windows.Forms.Label ModeLabel;
@@ -776,7 +785,7 @@
private System.Windows.Forms.Label ProfileLabel;
private System.Windows.Forms.TextBox ProfileNameText;
private System.Windows.Forms.TableLayoutPanel ProfileTable;
private System.Windows.Forms.ToolStripMenuItem CheckForUpdatesToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem CheckForUpdateToolStripMenuItem;
private System.Windows.Forms.ComboBox ServerComboBox;
private System.Windows.Forms.Label ServerLabel;
private System.Windows.Forms.ToolStripMenuItem ServerToolStripMenuItem;
@@ -785,24 +794,25 @@
private System.Windows.Forms.PictureBox SpeedPictureBox;
private System.Windows.Forms.ToolStripStatusLabel StatusLabel;
private System.Windows.Forms.StatusStrip StatusStrip;
private System.Windows.Forms.ToolStripMenuItem SubscribeToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem SubscriptionToolStripMenuItem;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
private System.Windows.Forms.ToolStripMenuItem UninstallServiceToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem UpdateServersFromSubscribeLinksToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem UpdateServersToolStripMenuItem;
private System.Windows.Forms.ToolStripStatusLabel UploadSpeedLabel;
private System.Windows.Forms.ToolStripStatusLabel UsedBandwidthLabel;
private System.Windows.Forms.ToolStripLabel NewVersionLabel;
private System.Windows.Forms.ToolStripLabel VersionLabel;
private System.Windows.Forms.ToolStripStatusLabel NatTypeStatusLightLabel;
private System.Windows.Forms.ToolStripStatusLabel blankToolStripStatusLabel;
private System.Windows.Forms.ToolStripMenuItem fAQToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem FAQToolStripMenuItem;
#endregion
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
private System.Windows.Forms.ContainerControl ButtomControlContainerControl;
private System.Windows.Forms.ToolStripMenuItem ShowHideConsoleToolStripMenuItem;
private System.Windows.Forms.ToolStripStatusLabel TcpStatusLabel;
private System.Windows.Forms.ToolStripStatusLabel HttpStatusLabel;
private System.Windows.Forms.ToolStripMenuItem ReloadModesToolStripMenuItem;
}
}

View File

@@ -19,6 +19,7 @@ using Netch.Enums;
using Netch.Forms.ModeForms;
using Netch.Interfaces;
using Netch.Models;
using Netch.Models.Modes;
using Netch.Properties;
using Netch.Services;
using Netch.Utils;
@@ -57,7 +58,7 @@ namespace Netch.Forms
private void AddAddServerToolStripMenuItems()
{
foreach (var serversUtil in ServerHelper.ServerUtilDictionary.Values.OrderBy(i => i.Priority)
.Where(i => !string.IsNullOrEmpty(i.FullName)))
.Where(i => !string.IsNullOrEmpty(i.FullName)))
{
var fullName = serversUtil.FullName;
var control = new ToolStripMenuItem
@@ -83,10 +84,7 @@ namespace Netch.Forms
SelectLastServer();
DelayTestHelper.UpdateTick(true);
ModeHelper.InitWatcher();
ModeHelper.Load();
LoadModes();
SelectLastMode();
ModeService.Instance.Load();
// 加载翻译
TranslateControls();
@@ -103,13 +101,13 @@ namespace Netch.Forms
// 检查订阅更新
if (Global.Settings.UpdateServersWhenOpened)
UpdateServersFromSubscribeAsync().Forget();
UpdateServersFromSubscriptionAsync().Forget();
// 打开软件时启动加速,产生开始按钮点击事件
if (Global.Settings.StartWhenOpened)
ControlButton.PerformClick();
Netch.SingleInstance.ListenForArgumentsFromSuccessiveInstances();
Program.SingleInstance.ListenForArgumentsFromSuccessiveInstances();
}
private void RecordSize()
@@ -215,15 +213,18 @@ namespace Netch.Forms
private async void ImportServersFromClipboardToolStripMenuItem_Click(object sender, EventArgs e)
{
var texts = Clipboard.GetText();
if (!string.IsNullOrWhiteSpace(texts))
{
var servers = ShareLink.ParseText(texts);
Global.Settings.Server.AddRange(servers);
NotifyTip(i18N.TranslateFormat("Import {0} server(s) form Clipboard", servers.Count));
if (string.IsNullOrWhiteSpace(texts))
return;
LoadServers();
await Configuration.SaveAsync();
}
var servers = ShareLink.ParseText(texts);
foreach (var server in servers)
server.Group = Constants.DefaultGroup;
Global.Settings.Server.AddRange(servers);
NotifyTip(i18N.TranslateFormat("Import {0} server(s) form Clipboard", servers.Count));
LoadServers();
await Configuration.SaveAsync();
}
private async void AddServerToolStripMenuItem_Click([NotNull] object? sender, EventArgs? e)
@@ -259,51 +260,64 @@ namespace Netch.Forms
Show();
}
private void ReloadModesToolStripMenuItem_Click(object sender, EventArgs e)
{
Enabled = false;
try
{
ModeService.Instance.Load();
}
finally
{
Enabled = true;
}
}
#endregion
#region Subscription
private void ManageSubscribeLinksToolStripMenuItem_Click(object sender, EventArgs e)
private void ManageSubscriptionLinksToolStripMenuItem_Click(object sender, EventArgs e)
{
Hide();
new SubscribeForm().ShowDialog();
new SubscriptionForm().ShowDialog();
LoadServers();
Show();
}
private async void UpdateServersFromSubscribeLinksToolStripMenuItem_Click(object sender, EventArgs e)
private async void UpdateServersFromSubscriptionLinksToolStripMenuItem_Click(object sender, EventArgs e)
{
await UpdateServersFromSubscribeAsync();
await UpdateServersFromSubscriptionAsync();
}
private async Task UpdateServersFromSubscribeAsync()
private async Task UpdateServersFromSubscriptionAsync()
{
void DisableItems(bool v)
{
MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ProfileGroupBox.Enabled = ControlButton.Enabled = v;
}
if (Global.Settings.SubscribeLink.Count <= 0)
if (Global.Settings.Subscription.Count <= 0)
{
MessageBoxX.Show(i18N.Translate("No subscription link"));
return;
}
StatusText(i18N.Translate("Starting update subscription"));
StatusText(i18N.Translate("Updating servers"));
DisableItems(false);
try
{
await Subscription.UpdateServersAsync();
await SubscriptionUtil.UpdateServersAsync();
LoadServers();
await Configuration.SaveAsync();
StatusText(i18N.Translate("Subscription updated"));
StatusText(i18N.Translate("Servers updated"));
}
catch (Exception e)
{
NotifyTip(i18N.Translate("update servers failed") + "\n" + e.Message, info: false);
Log.Error("更新服务器 失败!" + e);
NotifyTip(i18N.Translate("Unhandled update servers error") + "\n" + e.Message, info: false);
Log.Error(e, "Unhandled Update servers error");
}
finally
{
@@ -324,7 +338,7 @@ namespace Netch.Forms
void OnNewVersionFoundFailed(object? o, EventArgs? args)
{
NotifyTip(i18N.Translate("New version found failed"), info: false);
NotifyTip(i18N.Translate("Check for update failed"), info: false);
}
try
@@ -392,9 +406,9 @@ namespace Netch.Forms
private void ShowHideConsoleToolStripMenuItem_Click(object sender, EventArgs e)
{
var windowStyles = (WINDOW_STYLE)PInvoke.GetWindowLong(new HWND(Netch.ConsoleHwnd), WINDOW_LONG_PTR_INDEX.GWL_STYLE);
var windowStyles = (WINDOW_STYLE)PInvoke.GetWindowLong(new HWND(Program.ConsoleHwnd), WINDOW_LONG_PTR_INDEX.GWL_STYLE);
var visible = windowStyles.HasFlag(WINDOW_STYLE.WS_VISIBLE);
PInvoke.ShowWindow(Netch.ConsoleHwnd, visible ? SHOW_WINDOW_CMD.SW_HIDE : SHOW_WINDOW_CMD.SW_SHOWNOACTIVATE);
PInvoke.ShowWindow(Program.ConsoleHwnd, visible ? SHOW_WINDOW_CMD.SW_HIDE : SHOW_WINDOW_CMD.SW_SHOWNOACTIVATE);
}
#endregion
@@ -402,7 +416,7 @@ namespace Netch.Forms
/// <summary>
/// 菜单栏强制退出
/// </summary>
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
private void ForceExitToolStripMenuItem_Click(object sender, EventArgs e)
{
Exit(true);
}
@@ -464,7 +478,6 @@ namespace Netch.Forms
throw new MessageException(i18N.Translate("The downloaded file has the wrong hash"));
}
ModeHelper.SuspendWatcher = true;
await StopAsync();
await Configuration.SaveAsync();
@@ -472,7 +485,7 @@ namespace Netch.Forms
await Task.Run(updater.ApplyUpdate);
// release mutex, exit
Netch.SingleInstance.Dispose();
Program.SingleInstance.Dispose();
Process.Start(Global.NetchExecutable);
Environment.Exit(0);
}
@@ -482,7 +495,7 @@ namespace Netch.Forms
}
catch (Exception exception)
{
Log.Error(exception, "更新未处理异常");
Log.Error(exception, "Unhandled Update error");
NotifyTip(exception.Message, info: false);
}
finally
@@ -582,7 +595,7 @@ namespace Netch.Forms
private void SettingsButton_Click(object sender, EventArgs e)
{
var oldSettings = Global.Settings.Clone();
var oldSettings = Global.Settings.ShallowCopy();
Hide();
new SettingForm().ShowDialog();
@@ -765,25 +778,26 @@ namespace Netch.Forms
var mode = (Mode)ModeComboBox.SelectedItem;
if (ModifierKeys == Keys.Control)
{
Utils.Utils.Open(ModeHelper.GetFullPath(mode.RelativePath!));
Utils.Utils.Open(mode.FullName);
return;
}
switch (mode.Type)
{
case ModeType.Process:
case ModeType.ProcessMode:
Hide();
new ProcessForm(mode).ShowDialog();
Show();
break;
case ModeType.ProxyRuleIPs:
case ModeType.BypassRuleIPs:
case ModeType.TunMode:
Hide();
new RouteForm(mode).ShowDialog();
Show();
break;
case ModeType.ShareMode:
// throw new NotImplementedException();
default:
Utils.Utils.Open(ModeHelper.GetFullPath(mode.RelativePath!));
Utils.Utils.Open(mode.FullName);
break;
}
}
@@ -797,7 +811,7 @@ namespace Netch.Forms
return;
}
ModeHelper.Delete((Mode)ModeComboBox.SelectedItem);
ModeService.Delete((Mode)ModeComboBox.SelectedItem);
SelectLastMode();
}
@@ -995,7 +1009,7 @@ namespace Netch.Forms
// 启动需要禁用的控件
ServerToolStripMenuItem.Enabled = ModeToolStripMenuItem.Enabled =
SubscribeToolStripMenuItem.Enabled = UninstallServiceToolStripMenuItem.Enabled = enabled;
SubscriptionToolStripMenuItem.Enabled = UninstallServiceToolStripMenuItem.Enabled = enabled;
}
_state = value;
@@ -1058,6 +1072,8 @@ namespace Netch.Forms
private async Task StopCoreAsync()
{
State = State.Stopping;
_discoveryNatCts?.Cancel();
_httpConnectCts?.Cancel();
await MainController.StopAsync();
State = State.Stopped;
}
@@ -1082,9 +1098,10 @@ namespace Netch.Forms
}
text ??= i18N.Translate(StateExtension.GetStatusString(State));
StatusLabel.Text = i18N.Translate("Status", ": ") + text;
if (_state == State.Started)
StatusLabel.Text += StatusPortInfoText.Value;
text += StatusPortInfoText.Value;
StatusLabel.Text = i18N.Translate("Status", ": ") + text;
}
public void BandwidthState(bool state)
@@ -1123,9 +1140,9 @@ namespace Netch.Forms
private void ConnectivityStatusVisible(bool visible)
{
if (!visible)
TcpStatusLabel.Text = NatTypeStatusLabel.Text = "";
HttpStatusLabel.Text = NatTypeStatusLabel.Text = "";
TcpStatusLabel.Visible = NatTypeStatusLabel.Visible = NatTypeStatusLightLabel.Visible = visible;
HttpStatusLabel.Visible = NatTypeStatusLabel.Visible = NatTypeStatusLightLabel.Visible = visible;
}
/// <summary>
@@ -1164,19 +1181,20 @@ namespace Netch.Forms
await DiscoveryNatTypeAsync();
}
private CancellationTokenSource? _discoveryNatCts;
private async Task DiscoveryNatTypeAsync()
{
NatTypeStatusLabel.Enabled = false;
NatTypeStatusLabel.Text = i18N.Translate("Testing NAT Type");
UpdateNatTypeStatusLabelText(i18N.Translate("Testing NAT Type"));
using var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(5));
var discoveryNatTypeAsync = MainController.DiscoveryNatTypeAsync(cts.Token);
_discoveryNatCts = new CancellationTokenSource();
try
{
var res = await discoveryNatTypeAsync;
var res = await MainController.DiscoveryNatTypeAsync(_discoveryNatCts.Token);
if (_discoveryNatCts.IsCancellationRequested)
return;
if (!string.IsNullOrEmpty(res.PublicEnd))
{
@@ -1196,31 +1214,38 @@ namespace Netch.Forms
}
finally
{
_discoveryNatCts.Dispose();
_discoveryNatCts = null;
NatTypeStatusLabel.Enabled = true;
}
}
private CancellationTokenSource? _httpConnectCts;
private async Task HttpConnectAsync()
{
TcpStatusLabel.Enabled = false;
HttpStatusLabel.Enabled = false;
using var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(5));
var httpConnectAsync = MainController.HttpConnectAsync(cts.Token);
_httpConnectCts = new CancellationTokenSource();
try
{
var httpRes = await httpConnectAsync;
if (httpRes != null)
TcpStatusLabel.Text = $"TCP{i18N.Translate(": ")}{httpRes}ms";
else
TcpStatusLabel.Text = $"TCP{i18N.Translate(": ", "Timeout")}";
var res = await MainController.HttpConnectAsync(_httpConnectCts.Token);
if (_httpConnectCts.IsCancellationRequested)
return;
TcpStatusLabel.Visible = true;
if (res != null)
HttpStatusLabel.Text = $"HTTP{i18N.Translate(": ")}{res}ms";
else
HttpStatusLabel.Text = $"HTTP{i18N.Translate(": ", "Timeout")}";
HttpStatusLabel.Visible = true;
}
finally
{
TcpStatusLabel.Enabled = true;
_httpConnectCts.Dispose();
_httpConnectCts = null;
HttpStatusLabel.Enabled = true;
}
}
@@ -1242,7 +1267,7 @@ namespace Netch.Forms
if (!IsWaiting())
{
_resumeFlag = true;
Log.Information("操作系统即将挂起,自动停止");
Log.Information("OS Suspend, Stop");
ControlButton_Click(null, null);
}
@@ -1251,7 +1276,7 @@ namespace Netch.Forms
if (_resumeFlag)
{
_resumeFlag = false;
Log.Information("操作系统即将从挂起状态继续,自动重启");
Log.Information("OS Resume, Restart");
ControlButton_Click(null, null);
}
@@ -1478,6 +1503,7 @@ namespace Netch.Forms
}
case Mode item:
{
/*
// 绘制 模式Box 底色
e.Graphics.FillRectangle(Brushes.Gray, _numberBoxX, e.Bounds.Y, _numberBoxWidth, e.Bounds.Height);
@@ -1488,6 +1514,7 @@ namespace Netch.Forms
new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y),
Color.Black,
TextFormatFlags.Left);
*/
break;
}

View File

@@ -20,7 +20,7 @@ namespace Netch.Forms.ModeForms
return string.Empty;
var safeFileName = ToSafeFileName(name);
var relativePath = $"Custom\\{safeFileName}.txt";
var relativePath = $"Custom\\{safeFileName}.json";
return relativePath;
}
}

View File

@@ -32,43 +32,103 @@ namespace Netch.Forms.ModeForms
private void InitializeComponent()
{
this.ConfigurationGroupBox = new System.Windows.Forms.GroupBox();
this.ConfigurationLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.NamePanel = new System.Windows.Forms.Panel();
this.RemarkLabel = new System.Windows.Forms.Label();
this.RemarkTextBox = new System.Windows.Forms.TextBox();
this.FilenameLabel = new System.Windows.Forms.Label();
this.FilenameTextBox = new System.Windows.Forms.TextBox();
this.containerControl1 = new System.Windows.Forms.ContainerControl();
this.RuleRichTextBox = new System.Windows.Forms.RichTextBox();
this.ProcessGroupBox = new System.Windows.Forms.GroupBox();
this.SelectButton = new System.Windows.Forms.Button();
this.ScanButton = new System.Windows.Forms.Button();
this.ValidationButton = new System.Windows.Forms.Button();
this.ControlButton = new System.Windows.Forms.Button();
this.OptionsGroupBox = new System.Windows.Forms.GroupBox();
this.ModeSpecificOptionsLabel = new System.Windows.Forms.Label();
this.HandleTCPCheckBox = new Netch.Forms.SyncGlobalCheckBox();
this.HandleUDPCheckBox = new Netch.Forms.SyncGlobalCheckBox();
this.HandleDNSCheckBox = new Netch.Forms.SyncGlobalCheckBox();
this.DNSLabel = new System.Windows.Forms.Label();
this.DNSTextBox = new System.Windows.Forms.TextBox();
this.HandleProcDNSCheckBox = new Netch.Forms.SyncGlobalCheckBox();
this.ProxyDNSCheckBox = new Netch.Forms.SyncGlobalCheckBox();
this.HandleICMPCheckBox = new Netch.Forms.SyncGlobalCheckBox();
this.ICMPDelayLabel = new System.Windows.Forms.Label();
this.ICMPDelayTextBox = new System.Windows.Forms.TextBox();
this.HandleLoopbackCheckBox = new System.Windows.Forms.CheckBox();
this.HandleLANCheckBox = new System.Windows.Forms.CheckBox();
this.HandleChildProcCheckBox = new Netch.Forms.SyncGlobalCheckBox();
this.RuleTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.ValidationButton = new System.Windows.Forms.Button();
this.HandleTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.HandleHelperFlowLayoutPanel = new System.Windows.Forms.FlowLayoutPanel();
this.HandleLabel = new System.Windows.Forms.Label();
this.HandleSelectButton = new System.Windows.Forms.Button();
this.HandleScanButton = new System.Windows.Forms.Button();
this.HandleContentTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.HandleRuleRichTextBox = new System.Windows.Forms.RichTextBox();
this.BypassTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.BypassFlowLayoutPanel = new System.Windows.Forms.FlowLayoutPanel();
this.BypassLabel = new System.Windows.Forms.Label();
this.BypassSelectButton = new System.Windows.Forms.Button();
this.BypassScanButton = new System.Windows.Forms.Button();
this.BypassContentTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.BypassRuleRichTextBox = new System.Windows.Forms.RichTextBox();
this.ConfigurationGroupBox.SuspendLayout();
this.containerControl1.SuspendLayout();
this.ProcessGroupBox.SuspendLayout();
this.ConfigurationLayoutPanel.SuspendLayout();
this.NamePanel.SuspendLayout();
this.OptionsGroupBox.SuspendLayout();
this.RuleTableLayoutPanel.SuspendLayout();
this.HandleTableLayoutPanel.SuspendLayout();
this.HandleHelperFlowLayoutPanel.SuspendLayout();
this.HandleContentTableLayoutPanel.SuspendLayout();
this.BypassTableLayoutPanel.SuspendLayout();
this.BypassFlowLayoutPanel.SuspendLayout();
this.BypassContentTableLayoutPanel.SuspendLayout();
this.SuspendLayout();
//
// ConfigurationGroupBox
//
this.ConfigurationGroupBox.Controls.Add(this.RemarkLabel);
this.ConfigurationGroupBox.Controls.Add(this.RemarkTextBox);
this.ConfigurationGroupBox.Controls.Add(this.FilenameLabel);
this.ConfigurationGroupBox.Controls.Add(this.FilenameTextBox);
this.ConfigurationGroupBox.Controls.Add(this.containerControl1);
this.ConfigurationGroupBox.Controls.Add(this.ProcessGroupBox);
this.ConfigurationGroupBox.Controls.Add(this.ControlButton);
this.ConfigurationGroupBox.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.ConfigurationGroupBox.Controls.Add(this.ConfigurationLayoutPanel);
this.ConfigurationGroupBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.ConfigurationGroupBox.Location = new System.Drawing.Point(12, 5);
this.ConfigurationGroupBox.Location = new System.Drawing.Point(0, 0);
this.ConfigurationGroupBox.Name = "ConfigurationGroupBox";
this.ConfigurationGroupBox.Size = new System.Drawing.Size(431, 378);
this.ConfigurationGroupBox.Size = new System.Drawing.Size(934, 591);
this.ConfigurationGroupBox.TabIndex = 0;
this.ConfigurationGroupBox.TabStop = false;
this.ConfigurationGroupBox.Text = "Configuration";
//
// ConfigurationLayoutPanel
//
this.ConfigurationLayoutPanel.ColumnCount = 1;
this.ConfigurationLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.ConfigurationLayoutPanel.Controls.Add(this.NamePanel, 0, 0);
this.ConfigurationLayoutPanel.Controls.Add(this.OptionsGroupBox, 0, 1);
this.ConfigurationLayoutPanel.Controls.Add(this.RuleTableLayoutPanel, 0, 2);
this.ConfigurationLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.ConfigurationLayoutPanel.Location = new System.Drawing.Point(3, 19);
this.ConfigurationLayoutPanel.Name = "ConfigurationLayoutPanel";
this.ConfigurationLayoutPanel.RowCount = 3;
this.ConfigurationLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.ConfigurationLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.ConfigurationLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.ConfigurationLayoutPanel.Size = new System.Drawing.Size(928, 569);
this.ConfigurationLayoutPanel.TabIndex = 0;
//
// NamePanel
//
this.NamePanel.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.NamePanel.Controls.Add(this.RemarkLabel);
this.NamePanel.Controls.Add(this.RemarkTextBox);
this.NamePanel.Controls.Add(this.FilenameLabel);
this.NamePanel.Controls.Add(this.FilenameTextBox);
this.NamePanel.Controls.Add(this.ControlButton);
this.NamePanel.Location = new System.Drawing.Point(208, 3);
this.NamePanel.Name = "NamePanel";
this.NamePanel.Size = new System.Drawing.Size(512, 72);
this.NamePanel.TabIndex = 0;
//
// RemarkLabel
//
this.RemarkLabel.AutoSize = true;
this.RemarkLabel.Location = new System.Drawing.Point(12, 25);
this.RemarkLabel.Location = new System.Drawing.Point(8, 8);
this.RemarkLabel.Name = "RemarkLabel";
this.RemarkLabel.Size = new System.Drawing.Size(53, 17);
this.RemarkLabel.TabIndex = 0;
@@ -76,7 +136,7 @@ namespace Netch.Forms.ModeForms
//
// RemarkTextBox
//
this.RemarkTextBox.Location = new System.Drawing.Point(84, 22);
this.RemarkTextBox.Location = new System.Drawing.Point(72, 8);
this.RemarkTextBox.Name = "RemarkTextBox";
this.RemarkTextBox.Size = new System.Drawing.Size(341, 23);
this.RemarkTextBox.TabIndex = 1;
@@ -85,7 +145,7 @@ namespace Netch.Forms.ModeForms
// FilenameLabel
//
this.FilenameLabel.AutoSize = true;
this.FilenameLabel.Location = new System.Drawing.Point(12, 55);
this.FilenameLabel.Location = new System.Drawing.Point(8, 40);
this.FilenameLabel.Name = "FilenameLabel";
this.FilenameLabel.Size = new System.Drawing.Size(59, 17);
this.FilenameLabel.TabIndex = 2;
@@ -93,119 +153,491 @@ namespace Netch.Forms.ModeForms
//
// FilenameTextBox
//
this.FilenameTextBox.Location = new System.Drawing.Point(84, 52);
this.FilenameTextBox.Location = new System.Drawing.Point(72, 40);
this.FilenameTextBox.Name = "FilenameTextBox";
this.FilenameTextBox.ReadOnly = true;
this.FilenameTextBox.Size = new System.Drawing.Size(341, 23);
this.FilenameTextBox.TabIndex = 3;
//
// containerControl1
//
this.containerControl1.Controls.Add(this.RuleRichTextBox);
this.containerControl1.Location = new System.Drawing.Point(6, 81);
this.containerControl1.Name = "containerControl1";
this.containerControl1.Size = new System.Drawing.Size(419, 221);
this.containerControl1.TabIndex = 4;
this.containerControl1.Text = "containerControl1";
//
// RuleRichTextBox
//
this.RuleRichTextBox.DetectUrls = false;
this.RuleRichTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.RuleRichTextBox.Location = new System.Drawing.Point(0, 0);
this.RuleRichTextBox.Name = "RuleRichTextBox";
this.RuleRichTextBox.Size = new System.Drawing.Size(419, 221);
this.RuleRichTextBox.TabIndex = 0;
this.RuleRichTextBox.Text = "";
this.RuleRichTextBox.WordWrap = false;
//
// ProcessGroupBox
//
this.ProcessGroupBox.Controls.Add(this.SelectButton);
this.ProcessGroupBox.Controls.Add(this.ScanButton);
this.ProcessGroupBox.Controls.Add(this.ValidationButton);
this.ProcessGroupBox.Location = new System.Drawing.Point(6, 295);
this.ProcessGroupBox.Name = "ProcessGroupBox";
this.ProcessGroupBox.Size = new System.Drawing.Size(419, 44);
this.ProcessGroupBox.TabIndex = 5;
this.ProcessGroupBox.TabStop = false;
//
// SelectButton
//
this.SelectButton.Location = new System.Drawing.Point(6, 13);
this.SelectButton.Name = "SelectButton";
this.SelectButton.Size = new System.Drawing.Size(75, 23);
this.SelectButton.TabIndex = 0;
this.SelectButton.Text = "Select";
this.SelectButton.UseVisualStyleBackColor = true;
this.SelectButton.Click += new System.EventHandler(this.SelectButton_Click);
//
// ScanButton
//
this.ScanButton.Location = new System.Drawing.Point(87, 13);
this.ScanButton.Name = "ScanButton";
this.ScanButton.Size = new System.Drawing.Size(75, 23);
this.ScanButton.TabIndex = 1;
this.ScanButton.Text = "Scan";
this.ScanButton.UseVisualStyleBackColor = true;
this.ScanButton.Click += new System.EventHandler(this.ScanButton_Click);
//
// ValidationButton
//
this.ValidationButton.Location = new System.Drawing.Point(338, 13);
this.ValidationButton.Name = "ValidationButton";
this.ValidationButton.Size = new System.Drawing.Size(75, 23);
this.ValidationButton.TabIndex = 2;
this.ValidationButton.Text = "Validation";
this.ValidationButton.UseVisualStyleBackColor = true;
this.ValidationButton.Click += new System.EventHandler(this.ValidationButton_Click);
//
// ControlButton
//
this.ControlButton.Location = new System.Drawing.Point(344, 345);
this.ControlButton.Location = new System.Drawing.Point(424, 40);
this.ControlButton.Name = "ControlButton";
this.ControlButton.Size = new System.Drawing.Size(75, 23);
this.ControlButton.TabIndex = 6;
this.ControlButton.TabIndex = 4;
this.ControlButton.Text = "Save";
this.ControlButton.UseVisualStyleBackColor = true;
this.ControlButton.Click += new System.EventHandler(this.ControlButton_Click);
//
// Process
// OptionsGroupBox
//
this.OptionsGroupBox.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.OptionsGroupBox.Controls.Add(this.ModeSpecificOptionsLabel);
this.OptionsGroupBox.Controls.Add(this.HandleTCPCheckBox);
this.OptionsGroupBox.Controls.Add(this.HandleUDPCheckBox);
this.OptionsGroupBox.Controls.Add(this.HandleDNSCheckBox);
this.OptionsGroupBox.Controls.Add(this.DNSLabel);
this.OptionsGroupBox.Controls.Add(this.DNSTextBox);
this.OptionsGroupBox.Controls.Add(this.HandleProcDNSCheckBox);
this.OptionsGroupBox.Controls.Add(this.ProxyDNSCheckBox);
this.OptionsGroupBox.Controls.Add(this.HandleICMPCheckBox);
this.OptionsGroupBox.Controls.Add(this.ICMPDelayLabel);
this.OptionsGroupBox.Controls.Add(this.ICMPDelayTextBox);
this.OptionsGroupBox.Controls.Add(this.HandleLoopbackCheckBox);
this.OptionsGroupBox.Controls.Add(this.HandleLANCheckBox);
this.OptionsGroupBox.Controls.Add(this.HandleChildProcCheckBox);
this.OptionsGroupBox.Location = new System.Drawing.Point(15, 81);
this.OptionsGroupBox.Name = "OptionsGroupBox";
this.OptionsGroupBox.Size = new System.Drawing.Size(898, 183);
this.OptionsGroupBox.TabIndex = 1;
this.OptionsGroupBox.TabStop = false;
//
// ModeSpecificOptionsLabel
//
this.ModeSpecificOptionsLabel.AutoSize = true;
this.ModeSpecificOptionsLabel.Location = new System.Drawing.Point(720, 24);
this.ModeSpecificOptionsLabel.Name = "ModeSpecificOptionsLabel";
this.ModeSpecificOptionsLabel.Size = new System.Drawing.Size(138, 17);
this.ModeSpecificOptionsLabel.TabIndex = 13;
this.ModeSpecificOptionsLabel.Text = "Mode specific options";
//
// HandleTCPCheckBox
//
this.HandleTCPCheckBox.AutoCheck = false;
this.HandleTCPCheckBox.AutoSize = true;
this.HandleTCPCheckBox.BackColor = System.Drawing.Color.Yellow;
this.HandleTCPCheckBox.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point);
this.HandleTCPCheckBox.GlobalValue = false;
this.HandleTCPCheckBox.Location = new System.Drawing.Point(8, 24);
this.HandleTCPCheckBox.Name = "HandleTCPCheckBox";
this.HandleTCPCheckBox.Size = new System.Drawing.Size(99, 21);
this.HandleTCPCheckBox.SyncGlobal = false;
this.HandleTCPCheckBox.TabIndex = 0;
this.HandleTCPCheckBox.Text = "Handle TCP";
this.HandleTCPCheckBox.ThreeState = true;
this.HandleTCPCheckBox.UseVisualStyleBackColor = true;
this.HandleTCPCheckBox.Value = false;
//
// HandleUDPCheckBox
//
this.HandleUDPCheckBox.AutoCheck = false;
this.HandleUDPCheckBox.AutoSize = true;
this.HandleUDPCheckBox.BackColor = System.Drawing.Color.Yellow;
this.HandleUDPCheckBox.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point);
this.HandleUDPCheckBox.GlobalValue = false;
this.HandleUDPCheckBox.Location = new System.Drawing.Point(8, 56);
this.HandleUDPCheckBox.Name = "HandleUDPCheckBox";
this.HandleUDPCheckBox.Size = new System.Drawing.Size(102, 21);
this.HandleUDPCheckBox.SyncGlobal = false;
this.HandleUDPCheckBox.TabIndex = 1;
this.HandleUDPCheckBox.Text = "Handle UDP";
this.HandleUDPCheckBox.ThreeState = true;
this.HandleUDPCheckBox.UseVisualStyleBackColor = true;
this.HandleUDPCheckBox.Value = false;
//
// HandleDNSCheckBox
//
this.HandleDNSCheckBox.AutoCheck = false;
this.HandleDNSCheckBox.AutoSize = true;
this.HandleDNSCheckBox.BackColor = System.Drawing.Color.Yellow;
this.HandleDNSCheckBox.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point);
this.HandleDNSCheckBox.GlobalValue = false;
this.HandleDNSCheckBox.Location = new System.Drawing.Point(8, 88);
this.HandleDNSCheckBox.Name = "HandleDNSCheckBox";
this.HandleDNSCheckBox.Size = new System.Drawing.Size(203, 21);
this.HandleDNSCheckBox.SyncGlobal = false;
this.HandleDNSCheckBox.TabIndex = 2;
this.HandleDNSCheckBox.Text = "Handle DNS (DNS hijacking)";
this.HandleDNSCheckBox.ThreeState = true;
this.HandleDNSCheckBox.UseVisualStyleBackColor = true;
this.HandleDNSCheckBox.Value = false;
//
// DNSLabel
//
this.DNSLabel.AutoSize = true;
this.DNSLabel.Location = new System.Drawing.Point(248, 88);
this.DNSLabel.Name = "DNSLabel";
this.DNSLabel.Size = new System.Drawing.Size(34, 17);
this.DNSLabel.TabIndex = 3;
this.DNSLabel.Text = "DNS";
//
// DNSTextBox
//
this.DNSTextBox.Location = new System.Drawing.Point(296, 88);
this.DNSTextBox.Name = "DNSTextBox";
this.DNSTextBox.Size = new System.Drawing.Size(184, 23);
this.DNSTextBox.TabIndex = 4;
this.DNSTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// HandleProcDNSCheckBox
//
this.HandleProcDNSCheckBox.AutoCheck = false;
this.HandleProcDNSCheckBox.AutoSize = true;
this.HandleProcDNSCheckBox.BackColor = System.Drawing.Color.Yellow;
this.HandleProcDNSCheckBox.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point);
this.HandleProcDNSCheckBox.GlobalValue = false;
this.HandleProcDNSCheckBox.Location = new System.Drawing.Point(8, 120);
this.HandleProcDNSCheckBox.Name = "HandleProcDNSCheckBox";
this.HandleProcDNSCheckBox.Size = new System.Drawing.Size(216, 21);
this.HandleProcDNSCheckBox.SyncGlobal = false;
this.HandleProcDNSCheckBox.TabIndex = 5;
this.HandleProcDNSCheckBox.Text = "Handle handled process\'s DNS";
this.HandleProcDNSCheckBox.ThreeState = true;
this.HandleProcDNSCheckBox.UseVisualStyleBackColor = true;
this.HandleProcDNSCheckBox.Value = false;
//
// ProxyDNSCheckBox
//
this.ProxyDNSCheckBox.AutoCheck = false;
this.ProxyDNSCheckBox.AutoSize = true;
this.ProxyDNSCheckBox.BackColor = System.Drawing.Color.Yellow;
this.ProxyDNSCheckBox.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point);
this.ProxyDNSCheckBox.GlobalValue = false;
this.ProxyDNSCheckBox.Location = new System.Drawing.Point(240, 120);
this.ProxyDNSCheckBox.Name = "ProxyDNSCheckBox";
this.ProxyDNSCheckBox.Size = new System.Drawing.Size(195, 21);
this.ProxyDNSCheckBox.SyncGlobal = false;
this.ProxyDNSCheckBox.TabIndex = 6;
this.ProxyDNSCheckBox.Text = "Handle DNS through proxy";
this.ProxyDNSCheckBox.ThreeState = true;
this.ProxyDNSCheckBox.UseVisualStyleBackColor = true;
this.ProxyDNSCheckBox.Value = false;
//
// HandleICMPCheckBox
//
this.HandleICMPCheckBox.AutoCheck = false;
this.HandleICMPCheckBox.AutoSize = true;
this.HandleICMPCheckBox.BackColor = System.Drawing.Color.Yellow;
this.HandleICMPCheckBox.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point);
this.HandleICMPCheckBox.GlobalValue = false;
this.HandleICMPCheckBox.Location = new System.Drawing.Point(8, 152);
this.HandleICMPCheckBox.Name = "HandleICMPCheckBox";
this.HandleICMPCheckBox.Size = new System.Drawing.Size(107, 21);
this.HandleICMPCheckBox.SyncGlobal = false;
this.HandleICMPCheckBox.TabIndex = 7;
this.HandleICMPCheckBox.Text = "Handle ICMP";
this.HandleICMPCheckBox.ThreeState = true;
this.HandleICMPCheckBox.UseVisualStyleBackColor = true;
this.HandleICMPCheckBox.Value = false;
//
// ICMPDelayLabel
//
this.ICMPDelayLabel.AutoSize = true;
this.ICMPDelayLabel.Location = new System.Drawing.Point(176, 152);
this.ICMPDelayLabel.Name = "ICMPDelayLabel";
this.ICMPDelayLabel.Size = new System.Drawing.Size(99, 17);
this.ICMPDelayLabel.TabIndex = 8;
this.ICMPDelayLabel.Text = "ICMP delay(ms)";
//
// ICMPDelayTextBox
//
this.ICMPDelayTextBox.Location = new System.Drawing.Point(296, 152);
this.ICMPDelayTextBox.Name = "ICMPDelayTextBox";
this.ICMPDelayTextBox.Size = new System.Drawing.Size(80, 23);
this.ICMPDelayTextBox.TabIndex = 9;
this.ICMPDelayTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// HandleLoopbackCheckBox
//
this.HandleLoopbackCheckBox.AutoSize = true;
this.HandleLoopbackCheckBox.Location = new System.Drawing.Point(720, 56);
this.HandleLoopbackCheckBox.Name = "HandleLoopbackCheckBox";
this.HandleLoopbackCheckBox.Size = new System.Drawing.Size(158, 21);
this.HandleLoopbackCheckBox.TabIndex = 10;
this.HandleLoopbackCheckBox.Text = "Handle local loopback";
this.HandleLoopbackCheckBox.UseVisualStyleBackColor = true;
//
// HandleLANCheckBox
//
this.HandleLANCheckBox.AutoSize = true;
this.HandleLANCheckBox.Location = new System.Drawing.Point(720, 88);
this.HandleLANCheckBox.Name = "HandleLANCheckBox";
this.HandleLANCheckBox.Size = new System.Drawing.Size(96, 21);
this.HandleLANCheckBox.TabIndex = 11;
this.HandleLANCheckBox.Text = "Handle LAN";
this.HandleLANCheckBox.UseVisualStyleBackColor = true;
//
// HandleChildProcCheckBox
//
this.HandleChildProcCheckBox.AutoCheck = false;
this.HandleChildProcCheckBox.AutoSize = true;
this.HandleChildProcCheckBox.BackColor = System.Drawing.Color.Yellow;
this.HandleChildProcCheckBox.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point);
this.HandleChildProcCheckBox.GlobalValue = false;
this.HandleChildProcCheckBox.Location = new System.Drawing.Point(496, 24);
this.HandleChildProcCheckBox.Name = "HandleChildProcCheckBox";
this.HandleChildProcCheckBox.Size = new System.Drawing.Size(155, 21);
this.HandleChildProcCheckBox.SyncGlobal = false;
this.HandleChildProcCheckBox.TabIndex = 12;
this.HandleChildProcCheckBox.Text = "Handle child process";
this.HandleChildProcCheckBox.ThreeState = true;
this.HandleChildProcCheckBox.UseVisualStyleBackColor = true;
this.HandleChildProcCheckBox.Value = false;
//
// RuleTableLayoutPanel
//
this.RuleTableLayoutPanel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.RuleTableLayoutPanel.ColumnCount = 2;
this.RuleTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.RuleTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.RuleTableLayoutPanel.Controls.Add(this.ValidationButton, 0, 0);
this.RuleTableLayoutPanel.Controls.Add(this.HandleTableLayoutPanel, 0, 1);
this.RuleTableLayoutPanel.Controls.Add(this.BypassTableLayoutPanel, 1, 1);
this.RuleTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.RuleTableLayoutPanel.Location = new System.Drawing.Point(3, 270);
this.RuleTableLayoutPanel.Name = "RuleTableLayoutPanel";
this.RuleTableLayoutPanel.RowCount = 2;
this.RuleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.RuleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.RuleTableLayoutPanel.Size = new System.Drawing.Size(922, 296);
this.RuleTableLayoutPanel.TabIndex = 2;
//
// ValidationButton
//
this.ValidationButton.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.RuleTableLayoutPanel.SetColumnSpan(this.ValidationButton, 2);
this.ValidationButton.Location = new System.Drawing.Point(423, 3);
this.ValidationButton.Name = "ValidationButton";
this.ValidationButton.Size = new System.Drawing.Size(75, 23);
this.ValidationButton.TabIndex = 0;
this.ValidationButton.Text = "Validation";
this.ValidationButton.UseVisualStyleBackColor = true;
this.ValidationButton.Click += new System.EventHandler(this.ValidationButton_Click);
//
// HandleTableLayoutPanel
//
this.HandleTableLayoutPanel.ColumnCount = 1;
this.HandleTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.HandleTableLayoutPanel.Controls.Add(this.HandleHelperFlowLayoutPanel, 0, 0);
this.HandleTableLayoutPanel.Controls.Add(this.HandleContentTableLayoutPanel, 0, 1);
this.HandleTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.HandleTableLayoutPanel.Location = new System.Drawing.Point(3, 32);
this.HandleTableLayoutPanel.Name = "HandleTableLayoutPanel";
this.HandleTableLayoutPanel.RowCount = 2;
this.HandleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.HandleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.HandleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.HandleTableLayoutPanel.Size = new System.Drawing.Size(455, 261);
this.HandleTableLayoutPanel.TabIndex = 1;
//
// HandleHelperFlowLayoutPanel
//
this.HandleHelperFlowLayoutPanel.Controls.Add(this.HandleLabel);
this.HandleHelperFlowLayoutPanel.Controls.Add(this.HandleSelectButton);
this.HandleHelperFlowLayoutPanel.Controls.Add(this.HandleScanButton);
this.HandleHelperFlowLayoutPanel.Location = new System.Drawing.Point(3, 3);
this.HandleHelperFlowLayoutPanel.Name = "HandleHelperFlowLayoutPanel";
this.HandleHelperFlowLayoutPanel.Size = new System.Drawing.Size(269, 32);
this.HandleHelperFlowLayoutPanel.TabIndex = 0;
//
// HandleLabel
//
this.HandleLabel.AutoSize = true;
this.HandleLabel.Location = new System.Drawing.Point(3, 0);
this.HandleLabel.Name = "HandleLabel";
this.HandleLabel.Padding = new System.Windows.Forms.Padding(7);
this.HandleLabel.Size = new System.Drawing.Size(95, 31);
this.HandleLabel.TabIndex = 0;
this.HandleLabel.Text = "Handle rules";
//
// HandleSelectButton
//
this.HandleSelectButton.Location = new System.Drawing.Point(104, 3);
this.HandleSelectButton.Name = "HandleSelectButton";
this.HandleSelectButton.Size = new System.Drawing.Size(75, 23);
this.HandleSelectButton.TabIndex = 1;
this.HandleSelectButton.Text = "Select";
this.HandleSelectButton.UseVisualStyleBackColor = true;
this.HandleSelectButton.Click += new System.EventHandler(this.SelectButton_Click);
//
// HandleScanButton
//
this.HandleHelperFlowLayoutPanel.SetFlowBreak(this.HandleScanButton, true);
this.HandleScanButton.Location = new System.Drawing.Point(185, 3);
this.HandleScanButton.Name = "HandleScanButton";
this.HandleScanButton.Size = new System.Drawing.Size(75, 23);
this.HandleScanButton.TabIndex = 2;
this.HandleScanButton.Text = "Scan";
this.HandleScanButton.UseVisualStyleBackColor = true;
this.HandleScanButton.Click += new System.EventHandler(this.ScanButton_Click);
//
// HandleContentTableLayoutPanel
//
this.HandleContentTableLayoutPanel.ColumnCount = 1;
this.HandleContentTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.HandleContentTableLayoutPanel.Controls.Add(this.HandleRuleRichTextBox, 0, 0);
this.HandleContentTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.HandleContentTableLayoutPanel.Location = new System.Drawing.Point(3, 41);
this.HandleContentTableLayoutPanel.Name = "HandleContentTableLayoutPanel";
this.HandleContentTableLayoutPanel.RowCount = 1;
this.HandleContentTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.HandleContentTableLayoutPanel.Size = new System.Drawing.Size(449, 217);
this.HandleContentTableLayoutPanel.TabIndex = 1;
//
// HandleRuleRichTextBox
//
this.HandleRuleRichTextBox.DetectUrls = false;
this.HandleRuleRichTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.HandleRuleRichTextBox.Location = new System.Drawing.Point(3, 3);
this.HandleRuleRichTextBox.Name = "HandleRuleRichTextBox";
this.HandleRuleRichTextBox.Size = new System.Drawing.Size(443, 211);
this.HandleRuleRichTextBox.TabIndex = 0;
this.HandleRuleRichTextBox.Text = "";
this.HandleRuleRichTextBox.WordWrap = false;
//
// BypassTableLayoutPanel
//
this.BypassTableLayoutPanel.ColumnCount = 1;
this.BypassTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.BypassTableLayoutPanel.Controls.Add(this.BypassFlowLayoutPanel, 0, 0);
this.BypassTableLayoutPanel.Controls.Add(this.BypassContentTableLayoutPanel, 0, 1);
this.BypassTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.BypassTableLayoutPanel.Location = new System.Drawing.Point(464, 32);
this.BypassTableLayoutPanel.Name = "BypassTableLayoutPanel";
this.BypassTableLayoutPanel.RowCount = 2;
this.BypassTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.BypassTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.BypassTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.BypassTableLayoutPanel.Size = new System.Drawing.Size(455, 261);
this.BypassTableLayoutPanel.TabIndex = 2;
//
// BypassFlowLayoutPanel
//
this.BypassFlowLayoutPanel.Controls.Add(this.BypassLabel);
this.BypassFlowLayoutPanel.Controls.Add(this.BypassSelectButton);
this.BypassFlowLayoutPanel.Controls.Add(this.BypassScanButton);
this.BypassFlowLayoutPanel.Location = new System.Drawing.Point(3, 3);
this.BypassFlowLayoutPanel.Name = "BypassFlowLayoutPanel";
this.BypassFlowLayoutPanel.Size = new System.Drawing.Size(269, 32);
this.BypassFlowLayoutPanel.TabIndex = 0;
//
// BypassLabel
//
this.BypassLabel.AutoSize = true;
this.BypassLabel.Location = new System.Drawing.Point(3, 0);
this.BypassLabel.Name = "BypassLabel";
this.BypassLabel.Padding = new System.Windows.Forms.Padding(7);
this.BypassLabel.Size = new System.Drawing.Size(95, 31);
this.BypassLabel.TabIndex = 0;
this.BypassLabel.Text = "Bypass rules";
//
// BypassSelectButton
//
this.BypassSelectButton.Location = new System.Drawing.Point(104, 3);
this.BypassSelectButton.Name = "BypassSelectButton";
this.BypassSelectButton.Size = new System.Drawing.Size(75, 23);
this.BypassSelectButton.TabIndex = 1;
this.BypassSelectButton.Text = "Select";
this.BypassSelectButton.UseVisualStyleBackColor = true;
this.BypassSelectButton.Click += new System.EventHandler(this.SelectButton_Click);
//
// BypassScanButton
//
this.BypassScanButton.Location = new System.Drawing.Point(185, 3);
this.BypassScanButton.Name = "BypassScanButton";
this.BypassScanButton.Size = new System.Drawing.Size(75, 23);
this.BypassScanButton.TabIndex = 2;
this.BypassScanButton.Text = "Scan";
this.BypassScanButton.UseVisualStyleBackColor = true;
this.BypassScanButton.Click += new System.EventHandler(this.ScanButton_Click);
//
// BypassContentTableLayoutPanel
//
this.BypassContentTableLayoutPanel.ColumnCount = 1;
this.BypassContentTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.BypassContentTableLayoutPanel.Controls.Add(this.BypassRuleRichTextBox, 0, 0);
this.BypassContentTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.BypassContentTableLayoutPanel.Location = new System.Drawing.Point(3, 41);
this.BypassContentTableLayoutPanel.Name = "BypassContentTableLayoutPanel";
this.BypassContentTableLayoutPanel.RowCount = 1;
this.BypassContentTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.BypassContentTableLayoutPanel.Size = new System.Drawing.Size(449, 217);
this.BypassContentTableLayoutPanel.TabIndex = 1;
//
// BypassRuleRichTextBox
//
this.BypassRuleRichTextBox.DetectUrls = false;
this.BypassRuleRichTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.BypassRuleRichTextBox.Location = new System.Drawing.Point(3, 3);
this.BypassRuleRichTextBox.Name = "BypassRuleRichTextBox";
this.BypassRuleRichTextBox.Size = new System.Drawing.Size(443, 211);
this.BypassRuleRichTextBox.TabIndex = 0;
this.BypassRuleRichTextBox.Text = "";
this.BypassRuleRichTextBox.WordWrap = false;
//
// ProcessForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size(455, 388);
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.ClientSize = new System.Drawing.Size(934, 591);
this.Controls.Add(this.ConfigurationGroupBox);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.MaximizeBox = false;
this.MinimumSize = new System.Drawing.Size(950, 630);
this.Name = "ProcessForm";
this.Padding = new System.Windows.Forms.Padding(12, 5, 12, 5);
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Create Process Mode";
this.Load += new System.EventHandler(this.ModeForm_Load);
this.ConfigurationGroupBox.ResumeLayout(false);
this.ConfigurationGroupBox.PerformLayout();
this.containerControl1.ResumeLayout(false);
this.ProcessGroupBox.ResumeLayout(false);
this.ConfigurationLayoutPanel.ResumeLayout(false);
this.NamePanel.ResumeLayout(false);
this.NamePanel.PerformLayout();
this.OptionsGroupBox.ResumeLayout(false);
this.OptionsGroupBox.PerformLayout();
this.RuleTableLayoutPanel.ResumeLayout(false);
this.HandleTableLayoutPanel.ResumeLayout(false);
this.HandleHelperFlowLayoutPanel.ResumeLayout(false);
this.HandleHelperFlowLayoutPanel.PerformLayout();
this.HandleContentTableLayoutPanel.ResumeLayout(false);
this.BypassTableLayoutPanel.ResumeLayout(false);
this.BypassFlowLayoutPanel.ResumeLayout(false);
this.BypassFlowLayoutPanel.PerformLayout();
this.BypassContentTableLayoutPanel.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button ScanButton;
private System.Windows.Forms.ContainerControl containerControl1;
private System.Windows.Forms.Button HandleScanButton;
public System.Windows.Forms.GroupBox ConfigurationGroupBox;
private System.Windows.Forms.Label RemarkLabel;
private System.Windows.Forms.GroupBox ProcessGroupBox;
private System.Windows.Forms.TextBox RemarkTextBox;
private System.Windows.Forms.Button SelectButton;
private System.Windows.Forms.Button HandleSelectButton;
public System.Windows.Forms.Button ControlButton;
private System.Windows.Forms.Label FilenameLabel;
private System.Windows.Forms.TextBox FilenameTextBox;
private RichTextBox RuleRichTextBox;
private RichTextBox HandleRuleRichTextBox;
private Button ValidationButton;
private RichTextBox BypassRuleRichTextBox;
private Button BypassSelectButton;
private Button BypassScanButton;
private Label BypassLabel;
private Label HandleLabel;
private GroupBox OptionsGroupBox;
private SyncGlobalCheckBox ProxyDNSCheckBox;
private SyncGlobalCheckBox HandleDNSCheckBox;
private SyncGlobalCheckBox HandleUDPCheckBox;
private SyncGlobalCheckBox HandleTCPCheckBox;
private CheckBox HandleLANCheckBox;
private CheckBox HandleLoopbackCheckBox;
private TextBox ICMPDelayTextBox;
private TextBox DNSTextBox;
private SyncGlobalCheckBox HandleICMPCheckBox;
private SyncGlobalCheckBox HandleProcDNSCheckBox;
private Label ICMPDelayLabel;
private Label DNSLabel;
private FlowLayoutPanel BypassFlowLayoutPanel;
private FlowLayoutPanel HandleHelperFlowLayoutPanel;
private TableLayoutPanel ConfigurationLayoutPanel;
private Panel NamePanel;
private TableLayoutPanel HandleTableLayoutPanel;
private TableLayoutPanel RuleTableLayoutPanel;
private TableLayoutPanel BypassTableLayoutPanel;
private TableLayoutPanel HandleContentTableLayoutPanel;
private TableLayoutPanel BypassContentTableLayoutPanel;
private SyncGlobalCheckBox HandleChildProcCheckBox;
private Label ModeSpecificOptionsLabel;
}
}

View File

@@ -1,23 +1,24 @@
using Microsoft.WindowsAPICodePack.Dialogs;
using Netch.Controllers;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Windows.Forms;
using Netch.Controllers;
using Netch.Enums;
using Netch.Models.Modes;
using Netch.Models.Modes.ProcessMode;
using Netch.Properties;
using Netch.Services;
using Netch.Utils;
namespace Netch.Forms.ModeForms
{
public partial class ProcessForm : Form
public partial class ProcessForm : BindingForm
{
/// <summary>
/// 被编辑的模式
/// </summary>
private readonly Mode? _mode;
private readonly bool IsCreateMode;
private readonly Redirector _mode;
/// <summary>
/// 编辑模式
@@ -25,131 +26,141 @@ namespace Netch.Forms.ModeForms
/// <param name="mode">模式</param>
public ProcessForm(Mode? mode = null)
{
if (mode != null && mode.Type is not ModeType.Process)
throw new ArgumentOutOfRangeException();
switch (mode)
{
case Redirector processMode:
IsCreateMode = false;
_mode = processMode;
break;
case null:
IsCreateMode = true;
_mode = new Redirector();
break;
default:
throw new ArgumentOutOfRangeException();
}
InitializeComponent();
Icon = Resources.icon;
CheckForIllegalCrossThreadCalls = false;
InitBindings();
_mode = mode;
var g = Global.Settings.Redirector;
BindTextBox(RemarkTextBox, _ => true, s => _mode.i18NRemark = s, _mode.i18NRemark);
BindSyncGlobalCheckBox(HandleTCPCheckBox, b => _mode.FilterTCP = b, _mode.FilterTCP, g.FilterTCP);
BindSyncGlobalCheckBox(HandleUDPCheckBox, b => _mode.FilterUDP = b, _mode.FilterUDP, g.FilterUDP);
BindSyncGlobalCheckBox(HandleDNSCheckBox, b => _mode.FilterDNS = b, _mode.FilterDNS, g.FilterDNS);
BindTextBox(DNSTextBox, s => IPEndPoint.TryParse(s, out _), s => _mode.DNSHost = s, _mode.DNSHost ?? Constants.DefaultPrimaryDNS);
BindSyncGlobalCheckBox(HandleProcDNSCheckBox, b => _mode.HandleOnlyDNS = b, _mode.HandleOnlyDNS, g.HandleOnlyDNS);
BindSyncGlobalCheckBox(ProxyDNSCheckBox, b => _mode.DNSProxy = b, _mode.DNSProxy, g.DNSProxy);
BindSyncGlobalCheckBox(HandleICMPCheckBox, b => _mode.FilterICMP = b, _mode.FilterICMP, g.FilterICMP);
BindTextBox<int>(ICMPDelayTextBox, s => s >= 0, s => _mode.ICMPDelay = s, _mode.ICMPDelay ?? 10);
BindCheckBox(HandleLoopbackCheckBox, b => _mode.FilterLoopback = b, _mode.FilterLoopback);
BindCheckBox(HandleLANCheckBox, b => _mode.FilterIntranet = b, _mode.FilterIntranet);
BindSyncGlobalCheckBox(HandleChildProcCheckBox, b => _mode.FilterParent = b, _mode.FilterParent, g.FilterParent);
BindTextBox(BypassRuleRichTextBox, s => true, s => _mode.Bypass = s.GetLines().ToList(), string.Join(Constants.EOF, _mode.Bypass));
BindTextBox(HandleRuleRichTextBox, s => true, s => _mode.Handle = s.GetLines().ToList(), string.Join(Constants.EOF, _mode.Handle));
}
#region Model
public IEnumerable<string> Rules => RuleRichTextBox.Lines;
private void RuleAdd(string value)
private void InitBindings()
{
RuleRichTextBox.AppendText($"{value}\n");
DNSTextBox.DataBindings.Add(new Binding("Enabled", HandleDNSCheckBox, "Checked", true));
HandleProcDNSCheckBox.DataBindings.Add(new Binding("Enabled", HandleDNSCheckBox, "Checked", true));
ProxyDNSCheckBox.DataBindings.Add(new Binding("Enabled", HandleDNSCheckBox, "Checked", true));
ICMPDelayTextBox.DataBindings.Add(new Binding("Enabled", HandleICMPCheckBox, "Checked", true));
}
private void RuleAddRange(IEnumerable<string> value)
{
foreach (string s in value)
{
RuleAdd(s);
}
}
#endregion
public void ModeForm_Load(object sender, EventArgs e)
{
if (_mode != null)
if (!IsCreateMode)
{
Text = "Edit Process Mode";
RemarkTextBox.TextChanged -= RemarkTextBox_TextChanged;
RemarkTextBox.Text = _mode.Remark;
FilenameTextBox.Text = _mode.RelativePath;
RuleAddRange(_mode.Content);
RemarkTextBox.Text = _mode.i18NRemark;
FilenameTextBox.Text = ModeService.Instance.GetRelativePath(_mode.FullName);
}
if (!_mode.FullName.EndsWith(".json"))
ControlButton.Enabled = false;
BypassRuleRichTextBox.Text = string.Join(Constants.EOF, _mode.Bypass);
HandleRuleRichTextBox.Text = string.Join(Constants.EOF, _mode.Handle);
i18N.TranslateForm(this);
}
private void SelectButton_Click(object sender, EventArgs e)
{
var dialog = new CommonOpenFileDialog
RichTextBox ruleRichTextBox;
if (sender == HandleSelectButton)
ruleRichTextBox = HandleRuleRichTextBox;
else if (sender == BypassSelectButton)
ruleRichTextBox = BypassRuleRichTextBox;
else
{
IsFolderPicker = true,
Multiselect = true,
Title = i18N.Translate("Select a folder"),
AddToMostRecentlyUsedList = false,
EnsurePathExists = true,
NavigateToShortcut = true
};
if (dialog.ShowDialog(Handle) == CommonFileDialogResult.Ok)
{
foreach (string p in dialog.FileNames)
{
string path = p;
if (!path.EndsWith(@"\"))
path += @"\";
RuleAdd($"^{path.ToRegexString()}");
}
throw new InvalidOperationException();
}
var dialog = new FolderBrowserDialog();
if (dialog.ShowDialog() == DialogResult.OK)
{
var path = dialog.SelectedPath;
if (!path.EndsWith(@"\"))
path += @"\";
AppendText(ruleRichTextBox, $"^{path.ToRegexString()}");
}
}
private static void AppendText(Control ruleTextBox, string value)
{
if (ruleTextBox.Text.Any())
ruleTextBox.Text = ruleTextBox.Text.Trim() + Constants.EOF + value;
else
ruleTextBox.Text = value;
}
public void ControlButton_Click(object sender, EventArgs e)
{
if (!RuleRichTextBox.Lines.Any())
{
MessageBoxX.Show(i18N.Translate("Unable to add empty rule"));
return;
}
if (string.IsNullOrWhiteSpace(RemarkTextBox.Text))
{
MessageBoxX.Show(i18N.Translate("Please enter a mode remark"));
return;
}
if (string.IsNullOrWhiteSpace(FilenameTextBox.Text))
{
MessageBoxX.Show(i18N.Translate("Please enter a mode filename"));
return;
}
SaveBinds();
if (_mode != null)
{
_mode.Remark = RemarkTextBox.Text;
_mode.Content.Clear();
_mode.Content.AddRange(RuleRichTextBox.Lines);
_mode.WriteFile();
MessageBoxX.Show(i18N.Translate("Mode updated successfully"));
}
else
if (IsCreateMode)
{
var relativePath = FilenameTextBox.Text;
var fullName = ModeHelper.GetFullPath(relativePath);
var fullName = ModeService.Instance.GetFullPath(relativePath);
if (File.Exists(fullName))
{
MessageBoxX.Show(i18N.Translate("File already exists.\n Please Change the filename"));
return;
}
var mode = new Mode(fullName)
{
Type = ModeType.Process,
Remark = RemarkTextBox.Text
};
_mode.FullName = fullName;
mode.Content.AddRange(RuleRichTextBox.Lines);
mode.WriteFile();
ModeService.Instance.Add(_mode);
MessageBoxX.Show(i18N.Translate("Mode added successfully"));
}
else
{
_mode.WriteFile();
MessageBoxX.Show(i18N.Translate("Mode updated successfully"));
}
Close();
}
private void RemarkTextBox_TextChanged(object? sender, EventArgs? e)
{
if (!IsHandleCreated)
return;
BeginInvoke(new Action(() =>
{
FilenameTextBox.Text = FilenameTextBox.Text = ModeEditorUtils.GetCustomModeRelativePath(RemarkTextBox.Text);
@@ -158,24 +169,26 @@ namespace Netch.Forms.ModeForms
private void ScanButton_Click(object sender, EventArgs e)
{
var dialog = new CommonOpenFileDialog
RichTextBox ruleRichTextBox;
if (sender == HandleScanButton)
ruleRichTextBox = HandleRuleRichTextBox;
else if (sender == BypassScanButton)
ruleRichTextBox = BypassRuleRichTextBox;
else
{
IsFolderPicker = true,
Multiselect = false,
Title = i18N.Translate("Select a folder"),
AddToMostRecentlyUsedList = false,
EnsurePathExists = true,
NavigateToShortcut = true
};
throw new InvalidOperationException();
}
if (dialog.ShowDialog(Handle) == CommonFileDialogResult.Ok)
var dialog = new FolderBrowserDialog();
if (dialog.ShowDialog() == DialogResult.OK)
{
var path = dialog.FileName;
var path = dialog.SelectedPath;
var list = new List<string>();
const uint maxCount = 50;
try
{
ScanDirectory(path, list);
ScanDirectory(path, list, maxCount);
}
catch
{
@@ -185,13 +198,13 @@ namespace Netch.Forms.ModeForms
return;
}
RuleAddRange(list);
AppendText(ruleRichTextBox, string.Join(Constants.EOF, list));
}
}
private void ScanDirectory(string directory, List<string> list, uint maxCount = 30)
{
foreach (string dir in Directory.GetDirectories(directory))
foreach (var dir in Directory.GetDirectories(directory))
ScanDirectory(dir, list, maxCount);
list.AddRange(
@@ -203,7 +216,7 @@ namespace Netch.Forms.ModeForms
private void ValidationButton_Click(object sender, EventArgs e)
{
if (!NFController.CheckRules(Rules, out var results))
if (!NFController.CheckRules(_mode.Bypass, out var results))
MessageBoxX.Show(NFController.GenerateInvalidRulesMessage(results), LogLevel.WARNING);
else
MessageBoxX.Show("Fine");

View File

@@ -1,64 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
@@ -112,9 +52,9 @@
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -32,166 +32,349 @@ namespace Netch.Forms.ModeForms
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.ConfigurationGroupBox = new System.Windows.Forms.GroupBox();
this.comboBox1 = new System.Windows.Forms.ComboBox();
this.HandleTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.HandleLabel = new System.Windows.Forms.Label();
this.HandleContentTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.HandleRuleRichTextBox = new System.Windows.Forms.RichTextBox();
this.BypassTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.BypassLabel = new System.Windows.Forms.Label();
this.BypassContentTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.BypassRuleRichTextBox = new System.Windows.Forms.RichTextBox();
this.HandleDNSCheckBox = new Netch.Forms.SyncGlobalCheckBox();
this.DNSLabel = new System.Windows.Forms.Label();
this.DNSTextBox = new System.Windows.Forms.TextBox();
this.UseCustomDNSCheckBox = new System.Windows.Forms.CheckBox();
this.RuleTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.OptionsGroupBox = new System.Windows.Forms.GroupBox();
this.RemarkLabel = new System.Windows.Forms.Label();
this.RemarkTextBox = new System.Windows.Forms.TextBox();
this.FilenameLabel = new System.Windows.Forms.Label();
this.FilenameTextBox = new System.Windows.Forms.TextBox();
this.ActionLabel = new System.Windows.Forms.Label();
this.RemarkTextBox = new System.Windows.Forms.TextBox();
this.RemarkLabel = new System.Windows.Forms.Label();
this.containerControl1 = new System.Windows.Forms.ContainerControl();
this.richTextBox1 = new System.Windows.Forms.RichTextBox();
this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.DeleteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ControlButton = new System.Windows.Forms.Button();
this.NamePanel = new System.Windows.Forms.Panel();
this.ConfigurationLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.ConfigurationGroupBox = new System.Windows.Forms.GroupBox();
this.HandleTableLayoutPanel.SuspendLayout();
this.HandleContentTableLayoutPanel.SuspendLayout();
this.BypassTableLayoutPanel.SuspendLayout();
this.BypassContentTableLayoutPanel.SuspendLayout();
this.RuleTableLayoutPanel.SuspendLayout();
this.OptionsGroupBox.SuspendLayout();
this.NamePanel.SuspendLayout();
this.ConfigurationLayoutPanel.SuspendLayout();
this.ConfigurationGroupBox.SuspendLayout();
this.containerControl1.SuspendLayout();
this.contextMenuStrip.SuspendLayout();
this.SuspendLayout();
//
// ConfigurationGroupBox
// HandleTableLayoutPanel
//
this.ConfigurationGroupBox.Controls.Add(this.comboBox1);
this.ConfigurationGroupBox.Controls.Add(this.FilenameLabel);
this.ConfigurationGroupBox.Controls.Add(this.FilenameTextBox);
this.ConfigurationGroupBox.Controls.Add(this.ActionLabel);
this.ConfigurationGroupBox.Controls.Add(this.RemarkTextBox);
this.ConfigurationGroupBox.Controls.Add(this.RemarkLabel);
this.ConfigurationGroupBox.Controls.Add(this.containerControl1);
this.ConfigurationGroupBox.Location = new System.Drawing.Point(8, 12);
this.ConfigurationGroupBox.Name = "ConfigurationGroupBox";
this.ConfigurationGroupBox.Size = new System.Drawing.Size(340, 355);
this.ConfigurationGroupBox.TabIndex = 2;
this.ConfigurationGroupBox.TabStop = false;
this.ConfigurationGroupBox.Text = "Configuration";
this.HandleTableLayoutPanel.ColumnCount = 1;
this.HandleTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.HandleTableLayoutPanel.Controls.Add(this.HandleLabel, 0, 0);
this.HandleTableLayoutPanel.Controls.Add(this.HandleContentTableLayoutPanel, 0, 1);
this.HandleTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.HandleTableLayoutPanel.Location = new System.Drawing.Point(3, 3);
this.HandleTableLayoutPanel.Name = "HandleTableLayoutPanel";
this.HandleTableLayoutPanel.RowCount = 2;
this.HandleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.HandleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.HandleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.HandleTableLayoutPanel.Size = new System.Drawing.Size(455, 424);
this.HandleTableLayoutPanel.TabIndex = 1;
//
// comboBox1
// HandleLabel
//
this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBox1.FormattingEnabled = true;
this.comboBox1.Location = new System.Drawing.Point(84, 49);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(138, 25);
this.comboBox1.TabIndex = 11;
this.HandleLabel.AutoSize = true;
this.HandleLabel.Location = new System.Drawing.Point(3, 0);
this.HandleLabel.Name = "HandleLabel";
this.HandleLabel.Size = new System.Drawing.Size(81, 17);
this.HandleLabel.TabIndex = 0;
this.HandleLabel.Text = "Handle rules";
//
// FilenameLabel
// HandleContentTableLayoutPanel
//
this.FilenameLabel.AutoSize = true;
this.FilenameLabel.Location = new System.Drawing.Point(12, 79);
this.FilenameLabel.Name = "FilenameLabel";
this.FilenameLabel.Size = new System.Drawing.Size(59, 17);
this.FilenameLabel.TabIndex = 6;
this.FilenameLabel.Text = "Filename";
this.HandleContentTableLayoutPanel.ColumnCount = 1;
this.HandleContentTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.HandleContentTableLayoutPanel.Controls.Add(this.HandleRuleRichTextBox, 0, 0);
this.HandleContentTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.HandleContentTableLayoutPanel.Location = new System.Drawing.Point(3, 20);
this.HandleContentTableLayoutPanel.Name = "HandleContentTableLayoutPanel";
this.HandleContentTableLayoutPanel.RowCount = 1;
this.HandleContentTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.HandleContentTableLayoutPanel.Size = new System.Drawing.Size(449, 401);
this.HandleContentTableLayoutPanel.TabIndex = 1;
//
// FilenameTextBox
// HandleRuleRichTextBox
//
this.FilenameTextBox.Location = new System.Drawing.Point(84, 76);
this.FilenameTextBox.Name = "FilenameTextBox";
this.FilenameTextBox.ReadOnly = true;
this.FilenameTextBox.Size = new System.Drawing.Size(250, 23);
this.FilenameTextBox.TabIndex = 5;
this.HandleRuleRichTextBox.DetectUrls = false;
this.HandleRuleRichTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.HandleRuleRichTextBox.Location = new System.Drawing.Point(3, 3);
this.HandleRuleRichTextBox.Name = "HandleRuleRichTextBox";
this.HandleRuleRichTextBox.Size = new System.Drawing.Size(443, 395);
this.HandleRuleRichTextBox.TabIndex = 0;
this.HandleRuleRichTextBox.Text = "";
this.HandleRuleRichTextBox.WordWrap = false;
//
// ActionLabel
// BypassTableLayoutPanel
//
this.ActionLabel.AutoSize = true;
this.ActionLabel.Location = new System.Drawing.Point(12, 52);
this.ActionLabel.Name = "ActionLabel";
this.ActionLabel.Size = new System.Drawing.Size(44, 17);
this.ActionLabel.TabIndex = 0;
this.ActionLabel.Text = "Action";
this.BypassTableLayoutPanel.ColumnCount = 1;
this.BypassTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.BypassTableLayoutPanel.Controls.Add(this.BypassLabel, 0, 0);
this.BypassTableLayoutPanel.Controls.Add(this.BypassContentTableLayoutPanel, 0, 1);
this.BypassTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.BypassTableLayoutPanel.Location = new System.Drawing.Point(464, 3);
this.BypassTableLayoutPanel.Name = "BypassTableLayoutPanel";
this.BypassTableLayoutPanel.RowCount = 2;
this.BypassTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.BypassTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.BypassTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.BypassTableLayoutPanel.Size = new System.Drawing.Size(455, 424);
this.BypassTableLayoutPanel.TabIndex = 2;
//
// RemarkTextBox
// BypassLabel
//
this.RemarkTextBox.Location = new System.Drawing.Point(84, 22);
this.RemarkTextBox.Name = "RemarkTextBox";
this.RemarkTextBox.Size = new System.Drawing.Size(250, 23);
this.RemarkTextBox.TabIndex = 1;
this.RemarkTextBox.TextChanged += new System.EventHandler(this.RemarkTextBox_TextChanged);
this.BypassLabel.AutoSize = true;
this.BypassLabel.Location = new System.Drawing.Point(3, 0);
this.BypassLabel.Name = "BypassLabel";
this.BypassLabel.Size = new System.Drawing.Size(81, 17);
this.BypassLabel.TabIndex = 0;
this.BypassLabel.Text = "Bypass rules";
//
// BypassContentTableLayoutPanel
//
this.BypassContentTableLayoutPanel.ColumnCount = 1;
this.BypassContentTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.BypassContentTableLayoutPanel.Controls.Add(this.BypassRuleRichTextBox, 0, 0);
this.BypassContentTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.BypassContentTableLayoutPanel.Location = new System.Drawing.Point(3, 20);
this.BypassContentTableLayoutPanel.Name = "BypassContentTableLayoutPanel";
this.BypassContentTableLayoutPanel.RowCount = 1;
this.BypassContentTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.BypassContentTableLayoutPanel.Size = new System.Drawing.Size(449, 401);
this.BypassContentTableLayoutPanel.TabIndex = 1;
//
// BypassRuleRichTextBox
//
this.BypassRuleRichTextBox.DetectUrls = false;
this.BypassRuleRichTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.BypassRuleRichTextBox.Location = new System.Drawing.Point(3, 3);
this.BypassRuleRichTextBox.Name = "BypassRuleRichTextBox";
this.BypassRuleRichTextBox.Size = new System.Drawing.Size(443, 395);
this.BypassRuleRichTextBox.TabIndex = 0;
this.BypassRuleRichTextBox.Text = "";
this.BypassRuleRichTextBox.WordWrap = false;
//
// HandleDNSCheckBox
//
this.HandleDNSCheckBox.AutoCheck = false;
this.HandleDNSCheckBox.AutoSize = true;
this.HandleDNSCheckBox.BackColor = System.Drawing.Color.Yellow;
this.HandleDNSCheckBox.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point);
this.HandleDNSCheckBox.GlobalValue = false;
this.HandleDNSCheckBox.Location = new System.Drawing.Point(8, 24);
this.HandleDNSCheckBox.Name = "HandleDNSCheckBox";
this.HandleDNSCheckBox.Size = new System.Drawing.Size(203, 21);
this.HandleDNSCheckBox.SyncGlobal = false;
this.HandleDNSCheckBox.TabIndex = 2;
this.HandleDNSCheckBox.Text = "Handle DNS (DNS hijacking)";
this.HandleDNSCheckBox.ThreeState = true;
this.HandleDNSCheckBox.UseVisualStyleBackColor = true;
this.HandleDNSCheckBox.Value = false;
//
// DNSLabel
//
this.DNSLabel.AutoSize = true;
this.DNSLabel.Location = new System.Drawing.Point(176, 56);
this.DNSLabel.Name = "DNSLabel";
this.DNSLabel.Size = new System.Drawing.Size(34, 17);
this.DNSLabel.TabIndex = 3;
this.DNSLabel.Text = "DNS";
//
// DNSTextBox
//
this.DNSTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.UseCustomDNSCheckBox, "Checked", true));
this.DNSTextBox.Location = new System.Drawing.Point(224, 56);
this.DNSTextBox.Name = "DNSTextBox";
this.DNSTextBox.Size = new System.Drawing.Size(184, 23);
this.DNSTextBox.TabIndex = 4;
this.DNSTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// UseCustomDNSCheckBox
//
this.UseCustomDNSCheckBox.AutoSize = true;
this.UseCustomDNSCheckBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.HandleDNSCheckBox, "Checked", true));
this.UseCustomDNSCheckBox.Location = new System.Drawing.Point(8, 56);
this.UseCustomDNSCheckBox.Name = "UseCustomDNSCheckBox";
this.UseCustomDNSCheckBox.Size = new System.Drawing.Size(125, 21);
this.UseCustomDNSCheckBox.TabIndex = 7;
this.UseCustomDNSCheckBox.Text = "Use custom DNS";
this.UseCustomDNSCheckBox.ThreeState = true;
this.UseCustomDNSCheckBox.UseVisualStyleBackColor = true;
//
// RuleTableLayoutPanel
//
this.RuleTableLayoutPanel.ColumnCount = 2;
this.RuleTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.RuleTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.RuleTableLayoutPanel.Controls.Add(this.HandleTableLayoutPanel, 0, 0);
this.RuleTableLayoutPanel.Controls.Add(this.BypassTableLayoutPanel, 1, 0);
this.RuleTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.RuleTableLayoutPanel.Location = new System.Drawing.Point(3, 206);
this.RuleTableLayoutPanel.Name = "RuleTableLayoutPanel";
this.RuleTableLayoutPanel.RowCount = 1;
this.RuleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.RuleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 430F));
this.RuleTableLayoutPanel.Size = new System.Drawing.Size(922, 430);
this.RuleTableLayoutPanel.TabIndex = 2;
//
// OptionsGroupBox
//
this.OptionsGroupBox.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.OptionsGroupBox.Controls.Add(this.HandleDNSCheckBox);
this.OptionsGroupBox.Controls.Add(this.UseCustomDNSCheckBox);
this.OptionsGroupBox.Controls.Add(this.DNSLabel);
this.OptionsGroupBox.Controls.Add(this.DNSTextBox);
this.OptionsGroupBox.Location = new System.Drawing.Point(15, 81);
this.OptionsGroupBox.Name = "OptionsGroupBox";
this.OptionsGroupBox.Size = new System.Drawing.Size(898, 119);
this.OptionsGroupBox.TabIndex = 1;
this.OptionsGroupBox.TabStop = false;
this.OptionsGroupBox.Visible = false;
//
// RemarkLabel
//
this.RemarkLabel.AutoSize = true;
this.RemarkLabel.Location = new System.Drawing.Point(12, 25);
this.RemarkLabel.Location = new System.Drawing.Point(8, 8);
this.RemarkLabel.Name = "RemarkLabel";
this.RemarkLabel.Size = new System.Drawing.Size(53, 17);
this.RemarkLabel.TabIndex = 0;
this.RemarkLabel.Text = "Remark";
//
// containerControl1
// RemarkTextBox
//
this.containerControl1.Controls.Add(this.richTextBox1);
this.containerControl1.Location = new System.Drawing.Point(6, 103);
this.containerControl1.Name = "containerControl1";
this.containerControl1.Size = new System.Drawing.Size(328, 246);
this.containerControl1.TabIndex = 10;
this.containerControl1.Text = "containerControl1";
this.RemarkTextBox.Location = new System.Drawing.Point(72, 8);
this.RemarkTextBox.Name = "RemarkTextBox";
this.RemarkTextBox.Size = new System.Drawing.Size(341, 23);
this.RemarkTextBox.TabIndex = 1;
//
// richTextBox1
// FilenameLabel
//
this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.richTextBox1.Location = new System.Drawing.Point(0, 0);
this.richTextBox1.Name = "richTextBox1";
this.richTextBox1.Size = new System.Drawing.Size(328, 246);
this.richTextBox1.TabIndex = 0;
this.richTextBox1.Text = "";
this.FilenameLabel.AutoSize = true;
this.FilenameLabel.Location = new System.Drawing.Point(8, 40);
this.FilenameLabel.Name = "FilenameLabel";
this.FilenameLabel.Size = new System.Drawing.Size(59, 17);
this.FilenameLabel.TabIndex = 2;
this.FilenameLabel.Text = "Filename";
//
// contextMenuStrip
// FilenameTextBox
//
this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.DeleteToolStripMenuItem});
this.contextMenuStrip.Name = "contextMenuStrip";
this.contextMenuStrip.Size = new System.Drawing.Size(114, 26);
//
// DeleteToolStripMenuItem
//
this.DeleteToolStripMenuItem.Name = "DeleteToolStripMenuItem";
this.DeleteToolStripMenuItem.Size = new System.Drawing.Size(113, 22);
this.DeleteToolStripMenuItem.Text = "Delete";
this.FilenameTextBox.Location = new System.Drawing.Point(72, 40);
this.FilenameTextBox.Name = "FilenameTextBox";
this.FilenameTextBox.ReadOnly = true;
this.FilenameTextBox.Size = new System.Drawing.Size(341, 23);
this.FilenameTextBox.TabIndex = 3;
//
// ControlButton
//
this.ControlButton.Location = new System.Drawing.Point(273, 373);
this.ControlButton.Location = new System.Drawing.Point(424, 40);
this.ControlButton.Name = "ControlButton";
this.ControlButton.Size = new System.Drawing.Size(75, 23);
this.ControlButton.TabIndex = 3;
this.ControlButton.TabIndex = 4;
this.ControlButton.Text = "Save";
this.ControlButton.UseVisualStyleBackColor = true;
this.ControlButton.Click += new System.EventHandler(this.ControlButton_Click);
//
// Route
// NamePanel
//
this.NamePanel.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.NamePanel.Controls.Add(this.RemarkLabel);
this.NamePanel.Controls.Add(this.RemarkTextBox);
this.NamePanel.Controls.Add(this.FilenameLabel);
this.NamePanel.Controls.Add(this.FilenameTextBox);
this.NamePanel.Controls.Add(this.ControlButton);
this.NamePanel.Location = new System.Drawing.Point(208, 3);
this.NamePanel.Name = "NamePanel";
this.NamePanel.Size = new System.Drawing.Size(512, 72);
this.NamePanel.TabIndex = 0;
//
// ConfigurationLayoutPanel
//
this.ConfigurationLayoutPanel.ColumnCount = 1;
this.ConfigurationLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.ConfigurationLayoutPanel.Controls.Add(this.NamePanel, 0, 0);
this.ConfigurationLayoutPanel.Controls.Add(this.OptionsGroupBox, 0, 1);
this.ConfigurationLayoutPanel.Controls.Add(this.RuleTableLayoutPanel, 0, 2);
this.ConfigurationLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.ConfigurationLayoutPanel.Location = new System.Drawing.Point(3, 19);
this.ConfigurationLayoutPanel.Name = "ConfigurationLayoutPanel";
this.ConfigurationLayoutPanel.RowCount = 3;
this.ConfigurationLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.ConfigurationLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.ConfigurationLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.ConfigurationLayoutPanel.Size = new System.Drawing.Size(928, 639);
this.ConfigurationLayoutPanel.TabIndex = 0;
//
// ConfigurationGroupBox
//
this.ConfigurationGroupBox.Controls.Add(this.ConfigurationLayoutPanel);
this.ConfigurationGroupBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.ConfigurationGroupBox.Location = new System.Drawing.Point(0, 0);
this.ConfigurationGroupBox.Name = "ConfigurationGroupBox";
this.ConfigurationGroupBox.Size = new System.Drawing.Size(934, 661);
this.ConfigurationGroupBox.TabIndex = 1;
this.ConfigurationGroupBox.TabStop = false;
this.ConfigurationGroupBox.Text = "Configuration";
//
// RouteForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(356, 419);
this.ClientSize = new System.Drawing.Size(934, 661);
this.Controls.Add(this.ConfigurationGroupBox);
this.Controls.Add(this.ControlButton);
this.MinimumSize = new System.Drawing.Size(950, 700);
this.Name = "RouteForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Create Route Table Rule";
this.Load += new System.EventHandler(this.Route_Load);
this.HandleTableLayoutPanel.ResumeLayout(false);
this.HandleTableLayoutPanel.PerformLayout();
this.HandleContentTableLayoutPanel.ResumeLayout(false);
this.BypassTableLayoutPanel.ResumeLayout(false);
this.BypassTableLayoutPanel.PerformLayout();
this.BypassContentTableLayoutPanel.ResumeLayout(false);
this.RuleTableLayoutPanel.ResumeLayout(false);
this.OptionsGroupBox.ResumeLayout(false);
this.OptionsGroupBox.PerformLayout();
this.NamePanel.ResumeLayout(false);
this.NamePanel.PerformLayout();
this.ConfigurationLayoutPanel.ResumeLayout(false);
this.ConfigurationGroupBox.ResumeLayout(false);
this.ConfigurationGroupBox.PerformLayout();
this.containerControl1.ResumeLayout(false);
this.contextMenuStrip.ResumeLayout(false);
this.ResumeLayout(false);
}
public System.Windows.Forms.GroupBox ConfigurationGroupBox;
private System.Windows.Forms.ContainerControl containerControl1;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip;
public System.Windows.Forms.Button ControlButton;
private System.Windows.Forms.ToolStripMenuItem DeleteToolStripMenuItem;
private System.Windows.Forms.Label FilenameLabel;
private System.Windows.Forms.TextBox FilenameTextBox;
private System.Windows.Forms.Label RemarkLabel;
private System.Windows.Forms.TextBox RemarkTextBox;
private System.Windows.Forms.RichTextBox richTextBox1;
#endregion
private System.Windows.Forms.ComboBox comboBox1;
private System.Windows.Forms.Label ActionLabel;
private System.Windows.Forms.TableLayoutPanel HandleTableLayoutPanel;
private System.Windows.Forms.Label HandleLabel;
private System.Windows.Forms.TableLayoutPanel HandleContentTableLayoutPanel;
private System.Windows.Forms.RichTextBox HandleRuleRichTextBox;
private System.Windows.Forms.TableLayoutPanel BypassTableLayoutPanel;
private System.Windows.Forms.Label BypassLabel;
private System.Windows.Forms.TableLayoutPanel BypassContentTableLayoutPanel;
private System.Windows.Forms.RichTextBox BypassRuleRichTextBox;
private SyncGlobalCheckBox HandleDNSCheckBox;
private System.Windows.Forms.Label DNSLabel;
private System.Windows.Forms.TextBox DNSTextBox;
private System.Windows.Forms.TableLayoutPanel RuleTableLayoutPanel;
private System.Windows.Forms.GroupBox OptionsGroupBox;
private System.Windows.Forms.Label RemarkLabel;
private System.Windows.Forms.TextBox RemarkTextBox;
private System.Windows.Forms.Label FilenameLabel;
private System.Windows.Forms.TextBox FilenameTextBox;
private System.Windows.Forms.Panel NamePanel;
private System.Windows.Forms.TableLayoutPanel ConfigurationLayoutPanel;
private System.Windows.Forms.CheckBox UseCustomDNSCheckBox;
private System.Windows.Forms.Button ControlButton;
private System.Windows.Forms.GroupBox ConfigurationGroupBox;
}
}

View File

@@ -1,47 +1,61 @@
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System;
using System.IO;
using System.Windows.Forms;
using Netch.Enums;
using System.Linq;
using Netch.Models.Modes;
using Netch.Models.Modes.TunMode;
using Netch.Properties;
using Netch.Services;
using Netch.Utils;
namespace Netch.Forms.ModeForms
{
public partial class RouteForm : Form
public partial class RouteForm : BindingForm
{
private readonly TagItem<ModeType>[] _items =
{ new(ModeType.ProxyRuleIPs, "Proxy Rule IPs"), new(ModeType.BypassRuleIPs, "Bypass Rule IPs") };
private readonly bool IsCreateMode;
private readonly Mode? _mode;
private readonly TunMode _mode;
public RouteForm(Mode? mode = null)
{
if (mode != null && mode.Type is not (ModeType.ProxyRuleIPs or ModeType.BypassRuleIPs))
throw new ArgumentOutOfRangeException();
_mode = mode;
switch (mode)
{
case null:
IsCreateMode = true;
_mode = new TunMode();
break;
case TunMode tunMode:
IsCreateMode = false;
_mode = tunMode;
break;
default:
throw new ArgumentOutOfRangeException();
}
InitializeComponent();
Icon = Resources.icon;
comboBox1.DataSource = _items;
comboBox1.ValueMember = nameof(TagItem<int>.Value);
comboBox1.DisplayMember = nameof(TagItem<int>.Text);
BindTextBox(RemarkTextBox, _ => true, s => _mode.i18NRemark = s, _mode.i18NRemark);
// TODO Options Not implemented
BindTextBox(BypassRuleRichTextBox, s => true, s => _mode.Bypass = s.GetLines().ToList(), string.Join(Constants.EOF, _mode.Bypass));
BindTextBox(HandleRuleRichTextBox, s => true, s => _mode.Handle = s.GetLines().ToList(), string.Join(Constants.EOF, _mode.Handle));
}
private void Route_Load(object sender, EventArgs e)
{
if (_mode != null)
if (!IsCreateMode)
{
Text = "Edit Route Table Rule";
RemarkTextBox.TextChanged -= RemarkTextBox_TextChanged;
RemarkTextBox.Text = _mode.Remark;
comboBox1.SelectedValue = _mode.Type; // ComboBox SelectedValue worked after ctor
FilenameTextBox.Text = _mode.RelativePath;
richTextBox1.Lines = _mode.Content.ToArray();
RemarkTextBox.Text = _mode.i18NRemark;
FilenameTextBox.Text = ModeService.Instance.GetRelativePath(_mode.FullName);
}
if (!_mode.FullName.EndsWith(".json"))
ControlButton.Enabled = false;
i18N.TranslateForm(this);
}
@@ -53,50 +67,33 @@ namespace Netch.Forms.ModeForms
return;
}
if (string.IsNullOrWhiteSpace(FilenameTextBox.Text))
{
MessageBoxX.Show(i18N.Translate("Please enter a mode filename"));
return;
}
if (_mode != null)
{
_mode.Remark = RemarkTextBox.Text;
_mode.Content.Clear();
_mode.Content.AddRange(richTextBox1.Lines);
_mode.Type = (ModeType)comboBox1.SelectedValue;
_mode.WriteFile();
MessageBoxX.Show(i18N.Translate("Mode updated successfully"));
}
else
if (IsCreateMode)
{
var relativePath = FilenameTextBox.Text;
var fullName = ModeHelper.GetFullPath(relativePath);
var fullName = ModeService.Instance.GetFullPath(relativePath);
if (File.Exists(fullName))
{
MessageBoxX.Show(i18N.Translate("File already exists.\n Please Change the filename"));
return;
}
var mode = new Mode(fullName)
{
Type = (ModeType)comboBox1.SelectedValue,
Remark = RemarkTextBox.Text
};
_mode.FullName = fullName;
mode.Content.AddRange(richTextBox1.Lines);
mode.WriteFile();
ModeService.Instance.Add(_mode);
MessageBoxX.Show(i18N.Translate("Mode added successfully"));
}
else
{
_mode.WriteFile();
MessageBoxX.Show(i18N.Translate("Mode updated successfully"));
}
Close();
}
private void RemarkTextBox_TextChanged(object? sender, EventArgs? e)
{
BeginInvoke(new Action(() => { FilenameTextBox.Text = ModeEditorUtils.GetCustomModeRelativePath(RemarkTextBox.Text); }));
FilenameTextBox.Text = ModeEditorUtils.GetCustomModeRelativePath(RemarkTextBox.Text);
}
}
}

View File

@@ -36,10 +36,7 @@ namespace Netch.Forms
this.PortGroupBox = new System.Windows.Forms.GroupBox();
this.Socks5PortLabel = new System.Windows.Forms.Label();
this.Socks5PortTextBox = new System.Windows.Forms.TextBox();
this.HTTPPortLabel = new System.Windows.Forms.Label();
this.HTTPPortTextBox = new System.Windows.Forms.TextBox();
this.AllowDevicesCheckBox = new System.Windows.Forms.CheckBox();
this.ResolveServerHostnameCheckBox = new System.Windows.Forms.CheckBox();
this.ServerPingTypeLabel = new System.Windows.Forms.Label();
this.ICMPingRadioBtn = new System.Windows.Forms.RadioButton();
this.TCPingRadioBtn = new System.Windows.Forms.RadioButton();
@@ -54,13 +51,16 @@ namespace Netch.Forms
this.LanguageLabel = new System.Windows.Forms.Label();
this.LanguageComboBox = new System.Windows.Forms.ComboBox();
this.NFTabPage = new System.Windows.Forms.TabPage();
this.ProcessFilterProtocolLabel = new System.Windows.Forms.Label();
this.ProcessFilterProtocolComboBox = new System.Windows.Forms.ComboBox();
this.DNSHijackCheckBox = new System.Windows.Forms.CheckBox();
this.DNSHijackHostTextBox = new System.Windows.Forms.TextBox();
this.FilterTCPCheckBox = new System.Windows.Forms.CheckBox();
this.FilterUDPCheckBox = new System.Windows.Forms.CheckBox();
this.FilterICMPCheckBox = new System.Windows.Forms.CheckBox();
this.DNSHijackLabel = new System.Windows.Forms.Label();
this.ICMPDelayLabel = new System.Windows.Forms.Label();
this.ICMPDelayTextBox = new System.Windows.Forms.TextBox();
this.FilterDNSCheckBox = new System.Windows.Forms.CheckBox();
this.DNSHijackHostTextBox = new System.Windows.Forms.TextBox();
this.DNSProxyCheckBox = new System.Windows.Forms.CheckBox();
this.HandleProcDNSCheckBox = new System.Windows.Forms.CheckBox();
this.ChildProcessHandleCheckBox = new System.Windows.Forms.CheckBox();
this.WinTUNTabPage = new System.Windows.Forms.TabPage();
this.WinTUNGroupBox = new System.Windows.Forms.GroupBox();
@@ -98,9 +98,9 @@ namespace Netch.Forms
this.StopWhenExitedCheckBox = new System.Windows.Forms.CheckBox();
this.StartWhenOpenedCheckBox = new System.Windows.Forms.CheckBox();
this.MinimizeWhenStartedCheckBox = new System.Windows.Forms.CheckBox();
this.NoSupportDialogCheckBox = new System.Windows.Forms.CheckBox();
this.RunAtStartupCheckBox = new System.Windows.Forms.CheckBox();
this.CheckUpdateWhenOpenedCheckBox = new System.Windows.Forms.CheckBox();
this.NoSupportDialogCheckBox = new System.Windows.Forms.CheckBox();
this.CheckBetaUpdateCheckBox = new System.Windows.Forms.CheckBox();
this.UpdateServersWhenOpenedCheckBox = new System.Windows.Forms.CheckBox();
this.AioDNSTabPage = new System.Windows.Forms.TabPage();
@@ -144,7 +144,6 @@ namespace Netch.Forms
//
this.GeneralTabPage.BackColor = System.Drawing.SystemColors.ButtonFace;
this.GeneralTabPage.Controls.Add(this.PortGroupBox);
this.GeneralTabPage.Controls.Add(this.ResolveServerHostnameCheckBox);
this.GeneralTabPage.Controls.Add(this.ServerPingTypeLabel);
this.GeneralTabPage.Controls.Add(this.ICMPingRadioBtn);
this.GeneralTabPage.Controls.Add(this.TCPingRadioBtn);
@@ -169,8 +168,6 @@ namespace Netch.Forms
//
this.PortGroupBox.Controls.Add(this.Socks5PortLabel);
this.PortGroupBox.Controls.Add(this.Socks5PortTextBox);
this.PortGroupBox.Controls.Add(this.HTTPPortLabel);
this.PortGroupBox.Controls.Add(this.HTTPPortTextBox);
this.PortGroupBox.Controls.Add(this.AllowDevicesCheckBox);
this.PortGroupBox.Location = new System.Drawing.Point(8, 6);
this.PortGroupBox.Name = "PortGroupBox";
@@ -196,23 +193,6 @@ namespace Netch.Forms
this.Socks5PortTextBox.TabIndex = 1;
this.Socks5PortTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// HTTPPortLabel
//
this.HTTPPortLabel.AutoSize = true;
this.HTTPPortLabel.Location = new System.Drawing.Point(9, 54);
this.HTTPPortLabel.Name = "HTTPPortLabel";
this.HTTPPortLabel.Size = new System.Drawing.Size(38, 17);
this.HTTPPortLabel.TabIndex = 2;
this.HTTPPortLabel.Text = "HTTP";
//
// HTTPPortTextBox
//
this.HTTPPortTextBox.Location = new System.Drawing.Point(120, 51);
this.HTTPPortTextBox.Name = "HTTPPortTextBox";
this.HTTPPortTextBox.Size = new System.Drawing.Size(90, 23);
this.HTTPPortTextBox.TabIndex = 3;
this.HTTPPortTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// AllowDevicesCheckBox
//
this.AllowDevicesCheckBox.AutoSize = true;
@@ -224,20 +204,10 @@ namespace Netch.Forms
this.AllowDevicesCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
this.AllowDevicesCheckBox.UseVisualStyleBackColor = true;
//
// ResolveServerHostnameCheckBox
//
this.ResolveServerHostnameCheckBox.AutoSize = true;
this.ResolveServerHostnameCheckBox.Location = new System.Drawing.Point(267, 15);
this.ResolveServerHostnameCheckBox.Name = "ResolveServerHostnameCheckBox";
this.ResolveServerHostnameCheckBox.Size = new System.Drawing.Size(176, 21);
this.ResolveServerHostnameCheckBox.TabIndex = 1;
this.ResolveServerHostnameCheckBox.Text = "Resolve Server Hostname";
this.ResolveServerHostnameCheckBox.UseVisualStyleBackColor = true;
//
// ServerPingTypeLabel
//
this.ServerPingTypeLabel.AutoSize = true;
this.ServerPingTypeLabel.Location = new System.Drawing.Point(267, 44);
this.ServerPingTypeLabel.Location = new System.Drawing.Point(267, 15);
this.ServerPingTypeLabel.Name = "ServerPingTypeLabel";
this.ServerPingTypeLabel.Size = new System.Drawing.Size(86, 17);
this.ServerPingTypeLabel.TabIndex = 2;
@@ -246,7 +216,7 @@ namespace Netch.Forms
// ICMPingRadioBtn
//
this.ICMPingRadioBtn.AutoSize = true;
this.ICMPingRadioBtn.Location = new System.Drawing.Point(268, 63);
this.ICMPingRadioBtn.Location = new System.Drawing.Point(268, 34);
this.ICMPingRadioBtn.Name = "ICMPingRadioBtn";
this.ICMPingRadioBtn.Size = new System.Drawing.Size(75, 21);
this.ICMPingRadioBtn.TabIndex = 3;
@@ -257,7 +227,7 @@ namespace Netch.Forms
// TCPingRadioBtn
//
this.TCPingRadioBtn.AutoSize = true;
this.TCPingRadioBtn.Location = new System.Drawing.Point(366, 64);
this.TCPingRadioBtn.Location = new System.Drawing.Point(366, 35);
this.TCPingRadioBtn.Name = "TCPingRadioBtn";
this.TCPingRadioBtn.Size = new System.Drawing.Size(66, 21);
this.TCPingRadioBtn.TabIndex = 4;
@@ -354,13 +324,16 @@ namespace Netch.Forms
// NFTabPage
//
this.NFTabPage.BackColor = System.Drawing.SystemColors.ButtonFace;
this.NFTabPage.Controls.Add(this.ProcessFilterProtocolLabel);
this.NFTabPage.Controls.Add(this.ProcessFilterProtocolComboBox);
this.NFTabPage.Controls.Add(this.DNSHijackCheckBox);
this.NFTabPage.Controls.Add(this.DNSHijackHostTextBox);
this.NFTabPage.Controls.Add(this.FilterTCPCheckBox);
this.NFTabPage.Controls.Add(this.FilterUDPCheckBox);
this.NFTabPage.Controls.Add(this.FilterICMPCheckBox);
this.NFTabPage.Controls.Add(this.DNSHijackLabel);
this.NFTabPage.Controls.Add(this.ICMPDelayLabel);
this.NFTabPage.Controls.Add(this.ICMPDelayTextBox);
this.NFTabPage.Controls.Add(this.FilterDNSCheckBox);
this.NFTabPage.Controls.Add(this.DNSHijackHostTextBox);
this.NFTabPage.Controls.Add(this.HandleProcDNSCheckBox);
this.NFTabPage.Controls.Add(this.DNSProxyCheckBox);
this.NFTabPage.Controls.Add(this.ChildProcessHandleCheckBox);
this.NFTabPage.Location = new System.Drawing.Point(4, 29);
this.NFTabPage.Name = "NFTabPage";
@@ -369,80 +342,112 @@ namespace Netch.Forms
this.NFTabPage.TabIndex = 1;
this.NFTabPage.Text = "Process Mode";
//
// ProcessFilterProtocolLabel
// FilterTCPCheckBox
//
this.ProcessFilterProtocolLabel.AutoSize = true;
this.ProcessFilterProtocolLabel.Location = new System.Drawing.Point(30, 20);
this.ProcessFilterProtocolLabel.Name = "ProcessFilterProtocolLabel";
this.ProcessFilterProtocolLabel.Size = new System.Drawing.Size(89, 17);
this.ProcessFilterProtocolLabel.TabIndex = 0;
this.ProcessFilterProtocolLabel.Text = "Filter Protocol";
this.FilterTCPCheckBox.AutoSize = true;
this.FilterTCPCheckBox.Location = new System.Drawing.Point(16, 16);
this.FilterTCPCheckBox.Name = "FilterTCPCheckBox";
this.FilterTCPCheckBox.Size = new System.Drawing.Size(81, 21);
this.FilterTCPCheckBox.TabIndex = 1;
this.FilterTCPCheckBox.Text = "Handle TCP";
this.FilterTCPCheckBox.UseVisualStyleBackColor = true;
//
// ProcessFilterProtocolComboBox
// FilterUDPCheckBox
//
this.ProcessFilterProtocolComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.ProcessFilterProtocolComboBox.FormattingEnabled = true;
this.ProcessFilterProtocolComboBox.Location = new System.Drawing.Point(237, 17);
this.ProcessFilterProtocolComboBox.Name = "ProcessFilterProtocolComboBox";
this.ProcessFilterProtocolComboBox.Size = new System.Drawing.Size(98, 25);
this.ProcessFilterProtocolComboBox.TabIndex = 1;
//
// DNSHijackCheckBox
//
this.DNSHijackCheckBox.AutoSize = true;
this.DNSHijackCheckBox.Location = new System.Drawing.Point(15, 50);
this.DNSHijackCheckBox.Name = "DNSHijackCheckBox";
this.DNSHijackCheckBox.Size = new System.Drawing.Size(196, 21);
this.DNSHijackCheckBox.TabIndex = 2;
this.DNSHijackCheckBox.Text = "Handle process\'s DNS Hijack";
this.DNSHijackCheckBox.UseVisualStyleBackColor = true;
//
// DNSHijackHostTextBox
//
this.DNSHijackHostTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.DNSHijackCheckBox, "Checked", true));
this.DNSHijackHostTextBox.Location = new System.Drawing.Point(237, 48);
this.DNSHijackHostTextBox.Name = "DNSHijackHostTextBox";
this.DNSHijackHostTextBox.Size = new System.Drawing.Size(191, 23);
this.DNSHijackHostTextBox.TabIndex = 3;
this.DNSHijackHostTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.FilterUDPCheckBox.AutoSize = true;
this.FilterUDPCheckBox.Location = new System.Drawing.Point(216, 16);
this.FilterUDPCheckBox.Name = "FilterUDPCheckBox";
this.FilterUDPCheckBox.Size = new System.Drawing.Size(84, 21);
this.FilterUDPCheckBox.TabIndex = 2;
this.FilterUDPCheckBox.Text = "Handle UDP";
this.FilterUDPCheckBox.UseVisualStyleBackColor = true;
//
// FilterICMPCheckBox
//
this.FilterICMPCheckBox.AutoSize = true;
this.FilterICMPCheckBox.Location = new System.Drawing.Point(13, 80);
this.FilterICMPCheckBox.Location = new System.Drawing.Point(16, 48);
this.FilterICMPCheckBox.Name = "FilterICMPCheckBox";
this.FilterICMPCheckBox.Size = new System.Drawing.Size(90, 21);
this.FilterICMPCheckBox.TabIndex = 4;
this.FilterICMPCheckBox.Text = "Filter ICMP";
this.FilterICMPCheckBox.TabIndex = 3;
this.FilterICMPCheckBox.Text = "Handle ICMP";
this.FilterICMPCheckBox.UseVisualStyleBackColor = true;
//
// DNSHijackLabel
//
this.DNSHijackLabel.AutoSize = true;
this.DNSHijackLabel.Location = new System.Drawing.Point(48, 144);
this.DNSHijackLabel.Name = "DNSHijackLabel";
this.DNSHijackLabel.Size = new System.Drawing.Size(34, 17);
this.DNSHijackLabel.TabIndex = 3;
this.DNSHijackLabel.Text = "DNS";
//
// ICMPDelayLabel
//
this.ICMPDelayLabel.AutoSize = true;
this.ICMPDelayLabel.Location = new System.Drawing.Point(30, 110);
this.ICMPDelayLabel.Location = new System.Drawing.Point(48, 80);
this.ICMPDelayLabel.Name = "ICMPDelayLabel";
this.ICMPDelayLabel.Size = new System.Drawing.Size(100, 17);
this.ICMPDelayLabel.TabIndex = 5;
this.ICMPDelayLabel.Text = "ICMP Delay(ms)";
this.ICMPDelayLabel.TabIndex = 3;
this.ICMPDelayLabel.Text = "ICMP delay(ms)";
//
// ICMPDelayTextBox
//
this.ICMPDelayTextBox.Location = new System.Drawing.Point(237, 107);
this.ICMPDelayTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.FilterICMPCheckBox, "Checked", true));
this.ICMPDelayTextBox.Location = new System.Drawing.Point(216, 80);
this.ICMPDelayTextBox.Name = "ICMPDelayTextBox";
this.ICMPDelayTextBox.ReadOnly = true;
this.ICMPDelayTextBox.Size = new System.Drawing.Size(98, 23);
this.ICMPDelayTextBox.TabIndex = 6;
this.ICMPDelayTextBox.TabIndex = 4;
this.ICMPDelayTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// FilterDNSCheckBox
//
this.FilterDNSCheckBox.AutoSize = true;
this.FilterDNSCheckBox.Location = new System.Drawing.Point(16, 112);
this.FilterDNSCheckBox.Name = "FilterDNSCheckBox";
this.FilterDNSCheckBox.Size = new System.Drawing.Size(85, 21);
this.FilterDNSCheckBox.TabIndex = 5;
this.FilterDNSCheckBox.Text = "Handle DNS (DNS hijacking)";
this.FilterDNSCheckBox.UseVisualStyleBackColor = true;
//
// DNSHijackHostTextBox
//
this.DNSHijackHostTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.FilterDNSCheckBox, "Checked", true));
this.DNSHijackHostTextBox.Location = new System.Drawing.Point(216, 144);
this.DNSHijackHostTextBox.Name = "DNSHijackHostTextBox";
this.DNSHijackHostTextBox.Size = new System.Drawing.Size(191, 23);
this.DNSHijackHostTextBox.TabIndex = 6;
this.DNSHijackHostTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// DNSProxyCheckBox
//
this.DNSProxyCheckBox.AutoSize = true;
this.DNSProxyCheckBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.FilterDNSCheckBox, "Checked", true));
this.DNSProxyCheckBox.Location = new System.Drawing.Point(16, 208);
this.DNSProxyCheckBox.Name = "DNSProxyCheckBox";
this.DNSProxyCheckBox.Size = new System.Drawing.Size(184, 21);
this.DNSProxyCheckBox.TabIndex = 8;
this.DNSProxyCheckBox.Text = "Handle DNS through proxy";
this.DNSProxyCheckBox.UseVisualStyleBackColor = true;
//
// HandleProcDNSCheckBox
//
this.HandleProcDNSCheckBox.AutoSize = true;
this.HandleProcDNSCheckBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.FilterDNSCheckBox, "Checked", true));
this.HandleProcDNSCheckBox.Location = new System.Drawing.Point(16, 176);
this.HandleProcDNSCheckBox.Name = "HandleProcDNSCheckBox";
this.HandleProcDNSCheckBox.Size = new System.Drawing.Size(203, 21);
this.HandleProcDNSCheckBox.TabIndex = 7;
this.HandleProcDNSCheckBox.Text = "Handle handled process's DNS";
this.HandleProcDNSCheckBox.UseVisualStyleBackColor = true;
//
// ChildProcessHandleCheckBox
//
this.ChildProcessHandleCheckBox.AutoSize = true;
this.ChildProcessHandleCheckBox.Enabled = false;
this.ChildProcessHandleCheckBox.Location = new System.Drawing.Point(15, 140);
this.ChildProcessHandleCheckBox.Location = new System.Drawing.Point(16, 240);
this.ChildProcessHandleCheckBox.Name = "ChildProcessHandleCheckBox";
this.ChildProcessHandleCheckBox.Size = new System.Drawing.Size(150, 21);
this.ChildProcessHandleCheckBox.TabIndex = 8;
this.ChildProcessHandleCheckBox.Text = "Child Process Handle";
this.ChildProcessHandleCheckBox.TabIndex = 9;
this.ChildProcessHandleCheckBox.Text = "Handle child process";
this.ChildProcessHandleCheckBox.UseVisualStyleBackColor = true;
//
// WinTUNTabPage
@@ -551,7 +556,7 @@ namespace Netch.Forms
this.UseCustomDNSCheckBox.Name = "UseCustomDNSCheckBox";
this.UseCustomDNSCheckBox.Size = new System.Drawing.Size(127, 21);
this.UseCustomDNSCheckBox.TabIndex = 8;
this.UseCustomDNSCheckBox.Text = "Use Custom DNS";
this.UseCustomDNSCheckBox.Text = "Use custom DNS";
this.UseCustomDNSCheckBox.UseVisualStyleBackColor = true;
this.UseCustomDNSCheckBox.Click += new System.EventHandler(this.TUNTAPUseCustomDNSCheckBox_CheckedChanged);
//
@@ -760,9 +765,9 @@ namespace Netch.Forms
this.OtherTabPage.Controls.Add(this.StopWhenExitedCheckBox);
this.OtherTabPage.Controls.Add(this.StartWhenOpenedCheckBox);
this.OtherTabPage.Controls.Add(this.MinimizeWhenStartedCheckBox);
this.OtherTabPage.Controls.Add(this.NoSupportDialogCheckBox);
this.OtherTabPage.Controls.Add(this.RunAtStartupCheckBox);
this.OtherTabPage.Controls.Add(this.CheckUpdateWhenOpenedCheckBox);
this.OtherTabPage.Controls.Add(this.NoSupportDialogCheckBox);
this.OtherTabPage.Controls.Add(this.CheckBetaUpdateCheckBox);
this.OtherTabPage.Controls.Add(this.UpdateServersWhenOpenedCheckBox);
this.OtherTabPage.Location = new System.Drawing.Point(4, 29);
@@ -775,7 +780,7 @@ namespace Netch.Forms
// ExitWhenClosedCheckBox
//
this.ExitWhenClosedCheckBox.AutoSize = true;
this.ExitWhenClosedCheckBox.Location = new System.Drawing.Point(6, 6);
this.ExitWhenClosedCheckBox.Location = new System.Drawing.Point(16, 16);
this.ExitWhenClosedCheckBox.Name = "ExitWhenClosedCheckBox";
this.ExitWhenClosedCheckBox.Size = new System.Drawing.Size(123, 21);
this.ExitWhenClosedCheckBox.TabIndex = 0;
@@ -786,7 +791,7 @@ namespace Netch.Forms
// StopWhenExitedCheckBox
//
this.StopWhenExitedCheckBox.AutoSize = true;
this.StopWhenExitedCheckBox.Location = new System.Drawing.Point(200, 6);
this.StopWhenExitedCheckBox.Location = new System.Drawing.Point(224, 18);
this.StopWhenExitedCheckBox.Name = "StopWhenExitedCheckBox";
this.StopWhenExitedCheckBox.Size = new System.Drawing.Size(127, 21);
this.StopWhenExitedCheckBox.TabIndex = 1;
@@ -797,7 +802,7 @@ namespace Netch.Forms
// StartWhenOpenedCheckBox
//
this.StartWhenOpenedCheckBox.AutoSize = true;
this.StartWhenOpenedCheckBox.Location = new System.Drawing.Point(6, 28);
this.StartWhenOpenedCheckBox.Location = new System.Drawing.Point(16, 48);
this.StartWhenOpenedCheckBox.Name = "StartWhenOpenedCheckBox";
this.StartWhenOpenedCheckBox.Size = new System.Drawing.Size(137, 21);
this.StartWhenOpenedCheckBox.TabIndex = 2;
@@ -808,27 +813,17 @@ namespace Netch.Forms
// MinimizeWhenStartedCheckBox
//
this.MinimizeWhenStartedCheckBox.AutoSize = true;
this.MinimizeWhenStartedCheckBox.Location = new System.Drawing.Point(200, 28);
this.MinimizeWhenStartedCheckBox.Location = new System.Drawing.Point(224, 48);
this.MinimizeWhenStartedCheckBox.Name = "MinimizeWhenStartedCheckBox";
this.MinimizeWhenStartedCheckBox.Size = new System.Drawing.Size(158, 21);
this.MinimizeWhenStartedCheckBox.TabIndex = 3;
this.MinimizeWhenStartedCheckBox.Text = "Minimize when started";
this.MinimizeWhenStartedCheckBox.UseVisualStyleBackColor = true;
//
// NoSupportDialogCheckBox
//
this.NoSupportDialogCheckBox.AutoSize = true;
this.NoSupportDialogCheckBox.Location = new System.Drawing.Point(6, 72);
this.NoSupportDialogCheckBox.Name = "NoSupportDialogCheckBox";
this.NoSupportDialogCheckBox.Size = new System.Drawing.Size(174, 21);
this.NoSupportDialogCheckBox.TabIndex = 4;
this.NoSupportDialogCheckBox.Text = "Disable Support Warning";
this.NoSupportDialogCheckBox.UseVisualStyleBackColor = true;
//
// RunAtStartupCheckBox
//
this.RunAtStartupCheckBox.AutoSize = true;
this.RunAtStartupCheckBox.Location = new System.Drawing.Point(6, 50);
this.RunAtStartupCheckBox.Location = new System.Drawing.Point(16, 80);
this.RunAtStartupCheckBox.Name = "RunAtStartupCheckBox";
this.RunAtStartupCheckBox.Size = new System.Drawing.Size(109, 21);
this.RunAtStartupCheckBox.TabIndex = 4;
@@ -838,7 +833,7 @@ namespace Netch.Forms
// CheckUpdateWhenOpenedCheckBox
//
this.CheckUpdateWhenOpenedCheckBox.AutoSize = true;
this.CheckUpdateWhenOpenedCheckBox.Location = new System.Drawing.Point(200, 50);
this.CheckUpdateWhenOpenedCheckBox.Location = new System.Drawing.Point(224, 80);
this.CheckUpdateWhenOpenedCheckBox.Name = "CheckUpdateWhenOpenedCheckBox";
this.CheckUpdateWhenOpenedCheckBox.Size = new System.Drawing.Size(190, 21);
this.CheckUpdateWhenOpenedCheckBox.TabIndex = 5;
@@ -846,13 +841,23 @@ namespace Netch.Forms
this.CheckUpdateWhenOpenedCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
this.CheckUpdateWhenOpenedCheckBox.UseVisualStyleBackColor = true;
//
// NoSupportDialogCheckBox
//
this.NoSupportDialogCheckBox.AutoSize = true;
this.NoSupportDialogCheckBox.Location = new System.Drawing.Point(16, 112);
this.NoSupportDialogCheckBox.Name = "NoSupportDialogCheckBox";
this.NoSupportDialogCheckBox.Size = new System.Drawing.Size(174, 21);
this.NoSupportDialogCheckBox.TabIndex = 6;
this.NoSupportDialogCheckBox.Text = "Disable Support Warning";
this.NoSupportDialogCheckBox.UseVisualStyleBackColor = true;
//
// CheckBetaUpdateCheckBox
//
this.CheckBetaUpdateCheckBox.AutoSize = true;
this.CheckBetaUpdateCheckBox.Location = new System.Drawing.Point(200, 72);
this.CheckBetaUpdateCheckBox.Location = new System.Drawing.Point(224, 112);
this.CheckBetaUpdateCheckBox.Name = "CheckBetaUpdateCheckBox";
this.CheckBetaUpdateCheckBox.Size = new System.Drawing.Size(137, 21);
this.CheckBetaUpdateCheckBox.TabIndex = 6;
this.CheckBetaUpdateCheckBox.TabIndex = 7;
this.CheckBetaUpdateCheckBox.Text = "Check Beta update";
this.CheckBetaUpdateCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
this.CheckBetaUpdateCheckBox.UseVisualStyleBackColor = true;
@@ -860,10 +865,10 @@ namespace Netch.Forms
// UpdateServersWhenOpenedCheckBox
//
this.UpdateServersWhenOpenedCheckBox.AutoSize = true;
this.UpdateServersWhenOpenedCheckBox.Location = new System.Drawing.Point(200, 94);
this.UpdateServersWhenOpenedCheckBox.Location = new System.Drawing.Point(224, 144);
this.UpdateServersWhenOpenedCheckBox.Name = "UpdateServersWhenOpenedCheckBox";
this.UpdateServersWhenOpenedCheckBox.Size = new System.Drawing.Size(200, 21);
this.UpdateServersWhenOpenedCheckBox.TabIndex = 7;
this.UpdateServersWhenOpenedCheckBox.TabIndex = 8;
this.UpdateServersWhenOpenedCheckBox.Text = "Update Servers when opened";
this.UpdateServersWhenOpenedCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
this.UpdateServersWhenOpenedCheckBox.UseVisualStyleBackColor = true;
@@ -1008,11 +1013,8 @@ namespace Netch.Forms
private System.Windows.Forms.TabPage v2rayTabPage;
private System.Windows.Forms.GroupBox PortGroupBox;
private System.Windows.Forms.CheckBox AllowDevicesCheckBox;
private System.Windows.Forms.Label HTTPPortLabel;
private System.Windows.Forms.TextBox HTTPPortTextBox;
private System.Windows.Forms.Label Socks5PortLabel;
private System.Windows.Forms.TextBox Socks5PortTextBox;
private System.Windows.Forms.CheckBox ResolveServerHostnameCheckBox;
private System.Windows.Forms.GroupBox WinTUNGroupBox;
private System.Windows.Forms.CheckBox ProxyDNSCheckBox;
private System.Windows.Forms.CheckBox UseCustomDNSCheckBox;
@@ -1025,7 +1027,7 @@ namespace Netch.Forms
private System.Windows.Forms.Label TUNTAPAddressLabel;
private System.Windows.Forms.TextBox TUNTAPAddressTextBox;
private System.Windows.Forms.Button GlobalBypassIPsButton;
private System.Windows.Forms.CheckBox DNSHijackCheckBox;
private System.Windows.Forms.CheckBox FilterDNSCheckBox;
private System.Windows.Forms.Button ControlButton;
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
private System.Windows.Forms.TabPage OtherTabPage;
@@ -1073,12 +1075,15 @@ namespace Netch.Forms
private System.Windows.Forms.Label ServerPingTypeLabel;
private System.Windows.Forms.RadioButton TCPingRadioBtn;
private System.Windows.Forms.RadioButton ICMPingRadioBtn;
private System.Windows.Forms.ComboBox ProcessFilterProtocolComboBox;
private System.Windows.Forms.Label ProcessFilterProtocolLabel;
private System.Windows.Forms.CheckBox FilterICMPCheckBox;
private System.Windows.Forms.CheckBox ChildProcessHandleCheckBox;
private System.Windows.Forms.TextBox ICMPDelayTextBox;
private System.Windows.Forms.Label ICMPDelayLabel;
private System.Windows.Forms.CheckBox NoSupportDialogCheckBox;
private System.Windows.Forms.Label DNSHijackLabel;
private System.Windows.Forms.CheckBox HandleProcDNSCheckBox;
private System.Windows.Forms.CheckBox FilterTCPCheckBox;
private System.Windows.Forms.CheckBox FilterUDPCheckBox;
private System.Windows.Forms.CheckBox DNSProxyCheckBox;
}
}

View File

@@ -1,23 +1,17 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Windows.Forms;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using Serilog;
namespace Netch.Forms
{
public partial class SettingForm : Form
public partial class SettingForm : BindingForm
{
private readonly Dictionary<Control, Func<string, bool>> _checkActions = new();
private readonly Dictionary<Control, Action<Control>> _saveActions = new();
public SettingForm()
{
InitializeComponent();
@@ -26,22 +20,12 @@ namespace Netch.Forms
#region General
BindTextBox<ushort>(Socks5PortTextBox,
p => p.ToString() != HTTPPortTextBox.Text,
p => Global.Settings.Socks5LocalPort = p,
Global.Settings.Socks5LocalPort);
BindTextBox<ushort>(HTTPPortTextBox,
p => p.ToString() != Socks5PortTextBox.Text,
p => Global.Settings.HTTPLocalPort = p,
Global.Settings.HTTPLocalPort);
BindTextBox<ushort>(Socks5PortTextBox, p => true, p => Global.Settings.Socks5LocalPort = p, Global.Settings.Socks5LocalPort);
BindCheckBox(AllowDevicesCheckBox,
c => Global.Settings.LocalAddress = AllowDevicesCheckBox.Checked ? "0.0.0.0" : "127.0.0.1",
Global.Settings.LocalAddress switch { "127.0.0.1" => false, "0.0.0.0" => true, _ => false });
BindCheckBox(ResolveServerHostnameCheckBox, c => Global.Settings.ResolveServerHostname = c, Global.Settings.ResolveServerHostname);
BindRadioBox(ICMPingRadioBtn, _ => { }, !Global.Settings.ServerTCPing);
BindRadioBox(TCPingRadioBtn, c => Global.Settings.ServerTCPing = c, Global.Settings.ServerTCPing);
@@ -99,22 +83,25 @@ namespace Netch.Forms
#region Process Mode
BindListComboBox(ProcessFilterProtocolComboBox,
s => Global.Settings.Redirector.FilterProtocol = (PortType)Enum.Parse(typeof(PortType), s.ToString(), false),
Enum.GetNames(typeof(PortType)),
Global.Settings.Redirector.FilterProtocol.ToString());
BindCheckBox(FilterTCPCheckBox, b => Global.Settings.Redirector.FilterTCP = b, Global.Settings.Redirector.FilterTCP);
BindCheckBox(DNSHijackCheckBox, b => Global.Settings.Redirector.DNSHijack = b, Global.Settings.Redirector.DNSHijack);
BindTextBox(DNSHijackHostTextBox, s => true, s => Global.Settings.Redirector.DNSHijackHost = s, Global.Settings.Redirector.DNSHijackHost);
BindCheckBox(FilterUDPCheckBox, b => Global.Settings.Redirector.FilterUDP = b, Global.Settings.Redirector.FilterUDP);
BindCheckBox(FilterICMPCheckBox, b => Global.Settings.Redirector.FilterICMP = b, Global.Settings.Redirector.FilterICMP);
BindTextBox(ICMPDelayTextBox, s => int.TryParse(s, out _), s => { }, Global.Settings.Redirector.ICMPDelay);
BindTextBox<int>(ICMPDelayTextBox, s => true, s => Global.Settings.Redirector.ICMPDelay = s, Global.Settings.Redirector.ICMPDelay);
BindCheckBox(FilterDNSCheckBox, b => Global.Settings.Redirector.FilterDNS = b, Global.Settings.Redirector.FilterDNS);
BindTextBox(DNSHijackHostTextBox, s => true, s => Global.Settings.Redirector.DNSHost = s, Global.Settings.Redirector.DNSHost);
BindCheckBox(ChildProcessHandleCheckBox,
s => Global.Settings.Redirector.ChildProcessHandle = s,
Global.Settings.Redirector.ChildProcessHandle);
s => Global.Settings.Redirector.FilterParent = s,
Global.Settings.Redirector.FilterParent);
BindCheckBox(DNSProxyCheckBox, b => Global.Settings.Redirector.DNSProxy = b, Global.Settings.Redirector.DNSProxy);
BindCheckBox(HandleProcDNSCheckBox, b => Global.Settings.Redirector.HandleOnlyDNS = b, Global.Settings.Redirector.HandleOnlyDNS);
#endregion
@@ -247,7 +234,7 @@ namespace Netch.Forms
#region Check
var checkNotPassControl = _checkActions.Where(pair => !pair.Value.Invoke(pair.Key.Text)).Select(pair => pair.Key).ToList();
var checkNotPassControl = GetCheckFailedControls();
foreach (Control control in checkNotPassControl)
Utils.Utils.ChangeControlForeColor(control, Color.Red);
@@ -258,8 +245,7 @@ namespace Netch.Forms
#region Save
foreach (var pair in _saveActions)
pair.Value.Invoke(pair.Key);
SaveBinds();
#endregion
@@ -269,71 +255,5 @@ namespace Netch.Forms
MessageBoxX.Show(i18N.Translate("Saved"));
Close();
}
#region BindUtils
private void BindTextBox(TextBox control, Func<string, bool> check, Action<string> save, object value)
{
BindTextBox<string>(control, check, save, value);
}
private void BindTextBox<T>(TextBox control, Func<T, bool> check, Action<T> save, object value)
{
control.Text = value.ToString();
_checkActions.Add(control,
s =>
{
try
{
return check.Invoke((T)Convert.ChangeType(s, typeof(T)));
}
catch
{
return false;
}
});
_saveActions.Add(control, c => save.Invoke((T)Convert.ChangeType(((TextBox)c).Text, typeof(T))));
}
private void BindCheckBox(CheckBox control, Action<bool> save, bool value)
{
control.Checked = value;
_saveActions.Add(control, c => save.Invoke(((CheckBox)c).Checked));
}
private void BindRadioBox(RadioButton control, Action<bool> save, bool value)
{
control.Checked = value;
_saveActions.Add(control, c => save.Invoke(((RadioButton)c).Checked));
}
private void BindListComboBox<T>(ComboBox comboBox, Action<T> save, IEnumerable<T> values, T value) where T : notnull
{
if (comboBox.DropDownStyle != ComboBoxStyle.DropDownList)
throw new ArgumentOutOfRangeException();
var tagItems = values.Select(o => new TagItem<T>(o, o.ToString()!)).ToArray();
comboBox.Items.AddRange(tagItems.Cast<object>().ToArray());
comboBox.ValueMember = nameof(TagItem<T>.Value);
comboBox.DisplayMember = nameof(TagItem<T>.Text);
_saveActions.Add(comboBox, c => save.Invoke(((TagItem<T>)((ComboBox)c).SelectedItem).Value));
Load += (_, _) => { comboBox.SelectedItem = tagItems.SingleOrDefault(t => t.Value.Equals(value)); };
}
private void BindComboBox(ComboBox control, Func<string, bool> check, Action<string> save, string value, object[]? values = null)
{
if (values != null)
control.Items.AddRange(values);
_saveActions.Add(control, c => save.Invoke(((ComboBox)c).Text));
_checkActions.Add(control, check.Invoke);
Load += (_, _) => { control.Text = value; };
}
#endregion
}
}

View File

@@ -1,6 +1,6 @@
namespace Netch.Forms
{
partial class SubscribeForm
partial class SubscriptionForm
{
/// <summary>
/// Required designer variable.
@@ -29,24 +29,23 @@
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SubscribeForm));
this.AddSubscriptionBox = new System.Windows.Forms.GroupBox();
this.RemarkLabel = new System.Windows.Forms.Label();
this.RemarkTextBox = new System.Windows.Forms.TextBox();
this.LinkLabel = new System.Windows.Forms.Label();
this.LinkTextBox = new System.Windows.Forms.TextBox();
this.UserAgentLabel = new System.Windows.Forms.Label();
this.UserAgentTextBox = new System.Windows.Forms.TextBox();
this.UnselectButton = new System.Windows.Forms.Button();
this.AddButton = new System.Windows.Forms.Button();
this.UserAgentLabel = new System.Windows.Forms.Label();
this.LinkTextBox = new System.Windows.Forms.TextBox();
this.LinkLabel = new System.Windows.Forms.Label();
this.RemarkTextBox = new System.Windows.Forms.TextBox();
this.RemarkLabel = new System.Windows.Forms.Label();
this.SubscribeLinkListView = new System.Windows.Forms.ListView();
this.SubscriptionLinkListView = new System.Windows.Forms.ListView();
this.EnableColumnHeader = new System.Windows.Forms.ColumnHeader();
this.RemarkColumnHeader = new System.Windows.Forms.ColumnHeader();
this.LinkColumnHeader = new System.Windows.Forms.ColumnHeader();
this.UserAgentHeader = new System.Windows.Forms.ColumnHeader();
this.pContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.DeleteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.deleteServerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.DeleteServersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CopyLinkToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.MainTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.AddSubscriptionBox.SuspendLayout();
@@ -56,14 +55,14 @@
//
// AddSubscriptionBox
//
this.AddSubscriptionBox.Controls.Add(this.RemarkLabel);
this.AddSubscriptionBox.Controls.Add(this.RemarkTextBox);
this.AddSubscriptionBox.Controls.Add(this.LinkLabel);
this.AddSubscriptionBox.Controls.Add(this.LinkTextBox);
this.AddSubscriptionBox.Controls.Add(this.UserAgentLabel);
this.AddSubscriptionBox.Controls.Add(this.UserAgentTextBox);
this.AddSubscriptionBox.Controls.Add(this.UnselectButton);
this.AddSubscriptionBox.Controls.Add(this.AddButton);
this.AddSubscriptionBox.Controls.Add(this.UserAgentLabel);
this.AddSubscriptionBox.Controls.Add(this.LinkTextBox);
this.AddSubscriptionBox.Controls.Add(this.LinkLabel);
this.AddSubscriptionBox.Controls.Add(this.RemarkTextBox);
this.AddSubscriptionBox.Controls.Add(this.RemarkLabel);
this.AddSubscriptionBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.AddSubscriptionBox.Location = new System.Drawing.Point(8, 248);
this.AddSubscriptionBox.Name = "AddSubscriptionBox";
@@ -71,6 +70,47 @@
this.AddSubscriptionBox.TabIndex = 1;
this.AddSubscriptionBox.TabStop = false;
//
// RemarkLabel
//
this.RemarkLabel.AutoSize = true;
this.RemarkLabel.Location = new System.Drawing.Point(11, 19);
this.RemarkLabel.Name = "RemarkLabel";
this.RemarkLabel.Size = new System.Drawing.Size(53, 17);
this.RemarkLabel.TabIndex = 1;
this.RemarkLabel.Text = "Remark";
//
// RemarkTextBox
//
this.RemarkTextBox.Location = new System.Drawing.Point(109, 16);
this.RemarkTextBox.Name = "RemarkTextBox";
this.RemarkTextBox.Size = new System.Drawing.Size(545, 23);
this.RemarkTextBox.TabIndex = 2;
//
// LinkLabel
//
this.LinkLabel.AutoSize = true;
this.LinkLabel.Location = new System.Drawing.Point(11, 48);
this.LinkLabel.Name = "LinkLabel";
this.LinkLabel.Size = new System.Drawing.Size(31, 17);
this.LinkLabel.TabIndex = 3;
this.LinkLabel.Text = "Link";
//
// LinkTextBox
//
this.LinkTextBox.Location = new System.Drawing.Point(109, 45);
this.LinkTextBox.Name = "LinkTextBox";
this.LinkTextBox.Size = new System.Drawing.Size(545, 23);
this.LinkTextBox.TabIndex = 4;
//
// UserAgentLabel
//
this.UserAgentLabel.AutoSize = true;
this.UserAgentLabel.Location = new System.Drawing.Point(11, 77);
this.UserAgentLabel.Name = "UserAgentLabel";
this.UserAgentLabel.Size = new System.Drawing.Size(74, 17);
this.UserAgentLabel.TabIndex = 5;
this.UserAgentLabel.Text = "User-Agent";
//
// UserAgentTextBox
//
this.UserAgentTextBox.Location = new System.Drawing.Point(109, 74);
@@ -98,68 +138,28 @@
this.AddButton.UseVisualStyleBackColor = true;
this.AddButton.Click += new System.EventHandler(this.AddButton_Click);
//
// UserAgentLabel
// SubscriptionLinkListView
//
this.UserAgentLabel.AutoSize = true;
this.UserAgentLabel.Location = new System.Drawing.Point(11, 77);
this.UserAgentLabel.Name = "UserAgentLabel";
this.UserAgentLabel.Size = new System.Drawing.Size(74, 17);
this.UserAgentLabel.TabIndex = 5;
this.UserAgentLabel.Text = "User-Agent";
//
// LinkTextBox
//
this.LinkTextBox.Location = new System.Drawing.Point(109, 45);
this.LinkTextBox.Name = "LinkTextBox";
this.LinkTextBox.Size = new System.Drawing.Size(545, 23);
this.LinkTextBox.TabIndex = 4;
//
// LinkLabel
//
this.LinkLabel.AutoSize = true;
this.LinkLabel.Location = new System.Drawing.Point(11, 48);
this.LinkLabel.Name = "LinkLabel";
this.LinkLabel.Size = new System.Drawing.Size(31, 17);
this.LinkLabel.TabIndex = 3;
this.LinkLabel.Text = "Link";
//
// RemarkTextBox
//
this.RemarkTextBox.Location = new System.Drawing.Point(109, 16);
this.RemarkTextBox.Name = "RemarkTextBox";
this.RemarkTextBox.Size = new System.Drawing.Size(545, 23);
this.RemarkTextBox.TabIndex = 2;
//
// RemarkLabel
//
this.RemarkLabel.AutoSize = true;
this.RemarkLabel.Location = new System.Drawing.Point(11, 19);
this.RemarkLabel.Name = "RemarkLabel";
this.RemarkLabel.Size = new System.Drawing.Size(53, 17);
this.RemarkLabel.TabIndex = 1;
this.RemarkLabel.Text = "Remark";
//
// SubscribeLinkListView
//
this.SubscribeLinkListView.AllowColumnReorder = true;
this.SubscribeLinkListView.CheckBoxes = true;
this.SubscribeLinkListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[]
{
this.EnableColumnHeader, this.RemarkColumnHeader, this.LinkColumnHeader, this.UserAgentHeader
});
this.SubscribeLinkListView.Dock = System.Windows.Forms.DockStyle.Fill;
this.SubscribeLinkListView.FullRowSelect = true;
this.SubscribeLinkListView.HideSelection = false;
this.SubscribeLinkListView.Location = new System.Drawing.Point(8, 8);
this.SubscribeLinkListView.MultiSelect = false;
this.SubscribeLinkListView.Name = "SubscribeLinkListView";
this.SubscribeLinkListView.Size = new System.Drawing.Size(668, 234);
this.SubscribeLinkListView.TabIndex = 0;
this.SubscribeLinkListView.UseCompatibleStateImageBehavior = false;
this.SubscribeLinkListView.View = System.Windows.Forms.View.Details;
this.SubscribeLinkListView.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.SubscribeLinkListView_ItemChecked);
this.SubscribeLinkListView.SelectedIndexChanged += new System.EventHandler(this.SubscribeLinkListView_SelectedIndexChanged);
this.SubscribeLinkListView.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SubscribeLinkListView_MouseUp);
this.SubscriptionLinkListView.AllowColumnReorder = true;
this.SubscriptionLinkListView.CheckBoxes = true;
this.SubscriptionLinkListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.EnableColumnHeader,
this.RemarkColumnHeader,
this.LinkColumnHeader,
this.UserAgentHeader});
this.SubscriptionLinkListView.Dock = System.Windows.Forms.DockStyle.Fill;
this.SubscriptionLinkListView.FullRowSelect = true;
this.SubscriptionLinkListView.HideSelection = false;
this.SubscriptionLinkListView.Location = new System.Drawing.Point(8, 8);
this.SubscriptionLinkListView.MultiSelect = false;
this.SubscriptionLinkListView.Name = "SubscriptionLinkListView";
this.SubscriptionLinkListView.Size = new System.Drawing.Size(668, 234);
this.SubscriptionLinkListView.TabIndex = 0;
this.SubscriptionLinkListView.UseCompatibleStateImageBehavior = false;
this.SubscriptionLinkListView.View = System.Windows.Forms.View.Details;
this.SubscriptionLinkListView.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.SubscriptionLinkListView_ItemChecked);
this.SubscriptionLinkListView.SelectedIndexChanged += new System.EventHandler(this.SubscriptionLinkListView_SelectedIndexChanged);
this.SubscriptionLinkListView.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SubscriptionLinkListView_MouseUp);
//
// EnableColumnHeader
//
@@ -182,39 +182,39 @@
//
// pContextMenuStrip
//
this.pContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[]
{
this.DeleteToolStripMenuItem, this.deleteServerToolStripMenuItem, this.CopyLinkToolStripMenuItem
});
this.pContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.DeleteToolStripMenuItem,
this.DeleteServersToolStripMenuItem,
this.CopyLinkToolStripMenuItem});
this.pContextMenuStrip.Name = "pContextMenuStrip";
this.pContextMenuStrip.Size = new System.Drawing.Size(151, 70);
this.pContextMenuStrip.Size = new System.Drawing.Size(161, 70);
//
// DeleteToolStripMenuItem
//
this.DeleteToolStripMenuItem.Name = "DeleteToolStripMenuItem";
this.DeleteToolStripMenuItem.Size = new System.Drawing.Size(150, 22);
this.DeleteToolStripMenuItem.Size = new System.Drawing.Size(160, 22);
this.DeleteToolStripMenuItem.Text = "Delete";
this.DeleteToolStripMenuItem.Click += new System.EventHandler(this.DeleteToolStripMenuItem_Click);
//
// deleteServerToolStripMenuItem
// DeleteServersToolStripMenuItem
//
this.deleteServerToolStripMenuItem.Name = "deleteServerToolStripMenuItem";
this.deleteServerToolStripMenuItem.Size = new System.Drawing.Size(150, 22);
this.deleteServerToolStripMenuItem.Text = "DeleteServer";
this.deleteServerToolStripMenuItem.Click += new System.EventHandler(this.deleteServerToolStripMenuItem_Click);
this.DeleteServersToolStripMenuItem.Name = "DeleteServersToolStripMenuItem";
this.DeleteServersToolStripMenuItem.Size = new System.Drawing.Size(160, 22);
this.DeleteServersToolStripMenuItem.Text = "Delete Servers";
this.DeleteServersToolStripMenuItem.Click += new System.EventHandler(this.DeleteServersToolStripMenuItem_Click);
//
// CopyLinkToolStripMenuItem
//
this.CopyLinkToolStripMenuItem.Name = "CopyLinkToolStripMenuItem";
this.CopyLinkToolStripMenuItem.Size = new System.Drawing.Size(150, 22);
this.CopyLinkToolStripMenuItem.Text = "CopyLink";
this.CopyLinkToolStripMenuItem.Size = new System.Drawing.Size(160, 22);
this.CopyLinkToolStripMenuItem.Text = "Copy link";
this.CopyLinkToolStripMenuItem.Click += new System.EventHandler(this.CopyLinkToolStripMenuItem_Click);
//
// MainTableLayoutPanel
//
this.MainTableLayoutPanel.ColumnCount = 1;
this.MainTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.MainTableLayoutPanel.Controls.Add(this.SubscribeLinkListView, 0, 0);
this.MainTableLayoutPanel.Controls.Add(this.SubscriptionLinkListView, 0, 0);
this.MainTableLayoutPanel.Controls.Add(this.AddSubscriptionBox, 0, 1);
this.MainTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.MainTableLayoutPanel.Location = new System.Drawing.Point(0, 0);
@@ -227,25 +227,26 @@
this.MainTableLayoutPanel.Size = new System.Drawing.Size(684, 391);
this.MainTableLayoutPanel.TabIndex = 11;
//
// SubscribeForm
// SubscriptionForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size(684, 391);
this.Controls.Add(this.MainTableLayoutPanel);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (134)));
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.MaximizeBox = false;
this.Name = "SubscribeForm";
this.Name = "SubscriptionForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Subscribe";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.SubscribeForm_FormClosing);
this.Text = "Subscription";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.SubscriptionForm_FormClosing);
this.AddSubscriptionBox.ResumeLayout(false);
this.AddSubscriptionBox.PerformLayout();
this.pContextMenuStrip.ResumeLayout(false);
this.MainTableLayoutPanel.ResumeLayout(false);
this.ResumeLayout(false);
}
private System.Windows.Forms.ColumnHeader EnableColumnHeader;
@@ -257,7 +258,7 @@
private System.Windows.Forms.Label LinkLabel;
private System.Windows.Forms.TextBox RemarkTextBox;
private System.Windows.Forms.Button AddButton;
private System.Windows.Forms.ListView SubscribeLinkListView;
private System.Windows.Forms.ListView SubscriptionLinkListView;
private System.Windows.Forms.ColumnHeader RemarkColumnHeader;
private System.Windows.Forms.ColumnHeader LinkColumnHeader;
private System.Windows.Forms.ContextMenuStrip pContextMenuStrip;
@@ -269,6 +270,6 @@
#endregion
private System.Windows.Forms.ToolStripMenuItem deleteServerToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem DeleteServersToolStripMenuItem;
}
}

View File

@@ -1,15 +1,15 @@
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System;
using System.Linq;
using System.Windows.Forms;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
namespace Netch.Forms
{
public partial class SubscribeForm : Form
public partial class SubscriptionForm : Form
{
public SubscribeForm()
public SubscriptionForm()
{
InitializeComponent();
Icon = Resources.icon;
@@ -17,33 +17,33 @@ namespace Netch.Forms
i18N.TranslateForm(this);
i18N.TranslateForm(pContextMenuStrip);
InitSubscribeLink();
LoadSubscriptionLinks();
}
private int SelectedIndex
{
get
{
if (SubscribeLinkListView.MultiSelect)
if (SubscriptionLinkListView.MultiSelect)
throw new Exception();
return SubscribeLinkListView.SelectedIndices.Count == 0 ? -1 : SubscribeLinkListView.SelectedIndices[0];
return SubscriptionLinkListView.SelectedIndices.Count == 0 ? -1 : SubscriptionLinkListView.SelectedIndices[0];
}
}
#region EventHandler
private void SubscribeLinkListView_MouseUp(object sender, MouseEventArgs e)
private void SubscriptionLinkListView_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
if (SelectedIndex != -1)
pContextMenuStrip.Show(SubscribeLinkListView, e.Location);
pContextMenuStrip.Show(SubscriptionLinkListView, e.Location);
}
/// <summary>
/// 选中/取消选中
/// </summary>
private void SubscribeLinkListView_SelectedIndexChanged(object sender, EventArgs e)
private void SubscriptionLinkListView_SelectedIndexChanged(object sender, EventArgs e)
{
SetEditingGroup(SelectedIndex);
}
@@ -51,13 +51,13 @@ namespace Netch.Forms
/// <summary>
/// 订阅启/禁用
/// </summary>
private void SubscribeLinkListView_ItemChecked(object sender, ItemCheckedEventArgs e)
private void SubscriptionLinkListView_ItemChecked(object sender, ItemCheckedEventArgs e)
{
var index = e.Item.Index;
Global.Settings.SubscribeLink[index].Enable = SubscribeLinkListView.Items[index].Checked;
Global.Settings.Subscription[index].Enable = SubscriptionLinkListView.Items[index].Checked;
}
private async void SubscribeForm_FormClosing(object sender, FormClosingEventArgs e)
private async void SubscriptionForm_FormClosing(object sender, FormClosingEventArgs e)
{
await Configuration.SaveAsync();
}
@@ -94,13 +94,13 @@ namespace Netch.Forms
if (SelectedIndex == -1)
{
if (Global.Settings.SubscribeLink.Any(link => link.Remark.Equals(RemarkTextBox.Text)))
if (Global.Settings.Subscription.Any(link => link.Remark.Equals(RemarkTextBox.Text)))
{
MessageBoxX.Show("Remark Name Duplicate!");
MessageBoxX.Show(i18N.Translate("Subscription with the specified remark already exists"));
return;
}
Global.Settings.SubscribeLink.Add(new SubscribeLink
Global.Settings.Subscription.Add(new Subscription
{
Enable = true,
Remark = RemarkTextBox.Text,
@@ -110,7 +110,7 @@ namespace Netch.Forms
}
else
{
var subscribeLink = Global.Settings.SubscribeLink[SelectedIndex];
var subscribeLink = Global.Settings.Subscription[SelectedIndex];
RenameServers(subscribeLink.Remark, RemarkTextBox.Text);
subscribeLink.Link = LinkTextBox.Text;
@@ -118,7 +118,7 @@ namespace Netch.Forms
subscribeLink.UserAgent = UserAgentTextBox.Text;
}
InitSubscribeLink();
LoadSubscriptionLinks();
}
#endregion
@@ -131,24 +131,24 @@ namespace Netch.Forms
confirm: true) != DialogResult.OK)
return;
var subscribeLink = Global.Settings.SubscribeLink[SelectedIndex];
var subscribeLink = Global.Settings.Subscription[SelectedIndex];
DeleteServers(subscribeLink.Remark);
Global.Settings.SubscribeLink.Remove(subscribeLink);
Global.Settings.Subscription.Remove(subscribeLink);
InitSubscribeLink();
LoadSubscriptionLinks();
}
private void deleteServerToolStripMenuItem_Click(object sender, EventArgs e)
private void DeleteServersToolStripMenuItem_Click(object sender, EventArgs e)
{
if (MessageBoxX.Show(i18N.Translate("Confirm deletion?"), confirm: true) != DialogResult.OK)
return;
DeleteServers(Global.Settings.SubscribeLink[SelectedIndex].Remark);
DeleteServers(Global.Settings.Subscription[SelectedIndex].Remark);
}
private void CopyLinkToolStripMenuItem_Click(object sender, EventArgs e)
{
Clipboard.SetText(Global.Settings.SubscribeLink[SelectedIndex].Link);
Clipboard.SetText(Global.Settings.Subscription[SelectedIndex].Link);
}
#endregion
@@ -166,12 +166,12 @@ namespace Netch.Forms
server.Group = newGroup;
}
private void InitSubscribeLink()
private void LoadSubscriptionLinks()
{
SubscribeLinkListView.Items.Clear();
SubscriptionLinkListView.Items.Clear();
foreach (var item in Global.Settings.SubscribeLink)
SubscribeLinkListView.Items.Add(new ListViewItem(new[]
foreach (var item in Global.Settings.Subscription)
SubscriptionLinkListView.Items.Add(new ListViewItem(new[]
{
"",
item.Remark,
@@ -202,7 +202,7 @@ namespace Netch.Forms
return;
}
var item = Global.Settings.SubscribeLink[index];
var item = Global.Settings.Subscription[index];
AddSubscriptionBox.Text = item.Remark;
RemarkTextBox.Text = item.Remark;
LinkTextBox.Text = item.Link;

View File

@@ -0,0 +1,63 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="pContextMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@@ -0,0 +1,92 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Netch.Forms
{
public class SyncGlobalCheckBox : CheckBox
{
public SyncGlobalCheckBox()
{
AutoCheck = false;
OnSyncGlobalChanged();
}
private bool _syncGlobal;
private bool _globalValue;
public bool SyncGlobal
{
get => _syncGlobal;
set
{
if (value == _syncGlobal)
return;
_syncGlobal = value;
OnSyncGlobalChanged();
}
}
public bool GlobalValue
{
get => _globalValue;
set
{
if (value == _globalValue)
return;
_globalValue = value;
if (SyncGlobal)
Checked = value;
}
}
protected override void OnClick(EventArgs e)
{
if (Checked == GlobalValue)
{
SyncGlobal = !SyncGlobal;
if (SyncGlobal)
return;
}
Checked = !Checked;
base.OnClick(e);
}
public bool? Value
{
get => _syncGlobal ? null : Checked;
set
{
if (value == null)
{
SyncGlobal = true;
}
else
{
SyncGlobal = false;
Checked = (bool)value;
}
}
}
private void OnSyncGlobalChanged()
{
if (_syncGlobal)
{
Font = new Font(Font, FontStyle.Regular);
BackColor = SystemColors.Control;
}
else
{
Font = new Font(Font, FontStyle.Bold | FontStyle.Italic);
BackColor = Color.Yellow;
}
}
}
}

View File

@@ -2,9 +2,11 @@ using System;
using System.Collections.Generic;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Windows.Forms;
using Netch.Forms;
using Netch.Models;
using Netch.Models.Modes;
namespace Netch
{
@@ -42,7 +44,7 @@ namespace Netch
public static JsonSerializerOptions NewCustomJsonSerializerOptions() => new()
{
WriteIndented = true,
IgnoreNullValues = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
}

View File

@@ -1,11 +1,13 @@
using System.Threading.Tasks;
using Netch.Models;
using Netch.Models.Modes;
using Netch.Servers;
namespace Netch.Interfaces
{
public interface IModeController : IController
{
public ModeFeature Features { get; }
public Task StartAsync(Socks5Server server, Mode mode);
}
}

View File

@@ -37,8 +37,8 @@ namespace Netch.Interops
public enum NameList
{
TYPE_REST,
TYPE_ADDR,
TYPE_LIST,
TYPE_LISN,
TYPE_CDNS,
TYPE_ODNS
}

View File

@@ -1,15 +0,0 @@
using System.Runtime.InteropServices;
namespace Netch.Interops
{
public static class NFAPI
{
private const string nfapinet_bin = "nfapinet.dll";
[DllImport(nfapinet_bin, CallingConvention = CallingConvention.Cdecl)]
public static extern NF_STATUS nf_registerDriver(string driverName);
[DllImport(nfapinet_bin, CallingConvention = CallingConvention.Cdecl)]
public static extern NF_STATUS nf_unRegisterDriver(string driverName);
}
}

View File

@@ -1,11 +0,0 @@
namespace Netch.Interops
{
public enum NF_STATUS : int
{
NF_STATUS_SUCCESS = 0,
NF_STATUS_FAIL = -1,
NF_STATUS_INVALID_ENDPOINT_ID = -2,
NF_STATUS_NOT_INITIALIZED = -3,
NF_STATUS_IO_ERROR = -4
}
}

View File

@@ -8,38 +8,35 @@ namespace Netch.Interops
{
public enum NameList
{
TYPE_FILTERLOOPBACK,
TYPE_FILTERICMP,
TYPE_FILTERTCP,
TYPE_FILTERUDP,
AIO_FILTERLOOPBACK,
AIO_FILTERINTRANET, // LAN
AIO_FILTERPARENT,
AIO_FILTERICMP,
AIO_FILTERTCP,
AIO_FILTERUDP,
AIO_FILTERDNS,
TYPE_CLRNAME,
TYPE_ADDNAME,
TYPE_BYPNAME,
AIO_ICMPING,
TYPE_DNSHOST,
AIO_DNSONLY,
AIO_DNSPROX,
AIO_DNSHOST,
AIO_DNSPORT,
TYPE_TCPLISN,
TYPE_TCPTYPE,
TYPE_TCPHOST,
TYPE_TCPUSER,
TYPE_TCPPASS,
TYPE_TCPMETH,
TYPE_TCPPROT,
TYPE_TCPPRPA,
TYPE_TCPOBFS,
TYPE_TCPOBPA,
AIO_TGTHOST,
AIO_TGTPORT,
AIO_TGTUSER,
AIO_TGTPASS,
TYPE_UDPLISN,
TYPE_UDPTYPE,
TYPE_UDPHOST,
TYPE_UDPUSER,
TYPE_UDPPASS,
TYPE_UDPMETH,
TYPE_UDPPROT,
TYPE_UDPPRPA,
TYPE_UDPOBFS,
TYPE_UDPOBPA
AIO_CLRNAME,
AIO_ADDNAME,
AIO_BYPNAME
}
public static bool Dial(NameList name, bool value)
{
Log.Verbose($"[Redirector] Dial {name}: {value}");
return aio_dial(name, value.ToString().ToLower());
}
public static bool Dial(NameList name, string value)
@@ -58,10 +55,14 @@ namespace Netch.Interops
return await Task.Run(aio_free).ConfigureAwait(false);
}
public const int UdpNameListOffset = (int)NameList.TYPE_UDPLISN - (int)NameList.TYPE_TCPLISN;
private const string Redirector_bin = "Redirector.bin";
[DllImport(Redirector_bin, CallingConvention = CallingConvention.Cdecl)]
public static extern bool aio_register([MarshalAs(UnmanagedType.LPWStr)] string value);
[DllImport(Redirector_bin, CallingConvention = CallingConvention.Cdecl)]
public static extern bool aio_unregister([MarshalAs(UnmanagedType.LPWStr)] string value);
[DllImport(Redirector_bin, CallingConvention = CallingConvention.Cdecl)]
private static extern bool aio_dial(NameList name, [MarshalAs(UnmanagedType.LPWStr)] string value);

View File

@@ -0,0 +1,44 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using Netch.Models.Modes;
using Netch.Models.Modes.ProcessMode;
using Netch.Models.Modes.ShareMode;
using Netch.Models.Modes.TunMode;
namespace Netch.JsonConverter
{
public class ModeConverterWithTypeDiscriminator : JsonConverter<Mode>
{
public override Mode? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var jsonElement = JsonSerializer.Deserialize<JsonElement>(ref reader);
var modeTypePropertyName = JsonNamingPolicy.CamelCase.ConvertName(nameof(Mode.Type));
if (!jsonElement.TryGetProperty(modeTypePropertyName, out var modeTypeToken))
throw new JsonException();
var modeTypeEnum = modeTypeToken.ValueKind switch
{
JsonValueKind.Number => (ModeType)modeTypeToken.GetInt32(),
JsonValueKind.String => Enum.Parse<ModeType>(modeTypeToken.GetString()!),
_ => throw new JsonException()
};
var modeType = modeTypeEnum switch
{
ModeType.ProcessMode => typeof(Redirector),
ModeType.TunMode => typeof(TunMode),
ModeType.ShareMode => typeof(ShareMode),
_ => throw new ArgumentOutOfRangeException()
};
return (Mode?)jsonElement.Deserialize(modeType, options);
}
public override void Write(Utf8JsonWriter writer, Mode value, JsonSerializerOptions options)
{
JsonSerializer.Serialize<object>(writer, value, options);
}
}
}

View File

@@ -1,19 +1,18 @@
using Netch.Models;
using System;
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using Netch.Models;
using Netch.Utils;
namespace Netch.Utils
namespace Netch.JsonConverter
{
public class ServerConverterWithTypeDiscriminator : JsonConverter<Server>
{
public override bool CanConvert(Type typeToConvert) => typeToConvert == typeof(Server);
public override Server Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var jsonElement = JsonSerializer.Deserialize<JsonElement>(ref reader);
var type = ServerHelper.GetTypeByTypeName(jsonElement.GetProperty("Type").GetString()!);
return (Server)JsonSerializer.Deserialize(jsonElement.GetRawText(), type)!;
return (Server)jsonElement.Deserialize(type)!;
}
public override void Write(Utf8JsonWriter writer, Server value, JsonSerializerOptions options)

View File

@@ -1,123 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Netch.Enums;
using Netch.Utils;
namespace Netch.Models
{
public class Mode
{
private List<string>? _content;
public Mode(string? fullName)
{
FullName = fullName;
if (FullName == null || !File.Exists(FullName))
return;
Load();
}
public string? FullName { get; }
public List<string> Content => _content ??= ReadContent();
public string Remark { get; set; } = "";
public ModeType Type { get; set; } = ModeType.Process;
public string? RelativePath => FullName == null ? null : ModeHelper.GetRelativePath(FullName);
private void Load()
{
if (FullName == null)
return;
(Remark, Type) = ReadHead(FullName);
_content = null;
}
public IEnumerable<string> GetRules()
{
foreach (var s in Content)
{
if (string.IsNullOrWhiteSpace(s))
continue;
if (s.StartsWith("//"))
continue;
const string include = "#include";
if (s.StartsWith(include))
{
var relativePath = new StringBuilder(s[include.Length..].Trim());
relativePath.Replace("<", "").Replace(">", "");
relativePath.Replace(".h", ".txt");
var mode = Global.Modes.FirstOrDefault(m => m.RelativePath?.Equals(relativePath.ToString()) ?? false) ??
throw new MessageException($"{relativePath} file included in {Remark} not found");
if (mode == this)
throw new MessageException("Can't self-reference");
if (mode.Type != Type)
throw new MessageException($"{mode.Remark}'s mode is not as same as {Remark}'s mode");
if (mode.Content.Any(rule => rule.StartsWith(include)))
throw new Exception("Cannot reference mode that reference other mode");
foreach (var rule in mode.GetRules())
yield return rule;
}
else
{
yield return s;
}
}
}
private static (string, ModeType) ReadHead(string fileName)
{
var text = File.ReadLines(fileName).First();
if (text.First() != '#')
throw new FormatException($"{fileName} head not found at Line 0");
var strings = text[1..].SplitTrimEntries(',');
var remark = strings[0];
var typeNumber = int.TryParse(strings.ElementAtOrDefault(1), out var type) ? type : 0;
if (!Enum.GetValues(typeof(ModeType)).Cast<int>().Contains(typeNumber))
throw new NotSupportedException($"Not support mode \"{typeNumber}\".");
return (remark, (ModeType)typeNumber);
}
private List<string> ReadContent()
{
if (FullName == null || !File.Exists(FullName))
return new List<string>();
return File.ReadLines(FullName).Skip(1).ToList();
}
public void WriteFile()
{
var dir = Path.GetDirectoryName(FullName)!;
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
var content = $"# {Remark}, {(int)Type}{Constants.EOF}{string.Join(Constants.EOF, Content)}";
// 写入到模式文件里
File.WriteAllText(FullName!, content);
}
public override string ToString()
{
return $"[{(int)Type + 1}] {i18N.Translate(Remark)}";
}
}
}

View File

@@ -0,0 +1,29 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Netch.Utils;
namespace Netch.Models.Modes
{
public abstract class Mode
{
[JsonPropertyOrder(int.MinValue)]
public abstract ModeType Type { get; }
public Dictionary<string, string> Remark { get; set; } = new();
[JsonIgnore]
// File FullName
// TODO maybe make it becomes mode dictionary key
public string FullName { get; set; } = null!;
public override string ToString() => $"[{(int)Type + 1}] {i18NRemark}";
[JsonIgnore]
public string i18NRemark
{
// TODO i18N.Culture to support fallback
get => Remark.GetValueOrDefault(i18N.LangCode) ?? Remark.GetValueOrDefault("en") ?? "";
set => Remark[i18N.LangCode] = value;
}
}
}

View File

@@ -1,6 +1,6 @@
using System;
namespace Netch.Enums
namespace Netch.Models.Modes
{
[Flags]
public enum ModeFeature

View File

@@ -0,0 +1,20 @@
namespace Netch.Models.Modes
{
public enum ModeType
{
/// <summary>
/// 进程代理
/// </summary>
ProcessMode,
/// <summary>
/// 网络共享
/// </summary>
ShareMode,
/// <summary>
/// 网卡代理
/// </summary>
TunMode
}
}

View File

@@ -0,0 +1,39 @@
using System.Collections.Generic;
namespace Netch.Models.Modes.ProcessMode
{
public class Redirector : Mode
{
public override ModeType Type => ModeType.ProcessMode;
#region Base
public bool? FilterICMP { get; set; }
public bool? FilterTCP { get; set; }
public bool? FilterUDP { get; set; }
public bool? FilterDNS { get; set; }
public bool? FilterParent { get; set; }
public int? ICMPDelay { get; set; }
public bool? DNSProxy { get; set; }
public bool? HandleOnlyDNS { get; set; }
public string? DNSHost { get; set; }
#endregion
public bool FilterLoopback { get; set; } = false;
public bool FilterIntranet { get; set; } = true;
public List<string> Bypass { get; set; } = new();
public List<string> Handle { get; set; } = new();
}
}

View File

@@ -0,0 +1,9 @@
namespace Netch.Models.Modes.ShareMode
{
public class ShareMode : Mode
{
public override ModeType Type => ModeType.ShareMode;
public string Argument = "--preset uu";
}
}

View File

@@ -0,0 +1,13 @@
using System.Collections.Generic;
namespace Netch.Models.Modes.TunMode
{
public class TunMode : Mode
{
public override ModeType Type => ModeType.TunMode;
public List<string> Bypass { get; set; } = new();
public List<string> Handle { get; set; } = new();
}
}

View File

@@ -1,4 +1,6 @@
namespace Netch.Models
using Netch.Models.Modes;
namespace Netch.Models
{
public class Profile
{
@@ -13,7 +15,7 @@
public Profile(Server server, Mode mode, string name, int index)
{
ServerRemark = server.Remark;
ModeRemark = mode.Remark;
ModeRemark = mode.i18NRemark;
ProfileName = name;
Index = index;
}

View File

@@ -111,7 +111,8 @@ namespace Netch.Models
{
public static async Task<string> AutoResolveHostnameAsync(this Server server, AddressFamily inet = AddressFamily.Unspecified)
{
return Global.Settings.ResolveServerHostname ? (await DnsUtils.LookupAsync(server.Hostname, inet))!.ToString() : server.Hostname;
// ! MainController cached
return (await DnsUtils.LookupAsync(server.Hostname, inet))!.ToString();
}
public static bool IsInGroup(this Server server)

View File

@@ -0,0 +1,11 @@
namespace Netch.Models
{
public class AioDNSConfig
{
public string ChinaDNS { get; set; } = $"tcp://{Constants.DefaultCNPrimaryDNS}";
public string OtherDNS { get; set; } = $"tcp://{Constants.DefaultPrimaryDNS}";
public ushort ListenPort { get; set; } = 253;
}
}

View File

@@ -0,0 +1,19 @@
namespace Netch.Models
{
public class KcpConfig
{
public bool congestion { get; set; } = false;
public int downlinkCapacity { get; set; } = 100;
public int mtu { get; set; } = 1350;
public int readBufferSize { get; set; } = 2;
public int tti { get; set; } = 50;
public int uplinkCapacity { get; set; } = 12;
public int writeBufferSize { get; set; } = 2;
}
}

View File

@@ -0,0 +1,23 @@
namespace Netch.Models
{
public class RedirectorConfig
{
public bool FilterTCP { get; set; } = true;
public bool FilterUDP { get; set; } = true;
public bool FilterDNS { get; set; } = true;
public bool FilterParent { get; set; } = false;
public bool HandleOnlyDNS { get; set; } = true;
public bool DNSProxy { get; set; } = true;
public string DNSHost { get; set; } = Constants.DefaultPrimaryDNS;
public int ICMPDelay { get; set; } = 10;
public bool FilterICMP { get; set; } = false;
}
}

View File

@@ -1,117 +1,10 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
namespace Netch.Models
{
/// <summary>
/// TUN/TAP 适配器配置类
/// </summary>
public class TUNConfig
{
/// <summary>
/// 地址
/// </summary>
public string Address { get; set; } = "10.0.236.10";
/// <summary>
/// DNS
/// </summary>
public string HijackDNS { get; set; } = "tcp://1.1.1.1:53";
/// <summary>
/// 网关
/// </summary>
public string Gateway { get; set; } = "10.0.236.1";
/// <summary>
/// 掩码
/// </summary>
public string Netmask { get; set; } = "255.255.255.0";
/// <summary>
/// 模式 2 下是否代理 DNS
/// </summary>
public bool ProxyDNS { get; set; } = false;
/// <summary>
/// 使用自定义 DNS 设置
/// </summary>
public bool UseCustomDNS { get; set; } = true;
/// <summary>
/// 全局绕过 IP 列表
/// </summary>
public List<string> BypassIPs { get; set; } = new();
}
public class KcpConfig
{
public bool congestion { get; set; } = false;
public int downlinkCapacity { get; set; } = 100;
public int mtu { get; set; } = 1350;
public int readBufferSize { get; set; } = 2;
public int tti { get; set; } = 50;
public int uplinkCapacity { get; set; } = 12;
public int writeBufferSize { get; set; } = 2;
}
public class V2rayConfig
{
public bool AllowInsecure { get; set; } = false;
public KcpConfig KcpConfig { get; set; } = new();
public bool UseMux { get; set; } = false;
public bool V2rayNShareLink { get; set; } = true;
public bool XrayCone { get; set; } = false;
}
public class AioDNSConfig
{
public string ChinaDNS { get; set; } = "tcp://223.5.5.5:53";
public string OtherDNS { get; set; } = "tcp://1.1.1.1:53";
public ushort ListenPort { get; set; } = 253;
}
public class RedirectorConfig
{
/// <summary>
/// 不代理TCP
/// </summary>
public PortType FilterProtocol { get; set; } = PortType.Both;
/// <summary>
/// 是否开启DNS转发
/// </summary>
public bool DNSHijack { get; set; } = true;
/// <summary>
/// 转发DNS地址
/// </summary>
public string DNSHijackHost { get; set; } = "1.1.1.1:53";
[JsonIgnore]
public int ICMPDelay { get; } = 0;
public bool FilterICMP { get; set; } = false;
/// <summary>
/// 是否代理子进程
/// </summary>
public bool ChildProcessHandle { get; set; } = false;
}
/// <summary>
/// 用于读取和写入的配置的类
/// </summary>
@@ -191,11 +84,6 @@ namespace Netch.Models
/// </summary>
public int RequestTimeout { get; set; } = 10000;
/// <summary>
/// 解析服务器主机名
/// </summary>
public bool ResolveServerHostname { get; set; } = true;
/// <summary>
/// 是否开机启动软件
/// </summary>
@@ -244,7 +132,7 @@ namespace Netch.Models
/// <summary>
/// 订阅链接列表
/// </summary>
public List<SubscribeLink> SubscribeLink { get; set; } = new();
public List<Subscription> Subscription { get; set; } = new();
/// <summary>
/// TUNTAP 适配器配置
@@ -260,7 +148,21 @@ namespace Netch.Models
public bool NoSupportDialog { get; set; } = false;
public Setting Clone()
#region Migration
[Obsolete]
public JsonElement SubscribeLink
{
set
{
if (Subscription == null! || !Subscription.Any())
Subscription = value.Deserialize<List<Subscription>>()!;
}
}
#endregion
public Setting ShallowCopy()
{
return (Setting)MemberwiseClone();
}

View File

@@ -0,0 +1,45 @@
using System.Collections.Generic;
namespace Netch.Models
{
/// <summary>
/// TUN/TAP 适配器配置类
/// </summary>
public class TUNConfig
{
/// <summary>
/// 地址
/// </summary>
public string Address { get; set; } = "10.0.236.10";
/// <summary>
/// DNS
/// </summary>
public string HijackDNS { get; set; } = $"tcp://{Constants.DefaultPrimaryDNS}";
/// <summary>
/// 网关
/// </summary>
public string Gateway { get; set; } = "10.0.236.1";
/// <summary>
/// 掩码
/// </summary>
public string Netmask { get; set; } = "255.255.255.0";
/// <summary>
/// 模式 2 下是否代理 DNS
/// </summary>
public bool ProxyDNS { get; set; } = false;
/// <summary>
/// 使用自定义 DNS 设置
/// </summary>
public bool UseCustomDNS { get; set; } = false;
/// <summary>
/// Global bypass IPs
/// </summary>
public List<string> BypassIPs { get; set; } = new();
}
}

View File

@@ -0,0 +1,15 @@
namespace Netch.Models
{
public class V2rayConfig
{
public bool AllowInsecure { get; set; } = false;
public KcpConfig KcpConfig { get; set; } = new();
public bool UseMux { get; set; } = false;
public bool V2rayNShareLink { get; set; } = true;
public bool XrayCone { get; set; } = true;
}
}

View File

@@ -1,6 +1,6 @@
namespace Netch.Models
{
public class SubscribeLink
public class Subscription
{
/// <summary>
/// 启用状态

View File

@@ -32,9 +32,9 @@
<ItemGroup>
<PackageReference Include="HMBSbige.SingleInstance" Version="5.0.7" />
<PackageReference Include="MaxMind.GeoIP2" Version="4.0.1" />
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.71" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.VisualStudio.Threading" Version="16.10.56" />
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.1.506-beta">
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.73" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.VisualStudio.Threading" Version="17.0.63" />
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.1.588-beta">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
@@ -45,13 +45,12 @@
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="4.1.2" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" Condition="'$(Configuration)'=='Debug'" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.0" />
<PackageReference Include="Stun.Net" Version="5.0.0" />
<PackageReference Include="System.Management" Version="5.0.0" />
<PackageReference Include="System.Reactive" Version="5.0.0" />
<PackageReference Include="TaskScheduler" Version="2.9.1" />
<PackageReference Include="Microsoft-WindowsAPICodePack-Shell" Version="1.1.4" />
<PackageReference Include="System.Text.Json" Version="6.0.0-rc.2.21480.5" />
<PackageReference Include="TaskScheduler" Version="2.9.2" />
<PackageReference Include="WindowsFirewallHelper" Version="2.1.4.81" />
<PackageReference Include="System.ServiceProcess.ServiceController" Version="5.0.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" />
@@ -67,6 +66,13 @@
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Update="Forms\SyncGlobalCheckBox.cs">
<SubType>UserControl</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<None Remove="NativeMethods.txt" />
</ItemGroup>
<Target Condition="'$(PublishSingleFile)' == 'true'" AfterTargets="_ComputeFilesToBundle" Name="RemoveDupeAssemblies">

View File

@@ -25,9 +25,9 @@ using Windows.Win32.UI.WindowsAndMessaging;
namespace Netch
{
public static class Netch
public static class Program
{
public static readonly SingleInstanceService SingleInstance = new($"Global\\{nameof(Netch)}");
public static readonly SingleInstanceService SingleInstance = new($"Global\\{nameof(Program)}");
internal static HWND ConsoleHwnd { get; private set; }
@@ -45,6 +45,13 @@ namespace Netch
var binPath = Path.Combine(Global.NetchDir, "bin");
Environment.SetEnvironmentVariable("PATH", $"{Environment.GetEnvironmentVariable("PATH")};{binPath}");
if (!Directory.Exists("bin") || !Directory.EnumerateFileSystemEntries("bin").Any())
{
i18N.Load("System");
MessageBoxX.Show(i18N.Translate("Please extract all files then run the program!"));
Environment.Exit(2);
}
Updater.CleanOld(Global.NetchDir);
// 预创建目录
@@ -86,12 +93,6 @@ namespace Netch
// 加载语言
i18N.Load(Global.Settings.Language);
if (!Directory.Exists("bin") || !Directory.EnumerateFileSystemEntries("bin").Any())
{
MessageBoxX.Show(i18N.Translate("Please extract all files then run the program!"));
Environment.Exit(2);
}
Task.Run(LogEnvironment).Forget();
CheckClr();
CheckOS();
@@ -113,8 +114,15 @@ namespace Netch
Log.Information("OS: {OSVersion}", Environment.OSVersion);
Log.Information("SHA256: {Hash}", $"{Utils.Utils.SHA256CheckSum(Global.NetchExecutable)}");
Log.Information("System Language: {Language}", CultureInfo.CurrentCulture.Name);
#if RELEASE
if (Log.IsEnabled(LogEventLevel.Debug))
Log.Debug("Third-party Drivers:\n{Drivers}", string.Join("\n", SystemInfo.SystemDrivers(false)));
{
// TODO log level setting
Task.Run(() => Log.Debug("Third-party Drivers:\n{Drivers}", string.Join(Constants.EOF, SystemInfo.SystemDrivers(false)))).Forget();
Task.Run(() => Log.Debug("Running Processes: \n{Processes}", string.Join(Constants.EOF, SystemInfo.Processes(false)))).Forget();
}
#endif
}
private static void CheckClr()
@@ -130,10 +138,13 @@ namespace Netch
if (frameworkName.Version.Major != Environment.Version.Major)
{
Log.Information("CLR: {OSVersion}", Environment.Version);
Log.Information("CLR: {Version}", Environment.Version);
Flags.NoSupport = true;
if(!Global.Settings.NoSupportDialog)
MessageBoxX.Show(i18N.TranslateFormat("{0} won't get developers' support, Please do not report any issues or seek help from developers.", "CLR " + Environment.Version), LogLevel.WARNING);
if (!Global.Settings.NoSupportDialog)
MessageBoxX.Show(
i18N.TranslateFormat("{0} won't get developers' support, Please do not report any issues or seek help from developers.",
"CLR " + Environment.Version),
LogLevel.WARNING);
}
}
@@ -142,8 +153,11 @@ namespace Netch
if (Environment.OSVersion.Version.Build < 17763)
{
Flags.NoSupport = true;
if(!Global.Settings.NoSupportDialog)
MessageBoxX.Show(i18N.TranslateFormat("{0} won't get developers' support, Please do not report any issues or seek help from developers.", Environment.OSVersion), LogLevel.WARNING);
if (!Global.Settings.NoSupportDialog)
MessageBoxX.Show(
i18N.TranslateFormat("{0} won't get developers' support, Please do not report any issues or seek help from developers.",
Environment.OSVersion),
LogLevel.WARNING);
}
}
@@ -162,13 +176,13 @@ namespace Netch
Log.Logger = new LoggerConfiguration()
#if DEBUG
.MinimumLevel.Verbose()
.WriteTo.Async(c => c.Debug(outputTemplate: Constants.OutputTemplate))
#else
.MinimumLevel.Debug()
#endif
.WriteTo.Async(c => c.File(Path.Combine(Global.NetchDir, Constants.LogFile),
outputTemplate: Constants.OutputTemplate,
rollOnFileSizeLimit: false))
.WriteTo.Console(outputTemplate: Constants.OutputTemplate)
.MinimumLevel.Override(@"Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.CreateLogger();
@@ -176,7 +190,7 @@ namespace Netch
private static void Application_OnException(object sender, ThreadExceptionEventArgs e)
{
Log.Error(e.Exception, "未处理异常");
Log.Error(e.Exception, "Unhandled error");
}
private static void Application_OnExit(object? sender, EventArgs eventArgs)

View File

@@ -1,6 +1,6 @@
using Netch.Controllers;
using System.Reflection;
using System.Reflection;
using System.Runtime.InteropServices;
using Netch.Controllers;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
@@ -13,9 +13,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright(UpdateChecker.Copyright)]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
#if NET
[assembly: System.Runtime.Versioning.SupportedOSPlatformAttribute("Windows7.0")]
#endif
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型

View File

@@ -18,9 +18,9 @@
"Testing NAT Type": "正在测试 NAT 类型",
"Setup Route Table Rule": "配置路由规则",
"Test failed": "测试失败",
"Starting update subscription": "正在更新订阅",
"Subscription updated": "订阅更新完毕",
"Register driver": "正在注册驱动",
"Updating servers": "正在更新服务器",
"Servers updated": "服务器更新完毕",
"Installing netfilter2 driver": "正在安装 netfilter2 驱动",
"Server": "服务器",
"Import Servers From Clipboard": "从剪贴板导入服务器",
@@ -28,10 +28,10 @@
"Netch is now minimized to the notification bar, double click this icon to restore.": "Netch 已最小化至通知栏,双击此图标恢复窗口",
"New version available": "发现新版本",
"Already latest version": "已经是最新版本",
"New version found failed": "寻找新版本失败",
"Check for update failed": "检查更新失败",
"Mode": "模式",
"Help": "帮助",
"Check for updates": "检查更新",
"Check for update": "检查更新",
"Download and install now?": "立即下载并安装?",
"Start downloading new version": "开始下载新版本",
"Download update failed": "下载更新错误",
@@ -39,6 +39,10 @@
"Edit Process Mode": "修改进程模式",
"Create Route Table Rule": "创建路由表规则",
"Edit Route Table Rule": "修改路由表规则",
"Reload Modes": "重新加载模式",
"Handle rules": "处理规则",
"Bypass rules": "分流规则",
"Handle DNS through proxy": "经过代理处理 DNS",
"Address": "地址",
"Username": "用户名",
@@ -64,16 +68,16 @@
"Plugin": "插件",
"Plugin Options": "插件参数",
"Subscribe": "订阅",
"Manage Subscribe Links": "管理订阅链接",
"Update Servers From Subscribe Links": "从订阅链接更新服务器",
"Subscription": "订阅",
"Manage Subscriptions": "管理订阅",
"Update Servers": "更新服务器",
"No subscription link": "没有任何一条订阅链接",
"Updating {0}": "正在更新 {0}",
"Update {1} server(s) from {0}": "从 {0} 更新 {1} 个服务器",
"Update servers error from {0}": "从 {0} 更新服务器失败",
"Update {1} server(s) from {0}": "从 {0} 更新 {1} 个服务器",
"Update servers failed from {0}": "从 {0} 更新服务器失败",
"Confirm deletion?": "确认删除?",
"DeleteServer": "删除订阅节点",
"CopyLink": "复制链接",
"Delete Servers": "删除订阅节点",
"Copy link": "复制链接",
"Status": "状态",
"Link": "链接",
"Unselect": "取消选择",
@@ -103,17 +107,20 @@
"Please select a mode first": "请先选择一个模式",
"Please enter a profile name first": "请先为该配置设置一个名称",
"No saved profile here. Save a profile first by Ctrl+Click on the button": "当前按钮下没有保存配置,请先使用 CTRL + 左键 点击该按钮保存一个配置",
"Lookup Server hostname failed": "解析服务器主机名失败",
"Used": "已使用",
"Testing": "测试中",
"Remark": "备注",
"Filename": "文件名",
"Use Custom Filename": "使用自定义文件名",
"Add": "添加",
"Scan": "扫描",
"Save": "保存",
"Modify": "修改",
"Select": "选择",
"Validation": "验证",
"Action": "动作",
"Select a folder": "选择一个目录",
"Please enter an process name (xxx.exe)": "请输入一个进程名xxx.exe",
"Rule does not conform to C++ regular expression syntax": "规则不符合 C++ 正则表达式语法",
@@ -124,6 +131,7 @@
"Please enter a mode remark": "请输入模式的备注",
"File already exists.\n Please Change the filename": "文件名已存在,请修改文件名",
"Please enter a mode filename": "请输入模式的文件名",
"Above rules does not conform to C++ regular expression syntax": "以上规则不符合 C++ 正则表达式语法",
"Proxy Rule IPs": "代理规则 IP",
"Bypass Rule IPs": "绕过规则 IP",
@@ -132,6 +140,7 @@
"Delete or not ? Will clean up the corresponding group of items in the server list": "是否删除?将会清理服务器列表中对应组的项目",
"Remark can not be empty": "备注不可为空",
"Link can not be empty": "链接不可为空",
"Subscription with the specified remark already exists": "带有指定备注的订阅已存在",
"Link must start with http:// or https://": "链接必须以 http:// 或 https:// 开头",
"Settings": "设置",
@@ -142,7 +151,7 @@
"Allow other Devices to connect": "允许其他设备连入",
"Netmask": "子网掩码",
"Gateway": "网关",
"Use Custom DNS": "使用自定义 DNS",
"Use custom DNS": "使用自定义 DNS",
"Proxy DNS in Proxy Rule IPs Mode": "在 代理规则IP 模式下代理 DNS",
"Exit when closed": "关闭时退出",
"Stop when exited": "退出时停止",
@@ -150,18 +159,22 @@
"Check update when opened": "打开软件时检查更新",
"Check Beta update": "检查 Beta 更新",
"Update Servers when opened": "打开软件时更新服务器",
"Filter Protocol": "Filter 协议",
"Handle process's DNS Hijack": "被代理进程 DNS 劫持",
"Child Process Handle": "子进程代理",
"ICMP Delay(ms)": "ICMP 延迟(毫秒",
"Redirector built-in Shadowsocks support": "Redirector 内建 Shadowsocks 支持",
"Handle ICMP": "处理 ICMP",
"Handle TCP": "处理 TCP",
"Handle UDP": "处理 UDP",
"Handle DNS (DNS hijacking)": "处理 DNSDNS 劫持",
"Handle handled process's DNS": "处理被处理进程 DNS",
"Handle local loopback": "处理本地回环",
"Handle LAN": "处理局域网",
"Handle child process": "处理子进程",
"ICMP delay(ms)": "ICMP 延迟(毫秒)",
"Mode specific options": "模式专用设置",
"Profile Count": "快捷配置数量",
"Delay test after start(sec)": "启动后延迟测试(秒)",
"Ping Protocol": "延迟测试协议",
"Detection Tick(sec)": "检测心跳(秒)",
"STUN Server": "STUN 服务器",
"Language": "语言",
"Resolve Server Hostname": "解析服务器主机名",
"FullCone Support (Required Server Xray-core v1.3.0+)": "FullCone 支持(需服务端 Xray-core v1.3.0+",
"Disable Support Warning": "停用支持警告",
@@ -174,8 +187,7 @@
"The {0} port is in use.": "{0} 端口已被占用",
"The {0} port is reserved by system.": "{0} 端口是系统保留端口",
"\"Core.bin\" is missing. Please check your Antivirus software": "找不到 \"Core.bin\" 文件!请检查你的杀毒软件。",
"{0} won't get developers' support, Please do not report any issues or seek help from developers.": "{0} 将不会得到开发者的支持,请不要报告任何问题或寻求开发人员的帮助。",
"No Support": "不受支持"
}

View File

@@ -15,7 +15,7 @@ namespace Netch.Servers
protected override IEnumerable<string> StartedKeywords => new[] { "listening at" };
protected override IEnumerable<string> FailedKeywords => new[] { "Invalid config path", "usage", "plugin service exit unexpectedly" };
protected override IEnumerable<string> FailedKeywords => new[] { "error", "failed to start plguin" };
public override string Name => "Shadowsocks";
@@ -29,13 +29,10 @@ namespace Netch.Servers
var arguments = new object?[]
{
"-s", await server.AutoResolveHostnameAsync(),
"-p", server.Port,
"-b", this.LocalAddress(),
"-l", this.Socks5LocalPort(),
"-s", $"{await server.AutoResolveHostnameAsync()}:{server.Port}",
"-b", $"{this.LocalAddress()}:{this.Socks5LocalPort()}",
"-m", server.EncryptMethod,
"-k", server.Password,
"-u", SpecialArgument.Flag,
"--plugin", server.Plugin,
"--plugin-opts", server.PluginOption
};

View File

@@ -64,7 +64,7 @@ namespace Netch.Servers
var server = (ShadowsocksServer)s;
if (!SSGlobal.EncryptMethods.Contains(server.EncryptMethod))
{
Log.Warning("不支持的 SS 加密方式:{Method}", server.EncryptMethod);
Log.Warning("Unsupported SS Encrypt Method: {Method}", server.EncryptMethod);
return false;
}

View File

@@ -145,19 +145,19 @@ namespace Netch.Servers
var server = (ShadowsocksRServer)s;
if (!SSRGlobal.EncryptMethods.Contains(server.EncryptMethod))
{
Log.Error("不支持的 SSR 加密方式:{Method}", server.EncryptMethod);
Log.Error("Unsupported ShadowsocksR Encrypt method: {Method}", server.EncryptMethod);
return false;
}
if (!SSRGlobal.Protocols.Contains(server.Protocol))
{
Log.Error("不支持的 SSR 协议:{Protocol}", server.Protocol);
Log.Error("Unsupported ShadowsocksR Protocol: {Protocol}", server.Protocol);
return false;
}
if (!SSRGlobal.OBFSs.Contains(server.OBFS))
{
Log.Error("不支持的 SSR 混淆:{Obfs}", server.OBFS);
Log.Error("Unsupported ShadowsocksR Obfs: {Obfs}", server.OBFS);
return false;
}

View File

@@ -41,7 +41,7 @@ namespace Netch.Servers
},
ssl = new TrojanSSL
{
sni = server.Host.ValueOrDefault() ?? (Global.Settings.ResolveServerHostname ? server.Hostname : "")
sni = server.Host.ValueOrDefault() ?? server.Hostname
}
};

View File

@@ -152,7 +152,7 @@ namespace Netch.Servers
var tlsSettings = new TlsSettings
{
allowInsecure = Global.Settings.V2RayConfig.AllowInsecure,
serverName = server.ServerName.ValueOrDefault() ?? server.Hostname
serverName = server.ServerName.ValueOrDefault() ?? server.Host.SplitOrDefault()?[0]
};
switch (server.TLSSecureType)

View File

@@ -0,0 +1,115 @@
using System;
using System.IO;
using Netch.Controllers;
using Netch.Interfaces;
using Netch.Models;
using Netch.Models.Modes;
using Netch.Utils;
using Serilog;
namespace Netch.Services
{
public class ModeService
{
public static readonly ModeService Instance = new();
public string ModeDirectoryFullName => Path.Combine(Global.NetchDir, "mode");
public string GetRelativePath(string fullName)
{
var length = ModeDirectoryFullName.Length;
if (!ModeDirectoryFullName.EndsWith("\\"))
length++;
return fullName.Substring(length);
}
public string GetFullPath(string relativeName)
{
return Path.Combine(ModeDirectoryFullName, relativeName);
}
public void Load()
{
Global.Modes.Clear();
LoadCore(ModeDirectoryFullName);
Sort();
Global.MainForm.LoadModes();
}
private void LoadCore(string modeDirectory)
{
foreach (var directory in Directory.GetDirectories(modeDirectory))
LoadCore(directory);
// skip Directory with a disabled file in
if (File.Exists(Path.Combine(modeDirectory, Constants.DisableModeDirectoryFileName)))
return;
foreach (var file in Directory.GetFiles(modeDirectory))
{
try
{
Global.Modes.Add(ModeHelper.LoadMode(file));
}
catch (NotSupportedException)
{
// ignored
}
catch (Exception e)
{
Log.Warning(e, "Load mode \"{FileName}\" failed", file);
}
}
}
private static void Sort()
{
// TODO better sort need to discuss
// TODO replace Mode Collection type
Global.Modes.Sort((a, b) => string.Compare(a.i18NRemark, b.i18NRemark, StringComparison.Ordinal));
}
public void Add(Mode mode)
{
if (mode.FullName == null)
throw new InvalidOperationException();
Global.Modes.Add(mode);
Sort();
Global.MainForm.ModeComboBox.Items.Insert(Global.Modes.IndexOf(mode), mode);
mode.WriteFile();
}
public static void Delete(Mode mode)
{
if (mode.FullName == null)
throw new ArgumentException(nameof(mode.FullName));
Global.MainForm.ModeComboBox.Items.Remove(mode);
Global.Modes.Remove(mode);
if (File.Exists(mode.FullName))
File.Delete(mode.FullName);
}
public static IModeController GetModeControllerByType(ModeType type, out ushort? port, out string portName)
{
port = null;
portName = string.Empty;
switch (type)
{
case ModeType.ProcessMode:
return new NFController();
case ModeType.TunMode:
return new TUNController();
case ModeType.ShareMode:
return new PcapController();
default:
Log.Error("Unknown Mode Type \"{Type}\"", (int)type);
throw new MessageException("Unknown Mode Type");
}
}
}
}

View File

@@ -13,19 +13,13 @@ namespace Netch.Services
{
public class Updater
{
#region Static
#endregion
#region Class
private string UpdateFile { get; }
private string InstallDirectory { get; }
private readonly string _tempDirectory;
private static readonly string[] KeepDirectories = { "data", "mode\\Custom", "logging" };
private static readonly string[] KeepFiles = { ModeHelper.DisableModeDirectoryFileName };
private static readonly string[] KeepFiles = { Constants.DisableModeDirectoryFileName };
internal Updater(string updateFile, string installDirectory)
{
@@ -142,7 +136,5 @@ namespace Netch.Services
}
#endregion
#endregion
}
}

View File

@@ -78,7 +78,7 @@ namespace Netch.Utils
var pidHastSet = processes.Select(instance => instance.Id).ToHashSet();
Log.Information("流量统计进程: {Processes}", string.Join(',', processes.Select(v => $"({v.Id}){v.ProcessName}")));
Log.Information("Net traffic processes: {Processes}", string.Join(',', processes.Select(v => $"({v.Id}){v.ProcessName}")));
received = 0;

View File

@@ -5,6 +5,7 @@ using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Threading;
using Netch.JsonConverter;
using Netch.Models;
using Serilog;
@@ -50,12 +51,12 @@ namespace Netch.Utils
if (await LoadCoreAsync(FileFullName))
return;
Log.Information("尝试加载备份配置文件 {FileName}", BackupFileFullName);
Log.Information("Load backup configuration \"{FileName}\"", BackupFileFullName);
await LoadCoreAsync(BackupFileFullName);
}
catch (Exception e)
{
Log.Error(e, "加载配置异常");
Log.Error(e, "Load configuration failed");
Environment.Exit(-1);
}
}
@@ -77,7 +78,7 @@ namespace Netch.Utils
}
catch (Exception e)
{
Log.Error(e, @"从 {FileName} 加载配置异常", filename);
Log.Error(e, "Load configuration file \"{FileName}\" error ", filename);
return false;
}
}
@@ -90,8 +91,8 @@ namespace Netch.Utils
for (var i = 0; i < settings.Profiles.Count; i++)
settings.Profiles[i].Index = i;
settings.AioDNS.ChinaDNS = Utils.HostAppendPort(settings.AioDNS.ChinaDNS);
settings.AioDNS.OtherDNS = Utils.HostAppendPort(settings.AioDNS.OtherDNS);
settings.AioDNS.ChinaDNS = DnsUtils.AppendPort(settings.AioDNS.ChinaDNS);
settings.AioDNS.OtherDNS = DnsUtils.AppendPort(settings.AioDNS.OtherDNS);
}
/// <summary>
@@ -122,7 +123,7 @@ namespace Netch.Utils
}
catch (Exception e)
{
Log.Error(e, "保存配置异常");
Log.Error(e, "Save Configuration error");
}
}

View File

@@ -1,10 +1,9 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using Microsoft.VisualStudio.Threading;
using Netch.Models;
using Timer = System.Timers.Timer;
namespace Netch.Utils
{
@@ -12,9 +11,9 @@ namespace Netch.Utils
{
private static readonly Timer Timer;
private static readonly SemaphoreSlim Lock = new(1, 1);
private static readonly AsyncSemaphore Lock = new(1);
private static readonly SemaphoreSlim PoolLock = new(16, 16);
private static readonly AsyncSemaphore PoolLock = new(16);
public static readonly NumberRange Range = new(0, int.MaxValue / 1000);
@@ -47,28 +46,21 @@ namespace Netch.Utils
if (Lock.CurrentCount == 0)
{
if (waitFinish)
{
await Lock.WaitAsync();
Lock.Release();
}
(await Lock.EnterAsync()).Dispose();
return;
}
await Lock.WaitAsync();
using var _ = await Lock.EnterAsync();
try
{
var tasks = Global.Settings.Server.Select(async s =>
{
await PoolLock.WaitAsync();
try
using (await PoolLock.EnterAsync())
{
await s.PingAsync();
}
finally
{
PoolLock.Release();
}
});
await Task.WhenAll(tasks);
@@ -77,10 +69,6 @@ namespace Netch.Utils
{
// ignored
}
finally
{
Lock.Release();
}
}
public static void UpdateTick(bool performTestAtOnce = false)

View File

@@ -1,7 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
@@ -64,8 +62,7 @@ namespace Netch.Utils
Cache6.Add(hostname, result);
break;
default:
Trace.Assert(false);
break;
throw new ArgumentOutOfRangeException();
}
return result;
@@ -74,32 +71,18 @@ namespace Netch.Utils
return null;
}
/// <summary>
/// 查询
/// </summary>
/// <param name="hostname">主机名</param>
/// <returns></returns>
public static void ClearCache()
{
Cache.Clear();
Cache6.Clear();
}
public static IEnumerable<string> Split(string dns)
public static string AppendPort(string host, ushort port = 53)
{
return dns.SplitRemoveEmptyEntriesAndTrimEntries(',');
}
if (!host.Contains(':'))
return host + $":{port}";
public static bool TrySplit(string value, out IEnumerable<string> result, ushort maxCount = 0)
{
result = Split(value).ToArray();
return maxCount == 0 || result.Count() <= maxCount && result.All(ip => IPAddress.TryParse(ip, out _));
}
public static string Join(IEnumerable<string> dns)
{
return string.Join(",", dns);
return host;
}
}
}

View File

@@ -1,9 +1,9 @@
using System;
using System.IO;
using System.Linq;
using Serilog;
using WindowsFirewallHelper;
using WindowsFirewallHelper.FirewallRules;
using Serilog;
namespace Netch.Utils
{
@@ -18,7 +18,7 @@ namespace Netch.Utils
{
if (!FirewallWAS.IsLocallySupported)
{
Log.Warning("不支持防火墙");
Log.Warning("Windows Firewall Locally Unsupported");
return;
}
@@ -38,7 +38,7 @@ namespace Netch.Utils
}
catch (Exception e)
{
Log.Warning(e, "添加防火墙规则错误");
Log.Warning(e, "Create Netch Firewall rules error");
}
}
@@ -58,7 +58,7 @@ namespace Netch.Utils
}
catch (Exception e)
{
Log.Warning(e, "清除防火墙规则错误");
Log.Warning(e, "Remove Netch Firewall rules error");
}
}

View File

@@ -1,147 +1,142 @@
using System;
using System.IO;
using System.Linq;
using System.Reactive.Linq;
using Netch.Controllers;
using Netch.Enums;
using Netch.Interfaces;
using Netch.Models;
using Serilog;
using System.Text.Json;
using System.Text.Json.Serialization;
using Netch.JsonConverter;
using Netch.Models.Modes;
using Netch.Models.Modes.ProcessMode;
using Netch.Models.Modes.ShareMode;
using Netch.Models.Modes.TunMode;
using Netch.Services;
namespace Netch.Utils
{
public static class ModeHelper
{
public const string DisableModeDirectoryFileName = "disabled";
private static readonly JsonSerializerOptions JsonSerializerOptions = Global.NewCustomJsonSerializerOptions();
private static FileSystemWatcher _fileSystemWatcher = null!;
public static string ModeDirectoryFullName => Path.Combine(Global.NetchDir, "mode");
public static bool SuspendWatcher
static ModeHelper()
{
get => _fileSystemWatcher.EnableRaisingEvents;
set => _fileSystemWatcher.EnableRaisingEvents = value;
JsonSerializerOptions.Converters.Add(new ModeConverterWithTypeDiscriminator());
JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.Never;
}
public static void InitWatcher()
public static Mode LoadMode(string file)
{
_fileSystemWatcher = new FileSystemWatcher(ModeDirectoryFullName)
if (file.EndsWith(".json"))
return LoadJsonMode(file);
if (file.EndsWith(".txt"))
return ReadTxtMode(file);
throw new NotSupportedException();
}
private static Mode LoadJsonMode(string file)
{
using var fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true);
var mode = JsonSerializer.Deserialize<Mode>(fs, JsonSerializerOptions) ?? throw new ArgumentNullException();
mode.FullName = file;
return mode;
}
public static void WriteFile(this Mode mode)
{
using var fs = new FileStream(mode.FullName, FileMode.Create, FileAccess.Write, FileShare.None, 4096, true);
JsonSerializer.Serialize(fs, mode, JsonSerializerOptions);
}
private static Mode ReadTxtMode(string file)
{
Mode mode;
var ls = File.ReadAllLines(file);
string modeTypeNum;
if (ls.First().First() != '#')
throw new FormatException("Not a valid txt mode that begins with meta line");
var heads = ls[0][1..].Split(",", StringSplitOptions.TrimEntries);
switch (modeTypeNum = heads.ElementAtOrDefault(1) ?? "0")
{
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName,
IncludeSubdirectories = true,
EnableRaisingEvents = true
};
var created = Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(h => _fileSystemWatcher.Created += h,
h => _fileSystemWatcher.Created -= h)
.Select(x => x.EventArgs);
var changed = Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(h => _fileSystemWatcher.Changed += h,
h => _fileSystemWatcher.Changed -= h)
.Select(x => x.EventArgs);
var deleted = Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(h => _fileSystemWatcher.Deleted += h,
h => _fileSystemWatcher.Deleted -= h)
.Select(x => x.EventArgs);
var renamed = Observable.FromEventPattern<RenamedEventHandler, RenamedEventArgs>(h => _fileSystemWatcher.Renamed += h,
h => _fileSystemWatcher.Renamed -= h)
.Select(x => x.EventArgs);
var o = Observable.Merge(created, deleted, renamed, changed);
o.Throttle(TimeSpan.FromSeconds(3)).Subscribe(_ => OnModeChange(), exception => Log.Error(exception, "FileSystemWatcherError"));
}
private static void OnModeChange()
{
Load();
Global.MainForm.LoadModes();
}
public static string GetRelativePath(string fullName)
{
var length = ModeDirectoryFullName.Length;
if (!ModeDirectoryFullName.EndsWith("\\"))
length++;
return fullName.Substring(length);
}
public static string GetFullPath(string relativeName)
{
return Path.Combine(ModeDirectoryFullName, relativeName);
}
public static void Load()
{
Global.Modes.Clear();
LoadCore(ModeDirectoryFullName);
Sort();
}
private static void LoadCore(string modeDirectory)
{
try
{
foreach (var directory in Directory.GetDirectories(modeDirectory))
LoadCore(directory);
// skip Directory with a disabled file in
if (File.Exists(Path.Combine(modeDirectory, DisableModeDirectoryFileName)))
return;
foreach (var file in Directory.GetFiles(modeDirectory).Where(f => f.EndsWith(".txt")))
try
{
Global.Modes.Add(new Mode(file));
}
catch (Exception e)
{
Log.Warning(e, "Load mode \"{FileName}\" failed", file);
}
}
catch
{
// ignored
}
}
private static void Sort()
{
Global.Modes.Sort((a, b) => string.Compare(a.Remark, b.Remark, StringComparison.Ordinal));
}
public static void Delete(Mode mode)
{
if (mode.FullName == null)
throw new ArgumentException(nameof(mode.FullName));
Global.MainForm.ModeComboBox.Items.Remove(mode);
Global.Modes.Remove(mode);
if (File.Exists(mode.FullName))
File.Delete(mode.FullName);
}
public static (IModeController, ModeFeature) GetModeControllerByType(ModeType type, out ushort? port, out string portName)
{
port = null;
portName = string.Empty;
switch (type)
{
case ModeType.Process:
return (new NFController(), ModeFeature.SupportIPv6 | ModeFeature.SupportSocks5Auth);
case ModeType.ProxyRuleIPs:
return (new TUNController(), ModeFeature.SupportSocks5Auth);
case ModeType.BypassRuleIPs:
return (new TUNController(), ModeFeature.SupportSocks5Auth);
case ModeType.Pcap2Socks:
return (new PcapController(), 0);
case "0":
mode = new Redirector { FullName = file };
break;
case "1":
case "2":
mode = new TunMode { FullName = file };
break;
case "6":
mode = new ShareMode { FullName = file };
break;
default:
Log.Error("未知模式类型");
throw new MessageException("未知模式类型");
throw new ArgumentOutOfRangeException();
}
mode.Remark.Add("en", heads[0]);
foreach (var l in ls.Skip(1))
{
if (l.IsNullOrWhiteSpace())
continue;
if (l.StartsWith("//"))
continue;
Mode? includeMode = null;
if (l.StartsWith("#include"))
{
var relativePath = l["#include ".Length..].Replace("<", "").Replace(">", "").Replace(".h", ".txt").Trim();
includeMode = ReadTxtMode(ModeService.Instance.GetFullPath(relativePath));
}
switch (mode)
{
case Redirector processMode:
if (includeMode is Redirector pMode)
{
processMode.Bypass.AddRange(pMode.Bypass);
processMode.Handle.AddRange(pMode.Handle);
}
else if (l.StartsWith("!"))
processMode.Bypass.Add(l);
else
processMode.Handle.Add(l);
break;
case ShareMode shareMode:
shareMode.Argument = l;
break;
case TunMode tunMode:
if (includeMode is TunMode tMode)
{
tunMode.Bypass.AddRange(tMode.Bypass);
tMode.Handle.AddRange(tMode.Handle);
break;
}
switch (modeTypeNum)
{
case "1":
tunMode.Handle.Add(l);
break;
case "2":
tunMode.Bypass.Add(l);
break;
}
break;
default:
throw new ArgumentOutOfRangeException();
}
}
if (modeTypeNum == "2")
((TunMode)mode).Handle.Add("0.0.0.0/0");
return mode;
}
}
}

View File

@@ -5,8 +5,8 @@ using System.Management;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using Netch.Models;
using Windows.Win32;
using Netch.Models;
namespace Netch.Utils
{
@@ -15,14 +15,15 @@ namespace Netch.Utils
public static NetworkInterface GetBest(AddressFamily addressFamily = AddressFamily.InterNetwork)
{
string ipAddress;
if (addressFamily == AddressFamily.InterNetwork)
switch (addressFamily)
{
ipAddress = "114.114.114.114";
}
else
{
Trace.Assert(addressFamily == AddressFamily.InterNetworkV6);
throw new NotImplementedException();
case AddressFamily.InterNetwork:
ipAddress = "114.114.114.114";
break;
case AddressFamily.InterNetworkV6:
throw new NotImplementedException();
default:
throw new InvalidOperationException();
}
if (PInvoke.GetBestRoute(BitConverter.ToUInt32(IPAddress.Parse(ipAddress).GetAddressBytes(), 0), 0, out var route) != 0)

View File

@@ -28,7 +28,7 @@ namespace Netch.Utils
}
catch (Exception e)
{
Log.Error(e, "获取保留端口错误");
Log.Error(e, "Get reserved ports failed");
}
}
@@ -37,33 +37,41 @@ namespace Netch.Utils
if (port == 0)
throw new ArgumentOutOfRangeException();
if (inet != AddressFamily.InterNetwork)
Trace.Assert(inet == AddressFamily.InterNetworkV6);
var process = new List<Process>();
unsafe
switch (inet)
{
uint err;
uint size = 0;
PInvoke.GetExtendedTcpTable(default, ref size, false, (uint)inet, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_LISTENER, 0); // get size
var tcpTable = (MIB_TCPTABLE_OWNER_PID*)Marshal.AllocHGlobal((int)size);
if ((err = PInvoke.GetExtendedTcpTable(tcpTable, ref size, false, (uint)inet, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_LISTENER, 0)) != 0)
throw new Win32Exception((int)err);
for (var i = 0; i < tcpTable -> dwNumEntries; i++)
case AddressFamily.InterNetwork:
{
var row = tcpTable -> table.ReadOnlyItemRef(i);
var process = new List<Process>();
unsafe
{
uint err;
uint size = 0;
PInvoke.GetExtendedTcpTable(default, ref size, false, (uint)inet, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_LISTENER, 0); // get size
var tcpTable = (MIB_TCPTABLE_OWNER_PID*)Marshal.AllocHGlobal((int)size);
if (row.dwOwningPid is 0 or 4)
continue;
if ((err = PInvoke.GetExtendedTcpTable(tcpTable, ref size, false, (uint)inet, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_LISTENER, 0)) !=
0)
throw new Win32Exception((int)err);
if (PInvoke.ntohs((ushort)row.dwLocalPort) == port)
process.Add(Process.GetProcessById((int)row.dwOwningPid));
for (var i = 0; i < tcpTable -> dwNumEntries; i++)
{
var row = tcpTable -> table.ReadOnlyItemRef(i);
if (row.dwOwningPid is 0 or 4)
continue;
if (PInvoke.ntohs((ushort)row.dwLocalPort) == port)
process.Add(Process.GetProcessById((int)row.dwOwningPid));
}
}
return process;
}
case AddressFamily.InterNetworkV6:
throw new NotImplementedException();
default:
throw new InvalidOperationException();
}
return process;
}
private static void GetReservedPortRange(PortType portType, ref List<NumberRange> targetList)
@@ -86,7 +94,7 @@ namespace Netch.Utils
foreach (var line in output.SplitRemoveEmptyEntriesAndTrimEntries('\n'))
{
var value = line.Trim().SplitRemoveEmptyEntries(' ');
if (value.Length != 2)
if (value.Length < 2)
continue;
if (!ushort.TryParse(value[0], out var start) || !ushort.TryParse(value[1], out var end))
@@ -136,8 +144,7 @@ namespace Netch.Utils
break;
default:
Trace.Assert(false);
return;
throw new ArgumentOutOfRangeException(nameof(type), type, null);
}
}

View File

@@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using Netch.JsonConverter;
using Netch.Models;
using Netch.Servers;
using Serilog;
@@ -53,13 +54,13 @@ namespace Netch.Utils
}
catch (Exception e)
{
Log.Error(e, "从分享链接导入服务器异常");
Log.Error(e, "Parse servers from share link error");
}
}
}
catch (Exception e)
{
Log.Error(e, "从分享链接导入服务器异常");
Log.Error(e, "Parse servers from share link error");
}
return list;
@@ -84,7 +85,7 @@ namespace Netch.Utils
if (util != null)
list.AddRange(util.ParseUri(text));
else
Log.Warning("无法处理 {Scheme} 协议订阅链接", scheme);
Log.Warning("\"{Scheme}\" scheme share link not supported", scheme);
}
foreach (var node in list.Where(node => !node.Remark.IsNullOrWhiteSpace()))

View File

@@ -66,6 +66,8 @@ namespace Netch.Utils
{
switch (res.BindingTestResult, res.MappingBehavior, res.FilteringBehavior)
{
case (BindingTestResult.Fail, _, _):
return "NoUDP";
case (not BindingTestResult.Success, _, _):
return res.BindingTestResult.ToString();
case (_, MappingBehavior.Direct or MappingBehavior.EndpointIndependent, FilteringBehavior.EndpointIndependent):
@@ -74,6 +76,8 @@ namespace Netch.Utils
return "2";
case (_, MappingBehavior.AddressDependent or MappingBehavior.AddressAndPortDependent, _):
return "3";
case (_, MappingBehavior.Fail, _):
return MappingBehavior.Fail.ToString();
default:
return res.FilteringBehavior.ToString();
}

View File

@@ -8,16 +8,16 @@ using Serilog;
namespace Netch.Utils
{
public static class Subscription
public static class SubscriptionUtil
{
private static readonly object ServerLock = new();
public static async Task UpdateServersAsync(string? proxyServer = default)
{
await Task.WhenAll(Global.Settings.SubscribeLink.Select(item => UpdateServerCoreAsync(item, proxyServer)));
await Task.WhenAll(Global.Settings.Subscription.Select(item => UpdateServerCoreAsync(item, proxyServer)));
}
private static async Task UpdateServerCoreAsync(SubscribeLink item, string? proxyServer)
private static async Task UpdateServerCoreAsync(Subscription item, string? proxyServer)
{
try
{
@@ -53,8 +53,8 @@ namespace Netch.Utils
}
catch (Exception e)
{
Global.MainForm.NotifyTip($"{i18N.TranslateFormat("Update servers error from {0}", item.Remark)}\n{e.Message}", info: false);
Log.Warning(e, "更新服务器失败");
Global.MainForm.NotifyTip($"{i18N.TranslateFormat("Update servers failed from {0}", item.Remark)}\n{e.Message}", info: false);
Log.Warning(e, "Update servers failed");
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
@@ -13,14 +14,14 @@ namespace Netch.Utils
var mc = new ManagementClass("Win32_SystemDriver");
foreach (var obj in mc.GetInstances().Cast<ManagementObject>())
{
if (!(bool) obj["Started"])
if (!(bool)obj["Started"])
continue;
var path = obj["PathName"].ToString();
if (path == null)
continue;
var vendorExclude = new[] {"microsoft", "intel", "amd", "nvidia", "realtek"};
var vendorExclude = new[] { "microsoft", "intel", "amd", "nvidia", "realtek" };
var vendorName = FileVersionInfo.GetVersionInfo(path).LegalCopyright ?? string.Empty;
if (!allDriver && vendorExclude.Any(s => vendorName.Contains(s, StringComparison.OrdinalIgnoreCase)))
continue;
@@ -31,22 +32,28 @@ namespace Netch.Utils
public static IEnumerable<string> Processes(bool mask)
{
var hashset = new HashSet<string>();
var sortedSet = new SortedSet<string>();
var windowsFolder = Environment.GetFolderPath(Environment.SpecialFolder.Windows);
var windowsAppsFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "WindowsApps");
var userProfileFolder = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
foreach (var process in Process.GetProcesses())
{
try
{
if (process.Id is 0 or 4)
var path = process.MainModule?.FileName;
if (path == null)
continue;
if (process.MainModule!.FileName!.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.Windows), StringComparison.OrdinalIgnoreCase))
if (path.StartsWith(windowsFolder, StringComparison.OrdinalIgnoreCase))
continue;
if (path.StartsWith(windowsAppsFolder, StringComparison.OrdinalIgnoreCase))
continue;
var path = process.MainModule.FileName;
if (mask)
path = path.Replace(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "%USERPROFILE%");
hashset.Add(path);
sortedSet.Add(path.Replace(userProfileFolder, "%USERPROFILE%"));
else
sortedSet.Add(path);
}
catch (Exception)
{
@@ -54,7 +61,7 @@ namespace Netch.Utils
}
}
return hashset;
return sortedSet;
}
}
}

View File

@@ -33,7 +33,7 @@ namespace Netch.Utils
}
catch (Exception e)
{
Log.Warning(e, "打开 {Uri} 失败", path);
Log.Warning(e, "Open \"{Uri}\" failed", path);
}
}
@@ -246,14 +246,6 @@ namespace Netch.Utils
return subnet.GetAddressBytes().Sum(b => Convert.ToString(b, 2).Count(c => c == '1'));
}
public static string HostAppendPort(string host, ushort port = 53)
{
if (!host.Contains(':'))
host += $":{port}";
return host;
}
public static string GetHostFromUri(string str)
{
var startIndex = str.LastIndexOf('/');

View File

@@ -10,7 +10,7 @@ namespace Netch.Utils
public static class WebUtil
{
public const string DefaultUserAgent =
@"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.67";
@"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36 Edg/94.0.992.31";
static WebUtil()
{
@@ -50,7 +50,6 @@ namespace Netch.Utils
/// 异步下载并编码为字符串
/// </summary>
/// <param name="req"></param>
/// <param name="rep"></param>
/// <param name="encoding">编码默认UTF-8</param>
/// <returns></returns>
public static (HttpStatusCode, string) DownloadString(HttpWebRequest req, Encoding? encoding = null)

View File

@@ -1,5 +1,4 @@
using Netch.Properties;
using System.Collections;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
@@ -7,18 +6,17 @@ using System.Linq;
using System.Text;
using System.Text.Json;
using System.Windows.Forms;
using Netch.Properties;
using Serilog;
namespace Netch.Utils
{
public static class i18N
{
#if NET
static i18N()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}
#endif
/// <summary>
/// 数据
@@ -42,7 +40,7 @@ namespace Netch.Utils
{
var oldLangCode = LangCode;
LangCode = languages.FirstOrDefault(s => GetLanguage(s).Equals(GetLanguage(LangCode))) ?? "en-US";
Log.Information("找不到语言 {OldLangCode}, 使用 {LangCode}",oldLangCode,LangCode);
Log.Information("Not found language {OldLangCode}, use {LangCode} instead", oldLangCode, LangCode);
}
switch (LangCode)
@@ -62,7 +60,7 @@ namespace Netch.Utils
if (!dictionary.Any())
{
Log.Error("{LangCode} 语言文件错误", LangCode);
Log.Error("Invalid language file \"{LangCode}\"", LangCode);
return;
}

View File

@@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.6" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.6" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.7" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.7" />
<PackageReference Include="coverlet.collector" Version="3.1.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@@ -22,23 +22,20 @@ param (
$PublishSingleFile = $True
)
# .\scripts\download.ps1 $OutputPath
Remove-Item -Recurse -Force $OutputPath -Confirm:$false -ErrorAction Ignore
# if ( -Not $? ) {
# Exit 1
# }
.\scripts\download.ps1 $OutputPath
Write-Host "Building $Configuration to $OutputPath"
dotnet publish `
-c $Configuration `
-r "win-x64" `
-p:Platform="x64" `
-p:PublishSingleFile=$PublishSingleFile `
-r 'win-x64' `
-p:Platform='x64' `
-p:SelfContained=$SelfContained `
-p:PublishTrimmed=$SelfContained `
-p:PublishTrimmed=$False `
-p:PublishReadyToRun=$PublishReadyToRun `
-p:PublishSingleFile=$PublishSingleFile `
-p:IncludeNativeLibrariesForSelfExtract=$SelfContained `
-o $OutputPath `
Netch\Netch.csproj
if ($lastExitCode) { exit $lastExitCode }
exit 0
'.\Netch\Netch.csproj'
exit $lastExitCode

View File

@@ -22,7 +22,7 @@ New-Item -ItemType Directory -Name i18n | Out-Null
Copy-Item -Recurse -Force .\netchdata-master\* .\bin
Copy-Item -Recurse -Force .\netchmode-master\mode\* .\mode
Copy-Item -Recurse -Force .\netchi18n-master\i18n\* .\i18n
Copy-Item -Recurse -Force .\netchi18n-master\i18n\* .\i18n
Remove-Item -Recurse -Force netchdata-master
Remove-Item -Recurse -Force netchmode-master
@@ -31,9 +31,9 @@ Remove-Item -Force data.zip
Remove-Item -Force mode.zip
Remove-Item -Force i18n.zip
..\scripts\download\aiodns.ps1 -OutputPath bin
..\scripts\download\cloak.ps1 -OutputPath bin
..\scripts\download\xray-core.ps1 -OutputPath bin
..\scripts\download\cloak.ps1 -OutputPath bin
..\scripts\download\xray-core.ps1 -OutputPath bin
..\scripts\download\pcap2socks.ps1 -OutputPath bin
Get-Item *
Set-Location $last

View File

@@ -1,10 +0,0 @@
param([string]$OutputPath)
$address="https://github.com/aiocloud/aiodns/releases/download/1.0.4/aiodns.bin"
$domains="https://raw.githubusercontent.com/aiocloud/aiodns/master/aiodns.conf"
Invoke-WebRequest -Uri $address -OutFile aiodns.bin
Invoke-WebRequest -Uri $domains -OutFile aiodns.conf
Move-Item -Force aiodns.bin $OutputPath
Move-Item -Force aiodns.conf $OutputPath
exit 0

View File

@@ -1,5 +1,5 @@
param([string]$OutputPath)
$address="https://github.com/cbeuw/Cloak/releases/download/v2.5.4/ck-client-windows-amd64-v2.5.4.exe"
$address="https://github.com/cbeuw/Cloak/releases/download/v2.5.5/ck-client-windows-amd64-v2.5.5.exe"
Invoke-WebRequest -Uri $address -OutFile ck-client.exe

View File

@@ -0,0 +1,11 @@
param([string]$OutputPath)
$address="https://github.com/zhxie/pcap2socks/releases/download/v0.6.2/pcap2socks-v0.6.2-windows-amd64.zip"
Invoke-WebRequest -Uri $address -OutFile pcap2socks.zip
Expand-Archive -Force -Path pcap2socks.zip -DestinationPath pcap2socks
Move-Item -Force pcap2socks\pcap2socks.exe $OutputPath
Remove-Item -Recurse -Force pcap2socks
Remove-Item -Recurse -Force pcap2socks.zip
exit 0

View File

@@ -1,12 +1,12 @@
param([string]$OutputPath)
$address="https://github.com/XTLS/Xray-core/releases/download/v1.4.2/Xray-windows-64.zip"
$address="https://github.com/XTLS/Xray-core/releases/download/v1.4.5/Xray-windows-64.zip"
Invoke-WebRequest -Uri $address -OutFile xray-core.zip
Expand-Archive -Force -Path xray-core.zip -DestinationPath xray-core
Move-Item -Force xray-core\xray.exe $OutputPath
Move-Item -Force xray-core\geoip.dat $OutputPath
Move-Item -Force xray-core\geosite.dat $OutputPath
# Move-Item -Force xray-core\geoip.dat $OutputPath
# Move-Item -Force xray-core\geosite.dat $OutputPath
Remove-Item -Recurse -Force xray-core
Remove-Item -Recurse -Force xray-core.zip