Flow.Launcher/Flow.Launcher.Core/Plugin/PluginInstaller.cs

170 lines
7.1 KiB
C#
Raw Normal View History

using System;
2014-01-12 08:28:11 +00:00
using System.IO;
2016-01-06 06:45:08 +00:00
using System.Windows;
2014-01-12 08:28:11 +00:00
using ICSharpCode.SharpZipLib.Zip;
2014-03-02 03:04:30 +00:00
using Newtonsoft.Json;
2020-04-21 09:12:17 +00:00
using Flow.Launcher.Plugin;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Logger;
2014-01-12 08:28:11 +00:00
2020-04-21 09:12:17 +00:00
namespace Flow.Launcher.Core.Plugin
2014-01-12 08:28:11 +00:00
{
2014-12-27 04:34:51 +00:00
internal class PluginInstaller
2014-01-12 08:28:11 +00:00
{
2014-12-27 04:34:51 +00:00
internal static void Install(string path)
2014-01-12 08:28:11 +00:00
{
if (File.Exists(path))
{
2020-06-13 18:02:37 +00:00
string tempFolder = Path.Combine(Path.GetTempPath(), "flowlauncher", "plugins");
if (Directory.Exists(tempFolder))
2014-01-12 08:28:11 +00:00
{
2020-06-13 18:02:37 +00:00
Directory.Delete(tempFolder, true);
2014-01-12 08:28:11 +00:00
}
2020-06-13 18:02:37 +00:00
UnZip(path, tempFolder, true);
2014-01-12 08:28:11 +00:00
2020-06-13 18:02:37 +00:00
string jsonPath = Path.Combine(tempFolder, Constant.PluginMetadataFileName);
if (!File.Exists(jsonPath))
2014-01-12 08:28:11 +00:00
{
2014-03-11 15:54:37 +00:00
MessageBox.Show("Install failed: plugin config is missing");
2014-01-12 08:28:11 +00:00
return;
}
2020-06-13 18:02:37 +00:00
PluginMetadata plugin = GetMetadataFromJson(tempFolder);
2014-01-12 08:28:11 +00:00
if (plugin == null || plugin.Name == null)
{
2014-03-11 15:54:37 +00:00
MessageBox.Show("Install failed: plugin config is invalid");
2014-01-12 08:28:11 +00:00
return;
}
2020-06-13 18:02:37 +00:00
string pluginFolderPath = Infrastructure.UserSettings.DataLocation.PluginsDirectory;
2014-01-12 08:28:11 +00:00
2014-12-15 12:38:42 +00:00
string newPluginName = plugin.Name
.Replace("/", "_")
.Replace("\\", "_")
.Replace(":", "_")
.Replace("<", "_")
.Replace(">", "_")
.Replace("?", "_")
.Replace("*", "_")
.Replace("|", "_")
+ "-" + Guid.NewGuid();
2020-06-13 18:02:37 +00:00
string newPluginPath = Path.Combine(pluginFolderPath, newPluginName);
string content = $"Do you want to install following plugin?{Environment.NewLine}{Environment.NewLine}" +
$"Name: {plugin.Name}{Environment.NewLine}" +
$"Version: {plugin.Version}{Environment.NewLine}" +
$"Author: {plugin.Author}";
PluginPair existingPlugin = PluginManager.GetPluginForId(plugin.ID);
2014-03-13 14:31:44 +00:00
if (existingPlugin != null)
2014-01-12 08:28:11 +00:00
{
content = $"Do you want to update following plugin?{Environment.NewLine}{Environment.NewLine}" +
$"Name: {plugin.Name}{Environment.NewLine}" +
$"Old Version: {existingPlugin.Metadata.Version}" +
$"{Environment.NewLine}New Version: {plugin.Version}" +
$"{Environment.NewLine}Author: {plugin.Author}";
2014-01-12 08:28:11 +00:00
}
var result = MessageBox.Show(content, "Install plugin", MessageBoxButton.YesNo, MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
2014-01-12 08:28:11 +00:00
{
if (existingPlugin != null && Directory.Exists(existingPlugin.Metadata.PluginDirectory))
2014-01-12 08:28:11 +00:00
{
2014-12-15 12:38:42 +00:00
//when plugin is in use, we can't delete them. That's why we need to make plugin folder a random name
File.Create(Path.Combine(existingPlugin.Metadata.PluginDirectory, "NeedDelete.txt")).Close();
2014-01-12 08:28:11 +00:00
}
2014-03-13 14:31:44 +00:00
2020-06-13 18:02:37 +00:00
Directory.Move(tempFolder, newPluginPath);
2014-01-12 08:28:11 +00:00
2014-03-13 14:31:44 +00:00
//exsiting plugins may be has loaded by application,
//if we try to delelte those kind of plugins, we will get a error that indicate the
//file is been used now.
2020-04-23 09:24:13 +00:00
//current solution is to restart Flow Launcher. Ugly.
2014-03-13 14:31:44 +00:00
//if (MainWindow.Initialized)
//{
// Plugins.Initialize();
2014-03-13 14:31:44 +00:00
//}
if (MessageBox.Show($"You have installed plugin {plugin.Name} successfully.{Environment.NewLine}" +
2020-04-22 10:26:09 +00:00
"Restart Flow Launcher to take effect?",
"Install plugin", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
2014-01-12 08:28:11 +00:00
{
PluginManager.API.RestartApp();
2014-01-12 08:28:11 +00:00
}
}
}
}
2014-03-02 03:04:30 +00:00
private static PluginMetadata GetMetadataFromJson(string pluginDirectory)
2014-03-11 14:17:10 +00:00
{
string configPath = Path.Combine(pluginDirectory, Constant.PluginMetadataFileName);
2014-03-02 03:04:30 +00:00
PluginMetadata metadata;
2014-01-12 08:28:11 +00:00
2014-03-02 03:04:30 +00:00
if (!File.Exists(configPath))
2014-01-12 08:28:11 +00:00
{
return null;
}
try
{
2014-03-02 03:04:30 +00:00
metadata = JsonConvert.DeserializeObject<PluginMetadata>(File.ReadAllText(configPath));
metadata.PluginDirectory = pluginDirectory;
2014-03-02 03:04:30 +00:00
}
catch (Exception e)
2014-03-02 03:04:30 +00:00
{
Log.Exception($"|PluginInstaller.GetMetadataFromJson|plugin config {configPath} failed: invalid json format", e);
2014-03-02 03:04:30 +00:00
return null;
}
if (!AllowedLanguage.IsAllowed(metadata.Language))
{
Log.Error($"|PluginInstaller.GetMetadataFromJson|plugin config {configPath} failed: invalid language {metadata.Language}");
2014-03-02 03:04:30 +00:00
return null;
2014-01-12 08:28:11 +00:00
}
2014-03-02 03:04:30 +00:00
if (!File.Exists(metadata.ExecuteFilePath))
2014-01-12 08:28:11 +00:00
{
Log.Error($"|PluginInstaller.GetMetadataFromJson|plugin config {configPath} failed: file {metadata.ExecuteFilePath} doesn't exist");
2014-01-12 08:28:11 +00:00
return null;
}
2014-03-02 03:04:30 +00:00
return metadata;
2014-01-12 08:28:11 +00:00
}
/// <summary>
2020-06-13 18:02:37 +00:00
/// unzip plugin contents to the given directory.
2014-01-12 08:28:11 +00:00
/// </summary>
2020-06-13 18:02:37 +00:00
/// <param name="zipFile">The path to the zip file.</param>
/// <param name="strDirectory">The output directory.</param>
2014-01-12 08:28:11 +00:00
/// <param name="overWrite">overwirte</param>
2020-06-13 18:02:37 +00:00
private static void UnZip(string zipFile, string strDirectory, bool overWrite)
2014-01-12 08:28:11 +00:00
{
if (strDirectory == "")
strDirectory = Directory.GetCurrentDirectory();
2020-06-13 18:02:37 +00:00
using (ZipInputStream zipStream = new ZipInputStream(File.OpenRead(zipFile)))
2014-01-12 08:28:11 +00:00
{
ZipEntry theEntry;
2020-06-13 18:02:37 +00:00
while ((theEntry = zipStream.GetNextEntry()) != null)
2014-01-12 08:28:11 +00:00
{
2020-06-13 18:02:37 +00:00
var pathToZip = theEntry.Name;
var directoryName = String.IsNullOrEmpty(pathToZip) ? "" : Path.GetDirectoryName(pathToZip);
var fileName = Path.GetFileName(pathToZip);
var destinationDir = Path.Combine(strDirectory, directoryName);
var destinationFile = Path.Combine(destinationDir, fileName);
2014-01-12 08:28:11 +00:00
2020-06-13 18:02:37 +00:00
Directory.CreateDirectory(destinationDir);
2014-01-12 08:28:11 +00:00
2020-06-13 18:02:37 +00:00
if (String.IsNullOrEmpty(fileName) || (File.Exists(destinationFile) && !overWrite))
continue;
2014-01-12 08:28:11 +00:00
2020-06-13 18:02:37 +00:00
using (FileStream streamWriter = File.Create(destinationFile))
2014-01-12 08:28:11 +00:00
{
2020-06-13 18:02:37 +00:00
zipStream.CopyTo(streamWriter);
2014-01-12 08:28:11 +00:00
}
}
}
}
}
}