Compare commits

...

30 Commits

Author SHA1 Message Date
Space Time
e1b1c606e1 1.1.4 -> 1.1.5 第29次更新 2025-06-26 13:03:30 +08:00
Space Time
46de61c4f2 1.1.4 -> 1.1.5 第28次更新 2025-06-25 22:15:17 +08:00
Space Time
479c16c2a1 1.1.4 -> 1.1.5 第27次更新 2025-06-06 10:35:25 +08:00
Space Time
938ca77fc1 1.1.4 -> 1.1.5 第26次更新 2025-06-05 09:27:48 +08:00
Space Time
d9e307e647 1.1.4 -> 1.1.5 第25次更新 2025-06-05 09:09:16 +08:00
Space Time
85213b61da 1.1.4 -> 1.1.5 第24次更新 2025-06-05 08:54:06 +08:00
Space Time
bf7772a35f 1.1.4 -> 1.1.5 第23次更新 2025-06-04 21:59:22 +08:00
Space Time
188e56b57b 1.1.4 -> 1.1.5 第22次更新 2025-05-25 13:48:04 +08:00
Space Time
0150440de4 1.1.4 -> 1.1.5 第21次更新 2025-03-18 15:56:27 +08:00
Space Time
c25888bd5a 1.1.4 -> 1.1.5 第20次更新 2025-03-10 17:17:34 +08:00
Space Time
a97b04e5d9 1.1.4 -> 1.1.5 第19次更新 2025-03-03 17:03:23 +08:00
Space Time
b3dc94eb2b 1.1.4 -> 1.1.5 第18次更新 2025-03-01 12:44:47 +08:00
Space Time
597e441af5 1.1.4 -> 1.1.5 第17次更新 2025-02-25 16:30:10 +08:00
Space Time
8a81ba59dc 1.1.4 -> 1.1.5 第16次更新 2024-12-30 18:50:41 +08:00
Space Time
d748976aa9 1.1.5 (alpha) 更新 2024-12-30 16:34:12 +08:00
Space Time
f428de3fd7 1.1.4 -> 1.1.5 第15次更新 2024-12-29 22:16:58 +08:00
Space Time
bcccb73520 1.1.4 -> 1.1.5 第14次更新 2024-12-29 20:53:56 +08:00
Space Time
6fd9631d5c 1.1.4 -> 1.1.5 第13次更新 2024-12-29 20:04:24 +08:00
Space Time
2c5004f02d 1.1.4 -> 1.1.5 第12次更新 2024-12-29 19:52:54 +08:00
Space Time
8de6980f59 1.1.4 -> 1.1.5 第11次更新 2024-12-29 15:50:45 +08:00
Space Time
b1d41436de 1.1.4 -> 1.1.5 第10次更新 2024-12-29 15:13:28 +08:00
Space Time
1fd5b99e67 1.1.4 -> 1.1.5 第9次更新 2024-12-28 17:30:04 +08:00
Space Time
eecec3bbd7 1.1.4 -> 1.1.5 第8次更新 2024-12-27 22:10:50 +08:00
Space Time
ccf47c85c9 1.1.4 -> 1.1.5 第7次更新 2024-12-26 12:58:04 +08:00
Space Time
cf616b33a8 1.1.4 -> 1.1.5 第6次更新 2024-12-26 12:51:48 +08:00
Space Time
592f871778 1.1.4 -> 1.1.5 第5次更新 2024-12-26 12:46:20 +08:00
Space Time
f625d79667 1.1.4 -> 1.1.5 第4次更新 2024-12-26 12:35:53 +08:00
Space Time
80abfa8116 1.1.4 -> 1.1.5 第3次更新 2024-12-23 22:17:15 +08:00
Space Time
87d97c2f04 1.1.4 -> 1.1.5 第2次更新 2024-12-23 22:06:35 +08:00
Space Time
345c291305 1.1.4 -> 1.1.5 第1次更新 2024-12-23 13:57:39 +08:00
27 changed files with 514 additions and 213 deletions

View File

@ -15,12 +15,13 @@
"AboutVersionButtonContentConv.cs": [ "AboutConv.cs" ], "AboutVersionButtonContentConv.cs": [ "AboutConv.cs" ],
"MainAdminControlVisibilityConv.cs": [ "MainConv.cs" ], "MainAdminControlVisibilityConv.cs": [ "MainConv.cs" ],
"MainMihomoButtonContentConv.cs": [ "MainConv.cs" ], "MainMihomoButtonContentConv.cs": [ "MainConv.cs" ],
"MainMihomoButtonIsEnabledConv.cs": [ "MainConv.cs" ],
"MainMihomoButtonToolTipConv.cs": [ "MainConv.cs" ], "MainMihomoButtonToolTipConv.cs": [ "MainConv.cs" ],
"MainNginxButtonContentConv.cs": [ "MainConv.cs" ], "MainNginxButtonContentConv.cs": [ "MainConv.cs" ],
"MainNginxButtonIsEnabledConv.cs": [ "MainConv.cs" ],
"MainNginxButtonToolTipConv.cs": [ "MainConv.cs" ], "MainNginxButtonToolTipConv.cs": [ "MainConv.cs" ],
"MainNoClickButtonContentConv.cs": [ "MainConv.cs" ], "MainNoClickButtonContentConv.cs": [ "MainConv.cs" ],
"MainNoClickButtonToolTipConv.cs": [ "MainConv.cs" ], "MainNoClickButtonToolTipConv.cs": [ "MainConv.cs" ],
"MainProxyButtonIsEnabledConv.cs": [ "MainConv.cs" ],
"MainProxyColumnWidthConv.cs": [ "MainConv.cs" ], "MainProxyColumnWidthConv.cs": [ "MainConv.cs" ],
"MainSettingsBoxHintConv.cs": [ "MainConv.cs" ], "MainSettingsBoxHintConv.cs": [ "MainConv.cs" ],
"MainSettingsBoxTextConv.cs": [ "MainConv.cs" ], "MainSettingsBoxTextConv.cs": [ "MainConv.cs" ],

View File

@ -10,7 +10,7 @@ internal abstract class AboutConst : AboutMultilangConst
public static string DeveloperButtonUrl => "https://www.spacetimee.xyz"; public static string DeveloperButtonUrl => "https://www.spacetimee.xyz";
public static string VersionButtonVersionContent => Assembly.GetExecutingAssembly().GetName().Version!.ToString()[..^2]; public static string VersionButtonVersionContent => Assembly.GetExecutingAssembly().GetName().Version!.ToString()[..^2];
public static string VersionButtonUrl => "https://spacetime.lanzouu.com/b017hp0lc"; public static string VersionButtonUrl => "https://github.com/SpaceTimee/Sheas-Cealer/releases/latest";
public static string EmailButtonUrl => "Zeus6_6@163.com"; public static string EmailButtonUrl => "Zeus6_6@163.com";
public static string DocumentationButtonUrl => "https://github.com/SpaceTimee/Sheas-Cealer/wiki/Sheas-Cealer-Documentation"; public static string DocumentationButtonUrl => "https://github.com/SpaceTimee/Sheas-Cealer/wiki/Sheas-Cealer-Documentation";

View File

@ -26,6 +26,7 @@ internal abstract partial class MainConst : MainMultilangConst
internal static string HostsConfStartMarker => $"# Cealing Nginx Start{Environment.NewLine}"; internal static string HostsConfStartMarker => $"# Cealing Nginx Start{Environment.NewLine}";
internal static string HostsConfEndMarker => "# Cealing Nginx End"; internal static string HostsConfEndMarker => "# Cealing Nginx End";
internal static string ConginxPath => Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase!, "Cealing-Conginx.exe");
internal static string NginxPath => Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase!, "Cealing-Nginx.exe"); internal static string NginxPath => Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase!, "Cealing-Nginx.exe");
internal static string NginxConfPath => Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase!, "nginx.conf"); internal static string NginxConfPath => Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase!, "nginx.conf");
internal static string NginxLogsPath => Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase!, "logs"); internal static string NginxLogsPath => Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase!, "logs");
@ -36,12 +37,16 @@ internal abstract partial class MainConst : MainMultilangConst
internal static string NginxRootCertSubjectName => "CN=Cealing Cert Root"; internal static string NginxRootCertSubjectName => "CN=Cealing Cert Root";
internal static string NginxChildCertSubjectName => "CN=Cealing Cert Child"; internal static string NginxChildCertSubjectName => "CN=Cealing Cert Child";
internal static string ComihomoPath => Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase!, "Cealing-Comihomo.exe");
internal static string MihomoPath => Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase!, "Cealing-Mihomo.exe"); internal static string MihomoPath => Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase!, "Cealing-Mihomo.exe");
internal static string MihomoConfPath => Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase!, "config.yaml"); internal static string MihomoConfPath => Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase!, "config.yaml");
internal static string[] MihomoNameServers => ["https://doh.apad.pro/dns-query", "https://ns.net.kg/dns-query"]; internal static string[] MihomoNameServers => ["https://ns.net.kg/dns-query", "https://dnschina1.soraharu.com/dns-query", "https://0ms.dev/dns-query"];
internal static string NotifyIconText => "Sheas Cealer"; internal static string NotifyIconText => "Sheas Cealer";
[GeneratedRegex("^Cealing-Host-")]
internal static partial Regex CealHostPrefixRegex();
[GeneratedRegex(@"^(https?:\/\/)?[a-zA-Z0-9](-*[a-zA-Z0-9])*(\.[a-zA-Z0-9](-*[a-zA-Z0-9])*)*(:\d{1,5})?(\/[a-zA-Z0-9.\-_\~\!\$\&\'\(\)\*\+\,\;\=\:\@\%]*)*$")] [GeneratedRegex(@"^(https?:\/\/)?[a-zA-Z0-9](-*[a-zA-Z0-9])*(\.[a-zA-Z0-9](-*[a-zA-Z0-9])*)*(:\d{1,5})?(\/[a-zA-Z0-9.\-_\~\!\$\&\'\(\)\*\+\,\;\=\:\@\%]*)*$")]
internal static partial Regex UpstreamUrlRegex(); internal static partial Regex UpstreamUrlRegex();

View File

