/// <summary> /// Extracts the KIFINT entry to a fixed stream of <paramref name="kifintStream"/>. /// </summary> /// <param name="kifintStream">The stream to the open KIFINT archive.</param> /// <param name="entry">The KIFINT entry used to locate the file.</param> /// <param name="leaveOpen"> /// True if the KIFINT archive stream should be left open even after closing the returned stream. /// </param> /// <returns> /// A fixed stream containing the data of the decrypted entry. This stream must always be disposed of, because /// it's not guaranteed to be a fixed stream of <paramref name="kifintStream"/>. This is the case when the /// length is small enough for extracting bytes to be more efficient. /// </returns> /// /// <exception cref="ArgumentNullException"> /// <paramref name="kifintStream"/> or <paramref name="entry"/> is null. /// </exception> internal static Stream ExtractToStream(KifintStream kifintStream, KifintEntry entry, bool leaveOpen) { if (kifintStream == null) { throw new ArgumentNullException(nameof(kifintStream)); } if (entry == null) { throw new ArgumentNullException(nameof(entry)); } var kifint = entry.Kifint; // Smaller streams will be faster as reading a big chunk of data all at once. if (kifint.IsEncrypted && entry.Length < 131072 * 2) // Some arbitrary power of 2 cutoff length { try { return(new MemoryStream(ExtractToBytes(kifintStream, entry))); } finally { // We need to make sure the the stream is closed by us if we're not // relying on the fixed streams to close the KIFINT archive stream. if (!leaveOpen) { kifintStream.Close(); } } } kifintStream.Open(kifint); kifintStream.Position = entry.Offset; if (kifint.IsEncrypted) { return(new BlowfishInputStream(kifint.Blowfish, kifintStream, entry.Length, leaveOpen)); } return(new FixedStream(kifintStream, entry.Length, leaveOpen)); }
/// <summary> /// Extracts the KIFINT entry file from the the entry's KIFINT archive. /// </summary> /// <param name="kifintStream">The stream to the open KIFINT archive.</param> /// <param name="entry">The KIFINT entry used to locate the file.</param> /// <returns>A byte array containing the extracted KIFINT entry's file data.</returns> /// /// <exception cref="ArgumentNullException"> /// <paramref name="kifintStream"/> or <paramref name="entry"/> is null. /// </exception> internal static byte[] ExtractToBytes(KifintStream kifintStream, KifintEntry entry) { if (kifintStream == null) { throw new ArgumentNullException(nameof(kifintStream)); } if (entry == null) { throw new ArgumentNullException(nameof(entry)); } var kifint = entry.Kifint; kifintStream.Open(kifint); BinaryReader reader = new BinaryReader(kifintStream); kifintStream.Position = entry.Offset; byte[] buffer = reader.ReadBytes(entry.Length); if (kifint.IsEncrypted) { kifint.Blowfish.Decrypt(buffer, entry.Length & ~7); } return(buffer); }