diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 7a46fdf2e7..984ab41f0a 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -4,7 +4,6 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
-using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
@@ -30,7 +29,6 @@ using Emby.Server.Implementations.Cryptography;
using Emby.Server.Implementations.Data;
using Emby.Server.Implementations.Devices;
using Emby.Server.Implementations.Dto;
-using Emby.Server.Implementations.HttpServer;
using Emby.Server.Implementations.HttpServer.Security;
using Emby.Server.Implementations.IO;
using Emby.Server.Implementations.Library;
@@ -258,8 +256,8 @@ namespace Emby.Server.Implementations
IServiceCollection serviceCollection)
{
_xmlSerializer = new MyXmlSerializer();
- _jsonSerializer = new JsonSerializer();
-
+ _jsonSerializer = new JsonSerializer();
+
ServiceCollection = serviceCollection;
_networkManager = networkManager;
@@ -1026,80 +1024,54 @@ namespace Emby.Server.Implementations
protected abstract void RestartInternal();
- ///
- /// Comparison function used in .
- ///
- /// Item to compare.
- /// Item to compare with.
- /// Boolean result of the operation.
- private static int VersionCompare(
- (Version PluginVersion, string Name, string Path) a,
- (Version PluginVersion, string Name, string Path) b)
- {
- int compare = string.Compare(a.Name, b.Name, true, CultureInfo.InvariantCulture);
-
- if (compare == 0)
- {
- return a.PluginVersion.CompareTo(b.PluginVersion);
- }
-
- return compare;
- }
-
- ///
- /// Returns a list of plugins to install.
- ///
- /// Path to check.
- /// True if an attempt should be made to delete old plugs.
- /// Enumerable list of dlls to load.
- private IEnumerable GetPlugins(string path, bool cleanup = true)
+ ///
+ public IEnumerable GetLocalPlugins(string path, bool cleanup = true)
{
- var dllList = new List();
- var versions = new List<(Version PluginVersion, string Name, string Path)>();
+ var minimumVersion = new Version(0, 0, 0, 1);
+ var versions = new List();
var directories = Directory.EnumerateDirectories(path, "*.*", SearchOption.TopDirectoryOnly);
- string metafile;
foreach (var dir in directories)
{
try
{
- metafile = Path.Combine(dir, "meta.json");
+ var metafile = Path.Combine(dir, "meta.json");
if (File.Exists(metafile))
{
var manifest = _jsonSerializer.DeserializeFromFile(metafile);
if (!Version.TryParse(manifest.TargetAbi, out var targetAbi))
{
- targetAbi = new Version(0, 0, 0, 1);
+ targetAbi = minimumVersion;
}
if (!Version.TryParse(manifest.Version, out var version))
{
- version = new Version(0, 0, 0, 1);
+ version = minimumVersion;
}
if (ApplicationVersion >= targetAbi)
{
// Only load Plugins if the plugin is built for this version or below.
- versions.Add((version, manifest.Name, dir));
+ versions.Add(new LocalPlugin(manifest.Guid, manifest.Name, version, dir));
}
}
else
{
// No metafile, so lets see if the folder is versioned.
metafile = dir.Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries)[^1];
-
+
int versionIndex = dir.LastIndexOf('_');
- if (versionIndex != -1 && Version.TryParse(dir.Substring(versionIndex + 1), out Version ver))
+ if (versionIndex != -1 && Version.TryParse(dir.Substring(versionIndex + 1), out Version parsedVersion))
{
// Versioned folder.
- versions.Add((ver, metafile, dir));
+ versions.Add(new LocalPlugin(Guid.Empty, metafile, parsedVersion, dir));
}
else
{
- // Un-versioned folder - Add it under the path name and version 0.0.0.1.
- versions.Add((new Version(0, 0, 0, 1), metafile, dir));
- }
+ // Un-versioned folder - Add it under the path name and version 0.0.0.1.
+ versions.Add(new LocalPlugin(Guid.Empty, metafile, minimumVersion, dir));
+ }
}
}
catch
@@ -1109,14 +1081,14 @@ namespace Emby.Server.Implementations
}
string lastName = string.Empty;
- versions.Sort(VersionCompare);
+ versions.Sort(LocalPlugin.Compare);
// Traverse backwards through the list.
// The first item will be the latest version.
for (int x = versions.Count - 1; x >= 0; x--)
{
if (!string.Equals(lastName, versions[x].Name, StringComparison.OrdinalIgnoreCase))
{
- dllList.AddRange(Directory.EnumerateFiles(versions[x].Path, "*.dll", SearchOption.AllDirectories));
+ versions[x].DllFiles.AddRange(Directory.EnumerateFiles(versions[x].Path, "*.dll", SearchOption.AllDirectories));
lastName = versions[x].Name;
continue;
}
@@ -1124,6 +1096,7 @@ namespace Emby.Server.Implementations
if (!string.IsNullOrEmpty(lastName) && cleanup)
{
// Attempt a cleanup of old folders.
+ versions.RemoveAt(x);
try
{
Logger.LogDebug("Deleting {Path}", versions[x].Path);
@@ -1136,7 +1109,7 @@ namespace Emby.Server.Implementations
}
}
- return dllList;
+ return versions;
}
///
@@ -1147,21 +1120,24 @@ namespace Emby.Server.Implementations
{
if (Directory.Exists(ApplicationPaths.PluginsPath))
{
- foreach (var file in GetPlugins(ApplicationPaths.PluginsPath))
+ foreach (var plugin in GetLocalPlugins(ApplicationPaths.PluginsPath))
{
- Assembly plugAss;
- try
+ foreach (var file in plugin.DllFiles)
{
- plugAss = Assembly.LoadFrom(file);
- }
- catch (FileLoadException ex)
- {
- Logger.LogError(ex, "Failed to load assembly {Path}", file);
- continue;
- }
+ Assembly plugAss;
+ try
+ {
+ plugAss = Assembly.LoadFrom(file);
+ }
+ catch (FileLoadException ex)
+ {
+ Logger.LogError(ex, "Failed to load assembly {Path}", file);
+ continue;
+ }
- Logger.LogInformation("Loaded assembly {Assembly} from {Path}", plugAss.FullName, file);
- yield return plugAss;
+ Logger.LogInformation("Loaded assembly {Assembly} from {Path}", plugAss.FullName, file);
+ yield return plugAss;
+ }
}
}
diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs
index 003cf3c740..365d890655 100644
--- a/Emby.Server.Implementations/Updates/InstallationManager.cs
+++ b/Emby.Server.Implementations/Updates/InstallationManager.cs
@@ -15,14 +15,13 @@ using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.Updates;
-using MediaBrowser.Common.System;
+using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Updates;
using Microsoft.Extensions.Logging;
-using MediaBrowser.Model.System;
namespace Emby.Server.Implementations.Updates
{
@@ -45,7 +44,7 @@ namespace Emby.Server.Implementations.Updates
/// Gets the application host.
///
/// The application host.
- private readonly IApplicationHost _applicationHost;
+ private readonly IServerApplicationHost _applicationHost;
private readonly IZipClient _zipClient;
@@ -63,7 +62,7 @@ namespace Emby.Server.Implementations.Updates
public InstallationManager(
ILogger logger,
- IApplicationHost appHost,
+ IServerApplicationHost appHost,
IApplicationPaths appPaths,
IHttpClientFactory httpClientFactory,
IJsonSerializer jsonSerializer,
@@ -237,7 +236,8 @@ namespace Emby.Server.Implementations.Updates
private IEnumerable GetAvailablePluginUpdates(IReadOnlyList pluginCatalog)
{
- foreach (var plugin in _applicationHost.Plugins)
+ var plugins = _applicationHost.GetLocalPlugins(_appPaths.PluginsPath);
+ foreach (var plugin in plugins)
{
var compatibleVersions = GetCompatibleVersions(pluginCatalog, plugin.Name, plugin.Id, minVersion: plugin.Version);
var version = compatibleVersions.FirstOrDefault(y => y.Version > plugin.Version);
diff --git a/MediaBrowser.Common/Plugins/LocalPlugin.cs b/MediaBrowser.Common/Plugins/LocalPlugin.cs
new file mode 100644
index 0000000000..e26631615a
--- /dev/null
+++ b/MediaBrowser.Common/Plugins/LocalPlugin.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace MediaBrowser.Common.Plugins
+{
+ ///
+ /// Local plugin struct.
+ ///
+ public readonly struct LocalPlugin : IEquatable
+ {
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The plugin id.
+ /// The plugin name.
+ /// The plugin version.
+ /// The plugin path.
+ public LocalPlugin(Guid id, string name, Version version, string path)
+ {
+ Id = id;
+ Name = name;
+ Version = version;
+ Path = path;
+ DllFiles = new List();
+ }
+
+ ///
+ /// Gets the plugin id.
+ ///
+ public Guid Id { get; }
+
+ ///
+ /// Gets the plugin name.
+ ///
+ public string Name { get; }
+
+ ///
+ /// Gets the plugin version.
+ ///
+ public Version Version { get; }
+
+ ///
+ /// Gets the plugin path.
+ ///
+ public string Path { get; }
+
+ ///
+ /// Gets the list of dll files for this plugin.
+ ///
+ public List DllFiles { get; }
+
+ ///
+ /// == operator.
+ ///
+ /// Left item.
+ /// Right item.
+ /// Comparison result.
+ public static bool operator ==(LocalPlugin left, LocalPlugin right)
+ {
+ return left.Equals(right);
+ }
+
+ ///
+ /// != operator.
+ ///
+ /// Left item.
+ /// Right item.
+ /// Comparison result.
+ public static bool operator !=(LocalPlugin left, LocalPlugin right)
+ {
+ return !(left == right);
+ }
+
+ ///
+ /// Compare two .
+ ///
+ /// The first item.
+ /// The second item.
+ /// Comparison result.
+ public static int Compare(LocalPlugin a, LocalPlugin b)
+ {
+ var compare = string.Compare(a.Name, b.Name, true, CultureInfo.InvariantCulture);
+
+ // Id is not equal but name is.
+ if (a.Id != b.Id && compare == 0)
+ {
+ compare = a.Id.CompareTo(b.Id);
+ }
+
+ return compare == 0 ? a.Version.CompareTo(b.Version) : compare;
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ return obj is LocalPlugin other && this.Equals(other);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ return Name.GetHashCode(StringComparison.OrdinalIgnoreCase);
+ }
+
+ ///
+ public bool Equals(LocalPlugin other)
+ {
+ return Name.Equals(other.Name, StringComparison.OrdinalIgnoreCase)
+ && Id.Equals(other.Id);
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs
index cfad17fb72..8a55437c5d 100644
--- a/MediaBrowser.Controller/IServerApplicationHost.cs
+++ b/MediaBrowser.Controller/IServerApplicationHost.cs
@@ -6,8 +6,8 @@ using System.Net;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common;
+using MediaBrowser.Common.Plugins;
using MediaBrowser.Model.System;
-using Microsoft.AspNetCore.Http;
namespace MediaBrowser.Controller
{
@@ -119,5 +119,13 @@ namespace MediaBrowser.Controller
string ExpandVirtualPath(string path);
string ReverseVirtualPath(string path);
+
+ ///
+ /// Gets the list of local plugins.
+ ///
+ /// Plugin base directory.
+ /// Cleanup old plugins.
+ /// Enumerable of local plugins.
+ IEnumerable GetLocalPlugins(string path, bool cleanup = true);
}
}