internal static DwgFileHeader Parse(BitReader reader) { reader.StartCrcCheck(); var versionString = reader.ReadStringAscii(6); var version = DwgVersionIdExtensions.VersionIdFromString(versionString); var unknown1 = reader.ReadBytes(6); var maintVer = 0; if (version == DwgVersionId.R14) { maintVer = unknown1[5]; } var marker = reader.ReadByte(); if (marker != 1) { throw new DwgReadException("Expected value of 1 at offset 13."); } var imagePointer = reader.ReadInt(); var unknown2 = reader.ReadBytes(2); var codePage = reader.ReadShort(); var header = new DwgFileHeader(version, maintVer, imagePointer, codePage); var recordLocatorCount = reader.ReadInt(); for (int i = 0; i < recordLocatorCount; i++) { var locator = DwgSectionLocator.Parse(reader); switch (i) { case 0: header.HeaderVariablesLocator = locator; break; case 1: header.ClassSectionLocator = locator; break; case 2: header.ObjectMapLocator = locator; break; case 3: header.UnknownSection_R13C3AndLaterLocator = locator; break; case 4: header.UnknownSection_PaddingLocator = locator; break; } } ushort crcXorValue; switch (recordLocatorCount) { case 0: case 1: case 2: crcXorValue = 0; break; case 3: crcXorValue = 0xAD98; break; case 4: crcXorValue = 0x8101; break; case 5: crcXorValue = 0x3CC4; break; case 6: crcXorValue = 0x8461; break; default: throw new DwgReadException("Unsupported record locator count."); } reader.ValidateCrc(xorValue: crcXorValue); reader.ValidateSentinel(HeaderSentinel); return(header); }
internal void ValidateSecondHeader(BitReader parentReader, DwgHeaderVariables headerVariables) { var reader = parentReader.FromOffset(SecondHeaderPointer); reader.ValidateSentinel(SecondHeaderStartSentinel); var sectionStart = reader.Offset; reader.StartCrcCheck(); var reportedSectionSize = reader.Read_RL(); var expectedLocation = reader.Read_BL(); if (expectedLocation != sectionStart - SecondHeaderStartSentinel.Length) { throw new DwgReadException("Reported second header location incorrect."); } var version = DwgVersionIdExtensions.VersionIdFromString(reader.ReadStringAscii(6)); if (version != Version) { throw new DwgReadException("Inconsistent reported version."); } reader.ReadBytes(6); reader.Read_B(); reader.Read_B(); reader.Read_B(); reader.Read_B(); reader.ReadBytes(2); reader.ValidateBytes(SecondHeaderMidSentinel); var recordLocatorCount = reader.ReadByte(); for (int i = 0; i < recordLocatorCount; i++) { var id = reader.ReadByte(); var pointer = reader.Read_BL(); var length = reader.Read_BL(); if (pointer != 0) { switch (i) { case 0: HeaderVariablesLocator.ValidateLocator(id, pointer, length); break; case 1: ClassSectionLocator.ValidateLocator(id, pointer, length); break; case 2: ObjectMapLocator.ValidateLocator(id, pointer, length); break; case 3: UnknownSection_R13C3AndLaterLocator.ValidateLocator(id, pointer, length); break; case 4: UnknownSection_PaddingLocator.ValidateLocator(id, pointer, length); break; } } } var handleRecordCount = reader.Read_BS(); for (int i = 0; i < handleRecordCount; i++) { var byteCount = reader.Read_RC(); var id = reader.Read_RC(); var handle = DwgHandleReference.ReadSecondHeader(reader, byteCount); if (byteCount > 0) { if (id != i) { throw new DwgReadException("Invalid record handle ID."); } var actualHandle = -1; switch (i) { case 0: actualHandle = headerVariables.NextAvailableHandle.HandleOrOffset; break; case 1: actualHandle = headerVariables.BlockControlObjectHandle.HandleOrOffset; break; case 2: actualHandle = headerVariables.LayerControlObjectHandle.HandleOrOffset; break; case 3: actualHandle = headerVariables.StyleObjectControlHandle.HandleOrOffset; break; case 4: actualHandle = headerVariables.LineTypeObjectControlHandle.HandleOrOffset; break; case 5: actualHandle = headerVariables.ViewControlObjectHandle.HandleOrOffset; break; case 6: actualHandle = headerVariables.UcsControlObjectHandle.HandleOrOffset; break; case 7: actualHandle = headerVariables.ViewPortControlObjectHandle.HandleOrOffset; break; case 8: actualHandle = headerVariables.AppIdControlObjectHandle.HandleOrOffset; break; case 9: actualHandle = headerVariables.DimStyleControlObjectHandle.HandleOrOffset; break; case 10: actualHandle = headerVariables.ViewPortEntityHeaderControlObjectHandle.HandleOrOffset; break; case 11: actualHandle = headerVariables.NamedObjectsDictionaryHandle.HandleOrOffset; break; case 12: actualHandle = headerVariables.MLineStyleDictionaryHandle.HandleOrOffset; break; case 13: actualHandle = headerVariables.GroupDictionaryHandle.HandleOrOffset; break; } if (actualHandle > 0) { if (handle != actualHandle) { throw new DwgReadException($"Invalid record handle ID at location {i}. Expected: {handle}, Actual: {actualHandle}"); } } } } reader.ReadByte(); reader.ValidateCrc(initialValue: DwgHeaderVariables.InitialCrcValue); var junkByteCount = Math.Max(0, reportedSectionSize - (reader.Offset - sectionStart)); reader.SkipBytes(junkByteCount); reader.ValidateSentinel(SecondHeaderEndSentinel); var computedSectionSize = reader.Offset - sectionStart - SecondHeaderEndSentinel.Length; if (computedSectionSize != reportedSectionSize) { throw new DwgReadException($"Reported and actual second header sizes differ. Expected: {reportedSectionSize}, Actual: {computedSectionSize}"); } }