public BundleList ReadBundleList(string listName) { List <SuperBundle> listOfBundles = new List <SuperBundle>(); string[] compare = new string[] { "bundles", "chunks", "ebx", "res", "chunkMeta", "dbx" }; if (!compare.Contains(listName)) { throw new InvalidDataException("Unknown list type."); } int limit = Read7BitEncodedInt(); long startPosition = BaseStream.Position; while (BaseStream.Position < startPosition + limit) { SuperBundle currentBundle = ReadTableOfContentsPayload(); if (currentBundle != null) { listOfBundles.Add(currentBundle); } } BundleList bundleList = new BundleList(); bundleList.Name = listName; bundleList.Bundles = listOfBundles; bundleList.Limit = limit; return(bundleList); }
public static Int32 Chunk(BinaryWriter writer, SuperBundle superBundle) { Int32 totalFileSize = 0; UInt32 uncompressedFileSize = (UInt32) new FileInfo(superBundle.Changed).Length; using (BinaryReader changedFileReader = new BinaryReader(File.Open(superBundle.Changed, FileMode.Open))) { byte[] inBuffer; byte[] outBuffer = new byte[UInt16.MaxValue * 2]; UInt32 maximalUncompressedChunkSize = UInt16.MaxValue + 1; for (UInt32 currentPosition = 0; currentPosition < uncompressedFileSize; currentPosition += maximalUncompressedChunkSize) { UInt32 uncompressedChunkSize = uncompressedFileSize - currentPosition; if (uncompressedChunkSize > maximalUncompressedChunkSize) { uncompressedChunkSize = maximalUncompressedChunkSize; } inBuffer = changedFileReader.ReadBytes((int)uncompressedChunkSize); int compressedChunkSize = CompressionStrategy.Compress(inBuffer, outBuffer, (int)uncompressedChunkSize); writer.WriteUInt32BE(uncompressedChunkSize); totalFileSize += 8; // store uncompressed if (compressedChunkSize > uncompressedChunkSize) { writer.Write((byte)0); writer.Write((byte)0x71); writer.Write((UInt16)0); writer.Write(inBuffer); totalFileSize += (int)uncompressedChunkSize; } // store compressed else { writer.Write(CompressionStrategy.CompressionSignature); writer.Write((byte)0x70); writer.WriteUInt16BE((UInt16)compressedChunkSize); writer.Write(outBuffer, 0, compressedChunkSize); totalFileSize += compressedChunkSize; } } } return(totalFileSize); }
public void ResolveNewFiles(string tableOfContentsName, string directory) { FileInfo[] files = new DirectoryInfo(directory).GetFiles("*", SearchOption.AllDirectories); foreach (FileInfo file in files) { string[] pathLayers = Regex.Split(file.FullName.Substring(directory.Length), "(?:(bundles)|(chunks)|(ebx)|(res)|(chunkMeta)|(dbx))\\\\").Select(substring => substring.Trim('\\').Replace('\\', '/')).Where(_ => !String.IsNullOrEmpty(_)).ToArray(); BundleList bundleList = myTableOfContents.Payload.BundleCollections.SingleOrDefault(_ => _.Name == pathLayers[0]); if (bundleList != null) { SuperBundle correspondingBundle = null; // no indirection if (pathLayers.Length == 2) { correspondingBundle = bundleList.Bundles.SingleOrDefault(bundle => ((byte[])bundle.Properties["id"].Value).SequenceEqual(Helpers.StringToByteArray(pathLayers[1]))); } // indirection else { IEnumerable <SuperBundle> superBundles = bundleList.Bundles .Where(bundle => (string)bundle.Properties["id"].Value == pathLayers[1].Replace("_Dq_", ":")); if (superBundles != null) { BundleList indirectBundleList = superBundles.SelectMany(bundle => bundle.Indirection.BundleCollections .Where(list => list.Name == pathLayers[2])) .SingleOrDefault(); if (indirectBundleList != null) { correspondingBundle = indirectBundleList.Bundles .SingleOrDefault(bundle => bundle.Properties.ContainsKey("name") ? (string)bundle.Properties["name"].Value == pathLayers[3] : ((byte[])bundle.Properties["id"].Value).SequenceEqual(Helpers.StringToByteArray(pathLayers[3]))); } } } if (correspondingBundle != null) { correspondingBundle.Changed = file.FullName; } } } }
public SuperBundle ReadTableOfContentsPayload() { SuperBundle superBundle = new SuperBundle(); List <BundleList> bundleList = new List <BundleList>(); Dictionary <string, PropertyValue> properties = new Dictionary <string, PropertyValue>(); superBundle.Properties = properties; superBundle.BundleCollections = bundleList; byte currentInitialByte = ReadByte(); if (currentInitialByte == 0) { return(null); } superBundle.InitialByte = currentInitialByte; superBundle.Limit = Read7BitEncodedInt(); long startPosition = BaseStream.Position; while (BaseStream.Position < startPosition + superBundle.Limit) { byte entryOpCode = ReadByte(); if (entryOpCode == 0) { return(superBundle); } string entryName = ReadNullTerminatedString(); object value; switch (entryOpCode) { // list case 0x01: bundleList.Add(ReadBundleList(entryName)); continue; // boolean case 0x06: value = ReadByte() == 0x01; break; // string case 0x07: value = ReadString(); break; // 4-byte number case 0x08: value = ReadInt32(); break; // 8-byte number case 0x09: value = ReadInt64(); break; // 16 bytes hash case 0x0f: value = ReadBytes(16); break; // 20 bytes hash case 0x10: value = ReadBytes(20); break; // variable size blob case 0x02: case 0x13: int blobSize = Read7BitEncodedInt(); value = ReadBytes(blobSize); break; default: throw new InvalidDataException("Unknown opcode."); } properties.Add(entryName, new PropertyValue(entryOpCode, value)); } return(superBundle); }
public void Write(SuperBundle bundle) { if (bundle == null) { return; } Write(bundle.InitialByte); Write7BitEncodedInt(bundle.Limit); foreach (BundleList bundleList in bundle.BundleCollections) { Write(bundleList); } foreach (var property in bundle.Properties) { object value = property.Value.Value; Write(property.Value.Opcode); WriteNullTerminatedString(property.Key); switch (property.Value.Opcode) { // boolean case 0x06: Write((bool)value ? (byte)1 : (byte)0); break; // string case 0x07: WriteNullTerminatedStringWithLEB128Prefix((string)value); break; // 4-byte number case 0x08: Write((Int32)value); break; // 8-byte number case 0x09: Write((Int64)value); break; // 16 or 20 bytes hash case 0x0f: case 0x10: Write((byte[])value); break; // variable size blob case 0x02: case 0x13: Write7BitEncodedInt(((byte[])value).Length); Write((byte[])value); break; default: throw new InvalidDataException("Unknown opcode."); } } Write((byte)0); }