diff --git a/RevokeMsgPatcher/FormMain.Designer.cs b/RevokeMsgPatcher/FormMain.Designer.cs index 66d009e..93c5342 100644 --- a/RevokeMsgPatcher/FormMain.Designer.cs +++ b/RevokeMsgPatcher/FormMain.Designer.cs @@ -339,7 +339,7 @@ // this.panelCategories.Location = new System.Drawing.Point(83, 85); this.panelCategories.Name = "panelCategories"; - this.panelCategories.Size = new System.Drawing.Size(201, 18); + this.panelCategories.Size = new System.Drawing.Size(393, 18); this.panelCategories.TabIndex = 22; // // FormMain diff --git a/RevokeMsgPatcher/FormMain.cs b/RevokeMsgPatcher/FormMain.cs index 9bc6c0a..0c06c2d 100644 --- a/RevokeMsgPatcher/FormMain.cs +++ b/RevokeMsgPatcher/FormMain.cs @@ -3,6 +3,7 @@ using RevokeMsgPatcher.Model; using RevokeMsgPatcher.Modifier; using RevokeMsgPatcher.Utils; using System; +using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.IO; @@ -71,13 +72,36 @@ namespace RevokeMsgPatcher { // 自动获取应用安装路径 txtPath.Text = modifier.FindInstallPath(); - btnRestore.Enabled = false; - // 显示是否能够备份还原 - if (!string.IsNullOrEmpty(txtPath.Text)) + // 显示是否能够备份还原、版本和功能 + InitEditorsAndUI(txtPath.Text); + + } + + private void InitEditorsAndUI(string path) + { + if (!string.IsNullOrEmpty(path)) { - modifier.InitEditors(txtPath.Text); + EnableAllButton(false); + + // 清空界面元素 + lblVersion.Text = ""; + panelCategories.Controls.Clear(); + + // 重新计算并修改界面元素 + modifier.InitEditors(path); modifier.SetVersionLabelAndCategoryCategories(lblVersion, panelCategories); + + EnableAllButton(true); + + // 重新显示备份状态 + btnRestore.Enabled = false; btnRestore.Enabled = modifier.BackupExists(); + + List categories = UIController.GetCategoriesFromPanel(panelCategories); + if (categories != null && categories.Count == 0) + { + btnPatch.Enabled = false; + } } } @@ -97,9 +121,9 @@ namespace RevokeMsgPatcher EnableAllButton(false); // a.重新初始化编辑器 modifier.InitEditors(txtPath.Text); - // b.获取选择的功能 - string[] categories = UIController.GetCategoriesFromPanel(panelCategories); - if (panelCategories.Controls.Count > 0 && (categories == null || categories.Length == 0)) + // b.获取选择的功能 (精准匹配返回null) + List categories = UIController.GetCategoriesFromPanel(panelCategories); + if (categories != null && categories.Count == 0) { MessageBox.Show("请至少选择一项功能"); EnableAllButton(true); @@ -142,6 +166,7 @@ namespace RevokeMsgPatcher modifier.Patch(); ga.RequestPageView($"{enName}/{version}/patch/succ", "补丁安装成功"); MessageBox.Show("补丁安装成功!"); + } catch (BusinessException ex) { @@ -157,8 +182,7 @@ namespace RevokeMsgPatcher } finally { - EnableAllButton(true); - btnRestore.Enabled = modifier.BackupExists(); + InitEditorsAndUI(txtPath.Text); } } @@ -167,11 +191,12 @@ namespace RevokeMsgPatcher { if (modifier.IsAllFilesExist(txtPath.Text)) { - modifier.InitEditors(txtPath.Text); - btnRestore.Enabled = modifier.BackupExists(); + InitEditorsAndUI(txtPath.Text); } else { + UIController.AddMsgToPanel(panelCategories, "请输入正确的应用路径"); + lblVersion.Text = ""; btnPatch.Enabled = false; btnRestore.Enabled = false; } @@ -190,14 +215,8 @@ namespace RevokeMsgPatcher else { txtPath.Text = dialog.SelectedPath; - btnRestore.Enabled = false; - // 显示是否能够备份还原 - if (!string.IsNullOrEmpty(txtPath.Text)) - { - modifier.InitEditors(txtPath.Text); - modifier.SetVersionLabelAndCategoryCategories(lblVersion, panelCategories); - btnRestore.Enabled = modifier.BackupExists(); - } + // 显示是否能够备份还原、版本和功能 + InitEditorsAndUI(txtPath.Text); } } } @@ -219,12 +238,13 @@ namespace RevokeMsgPatcher MessageBox.Show(ex.Message); } EnableAllButton(true); - btnRestore.Enabled = modifier.BackupExists(); + // 重新计算显示是否能够备份还原、版本和功能 + InitEditorsAndUI(txtPath.Text); } private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { - System.Diagnostics.Process.Start("https://github.com/huiyadanli/RevokeMsgPatcher"); + Process.Start("https://github.com/huiyadanli/RevokeMsgPatcher"); } private async void FormMain_Load(object sender, EventArgs e) @@ -313,16 +333,9 @@ namespace RevokeMsgPatcher } txtPath.Text = modifier.FindInstallPath(); EnableAllButton(true); - lblVersion.Text = ""; - btnRestore.Enabled = false; - panelCategories.Controls.Clear(); - // 显示是否能够备份还原 - if (!string.IsNullOrEmpty(txtPath.Text)) - { - modifier.InitEditors(txtPath.Text); - modifier.SetVersionLabelAndCategoryCategories(lblVersion, panelCategories); - btnRestore.Enabled = modifier.BackupExists(); - } + + // 重新计算显示是否能够备份还原、版本和功能 + InitEditorsAndUI(txtPath.Text); ga.RequestPageView($"{GetCheckedRadioButtonNameEn()}/{lblVersion.Text}/switch", "切换标签页"); } diff --git a/RevokeMsgPatcher/Forms/UIController.cs b/RevokeMsgPatcher/Forms/UIController.cs index 20b26f0..1d10c47 100644 --- a/RevokeMsgPatcher/Forms/UIController.cs +++ b/RevokeMsgPatcher/Forms/UIController.cs @@ -10,7 +10,7 @@ namespace RevokeMsgPatcher.Forms { public class UIController { - public static void AddCategoryCheckBoxToPanel(Panel panel, string[] categories = null) + public static void AddCategoryCheckBoxToPanel(Panel panel, string[] categories, string[] installed) { if (categories != null && categories.Length != 0) { @@ -24,9 +24,9 @@ namespace RevokeMsgPatcher.Forms Checked = true, AutoSize = true }; - // 只有一个选项时,必选 - if (categories.Length == 1) + if (installed.Contains(categories[i])) { + chk.Text = chk.Text + "(已安装)"; chk.Enabled = false; } panel.Controls.Add(chk); @@ -45,22 +45,30 @@ namespace RevokeMsgPatcher.Forms { Name = "lblCategoriesMsg", Text = msg, - TextAlign = ContentAlignment.MiddleLeft + TextAlign = ContentAlignment.MiddleLeft, + Size = new Size(panel.Width, panel.Height) }; panel.Controls.Add(label); } - public static string[] GetCategoriesFromPanel(Panel panel) + public static List GetCategoriesFromPanel(Panel panel) { List categories = new List(); - foreach (CheckBox checkBox in panel.Controls) + foreach (Control ctrl in panel.Controls) { - if (checkBox.Checked) + if (ctrl is CheckBox checkBox) { - categories.Add(checkBox.Text); + if (checkBox.Enabled && checkBox.Checked) + { + categories.Add(checkBox.Text); + } + } + else if (ctrl is Label label) + { + return null; // 如果是标签, 说明是精准匹配, 直接返回null } } - return categories.ToArray(); + return categories; } } } diff --git a/RevokeMsgPatcher/Matcher/ModifyFinder.cs b/RevokeMsgPatcher/Matcher/ModifyFinder.cs index 4bb75cd..353a27b 100644 --- a/RevokeMsgPatcher/Matcher/ModifyFinder.cs +++ b/RevokeMsgPatcher/Matcher/ModifyFinder.cs @@ -79,6 +79,13 @@ namespace RevokeMsgPatcher.Matcher } } + public static SortedSet FindReplacedFunction(string path, List replacePatterns) + { + byte[] fileByteArray = File.ReadAllBytes(path); + Tuple> res = IsAllReplaced(fileByteArray, replacePatterns); + return res.Item2; + } + private static Tuple> IsAllReplaced(byte[] fileByteArray, List replacePatterns) { int matchNum = 0; diff --git a/RevokeMsgPatcher/Modifier/AppModifier.cs b/RevokeMsgPatcher/Modifier/AppModifier.cs index 699bf0f..aa09e3d 100644 --- a/RevokeMsgPatcher/Modifier/AppModifier.cs +++ b/RevokeMsgPatcher/Modifier/AppModifier.cs @@ -51,8 +51,8 @@ namespace RevokeMsgPatcher.Modifier string version = GetVersion(); // 补丁信息中是否都有对应的版本 int i = 0, j = 0; - // 特征码匹配的时候的可选功能项 - SortedSet categories = new SortedSet(); + + // 精确版本匹配 foreach (FileHexEditor editor in editors) // 多种文件 { // 精确版本匹配 @@ -69,7 +69,22 @@ namespace RevokeMsgPatcher.Modifier { i++; } + } + if (i == editors.Count) + { + label.Text = version + "(已支持)"; + label.ForeColor = Color.Green; + UIController.AddMsgToPanel(panel, "只有基于特征的补丁才能选择功能"); + return; + } + + // 模糊版本匹配(特征码) + // 特征码匹配的时候的可选功能项 + SortedSet categories = new SortedSet(); + SortedSet installed = new SortedSet(); + foreach (FileHexEditor editor in editors) // 多种文件 + { // 匹配出对应版本是否有可以使用的特征 if (config.FileCommonModifyInfos != null) { @@ -87,6 +102,12 @@ namespace RevokeMsgPatcher.Modifier categories.Add(c); } } + // 获取已经安装过的功能类型 + SortedSet replaced = ModifyFinder.FindReplacedFunction(editor.FilePath, commonModifyInfo.ReplacePatterns); + foreach (string c in replaced) + { + installed.Add(c); + } inRange = true; break; } @@ -99,17 +120,11 @@ namespace RevokeMsgPatcher.Modifier } // 全部都有对应匹配的版本 - if (i == editors.Count) - { - label.Text = version + "(已支持)"; - label.ForeColor = Color.Green; - UIController.AddMsgToPanel(panel, "只有基于特征的补丁才能选择功能"); - } - else if (j == editors.Count) + if (j == editors.Count) { label.Text = version + "(支持特征防撤回)"; label.ForeColor = Color.LimeGreen; - UIController.AddCategoryCheckBoxToPanel(panel, categories.ToArray()); + UIController.AddCategoryCheckBoxToPanel(panel, categories.ToArray(), installed.ToArray()); } else { @@ -236,7 +251,7 @@ namespace RevokeMsgPatcher.Modifier /// b.验证文件完整性,寻找对应的补丁信息 /// /// 操作类型(防撤回或者多开等),为空则是所有操作 - public void ValidateAndFindModifyInfo(string[] categories) + public void ValidateAndFindModifyInfo(List categories) { // 寻找对应文件版本与SHA1的修改信息 foreach (FileHexEditor editor in editors) // 多种文件 @@ -291,7 +306,7 @@ namespace RevokeMsgPatcher.Modifier { List replacePatterns = editor.FileCommonModifyInfo.ReplacePatterns; // 根据需要操作的功能类型(防撤回或者多开等)筛选特征码 - if (categories.Length > 0) + if (categories != null && categories.Count > 0) { replacePatterns = editor.FileCommonModifyInfo.ReplacePatterns.Where(info => categories.Contains(info.Category)).ToList(); }