From 69dad1be6c2bca648b54089f62047e78ecadc5e9 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 11 Nov 2023 15:05:24 +0800 Subject: [PATCH] Check if plugin has been modified when installing/updating/uninstalling --- Flow.Launcher.Core/Plugin/PluginManager.cs | 56 ++++++++++++++++++- .../Languages/en.xaml | 4 +- .../PluginsManager.cs | 36 ++++++++---- 3 files changed, 81 insertions(+), 15 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index ea8b79aa4..64e097379 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -31,6 +31,7 @@ namespace Flow.Launcher.Core.Plugin private static PluginsSettings Settings; private static List _metadatas; + private static List _modifiedPlugins = new List(); /// /// Directories that will hold Flow Launcher plugin directory @@ -358,8 +359,42 @@ namespace Flow.Launcher.Core.Plugin && newMetadata.Version.CompareTo(x.Metadata.Version) <= 0); } - public static void Install(UserPlugin plugin, string downloadedFilePath) + #region Public functions + + public static bool PluginModified(string uuid) { + return _modifiedPlugins.Contains(uuid); + } + + public static void UpdatePlugin(PluginMetadata existingVersion, UserPlugin newVersion, string downloadedFilePath) + { + InstallPlugin(newVersion, downloadedFilePath, checkModified:false); + UninstallPlugin(existingVersion, removeSettings:false, checkModified:false); + _modifiedPlugins.Add(existingVersion.ID); + } + + public static void InstallPlugin(UserPlugin plugin, string downloadedFilePath) + { + InstallPlugin(plugin, downloadedFilePath, true); + } + + public static void UninstallPlugin(PluginMetadata plugin, bool removeSettings = true) + { + UninstallPlugin(plugin, removeSettings, true); + } + + #endregion + + #region Internal functions + + internal static void InstallPlugin(UserPlugin plugin, string downloadedFilePath, bool checkModified) + { + if (checkModified && PluginModified(plugin.ID)) + { + // Distinguish exception from installing same or less version + throw new ArgumentException($"Plugin {plugin.Name} {plugin.ID} has been modified.", nameof(plugin)); + } + var tempFolderPath = Path.Combine(Path.GetTempPath(), "flowlauncher"); var tempFolderPluginPath = Path.Combine(tempFolderPath, "plugin"); @@ -420,10 +455,20 @@ namespace Flow.Launcher.Core.Plugin FilesFolders.CopyAll(pluginFolderPath, newPluginPath); Directory.Delete(pluginFolderPath, true); + + if (checkModified) + { + _modifiedPlugins.Add(plugin.ID); + } } - public static void Uninstall(PluginMetadata plugin, bool removeSettings = true) + internal static void UninstallPlugin(PluginMetadata plugin, bool removeSettings, bool checkModified) { + if (checkModified && PluginModified(plugin.ID)) + { + throw new ArgumentException($"Plugin {plugin.Name} has been modified"); + } + if (removeSettings) { Settings.Plugins.Remove(plugin.ID); @@ -432,6 +477,13 @@ namespace Flow.Launcher.Core.Plugin // Marked for deletion. Will be deleted on next start up using var _ = File.CreateText(Path.Combine(plugin.PluginDirectory, "NeedDelete.txt")); + + if (checkModified) + { + _modifiedPlugins.Add(plugin.ID); + } } + + #endregion } } diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml index 1daa73261..42a1ac9b8 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml @@ -20,6 +20,7 @@ Error: A plugin which has the same or greater version with {0} already exists. Error installing plugin Error occurred while trying to install {0} + Error uninstalling plugin No update available All plugins are up to date {0} by {1} {2}{3}Would you like to update this plugin? After the update Flow will automatically restart. @@ -36,7 +37,8 @@ Plugin {0} successfully installed. Please restart Flow. Plugin {0} successfully uninstalled. Please restart Flow. Plugin {0} successfully updated. Please restart Flow. - + Plugin {0} has already been modified. Please restart Flow before making any further changes. + Plugins Manager Management of installing, uninstalling or updating Flow Launcher plugins diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 97cfb67d1..6667c3d4d 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -239,8 +239,6 @@ namespace Flow.Launcher.Plugin.PluginsManager Context.API.GetTranslation("plugin_pluginsmanager_update_title"), MessageBoxButton.YesNo) == MessageBoxResult.Yes) { - Uninstall(x.PluginExistingMetadata, false); - var downloadToFilePath = Path.Combine(DataLocation.PluginsDirectory, $"{x.Name}-{x.NewVersion}.zip"); @@ -249,7 +247,7 @@ namespace Flow.Launcher.Plugin.PluginsManager await Http.DownloadAsync(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath) .ConfigureAwait(false); - Install(x.PluginNewUserPlugin, downloadToFilePath); + PluginManager.UpdatePlugin(x.PluginExistingMetadata, x.PluginNewUserPlugin, downloadToFilePath); if (Settings.AutoRestartAfterChanging) { @@ -413,19 +411,24 @@ namespace Flow.Launcher.Plugin.PluginsManager throw new FileNotFoundException($"Plugin {plugin.ID} zip file not found at {downloadedFilePath}", downloadedFilePath); try { - PluginManager.Install(plugin, downloadedFilePath); + PluginManager.InstallPlugin(plugin, downloadedFilePath); } - catch(FileNotFoundException e) + catch (FileNotFoundException e) { + Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), + Context.API.GetTranslation("plugin_pluginsmanager_install_errormetadatafile")); Log.Exception("Flow.Launcher.Plugin.PluginsManager", e.Message, e); - MessageBox.Show(Context.API.GetTranslation("plugin_pluginsmanager_install_errormetadatafile"), - Context.API.GetTranslation("plugin_pluginsmanager_install_error_title")); } - catch(InvalidOperationException e) + catch (InvalidOperationException e) { + Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), + string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_duplicate"), plugin.Name)); + Log.Exception("Flow.Launcher.Plugin.PluginsManager", e.Message, e); + } + catch (ArgumentException e) { + Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), + string.Format(Context.API.GetTranslation("plugin_pluginsmanager_plugin_modified_error"), plugin.Name)); Log.Exception("Flow.Launcher.Plugin.PluginsManager", e.Message, e); - MessageBox.Show(string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_duplicate"), plugin.Name), - Context.API.GetTranslation("plugin_pluginsmanager_install_error_title")); } } @@ -482,9 +485,18 @@ namespace Flow.Launcher.Plugin.PluginsManager return Search(results, search); } - private static void Uninstall(PluginMetadata plugin, bool removeSettings = true) + private void Uninstall(PluginMetadata plugin) { - PluginManager.Uninstall(plugin, removeSettings); + try + { + PluginManager.UninstallPlugin(plugin, removeSettings:true); + } + catch (ArgumentException e) + { + Log.Exception("Flow.Launcher.Plugin.PluginsManager", e.Message, e); + Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_uninstall_error_title"), + Context.API.GetTranslation("plugin_pluginsmanager_plugin_modified_error")); + } } } }