Add support for ZIP plugin archives

Most code from @cvium. Also removes the lazy and ill-conceived GUID-
based checksumming, which just died with ZIP archives.
This commit is contained in:
Joshua Boniface 2019-02-10 17:29:55 -05:00
parent bcb32ec6ad
commit 2f4a00d322
2 changed files with 27 additions and 27 deletions

View File

@ -564,7 +564,7 @@ namespace Emby.Server.Implementations
{ {
try try
{ {
var assembly = Assembly.Load(File.ReadAllBytes(file)); var assembly = Assembly.LoadFrom(file);
return new Tuple<Assembly, string>(assembly, file); return new Tuple<Assembly, string>(assembly, file);
} }
@ -777,12 +777,12 @@ namespace Emby.Server.Implementations
SocketFactory = new SocketFactory(); SocketFactory = new SocketFactory();
RegisterSingleInstance(SocketFactory); RegisterSingleInstance(SocketFactory);
InstallationManager = new InstallationManager(LoggerFactory, this, ApplicationPaths, HttpClient, JsonSerializer, ServerConfigurationManager, FileSystemManager, CryptographyProvider, PackageRuntime);
RegisterSingleInstance(InstallationManager);
ZipClient = new ZipClient(FileSystemManager); ZipClient = new ZipClient(FileSystemManager);
RegisterSingleInstance(ZipClient); RegisterSingleInstance(ZipClient);
InstallationManager = new InstallationManager(LoggerFactory, this, ApplicationPaths, HttpClient, JsonSerializer, ServerConfigurationManager, FileSystemManager, CryptographyProvider, ZipClient, PackageRuntime);
RegisterSingleInstance(InstallationManager);
HttpResultFactory = new HttpResultFactory(LoggerFactory, FileSystemManager, JsonSerializer, CreateBrotliCompressor()); HttpResultFactory = new HttpResultFactory(LoggerFactory, FileSystemManager, JsonSerializer, CreateBrotliCompressor());
RegisterSingleInstance(HttpResultFactory); RegisterSingleInstance(HttpResultFactory);
@ -1603,7 +1603,7 @@ namespace Emby.Server.Implementations
{ {
try try
{ {
return FilterAssembliesToLoad(Directory.EnumerateFiles(path, "*.dll", SearchOption.TopDirectoryOnly)) return FilterAssembliesToLoad(Directory.EnumerateFiles(path, "*.dll", SearchOption.AllDirectories))
.Select(LoadAssembly) .Select(LoadAssembly)
.Where(a => a != null) .Where(a => a != null)
.ToList(); .ToList();

View File

@ -116,6 +116,7 @@ namespace Emby.Server.Implementations.Updates
private readonly IApplicationHost _applicationHost; private readonly IApplicationHost _applicationHost;
private readonly ICryptoProvider _cryptographyProvider; private readonly ICryptoProvider _cryptographyProvider;
private readonly IZipClient _zipClient;
// netframework or netcore // netframework or netcore
private readonly string _packageRuntime; private readonly string _packageRuntime;
@ -129,6 +130,7 @@ namespace Emby.Server.Implementations.Updates
IServerConfigurationManager config, IServerConfigurationManager config,
IFileSystem fileSystem, IFileSystem fileSystem,
ICryptoProvider cryptographyProvider, ICryptoProvider cryptographyProvider,
IZipClient zipClient,
string packageRuntime) string packageRuntime)
{ {
if (loggerFactory == null) if (loggerFactory == null)
@ -146,6 +148,7 @@ namespace Emby.Server.Implementations.Updates
_config = config; _config = config;
_fileSystem = fileSystem; _fileSystem = fileSystem;
_cryptographyProvider = cryptographyProvider; _cryptographyProvider = cryptographyProvider;
_zipClient = zipClient;
_packageRuntime = packageRuntime; _packageRuntime = packageRuntime;
_logger = loggerFactory.CreateLogger(nameof(InstallationManager)); _logger = loggerFactory.CreateLogger(nameof(InstallationManager));
} }
@ -527,13 +530,19 @@ namespace Emby.Server.Implementations.Updates
private async Task PerformPackageInstallation(IProgress<double> progress, string target, PackageVersionInfo package, CancellationToken cancellationToken) private async Task PerformPackageInstallation(IProgress<double> progress, string target, PackageVersionInfo package, CancellationToken cancellationToken)
{ {
// Target based on if it is an archive or single assembly // Target based on if it is an archive or single assembly
// zip archives are assumed to contain directory structures relative to our ProgramDataPath
var extension = Path.GetExtension(package.targetFilename); var extension = Path.GetExtension(package.targetFilename);
var isArchive = string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase) || string.Equals(extension, ".rar", StringComparison.OrdinalIgnoreCase) || string.Equals(extension, ".7z", StringComparison.OrdinalIgnoreCase); var isArchive = string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase);
if (target == null) if (target == null)
{ {
target = Path.Combine(isArchive ? _appPaths.TempUpdatePath : _appPaths.PluginsPath, package.targetFilename); if (isArchive)
{
target = Path.Combine(_appPaths.PluginsPath, Path.GetFileNameWithoutExtension(package.targetFilename));
}
else
{
target = Path.Combine(_appPaths.PluginsPath, package.targetFilename);
}
} }
// Download to temporary file so that, if interrupted, it won't destroy the existing installation // Download to temporary file so that, if interrupted, it won't destroy the existing installation
@ -547,31 +556,22 @@ namespace Emby.Server.Implementations.Updates
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
// Validate with a checksum // TODO: Validate with a checksum, *properly*
var packageChecksum = string.IsNullOrWhiteSpace(package.checksum) ? Guid.Empty : new Guid(package.checksum);
if (!packageChecksum.Equals(Guid.Empty)) // support for legacy uploads for now
{
using (var stream = File.OpenRead(tempFile))
{
var check = Guid.Parse(BitConverter.ToString(_cryptographyProvider.ComputeMD5(stream)).Replace("-", string.Empty));
if (check != packageChecksum)
{
throw new Exception(string.Format("Download validation failed for {0}. Probably corrupted during transfer.", package.name));
}
}
}
cancellationToken.ThrowIfCancellationRequested();
// Success - move it to the real target // Success - move it to the real target
try try
{ {
Directory.CreateDirectory(Path.GetDirectoryName(target));
File.Copy(tempFile, target, true);
//If it is an archive - write out a version file so we know what it is
if (isArchive) if (isArchive)
{ {
File.WriteAllText(target + ".ver", package.versionStr); using (var stream = File.OpenRead(tempFile))
{
_zipClient.ExtractAllFromZip(stream, target, true);
}
}
else
{
Directory.CreateDirectory(Path.GetDirectoryName(target));
File.Copy(tempFile, target, true);
} }
} }
catch (IOException ex) catch (IOException ex)