/// <summary> /// Deserializes the <see cref="XvEntryHeader"/> from the underlying <see cref="Stream"/> of the specified <see cref="BinaryReader"/>. /// </summary> /// <param name="reader">The <see cref="BinaryReader"/> to read from.</param> /// <param name="key">The hash used to decrypt <see cref="XvEntryHeader"/> information.</param> /// <returns>A new <see cref="XvEntryHeader"/> populated with the entry's data.</returns> public static XvEntryHeader Deserialize(BinaryReader reader, ulong key) { //* get the basic entry information XvEntryHeader header = ReadHeader(reader); //* set the key incase it's not updated header.RollingKey = key; //* if the archive encrypts the meta data, decrypt it //* thanks to daxxy if ((header.Flags & XvEntryHeaderFlags.SafeHeader) != XvEntryHeaderFlags.SafeHeader) { ulong fileSizeKey = (key * XvArchive.ENTRY_KEY) ^ header.Hash, dataOffsetKey = (fileSizeKey * XvArchive.ENTRY_KEY) ^ ~(header.Hash); uint uncompressedKey = (uint)(fileSizeKey >> 32), compressedKey = (uint)(fileSizeKey & 0xFFFFFFFF); header.Size ^= uncompressedKey; header.CompressedSize ^= compressedKey; header.OffsetData ^= dataOffsetKey; header.RollingKey = dataOffsetKey; long returnPosition = reader.BaseStream.Position; reader.BaseStream.Seek((long)(header.OffsetData + header.CompressedSize - IV_OFFSET), SeekOrigin.Begin); header.IV = reader.ReadBytes(16); header.CompressedSize -= IV_OFFSET; reader.BaseStream.Seek(returnPosition, SeekOrigin.Begin); } return(header); }
/// <summary> /// /// </summary> /// <param name="reader"></param> /// <returns></returns> private static XvEntryHeader ReadHeader(BinaryReader reader) { XvEntryHeader header = new XvEntryHeader { Hash = reader.ReadUInt64(), Size = reader.ReadUInt32(), CompressedSize = reader.ReadUInt32(), Flags = (XvEntryHeaderFlags)reader.ReadUInt32(), OffsetName = reader.ReadUInt32(), OffsetData = reader.ReadUInt64(), OffsetFullPath = reader.ReadUInt32(), LocalizeType = reader.ReadByte(), LocalizeLocale = reader.ReadByte(), Key = reader.ReadUInt16() }; long returnPosition = reader.BaseStream.Position; reader.BaseStream.Seek(header.OffsetName, SeekOrigin.Begin); header.Name = reader.ReadStringNullTerminated(); reader.BaseStream.Seek(header.OffsetFullPath, SeekOrigin.Begin); header.Path = reader.ReadStringNullTerminated(); reader.BaseStream.Seek(returnPosition, SeekOrigin.Begin); return(header); }
/// <summary> /// /// </summary> /// <param name="reader"></param> /// <returns></returns> public static XvEntryHeader Deserialize(BinaryReader reader) { XvEntryHeader header = ReadHeader(reader); if ((header.Flags & XvEntryHeaderFlags.SafeHeader) != XvEntryHeaderFlags.SafeHeader) { throw new InvalidDataException("SAFE HEADER FLAG NOT SET BUT WRONG DESERIALIZE CALLED"); } return(header); }