using System; using System.IO; using System.IO.Compression; using System.Net.Http; using System.Threading; using System.Threading.Tasks; namespace Artemis.Core { /// /// Represents a plugin prerequisite action that extracts a ZIP file /// public class ExtractArchiveAction : PluginPrerequisiteAction { /// /// Creates a new instance of . /// /// The name of the action /// The ZIP file to extract /// The folder into which to extract the file public ExtractArchiveAction(string name, string fileName, string target) : base(name) { FileName = fileName ?? throw new ArgumentNullException(nameof(fileName)); Target = target ?? throw new ArgumentNullException(nameof(target)); ShowProgressBar = true; } /// /// Gets the file to extract /// public string FileName { get; } /// /// Gets the folder into which to extract the file /// public string Target { get; } /// public override async Task Execute(CancellationToken cancellationToken) { using HttpClient client = new(); ShowSubProgressBar = true; Status = $"Extracting {FileName}"; Utilities.CreateAccessibleDirectory(Target); await using (FileStream fileStream = new(FileName, FileMode.Open)) { ZipArchive archive = new(fileStream); long count = 0; foreach (ZipArchiveEntry entry in archive.Entries) { await using Stream unzippedEntryStream = entry.Open(); Progress.Report((count, archive.Entries.Count)); if (entry.Length > 0) { string path = Path.Combine(Target, entry.FullName); CreateDirectoryForFile(path); await using Stream extractStream = new FileStream(path, FileMode.OpenOrCreate); await unzippedEntryStream.CopyToAsync(entry.Length, extractStream, SubProgress, cancellationToken); } count++; } } Progress.Report((1, 1)); ShowSubProgressBar = false; Status = "Finished extracting"; } private static void CreateDirectoryForFile(string path) { string? directory = Path.GetDirectoryName(path); if (directory == null) throw new ArtemisCoreException($"Failed to get directory from path {path}"); Utilities.CreateAccessibleDirectory(directory); } } }