/// <summary> /// Read the header from a stream. This method advances the stream by /// the length of the header but doesn't close the stream. /// </summary> /// <param name="stream">The stream to read the header from</param> /// <returns>Sii file header information</returns> public static SiiHeader FromStream(Stream stream) { SiiHeader header = new SiiHeader(); using (BinaryReader br = new BinaryReader(stream, Encoding.UTF8, true)) { header.Signature = br.ReadUInt32(); header.Hmac = br.ReadBytes(32); header.InitializationVector = br.ReadBytes(16); header.DecompressedUnitSize = br.ReadUInt32(); } return(header); }
/// <summary> /// Read a Sii binary file. /// </summary> /// <param name="stream">Stream containing the sii binary data</param> /// <returns>The root Sii object representing the unit</returns> public async Task <Object> ReadFromBinary(Stream stream) { SiiHeader header = SiiHeader.FromStream(stream); using (MemoryStream plainStream = new MemoryStream()) { if (header.Signature != SII_CRYPTO_UNIT_SIGNATURE) // Not a valid encrypted unit { throw new InvalidSiiFileException(); } await SiiEncryption.Decrypt(stream, plainStream, header.InitializationVector); plainStream.Position = 0; byte[] plainSig = new byte[SII_TEXT_UNIT_SIGNATURE.Length]; byte[] txtSig = Encoding.UTF8.GetBytes(SII_TEXT_UNIT_SIGNATURE); bool compressed = false; plainStream.Read(plainSig, 0, plainSig.Length); plainStream.Position = 0; for (int i = 0; i < txtSig.Length; i++) { if (txtSig[i] != plainSig[i]) { compressed = true; break; } } Stream decompressedStream; if (compressed) { decompressedStream = new MemoryStream(); await SiiCompression.Decompress(plainStream, decompressedStream); decompressedStream.Position = 0; } else { decompressedStream = plainStream; } return(await ReadFromText(decompressedStream)); } }