|
|
@ -80,7 +80,7 @@ namespace Emby.Server.Implementations.Plugins
|
|
|
|
// Now load the assemblies..
|
|
|
|
// Now load the assemblies..
|
|
|
|
foreach (var plugin in _plugins)
|
|
|
|
foreach (var plugin in _plugins)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
CheckIfStillSuperceded(plugin);
|
|
|
|
UpdatePluginSuperceedStatus(plugin);
|
|
|
|
|
|
|
|
|
|
|
|
if (plugin.IsEnabledAndSupported == false)
|
|
|
|
if (plugin.IsEnabledAndSupported == false)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -134,7 +134,7 @@ namespace Emby.Server.Implementations.Plugins
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CheckIfStillSuperceded(plugin);
|
|
|
|
UpdatePluginSuperceedStatus(plugin);
|
|
|
|
if (!plugin.IsEnabledAndSupported)
|
|
|
|
if (!plugin.IsEnabledAndSupported)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
@ -172,7 +172,7 @@ namespace Emby.Server.Implementations.Plugins
|
|
|
|
// Load the plugin.
|
|
|
|
// Load the plugin.
|
|
|
|
var plugin = LoadManifest(folder);
|
|
|
|
var plugin = LoadManifest(folder);
|
|
|
|
// Make sure we haven't already loaded this.
|
|
|
|
// Make sure we haven't already loaded this.
|
|
|
|
if (plugin == null || _plugins.Any(p => p.Manifest.Equals(plugin.Manifest)))
|
|
|
|
if (_plugins.Any(p => p.Manifest.Equals(plugin.Manifest)))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -435,7 +435,7 @@ namespace Emby.Server.Implementations.Plugins
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void CheckIfStillSuperceded(LocalPlugin plugin)
|
|
|
|
private void UpdatePluginSuperceedStatus(LocalPlugin plugin)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (plugin.Manifest.Status != PluginStatus.Superceded)
|
|
|
|
if (plugin.Manifest.Status != PluginStatus.Superceded)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -464,7 +464,6 @@ namespace Emby.Server.Implementations.Plugins
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Directory.Delete(plugin.Path, true);
|
|
|
|
Directory.Delete(plugin.Path, true);
|
|
|
|
_logger.LogDebug("Deleted {Path}", plugin.Path);
|
|
|
|
_logger.LogDebug("Deleted {Path}", plugin.Path);
|
|
|
|
_plugins.Remove(plugin);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#pragma warning disable CA1031 // Do not catch general exception types
|
|
|
|
#pragma warning disable CA1031 // Do not catch general exception types
|
|
|
|
catch
|
|
|
|
catch
|
|
|
@ -476,79 +475,69 @@ namespace Emby.Server.Implementations.Plugins
|
|
|
|
return _plugins.Remove(plugin);
|
|
|
|
return _plugins.Remove(plugin);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private LocalPlugin? LoadManifest(string dir)
|
|
|
|
private LocalPlugin LoadManifest(string dir)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
try
|
|
|
|
Version? version;
|
|
|
|
|
|
|
|
PluginManifest? manifest = null;
|
|
|
|
|
|
|
|
var metafile = Path.Combine(dir, "meta.json");
|
|
|
|
|
|
|
|
if (File.Exists(metafile))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Version? version;
|
|
|
|
try
|
|
|
|
PluginManifest? manifest = null;
|
|
|
|
|
|
|
|
var metafile = Path.Combine(dir, "meta.json");
|
|
|
|
|
|
|
|
if (File.Exists(metafile))
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
try
|
|
|
|
var data = File.ReadAllText(metafile, Encoding.UTF8);
|
|
|
|
{
|
|
|
|
manifest = JsonSerializer.Deserialize<PluginManifest>(data, _jsonOptions);
|
|
|
|
var data = File.ReadAllText(metafile, Encoding.UTF8);
|
|
|
|
}
|
|
|
|
manifest = JsonSerializer.Deserialize<PluginManifest>(data, _jsonOptions);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma warning disable CA1031 // Do not catch general exception types
|
|
|
|
#pragma warning disable CA1031 // Do not catch general exception types
|
|
|
|
catch (Exception ex)
|
|
|
|
catch (Exception ex)
|
|
|
|
#pragma warning restore CA1031 // Do not catch general exception types
|
|
|
|
#pragma warning restore CA1031 // Do not catch general exception types
|
|
|
|
{
|
|
|
|
|
|
|
|
_logger.LogError(ex, "Error deserializing {Path}.", dir);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (manifest != null)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (!Version.TryParse(manifest.TargetAbi, out var targetAbi))
|
|
|
|
_logger.LogError(ex, "Error deserializing {Path}.", dir);
|
|
|
|
{
|
|
|
|
|
|
|
|
targetAbi = _minimumVersion;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!Version.TryParse(manifest.Version, out version))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
manifest.Version = _minimumVersion.ToString();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new LocalPlugin(dir, _appVersion >= targetAbi, manifest);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// No metafile, so lets see if the folder is versioned.
|
|
|
|
if (manifest != null)
|
|
|
|
// TODO: Phase this support out in future versions.
|
|
|
|
{
|
|
|
|
metafile = dir.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries)[^1];
|
|
|
|
if (!Version.TryParse(manifest.TargetAbi, out var targetAbi))
|
|
|
|
int versionIndex = dir.LastIndexOf('_');
|
|
|
|
|
|
|
|
if (versionIndex != -1)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// Get the version number from the filename if possible.
|
|
|
|
targetAbi = _minimumVersion;
|
|
|
|
metafile = Path.GetFileName(dir[..versionIndex]) ?? dir[..versionIndex];
|
|
|
|
|
|
|
|
version = Version.TryParse(dir.AsSpan()[(versionIndex + 1)..], out Version? parsedVersion) ? parsedVersion : _appVersion;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
|
|
|
|
|
|
|
|
if (!Version.TryParse(manifest.Version, out version))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// Un-versioned folder - Add it under the path name and version it suitable for this instance.
|
|
|
|
manifest.Version = _minimumVersion.ToString();
|
|
|
|
version = _appVersion;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Auto-create a plugin manifest, so we can disable it, if it fails to load.
|
|
|
|
return new LocalPlugin(dir, _appVersion >= targetAbi, manifest);
|
|
|
|
manifest = new PluginManifest
|
|
|
|
}
|
|
|
|
{
|
|
|
|
|
|
|
|
Status = PluginStatus.Restart,
|
|
|
|
|
|
|
|
Name = metafile,
|
|
|
|
|
|
|
|
AutoUpdate = false,
|
|
|
|
|
|
|
|
Id = metafile.GetMD5(),
|
|
|
|
|
|
|
|
TargetAbi = _appVersion.ToString(),
|
|
|
|
|
|
|
|
Version = version.ToString()
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new LocalPlugin(dir, true, manifest);
|
|
|
|
// No metafile, so lets see if the folder is versioned.
|
|
|
|
|
|
|
|
// TODO: Phase this support out in future versions.
|
|
|
|
|
|
|
|
metafile = dir.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries)[^1];
|
|
|
|
|
|
|
|
int versionIndex = dir.LastIndexOf('_');
|
|
|
|
|
|
|
|
if (versionIndex != -1)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// Get the version number from the filename if possible.
|
|
|
|
|
|
|
|
metafile = Path.GetFileName(dir[..versionIndex]) ?? dir[..versionIndex];
|
|
|
|
|
|
|
|
version = Version.TryParse(dir.AsSpan()[(versionIndex + 1)..], out Version? parsedVersion) ? parsedVersion : _appVersion;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#pragma warning disable CA1031 // Do not catch general exception types
|
|
|
|
else
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
|
|
#pragma warning restore CA1031 // Do not catch general exception types
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
_logger.LogError(ex, "Something went wrong!");
|
|
|
|
// Un-versioned folder - Add it under the path name and version it suitable for this instance.
|
|
|
|
return null;
|
|
|
|
version = _appVersion;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Auto-create a plugin manifest, so we can disable it, if it fails to load.
|
|
|
|
|
|
|
|
manifest = new PluginManifest
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Status = PluginStatus.Restart,
|
|
|
|
|
|
|
|
Name = metafile,
|
|
|
|
|
|
|
|
AutoUpdate = false,
|
|
|
|
|
|
|
|
Id = metafile.GetMD5(),
|
|
|
|
|
|
|
|
TargetAbi = _appVersion.ToString(),
|
|
|
|
|
|
|
|
Version = version.ToString()
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new LocalPlugin(dir, true, manifest);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
@ -566,14 +555,9 @@ namespace Emby.Server.Implementations.Plugins
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var directories = Directory.EnumerateDirectories(_pluginsPath, "*.*", SearchOption.TopDirectoryOnly);
|
|
|
|
var directories = Directory.EnumerateDirectories(_pluginsPath, "*.*", SearchOption.TopDirectoryOnly);
|
|
|
|
LocalPlugin? entry;
|
|
|
|
|
|
|
|
foreach (var dir in directories)
|
|
|
|
foreach (var dir in directories)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
entry = LoadManifest(dir);
|
|
|
|
versions.Add(LoadManifest(dir));
|
|
|
|
if (entry != null)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
versions.Add(entry);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
string lastName = string.Empty;
|
|
|
|
string lastName = string.Empty;
|
|
|
@ -582,7 +566,7 @@ namespace Emby.Server.Implementations.Plugins
|
|
|
|
// The first item will be the latest version.
|
|
|
|
// The first item will be the latest version.
|
|
|
|
for (int x = versions.Count - 1; x >= 0; x--)
|
|
|
|
for (int x = versions.Count - 1; x >= 0; x--)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
entry = versions[x];
|
|
|
|
var entry = versions[x];
|
|
|
|
if (!string.Equals(lastName, entry.Name, StringComparison.OrdinalIgnoreCase))
|
|
|
|
if (!string.Equals(lastName, entry.Name, StringComparison.OrdinalIgnoreCase))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
entry.DllFiles.AddRange(Directory.EnumerateFiles(entry.Path, "*.dll", SearchOption.AllDirectories));
|
|
|
|
entry.DllFiles.AddRange(Directory.EnumerateFiles(entry.Path, "*.dll", SearchOption.AllDirectories));
|
|
|
|