Example #1
0
            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;
            }
Example #2
0
        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;
                    }
                }
        }
Example #3
0
        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);
        }
Example #4
0
        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}");
            }
        }
Example #5
0
        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);
 }
Example #7
0
        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();
 }
Example #9
0
        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);
        }
Example #10
0
        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);
        }
Example #11
0
        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();
            }
        }
Example #12
0
 public CentralDirectoryLocatorOffset(Stream stream, CustomBinaryReader reader)
 {
     unknownA = reader.ReadInt32();
     DirectoryLocatorOffset = reader.ReadInt64();
     unknownB = reader.ReadInt32();
 }