From a82e65ea7b4e16cca8b7441598b9e8baa9d914a6 Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Sat, 8 Sep 2007 16:12:29 +0000 Subject: [PATCH] Support for getting OLE object data from slide show. See Bug 43247 for details. git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@573872 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/poi/hslf/HSLFSlideShow.java | 66 ++++-- .../org/apache/poi/hslf/record/CString.java | 8 + .../org/apache/poi/hslf/record/ExEmbed.java | 188 ++++++++++++++++ .../apache/poi/hslf/record/ExEmbedAtom.java | 161 +++++++++++++ .../apache/poi/hslf/record/ExOleObjAtom.java | 213 ++++++++++++++++++ .../apache/poi/hslf/record/ExOleObjStg.java | 112 +++++++++ .../apache/poi/hslf/record/RecordTypes.java | 8 +- .../apache/poi/hslf/usermodel/ObjectData.java | 51 +++++ .../poi/hslf/data/ole2-embedding-2003.ppt | Bin 0 -> 40448 bytes .../poi/hslf/model/TestOleEmbedding.java | 62 +++++ 10 files changed, 847 insertions(+), 22 deletions(-) create mode 100644 src/scratchpad/src/org/apache/poi/hslf/record/ExEmbed.java create mode 100644 src/scratchpad/src/org/apache/poi/hslf/record/ExEmbedAtom.java create mode 100644 src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjAtom.java create mode 100644 src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjStg.java create mode 100644 src/scratchpad/src/org/apache/poi/hslf/usermodel/ObjectData.java create mode 100644 src/scratchpad/testcases/org/apache/poi/hslf/data/ole2-embedding-2003.ppt create mode 100644 src/scratchpad/testcases/org/apache/poi/hslf/model/TestOleEmbedding.java diff --git a/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java b/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java index e41bc3d5d..473b8f889 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java +++ b/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java @@ -20,28 +20,37 @@ package org.apache.poi.hslf; -import java.util.*; -import java.io.*; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; import org.apache.poi.POIDocument; -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.poifs.filesystem.DocumentEntry; -import org.apache.poi.poifs.filesystem.DocumentInputStream; - -import org.apache.poi.hpsf.PropertySet; -import org.apache.poi.hpsf.PropertySetFactory; -import org.apache.poi.hpsf.MutablePropertySet; -import org.apache.poi.hpsf.SummaryInformation; -import org.apache.poi.hpsf.DocumentSummaryInformation; - import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException; import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException; import org.apache.poi.hslf.exceptions.HSLFException; -import org.apache.poi.hslf.record.*; +import org.apache.poi.hslf.record.CurrentUserAtom; +import org.apache.poi.hslf.record.ExOleObjStg; +import org.apache.poi.hslf.record.PersistPtrHolder; +import org.apache.poi.hslf.record.PositionDependentRecord; +import org.apache.poi.hslf.record.Record; +import org.apache.poi.hslf.record.UserEditAtom; +import org.apache.poi.hslf.usermodel.ObjectData; import org.apache.poi.hslf.usermodel.PictureData; +import org.apache.poi.poifs.filesystem.DocumentEntry; +import org.apache.poi.poifs.filesystem.DocumentInputStream; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; /** * This class contains the main functionality for the Powerpoint file @@ -68,8 +77,11 @@ public class HSLFSlideShow extends POIDocument // Raw Pictures contained in the pictures stream private PictureData[] _pictures; - - /** + + // Embedded objects stored in storage records in the document stream, lazily populated. + private ObjectData[] _objects; + + /** * Returns the underlying POIFSFileSystem for the document * that is open. */ @@ -507,4 +519,22 @@ public class HSLFSlideShow extends POIDocument public PictureData[] getPictures() { return _pictures; } + + /** + * Gets embedded object data from the slide show. + * + * @return the embedded objects. + */ + public ObjectData[] getEmbeddedObjects() { + if (_objects == null) { + List objects = new ArrayList(); + for (int i = 0; i < _records.length; i++) { + if (_records[i] instanceof ExOleObjStg) { + objects.add(new ObjectData((ExOleObjStg) _records[i])); + } + } + _objects = (ObjectData[]) objects.toArray(new ObjectData[objects.size()]); + } + return _objects; + } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/CString.java b/src/scratchpad/src/org/apache/poi/hslf/record/CString.java index d51bf5e0a..b17efc40b 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/CString.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/CString.java @@ -111,4 +111,12 @@ public class CString extends RecordAtom { // Write out our text out.write(_text); } + + /** + * Gets a string representation of this object, primarily for debugging. + * @return a string representation of this object. + */ + public String toString() { + return getText(); + } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/ExEmbed.java b/src/scratchpad/src/org/apache/poi/hslf/record/ExEmbed.java new file mode 100644 index 000000000..a021d6b10 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/record/ExEmbed.java @@ -0,0 +1,188 @@ +/* ==================================================================== + 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.hslf.record; + +import java.io.OutputStream; +import java.io.IOException; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.POILogger; + +/** + * This data represents an embedded object in the document. + * + * @author Daniel Noll + */ +public class ExEmbed extends RecordContainer { + + /** + * Record header data. + */ + private byte[] _header; + + // Links to our more interesting children + private ExEmbedAtom embedAtom; + private ExOleObjAtom oleObjAtom; + private CString menuName; + private CString progId; + private CString clipboardName; + + /** + * Set things up, and find our more interesting children + * + * @param source the source data as a byte array. + * @param start the start offset into the byte array. + * @param len the length of the slice in the byte array. + */ + protected ExEmbed(byte[] source, int start, int len) { + // Grab the header + _header = new byte[8]; + System.arraycopy(source,start,_header,0,8); + + // Find our children + _children = Record.findChildRecords(source,start+8,len-8); + findInterestingChildren(); + } + + /** + * Create a new ExEmbed, with blank fields + */ + public ExEmbed() { + _header = new byte[8]; + _children = new Record[5]; + + // Setup our header block + _header[0] = 0x0f; // We are a container record + LittleEndian.putShort(_header, 2, (short)getRecordType()); + + // Setup our child records + CString cs1 = new CString(); + CString cs2 = new CString(); + CString cs3 = new CString(); +// cs1.setCount(0x00); +// cs2.setCount(0x10); + _children[0] = new ExEmbedAtom(); + _children[1] = new ExOleObjAtom(); + _children[2] = cs1; + _children[3] = cs2; + _children[4] = cs3; + findInterestingChildren(); + } + + /** + * Go through our child records, picking out the ones that are + * interesting, and saving those for use by the easy helper methods. + */ + private void findInterestingChildren() { + + // First child should be the ExHyperlinkAtom + if(_children[0] instanceof ExEmbedAtom) { + embedAtom = (ExEmbedAtom)_children[0]; + } else { + logger.log(POILogger.ERROR, "First child record wasn't a ExEmbedAtom, was of type " + _children[0].getRecordType()); + } + + // Second child should be the ExOleObjAtom + if (_children[1] instanceof ExOleObjAtom) { + oleObjAtom = (ExOleObjAtom)_children[1]; + } else { + logger.log(POILogger.ERROR, "Second child record wasn't a ExOleObjAtom, was of type " + _children[1].getRecordType()); + } + + for (int i = 2; i < _children.length; i++) { + if (_children[i] instanceof CString){ + if (menuName == null) menuName = (CString)_children[i]; + else if (progId == null) progId = (CString)_children[i]; + else if (clipboardName == null) clipboardName = (CString)_children[i]; + } else { + logger.log(POILogger.ERROR, "Record after atoms wasn't a CString, was of type " + _children[i].getRecordType()); + } + } + } + + /** + * Gets the {@code ExEmbedAtom}. + * + * @return the {@code ExEmbedAtom}. + */ + public ExEmbedAtom getExEmbedAtom() + { + return embedAtom; + } + + /** + * Gets the {@code ExOleObjAtom}. + * + * @return the {@code ExOleObjAtom}. + */ + public ExOleObjAtom getExOleObjAtom() + { + return oleObjAtom; + } + + /** + * Gets the name used for menus and the Links dialog box. + * + * @return the name used for menus and the Links dialog box. + */ + public String getMenuName() + { + return menuName == null ? null : menuName.getText(); + } + + /** + * Gets the OLE Programmatic Identifier. + * + * @return the OLE Programmatic Identifier. + */ + public String getProgId() + { + return progId == null ? null : progId.getText(); + } + + /** + * Gets the name that appears in the paste special dialog. + * + * @return the name that appears in the paste special dialog. + */ + public String getClipboardName() + { + return clipboardName == null ? null : clipboardName.getText(); + } + + /** + * Returns the type (held as a little endian in bytes 3 and 4) + * that this class handles. + * + * @return the record type. + */ + public long getRecordType() { + return RecordTypes.ExEmbed.typeID; + } + + /** + * Have the contents printer out into an OutputStream, used when + * writing a file back out to disk. + * + * @param out the output stream. + * @throws IOException if there was an error writing to the stream. + */ + public void writeOut(OutputStream out) throws IOException { + writeOut(_header[0],_header[1],getRecordType(),_children,out); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/ExEmbedAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/ExEmbedAtom.java new file mode 100644 index 000000000..d2344c415 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/record/ExEmbedAtom.java @@ -0,0 +1,161 @@ +/* ==================================================================== + 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.hslf.record; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.poi.util.LittleEndian; + +/** + * The atom that holds metadata on a specific embedded object in the document. + * + * + * + * @author Daniel Noll + */ +public class ExEmbedAtom extends RecordAtom { + + /** + * Embedded document does not follow the color scheme. + */ + public static final int DOES_NOT_FOLLOW_COLOR_SCHEME = 0; + + /** + * Embedded document follows the entire color scheme. + */ + public static final int FOLLOWS_ENTIRE_COLOR_SCHEME = 1; + + /** + * Embedded document follows the text and background scheme. + */ + public static final int FOLLOWS_TEXT_AND_BACKGROUND_SCHEME = 2; + + /** + * Record header. + */ + private byte[] _header; + + /** + * Record data. + */ + private byte[] _data; + + /** + * Constructs a brand new embedded object atom record. + */ + protected ExEmbedAtom() { + _header = new byte[8]; + _data = new byte[7]; + + LittleEndian.putShort(_header, 2, (short)getRecordType()); + LittleEndian.putInt(_header, 4, _data.length); + + // It is fine for the other values to be zero + } + + /** + * Constructs the embedded object atom record from its source data. + * + * @param source the source data as a byte array. + * @param start the start offset into the byte array. + * @param len the length of the slice in the byte array. + */ + protected ExEmbedAtom(byte[] source, int start, int len) { + // Get the header. + _header = new byte[8]; + System.arraycopy(source,start,_header,0,8); + + // Get the record data. + _data = new byte[len-8]; + System.arraycopy(source,start+8,_data,0,len-8); + + // Must be at least 4 bytes long + if(_data.length < 7) { + throw new IllegalArgumentException("The length of the data for a ExEmbedAtom must be at least 4 bytes, but was only " + _data.length); + } + } + + /** + * Gets whether the object follows the color scheme. + * + * @return one of {@link #DOES_NOT_FOLLOW_COLOR_SCHEME}, + * {@link #FOLLOWS_ENTIRE_COLOR_SCHEME}, or + * {@link #FOLLOWS_TEXT_AND_BACKGROUND_SCHEME}. + */ + public int getFollowColorScheme() { + return LittleEndian.getInt(_data, 0); + } + + /** + * Gets whether the embedded server cannot be locked. + * + * @return {@code true} if the embedded server cannot be locked. + */ + public boolean getCantLockServerB() { + return _data[4] != 0; + } + + /** + * Gets whether it is not required to send the dimensions to the embedded object. + * + * @return {@code true} if the embedded server does not require the object dimensions. + */ + public boolean getNoSizeToServerB() { + return _data[5] != 0; + } + + /** + * Getswhether the object is a Word table. + * + * @return {@code true} if the object is a Word table. + */ + public boolean getIsTable() { + return _data[6] != 0; + } + + /** + * Gets the record type. + * @return the record type. + */ + public long getRecordType() { + return RecordTypes.ExEmbedAtom.typeID; + } + + /** + * Write the contents of the record back, so it can be written + * to disk + * + * @param out the output stream to write to. + * @throws IOException if an error occurs. + */ + public void writeOut(OutputStream out) throws IOException { + out.write(_header); + out.write(_data); + } + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjAtom.java new file mode 100644 index 000000000..ae96275cd --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjAtom.java @@ -0,0 +1,213 @@ +/* ==================================================================== + 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.hslf.record; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.poi.util.LittleEndian; + +/** + * Atom storing information for an OLE object. + * + * + * + * @author Daniel Noll + */ +public class ExOleObjAtom extends RecordAtom { + + public static final int DRAW_ASPECT_VISIBLE = 1; + public static final int DRAW_ASPECT_ICON = 4; + + public static final int TYPE_EMBEDDED = 0; + public static final int TYPE_LINKED = 1; + + public static final int SUBTYPE_DEFAULT = 0; + public static final int SUBTYPE_CLIPART_GALLERY = 1; + public static final int SUBTYPE_WORD_TABLE = 2; + public static final int SUBTYPE_EXCEL = 3; + public static final int SUBTYPE_GRAPH = 4; + public static final int SUBTYPE_ORGANIZATION_CHART = 5; + public static final int SUBTYPE_EQUATION = 6; + public static final int SUBTYPE_WORDART = 7; + public static final int SUBTYPE_SOUND = 8; + public static final int SUBTYPE_IMAGE = 9; + public static final int SUBTYPE_POWERPOINT_PRESENTATION = 10; + public static final int SUBTYPE_POWERPOINT_SLIDE = 11; + public static final int SUBTYPE_PROJECT = 12; + public static final int SUBTYPE_NOTEIT = 13; + public static final int SUBTYPE_EXCEL_CHART = 14; + public static final int SUBTYPE_MEDIA_PLAYER = 15; + + /** + * Record header. + */ + private byte[] _header; + + /** + * Record data. + */ + private byte[] _data; + + /** + * Constructs a brand new link related atom record. + */ + protected ExOleObjAtom() { + _header = new byte[8]; + _data = new byte[18]; + + LittleEndian.putShort(_header, 2, (short)getRecordType()); + LittleEndian.putInt(_header, 4, _data.length); + + // I hope it is fine for the other values to be zero. + } + + /** + * Constructs the link related atom record from its + * source data. + * + * @param source the source data as a byte array. + * @param start the start offset into the byte array. + * @param len the length of the slice in the byte array. + */ + protected ExOleObjAtom(byte[] source, int start, int len) { + // Get the header. + _header = new byte[8]; + System.arraycopy(source,start,_header,0,8); + + // Get the record data. + _data = new byte[len-8]; + System.arraycopy(source,start+8,_data,0,len-8); + + // Must be at least 24 bytes long + if(_data.length < 24) { + throw new IllegalArgumentException("The length of the data for a ExOleObjAtom must be at least 24 bytes, but was only " + _data.length); + } + } + + /** + * Gets whether the object can be completely seen, or if only the + * icon is visible. + * + * @return the draw aspect, one of the {@code DRAW_ASPECT_*} constants. + */ + public int getDrawAspect() { + return LittleEndian.getInt(_data, 0); + } + + /** + * Gets whether the object is embedded or linked. + * + * @return the type, one of the {@code TYPE_EMBEDDED_*} constants. + */ + public int getType() { + return LittleEndian.getInt(_data, 4); + } + + /** + * Gets the unique identifier for the OLE object. + * + * @return the object ID. + */ + public int getObjID() { + return LittleEndian.getInt(_data, 8); + } + + /** + * Gets the type of OLE object. + * + * @return the sub-type, one of the {@code SUBTYPE_*} constants. + */ + public int getSubType() { + return LittleEndian.getInt(_data, 12); + } + + /** + * Gets the reference to the persistent object + * + * @return the reference to the persistent object, corresponds with an + * {@code ExOleObjStg} storage container. + */ + public int getObjStgDataRef() { + return LittleEndian.getInt(_data, 16); + } + + /** + * Gets whether the object's image is blank. + * + * @return {@code true} if the object's image is blank. + */ + public boolean getIsBlank() { + // Even though this is a mere boolean, KOffice's code says it's an int. + return LittleEndian.getInt(_data, 20) != 0; + } + + /** + * Returns the type (held as a little endian in bytes 3 and 4) + * that this class handles. + */ + public long getRecordType() { + return RecordTypes.ExOleObjAtom.typeID; + } + + /** + * 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 { + out.write(_header); + out.write(_data); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjStg.java b/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjStg.java new file mode 100644 index 000000000..7c4742792 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjStg.java @@ -0,0 +1,112 @@ +/* ==================================================================== + 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.hslf.record; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.zip.InflaterInputStream; + +import org.apache.poi.util.LittleEndian; + +/** + * Storage for embedded OLE objects. + * + * @author Daniel Noll + */ +public class ExOleObjStg extends RecordAtom { + /** + * Record header. + */ + private byte[] _header; + + /** + * Record data. + */ + private byte[] _data; + + /** + * Constructs a new empty storage container. + */ + protected ExOleObjStg() { + _header = new byte[8]; + _data = new byte[0]; + + LittleEndian.putShort(_header, 2, (short)getRecordType()); + LittleEndian.putInt(_header, 4, _data.length); + } + + /** + * Constructs the link related atom record from its + * source data. + * + * @param source the source data as a byte array. + * @param start the start offset into the byte array. + * @param len the length of the slice in the byte array. + */ + protected ExOleObjStg(byte[] source, int start, int len) { + // Get the header. + _header = new byte[8]; + System.arraycopy(source,start,_header,0,8); + + // Get the record data. + _data = new byte[len-8]; + System.arraycopy(source,start+8,_data,0,len-8); + } + + /** + * Gets the uncompressed length of the data. + * + * @return the uncompressed length of the data. + */ + public int getDataLength() { + return LittleEndian.getInt(_data, 0); + } + + /** + * Opens an input stream which will decompress the data on the fly. + * + * @return the data input stream. + */ + public InputStream getData() { + InputStream compressedStream = new ByteArrayInputStream(_data, 4, _data.length); + return new InflaterInputStream(compressedStream); + } + + /** + * Gets the record type. + * + * @return the record type. + */ + public long getRecordType() { + return RecordTypes.ExOleObjStg.typeID; + } + + /** + * Write the contents of the record back, so it can be written + * to disk. + * + * @param out the output stream to write to. + * @throws IOException if an error occurs. + */ + public void writeOut(OutputStream out) throws IOException { + out.write(_header); + out.write(_data); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java b/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java index 3c8d3aa41..69173bf5b 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java @@ -98,11 +98,11 @@ public class RecordTypes { public static final Type FontEmbeddedData = new Type(4024,null); public static final Type CString = new Type(4026,CString.class); public static final Type MetaFile = new Type(4033,null); - public static final Type ExOleObjAtom = new Type(4035,null); + public static final Type ExOleObjAtom = new Type(4035,ExOleObjAtom.class); public static final Type SrKinsoku = new Type(4040,null); public static final Type HandOut = new Type(4041,null); - public static final Type ExEmbed = new Type(4044,null); - public static final Type ExEmbedAtom = new Type(4045,null); + public static final Type ExEmbed = new Type(4044,ExEmbed.class); + public static final Type ExEmbedAtom = new Type(4045,ExEmbedAtom.class); public static final Type ExLink = new Type(4046,null); public static final Type BookmarkEntityAtom = new Type(4048,null); public static final Type ExLinkAtom = new Type(4049,null); @@ -136,7 +136,7 @@ public class RecordTypes { public static final Type ExCDAudio = new Type(4110,null); public static final Type ExWAVAudioEmbedded = new Type(4111,null); public static final Type ExWAVAudioLink = new Type(4112,null); - public static final Type ExOleObjStg = new Type(4113,null); + public static final Type ExOleObjStg = new Type(4113,ExOleObjStg.class); public static final Type ExCDAudioAtom = new Type(4114,null); public static final Type ExWAVAudioEmbeddedAtom = new Type(4115,null); public static final Type AnimationInfoAtom = new Type(4116,null); diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/ObjectData.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/ObjectData.java new file mode 100644 index 000000000..66b4f0373 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/ObjectData.java @@ -0,0 +1,51 @@ +/* ==================================================================== + 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.hslf.usermodel; + +import java.io.InputStream; + +import org.apache.poi.hslf.record.ExOleObjStg; + +/** + * A class that represents object data embedded in a slide show. + * + * @author Daniel Noll + */ +public class ObjectData { + /** + * The record that contains the object data. + */ + private ExOleObjStg storage; + + /** + * Creates the object data wrapping the record that contains the object data. + * + * @param storage the record that contains the object data. + */ + public ObjectData(ExOleObjStg storage) { + this.storage = storage; + } + + /** + * Gets an input stream which returns the binary of the embedded data. + * + * @return the input stream which will contain the binary of the embedded data. + */ + public InputStream getData() { + return storage.getData(); + } +} diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/data/ole2-embedding-2003.ppt b/src/scratchpad/testcases/org/apache/poi/hslf/data/ole2-embedding-2003.ppt new file mode 100644 index 0000000000000000000000000000000000000000..506888fdbbf8d7d8c5ffbb43d1a2fcb6db471c8d GIT binary patch literal 40448 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