/* Copyright (C) 2019 erri120 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* * This file contains parts of the Oblivion Mod Manager licensed under GPLv2 * and has been modified for use in this OMODFramework * Original source: https://www.nexusmods.com/oblivion/mods/2097 * GPLv2: https://opensource.org/licenses/gpl-2.0.php */ using System; using System.Collections.Generic; using System.IO; using System.Text; using ICSharpCode.SharpZipLib.Zip; namespace OMODExtraction { public class OMOD { protected class PrivateData { internal ZipFile ModFile; } private PrivateData _pD = new PrivateData(); public readonly string FilePath; public readonly string FileName; public readonly string LowerFileName; public string FullFilePath => Path.Combine(FilePath, FileName); public readonly CompressionType Compression; private ZipFile ModFile { get { if (_pD.ModFile != null) return _pD.ModFile; _pD.ModFile = new ZipFile(FullFilePath); return _pD.ModFile; } } public OMOD(string path) { if (!File.Exists(path)) throw new Framework.OMODFrameworkException($"The provided file at {path} does not exists!"); FilePath = Path.GetDirectoryName(path); FileName = Path.GetFileName(path); LowerFileName = FileName?.ToLower(); using (var configStream = ExtractWholeFile("config")) { if (configStream == null) throw new Framework.OMODFrameworkException($"Could not find the configuration data for {FileName} !"); using (var br = new BinaryReader(configStream)) { var fileVersion = br.ReadByte(); br.ReadString(); //mod name br.ReadInt32(); // major version br.ReadInt32(); // minor version br.ReadString(); // author br.ReadString(); // email br.ReadString(); // website br.ReadString(); // description if (fileVersion >= 2) br.ReadInt64(); else br.ReadString(); Compression = (CompressionType)br.ReadByte(); } } Close(); } public void Close() { _pD.ModFile?.Close(); _pD.ModFile = null; } public string ExtractPlugins() { return ParseCompressedStream("plugins.crc", "plugins"); } public string ExtractDataFiles() { return ParseCompressedStream("data.crc", "data"); } private string ParseCompressedStream(string dataInfo, string dataCompressed) { var infoStream = ExtractWholeFile(dataInfo); if (infoStream == null) return null; var compressedStream = ExtractWholeFile(dataCompressed); var path = CompressionHandler.DecompressFiles(infoStream, compressedStream, Compression); infoStream.Close(); compressedStream.Close(); return path; } private Stream ExtractWholeFile(string s) { string s2 = null; return ExtractWholeFile(s, ref s2); } private Stream ExtractWholeFile(string s, ref string path) { var ze = ModFile.GetEntry(s); return ze == null ? null : ExtractWholeFile(ze, ref path); } private Stream ExtractWholeFile(ZipEntry ze, ref string path) { var file = ModFile.GetInputStream(ze); Stream tempStream; if (path != null || ze.Size > Framework.MaxMemoryStreamSize) tempStream = Utils.CreateTempFile(out path); else tempStream = new MemoryStream((int)ze.Size); byte[] buffer = new byte[4096]; int i; while ((i = file.Read(buffer, 0, 4096)) > 0) tempStream.Write(buffer, 0, i); tempStream.Position = 0; return tempStream; } } }