Preserve unread bytes when serializing the record

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@597653 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yegor Kozlov 2007-11-23 12:51:44 +00:00
parent 52d3ba08e0
commit 9c7f6307c4
2 changed files with 106 additions and 7 deletions

View File

@ -43,8 +43,15 @@ public class EmbeddedObjectRefSubRecord
public String field_5_ole_classname; // Classname of the embedded OLE document (e.g. Word.Document.8)
public int field_6_stream_id; // ID of the OLE stream containing the actual data.
private int field_5_ole_classname_padding; // developer laziness...
public byte[] remainingBytes;
public EmbeddedObjectRefSubRecord()
{
field_2_unknown = new short[0];
remainingBytes = new byte[0];
field_1_stream_id_offset = 6;
field_5_ole_classname = "";
}
/**
@ -93,19 +100,25 @@ public class EmbeddedObjectRefSubRecord
// Padded with NUL bytes. The -2 is because field_1_stream_id_offset
// is relative to after the offset field, whereas in.getRecordOffset()
// is relative to the start of this record.
// is relative to the start of this record (minus the header.)
field_5_ole_classname_padding = 0;
while (in.getRecordOffset() - 2 < field_1_stream_id_offset)
{
field_5_ole_classname_padding++;
in.readByte(); // discard
}
field_6_stream_id = in.readInt();
remainingBytes = in.readRemainder();
}
public int serialize(int offset, byte[] data)
{
int pos = offset;
LittleEndian.putShort(data, pos, sid); pos += 2;
LittleEndian.putShort(data, pos, (short)(getRecordSize() - 4)); pos += 2;
LittleEndian.putShort(data, pos, field_1_stream_id_offset); pos += 2;
LittleEndian.putShortArray(data, pos, field_2_unknown); pos += field_2_unknown.length * 2 + 2;
LittleEndian.putShort(data, pos, field_3_unicode_len); pos += 2;
@ -120,11 +133,14 @@ public class EmbeddedObjectRefSubRecord
StringUtil.putCompressedUnicode( field_5_ole_classname, data, pos ); pos += field_5_ole_classname.length();
}
// Padded with NUL bytes.
pos = field_1_stream_id_offset;
// Padded with the same number of NUL bytes as were originally skipped.
// XXX: This is only accurate until we make the classname mutable.
pos += field_5_ole_classname_padding;
LittleEndian.putInt(data, pos, field_6_stream_id); pos += 4;
System.arraycopy(remainingBytes, 0, data, pos, remainingBytes.length);
return getRecordSize();
}
@ -133,8 +149,9 @@ public class EmbeddedObjectRefSubRecord
*/
public int getRecordSize()
{
// Conveniently this stores the length of all the crap before the final int value.
return field_1_stream_id_offset + 4;
// The stream id offset is relative to after the stream ID.
// Add 2 bytes for the stream id offset and 4 bytes for the stream id itself and 4 byts for the record header.
return remainingBytes.length + field_1_stream_id_offset + 2 + 4 + 4;
}
/**
@ -160,7 +177,7 @@ public class EmbeddedObjectRefSubRecord
.append(System.getProperty("line.separator"));
buffer.append(" .unknown = ")
.append("0x").append(HexDump.toHex( field_2_unknown ))
.append(" (").append( field_2_unknown ).append(" )")
.append(" (").append( field_2_unknown.length ).append(" )")
.append(System.getProperty("line.separator"));
buffer.append(" .unicodeLen = ")
.append("0x").append(HexDump.toHex( field_3_unicode_len ))

View File

@ -0,0 +1,82 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record;
import junit.framework.TestCase;
import org.apache.poi.util.HexRead;
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.util.Arrays;
/**
* Tests the serialization and deserialization of the TestEmbeddedObjectRefSubRecord
* class works correctly. Test data taken directly from a real
* Excel file.
*
* @author Yegor Kozlov
*/
public class TestEmbeddedObjectRefSubRecord extends TestCase {
String data1 = "[20, 00, 05, 00, FC, 10, 76, 01, 02, 24, 14, DF, 00, 03, 10, 00, 00, 46, 6F, 72, 6D, 73, 2E, 43, 68, 65, 63, 6B, 42, 6F, 78, 2E, 31, 00, 00, 00, 00, 00, 70, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, ]";
public void testStore() throws IOException {
byte[] src = HexRead.readFromString(data1);
src = TestcaseRecordInputStream.mergeDataAndSid(EmbeddedObjectRefSubRecord.sid, (short)src.length, src);
RecordInputStream in = new RecordInputStream(new ByteArrayInputStream(src));
in.nextRecord();
EmbeddedObjectRefSubRecord record1 = new EmbeddedObjectRefSubRecord(in);
byte[] ser = record1.serialize();
RecordInputStream in2 = new RecordInputStream(new ByteArrayInputStream(ser));
in2.nextRecord();
EmbeddedObjectRefSubRecord record2 = new EmbeddedObjectRefSubRecord(in2);
assertTrue(Arrays.equals(src, ser));
assertEquals(record1.field_1_stream_id_offset, record2.field_1_stream_id_offset);
assertTrue(Arrays.equals(record1.field_2_unknown, record2.field_2_unknown));
assertEquals(record1.field_3_unicode_len, record2.field_3_unicode_len);
assertEquals(record1.field_4_unicode_flag, record2.field_4_unicode_flag);
assertEquals(record1.field_5_ole_classname, record2.field_5_ole_classname);
assertEquals(record1.field_6_stream_id, record2.field_6_stream_id);
assertTrue(Arrays.equals(record1.remainingBytes, record2.remainingBytes));
}
public void testCreate() throws IOException {
EmbeddedObjectRefSubRecord record1 = new EmbeddedObjectRefSubRecord();
byte[] ser = record1.serialize();
RecordInputStream in2 = new RecordInputStream(new ByteArrayInputStream(ser));
in2.nextRecord();
EmbeddedObjectRefSubRecord record2 = new EmbeddedObjectRefSubRecord(in2);
assertEquals(record1.field_1_stream_id_offset, record2.field_1_stream_id_offset);
assertTrue(Arrays.equals(record1.field_2_unknown, record2.field_2_unknown));
assertEquals(record1.field_3_unicode_len, record2.field_3_unicode_len);
assertEquals(record1.field_4_unicode_flag, record2.field_4_unicode_flag);
assertEquals(record1.field_5_ole_classname, record2.field_5_ole_classname);
assertEquals(record1.field_6_stream_id, record2.field_6_stream_id);
assertTrue(Arrays.equals(record1.remainingBytes, record2.remainingBytes));
}
}