using System; using System.IO; using System.IO.Compression; using System.Linq; using System.Threading.Tasks; namespace PluginManager.Others; public static class ArchiveManager { private static string? archiveFolder; public static bool isInitialized { get; private set; } public static void Initialize() { if (isInitialized) throw new Exception("ArchiveManager is already initialized"); if (!Config.Data.ContainsKey("ArchiveFolder")) Config.Data["ArchiveFolder"] = "./Data/PAKS/"; archiveFolder = Config.Data["ArchiveFolder"]; isInitialized = true; } /// /// Read data from a file that is inside an archive (ZIP format) /// /// The file name that is inside the archive or its full path /// The archive location from the PAKs folder /// A string that represents the content of the file or null if the file does not exists or it has no content public static async Task ReadFromPakAsync(string FileName, string archFile) { if (!isInitialized) throw new Exception("ArchiveManager is not initialized"); archFile = archiveFolder + archFile; if (!File.Exists(archFile)) throw new Exception("Failed to load file !"); try { string? textValue = null; using (var fs = new FileStream(archFile, FileMode.Open)) using (var zip = new ZipArchive(fs, ZipArchiveMode.Read)) { foreach (var entry in zip.Entries) if (entry.Name == FileName || entry.FullName == FileName) using (var s = entry.Open()) using (var reader = new StreamReader(s)) { textValue = await reader.ReadToEndAsync(); reader.Close(); s.Close(); fs.Close(); } } return textValue; } catch (Exception ex) { Config.Logger.Log(ex.Message, "Archive Manager", LogLevel.ERROR); // Write the error to a file await Task.Delay(100); return await ReadFromPakAsync(FileName, archFile); } } /// /// Extract zip to location /// /// The zip location /// The target location /// The progress that is updated as a file is processed /// The type of progress /// public static async Task ExtractArchive( string zip, string folder, IProgress progress, UnzipProgressType type) { if (!isInitialized) throw new Exception("ArchiveManager is not initialized"); Directory.CreateDirectory(folder); using (var archive = ZipFile.OpenRead(zip)) { if (type == UnzipProgressType.PERCENTAGE_FROM_NUMBER_OF_FILES) { var totalZIPFiles = archive.Entries.Count(); var currentZIPFile = 0; foreach (var entry in archive.Entries) { if (entry.FullName.EndsWith("/")) // it is a folder Directory.CreateDirectory(Path.Combine(folder, entry.FullName)); else try { entry.ExtractToFile(Path.Combine(folder, entry.FullName), true); } catch (Exception ex) { Config.Logger.Log($"Failed to extract {entry.Name}. Exception: {ex.Message}", "Archive Manager", LogLevel.ERROR); } currentZIPFile++; await Task.Delay(10); if (progress != null) progress.Report((float)currentZIPFile / totalZIPFiles * 100); } } else if (type == UnzipProgressType.PERCENTAGE_FROM_TOTAL_SIZE) { ulong zipSize = 0; foreach (var entry in archive.Entries) zipSize += (ulong)entry.CompressedLength; ulong currentSize = 0; foreach (var entry in archive.Entries) { if (entry.FullName.EndsWith("/")) { Directory.CreateDirectory(Path.Combine(folder, entry.FullName)); continue; } try { entry.ExtractToFile(Path.Combine(folder, entry.FullName), true); currentSize += (ulong)entry.CompressedLength; } catch (Exception ex) { Config.Logger.Log($"Failed to extract {entry.Name}. Exception: {ex.Message}", "Archive Manager", LogLevel.ERROR); } await Task.Delay(10); if (progress != null) progress.Report((float)currentSize / zipSize * 100); } } } } }