public FileStructureExtraData(Stream stream, CustomBinaryReader reader, int extra_length) { var end = stream.Position + extra_length; _UnknownID = reader.ReadInt16(); StructureSizeAfterHeader = reader.ReadInt16(); UncompressedFileLength = reader.ReadInt32(); _UnknownD = reader.ReadInt32(); CompressedFileLength = reader.ReadInt32(); _UnknownF = reader.ReadInt32(); var data_offset_ldword = (Int64)reader.ReadUInt32(); var data_offset_hdword = (Int64)reader.ReadUInt32(); DataOffset = data_offset_ldword + (data_offset_hdword << 32); _UnknownG = reader.ReadInt32(); _Timestamp_Maybe_But_Not_Sure = reader.ReadInt32(); // here be demons and lots of padding // make sure we read this to ensure the stream position is correct var padding_length = end - stream.Position; var data = reader.ReadBytes((int)padding_length); if (stream.Position % 0x1000 != 0) { throw new Exception("File Data Section Alignment Error (End Extra Read)"); } FileDataOffset = stream.Position; }
void PopulateDirectory(FileStream stream, CustomBinaryReader reader, CentralDirectoryLocator central_directory_locator) { long central_directory_base_offset = central_directory_locator.ContentDirectoryOffset; stream.Position = central_directory_base_offset; byte[] central_directory_data = reader.ReadBytes(central_directory_locator.ContentDictionarySize); using (MemoryStream central_directory_stream = new MemoryStream(central_directory_data)) using (CustomBinaryReader central_directory_reader = new CustomBinaryReader(central_directory_stream)) { // rebase current offset to 0 because we've copied data to a relative stream long central_directory_current_offset = 0; content_dictionary_count = central_directory_locator.DontentDictionaryCount; for (int i = 0; i < central_directory_locator.DontentDictionaryCount; i++) { var central_directory = ReadPK(central_directory_stream, central_directory_reader, central_directory_current_offset) as CentralDirectory; central_directory_current_offset = central_directory_stream.Position; //TODO async query //var file_structure = ReadPK(stream, reader, central_directory.extra.data_offset) as FileStructure; Files[central_directory.Filename] = new P4KFile(this, central_directory); //var file_data = ReadDataFromFileSection(stream, reader, file_offset.extra.file_data_offset, file_offset.extra.file_data_length); /*if(PopulateDirectoryCallbackFunc != null) * { * PopulateDirectoryCallbackFunc(i, central_directory_locator.content_dictionary_count); * }*/ current_index = i; } } }
public Mutex GetStream(out FileStream stream, out CustomBinaryReader reader, out CustomBinaryWriter writer) { mutex.WaitOne(); stream = this.fileStream; reader = this.customBinaryReader; writer = this.customBinaryWriter; return(mutex); }
public void Initialize(string filename, bool readOnly, bool logging = false) { Filename = filename; Logging = logging; mutex = new Mutex(); if (readOnly) { ReadOnly = true; fileStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); } else { try { ReadOnly = false; fileStream = File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None); } catch (IOException) { ReadOnly = true; fileStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); } } try { mutex.WaitOne(); customBinaryReader = new CustomBinaryReader(fileStream); customBinaryWriter = ReadOnly ? null : new CustomBinaryWriter(fileStream); var offset_central_directory_end = FindEndCentralDirectoryOffset(fileStream, customBinaryReader); central_directory_end = ReadPK(fileStream, customBinaryReader, offset_central_directory_end) as CentralDirectoryEnd; var offset_central_directory_locator_offset = offset_central_directory_end - 0x14; central_directory_locator_offset = ReadPK(fileStream, customBinaryReader, offset_central_directory_locator_offset) as CentralDirectoryLocatorOffset; var offset_central_directory_locator = central_directory_locator_offset.DirectoryLocatorOffset; central_directory_locator = ReadPK(fileStream, customBinaryReader, offset_central_directory_locator) as CentralDirectoryLocator; PopulateDirectory(fileStream, customBinaryReader, central_directory_locator); } finally { mutex.ReleaseMutex(); } if (Logging) { Console.WriteLine($"Finished loading {filename}"); } }
public static byte[] ReadDataFromFileSection(FileStream stream, CustomBinaryReader reader, Int64 offset, int size) { stream.Position = offset; if (offset % 0x1000 != 0) { throw new Exception("File data alignment error"); } return(reader.ReadBytes(size)); }
public CentralDirectoryEnd(Stream stream, CustomBinaryReader reader) { DiskNumber = reader.ReadInt16(); DiskNumberWithCD = reader.ReadInt16(); DiskEntries = reader.ReadInt16(); TotalEntries = reader.ReadInt16(); CentralDirectorySize = reader.ReadInt32(); OffsetOfCdStartingDisk = reader.ReadInt32(); CommentLength = reader.ReadInt16(); Comment = reader.ReadString(CommentLength); }
static long FindEndCentralDirectoryOffset(FileStream stream, CustomBinaryReader reader) { // last PK must be within 0x1000 alignment, worst case scenario long length = Math.Min(stream.Length, 0x2000L); stream.Position = stream.Length - length; byte[] data = reader.ReadBytes((int)length); byte[] end_central_directory_magic = { 0x50, 0x4B, 0x05, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; long current_offset = length - end_central_directory_magic.LongLength; bool found = true; for (; current_offset > 0; current_offset--) { found = true; for (long magic_index = 0; magic_index < end_central_directory_magic.LongLength; magic_index++) { if (data[current_offset + magic_index] != end_central_directory_magic[magic_index]) { found = false; break; } } if (found) { break; } } if (!found) { throw new Exception("Couldn't find CentralDirectoryEnd"); } long offset_from_eof = length - current_offset; stream.Position = stream.Length - offset_from_eof; return(stream.Position); }
public CentralDirectoryLocator(Stream stream, CustomBinaryReader reader) { unknownA = reader.ReadInt32(); unknownB = reader.ReadInt32(); unknownC = reader.ReadInt16(); unknownD = reader.ReadInt16(); unknownE = reader.ReadInt32(); unknownF = reader.ReadInt32(); DontentDictionaryCount = reader.ReadInt32(); unknownG = reader.ReadInt32(); ContentDictionaryCount2 = reader.ReadInt32(); unknownH = reader.ReadInt32(); ContentDictionarySize = reader.ReadInt32(); unknownI = reader.ReadInt32(); ContentDirectoryOffset = reader.ReadInt64(); }
public FileStructure(Stream stream, CustomBinaryReader reader) { if ((stream.Position - 4) % 0x1000 != 0) { throw new Exception("File Data Section Alignment Error (Pre Read)"); } Version = reader.ReadInt16(); Flags = reader.ReadInt16(); CompressionMode = (FileCompressionMode)reader.ReadInt16(); ModificationTime = reader.ReadUInt16(); ModificationDate = reader.ReadUInt16(); CRC32 = reader.ReadInt32(); CompressedSize = reader.ReadInt32(); UncompressedSize = reader.ReadInt32(); FilenameLength = reader.ReadInt16(); ExtraLength = reader.ReadInt16(); Filename = reader.ReadString(FilenameLength); Extra = new FileStructureExtraData(stream, reader, ExtraLength); }
public void WriteContentDirectoryChunk(FileStream stream, CustomBinaryReader reader, CustomBinaryWriter writer) { stream.Position = central_directory_locator.ContentDirectoryOffset; var cd_chunk = CreateCentralDirectoryChunk(); writer.Write(cd_chunk); central_directory_locator.ContentDictionarySize = cd_chunk.Length; central_directory_locator.DontentDictionaryCount = Files.Count; central_directory_locator.ContentDictionaryCount2 = Files.Count; central_directory_locator_offset.DirectoryLocatorOffset = stream.Position; byte[] locator_bytes = this.central_directory_locator.CreateBinaryData(true); byte[] locator_offset_bytes = this.central_directory_locator_offset.CreateBinaryData(true); byte[] cd_end_bytes = this.central_directory_end.CreateBinaryData(true); writer.Write(locator_bytes); writer.Write(locator_offset_bytes); writer.Write(cd_end_bytes); }
public object ReadPK(Stream stream, CustomBinaryReader reader, Int64 offset) { stream.Seek(offset, SeekOrigin.Begin); var magic = reader.ReadInt16(); if (magic != 0x4B50) { throw new Exception("Invalid PK offset"); } Signature signature = (Signature)reader.ReadInt16(); switch (signature) { case Signature.CentralDirectory: CentralDirectory centralDirectory = new CentralDirectory(stream, reader); if (Logging) { Console.WriteLine($"Found CentralDirectory {centralDirectory.Filename}"); } if (Logging) { Console.WriteLine($"Searching for FileStructure @{centralDirectory.Extra.data_offset.ToString("X")}"); } return(centralDirectory); case Signature.FileStructure: FileStructure fileStructure = new FileStructure(stream, reader); if (Logging) { Console.WriteLine($"Found FileStructure {fileStructure.Filename}"); } return(fileStructure); case Signature.CentralDirectoryLocator: CentralDirectoryLocator centralDirectoryLocator = new CentralDirectoryLocator(stream, reader); if (Logging) { Console.WriteLine($"Found CentralDirectoryLocator @{offset}"); } return(centralDirectoryLocator); case Signature.CentralDirectoryLocatorOffset: CentralDirectoryLocatorOffset centralDirectoryLocatorOffset = new CentralDirectoryLocatorOffset(stream, reader); if (Logging) { Console.WriteLine($"Found CentralDirectoryLocatorOffset @{offset}"); } return(centralDirectoryLocatorOffset); case Signature.CentralDirectoryEnd: CentralDirectoryEnd centralDirectoryEnd = new CentralDirectoryEnd(stream, reader); if (Logging) { Console.WriteLine($"Found CentralDirectoryEnd @{offset}"); } return(centralDirectoryEnd); default: throw new NotImplementedException(); } }
public CentralDirectoryLocatorOffset(Stream stream, CustomBinaryReader reader) { unknownA = reader.ReadInt32(); DirectoryLocatorOffset = reader.ReadInt64(); unknownB = reader.ReadInt32(); }