@ -150,6 +150,15 @@ namespace Sheas_Cealer.Consts {
} }
} }
/// <summary>
/// 查找类似 You are using hosts-based non-wildcard domain global cealing. Do you want to continue? 的本地化字符串。
/// </summary>
public static string _LaunchHostsNginxPrompt {
get {
return ResourceManager.GetString("_LaunchHostsNginxPrompt", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Mihomo failed to launch 的本地化字符串。 /// 查找类似 Mihomo failed to launch 的本地化字符串。
/// </summary> /// </summary>
@ -276,6 +285,24 @@ namespace Sheas_Cealer.Consts {
} }
} }
/// <summary>
/// 查找类似 GLB. Purging CHA. 的本地化字符串。
/// </summary>
public static string ComihomoButtonIsInitingContent {
get {
return ResourceManager.GetString("ComihomoButtonIsInitingContent", resourceCulture);
}
}
/// <summary>
/// 查找类似 GLB. Cealing INIT. 的本地化字符串。
/// </summary>
public static string ConginxButtonIsInitingContent {
get {
return ResourceManager.GetString("ConginxButtonIsInitingContent", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Edit Hosts Conf 的本地化字符串。 /// 查找类似 Edit Hosts Conf 的本地化字符串。
/// </summary> /// </summary>
@ -411,6 +438,15 @@ namespace Sheas_Cealer.Consts {
} }
} }
/// <summary>
/// 查找类似 GLB. Purging STP. 的本地化字符串。
/// </summary>
public static string MihomoButtonIsStoppingContent {
get {
return ResourceManager.GetString("MihomoButtonIsStoppingContent", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 GLB. Cealing INIT. 的本地化字符串。 /// 查找类似 GLB. Cealing INIT. 的本地化字符串。
/// </summary> /// </summary>

View File

@ -123,6 +123,18 @@
<data name="AboutButtonToolTip" xml:space="preserve"> <data name="AboutButtonToolTip" xml:space="preserve">
<value>Click to open the about window</value> <value>Click to open the about window</value>
</data> </data>
<data name="BrowserButtonContent" xml:space="preserve">
<value>Start Cealing</value>
</data>
<data name="BrowserButtonToolTip" xml:space="preserve">
<value>Click to launch the injected browser</value>
</data>
<data name="ComihomoButtonIsInitingContent" xml:space="preserve">
<value>GLB. Purging CHA.</value>
</data>
<data name="ConginxButtonIsInitingContent" xml:space="preserve">
<value>GLB. Cealing INIT.</value>
</data>
<data name="EditHostsConfButtonContent" xml:space="preserve"> <data name="EditHostsConfButtonContent" xml:space="preserve">
<value>Edit Hosts Conf</value> <value>Edit Hosts Conf</value>
</data> </data>
@ -168,6 +180,9 @@
<data name="MihomoButtonIsStoppedToolTip" xml:space="preserve"> <data name="MihomoButtonIsStoppedToolTip" xml:space="preserve">
<value>Click to launch a local Mihomo</value> <value>Click to launch a local Mihomo</value>
</data> </data>
<data name="MihomoButtonIsStoppingContent" xml:space="preserve">
<value>GLB. Purging STP.</value>
</data>
<data name="NginxButtonIsInitingContent" xml:space="preserve"> <data name="NginxButtonIsInitingContent" xml:space="preserve">
<value>GLB. Cealing INIT.</value> <value>GLB. Cealing INIT.</value>
</data> </data>
@ -234,12 +249,6 @@
<data name="SettingsModeButtonUpstreamUrlContent" xml:space="preserve"> <data name="SettingsModeButtonUpstreamUrlContent" xml:space="preserve">
<value>Upstream URL</value> <value>Upstream URL</value>
</data> </data>
<data name="BrowserButtonContent" xml:space="preserve">
<value>Start Cealing</value>
</data>
<data name="BrowserButtonToolTip" xml:space="preserve">
<value>Click to launch the injected browser</value>
</data>
<data name="UpdateUpstreamHostButtonContent" xml:space="preserve"> <data name="UpdateUpstreamHostButtonContent" xml:space="preserve">
<value>Update Upstream Host</value> <value>Update Upstream Host</value>
</data> </data>
@ -276,6 +285,9 @@
<data name="_KillBrowserProcessPrompt" xml:space="preserve"> <data name="_KillBrowserProcessPrompt" xml:space="preserve">
<value>All processes of the selected browser will be closed before launching. Do you want to continue?</value> <value>All processes of the selected browser will be closed before launching. Do you want to continue?</value>
</data> </data>
<data name="_LaunchHostsNginxPrompt" xml:space="preserve">
<value>You are using hosts-based non-wildcard domain global cealing. Do you want to continue?</value>
</data>
<data name="_LaunchMihomoErrorMsg" xml:space="preserve"> <data name="_LaunchMihomoErrorMsg" xml:space="preserve">
<value>Mihomo failed to launch</value> <value>Mihomo failed to launch</value>
</data> </data>

View File

@ -123,6 +123,18 @@
<data name="AboutButtonToolTip" xml:space="preserve"> <data name="AboutButtonToolTip" xml:space="preserve">
<value>点击打开关于窗口</value> <value>点击打开关于窗口</value>
</data> </data>
<data name="BrowserButtonContent" xml:space="preserve">
<value>启动伪造</value>
</data>
<data name="BrowserButtonToolTip" xml:space="preserve">
<value>点击启动参数注入完成的浏览器</value>
</data>
<data name="ComihomoButtonIsInitingContent" xml:space="preserve">
<value>全局净化调整中</value>
</data>
<data name="ConginxButtonIsInitingContent" xml:space="preserve">
<value>全局伪造启动中</value>
</data>
<data name="EditHostsConfButtonContent" xml:space="preserve"> <data name="EditHostsConfButtonContent" xml:space="preserve">
<value>编辑 Hosts 配置</value> <value>编辑 Hosts 配置</value>
</data> </data>
@ -168,6 +180,9 @@
<data name="MihomoButtonIsStoppedToolTip" xml:space="preserve"> <data name="MihomoButtonIsStoppedToolTip" xml:space="preserve">
<value>点击启动本地 Mihomo</value> <value>点击启动本地 Mihomo</value>
</data> </data>
<data name="MihomoButtonIsStoppingContent" xml:space="preserve">
<value>全局净化停止中</value>
</data>
<data name="NginxButtonIsInitingContent" xml:space="preserve"> <data name="NginxButtonIsInitingContent" xml:space="preserve">
<value>全局伪造启动中</value> <value>全局伪造启动中</value>
</data> </data>
@ -234,12 +249,6 @@
<data name="SettingsModeButtonUpstreamUrlContent" xml:space="preserve"> <data name="SettingsModeButtonUpstreamUrlContent" xml:space="preserve">
<value>上游链接</value> <value>上游链接</value>
</data> </data>
<data name="BrowserButtonContent" xml:space="preserve">
<value>启动伪造</value>
</data>
<data name="BrowserButtonToolTip" xml:space="preserve">
<value>点击启动参数注入完成的浏览器</value>
</data>
<data name="UpdateUpstreamHostButtonContent" xml:space="preserve"> <data name="UpdateUpstreamHostButtonContent" xml:space="preserve">
<value>更新上游规则</value> <value>更新上游规则</value>
</data> </data>
@ -276,6 +285,9 @@
<data name="_KillBrowserProcessPrompt" xml:space="preserve"> <data name="_KillBrowserProcessPrompt" xml:space="preserve">
<value>启动前将关闭所选浏览器的所有进程,是否继续?</value> <value>启动前将关闭所选浏览器的所有进程,是否继续?</value>
</data> </data>
<data name="_LaunchHostsNginxPrompt" xml:space="preserve">
<value>正在使用基于 Hosts 的非泛域名全局伪造,是否继续?</value>
</data>
<data name="_LaunchMihomoErrorMsg" xml:space="preserve"> <data name="_LaunchMihomoErrorMsg" xml:space="preserve">
<value>Mihomo 启动失败</value> <value>Mihomo 启动失败</value>
</data> </data>

View File

@ -4,12 +4,13 @@ internal static class MainConv
{ {
public static MainAdminControlVisibilityConv MainAdminControlVisibilityConv => new(); public static MainAdminControlVisibilityConv MainAdminControlVisibilityConv => new();
public static MainMihomoButtonContentConv MainMihomoButtonContentConv => new(); public static MainMihomoButtonContentConv MainMihomoButtonContentConv => new();
public static MainMihomoButtonIsEnabledConv MainMihomoButtonIsEnabledConv => new();
public static MainMihomoButtonToolTipConv MainMihomoButtonToolTipConv => new(); public static MainMihomoButtonToolTipConv MainMihomoButtonToolTipConv => new();
public static MainNginxButtonContentConv MainNginxButtonContentConv => new(); public static MainNginxButtonContentConv MainNginxButtonContentConv => new();
public static MainNginxButtonToolTipConv MainNginxButtonToolTipConv => new(); public static MainNginxButtonToolTipConv MainNginxButtonToolTipConv => new();
public static MainNoClickButtonContentConv MainNoClickButtonContentConv => new(); public static MainNoClickButtonContentConv MainNoClickButtonContentConv => new();
public static MainNoClickButtonToolTipConv MainNoClickButtonToolTipConv => new(); public static MainNoClickButtonToolTipConv MainNoClickButtonToolTipConv => new();
public static MainProxyButtonIsEnabledConv MainProxyButtonIsEnabledConv => new(); public static MainNginxButtonIsEnabledConv MainNginxButtonIsEnabledConv => new();
public static MainProxyColumnWidthConv MainProxyColumnWidthConv => new(); public static MainProxyColumnWidthConv MainProxyColumnWidthConv => new();
public static MainSettingsBoxHintConv MainSettingsBoxHintConv => new(); public static MainSettingsBoxHintConv MainSettingsBoxHintConv => new();
public static MainSettingsBoxTextConv MainSettingsBoxTextConv => new(); public static MainSettingsBoxTextConv MainSettingsBoxTextConv => new();

View File

@ -10,9 +10,14 @@ internal class MainMihomoButtonContentConv : IMultiValueConverter
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{ {
bool isMihomoRunning = (bool)values[0]; bool isMihomoRunning = (bool)values[0];
bool isMihomoIniting = (bool)values[1]; bool isComihomoIniting = (bool)values[1];
bool isMihomoIniting = (bool)values[2];
bool isCoproxyIniting = (bool)values[3];
bool isCoproxyStopping = (bool)values[4];
return isMihomoIniting ? MainConst.MihomoButtonIsInitingContent : return isCoproxyIniting || isCoproxyStopping ? Binding.DoNothing :
isComihomoIniting ? MainConst.MihomoButtonIsStoppingContent :
isMihomoIniting ? MainConst.MihomoButtonIsInitingContent :
isMihomoRunning ? MainConst.MihomoButtonIsRunningContent : MainConst.MihomoButtonIsStoppedContent; isMihomoRunning ? MainConst.MihomoButtonIsRunningContent : MainConst.MihomoButtonIsStoppedContent;
} }

View File

@ -0,0 +1,21 @@
using System;
using System.Globalization;
using System.Windows.Data;
namespace Sheas_Cealer.Convs;
internal class MainMihomoButtonIsEnabledConv : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
bool isCoMihomoExist = (bool)values[0];
bool isMihomoExist = (bool)values[1];
bool isCoproxyIniting = (bool)values[2];
bool isComihomoIniting = (bool)values[3];
bool isMihomoIniting = (bool)values[4];
return !isCoproxyIniting && !isComihomoIniting && !isMihomoIniting && (isCoMihomoExist || isMihomoExist);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException();
}

View File

@ -9,11 +9,14 @@ internal class MainNginxButtonContentConv : IMultiValueConverter
{ {
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{ {
bool isNginxRunning = (bool)values[0]; bool isConginxRunning = (bool)values[0];
bool isNginxIniting = (bool)values[1]; bool isNginxRunning = (bool)values[1];
bool isCoproxyIniting = (bool)values[2];
bool isNginxIniting = (bool)values[3];
return isNginxIniting ? MainConst.NginxButtonIsInitingContent : return isCoproxyIniting ? MainConst.ConginxButtonIsInitingContent :
isNginxRunning ? MainConst.NginxButtonIsRunningContent : MainConst.NginxButtonIsStoppedContent; isNginxIniting ? MainConst.NginxButtonIsInitingContent :
isConginxRunning || isNginxRunning ? MainConst.NginxButtonIsRunningContent : MainConst.NginxButtonIsStoppedContent;
} }
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException(); public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException();

View File

@ -0,0 +1,22 @@
using System;
using System.Globalization;
using System.Windows.Data;
namespace Sheas_Cealer.Convs;
internal class MainNginxButtonIsEnabledConv : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
bool isConginxExist = (bool)values[0];
bool isNginxExist = (bool)values[1];
bool isCoproxyIniting = (bool)values[2];
bool isNginxIniting = (bool)values[3];
bool isComihomoIniting = (bool)values[4];
bool isMihomoIniting = (bool)values[5];
return !isCoproxyIniting && !isNginxIniting && !isComihomoIniting && !isMihomoIniting && (isConginxExist || isNginxExist);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException();
}

View File

@ -5,14 +5,15 @@ using System.Windows.Data;
namespace Sheas_Cealer.Convs; namespace Sheas_Cealer.Convs;
internal class MainNginxButtonToolTipConv : IValueConverter internal class MainNginxButtonToolTipConv : IMultiValueConverter
{ {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{ {
bool isNginxRunning = (bool)value; bool isConginxRunning = (bool)values[0];
bool isNginxRunning = (bool)values[1];
return isNginxRunning ? MainConst.NginxButtonIsRunningToolTip : MainConst.NginxButtonIsStoppedToolTip; return isConginxRunning || isNginxRunning ? MainConst.NginxButtonIsRunningToolTip : MainConst.NginxButtonIsStoppedToolTip;
} }
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotImplementedException(); public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException();
} }

View File

@ -1,18 +0,0 @@
using System;
using System.Globalization;
using System.Windows.Data;
namespace Sheas_Cealer.Convs;
internal class MainProxyButtonIsEnabledConv : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
bool isProxyExist = (bool)values[0];
bool isProxyIniting = (bool)values[1];
return !isProxyIniting && isProxyExist;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException();
}

View File

@ -74,21 +74,42 @@ internal partial class MainPres : GlobalPres
[ObservableProperty] [ObservableProperty]
private bool isUpstreamHostUtd = true; private bool isUpstreamHostUtd = true;
[ObservableProperty]
private bool isCoproxyIniting = false;
[ObservableProperty]
private bool isCoproxyStopping = false;
[ObservableProperty]
private bool isConginxExist = File.Exists(MainConst.ConginxPath);
[ObservableProperty] [ObservableProperty]
private bool isNginxExist = File.Exists(MainConst.NginxPath); private bool isNginxExist = File.Exists(MainConst.NginxPath);
[ObservableProperty] [ObservableProperty]
private bool isNginxIniting = false; private bool isNginxIniting = false;
[ObservableProperty]
private bool isConginxRunning = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(MainConst.ConginxPath)).Length != 0;
[ObservableProperty] [ObservableProperty]
private bool isNginxRunning = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(MainConst.NginxPath)).Length != 0; private bool isNginxRunning = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(MainConst.NginxPath)).Length != 0;
[ObservableProperty]
private bool isComihomoExist = File.Exists(MainConst.ComihomoPath);
[ObservableProperty] [ObservableProperty]
private bool isMihomoExist = File.Exists(MainConst.MihomoPath); private bool isMihomoExist = File.Exists(MainConst.MihomoPath);
[ObservableProperty]
private bool isComihomoIniting = false;
[ObservableProperty] [ObservableProperty]
private bool isMihomoIniting = false; private bool isMihomoIniting = false;
[ObservableProperty]
private bool isComihomoRunning = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(MainConst.ComihomoPath)).Length != 0;
[ObservableProperty] [ObservableProperty]
private bool isMihomoRunning = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(MainConst.MihomoPath)).Length != 0; private bool isMihomoRunning = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(MainConst.MihomoPath)).Length != 0;

