diff options
author | Andreas Beeker <kiwiwings@apache.org> | 2014-02-01 21:45:48 +0000 |
---|---|---|
committer | Andreas Beeker <kiwiwings@apache.org> | 2014-02-01 21:45:48 +0000 |
commit | e484fd75d01772e90fd1fdf6e7f6412e144da261 (patch) | |
tree | 7465067ddbe92e4846c3b05224366bece8921a20 | |
parent | bc936983a5947d7e511a3a66af7c1aac4821ce88 (diff) | |
download | poi-e484fd75d01772e90fd1fdf6e7f6412e144da261.tar.gz poi-e484fd75d01772e90fd1fdf6e7f6412e144da261.zip |
Bug 51891 - Fix StringIndexOutOfBoundsException : Ole10Native.<init> (parsing word file)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1563483 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | src/java/org/apache/poi/hpsf/ClassID.java | 1 | ||||
-rw-r--r-- | src/java/org/apache/poi/poifs/filesystem/Ole10Native.java | 690 | ||||
-rw-r--r-- | src/testcases/org/apache/poi/poifs/AllPOIFSTests.java | 25 | ||||
-rw-r--r-- | src/testcases/org/apache/poi/poifs/filesystem/AllPOIFSFileSystemTests.java | 40 | ||||
-rw-r--r-- | src/testcases/org/apache/poi/poifs/filesystem/TestOle10Native.java | 80 | ||||
-rw-r--r-- | test-data/poifs/20-Force-on-a-current-S00.doc | bin | 0 -> 58368 bytes | |||
-rw-r--r-- | test-data/poifs/multimedia.doc | bin | 0 -> 4835840 bytes |
7 files changed, 470 insertions, 366 deletions
diff --git a/src/java/org/apache/poi/hpsf/ClassID.java b/src/java/org/apache/poi/hpsf/ClassID.java index a49d9df588..c78702c3c1 100644 --- a/src/java/org/apache/poi/hpsf/ClassID.java +++ b/src/java/org/apache/poi/hpsf/ClassID.java @@ -40,6 +40,7 @@ public class ClassID public static final ClassID WORD95 = new ClassID("{00020900-0000-0000-C000-000000000046}"); public static final ClassID POWERPOINT97 = new ClassID("{64818D10-4F9B-11CF-86EA-00AA00B929E8}"); public static final ClassID POWERPOINT95 = new ClassID("{EA7BAE70-FB3B-11CD-A903-00AA00510EA3}"); + public static final ClassID EQUATION30 = new ClassID("{0002CE02-0000-0000-C000-000000000046}"); /** diff --git a/src/java/org/apache/poi/poifs/filesystem/Ole10Native.java b/src/java/org/apache/poi/poifs/filesystem/Ole10Native.java index 2c950da3ff..122eb0a5ae 100644 --- a/src/java/org/apache/poi/poifs/filesystem/Ole10Native.java +++ b/src/java/org/apache/poi/poifs/filesystem/Ole10Native.java @@ -17,14 +17,13 @@ package org.apache.poi.poifs.filesystem; -import java.io.ByteArrayOutputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.poi.util.HexDump; -import org.apache.poi.util.LittleEndian; +import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.LittleEndianOutputStream;
import org.apache.poi.util.StringUtil;
/**
@@ -35,341 +34,378 @@ import org.apache.poi.util.StringUtil; */ public class Ole10Native { - public static final String OLE10_NATIVE = "\u0001Ole10Native"; - protected static final String ISO1 = "ISO-8859-1"; - - // (the fields as they appear in the raw record:) - private int totalSize; // 4 bytes, total size of record not including this field - private short flags1 = 2; // 2 bytes, unknown, mostly [02 00] - private String label; // ASCIIZ, stored in this field without the terminating zero - private String fileName; // ASCIIZ, stored in this field without the terminating zero - private short flags2 = 0; // 2 bytes, unknown, mostly [00 00] - private short unknown1 = 3; // see below - private String command; // ASCIIZ, stored in this field without the terminating zero - private byte[] dataBuffer; // varying size, the actual native data - private short flags3 = 0; // some final flags? or zero terminators?, sometimes not there - - /** - * Creates an instance of this class from an embedded OLE Object. The OLE Object is expected - * to include a stream "{01}Ole10Native" which contains the actual - * data relevant for this class.
- *
- * @param poifs POI Filesystem object
- * @return Returns an instance of this class
- * @throws IOException on IO error
- * @throws Ole10NativeException on invalid or unexcepted data format
- */
- public static Ole10Native createFromEmbeddedOleObject(POIFSFileSystem poifs) throws IOException, Ole10NativeException {
- return createFromEmbeddedOleObject(poifs.getRoot());
- }
+ public static final String OLE10_NATIVE = "\u0001Ole10Native"; + protected static final String ISO1 = "ISO-8859-1"; + + // (the fields as they appear in the raw record:)
+ private int totalSize; // 4 bytes, total size of record not including this field + private short flags1 = 2; // 2 bytes, unknown, mostly [02 00] + private String label; // ASCIIZ, stored in this field without the terminating zero + private String fileName; // ASCIIZ, stored in this field without the terminating zero + private short flags2 = 0; // 2 bytes, unknown, mostly [00 00] + private short unknown1 = 3; // see below + private String command; // ASCIIZ, stored in this field without the terminating zero + private byte[] dataBuffer; // varying size, the actual native data + private short flags3 = 0; // some final flags? or zero terminators?, sometimes not there + + /**
+ * the field encoding mode - merely a try-and-error guess ...
+ **/
+ private enum EncodingMode {
+ /**
+ * the data is stored in parsed format - including label, command, etc.
+ */
+ parsed,
+ /**
+ * the data is stored raw after the length field
+ */
+ unparsed,
+ /**
+ * the data is stored raw after the length field and the flags1 field
+ */
+ compact;
+ }
+
+ private EncodingMode mode;
+
+
+
+ /** + * Creates an instance of this class from an embedded OLE Object. The OLE Object is expected + * to include a stream "{01}Ole10Native" which contains the actual + * data relevant for this class.
+ *
+ * @param poifs POI Filesystem object
+ * @return Returns an instance of this class
+ * @throws IOException on IO error
+ * @throws Ole10NativeException on invalid or unexcepted data format
+ */
+ public static Ole10Native createFromEmbeddedOleObject(POIFSFileSystem poifs) throws IOException, Ole10NativeException {
+ return createFromEmbeddedOleObject(poifs.getRoot());
+ }
+
+ /**
+ * Creates an instance of this class from an embedded OLE Object. The OLE Object is expected
+ * to include a stream "{01}Ole10Native" which contains the actual
+ * data relevant for this class.
+ *
+ * @param directory POI Filesystem object
+ * @return Returns an instance of this class
+ * @throws IOException on IO error
+ * @throws Ole10NativeException on invalid or unexcepted data format
+ */
+ public static Ole10Native createFromEmbeddedOleObject(DirectoryNode directory) throws IOException, Ole10NativeException {
+ DocumentEntry nativeEntry =
+ (DocumentEntry)directory.getEntry(OLE10_NATIVE);
+ byte[] data = new byte[nativeEntry.getSize()];
+ directory.createDocumentInputStream(nativeEntry).read(data);
- /**
- * Creates an instance of this class from an embedded OLE Object. The OLE Object is expected
- * to include a stream "{01}Ole10Native" which contains the actual
- * data relevant for this class.
- *
- * @param directory POI Filesystem object
- * @return Returns an instance of this class
- * @throws IOException on IO error
- * @throws Ole10NativeException on invalid or unexcepted data format
- */
- public static Ole10Native createFromEmbeddedOleObject(DirectoryNode directory) throws IOException, Ole10NativeException {
- boolean plain = false;
+ return new Ole10Native(data, 0);
+ } + + /** + * Creates an instance and fills the fields based on ... the fields + */ + public Ole10Native(String label, String filename, String command, byte[] data) { + setLabel(label); + setFileName(filename); + setCommand(command); + setDataBuffer(data);
+ mode = EncodingMode.parsed; + } - try {
- directory.getEntry("\u0001Ole10ItemName");
- plain = true;
- } catch (FileNotFoundException ex) {
- plain = false;
- }
-
- DocumentEntry nativeEntry =
- (DocumentEntry)directory.getEntry(OLE10_NATIVE);
- byte[] data = new byte[nativeEntry.getSize()];
- directory.createDocumentInputStream(nativeEntry).read(data);
+ /**
+ * Creates an instance and fills the fields based on the data in the given buffer.
+ *
+ * @param data The buffer containing the Ole10Native record
+ * @param offset The start offset of the record in the buffer
+ * @param plain as of POI 3.11 this parameter is ignored
+ * @throws Ole10NativeException on invalid or unexcepted data format
+ *
+ * @deprecated parameter plain is ignored, use {@link #Ole10Native(byte[],int)}
+ */
+ public Ole10Native(byte[] data, int offset, boolean plain) throws Ole10NativeException {
+ this(data, offset);
+ }
+ + /** + * Creates an instance and fills the fields based on the data in the given buffer. + * + * @param data The buffer containing the Ole10Native record + * @param offset The start offset of the record in the buffer
+ * @throws Ole10NativeException on invalid or unexcepted data format
+ */
+ public Ole10Native(byte[] data, int offset) throws Ole10NativeException {
+ int ofs = offset; // current offset, initialized to start
+
+ if (data.length < offset + 2) {
+ throw new Ole10NativeException("data is too small");
+ }
+
+ totalSize = LittleEndian.getInt(data, ofs);
+ ofs += LittleEndianConsts.INT_SIZE;
+
+ mode = EncodingMode.unparsed;
+ if (LittleEndian.getShort(data, ofs) == 2) {
+ // some files like equations don't have a valid filename,
+ // but somehow encode the formula right away in the ole10 header
+ if (Character.isISOControl(data[ofs+LittleEndianConsts.SHORT_SIZE])) {
+ mode = EncodingMode.compact;
+ } else {
+ mode = EncodingMode.parsed;
+ }
+ }
- return new Ole10Native(data, 0, plain);
- } - - /** - * Creates an instance and fills the fields based on ... the fields - */ - public Ole10Native(String label, String filename, String command, byte[] data) { - setLabel(label); - setFileName(filename); - setCommand(command); - setDataBuffer(data); - } - - /** - * Creates an instance and fills the fields based on the data in the given buffer. - * - * @param data The buffer containing the Ole10Native record - * @param offset The start offset of the record in the buffer
- * @throws Ole10NativeException on invalid or unexcepted data format
- */
- public Ole10Native(byte[] data, int offset) throws Ole10NativeException {
- this(data, offset, false);
- }
- /**
- * Creates an instance and fills the fields based on the data in the given buffer.
- *
- * @param data The buffer containing the Ole10Native record
- * @param offset The start offset of the record in the buffer
- * @param plain Specified 'plain' format without filename
- * @throws Ole10NativeException on invalid or unexcepted data format
- */
- public Ole10Native(byte[] data, int offset, boolean plain) throws Ole10NativeException {
- int ofs = offset; // current offset, initialized to start
+ int dataSize;
+ switch (mode) {
+ case parsed: {
+ flags1 = LittleEndian.getShort(data, ofs);
+
+ // structured format
+ ofs += LittleEndianConsts.SHORT_SIZE;
+
+ int len = getStringLength(data, ofs);
+ label = StringUtil.getFromCompressedUnicode(data, ofs, len - 1);
+ ofs += len;
+
+ len = getStringLength(data, ofs);
+ fileName = StringUtil.getFromCompressedUnicode(data, ofs, len - 1);
+ ofs += len;
+
+ flags2 = LittleEndian.getShort(data, ofs);
+ ofs += LittleEndianConsts.SHORT_SIZE; + + unknown1 = LittleEndian.getShort(data, ofs); + ofs += LittleEndianConsts.SHORT_SIZE; + + len = LittleEndian.getInt(data, ofs); + ofs += LittleEndianConsts.INT_SIZE;
+ command = StringUtil.getFromCompressedUnicode(data, ofs, len - 1); + ofs += len; + + if (totalSize < ofs) { + throw new Ole10NativeException("Invalid Ole10Native"); + } + + dataSize = LittleEndian.getInt(data, ofs); + ofs += LittleEndianConsts.INT_SIZE; + + if (dataSize < 0 || totalSize - (ofs - LittleEndianConsts.INT_SIZE) < dataSize) { + throw new Ole10NativeException("Invalid Ole10Native"); + }
+ break;
+ }
+ case compact:
+ flags1 = LittleEndian.getShort(data, ofs);
+ ofs += LittleEndianConsts.SHORT_SIZE;
+ dataSize = totalSize - LittleEndianConsts.SHORT_SIZE;
+ break;
+ default:
+ case unparsed:
+ dataSize = totalSize;
+ break;
+ } + + dataBuffer = new byte[dataSize]; + System.arraycopy(data, ofs, dataBuffer, 0, dataSize); + ofs += dataSize; + }
- if (data.length<offset+2) {
- throw new Ole10NativeException("data is too small");
+ /*
+ * Helper - determine length of zero terminated string (ASCIIZ).
+ */
+ private static int getStringLength(byte[] data, int ofs) {
+ int len = 0;
+ while (len + ofs < data.length && data[ofs + len] != 0) {
+ len++;
+ }
+ len++;
+ return len;
}
- totalSize = LittleEndian.getInt(data, ofs);
- ofs += LittleEndianConsts.INT_SIZE;
+ /**
+ * Returns the value of the totalSize field - the total length of the
+ * structure is totalSize + 4 (value of this field + size of this field).
+ *
+ * @return the totalSize
+ */
+ public int getTotalSize() {
+ return totalSize;
+ }
- if (plain) { - dataBuffer = new byte[totalSize-4]; - System.arraycopy(data, 4, dataBuffer, 0, dataBuffer.length); - // int dataSize = totalSize - 4; - - byte[] oleLabel = new byte[8]; - System.arraycopy(dataBuffer, 0, oleLabel, 0, Math.min(dataBuffer.length, 8)); - label = "ole-"+ HexDump.toHex(oleLabel);
- fileName = label;
- command = label;
- } else { - flags1 = LittleEndian.getShort(data, ofs); - ofs += LittleEndianConsts.SHORT_SIZE; - - int len = getStringLength(data, ofs); - label = StringUtil.getFromCompressedUnicode(data, ofs, len - 1); - ofs += len; - - len = getStringLength(data, ofs); - fileName = StringUtil.getFromCompressedUnicode(data, ofs, len - 1); - ofs += len; - - flags2 = LittleEndian.getShort(data, ofs); - ofs += LittleEndianConsts.SHORT_SIZE; - - unknown1 = LittleEndian.getShort(data, ofs); - ofs += LittleEndianConsts.SHORT_SIZE; - - len = LittleEndian.getInt(data, ofs); - ofs += LittleEndianConsts.INT_SIZE; - - command = StringUtil.getFromCompressedUnicode(data, ofs, len - 1); - ofs += len; - - if (totalSize < ofs) { - throw new Ole10NativeException("Invalid Ole10Native"); - } - - int dataSize = LittleEndian.getInt(data, ofs); - ofs += LittleEndianConsts.INT_SIZE; - - if (dataSize < 0 || totalSize - (ofs - LittleEndianConsts.INT_SIZE) < dataSize) { - throw new Ole10NativeException("Invalid Ole10Native"); - } - - dataBuffer = new byte[dataSize]; - System.arraycopy(data, ofs, dataBuffer, 0, dataSize); - ofs += dataSize; - } - } - - /*
- * Helper - determine length of zero terminated string (ASCIIZ).
- */
- private static int getStringLength(byte[] data, int ofs) {
- int len = 0;
- while (len+ofs<data.length && data[ofs + len] != 0) {
- len++;
+ /**
+ * Returns flags1 - currently unknown - usually 0x0002.
+ *
+ * @return the flags1
+ */
+ public short getFlags1() {
+ return flags1;
}
- len++;
- return len;
- }
- /**
- * Returns the value of the totalSize field - the total length of the structure
- * is totalSize + 4 (value of this field + size of this field).
- *
- * @return the totalSize
- */
- public int getTotalSize() {
- return totalSize;
- }
+ /**
+ * Returns the label field - usually the name of the file (without
+ * directory) but probably may be any name specified during
+ * packaging/embedding the data.
+ *
+ * @return the label
+ */
+ public String getLabel() {
+ return label;
+ }
- /**
- * Returns flags1 - currently unknown - usually 0x0002.
- *
- * @return the flags1
- */
- public short getFlags1() {
- return flags1;
- }
+ /**
+ * Returns the fileName field - usually the name of the file being embedded
+ * including the full path.
+ *
+ * @return the fileName
+ */
+ public String getFileName() {
+ return fileName;
+ }
- /**
- * Returns the label field - usually the name of the file (without directory) but
- * probably may be any name specified during packaging/embedding the data.
- *
- * @return the label
- */
- public String getLabel() {
- return label;
- }
+ /**
+ * Returns flags2 - currently unknown - mostly 0x0000.
+ *
+ * @return the flags2
+ */
+ public short getFlags2() {
+ return flags2;
+ }
- /**
- * Returns the fileName field - usually the name of the file being embedded
- * including the full path.
- *
- * @return the fileName
- */
- public String getFileName() {
- return fileName;
- }
+ /**
+ * Returns unknown1 field - currently unknown.
+ *
+ * @return the unknown1
+ */
+ public short getUnknown1() {
+ return unknown1;
+ }
- /**
- * Returns flags2 - currently unknown - mostly 0x0000.
- *
- * @return the flags2
- */
- public short getFlags2() {
- return flags2;
- }
+ /**
+ * Returns the command field - usually the name of the file being embedded
+ * including the full path, may be a command specified during embedding the
+ * file.
+ *
+ * @return the command
+ */
+ public String getCommand() {
+ return command;
+ }
- /**
- * Returns unknown1 field - currently unknown.
- * - * @return the unknown1 - */ - public short getUnknown1() { - return unknown1; - } - - /** - * Returns the command field - usually the name of the file being embedded - * including the full path, may be a command specified during embedding the file. - * - * @return the command
- */
- public String getCommand() {
- return command;
- }
+ /**
+ * Returns the size of the embedded file. If the size is 0 (zero), no data
+ * has been embedded. To be sure, that no data has been embedded, check
+ * whether {@link #getDataBuffer()} returns <code>null</code>.
+ *
+ * @return the dataSize
+ */
+ public int getDataSize() {
+ return dataBuffer.length;
+ }
- /**
- * Returns the size of the embedded file. If the size is 0 (zero), no data has been
- * embedded. To be sure, that no data has been embedded, check whether
- * {@link #getDataBuffer()} returns <code>null</code>.
- *
- * @return the dataSize - */ - public int getDataSize() { - return dataBuffer.length; - } - - /** - * Returns the buffer containing the embedded file's data, or <code>null</code>
- * if no data was embedded. Note that an embedding may provide information about
- * the data, but the actual data is not included. (So label, filename etc. are
- * available, but this method returns <code>null</code>.)
- *
- * @return the dataBuffer
- */
- public byte[] getDataBuffer() {
- return dataBuffer;
- }
+ /**
+ * Returns the buffer containing the embedded file's data, or
+ * <code>null</code> if no data was embedded. Note that an embedding may
+ * provide information about the data, but the actual data is not included.
+ * (So label, filename etc. are available, but this method returns
+ * <code>null</code>.)
+ *
+ * @return the dataBuffer
+ */
+ public byte[] getDataBuffer() {
+ return dataBuffer;
+ }
- /**
- * Returns the flags3 - currently unknown.
- *
- * @return the flags3
- */
- public short getFlags3() { - return flags3; - } - - /** - * Have the contents printer out into an OutputStream, used when writing a - * file back out to disk (Normally, atom classes will keep their bytes - * around, but non atom classes will just request the bytes from their - * children, then chuck on their header and return) - */ - public void writeOut(OutputStream out) throws IOException { - byte intbuf[] = new byte[LittleEndianConsts.INT_SIZE]; - byte shortbuf[] = new byte[LittleEndianConsts.SHORT_SIZE]; - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - bos.write(intbuf); // total size, will be determined later .. - - LittleEndian.putShort(shortbuf, 0, getFlags1()); - bos.write(shortbuf); - - bos.write(getLabel().getBytes(ISO1)); - bos.write(0); - - bos.write(getFileName().getBytes(ISO1)); - bos.write(0); - - LittleEndian.putShort(shortbuf, 0, getFlags2()); - bos.write(shortbuf); - - LittleEndian.putShort(shortbuf, 0, getUnknown1()); - bos.write(shortbuf); - - LittleEndian.putInt(intbuf, 0, getCommand().length()+1); - bos.write(intbuf); - - bos.write(getCommand().getBytes(ISO1)); - bos.write(0); - - LittleEndian.putInt(intbuf, 0, getDataBuffer().length); - bos.write(intbuf); - - bos.write(getDataBuffer()); - - LittleEndian.putShort(shortbuf, 0, getFlags3()); - bos.write(shortbuf); - - // update total size - length of length-field (4 bytes) - byte data[] = bos.toByteArray(); - totalSize = data.length - LittleEndianConsts.INT_SIZE; - LittleEndian.putInt(data, 0, totalSize); - - out.write(data); - } - - public void setFlags1(short flags1) { - this.flags1 = flags1; - } - - public void setFlags2(short flags2) { - this.flags2 = flags2; - } - - public void setFlags3(short flags3) { - this.flags3 = flags3; - } - - public void setLabel(String label) { - this.label = label; - } - - public void setFileName(String fileName) { - this.fileName = fileName; - } - - public void setCommand(String command) { - this.command = command; - } - - public void setUnknown1(short unknown1) { - this.unknown1 = unknown1; - } + /**
+ * Returns the flags3 - currently unknown.
+ *
+ * @return the flags3
+ */
+ public short getFlags3() {
+ return flags3;
+ }
+
+ /** + * Have the contents printer out into an OutputStream, used when writing a + * file back out to disk (Normally, atom classes will keep their bytes + * around, but non atom classes will just request the bytes from their + * children, then chuck on their header and return) + */ + public void writeOut(OutputStream out) throws IOException {
+ // byte intbuf[] = new byte[LittleEndianConsts.INT_SIZE];
+ // byte shortbuf[] = new byte[LittleEndianConsts.SHORT_SIZE];
+
+ @SuppressWarnings("resource")
+ LittleEndianOutputStream leosOut = new LittleEndianOutputStream(out);
+
+ switch (mode) {
+ case parsed: {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ LittleEndianOutputStream leos = new LittleEndianOutputStream(bos);
+ // total size, will be determined later ..
+
+ leos.writeShort(getFlags1());
+ leos.write(getLabel().getBytes(ISO1));
+ leos.write(0);
+ leos.write(getFileName().getBytes(ISO1));
+ leos.write(0);
+ leos.writeShort(getFlags2());
+ leos.writeShort(getUnknown1());
+ leos.writeInt(getCommand().length() + 1);
+ leos.write(getCommand().getBytes(ISO1));
+ leos.write(0);
+ leos.writeInt(getDataSize());
+ leos.write(getDataBuffer());
+ leos.writeShort(getFlags3());
+ leos.close(); // satisfy compiler ...
+
+ leosOut.writeInt(bos.size()); // total size
+ bos.writeTo(out);
+ break;
+ }
+ case compact:
+ leosOut.writeInt(getDataSize()+LittleEndianConsts.SHORT_SIZE);
+ leosOut.writeShort(getFlags1());
+ out.write(getDataBuffer());
+ break;
+ default:
+ case unparsed:
+ leosOut.writeInt(getDataSize());
+ out.write(getDataBuffer());
+ break;
+ }
+
+ }
- public void setDataBuffer(byte dataBuffer[]) { - this.dataBuffer = dataBuffer; - } + public void setFlags1(short flags1) {
+ this.flags1 = flags1;
+ }
+
+ public void setFlags2(short flags2) {
+ this.flags2 = flags2;
+ }
+
+ public void setFlags3(short flags3) {
+ this.flags3 = flags3;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+ public void setCommand(String command) {
+ this.command = command;
+ }
+
+ public void setUnknown1(short unknown1) {
+ this.unknown1 = unknown1;
+ }
+
+ public void setDataBuffer(byte dataBuffer[]) {
+ this.dataBuffer = dataBuffer;
+ }
} diff --git a/src/testcases/org/apache/poi/poifs/AllPOIFSTests.java b/src/testcases/org/apache/poi/poifs/AllPOIFSTests.java index d4f81f7ee2..012cc3b644 100644 --- a/src/testcases/org/apache/poi/poifs/AllPOIFSTests.java +++ b/src/testcases/org/apache/poi/poifs/AllPOIFSTests.java @@ -17,27 +17,24 @@ package org.apache.poi.poifs; -import junit.framework.Test; -import junit.framework.TestSuite; - import org.apache.poi.poifs.eventfilesystem.TestPOIFSReaderRegistry; import org.apache.poi.poifs.filesystem.AllPOIFSFileSystemTests; import org.apache.poi.poifs.nio.TestDataSource; import org.apache.poi.poifs.property.AllPOIFSPropertyTests; import org.apache.poi.poifs.storage.AllPOIFSStorageTests; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + /** * Test suite for all sub-packages of org.apache.poi.poifs - * - * @author Josh Micich */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + TestPOIFSReaderRegistry.class + , TestDataSource.class + , AllPOIFSFileSystemTests.class + , AllPOIFSPropertyTests.class + , AllPOIFSStorageTests.class +}) public final class AllPOIFSTests { - public static Test suite() { - TestSuite result = new TestSuite("Tests for org.apache.poi.poifs"); - result.addTestSuite(TestPOIFSReaderRegistry.class); - result.addTestSuite(TestDataSource.class); - result.addTest(AllPOIFSFileSystemTests.suite()); - result.addTest(AllPOIFSPropertyTests.suite()); - result.addTest(AllPOIFSStorageTests.suite()); - return result; - } } diff --git a/src/testcases/org/apache/poi/poifs/filesystem/AllPOIFSFileSystemTests.java b/src/testcases/org/apache/poi/poifs/filesystem/AllPOIFSFileSystemTests.java index bc46e17c9a..364aa1a6e2 100644 --- a/src/testcases/org/apache/poi/poifs/filesystem/AllPOIFSFileSystemTests.java +++ b/src/testcases/org/apache/poi/poifs/filesystem/AllPOIFSFileSystemTests.java @@ -17,31 +17,27 @@ package org.apache.poi.poifs.filesystem; -import junit.framework.Test; -import junit.framework.TestSuite; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; /** * Tests for org.apache.poi.poifs.filesystem<br/> - * - * @author Josh Micich */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + TestDirectoryNode.class + , TestDocument.class + , TestDocumentDescriptor.class + , TestDocumentInputStream.class + , TestDocumentNode.class + , TestDocumentOutputStream.class + , TestEmptyDocument.class + , TestOffice2007XMLException.class + , TestPOIFSDocumentPath.class + , TestPOIFSFileSystem.class + , TestNPOIFSFileSystem.class + , TestPropertySorter.class + , TestOle10Native.class +}) public final class AllPOIFSFileSystemTests { - - public static Test suite() { - TestSuite result = new TestSuite("Tests for org.apache.poi.poifs.filesystem"); - result.addTestSuite(TestDirectoryNode.class); - result.addTestSuite(TestDocument.class); - result.addTestSuite(TestDocumentDescriptor.class); - result.addTestSuite(TestDocumentInputStream.class); - result.addTestSuite(TestDocumentNode.class); - result.addTestSuite(TestDocumentOutputStream.class); - result.addTestSuite(TestEmptyDocument.class); - result.addTestSuite(TestOffice2007XMLException.class); - result.addTestSuite(TestPOIFSDocumentPath.class); - result.addTestSuite(TestPOIFSFileSystem.class); - result.addTestSuite(TestNPOIFSFileSystem.class); - result.addTestSuite(TestPropertySorter.class); - result.addTestSuite(TestOle10Native.class); - return result; - } } diff --git a/src/testcases/org/apache/poi/poifs/filesystem/TestOle10Native.java b/src/testcases/org/apache/poi/poifs/filesystem/TestOle10Native.java index 1ff45be73f..32f0f96ab6 100644 --- a/src/testcases/org/apache/poi/poifs/filesystem/TestOle10Native.java +++ b/src/testcases/org/apache/poi/poifs/filesystem/TestOle10Native.java @@ -17,14 +17,26 @@ package org.apache.poi.poifs.filesystem; -import junit.framework.TestCase; -import org.apache.poi.POIDataSamples; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.util.IOUtils; +import org.junit.Test; -public class TestOle10Native extends TestCase { +public class TestOle10Native { private static final POIDataSamples dataSamples = POIDataSamples.getPOIFSInstance(); + @Test public void testOleNative() throws IOException, Ole10NativeException { POIFSFileSystem fs = new POIFSFileSystem(dataSamples.openResourceAsStream("oleObject1.bin")); @@ -33,4 +45,66 @@ public class TestOle10Native extends TestCase { assertEquals("File1.svg", ole.getLabel()); assertEquals("D:\\Documents and Settings\\rsc\\My Documents\\file1.svg", ole.getCommand()); } + + @Test + public void testFiles() throws IOException, Ole10NativeException { + File files[] = { + // bug 51891 + POIDataSamples.getPOIFSInstance().getFile("multimedia.doc"), + // tika bug 1072 + POIDataSamples.getPOIFSInstance().getFile("20-Force-on-a-current-S00.doc"), + // other files containing ole10native records ... + POIDataSamples.getDocumentInstance().getFile("Bug53380_3.doc"), + POIDataSamples.getDocumentInstance().getFile("Bug47731.doc") + }; + + for (File f : files) { + NPOIFSFileSystem fs = new NPOIFSFileSystem(f, true); + List<Entry> entries = new ArrayList<Entry>(); + findOle10(entries, fs.getRoot(), "/", ""); + + for (Entry e : entries) { + ByteArrayOutputStream bosExp = new ByteArrayOutputStream(); + InputStream is = ((DirectoryNode)e.getParent()).createDocumentInputStream(e); + IOUtils.copy(is,bosExp); + is.close(); + + Ole10Native ole = Ole10Native.createFromEmbeddedOleObject((DirectoryNode)e.getParent()); + + ByteArrayOutputStream bosAct = new ByteArrayOutputStream(); + ole.writeOut(bosAct); + + assertThat(bosExp.toByteArray(), equalTo(bosAct.toByteArray())); + } + + fs.close(); + } + } + + /* + void searchOle10Files() throws Exception { + File dir = new File("test-data/document"); + for (File file : dir.listFiles(new FileFilter(){ + public boolean accept(File pathname) { + return pathname.getName().endsWith("doc"); + } + })) { + NPOIFSFileSystem fs = new NPOIFSFileSystem(file, true); + findOle10(null, fs.getRoot(), "/", file.getName()); + fs.close(); + } + }*/ + + void findOle10(List<Entry> entries, DirectoryNode dn, String path, String filename) { + Iterator<Entry> iter = dn.getEntries(); + while (iter.hasNext()) { + Entry e = iter.next(); + if (Ole10Native.OLE10_NATIVE.equals(e.getName())) { + if (entries != null) entries.add(e); + // System.out.println(filename+" : "+path); + } else if (e.isDirectoryEntry()) { + findOle10(entries, (DirectoryNode)e, path+e.getName()+"/", filename); + } + } + } } diff --git a/test-data/poifs/20-Force-on-a-current-S00.doc b/test-data/poifs/20-Force-on-a-current-S00.doc Binary files differnew file mode 100644 index 0000000000..3ad75ebc07 --- /dev/null +++ b/test-data/poifs/20-Force-on-a-current-S00.doc diff --git a/test-data/poifs/multimedia.doc b/test-data/poifs/multimedia.doc Binary files differnew file mode 100644 index 0000000000..51b356d4af --- /dev/null +++ b/test-data/poifs/multimedia.doc |