From: Dominik Stadler Date: Tue, 25 Aug 2015 08:28:54 +0000 (+0000) Subject: Allow multiple instances of HeaderFooterRecord in CustomViewSettingsRecordAggregate... X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=97fa448a2cd0d8a0abe67ba504fbe240ea387dc6;p=poi.git Allow multiple instances of HeaderFooterRecord in CustomViewSettingsRecordAggregate similar to ChartSubstreamRecordAggreagte in order to read sample 49931.xls correctly after re-saving it with HSSFWorkbook Improve error output git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1697600 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/poi/hssf/record/aggregates/ChartSubstreamRecordAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/ChartSubstreamRecordAggregate.java index dc73209933..3353813086 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/ChartSubstreamRecordAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/ChartSubstreamRecordAggregate.java @@ -50,7 +50,7 @@ public final class ChartSubstreamRecordAggregate extends RecordAggregate { continue; } throw new IllegalStateException( - "Found more than one PageSettingsBlock in chart sub-stream"); + "Found more than one PageSettingsBlock in chart sub-stream, had sid: " + rs.peekNextSid()); } _psBlock = new PageSettingsBlock(rs); temp.add(_psBlock); diff --git a/src/java/org/apache/poi/hssf/record/aggregates/CustomViewSettingsRecordAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/CustomViewSettingsRecordAggregate.java index bc6a737e63..168f04f1d7 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/CustomViewSettingsRecordAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/CustomViewSettingsRecordAggregate.java @@ -47,10 +47,15 @@ public final class CustomViewSettingsRecordAggregate extends RecordAggregate { List temp = new ArrayList(); while (rs.peekNextSid() != UserSViewEnd.sid) { if (PageSettingsBlock.isComponentRecord(rs.peekNextSid())) { - if (_psBlock != null) { - throw new IllegalStateException( - "Found more than one PageSettingsBlock in custom view settings sub-stream"); - } + if (_psBlock != null) { + if (rs.peekNextSid() == HeaderFooterRecord.sid) { + // test samples: 45538_classic_Footer.xls, 45538_classic_Header.xls + _psBlock.addLateHeaderFooter((HeaderFooterRecord)rs.getNext()); + continue; + } + throw new IllegalStateException( + "Found more than one PageSettingsBlock in chart sub-stream, had sid: " + rs.peekNextSid()); + } _psBlock = new PageSettingsBlock(rs); temp.add(_psBlock); continue; diff --git a/src/testcases/org/apache/poi/hssf/record/aggregates/TestPageSettingsBlock.java b/src/testcases/org/apache/poi/hssf/record/aggregates/TestPageSettingsBlock.java index 71e48f2171..a63fd7b039 100644 --- a/src/testcases/org/apache/poi/hssf/record/aggregates/TestPageSettingsBlock.java +++ b/src/testcases/org/apache/poi/hssf/record/aggregates/TestPageSettingsBlock.java @@ -380,4 +380,82 @@ public final class TestPageSettingsBlock extends TestCase { assertArrayEquals(svb.getGuid(), hd2.getGuid()); } + public void testDuplicateHeaderFooterInside_bug48026() { + + Record[] recs = { + BOFRecord.createSheetBOF(), + new IndexRecord(), + + //PageSettingsBlock + new HeaderRecord("&LDecember"), + new FooterRecord("&LJanuary"), + new DimensionsRecord(), + + new WindowTwoRecord(), + + //CustomViewSettingsRecordAggregate + new UserSViewBegin(HexRead.readFromString("53 CE BD CC DE 38 44 45 97 C1 5C 89 F9 37 32 1B 01 00 00 00 64 00 00 00 40 00 00 00 03 00 00 00 7D 00 00 20 00 00 34 00 00 00 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF")), + new SelectionRecord(0, 0), + + // two HeaderFooterRecord records, the first one has zero GUID (16 bytes at offset 12) and belongs to the PSB, + // the other is matched with a CustomViewSettingsRecordAggregate having UserSViewBegin with the same GUID + new HeaderFooterRecord(HexRead.readFromString("9C 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 34 33 00 00 00 00 00 00 00 00")), + new HeaderFooterRecord(HexRead.readFromString("9C 08 00 00 00 00 00 00 00 00 00 00 53 CE BD CC DE 38 44 45 97 C1 5C 89 F9 37 32 1B 34 33 00 00 00 00 00 00 00 00")), + + new UserSViewEnd(HexRead.readFromString("01 00")), + + EOFRecord.instance, + }; + RecordStream rs = new RecordStream(Arrays.asList(recs), 0); + InternalSheet sheet; + try { + sheet = InternalSheet.createSheet(rs); + } catch (RuntimeException e) { + if (e.getMessage().equals("Duplicate PageSettingsBlock record (sid=0x89c)")) { + throw new AssertionFailedError("Identified bug 48026"); + } + throw e; + } + + RecordCollector rv = new RecordCollector(); + sheet.visitContainedRecords(rv, 0); + Record[] outRecs = rv.getRecords(); + + assertEquals(recs.length+1, outRecs.length); + //expected order of records: + Record[] expectedRecs = { + recs[0], //BOFRecord + recs[1], //IndexRecord + + //PageSettingsBlock + recs[2], //HeaderRecord + recs[3], //FooterRecord + recs[4], // DimensionsRecord + recs[5], // WindowTwoRecord + + //CustomViewSettingsRecordAggregate + recs[6], // UserSViewBegin + recs[7], // SelectionRecord + recs[2], //HeaderRecord + recs[3], //FooterRecord + recs[8], // HeaderFooterRecord +// recs[9], //HeaderFooterRecord + recs[10], // UserSViewEnd + + recs[11], //EOFRecord + }; + for(int i=0; i < expectedRecs.length; i++){ + assertEquals("Record mismatch at index " + i, expectedRecs[i].getClass(), outRecs[i].getClass()); + } + HeaderFooterRecord hd1 = (HeaderFooterRecord)expectedRecs[10]; + //GUID is zero + assertArrayEquals(new byte[16], hd1.getGuid()); + assertTrue(hd1.isCurrentSheet()); + + UserSViewBegin svb = (UserSViewBegin)expectedRecs[6]; + HeaderFooterRecord hd2 = (HeaderFooterRecord)recs[9]; + assertFalse(hd2.isCurrentSheet()); + //GUIDs of HeaderFooterRecord and UserSViewBegin must be the same + assertArrayEquals(svb.getGuid(), hd2.getGuid()); + } }