From 7fec860cd8cdf142b742c1bdf66817c8056d30c5 Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Fri, 23 Nov 2007 12:52:51 +0000 Subject: [PATCH] fixed bugs 43877 and 39512: Fix for handling mixed OBJ and CONTINUE records git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@597654 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/hssf/record/DrawingRecord.java | 16 +++-- .../apache/poi/hssf/record/RecordFactory.java | 3 + .../org/apache/poi/hssf/data/39512.xls | Bin 0 -> 29696 bytes .../poi/hssf/record/TestRecordFactory.java | 62 ++++++++++++++++++ 4 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 src/testcases/org/apache/poi/hssf/data/39512.xls diff --git a/src/java/org/apache/poi/hssf/record/DrawingRecord.java b/src/java/org/apache/poi/hssf/record/DrawingRecord.java index 4dbc53015..d73702b6a 100644 --- a/src/java/org/apache/poi/hssf/record/DrawingRecord.java +++ b/src/java/org/apache/poi/hssf/record/DrawingRecord.java @@ -23,6 +23,7 @@ public class DrawingRecord extends Record public static final short sid = 0xEC; private byte[] recordData; + private byte[] contd; public DrawingRecord() { @@ -53,10 +54,8 @@ public class DrawingRecord extends Record public void processContinueRecord( byte[] record ) { - byte[] newBuffer = new byte[ recordData.length + record.length ]; - System.arraycopy( recordData, 0, newBuffer, 0, recordData.length ); - System.arraycopy( record, 0, newBuffer, recordData.length, record.length); - recordData = newBuffer; + //don't merge continue record with the drawing record, it must be serialized separately + contd = record; } public int serialize( int offset, byte[] data ) @@ -92,7 +91,14 @@ public class DrawingRecord extends Record public byte[] getData() { - return recordData; + if(contd != null) { + byte[] newBuffer = new byte[ recordData.length + contd.length ]; + System.arraycopy( recordData, 0, newBuffer, 0, recordData.length ); + System.arraycopy( contd, 0, newBuffer, recordData.length, contd.length); + return newBuffer; + } else { + return recordData; + } } public void setData( byte[] thedata ) diff --git a/src/java/org/apache/poi/hssf/record/RecordFactory.java b/src/java/org/apache/poi/hssf/record/RecordFactory.java index 398576dc7..927d5f08b 100644 --- a/src/java/org/apache/poi/hssf/record/RecordFactory.java +++ b/src/java/org/apache/poi/hssf/record/RecordFactory.java @@ -140,6 +140,9 @@ public class RecordFactory // Drawing records have a very strange continue behaviour. //There can actually be OBJ records mixed between the continues. lastDrawingRecord.processContinueRecord( ((ContinueRecord)record).getData() ); + //we must rememeber the position of the continue record. + //in the serialization procedure the original structure of records must be preserved + records.add(record); } else if (record.getSid() == ContinueRecord.sid && (lastRecord instanceof DrawingGroupRecord)) { ((DrawingGroupRecord)lastRecord).processContinueRecord(((ContinueRecord)record).getData()); diff --git a/src/testcases/org/apache/poi/hssf/data/39512.xls b/src/testcases/org/apache/poi/hssf/data/39512.xls new file mode 100644 index 0000000000000000000000000000000000000000..44cf5718ecc4a7a29558921095882e2b6b63a73b GIT binary patch literal 29696 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 literal 0 HcmV?d00001 diff --git a/src/testcases/org/apache/poi/hssf/record/TestRecordFactory.java b/src/testcases/org/apache/poi/hssf/record/TestRecordFactory.java index 4dbb2a5b0..4f721a798 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestRecordFactory.java +++ b/src/testcases/org/apache/poi/hssf/record/TestRecordFactory.java @@ -20,8 +20,13 @@ package org.apache.poi.hssf.record; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.List; +import java.util.Iterator; +import java.util.Arrays; import junit.framework.TestCase; +import org.apache.poi.util.HexRead; /** * Tests the record factory @@ -166,6 +171,63 @@ public class TestRecordFactory assertEquals("4th data byte", 4, record.getData()[ 0 ]); } + /** + * Drawing records have a very strange continue behaviour. + * There can actually be OBJ records mixed between the continues. + * Record factory must preserve this structure when reading records. + */ + public void testMixedContinue() throws Exception { + /** + * Taken from a real file $HSSF.testdata.path/39512.xls. See Bug 39512 for details. + */ + String dump = + //OBJ + "5D, 00, 48, 00, 15, 00, 12, 00, 0C, 00, 3C, 00, 11, 00, A0, 2E, 03, 01, CC, 42, " + + "CF, 00, 00, 00, 00, 00, 0A, 00, 0C, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, " + + "03, 00, 0B, 00, 06, 00, 28, 01, 03, 01, 00, 00, 12, 00, 08, 00, 00, 00, 00, 00, " + + "00, 00, 03, 00, 11, 00, 04, 00, 3D, 00, 00, 00, 00, 00, 00, 00, " + + //MSODRAWING + "EC, 00, 08, 00, 00, 00, 0D, F0, 00, 00, 00, 00, " + + //TXO + "B6, 01, 12, 00, 22, 02, 00, 00, 00, 00, 00, 00, 00, 00, 10, 00, 10, 00, 00, 00, " + + "00, 00, 3C, 00, 21, 00, 01, 4F, 00, 70, 00, 74, 00, 69, 00, 6F, 00, 6E, 00, 20, " + + "00, 42, 00, 75, 00, 74, 00, 74, 00, 6F, 00, 6E, 00, 20, 00, 33, 00, 39, 00, 3C, " + + "00, 10, 00, 00, 00, 05, 00, 00, 00, 00, 00, 10, 00, 00, 00, 00, 00, 00, 00, " + + //CONTINUE + "3C, 00, 7E, 00, 0F, 00, 04, F0, 7E, 00, 00, 00, 92, 0C, 0A, F0, 08, 00, 00, 00, " + + "3D, 04, 00, 00, 00, 0A, 00, 00, A3, 00, 0B, F0, 3C, 00, 00, 00, 7F, 00, 00, 01, " + + "00, 01, 80, 00, 8C, 01, 03, 01, 85, 00, 01, 00, 00, 00, 8B, 00, 02, 00, 00, 00, " + + "BF, 00, 08, 00, 1A, 00, 7F, 01, 29, 00, 29, 00, 81, 01, 41, 00, 00, 08, BF, 01, " + + "00, 00, 10, 00, C0, 01, 40, 00, 00, 08, FF, 01, 00, 00, 08, 00, 00, 00, 10, F0, " + + "12, 00, 00, 00, 02, 00, 02, 00, A0, 03, 18, 00, B5, 00, 04, 00, 30, 02, 1A, 00, " + + "00, 00, 00, 00, 11, F0, 00, 00, 00, 00, " + + //OBJ + "5D, 00, 48, 00, 15, 00, 12, 00, 0C, 00, 3D, 00, 11, 00, 8C, 01, 03, 01, C8, 59, CF, 00, 00, " + + "00, 00, 00, 0A, 00, 0C, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 03, 00, 0B, 00, 06, 00, " + + "7C, 16, 03, 01, 00, 00, 12, 00, 08, 00, 00, 00, 00, 00, 00, 00, 03, 00, 11, 00, 04, 00, 01, " + + "00, 00, 00, 00, 00, 00, 00"; + byte[] data = HexRead.readFromString(dump); + + List records = RecordFactory.createRecords(new ByteArrayInputStream(data)); + assertEquals(5, records.size()); + assertTrue(records.get(0) instanceof ObjRecord); + assertTrue(records.get(1) instanceof DrawingRecord); + assertTrue(records.get(2) instanceof TextObjectRecord); + assertTrue(records.get(3) instanceof ContinueRecord); + assertTrue(records.get(4) instanceof ObjRecord); + + //serialize and verify that the serialized data is the same as the original + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for(Iterator it = records.iterator(); it.hasNext(); ){ + Record rec = (Record)it.next(); + out.write(rec.serialize()); + } + + byte[] ser = out.toByteArray(); + assertEquals(data.length, ser.length); + assertTrue(Arrays.equals(data, ser)); + } + public static void main(String [] ignored_args) { System.out