View File

@ -8,14 +8,9 @@ internal class BrowserProc : Proc
{ {
private readonly bool ShutDownAppOnProcessExit; private readonly bool ShutDownAppOnProcessExit;
internal BrowserProc(string browserPath, bool shutDownAppOnProcessExit) : base(browserPath) internal BrowserProc(string browserPath, bool shutDownAppOnProcessExit) : base(browserPath) => ShutDownAppOnProcessExit = shutDownAppOnProcessExit;
{
ShutDownAppOnProcessExit = shutDownAppOnProcessExit;
Process_Exited(null!, null!); protected sealed override void Process_Exited(object? sender, EventArgs e)
}
protected sealed override void Process_Exited(object sender, EventArgs e)
{ {
if (ShutDownAppOnProcessExit) if (ShutDownAppOnProcessExit)
Application.Current.Dispatcher.InvokeShutdown(); Application.Current.Dispatcher.InvokeShutdown();

9
Proces/ComihomoProc.cs Normal file
View File

@ -0,0 +1,9 @@
using Sheas_Cealer.Consts;
using Sheas_Core;
namespace Sheas_Cealer.Proces;
internal class ComihomoProc : Proc
{
internal ComihomoProc() : base(MainConst.ComihomoPath) { }
}

13
Proces/ConginxProc.cs Normal file
View File

@ -0,0 +1,13 @@
using Sheas_Cealer.Consts;
using Sheas_Cealer.Utils;
using Sheas_Core;
using System;
namespace Sheas_Cealer.Proces;
internal class ConginxProc : Proc
{
internal ConginxProc() : base(MainConst.ConginxPath) { }
protected override async void Process_Exited(object? sender, EventArgs e) => await NginxCleaner.Clean();
}

View File

@ -9,5 +9,5 @@ internal class NginxProc : Proc
{ {
internal NginxProc() : base(MainConst.NginxPath) { } internal NginxProc() : base(MainConst.NginxPath) { }
protected override async void Process_Exited(object sender, EventArgs e) => await NginxCleaner.Clean(); protected override async void Process_Exited(object? sender, EventArgs e) => await NginxCleaner.Clean();
} }

View File

@ -6,9 +6,9 @@
[English README](README_EN.md) [English README](README_EN.md)
## 自我介绍 ## 自我介绍
**Sheas Cealer**: 一只基于 **WPF(.Net8)** 的 SNI 伪造工具 **Sheas Cealer**: 一只基于 **WPF(.Net8)**桌面端 SNI 伪造工具
* 适用平台: Windows * 适用平台: Windows (Win10 之前的系统版本请使用 [1.1.0](https://github.com/SpaceTimee/Sheas-Cealer/releases/tag/1.1.0)) (其他平台请参考[相关项目](https://github.com/SpaceTimee/Sheas-Cealer#相关项目))
## 词汇解释 ## 词汇解释
**[Sheas Cealer Dictionary](https://github.com/SpaceTimee/Sheas-Cealer/wiki/Sheas-Cealer-Dictionary)** **[Sheas Cealer Dictionary](https://github.com/SpaceTimee/Sheas-Cealer/wiki/Sheas-Cealer-Dictionary)**
@ -17,24 +17,24 @@
1. 内置伪造规则在 [Cealing Host 存储库](https://github.com/SpaceTimee/Cealing-Host) 持续更新 1. 内置伪造规则在 [Cealing Host 存储库](https://github.com/SpaceTimee/Cealing-Host) 持续更新
2. Sheas Cealer 更新时不会覆盖已有的伪造规则,如需与上游同步,需点击**更新上游规则**按钮,或**手动修改覆盖** 2. Sheas Cealer 更新时不会覆盖已有的伪造规则,如需与上游同步,需点击**更新上游规则**按钮,或**手动修改覆盖**
3. 本项目及所有相关资源仅供**抵御网络非法监听**和**开展网络安全研究**使用,无意绕过任何国家审查设备的审查 3. 本项目及所有相关资源仅供**抵御网络非法监听**和**开展网络安全研究**使用,无意绕过任何国家审查设备的审查
4. 为避免不必要的麻烦,使用前请先阅读**注意事项**和**用户协议** 4. 为避免不必要的麻烦,使用前请先阅读[**用户协议**](https://github.com/SpaceTimee/Sheas-Cealer#用户协议)
5. Sheas Cealer 仍处于**开发阶段**,但每个正式版发布前会尽量确保其**稳定可用** 5. Sheas Cealer 仍处于**开发阶段**,但每个正式版发布前会尽量确保其**稳定可用**
6. Github Release 中会保留目前能够使用的**所有版本**,但强烈推荐使用**最新版**
7. 注意事项第 3 条将从 2024.12.31 起正式严格执行
## 用户协议 ## 用户协议
1. [隐私政策](https://thoughts.teambition.com/share/6264eda98adeb10041b92fda#title=Sheas_Cealer_隐私政策) 1. [隐私政策](https://thoughts.teambition.com/share/6264eda98adeb10041b92fda#title=Sheas_Cealer_隐私政策)
2. [使用协议](https://thoughts.teambition.com/share/6264edd78adeb10041b92fdb#title=Sheas_Cealer_使用协议) 2. [使用协议](https://thoughts.teambition.com/share/6264edd78adeb10041b92fdb#title=Sheas_Cealer_使用协议)
## 下载地址 ## 下载地址
1. Github (首选): [https://github.com/SpaceTimee/Sheas-Cealer/releases](https://github.com/SpaceTimee/Sheas-Cealer/releases) 1. Github: [https://github.com/SpaceTimee/Sheas-Cealer/releases](https://github.com/SpaceTimee/Sheas-Cealer/releases)
2. 蓝奏云 (密码 3wnj) (大陆推荐): [https://spacetime.lanzouu.com/b017hp0lc](https://spacetime.lanzouu.com/b017hp0lc) 2. 群文件 (参与内测): 参考[联系方式](https://github.com/SpaceTimee/Sheas-Cealer#联系方式)
> 出于不可抗力因素Sheas Cealer 暂时无法再提供蓝奏云下载地址,在此依旧感谢蓝奏云一直以来的免费分发服务
## 安装方式 ## 安装方式
1. Setup 安装器 (首选): 下载 Sheas Cealer Setup.exe 并运行 -> 按照提示设置即可安装 1. Setup 安装器 (首选): 下载 Sheas Cealer Setup.exe 并运行 -> 按照提示设置即可安装
2. Zip 压缩包 (免安装): 下载 Sheas Cealer Zip.zip 并解压 -> 完成后即可直接使用 2. Zip 压缩包 (免安装): 下载 Sheas Cealer Zip.zip 并解压 -> 完成后即可直接使用
> Scd 版本: Scd 版本内置 .Net 运行时,可在缺乏 .Net 运行时的环境下运行,但代价是更大的文件体积以及更差跨平台能力,如果没有特殊原因,不建议使用 Scd 版本 > Scd 版本: Scd 版本内置 .Net 运行时,可在缺乏 .Net 运行时的环境下运行,但代价是更大的文件体积以及更差跨平台能力,如果没有特殊原因,不建议使用 Scd 版本
## 食用文档 ## 食用文档
**[Sheas Cealer Documentation](https://github.com/SpaceTimee/Sheas-Cealer/wiki/Sheas-Cealer-Documentation)** **[Sheas Cealer Documentation](https://github.com/SpaceTimee/Sheas-Cealer/wiki/Sheas-Cealer-Documentation)**
@ -53,20 +53,19 @@
**Space Time** **Space Time**
## 联系方式 ## 联系方式
1. **QQ 群 (主群): 716266896338919498** 1. **QQ 群: 1034315671716266896338919498**
2. TG 群 (分群): [PixCealerChat](https://t.me/PixCealerChat) 2. **TG 群: [PixCealerChat](https://t.me/PixCealerChat)**
3. **邮箱: Zeus6_6@163.com** 3. 邮箱: Zeus6_6@163.com
## 相关项目 ## 相关项目
1. [Cealing Host](https://github.com/SpaceTimee/Cealing-Host): 最新的 Sheas Cealer 内置伪造规则 1. [Sheas Cealer Droid](https://github.com/SpaceTimee/Sheas-Cealer-Droid): Sheas Cealer 安卓端
2. [Sheas Dop](https://github.com/SpaceTimee/Sheas-Dop): DNS 抗污染解析工具 (Sheas Cealer 全局净化子项目) 2. [Sheas Cealer Nix](https://github.com/SpaceTimee/Sheas-Cealer/tree/nix): Sheas Cealer 跨平台桌面端
3. [Sheas Nginx](https://github.com/SpaceTimee/Sheas-Nginx): Pixiv Nginx 启动器 (Sheas Cealer 全局伪造 × Pixiv Nginx 合作子项目) 3. [Cealing Host](https://github.com/SpaceTimee/Cealing-Host): 最新的 Sheas Cealer 内置伪造规则
4. [Bot CealingCat](https://github.com/SpaceTimee/Bot-CealingCat): 提供 Sheas Cealer 相关服务的 Telegram Bot 4. [Sheas Dop](https://github.com/SpaceTimee/Sheas-Dop): DNS 抗污染解析工具 (Sheas Cealer 全局净化子项目)
5. [Console HostChecker](https://github.com/SpaceTimee/Console-HostChecker): Cealing Host 自动化检查脚本 5. [Sheas Nginx](https://github.com/SpaceTimee/Sheas-Nginx): Pixiv Nginx 启动器 (Sheas Cealer 全局伪造 × Pixiv Nginx 合作子项目)
6. [Console HostGenerator](https://github.com/SpaceTimee/Console-HostGenerator): Cealing Host 自动化生成脚本 6. [Bot CealingCat](https://github.com/SpaceTimee/Bot-CealingCat): 提供 Sheas Cealer 相关服务的 Telegram Bot
7. [Console HostChecker](https://github.com/SpaceTimee/Console-HostChecker): Cealing Host 自动化检查脚本
## 推广合作 8. [Console HostGenerator](https://github.com/SpaceTimee/Console-HostGenerator): Cealing Host 自动化生成脚本
[产品社区营](https://mp.weixin.qq.com/s?__biz=MzI3MTQ0ODQ3Ng==&mid=2247487284&idx=1&sn=94fcb19438ddba204c4fbe4803edc062&chksm=eb6ebe23f78ca1c3a360e8b46558c14cb8360ad199a19cbc1b4b4b8e2379c98699f2d6eca5da)
## 许可证 ## 许可证
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FSpaceTimee%2FSheas-Cealer.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2FSpaceTimee%2FSheas-Cealer?ref=badge_large) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FSpaceTimee%2FSheas-Cealer.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2FSpaceTimee%2FSheas-Cealer?ref=badge_large)

View File

@ -6,9 +6,9 @@
[中文 README](README.md) [中文 README](README.md)
## About ## About
**Sheas Cealer**: A SNI concealing tool based on **WPF(.Net8)** **Sheas Cealer**: A desktop SNI concealing tool based on **WPF(.Net8)**
* Applicable platform: Windows * Applicable platform: Windows (For system versions before Win10, please use [1.1.0](https://github.com/SpaceTimee/Sheas-Cealer/releases/tag/1.1.0)) (For more platforms, please refer to [Projects](https://github.com/SpaceTimee/Sheas-Cealer#Projects))
## Vocabulary ## Vocabulary
**[Sheas Cealer Dictionary](https://github.com/SpaceTimee/Sheas-Cealer/wiki/Sheas-Cealer-Dictionary)** **[Sheas Cealer Dictionary](https://github.com/SpaceTimee/Sheas-Cealer/wiki/Sheas-Cealer-Dictionary)**
@ -17,10 +17,8 @@
1. The Built-in Cealing Host is continuously updated in the [Cealing Host repository](https://github.com/SpaceTimee/Cealing-Host) 1. The Built-in Cealing Host is continuously updated in the [Cealing Host repository](https://github.com/SpaceTimee/Cealing-Host)
2. When Sheas Cealer is updated, it will not overwrite the existing configs. If you need to synchronize with the upstream, you need to click the **Update Upstream Host** button, or **manually overwrite** 2. When Sheas Cealer is updated, it will not overwrite the existing configs. If you need to synchronize with the upstream, you need to click the **Update Upstream Host** button, or **manually overwrite**
3. This project and all its resources are for the sole purpose of **defending against illegal network monitoring** and **conducting network security research**, and are not intended to bypass the censorship of any country 3. This project and all its resources are for the sole purpose of **defending against illegal network monitoring** and **conducting network security research**, and are not intended to bypass the censorship of any country
4. Please read the **Notes** and **Agreements** before use 4. Please read the [**Agreements**](https://github.com/SpaceTimee/Sheas-Cealer#Agreements) before use
5. Sheas Cealer is still in the **development stage**, but each production version will be **stable and available** before release 5. Sheas Cealer is still in the **development stage**, but each production version will be **stable and available** before release
6. Github Release will retain **all versions** that can be used currently, but it is strongly recommended to use the **latest version**
7. Note 3 will be officially and strictly implemented from 2024.12.31
## Agreements ## Agreements
1. [Privacy Policy](https://thoughts.teambition.com/share/6264eda98adeb10041b92fda#title=Sheas_Cealer_隐私政策) 1. [Privacy Policy](https://thoughts.teambition.com/share/6264eda98adeb10041b92fda#title=Sheas_Cealer_隐私政策)
@ -28,14 +26,16 @@
## Download ## Download
1. Github (preferred): [https://github.com/SpaceTimee/Sheas-Cealer/releases](https://github.com/SpaceTimee/Sheas-Cealer/releases) 1. Github (preferred): [https://github.com/SpaceTimee/Sheas-Cealer/releases](https://github.com/SpaceTimee/Sheas-Cealer/releases)
2. Lanzou (password 3wnj) (recommended in mainland China): [https://spacetime.lanzouu.com/b017hp0lc](https://spacetime.lanzouu.com/b017hp0lc) 2. Group File (participate in internal testing): Please refer to [Contacts](https://github.com/SpaceTimee/Sheas-Cealer#Contacts)
> Scd version: The Scd version has a built-in .Net runtime and can run in an environment without a .Net runtime, but the cost is a larger file size and worse cross-platform capabilities. If there is no special reason, it is not recommended to use the Scd version > Due to force majeure, Sheas Cealer is temporarily unable to provide the download address of Lanzou Cloud. We would like to thank Lanzou Cloud for its free distribution service
## Installation ## Installation
1. Setup Installer (preferred): Download Sheas Cealer Setup.exe and run -> Then follow the prompts to install 1. Setup Installer (preferred): Download Sheas Cealer Setup.exe and run -> Then follow the prompts to install
2. Zip Package (installation-free): Download Sheas Cealer Zip.zip and unzip -> Then you can use it directly 2. Zip Package (installation-free): Download Sheas Cealer Zip.zip and unzip -> Then you can use it directly
> Scd version: The Scd version has a built-in .Net runtime and can run in an environment without a .Net runtime, but the cost is a larger file size and worse cross-platform capabilities. If there is no special reason, it is not recommended to use the Scd version
## Documentation ## Documentation
**[Sheas Cealer Documentation](https://github.com/SpaceTimee/Sheas-Cealer/wiki/Sheas-Cealer-Documentation)** **[Sheas Cealer Documentation](https://github.com/SpaceTimee/Sheas-Cealer/wiki/Sheas-Cealer-Documentation)**
@ -53,17 +53,19 @@ Using the startup parameter feature of the Chromium kernel to conceal SNI. For m
**Space Time** **Space Time**
## Contacts ## Contacts
1. **QQ Group (Main Group): 716266896, 338919498** 1. **QQ Group: 1034315671, 716266896, 338919498**
2. TG Group (Sub Group): [PixCealerChat](https://t.me/PixCealerChat) 2. **TG Group: [PixCealerChat](https://t.me/PixCealerChat)**
3. **Email: Zeus6_6@163.com** 3. Email: Zeus6_6@163.com
## Projects ## Projects
1. [Cealing Host](https://github.com/SpaceTimee/Cealing-Host): The latest Built-in Cealing Host 1. [Sheas Cealer Droid](https://github.com/SpaceTimee/Sheas-Cealer-Droid): Sheas Cealer for Android
2. [Sheas Dop](https://github.com/SpaceTimee/Sheas-Dop): DNS anti-pollution resolution tool (Sheas Cealer Global Cealing subproject) 2. [Sheas Cealer Nix](https://github.com/SpaceTimee/Sheas-Cealer/tree/nix): Sheas Cealer cross-platform for desktop
3. [Sheas Nginx](https://github.com/SpaceTimee/Sheas-Nginx): Pixiv Nginx launcher (Sheas Cealer Global Purging × Pixiv Nginx cooperative subproject) 3. [Cealing Host](https://github.com/SpaceTimee/Cealing-Host): The latest Built-in Cealing Host
4. [Bot CealingCat](https://github.com/SpaceTimee/Bot-CealingCat): Telegram Bot providing Sheas Cealer related services 4. [Sheas Dop](https://github.com/SpaceTimee/Sheas-Dop): DNS anti-pollution resolution tool (Sheas Cealer Global Cealing subproject)
5. [Console HostChecker](https://github.com/SpaceTimee/Console-HostChecker): Cealing Host automated checking script 5. [Sheas Nginx](https://github.com/SpaceTimee/Sheas-Nginx): Pixiv Nginx launcher (Sheas Cealer Global Purging × Pixiv Nginx cooperative subproject)
6. [Console HostGenerator](https://github.com/SpaceTimee/Console-HostGenerator): Cealing Host automated generation script 6. [Bot CealingCat](https://github.com/SpaceTimee/Bot-CealingCat): Telegram Bot providing Sheas Cealer related services
7. [Console HostChecker](https://github.com/SpaceTimee/Console-HostChecker): Cealing Host automated checking script
8. [Console HostGenerator](https://github.com/SpaceTimee/Console-HostGenerator): Cealing Host automated generation script
## License ## License
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FSpaceTimee%2FSheas-Cealer.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2FSpaceTimee%2FSheas-Cealer?ref=badge_large) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FSpaceTimee%2FSheas-Cealer.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2FSpaceTimee%2FSheas-Cealer?ref=badge_large)

View File

@ -8,10 +8,10 @@
<PackageReleaseNotes>Just Ceal It</PackageReleaseNotes> <PackageReleaseNotes>Just Ceal It</PackageReleaseNotes>
<Authors>Space Time</Authors> <Authors>Space Time</Authors>
<Company>Space Time</Company> <Company>Space Time</Company>
<AssemblyVersion>1.1.4</AssemblyVersion> <AssemblyVersion>1.1.5</AssemblyVersion>
<Version>1.1.4</Version> <Version>1.1.5</Version>
<FileVersion>1.1.4</FileVersion> <FileVersion>1.1.5</FileVersion>
<InformationalVersion>1.1.4</InformationalVersion> <InformationalVersion>1.1.5</InformationalVersion>
<PackageTags>Tool;Sheas;Cealer;Sni</PackageTags> <PackageTags>Tool;Sheas;Cealer;Sni</PackageTags>
<ApplicationIcon>Sheas-Cealer-Logo.ico</ApplicationIcon> <ApplicationIcon>Sheas-Cealer-Logo.ico</ApplicationIcon>
<PackageIcon>Sheas Cealer Logo.png</PackageIcon> <PackageIcon>Sheas Cealer Logo.png</PackageIcon>
@ -30,20 +30,13 @@
<UseWindowsForms>True</UseWindowsForms> <UseWindowsForms>True</UseWindowsForms>
<IsPublishable>True</IsPublishable> <IsPublishable>True</IsPublishable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks> <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<ErrorReport>none</ErrorReport> <ErrorReport>none</ErrorReport>
<NoWin32Manifest>true</NoWin32Manifest> <NoWin32Manifest>true</NoWin32Manifest>
<AppDesignerFolder>Props</AppDesignerFolder> <AppDesignerFolder>Props</AppDesignerFolder>
<NeutralLanguage>en</NeutralLanguage> <NeutralLanguage>en</NeutralLanguage>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="bin\**" /> <Compile Remove="bin\**" />
<EmbeddedResource Remove="bin\**" /> <EmbeddedResource Remove="bin\**" />
@ -51,10 +44,6 @@
<Page Remove="bin\**" /> <Page Remove="bin\**" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<AdditionalFiles Remove="app.manifest" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<None Remove=".filenesting.json" /> <None Remove=".filenesting.json" />
<None Remove=".gitattributes" /> <None Remove=".gitattributes" />
@ -73,44 +62,37 @@
<ItemGroup> <ItemGroup>
<Reference Include="Ona-Core"> <Reference Include="Ona-Core">
<HintPath>..\Ona-Core\bin\Release\net8.0-windows10.0.26100.0\Ona-Core.dll</HintPath> <HintPath>..\Ona-Core\bin\Release\net8.0\Ona-Core.dll</HintPath>
</Reference> </Reference>
<Reference Include="Sheas-Core"> <Reference Include="Sheas-Core">
<HintPath>..\Sheas-Core\bin\Release\net8.0-windows10.0.26100.0\Sheas-Core.dll</HintPath> <HintPath>..\Sheas-Core\bin\Release\net8.0\Sheas-Core.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Update="Consts\AboutMultilangConst.Designer.cs"> <Compile Update="Consts\MainMultilangConst.Designer.cs">
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DependentUpon>AboutMultilangConst.resx</DependentUpon> <DependentUpon>MainMultilangConst.resx</DependentUpon>
</Compile> </Compile>
<Compile Update="Consts\SettingsMultilangConst.Designer.cs"> <Compile Update="Consts\SettingsMultilangConst.Designer.cs">
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DependentUpon>SettingsMultilangConst.resx</DependentUpon> <DependentUpon>SettingsMultilangConst.resx</DependentUpon>
</Compile> </Compile>
<Compile Update="Consts\AboutMultilangConst.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>AboutMultilangConst.resx</DependentUpon>
</Compile>
<Compile Update="Props\Settings.Designer.cs"> <Compile Update="Props\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput> <DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon> <DependentUpon>Settings.settings</DependentUpon>
</Compile> </Compile>
<Compile Update="Consts\MainMultilangConst.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>MainMultilangConst.resx</DependentUpon>
</Compile>
<Compile Update="Wins\SettingsWin.xaml.cs">
<SubType>Code</SubType>
</Compile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Update="Consts\AboutMultilangConst.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>AboutMultilangConst.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Update="Consts\MainMultilangConst.resx"> <EmbeddedResource Update="Consts\MainMultilangConst.resx">
<Generator>PublicResXFileCodeGenerator</Generator> <Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>MainMultilangConst.Designer.cs</LastGenOutput> <LastGenOutput>MainMultilangConst.Designer.cs</LastGenOutput>
@ -119,9 +101,10 @@
<Generator>PublicResXFileCodeGenerator</Generator> <Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>SettingsMultilangConst.Designer.cs</LastGenOutput> <LastGenOutput>SettingsMultilangConst.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> <EmbeddedResource Update="Consts\AboutMultilangConst.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<ItemGroup> <LastGenOutput>AboutMultilangConst.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Update="Props\Settings.settings"> <None Update="Props\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator> <Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput> <LastGenOutput>Settings.Designer.cs</LastGenOutput>

11
Utils/DnsFlusher.cs Normal file
View File

@ -0,0 +1,11 @@
using System.Runtime.InteropServices;
namespace Sheas_Cealer.Utils;
internal static partial class DnsFlusher
{
[LibraryImport("dnsapi.dll")]
private static partial void DnsFlushResolverCache();
internal static void FlushDns() => DnsFlushResolverCache();
}

View File

@ -2,44 +2,34 @@
using System; using System;
using System.IO; using System.IO;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Sheas_Cealer.Utils; namespace Sheas_Cealer.Utils;
internal static class NginxCleaner internal static class NginxCleaner
{ {
internal static readonly SemaphoreSlim IsNginxCleaningSemaphore = new(1);
internal static async Task Clean() internal static async Task Clean()
{ {
if (!await IsNginxCleaningSemaphore.WaitAsync(0)) string hostsContent = await File.ReadAllTextAsync(MainConst.HostsConfPath);
return; int hostsConfStartIndex = hostsContent.IndexOf(MainConst.HostsConfStartMarker, StringComparison.Ordinal);
int hostsConfEndIndex = hostsContent.LastIndexOf(MainConst.HostsConfEndMarker, StringComparison.Ordinal);
try if (hostsConfStartIndex != -1 && hostsConfEndIndex != -1)
{ await File.WriteAllTextAsync(MainConst.HostsConfPath, hostsContent.Remove(hostsConfStartIndex, hostsConfEndIndex - hostsConfStartIndex + MainConst.HostsConfEndMarker.Length));
string hostsContent = await File.ReadAllTextAsync(MainConst.HostsConfPath);
int hostsConfStartIndex = hostsContent.IndexOf(MainConst.HostsConfStartMarker, StringComparison.Ordinal);
int hostsConfEndIndex = hostsContent.LastIndexOf(MainConst.HostsConfEndMarker, StringComparison.Ordinal);
if (hostsConfStartIndex != -1 && hostsConfEndIndex != -1) using X509Store certStore = new(StoreName.Root, StoreLocation.LocalMachine, OpenFlags.ReadWrite);
await File.WriteAllTextAsync(MainConst.HostsConfPath, hostsContent.Remove(hostsConfStartIndex, hostsConfEndIndex - hostsConfStartIndex + MainConst.HostsConfEndMarker.Length));
using X509Store certStore = new(StoreName.Root, StoreLocation.CurrentUser, OpenFlags.ReadWrite); foreach (X509Certificate2 storedCert in certStore.Certificates)
if (storedCert.Subject == MainConst.NginxRootCertSubjectName)
while (true)
try
{
certStore.Remove(storedCert);
foreach (X509Certificate2 storedCert in certStore.Certificates) break;
if (storedCert.Subject == MainConst.NginxRootCertSubjectName) }
while (true) catch { }
try
{
certStore.Remove(storedCert);
break; certStore.Close();
}
catch { }
certStore.Close();
}
finally { IsNginxCleaningSemaphore.Release(); }
} }
} }

View File

@ -29,8 +29,7 @@
Content="{x:Static consts:AboutConst.DeveloperButtonContent}" Content="{x:Static consts:AboutConst.DeveloperButtonContent}"
ToolTip="{x:Static consts:AboutConst.DeveloperButtonUrl}" ToolTip="{x:Static consts:AboutConst.DeveloperButtonUrl}"
Click="AboutButton_Click" /> Click="AboutButton_Click" />
<Button x:Name="VersionButton" <Button Grid.Row="1" Grid.Column="0" Margin="5" d:Content="# # #: #.#.#"
Grid.Row="1" Grid.Column="0" Margin="5" d:Content="# # #: #.#.#"
d:Foreground="{Binding Source={x:Static consts:AboutConst.AccentBlueColor}, Converter={x:Static convs:AboutConv.AboutAccentButtonForegroundConv}}" d:Foreground="{Binding Source={x:Static consts:AboutConst.AccentBlueColor}, Converter={x:Static convs:AboutConv.AboutAccentButtonForegroundConv}}"
Foreground="{Binding AccentForegroundColor, Converter={x:Static convs:AboutConv.AboutAccentButtonForegroundConv}}" Foreground="{Binding AccentForegroundColor, Converter={x:Static convs:AboutConv.AboutAccentButtonForegroundConv}}"
ToolTip="{x:Static consts:AboutConst.VersionButtonUrl}" ToolTip="{x:Static consts:AboutConst.VersionButtonUrl}"

View File

@ -53,9 +53,6 @@ public partial class AboutWin : Window
{ {
Button senderButton = (Button)sender; Button senderButton = (Button)sender;
if (senderButton == VersionButton)
MessageBox.Show($"{AboutConst._ReleasePagePasswordLabel} 3wnj");
ProcessStartInfo processStartInfo = new(senderButton == EmailButton ? "mailto:" : string.Empty + senderButton.ToolTip) { UseShellExecute = true }; ProcessStartInfo processStartInfo = new(senderButton == EmailButton ? "mailto:" : string.Empty + senderButton.ToolTip) { UseShellExecute = true };
try { Process.Start(processStartInfo); } try { Process.Start(processStartInfo); }

View File

@ -77,20 +77,31 @@
<Button x:Name="NginxButton" <Button x:Name="NginxButton"
Grid.Column="1" Margin="5" d:Content="# # # #" Grid.Column="1" Margin="5" d:Content="# # # #"
Visibility="{Binding Source={x:Static consts:MainConst.IsAdmin}, Converter={x:Static convs:MainConv.MainAdminControlVisibilityConv}}" Visibility="{Binding Source={x:Static consts:MainConst.IsAdmin}, Converter={x:Static convs:MainConv.MainAdminControlVisibilityConv}}"
ToolTip="{Binding IsNginxRunning, Converter={x:Static convs:MainConv.MainNginxButtonToolTipConv}}"
Click="LaunchButton_Click" PreviewMouseDown="LaunchButton_PreviewMouseDown"> Click="LaunchButton_Click" PreviewMouseDown="LaunchButton_PreviewMouseDown">
<Button.IsEnabled> <Button.IsEnabled>
<MultiBinding Converter="{x:Static convs:MainConv.MainProxyButtonIsEnabledConv}"> <MultiBinding Converter="{x:Static convs:MainConv.MainNginxButtonIsEnabledConv}">
<Binding Path="IsConginxExist" />
<Binding Path="IsNginxExist" /> <Binding Path="IsNginxExist" />
<Binding Path="IsCoproxyIniting" />
<Binding Path="IsNginxIniting" /> <Binding Path="IsNginxIniting" />
<Binding Path="IsComihomoIniting" />
<Binding Path="IsMihomoIniting" />
</MultiBinding> </MultiBinding>
</Button.IsEnabled> </Button.IsEnabled>
<Button.Content> <Button.Content>
<MultiBinding Converter="{x:Static convs:MainConv.MainNginxButtonContentConv}"> <MultiBinding Converter="{x:Static convs:MainConv.MainNginxButtonContentConv}">
<Binding Path="IsConginxRunning" />
<Binding Path="IsNginxRunning" /> <Binding Path="IsNginxRunning" />
<Binding Path="IsCoproxyIniting" />
<Binding Path="IsNginxIniting" /> <Binding Path="IsNginxIniting" />
</MultiBinding> </MultiBinding>
</Button.Content> </Button.Content>
<Button.ToolTip>
<MultiBinding Converter="{x:Static convs:MainConv.MainNginxButtonToolTipConv}">
<Binding Path="IsConginxRunning" />
<Binding Path="IsNginxRunning" />
</MultiBinding>
</Button.ToolTip>
</Button> </Button>
<Button x:Name="MihomoButton" <Button x:Name="MihomoButton"
Grid.Column="2" Margin="5" d:Content="# # # #" Grid.Column="2" Margin="5" d:Content="# # # #"
@ -98,15 +109,21 @@
ToolTip="{Binding IsMihomoRunning, Converter={x:Static convs:MainConv.MainMihomoButtonToolTipConv}}" ToolTip="{Binding IsMihomoRunning, Converter={x:Static convs:MainConv.MainMihomoButtonToolTipConv}}"
Click="LaunchButton_Click" PreviewMouseDown="LaunchButton_PreviewMouseDown"> Click="LaunchButton_Click" PreviewMouseDown="LaunchButton_PreviewMouseDown">
<Button.IsEnabled> <Button.IsEnabled>
<MultiBinding Converter="{x:Static convs:MainConv.MainProxyButtonIsEnabledConv}"> <MultiBinding Converter="{x:Static convs:MainConv.MainMihomoButtonIsEnabledConv}">
<Binding Path="IsComihomoExist" />
<Binding Path="IsMihomoExist" /> <Binding Path="IsMihomoExist" />
<Binding Path="IsCoproxyIniting" />
<Binding Path="IsComihomoIniting" />
<Binding Path="IsMihomoIniting" /> <Binding Path="IsMihomoIniting" />
</MultiBinding> </MultiBinding>
</Button.IsEnabled> </Button.IsEnabled>
<Button.Content> <Button.Content>
<MultiBinding Converter="{x:Static convs:MainConv.MainMihomoButtonContentConv}"> <MultiBinding Converter="{x:Static convs:MainConv.MainMihomoButtonContentConv}">
<Binding Path="IsMihomoRunning" /> <Binding Path="IsMihomoRunning" />
<Binding Path="IsComihomoIniting" />
<Binding Path="IsMihomoIniting" /> <Binding Path="IsMihomoIniting" />
<Binding Path="IsCoproxyIniting" />
<Binding Path="IsCoproxyStopping" />
</MultiBinding> </MultiBinding>
</Button.Content> </Button.Content>
</Button> </Button>
@ -135,9 +152,13 @@
ToolTip="{x:Static consts:MainConst.EditNginxConfButtonToolTip}" ToolTip="{x:Static consts:MainConst.EditNginxConfButtonToolTip}"
Click="EditConfButton_Click"> Click="EditConfButton_Click">
<Button.IsEnabled> <Button.IsEnabled>
<MultiBinding Converter="{x:Static convs:MainConv.MainProxyButtonIsEnabledConv}"> <MultiBinding Converter="{x:Static convs:MainConv.MainNginxButtonIsEnabledConv}">
<Binding Path="IsConginxExist" />
<Binding Path="IsNginxExist" /> <Binding Path="IsNginxExist" />
<Binding Path="IsCoproxyIniting" />
<Binding Path="IsNginxIniting" /> <Binding Path="IsNginxIniting" />
<Binding Path="IsComihomoIniting" />
<Binding Path="IsMihomoIniting" />
</MultiBinding> </MultiBinding>
</Button.IsEnabled> </Button.IsEnabled>
</Button> </Button>
@ -147,8 +168,11 @@
ToolTip="{x:Static consts:MainConst.EditMihomoConfButtonToolTip}" ToolTip="{x:Static consts:MainConst.EditMihomoConfButtonToolTip}"
Click="EditConfButton_Click"> Click="EditConfButton_Click">
<Button.IsEnabled> <Button.IsEnabled>
<MultiBinding Converter="{x:Static convs:MainConv.MainProxyButtonIsEnabledConv}"> <MultiBinding Converter="{x:Static convs:MainConv.MainMihomoButtonIsEnabledConv}">
<Binding Path="IsComihomoExist" />
<Binding Path="IsMihomoExist" /> <Binding Path="IsMihomoExist" />
<Binding Path="IsCoproxyIniting" />
<Binding Path="IsComihomoIniting" />
<Binding Path="IsMihomoIniting" /> <Binding Path="IsMihomoIniting" />
</MultiBinding> </MultiBinding>
</Button.IsEnabled> </Button.IsEnabled>

View File

@ -48,6 +48,8 @@ public partial class MainWin : Window
private string CealArgs = string.Empty; private string CealArgs = string.Empty;
private NginxConfig? NginxConfs; private NginxConfig? NginxConfs;
private string? ExtraNginxConfs; private string? ExtraNginxConfs;
private string? ComihomoConfs;
private string? HostsComihomoConfs;
private string? MihomoConfs; private string? MihomoConfs;
private string? ExtraMihomoConfs; private string? ExtraMihomoConfs;
@ -83,13 +85,11 @@ public partial class MainWin : Window
foreach (string cealHostPath in Directory.GetFiles(CealHostWatcher.Path, CealHostWatcher.Filter)) foreach (string cealHostPath in Directory.GetFiles(CealHostWatcher.Path, CealHostWatcher.Filter))
CealHostWatcher_Changed(null!, new(new(), Path.GetDirectoryName(cealHostPath)!, Path.GetFileName(cealHostPath))); CealHostWatcher_Changed(null!, new(new(), Path.GetDirectoryName(cealHostPath)!, Path.GetFileName(cealHostPath)));
MihomoConfWatcher_Changed(null!, null!); if (MainConst.IsAdmin && !MainPres.IsConginxRunning && !MainPres.IsNginxRunning)
if (!MainPres.IsNginxRunning)
await NginxCleaner.Clean(); await NginxCleaner.Clean();
if (Array.Exists(Environment.GetCommandLineArgs(), arg => arg.Equals("-s", StringComparison.OrdinalIgnoreCase))) if (Array.Exists(Environment.GetCommandLineArgs(), arg => arg.Equals("-s", StringComparison.OrdinalIgnoreCase)))
LaunchButton_Click(null, null!); LaunchButton_Click(null, (RoutedEventArgs)RoutedEventArgs.Empty);
UpdateUpstreamHostButton_Click(null, null!); UpdateUpstreamHostButton_Click(null, null!);
}); });
@ -167,11 +167,11 @@ public partial class MainWin : Window
Button? senderButton = sender as Button; Button? senderButton = sender as Button;
if (senderButton == NginxButton) if (senderButton == NginxButton)
NginxButtonHoldTimer_Tick(null, null!); NginxButtonHoldTimer_Tick(null, EventArgs.Empty);
else if (senderButton == MihomoButton) else if (senderButton == MihomoButton)
MihomoButtonHoldTimer_Tick(null, null!); MihomoButtonHoldTimer_Tick(null, EventArgs.Empty);
else else
BrowserButtonHoldTimer_Tick(sender == null, null!); BrowserButtonHoldTimer_Tick(sender == null, EventArgs.Empty);
} }
private void LaunchButton_PreviewMouseDown(object sender, MouseButtonEventArgs e) private void LaunchButton_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{ {
@ -185,7 +185,7 @@ public partial class MainWin : Window
{ {
HoldButtonTimer?.Stop(); HoldButtonTimer?.Stop();
if ((CealHostRulesDict.ContainsValue(null!) && MessageBox.Show(MainConst._CealHostErrorPrompt, string.Empty, MessageBoxButton.YesNo) != MessageBoxResult.Yes) || if ((CealHostRulesDict.ContainsValue(null) && MessageBox.Show(MainConst._CealHostErrorPrompt, string.Empty, MessageBoxButton.YesNo) != MessageBoxResult.Yes) ||
(sender is not true && MessageBox.Show(MainConst._KillBrowserProcessPrompt, string.Empty, MessageBoxButton.YesNo) != MessageBoxResult.Yes)) (sender is not true && MessageBox.Show(MainConst._KillBrowserProcessPrompt, string.Empty, MessageBoxButton.YesNo) != MessageBoxResult.Yes))
return; return;
@ -197,23 +197,22 @@ public partial class MainWin : Window
await Task.Run(() => await Task.Run(() =>
{ {
new BrowserProc(MainPres.BrowserPath, sender is bool).Run(Path.GetDirectoryName(MainPres.BrowserPath), $"{CealArgs} {MainPres.ExtraArgs.Trim()}"); new BrowserProc(MainPres.BrowserPath, sender is bool).Run(Path.GetDirectoryName(MainPres.BrowserPath)!, $"{CealArgs} {MainPres.ExtraArgs.Trim()}");
}); });
} }
private async void NginxButtonHoldTimer_Tick(object? sender, EventArgs e) private async void NginxButtonHoldTimer_Tick(object? sender, EventArgs e)
{ {
HoldButtonTimer?.Stop(); HoldButtonTimer?.Stop();
if (!MainPres.IsNginxRunning) if (!MainPres.IsConginxRunning && !MainPres.IsNginxRunning)
{ {
if (NginxCleaner.IsNginxCleaningSemaphore.CurrentCount == 0 || !await IsNginxLaunchingSemaphore.WaitAsync(0))
return;
try try
{ {
if ((CealHostRulesDict.ContainsValue(null!) && MessageBox.Show(MainConst._CealHostErrorPrompt, string.Empty, MessageBoxButton.YesNo) != MessageBoxResult.Yes) || if ((!MainPres.IsConginxExist && !MainPres.IsNginxExist) ||
(CealHostRulesDict.ContainsValue(null!) && MessageBox.Show(MainConst._CealHostErrorPrompt, string.Empty, MessageBoxButton.YesNo) != MessageBoxResult.Yes) ||
(NginxHttpsPort != 443 && MessageBox.Show(string.Format(MainConst._NginxHttpsPortOccupiedPrompt, NginxHttpsPort), string.Empty, MessageBoxButton.YesNo) != MessageBoxResult.Yes) || (NginxHttpsPort != 443 && MessageBox.Show(string.Format(MainConst._NginxHttpsPortOccupiedPrompt, NginxHttpsPort), string.Empty, MessageBoxButton.YesNo) != MessageBoxResult.Yes) ||
(NginxHttpPort != 80 && MessageBox.Show(string.Format(MainConst._NginxHttpPortOccupiedPrompt, NginxHttpPort), string.Empty, MessageBoxButton.YesNo) != MessageBoxResult.Yes) || (NginxHttpPort != 80 && MessageBox.Show(string.Format(MainConst._NginxHttpPortOccupiedPrompt, NginxHttpPort), string.Empty, MessageBoxButton.YesNo) != MessageBoxResult.Yes) ||
(sender != null && MessageBox.Show(MainConst._LaunchHostsNginxPrompt, string.Empty, MessageBoxButton.YesNo) != MessageBoxResult.Yes) ||
(MessageBox.Show(MainConst._LaunchProxyPrompt, string.Empty, MessageBoxButton.YesNo) != MessageBoxResult.Yes) || (MessageBox.Show(MainConst._LaunchProxyPrompt, string.Empty, MessageBoxButton.YesNo) != MessageBoxResult.Yes) ||
(MainPres.IsFlashing && MessageBox.Show(MainConst._LaunchNginxFlashingPrompt, string.Empty, MessageBoxButton.YesNo) != MessageBoxResult.Yes)) (MainPres.IsFlashing && MessageBox.Show(MainConst._LaunchNginxFlashingPrompt, string.Empty, MessageBoxButton.YesNo) != MessageBoxResult.Yes))
return; return;
@ -225,6 +224,9 @@ public partial class MainWin : Window
if (!Directory.Exists(MainConst.NginxTempPath)) if (!Directory.Exists(MainConst.NginxTempPath))
Directory.CreateDirectory(MainConst.NginxTempPath); Directory.CreateDirectory(MainConst.NginxTempPath);
if (sender == null)
File.Move(MainConst.NginxPath, MainConst.ConginxPath);
RSA certKey = RSA.Create(2048); RSA certKey = RSA.Create(2048);
#region Root Cert #region Root Cert
@ -233,7 +235,7 @@ public partial class MainWin : Window
rootCertRequest.CertificateExtensions.Add(new X509BasicConstraintsExtension(true, false, 0, false)); rootCertRequest.CertificateExtensions.Add(new X509BasicConstraintsExtension(true, false, 0, false));
using X509Certificate2 rootCert = rootCertRequest.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddYears(100)); using X509Certificate2 rootCert = rootCertRequest.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddYears(100));
using X509Store certStore = new(StoreName.Root, StoreLocation.CurrentUser, OpenFlags.ReadWrite); using X509Store certStore = new(StoreName.Root, StoreLocation.LocalMachine, OpenFlags.ReadWrite);
certStore.Add(rootCert); certStore.Add(rootCert);
certStore.Close(); certStore.Close();
@ -256,14 +258,18 @@ public partial class MainWin : Window
if (cealHostIncludeDomain.TrimStart('$').StartsWith('*')) if (cealHostIncludeDomain.TrimStart('$').StartsWith('*'))
{ {
childCertSanBuilder.AddDnsName($"*.{cealHostIncludeDomainWithoutWildcard}"); childCertSanBuilder.AddDnsName($"*.{cealHostIncludeDomainWithoutWildcard}");
hostsConfAppendContent += $"127.0.0.1 www.{cealHostIncludeDomainWithoutWildcard}{Environment.NewLine}";
if (sender != null)
hostsConfAppendContent += $"127.0.0.1 www.{cealHostIncludeDomainWithoutWildcard}{Environment.NewLine}";
if (cealHostIncludeDomain.TrimStart('$').StartsWith("*.")) if (cealHostIncludeDomain.TrimStart('$').StartsWith("*."))
continue; continue;
} }
childCertSanBuilder.AddDnsName(cealHostIncludeDomainWithoutWildcard); childCertSanBuilder.AddDnsName(cealHostIncludeDomainWithoutWildcard);
hostsConfAppendContent += $"127.0.0.1 {cealHostIncludeDomainWithoutWildcard}{Environment.NewLine}";
if (sender != null)
hostsConfAppendContent += $"127.0.0.1 {cealHostIncludeDomainWithoutWildcard}{Environment.NewLine}";
} }
childCertRequest.CertificateExtensions.Add(childCertSanBuilder.Build()); childCertRequest.CertificateExtensions.Add(childCertSanBuilder.Build());
@ -273,21 +279,31 @@ public partial class MainWin : Window
await File.WriteAllTextAsync(MainConst.NginxCertPath, childCert.ExportCertificatePem()); await File.WriteAllTextAsync(MainConst.NginxCertPath, childCert.ExportCertificatePem());
await File.WriteAllTextAsync(MainConst.NginxKeyPath, certKey.ExportPkcs8PrivateKeyPem()); await File.WriteAllTextAsync(MainConst.NginxKeyPath, certKey.ExportPkcs8PrivateKeyPem());
hostsConfAppendContent += MainConst.HostsConfEndMarker; if (sender != null)
{
hostsConfAppendContent += MainConst.HostsConfEndMarker;
File.SetAttributes(MainConst.HostsConfPath, File.GetAttributes(MainConst.HostsConfPath) & ~FileAttributes.ReadOnly); File.SetAttributes(MainConst.HostsConfPath, File.GetAttributes(MainConst.HostsConfPath) & ~FileAttributes.ReadOnly);
await File.AppendAllTextAsync(MainConst.HostsConfPath, hostsConfAppendContent); await File.AppendAllTextAsync(MainConst.HostsConfPath, hostsConfAppendContent);
}
#endregion Child Cert & Hosts #endregion Child Cert & Hosts
try try
{ {
MainPres.IsNginxIniting = true; if (sender == null)
MainPres.IsCoproxyIniting = true;
else
MainPres.IsNginxIniting = true;
NginxConfWatcher.EnableRaisingEvents = false; NginxConfWatcher.EnableRaisingEvents = false;
NginxConfs!.Save(MainConst.NginxConfPath); NginxConfs!.Save(MainConst.NginxConfPath);
await Task.Run(() => await Task.Run(() =>
{ {
new NginxProc().Run(Path.GetDirectoryName(MainConst.NginxPath), @$"-c ""{Path.GetRelativePath(Path.GetDirectoryName(MainConst.NginxPath)!, MainConst.NginxConfPath)}"""); if (sender == null)
new ConginxProc().Run(Path.GetDirectoryName(MainConst.ConginxPath)!, @$"-c ""{Path.GetRelativePath(Path.GetDirectoryName(MainConst.ConginxPath)!, MainConst.NginxConfPath)}""");
else
new NginxProc().Run(Path.GetDirectoryName(MainConst.NginxPath)!, @$"-c ""{Path.GetRelativePath(Path.GetDirectoryName(MainConst.NginxPath)!, MainConst.NginxConfPath)}""");
}); });
while (true) while (true)
@ -304,7 +320,7 @@ public partial class MainWin : Window
break; break;
} }
if (MainPres.IsNginxRunning) if (sender == null ? MainPres.IsConginxRunning : MainPres.IsNginxRunning)
continue; continue;
if (MessageBox.Show(MainConst._LaunchNginxErrorPrompt, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes) if (MessageBox.Show(MainConst._LaunchNginxErrorPrompt, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes)
@ -312,54 +328,107 @@ public partial class MainWin : Window
break; break;
} }
if (sender == null)
MihomoButtonHoldTimer_Tick(null, EventArgs.Empty);
DnsFlusher.FlushDns();
} }
finally finally
{ {
await File.WriteAllTextAsync(MainConst.NginxConfPath, ExtraNginxConfs); await File.WriteAllTextAsync(MainConst.NginxConfPath, ExtraNginxConfs);
NginxConfWatcher.EnableRaisingEvents = true; NginxConfWatcher.EnableRaisingEvents = true;
MainPres.IsNginxIniting = false;
if (sender != null)
MainPres.IsNginxIniting = false;
} }
} }
finally { IsNginxLaunchingSemaphore.Release(); } finally { IsNginxLaunchingSemaphore.Release(); }
} }
else else
foreach (Process nginxProcess in Process.GetProcessesByName(Path.GetFileNameWithoutExtension(MainConst.NginxPath))) {
bool isConginxRunning = MainPres.IsConginxRunning;
if (isConginxRunning)
MainPres.IsCoproxyStopping = true;
foreach (Process nginxProcess in Process.GetProcessesByName(Path.GetFileNameWithoutExtension(isConginxRunning ? MainConst.ConginxPath : MainConst.NginxPath)))
{ {
nginxProcess.Exited += async (_, _) => nginxProcess.Exited += async (_, _) =>
{ {
await NginxCleaner.Clean(); await NginxCleaner.Clean();
NginxHttpPort = 80;
NginxHttpsPort = 443;
NginxConfWatcher_Changed(null!, null!); NginxConfWatcher_Changed(null!, null!);
}; };
nginxProcess.Kill(); nginxProcess.Kill();
} }
if (isConginxRunning)
{
MainPres.IsConginxRunning = false;
File.Move(MainConst.ConginxPath, MainConst.NginxPath);
MihomoButtonHoldTimer_Tick(null, EventArgs.Empty);
}
else
MainPres.IsNginxRunning = false;
}
} }
private async void MihomoButtonHoldTimer_Tick(object? sender, EventArgs e) private async void MihomoButtonHoldTimer_Tick(object? sender, EventArgs e)
{ {
HoldButtonTimer?.Stop(); HoldButtonTimer?.Stop();
if (!MainPres.IsMihomoRunning) if (!MainPres.IsComihomoRunning && !MainPres.IsMihomoRunning)
{ {
if (!MainPres.IsComihomoExist && !MainPres.IsMihomoExist)
return;
if (string.IsNullOrWhiteSpace(MihomoConfs)) if (string.IsNullOrWhiteSpace(MihomoConfs))
throw new(MainConst._MihomoConfErrorMsg); throw new(MainConst._MihomoConfErrorMsg);
if (MessageBox.Show(MainConst._LaunchProxyPrompt, string.Empty, MessageBoxButton.YesNo) != MessageBoxResult.Yes) if (!MainPres.IsConginxRunning && !MainPres.IsCoproxyStopping && MessageBox.Show(MainConst._LaunchProxyPrompt, string.Empty, MessageBoxButton.YesNo) != MessageBoxResult.Yes)
return; return;
if (!File.Exists(MainConst.MihomoConfPath)) if (!File.Exists(MainConst.MihomoConfPath))
await File.Create(MainConst.MihomoConfPath).DisposeAsync(); await File.Create(MainConst.MihomoConfPath).DisposeAsync();
if (MainPres.IsConginxRunning)
if (MainPres.IsMihomoExist)
{
File.Move(MainConst.MihomoPath, MainConst.ComihomoPath);
MainPres.IsComihomoExist = true;
MainPres.IsMihomoExist = false;
}
else if (MainPres.IsComihomoExist)
{
File.Move(MainConst.ComihomoPath, MainConst.MihomoPath);
MainPres.IsComihomoExist = false;
MainPres.IsMihomoExist = true;
}
try try
{ {
MainPres.IsMihomoIniting = true; if (MainPres.IsComihomoExist)
MainPres.IsComihomoIniting = true;
else
MainPres.IsMihomoIniting = true;
MihomoConfWatcher.EnableRaisingEvents = false; MihomoConfWatcher.EnableRaisingEvents = false;
await File.WriteAllTextAsync(MainConst.MihomoConfPath, MihomoConfs); await File.WriteAllTextAsync(MainConst.MihomoConfPath, !MainPres.IsConginxRunning ? MihomoConfs :
MainPres.IsComihomoExist ? HostsComihomoConfs : ComihomoConfs);
await Task.Run(() => await Task.Run(() =>
{ {
new MihomoProc().Run(Path.GetDirectoryName(MainConst.MihomoPath), @$"-d ""{Path.GetDirectoryName(MainConst.MihomoConfPath)}"""); if (MainPres.IsComihomoExist)
{
new ComihomoProc().Run(Path.GetDirectoryName(MainConst.ComihomoPath)!, @$"-d ""{Path.GetDirectoryName(MainConst.MihomoConfPath)}""");
MainPres.IsComihomoRunning = true;
}
else
{
new MihomoProc().Run(Path.GetDirectoryName(MainConst.MihomoPath)!, @$"-d ""{Path.GetDirectoryName(MainConst.MihomoConfPath)}""");
MainPres.IsMihomoRunning = true;
}
}); });
while (true) while (true)
@ -376,7 +445,7 @@ public partial class MainWin : Window
break; break;
} }
if (MainPres.IsMihomoRunning) if (MainPres.IsComihomoExist ? MainPres.IsComihomoRunning : MainPres.IsMihomoRunning)
continue; continue;
MessageBox.Show(MainConst._LaunchMihomoErrorMsg); MessageBox.Show(MainConst._LaunchMihomoErrorMsg);
@ -388,20 +457,59 @@ public partial class MainWin : Window
{ {
await File.WriteAllTextAsync(MainConst.MihomoConfPath, ExtraMihomoConfs); await File.WriteAllTextAsync(MainConst.MihomoConfPath, ExtraMihomoConfs);
MihomoConfWatcher.EnableRaisingEvents = true; MihomoConfWatcher.EnableRaisingEvents = true;
MainPres.IsMihomoIniting = false;
if (MainPres.IsCoproxyIniting)
MainPres.IsCoproxyIniting = false;
else if (MainPres.IsCoproxyStopping)
MainPres.IsCoproxyStopping = false;
if (MainPres.IsComihomoExist)
MainPres.IsComihomoIniting = false;
else
MainPres.IsMihomoIniting = false;
} }
} }
else else
foreach (Process mihomoProcess in Process.GetProcessesByName(Path.GetFileNameWithoutExtension(MainConst.MihomoPath))) {
bool isComihomoRunning = MainPres.IsComihomoRunning;
foreach (Process mihomoProcess in Process.GetProcessesByName(Path.GetFileNameWithoutExtension(isComihomoRunning ? MainConst.ComihomoPath : MainConst.MihomoPath)))
{ {
mihomoProcess.Exited += (_, _) => mihomoProcess.Exited += (_, _) => MihomoConfWatcher_Changed(null!, null!);
{
MihomoMixedPort = 7880;
MihomoConfWatcher_Changed(null!, null!);
};
mihomoProcess.Kill(); mihomoProcess.Kill();
} }
if (isComihomoRunning)
MainPres.IsComihomoRunning = false;
else
MainPres.IsMihomoRunning = false;
if (MainPres.IsConginxRunning)
{
if (MainPres.IsCoproxyIniting)
{
File.Move(MainConst.MihomoPath, MainConst.ComihomoPath);
MainPres.IsComihomoExist = true;
MainPres.IsMihomoExist = false;
}
MihomoButtonHoldTimer_Tick(null, EventArgs.Empty);
return;
}
if (MainPres.IsComihomoExist)
{
File.Move(MainConst.ComihomoPath, MainConst.MihomoPath);
MainPres.IsComihomoExist = false;
MainPres.IsMihomoExist = true;
MainPres.IsCoproxyStopping = false;
}
else if (MainPres.IsCoproxyStopping)
MihomoButtonHoldTimer_Tick(null, EventArgs.Empty);
}
} }
private async void EditHostButton_Click(object sender, RoutedEventArgs e) private async void EditHostButton_Click(object sender, RoutedEventArgs e)
@ -568,14 +676,18 @@ public partial class MainWin : Window
private void ProxyTimer_Tick(object? sender, EventArgs e) private void ProxyTimer_Tick(object? sender, EventArgs e)
{ {
MainPres.IsConginxExist = File.Exists(Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase!, Path.GetFileName(MainConst.ConginxPath)));
MainPres.IsNginxExist = File.Exists(Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase!, Path.GetFileName(MainConst.NginxPath))); MainPres.IsNginxExist = File.Exists(Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase!, Path.GetFileName(MainConst.NginxPath)));
MainPres.IsConginxRunning = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(MainConst.ConginxPath)).Length != 0;
MainPres.IsNginxRunning = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(MainConst.NginxPath)).Length != 0; MainPres.IsNginxRunning = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(MainConst.NginxPath)).Length != 0;
MainPres.IsComihomoExist = File.Exists(Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase!, Path.GetFileName(MainConst.ComihomoPath)));
MainPres.IsMihomoExist = File.Exists(Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase!, Path.GetFileName(MainConst.MihomoPath))); MainPres.IsMihomoExist = File.Exists(Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase!, Path.GetFileName(MainConst.MihomoPath)));
MainPres.IsComihomoRunning = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(MainConst.ComihomoPath)).Length != 0;
MainPres.IsMihomoRunning = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(MainConst.MihomoPath)).Length != 0; MainPres.IsMihomoRunning = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(MainConst.MihomoPath)).Length != 0;
} }
private async void CealHostWatcher_Changed(object sender, FileSystemEventArgs e) private async void CealHostWatcher_Changed(object sender, FileSystemEventArgs e)
{ {
string cealHostName = e.Name!.TrimStart("Cealing-Host-".ToCharArray()).TrimEnd(".json".ToCharArray()); string cealHostName = MainConst.CealHostPrefixRegex().Replace(Path.GetFileNameWithoutExtension(e.Name!), string.Empty);
try try
{ {
@ -639,11 +751,12 @@ public partial class MainWin : Window
CealArgs = @$"--host-rules=""{hostRules.TrimEnd(',')}"" --host-resolver-rules=""{hostResolverRules.TrimEnd(',')}"" --test-type --ignore-certificate-errors"; CealArgs = @$"--host-rules=""{hostRules.TrimEnd(',')}"" --host-resolver-rules=""{hostResolverRules.TrimEnd(',')}"" --test-type --ignore-certificate-errors";
NginxConfWatcher_Changed(null!, null!); NginxConfWatcher_Changed(null!, null!);
MihomoConfWatcher_Changed(null!, null!);
} }
} }
private async void NginxConfWatcher_Changed(object sender, FileSystemEventArgs e) private async void NginxConfWatcher_Changed(object sender, FileSystemEventArgs e)
{ {
if (!MainConst.IsAdmin || !MainPres.IsNginxExist) if (!MainConst.IsAdmin || (!MainPres.IsNginxExist && !MainPres.IsConginxExist))
return; return;
if (!File.Exists(MainConst.NginxConfPath)) if (!File.Exists(MainConst.NginxConfPath))
@ -653,6 +766,9 @@ public partial class MainWin : Window
if (!Directory.Exists(MainConst.NginxTempPath)) if (!Directory.Exists(MainConst.NginxTempPath))
Directory.CreateDirectory(MainConst.NginxTempPath); Directory.CreateDirectory(MainConst.NginxTempPath);
NginxHttpPort = 80;
NginxHttpsPort = 443;
foreach (IPEndPoint activeTcpListener in IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners()) foreach (IPEndPoint activeTcpListener in IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners())
if (activeTcpListener.Port == NginxHttpPort) if (activeTcpListener.Port == NginxHttpPort)
NginxHttpPort++; NginxHttpPort++;
@ -680,6 +796,7 @@ public partial class MainWin : Window
.AddOrUpdate("events:worker_connections", "65536") .AddOrUpdate("events:worker_connections", "65536")
.AddOrUpdate("http:proxy_set_header", "Host $http_host") .AddOrUpdate("http:proxy_set_header", "Host $http_host")
.AddOrUpdate("http:proxy_ssl_server_name", !MainPres.IsFlashing ? "on" : "off") .AddOrUpdate("http:proxy_ssl_server_name", !MainPres.IsFlashing ? "on" : "off")
.AddOrUpdate("http:proxy_buffer_size", "14k")
.AddOrUpdate($"http:server[{serverIndex}]:listen", $"{NginxHttpPort} default_server") .AddOrUpdate($"http:server[{serverIndex}]:listen", $"{NginxHttpPort} default_server")
.AddOrUpdate($"http:server[{serverIndex}]:return", "https://$host$request_uri"); .AddOrUpdate($"http:server[{serverIndex}]:return", "https://$host$request_uri");
@ -717,7 +834,7 @@ public partial class MainWin : Window
} }
private async void MihomoConfWatcher_Changed(object sender, FileSystemEventArgs e) private async void MihomoConfWatcher_Changed(object sender, FileSystemEventArgs e)
{ {
if (!MainConst.IsAdmin || !MainPres.IsMihomoExist) if (!MainConst.IsAdmin || (!MainPres.IsMihomoExist && !MainPres.IsComihomoExist))
return; return;
try try
@ -725,6 +842,8 @@ public partial class MainWin : Window
if (!File.Exists(MainConst.MihomoConfPath)) if (!File.Exists(MainConst.MihomoConfPath))
await File.Create(MainConst.MihomoConfPath).DisposeAsync(); await File.Create(MainConst.MihomoConfPath).DisposeAsync();
MihomoMixedPort = 7880;
foreach (IPEndPoint activeTcpListener in IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners()) foreach (IPEndPoint activeTcpListener in IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners())
if (activeTcpListener.Port == MihomoMixedPort) if (activeTcpListener.Port == MihomoMixedPort)
MihomoMixedPort++; MihomoMixedPort++;
@ -737,16 +856,14 @@ public partial class MainWin : Window
.IgnoreUnmatchedProperties() .IgnoreUnmatchedProperties()
.Build() .Build()
.Deserialize<Dictionary<string, object>>(ExtraMihomoConfs = await new StreamReader(mihomoConfStream).ReadToEndAsync()) ?? []; .Deserialize<Dictionary<string, object>>(ExtraMihomoConfs = await new StreamReader(mihomoConfStream).ReadToEndAsync()) ?? [];
Dictionary<string, object> hostsMihomoConfDict = new DeserializerBuilder()
.WithNamingConvention(HyphenatedNamingConvention.Instance)
.IgnoreUnmatchedProperties()
.Build()
.Deserialize<Dictionary<string, object>>(ExtraMihomoConfs = await new StreamReader(mihomoConfStream).ReadToEndAsync()) ?? [];
mihomoConfDict["mixed-port"] = MihomoMixedPort; mihomoConfDict["mixed-port"] = hostsMihomoConfDict["mixed-port"] = MihomoMixedPort;
mihomoConfDict["dns"] = new mihomoConfDict["tun"] = hostsMihomoConfDict["tun"] = new
{
enable = true,
listen = ":53",
enhancedMode = "redir-host",
nameserver = MainConst.MihomoNameServers
};
mihomoConfDict["tun"] = new
{ {
enable = true, enable = true,
stack = "system", stack = "system",
@ -754,10 +871,50 @@ public partial class MainWin : Window
autoDetectInterface = true, autoDetectInterface = true,
dnsHijack = new[] { "any:53", "tcp://any:53" } dnsHijack = new[] { "any:53", "tcp://any:53" }
}; };
mihomoConfDict["dns"] = new
{
enable = true,
listen = ":53",
ipv6 = true,
nameserver = MainConst.MihomoNameServers
};
hostsMihomoConfDict["dns"] = new
{
enable = true,
listen = ":53",
ipv6 = true
};
MihomoConfs = new SerializerBuilder().WithNamingConvention(HyphenatedNamingConvention.Instance).Build().Serialize(mihomoConfDict); MihomoConfs = new SerializerBuilder().WithNamingConvention(HyphenatedNamingConvention.Instance).Build().Serialize(mihomoConfDict);
Dictionary<string, string> mihomoHostsDict = [];
foreach (List<(List<(string cealHostIncludeDomain, string cealHostExcludeDomain)> cealHostDomainPairs, string? cealHostSni, string cealHostIp)>? cealHostRules in CealHostRulesDict.Values)
foreach ((List<(string cealHostIncludeDomain, string cealHostExcludeDomain)> cealHostDomainPairs, _, _) in cealHostRules ?? [])
foreach ((string cealHostIncludeDomain, _) in cealHostDomainPairs)
{
string cealHostIncludeDomainWithoutWildcard = cealHostIncludeDomain.TrimStart('$').TrimStart('*').TrimStart('.');
if (cealHostIncludeDomain.StartsWith('#') || cealHostIncludeDomainWithoutWildcard.Contains('*') || string.IsNullOrWhiteSpace(cealHostIncludeDomainWithoutWildcard))
continue;
if (cealHostIncludeDomain.TrimStart('$').StartsWith('*'))
{
mihomoHostsDict.TryAdd($"*.{cealHostIncludeDomainWithoutWildcard}", "127.0.0.1");
if (cealHostIncludeDomain.TrimStart('$').StartsWith("*."))
continue;
}
mihomoHostsDict.TryAdd(cealHostIncludeDomainWithoutWildcard, "127.0.0.1");
}
mihomoConfDict["hosts"] = hostsMihomoConfDict["hosts"] = mihomoHostsDict;
ComihomoConfs = new SerializerBuilder().WithNamingConvention(HyphenatedNamingConvention.Instance).Build().Serialize(mihomoConfDict);
HostsComihomoConfs = new SerializerBuilder().WithNamingConvention(HyphenatedNamingConvention.Instance).Build().Serialize(hostsMihomoConfDict);
} }
catch { MihomoConfs = string.Empty; } catch { ComihomoConfs = HostsComihomoConfs = MihomoConfs = string.Empty; }
} }
private void MainWin_KeyDown(object sender, KeyEventArgs e) private void MainWin_KeyDown(object sender, KeyEventArgs e)
{ {