| /* ==================================================================== |
| 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 static org.apache.poi.util.GenericRecordUtil.getBitsAsString; |
| import static org.apache.poi.util.GenericRecordUtil.safeEnum; |
| |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.util.Arrays; |
| import java.util.Map; |
| import java.util.function.Supplier; |
| |
| import org.apache.poi.util.GenericRecordJsonWriter; |
| import org.apache.poi.util.GenericRecordUtil; |
| import org.apache.poi.util.IOUtils; |
| import org.apache.poi.util.LittleEndian; |
| |
| /** |
| * Atom storing information for an OLE object. |
| * |
| * offset type name description |
| * |
| * 0 uint4 drawAspect Stores whether the object can be completely seen |
| * (value of 1), or if only the icon is visible (value of 4). |
| * |
| * 4 sint4 type Specifies whether the object is embedded or linked. |
| * 0 - embedded |
| * 1 - linked |
| * |
| * 8 sint4 objID Unique identifier for the OLE object |
| * |
| * 2 sint4 subType This specifies the type of ole object. |
| * 0 - Default object |
| * 1 - Microsoft Clipart Gallery |
| * 2 - Microsoft Word table |
| * 3 - Microsoft Excel |
| * 4 - Microsoft Graph |
| * 5 - Microsoft Organization Chart |
| * 6 - Microsoft Equation Editor |
| * 7 - Microsoft Wordart object |
| * 8 - Sound |
| * 9 - Image |
| * 10 - PowerPoint presentation |
| * 11 - PowerPoint slide |
| * 12 - Microsoft Project |
| * 13 - Microsoft Note-It Ole |
| * 14 - Microsoft Excel chart |
| * 15 - Media Player object |
| * |
| * 16 sint4 objStgDataRef Reference to persist object |
| * |
| * 20 bool1 isBlank Set if the object's image is blank |
| * (note: KOffice has this as an int.) |
| */ |
| public class ExOleObjAtom extends RecordAtom { |
| |
| public enum OleType { |
| /** An embedded OLE object; the object is serialized and saved within the file. */ |
| EMBEDDED, |
| /** A linked OLE object; the object is saved outside of the file. */ |
| LINKED, |
| /** The OLE object is an ActiveX control. */ |
| CONTROL |
| } |
| |
| public enum Subtype { |
| DEFAULT, |
| CLIPART_GALLERY, |
| WORD_TABLE, |
| EXCEL, |
| GRAPH, |
| ORGANIZATION_CHART, |
| EQUATION, |
| WORDART, |
| SOUND, |
| IMAGE, |
| POWERPOINT_PRESENTATION, |
| POWERPOINT_SLIDE, |
| PROJECT, |
| NOTEIT, |
| EXCEL_CHART, |
| MEDIA_PLAYER |
| } |
| |
| private static final int[] DRAWASPECT_MASKS = { |
| 0x0001, 0x0002, 0x0004, 0x0008 |
| }; |
| |
| private static final String[] DRAWASPECT_NAMES = { |
| "CONTENT", "THUMBNAIL", "ICON", "DOCPRINT" |
| }; |
| |
| //arbitrarily selected; may need to increase |
| private static final int MAX_RECORD_LENGTH = 10_485_760; |
| |
| /** |
| * The object) is displayed as an embedded object inside of a container, |
| */ |
| public static final int DRAW_ASPECT_VISIBLE = 1; |
| /** |
| * The object is displayed as a thumbnail image. |
| */ |
| public static final int DRAW_ASPECT_THUMBNAIL = 2; |
| /** |
| * The object is displayed as an icon. |
| */ |
| public static final int DRAW_ASPECT_ICON = 4; |
| /** |
| * The object is displayed on the screen as though it were printed to a printer. |
| */ |
| public static final int DRAW_ASPECT_DOCPRINT = 8; |
| |
| /** |
| * An embedded OLE object; the object is serialized and saved within the file. |
| */ |
| public static final int TYPE_EMBEDDED = 0; |
| /** |
| * A linked OLE object; the object is saved outside of the file. |
| */ |
| public static final int TYPE_LINKED = 1; |
| /** |
| * The OLE object is an ActiveX control. |
| */ |
| public static final int TYPE_CONTROL = 2; |
| |
| 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. |
| */ |
| public ExOleObjAtom() { |
| _header = new byte[8]; |
| _data = new byte[24]; |
| |
| LittleEndian.putShort(_header, 0, (short)1); //MUST be 0x1 |
| 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 ExOleObjAtom(byte[] source, int start, int len) { |
| // Get the header. |
| _header = Arrays.copyOfRange(source, start, start+8); |
| |
| // Get the record data. |
| _data = IOUtils.safelyClone(source, start+8, len-8, MAX_RECORD_LENGTH); |
| |
| // 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); |
| } |
| |
| /** |
| * Sets whether the object can be completely seen, or if only the |
| * icon is visible. |
| * |
| * @param aspect the draw aspect, one of the {@code DRAW_ASPECT_*} constants. |
| */ |
| public void setDrawAspect(int aspect) { |
| LittleEndian.putInt(_data, 0, aspect); |
| } |
| |
| /** |
| * 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); |
| } |
| |
| /** |
| * Sets whether the object is embedded or linked. |
| * |
| * @param type the type, one of the {@code TYPE_EMBEDDED_*} constants. |
| */ |
| public void setType(int type) { |
| LittleEndian.putInt(_data, 4, type); |
| } |
| |
| /** |
| * Gets the unique identifier for the OLE object. |
| * |
| * @return the object ID. |
| */ |
| public int getObjID() { |
| return LittleEndian.getInt(_data, 8); |
| } |
| |
| /** |
| * Sets the unique identifier for the OLE object. |
| * |
| * @param id the object ID. |
| */ |
| public void setObjID(int id) { |
| LittleEndian.putInt(_data, 8, id); |
| } |
| |
| /** |
| * Gets the type of OLE object. |
| * |
| * @return the sub-type, one of the {@code SUBTYPE_*} constants. |
| */ |
| public int getSubType() { |
| return LittleEndian.getInt(_data, 12); |
| } |
| |
| /** |
| * Sets the type of OLE object. |
| * |
| * @param type the sub-type, one of the {@code SUBTYPE_*} constants. |
| */ |
| public void setSubType(int type) { |
| LittleEndian.putInt(_data, 12, type); |
| } |
| |
| /** |
| * 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); |
| } |
| |
| /** |
| * Sets the reference to the persistent object |
| * |
| * @param ref the reference to the persistent object, corresponds with an |
| * {@code ExOleObjStg} storage container. |
| */ |
| public void setObjStgDataRef(int ref) { |
| LittleEndian.putInt(_data, 16, ref); |
| } |
| |
| /** |
| * 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; |
| } |
| |
| /** |
| * Gets misc options (the last four bytes in the atom). |
| * |
| * @return {@code true} if the object's image is blank. |
| */ |
| public int getOptions() { |
| // Even though this is a mere boolean, KOffice's code says it's an int. |
| return LittleEndian.getInt(_data, 20); |
| } |
| |
| /** |
| * Sets misc options (the last four bytes in the atom). |
| */ |
| public void setOptions(int opts) { |
| // Even though this is a mere boolean, KOffice's code says it's an int. |
| LittleEndian.putInt(_data, 20, opts); |
| } |
| |
| /** |
| * 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); |
| } |
| |
| public String toString() { |
| return GenericRecordJsonWriter.marshal(this); |
| } |
| |
| @Override |
| public Map<String, Supplier<?>> getGenericProperties() { |
| return GenericRecordUtil.getGenericProperties( |
| "drawAspect", getBitsAsString(this::getDrawAspect, DRAWASPECT_MASKS, DRAWASPECT_NAMES), |
| "type", safeEnum(OleType.values(), this::getType), |
| "objID", this::getObjID, |
| "subType", safeEnum(Subtype.values(), this::getSubType), |
| "objStgDataRef", this::getObjStgDataRef, |
| "options", this::getOptions |
| ); |
| } |
| } |