You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ExOleObjAtom.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.hslf.record;
  16. import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
  17. import static org.apache.poi.util.GenericRecordUtil.safeEnum;
  18. import java.io.IOException;
  19. import java.io.OutputStream;
  20. import java.util.Map;
  21. import java.util.function.Supplier;
  22. import org.apache.poi.util.GenericRecordJsonWriter;
  23. import org.apache.poi.util.GenericRecordUtil;
  24. import org.apache.poi.util.IOUtils;
  25. import org.apache.poi.util.LittleEndian;
  26. /**
  27. * Atom storing information for an OLE object.
  28. *
  29. * offset type name description
  30. *
  31. * 0 uint4 drawAspect Stores whether the object can be completely seen
  32. * (value of 1), or if only the icon is visible (value of 4).
  33. *
  34. * 4 sint4 type Specifies whether the object is embedded or linked.
  35. * 0 - embedded
  36. * 1 - linked
  37. *
  38. * 8 sint4 objID Unique identifier for the OLE object
  39. *
  40. * 2 sint4 subType This specifies the type of ole object.
  41. * 0 - Default object
  42. * 1 - Microsoft Clipart Gallery
  43. * 2 - Microsoft Word table
  44. * 3 - Microsoft Excel
  45. * 4 - Microsoft Graph
  46. * 5 - Microsoft Organization Chart
  47. * 6 - Microsoft Equation Editor
  48. * 7 - Microsoft Wordart object
  49. * 8 - Sound
  50. * 9 - Image
  51. * 10 - PowerPoint presentation
  52. * 11 - PowerPoint slide
  53. * 12 - Microsoft Project
  54. * 13 - Microsoft Note-It Ole
  55. * 14 - Microsoft Excel chart
  56. * 15 - Media Player object
  57. *
  58. * 16 sint4 objStgDataRef Reference to persist object
  59. *
  60. * 20 bool1 isBlank Set if the object's image is blank
  61. * (note: KOffice has this as an int.)
  62. */
  63. public class ExOleObjAtom extends RecordAtom {
  64. public enum OleType {
  65. /** An embedded OLE object; the object is serialized and saved within the file. */
  66. EMBEDDED,
  67. /** A linked OLE object; the object is saved outside of the file. */
  68. LINKED,
  69. /** The OLE object is an ActiveX control. */
  70. CONTROL
  71. }
  72. public enum Subtype {
  73. DEFAULT,
  74. CLIPART_GALLERY,
  75. WORD_TABLE,
  76. EXCEL,
  77. GRAPH,
  78. ORGANIZATION_CHART,
  79. EQUATION,
  80. WORDART,
  81. SOUND,
  82. IMAGE,
  83. POWERPOINT_PRESENTATION,
  84. POWERPOINT_SLIDE,
  85. PROJECT,
  86. NOTEIT,
  87. EXCEL_CHART,
  88. MEDIA_PLAYER
  89. }
  90. private static final int[] DRAWASPECT_MASKS = {
  91. 0x0001, 0x0002, 0x0004, 0x0008
  92. };
  93. private static final String[] DRAWASPECT_NAMES = {
  94. "CONTENT", "THUMBNAIL", "ICON", "DOCPRINT"
  95. };
  96. //arbitrarily selected; may need to increase
  97. private static final int MAX_RECORD_LENGTH = 10_485_760;
  98. /**
  99. * The object) is displayed as an embedded object inside of a container,
  100. */
  101. public static final int DRAW_ASPECT_VISIBLE = 1;
  102. /**
  103. * The object is displayed as a thumbnail image.
  104. */
  105. public static final int DRAW_ASPECT_THUMBNAIL = 2;
  106. /**
  107. * The object is displayed as an icon.
  108. */
  109. public static final int DRAW_ASPECT_ICON = 4;
  110. /**
  111. * The object is displayed on the screen as though it were printed to a printer.
  112. */
  113. public static final int DRAW_ASPECT_DOCPRINT = 8;
  114. /**
  115. * An embedded OLE object; the object is serialized and saved within the file.
  116. */
  117. public static final int TYPE_EMBEDDED = 0;
  118. /**
  119. * A linked OLE object; the object is saved outside of the file.
  120. */
  121. public static final int TYPE_LINKED = 1;
  122. /**
  123. * The OLE object is an ActiveX control.
  124. */
  125. public static final int TYPE_CONTROL = 2;
  126. public static final int SUBTYPE_DEFAULT = 0;
  127. public static final int SUBTYPE_CLIPART_GALLERY = 1;
  128. public static final int SUBTYPE_WORD_TABLE = 2;
  129. public static final int SUBTYPE_EXCEL = 3;
  130. public static final int SUBTYPE_GRAPH = 4;
  131. public static final int SUBTYPE_ORGANIZATION_CHART = 5;
  132. public static final int SUBTYPE_EQUATION = 6;
  133. public static final int SUBTYPE_WORDART = 7;
  134. public static final int SUBTYPE_SOUND = 8;
  135. public static final int SUBTYPE_IMAGE = 9;
  136. public static final int SUBTYPE_POWERPOINT_PRESENTATION = 10;
  137. public static final int SUBTYPE_POWERPOINT_SLIDE = 11;
  138. public static final int SUBTYPE_PROJECT = 12;
  139. public static final int SUBTYPE_NOTEIT = 13;
  140. public static final int SUBTYPE_EXCEL_CHART = 14;
  141. public static final int SUBTYPE_MEDIA_PLAYER = 15;
  142. /**
  143. * Record header.
  144. */
  145. private byte[] _header;
  146. /**
  147. * Record data.
  148. */
  149. private byte[] _data;
  150. /**
  151. * Constructs a brand new link related atom record.
  152. */
  153. public ExOleObjAtom() {
  154. _header = new byte[8];
  155. _data = new byte[24];
  156. LittleEndian.putShort(_header, 0, (short)1); //MUST be 0x1
  157. LittleEndian.putShort(_header, 2, (short)getRecordType());
  158. LittleEndian.putInt(_header, 4, _data.length);
  159. }
  160. /**
  161. * Constructs the link related atom record from its
  162. * source data.
  163. *
  164. * @param source the source data as a byte array.
  165. * @param start the start offset into the byte array.
  166. * @param len the length of the slice in the byte array.
  167. */
  168. protected ExOleObjAtom(byte[] source, int start, int len) {
  169. // Get the header.
  170. _header = new byte[8];
  171. System.arraycopy(source,start,_header,0,8);
  172. // Get the record data.
  173. _data = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH);
  174. System.arraycopy(source,start+8,_data,0,len-8);
  175. // Must be at least 24 bytes long
  176. if(_data.length < 24) {
  177. throw new IllegalArgumentException("The length of the data for a ExOleObjAtom must be at least 24 bytes, but was only " + _data.length);
  178. }
  179. }
  180. /**
  181. * Gets whether the object can be completely seen, or if only the
  182. * icon is visible.
  183. *
  184. * @return the draw aspect, one of the {@code DRAW_ASPECT_*} constants.
  185. */
  186. public int getDrawAspect() {
  187. return LittleEndian.getInt(_data, 0);
  188. }
  189. /**
  190. * Sets whether the object can be completely seen, or if only the
  191. * icon is visible.
  192. *
  193. * @param aspect the draw aspect, one of the {@code DRAW_ASPECT_*} constants.
  194. */
  195. public void setDrawAspect(int aspect) {
  196. LittleEndian.putInt(_data, 0, aspect);
  197. }
  198. /**
  199. * Gets whether the object is embedded or linked.
  200. *
  201. * @return the type, one of the {@code TYPE_EMBEDDED_*} constants.
  202. */
  203. public int getType() {
  204. return LittleEndian.getInt(_data, 4);
  205. }
  206. /**
  207. * Sets whether the object is embedded or linked.
  208. *
  209. * @param type the type, one of the {@code TYPE_EMBEDDED_*} constants.
  210. */
  211. public void setType(int type) {
  212. LittleEndian.putInt(_data, 4, type);
  213. }
  214. /**
  215. * Gets the unique identifier for the OLE object.
  216. *
  217. * @return the object ID.
  218. */
  219. public int getObjID() {
  220. return LittleEndian.getInt(_data, 8);
  221. }
  222. /**
  223. * Sets the unique identifier for the OLE object.
  224. *
  225. * @param id the object ID.
  226. */
  227. public void setObjID(int id) {
  228. LittleEndian.putInt(_data, 8, id);
  229. }
  230. /**
  231. * Gets the type of OLE object.
  232. *
  233. * @return the sub-type, one of the {@code SUBTYPE_*} constants.
  234. */
  235. public int getSubType() {
  236. return LittleEndian.getInt(_data, 12);
  237. }
  238. /**
  239. * Sets the type of OLE object.
  240. *
  241. * @param type the sub-type, one of the {@code SUBTYPE_*} constants.
  242. */
  243. public void setSubType(int type) {
  244. LittleEndian.putInt(_data, 12, type);
  245. }
  246. /**
  247. * Gets the reference to the persistent object
  248. *
  249. * @return the reference to the persistent object, corresponds with an
  250. * {@code ExOleObjStg} storage container.
  251. */
  252. public int getObjStgDataRef() {
  253. return LittleEndian.getInt(_data, 16);
  254. }
  255. /**
  256. * Sets the reference to the persistent object
  257. *
  258. * @param ref the reference to the persistent object, corresponds with an
  259. * {@code ExOleObjStg} storage container.
  260. */
  261. public void setObjStgDataRef(int ref) {
  262. LittleEndian.putInt(_data, 16, ref);
  263. }
  264. /**
  265. * Gets whether the object's image is blank.
  266. *
  267. * @return {@code true} if the object's image is blank.
  268. */
  269. public boolean getIsBlank() {
  270. // Even though this is a mere boolean, KOffice's code says it's an int.
  271. return LittleEndian.getInt(_data, 20) != 0;
  272. }
  273. /**
  274. * Gets misc options (the last four bytes in the atom).
  275. *
  276. * @return {@code true} if the object's image is blank.
  277. */
  278. public int getOptions() {
  279. // Even though this is a mere boolean, KOffice's code says it's an int.
  280. return LittleEndian.getInt(_data, 20);
  281. }
  282. /**
  283. * Sets misc options (the last four bytes in the atom).
  284. */
  285. public void setOptions(int opts) {
  286. // Even though this is a mere boolean, KOffice's code says it's an int.
  287. LittleEndian.putInt(_data, 20, opts);
  288. }
  289. /**
  290. * Returns the type (held as a little endian in bytes 3 and 4)
  291. * that this class handles.
  292. */
  293. public long getRecordType() {
  294. return RecordTypes.ExOleObjAtom.typeID;
  295. }
  296. /**
  297. * Have the contents printer out into an OutputStream, used when
  298. * writing a file back out to disk
  299. * (Normally, atom classes will keep their bytes around, but
  300. * non atom classes will just request the bytes from their
  301. * children, then chuck on their header and return)
  302. */
  303. public void writeOut(OutputStream out) throws IOException {
  304. out.write(_header);
  305. out.write(_data);
  306. }
  307. public String toString() {
  308. return GenericRecordJsonWriter.marshal(this);
  309. }
  310. @Override
  311. public Map<String, Supplier<?>> getGenericProperties() {
  312. return GenericRecordUtil.getGenericProperties(
  313. "drawAspect", getBitsAsString(this::getDrawAspect, DRAWASPECT_MASKS, DRAWASPECT_NAMES),
  314. "type", safeEnum(OleType.values(), this::getType),
  315. "objID", this::getObjID,
  316. "subType", safeEnum(Subtype.values(), this::getSubType),
  317. "objStgDataRef", this::getObjStgDataRef,
  318. "options", this::getOptions
  319. );
  320. }
  321. }