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.

UserEditAtom.java 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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 java.io.IOException;
  17. import java.io.OutputStream;
  18. import java.util.Collections;
  19. import java.util.LinkedHashMap;
  20. import java.util.Map;
  21. import java.util.function.Supplier;
  22. import org.apache.poi.hslf.exceptions.HSLFException;
  23. import org.apache.poi.util.LittleEndian;
  24. import org.apache.poi.util.LittleEndianConsts;
  25. /**
  26. * A UserEdit Atom (type 4085). Holds information which bits of the file
  27. * were last used by powerpoint, the version of powerpoint last used etc.
  28. *
  29. * ** WARNING ** stores byte offsets from the start of the PPT stream to
  30. * other records! If you change the size of any elements before one of
  31. * these, you'll need to update the offsets!
  32. */
  33. public final class UserEditAtom extends PositionDependentRecordAtom
  34. {
  35. public static final int LAST_VIEW_NONE = 0;
  36. public static final int LAST_VIEW_SLIDE_VIEW = 1;
  37. public static final int LAST_VIEW_OUTLINE_VIEW = 2;
  38. public static final int LAST_VIEW_NOTES = 3;
  39. private byte[] _header;
  40. private static final long _type = RecordTypes.UserEditAtom.typeID;
  41. private short unused;
  42. private int lastViewedSlideID;
  43. private int pptVersion;
  44. private int lastUserEditAtomOffset;
  45. private int persistPointersOffset;
  46. private int docPersistRef;
  47. private int maxPersistWritten;
  48. private short lastViewType;
  49. private int encryptSessionPersistIdRef = -1;
  50. // Somewhat user facing getters
  51. public int getLastViewedSlideID() { return lastViewedSlideID; }
  52. public short getLastViewType() { return lastViewType; }
  53. // Scary internal getters
  54. public int getLastUserEditAtomOffset() { return lastUserEditAtomOffset; }
  55. public int getPersistPointersOffset() { return persistPointersOffset; }
  56. public int getDocPersistRef() { return docPersistRef; }
  57. public int getMaxPersistWritten() { return maxPersistWritten; }
  58. public int getEncryptSessionPersistIdRef() { return encryptSessionPersistIdRef; }
  59. // More scary internal setters
  60. public void setLastUserEditAtomOffset(int offset) { lastUserEditAtomOffset = offset; }
  61. public void setPersistPointersOffset(int offset) { persistPointersOffset = offset; }
  62. public void setLastViewType(short type) { lastViewType=type; }
  63. public void setMaxPersistWritten(int max) { maxPersistWritten=max; }
  64. public void setEncryptSessionPersistIdRef(int id) {
  65. encryptSessionPersistIdRef=id;
  66. LittleEndian.putInt(_header,4,(id == -1 ? 28 : 32));
  67. }
  68. /* *************** record code follows ********************** */
  69. /**
  70. * For the UserEdit Atom
  71. */
  72. protected UserEditAtom(byte[] source, int start, int len) {
  73. // Sanity Checking
  74. if(len < 34) { len = 34; }
  75. int offset = start;
  76. // Get the header
  77. _header = new byte[8];
  78. System.arraycopy(source,offset,_header,0,8);
  79. offset += 8;
  80. // Get the last viewed slide ID
  81. lastViewedSlideID = LittleEndian.getInt(source,offset);
  82. offset += LittleEndianConsts.INT_SIZE;
  83. // Get the PPT version
  84. pptVersion = LittleEndian.getInt(source,offset);
  85. offset += LittleEndianConsts.INT_SIZE;
  86. // Get the offset to the previous incremental save's UserEditAtom
  87. // This will be the byte offset on disk where the previous one
  88. // starts, or 0 if this is the first one
  89. lastUserEditAtomOffset = LittleEndian.getInt(source,offset);
  90. offset += LittleEndianConsts.INT_SIZE;
  91. // Get the offset to the persist pointers
  92. // This will be the byte offset on disk where the preceding
  93. // PersistPtrFullBlock or PersistPtrIncrementalBlock starts
  94. persistPointersOffset = LittleEndian.getInt(source,offset);
  95. offset += LittleEndianConsts.INT_SIZE;
  96. // Get the persist reference for the document persist object
  97. // Normally seems to be 1
  98. docPersistRef = LittleEndian.getInt(source,offset);
  99. offset += LittleEndianConsts.INT_SIZE;
  100. // Maximum number of persist objects written
  101. maxPersistWritten = LittleEndian.getInt(source,offset);
  102. offset += LittleEndianConsts.INT_SIZE;
  103. // Last view type
  104. lastViewType = LittleEndian.getShort(source,offset);
  105. offset += LittleEndianConsts.SHORT_SIZE;
  106. // unused
  107. unused = LittleEndian.getShort(source,offset);
  108. offset += LittleEndianConsts.SHORT_SIZE;
  109. // There might be a few more bytes, which are a reserved field
  110. if (offset-start<len) {
  111. encryptSessionPersistIdRef = LittleEndian.getInt(source,offset);
  112. offset += LittleEndianConsts.INT_SIZE;
  113. }
  114. assert(offset-start == len);
  115. }
  116. /**
  117. * We are of type 4085
  118. */
  119. @Override
  120. public long getRecordType() { return _type; }
  121. /**
  122. * At write-out time, update the references to PersistPtrs and
  123. * other UserEditAtoms to point to their new positions
  124. */
  125. @Override
  126. public void updateOtherRecordReferences(Map<Integer,Integer> oldToNewReferencesLookup) {
  127. // Look up the new positions of our preceding UserEditAtomOffset
  128. if(lastUserEditAtomOffset != 0) {
  129. Integer newLocation = oldToNewReferencesLookup.get(Integer.valueOf(lastUserEditAtomOffset));
  130. if(newLocation == null) {
  131. throw new HSLFException("Couldn't find the new location of the UserEditAtom that used to be at " + lastUserEditAtomOffset);
  132. }
  133. lastUserEditAtomOffset = newLocation.intValue();
  134. }
  135. // Ditto for our PersistPtr
  136. Integer newLocation = oldToNewReferencesLookup.get(Integer.valueOf(persistPointersOffset));
  137. if(newLocation == null) {
  138. throw new HSLFException("Couldn't find the new location of the PersistPtr that used to be at " + persistPointersOffset);
  139. }
  140. persistPointersOffset = newLocation.intValue();
  141. }
  142. /**
  143. * Write the contents of the record back, so it can be written
  144. * to disk
  145. */
  146. @Override
  147. public void writeOut(OutputStream out) throws IOException {
  148. // Header
  149. out.write(_header);
  150. // Write out the values
  151. writeLittleEndian(lastViewedSlideID,out);
  152. writeLittleEndian(pptVersion,out);
  153. writeLittleEndian(lastUserEditAtomOffset,out);
  154. writeLittleEndian(persistPointersOffset,out);
  155. writeLittleEndian(docPersistRef,out);
  156. writeLittleEndian(maxPersistWritten,out);
  157. writeLittleEndian(lastViewType,out);
  158. writeLittleEndian(unused,out);
  159. if (encryptSessionPersistIdRef != -1) {
  160. // optional field
  161. writeLittleEndian(encryptSessionPersistIdRef,out);
  162. }
  163. }
  164. @Override
  165. public Map<String, Supplier<?>> getGenericProperties() {
  166. final Map<String, Supplier<?>> m = new LinkedHashMap<>();
  167. m.put("lastViewedSlideID", this::getLastViewedSlideID);
  168. m.put("pptVersion", () -> pptVersion);
  169. m.put("lastUserEditAtomOffset", this::getLastUserEditAtomOffset);
  170. m.put("persistPointersOffset", this::getPersistPointersOffset);
  171. m.put("docPersistRef", this::getDocPersistRef);
  172. m.put("maxPersistWritten", this::getMaxPersistWritten);
  173. m.put("lastViewType", this::getLastViewType);
  174. m.put("encryptSessionPersistIdRef", this::getEncryptSessionPersistIdRef);
  175. return Collections.unmodifiableMap(m);
  176. }
  177. }