public byte[] PeekHeader(int length) { GKZipFile.DebugLog($"Extracting {Name} to memory"); if (FileEntryOffset == null) { GetFileEntryOffset(); } using (var fs = new FileStream(Parent.ZIPPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { fs.Seek(FileEntryOffset.Value + 26, SeekOrigin.Begin); var lengthBytes = new byte[4]; fs.Read(lengthBytes, 0, 4); var n = BitConverter.ToInt16(lengthBytes, 0); var m = BitConverter.ToInt16(lengthBytes, 2); var targetOffset = FileEntryOffset.Value + 30 + n + m; GKZipFile.DebugLog($"Seeking to {targetOffset} ({FileEntryOffset} + 30 + {n} + {m}"); fs.Seek(targetOffset, SeekOrigin.Begin); using (var outputStream = new MemoryStream()) { if (CompressionMethod > 0x0) { GKZipFile.DebugLog("Passing file through DeflateStream as CompressionMethod is > 0x0"); using (var contentStream = new MemoryStream()) { contentStream.SetLength(CompressedSize); fs.Read(contentStream.GetBuffer(), 0, CompressedSize); // contentStream now has *just* our compressed file, so we can use a deflatestream and target it using (var decompStream = new DeflateStream(contentStream, CompressionMode.Decompress)) { var buffer = new byte[length]; decompStream.Read(buffer, 0, length); outputStream.Write(buffer, 0, length); } } } else { var buff = new byte[length]; fs.Read(buff, 0, length); outputStream.Write(buff, 0, length); } outputStream.Flush(); outputStream.Close(); return(outputStream.ToArray()); } } }
/// <summary> /// In batch extraction, we provide a list of input files to search and perform extractions from based on a predicate. /// </summary> /// <param name="inputFiles"></param> /// <param name="outputDirectoryPath"></param> /// <param name="predicate"></param> static public void BatchExtract(string[] inputFiles, string outputDirectoryPath, Func <CDEntry, bool> predicate) { var outputDirectory = default(DirectoryInfo); if (!Directory.Exists(outputDirectoryPath)) { outputDirectory = Directory.CreateDirectory(outputDirectoryPath); } else { outputDirectory = new DirectoryInfo(outputDirectoryPath); } var activeTasks = new List <Task>(); foreach (var item in inputFiles) { var inputFile = new FileInfo(item); var match = Regex.Match(inputFile.Name, @"(?<udid>[\w\W]*?)_files\.zip"); if (!match.Success) { throw new Exception($"Is this even a GK Zip? {inputFile.Name}"); } var udid = match.Groups["udid"].Value; Directory.CreateDirectory(outputDirectory.FullName + "\\" + udid); activeTasks.Add(Task.Factory.StartNew(() => { var gkz = new GKZipFile(item, false); var sw = new Stopwatch(); sw.Start(); GKZipFile.DebugLog($"Starting item with udid {udid} {item}"); var reviewedEntries = 0; foreach (var entry in gkz) { if (predicate(entry)) { entry.ExtractToFolder(outputDirectory.FullName + "\\" + udid + "\\"); GKZipFile.DebugLog($"Extracted {entry.Name} to .\\{udid}"); } reviewedEntries++; } sw.Stop(); GKZipFile.DebugLog($"({udid}) - Work completed in {sw.ElapsedMilliseconds}ms ({reviewedEntries} entries)"); })); } Task.WaitAll(activeTasks.ToArray()); }
/// <summary> /// This only works if we've populated our CentralDirectory property (set the second parameter of parse call to true) /// </summary> /// <returns>Successful or not</returns> public bool GetFileEntryOffset() { if (FileEntryOffset != null) { return(true); } CompressedSize = BitConverter.ToInt32(Parent.CentralDirectory, (int)RelativeOffset + 20); UncompressedSize = BitConverter.ToInt32(Parent.CentralDirectory, (int)RelativeOffset + 24); var cur = 0; var bFound = false; while (cur < LengthExtraFieldM) { var relPos = (int)RelativeOffset + 46 + LengthFileNameN; var length = BitConverter.ToInt16(Parent.CentralDirectory, cur + relPos + 2); if (Parent.CentralDirectory[relPos + cur] == 0x1 && Parent.CentralDirectory[relPos + cur + 1] == 0x00) { FileEntryOffset = BitConverter.ToInt64(Parent.CentralDirectory, cur + relPos + 4); bFound = true; } cur += length + 4; } GKZipFile.DebugLog($"RE: {Name}"); if (!bFound) { FileEntryOffset = (long)BitConverter.ToUInt32(Parent.CentralDirectory, (int)RelativeOffset + 42); GKZipFile.DebugLog($"File absolute offset is (loop failed; fallback value): {FileEntryOffset}"); return(false); } else { GKZipFile.DebugLog($"File absolute offset is {FileEntryOffset}"); return(true); } }
public byte[] ExtractToMemory() { GKZipFile.DebugLog($"Extracting {Name} to memory"); if (FileEntryOffset == null) { GetFileEntryOffset(); } using (var fs = new FileStream(Parent.ZIPPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { fs.Seek(FileEntryOffset.Value + 26, SeekOrigin.Begin); var lengthBytes = new byte[4]; fs.Read(lengthBytes, 0, 4); var n = BitConverter.ToInt16(lengthBytes, 0); var m = BitConverter.ToInt16(lengthBytes, 2); var targetOffset = FileEntryOffset.Value + 30 + n + m; GKZipFile.DebugLog($"Seeking to {targetOffset} ({FileEntryOffset} + 30 + {n} + {m}"); fs.Seek(targetOffset, SeekOrigin.Begin); using (var outputStream = new MemoryStream()) { if (CompressionMethod > 0x0) { GKZipFile.DebugLog("Passing file through DeflateStream as CompressionMethod is > 0x0"); using (var contentStream = new MemoryStream()) { contentStream.SetLength(CompressedSize); fs.Read(contentStream.GetBuffer(), 0, CompressedSize); // contentStream now has *just* our compressed file, so we can use a deflatestream and target it using (var decompStream = new DeflateStream(contentStream, CompressionMode.Decompress)) { var bytesRead = 0; //var offset = 0; var bytesToRead = 2048; var buffer = new byte[bytesToRead]; var totalBytesRead = 0; while (true) { bytesRead = decompStream.Read(buffer, 0, bytesToRead); if (bytesRead == 0) { break; } outputStream.Write(buffer, 0, bytesRead); totalBytesRead += bytesRead; } } } } else { var bytesToRead = 2048; var buffer = new byte[bytesToRead]; var totalBytesRead = 0; while (totalBytesRead < CompressedSize) { if (totalBytesRead + bytesToRead > CompressedSize) { bytesToRead = CompressedSize - totalBytesRead; buffer = new byte[bytesToRead]; // adjust the length of the buffer } fs.Read(buffer, 0, bytesToRead); outputStream.Write(buffer, 0, bytesToRead); totalBytesRead += bytesToRead; } } outputStream.Flush(); outputStream.Close(); return(outputStream.ToArray()); } fs.Close(); } }