From 8d193a63cdc43f5dd38a43c4ed2b33735d313382 Mon Sep 17 00:00:00 2001 From: Rudolf Kolbe Date: Mon, 27 Dec 2021 08:59:18 +0100 Subject: [PATCH] Zip (including APK) Loading (#902) * load ZipFile makes it possible to directly load apk files * use LoadFile for recursive zip opening * set System.IO.Compression version * keep identical format in AssetStudio.csproj * try/catch the loading of each zip entry * remove extra new line in FileReader.cs * apply requested changes --- AssetStudio/AssetStudio.csproj | 1 + AssetStudio/AssetsManager.cs | 46 ++++++++++++++++++++++++++++++++++ AssetStudio/FileReader.cs | 13 ++++++---- AssetStudio/FileType.cs | 3 ++- 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/AssetStudio/AssetStudio.csproj b/AssetStudio/AssetStudio.csproj index e821b3c..850a85a 100644 --- a/AssetStudio/AssetStudio.csproj +++ b/AssetStudio/AssetStudio.csproj @@ -14,6 +14,7 @@ + diff --git a/AssetStudio/AssetsManager.cs b/AssetStudio/AssetsManager.cs index 8c69d89..818e35e 100644 --- a/AssetStudio/AssetsManager.cs +++ b/AssetStudio/AssetsManager.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Linq; using System.Text; using static AssetStudio.ImportHelper; @@ -84,6 +85,9 @@ namespace AssetStudio case FileType.BrotliFile: LoadFile(DecompressBrotli(reader)); break; + case FileType.ZipFile: + LoadZipFile(reader); + break; } } @@ -234,6 +238,48 @@ namespace AssetStudio } } + private void LoadZipFile(FileReader reader) + { + Logger.Info("Loading " + reader.FileName); + try + { + using (ZipArchive archive = new ZipArchive(reader.BaseStream, ZipArchiveMode.Read)) + { + foreach (ZipArchiveEntry entry in archive.Entries) + { + try + { + string dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), reader.FileName, entry.FullName); + // create a new stream + // - to store the deflated stream in + // - to keep the data for later extraction + Stream streamReader = new MemoryStream(); + using (Stream entryStream = entry.Open()) + { + entryStream.CopyTo(streamReader); + } + streamReader.Position = 0; + + FileReader entryReader = new FileReader(dummyPath, streamReader); + LoadFile(entryReader); + } + catch (Exception e) + { + Logger.Error($"Error while reading zip entry {entry.FullName}", e); + } + } + } + } + catch (Exception e) + { + Logger.Error($"Error while reading zip file {reader.FileName}", e); + } + finally + { + reader.Dispose(); + } + } + public void CheckStrippedVersion(SerializedFile assetsFile) { if (assetsFile.IsVersionStripped && string.IsNullOrEmpty(SpecifyUnityVersion)) diff --git a/AssetStudio/FileReader.cs b/AssetStudio/FileReader.cs index 59ea66f..61426b4 100644 --- a/AssetStudio/FileReader.cs +++ b/AssetStudio/FileReader.cs @@ -11,6 +11,8 @@ namespace AssetStudio private static readonly byte[] gzipMagic = { 0x1f, 0x8b }; private static readonly byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 }; + private static readonly byte[] zipMagic = { 0x50, 0x4B, 0x03, 0x04 }; + private static readonly byte[] zipSpannedMagic = { 0x50, 0x4B, 0x07, 0x08 }; public FileReader(string path) : this(path, File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { } @@ -36,7 +38,7 @@ namespace AssetStudio return FileType.WebFile; default: { - var magic = ReadBytes(2); + byte[] magic = ReadBytes(2); Position = 0; if (gzipMagic.SequenceEqual(magic)) { @@ -53,10 +55,11 @@ namespace AssetStudio { return FileType.AssetsFile; } - else - { - return FileType.ResourceFile; - } + magic = ReadBytes(4); + Position = 0; + if (zipMagic.SequenceEqual(magic) || zipSpannedMagic.SequenceEqual(magic)) + return FileType.ZipFile; + return FileType.ResourceFile; } } } diff --git a/AssetStudio/FileType.cs b/AssetStudio/FileType.cs index 04fb30d..f803e97 100644 --- a/AssetStudio/FileType.cs +++ b/AssetStudio/FileType.cs @@ -13,6 +13,7 @@ namespace AssetStudio WebFile, ResourceFile, GZipFile, - BrotliFile + BrotliFile, + ZipFile } }