/// <summary> /// Read in offsets. Converting to Int32 because .NET Stream.Read method takes Int32s. /// </summary> /// <param name="stream"></param> /// <param name="trailer"></param> /// <returns></returns> private static int[] ReadNodeOffsets(Stream stream, PListTrailer trailer) { // the bitconverter library we use only knows how to deal with integer offsets if (trailer.NumObjects > int.MaxValue) { throw new PListFormatException($"Offset table contains too many entries: {trailer.NumObjects}."); } var converter = EndianBitConverter.BigEndian; // position the stream at the start of the offset table if (stream.Seek((long)trailer.OffsetTableOffset, SeekOrigin.Begin) != (long)trailer.OffsetTableOffset) { throw new PListFormatException("Invalid plist file: unable to seek to start of the offset table."); } var offsetSize = trailer.OffsetIntSize; var buffer = new byte[offsetSize]; var nodeOffsets = new int[trailer.NumObjects]; for (ulong i = 0; i < trailer.NumObjects; i++) { if (stream.Read(buffer, 0, buffer.Length) != buffer.Length) { throw new PListFormatException($"Invalid plist file: unable to read value {i} in the offset table."); } nodeOffsets[i] = ReadNumber(buffer, converter); } return(nodeOffsets); }
private static PListTrailer ReadTrailer(Stream stream) { // trailer is 32 bytes long, at the end of the file var buffer = new byte[32]; stream.Seek(-32, SeekOrigin.End); if (stream.Read(buffer, 0, buffer.Length) != buffer.Length) { throw new PListFormatException("Invalid plist file: unable to read trailer."); } // all data in a binary plist file is big-endian var converter = EndianBitConverter.BigEndian; var trailer = new PListTrailer { Unused = new byte[5], SortVersionl = buffer[5], OffsetIntSize = buffer[6], ObjectRefSize = buffer[7], NumObjects = converter.ToUInt64(buffer, 8), TopObject = converter.ToUInt64(buffer, 16), OffsetTableOffset = converter.ToUInt64(buffer, 24) }; return(trailer); }