Author: kiwiwings
Date: Fri Dec 27 00:22:19 2013
New Revision: 1553610
URL: http://svn.apache.org/r1553610
Log:
Bug 48593 - [PATCH] Multiple Saves Causes Slide Corruption
Added:
poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/HSLFTestDataSamples.java
Modified:
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjStg.java
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java
poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/TestReWrite.java
Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java?rev=1553610&r1=1553609&r2=1553610&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java
(original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java Fri Dec
27 00:22:19 2013
@@ -29,6 +29,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
+import java.util.Map;
import org.apache.poi.POIDocument;
import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
@@ -40,12 +41,14 @@ import org.apache.poi.hslf.record.Persis
import org.apache.poi.hslf.record.PersistRecord;
import org.apache.poi.hslf.record.PositionDependentRecord;
import org.apache.poi.hslf.record.Record;
+import org.apache.poi.hslf.record.RecordTypes;
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.DirectoryNode;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.DocumentInputStream;
+import org.apache.poi.poifs.filesystem.EntryUtils;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.LittleEndian;
@@ -59,6 +62,8 @@ import org.apache.poi.util.POILogger;
* @author Nick Burch
*/
public final class HSLFSlideShow extends POIDocument {
+ public static final int UNSET_OFFSET = -1;
+
// For logging
private POILogger logger = POILogFactory.getLogger(this.getClass());
@@ -346,6 +351,7 @@ public final class HSLFSlideShow extends
int offset = pos;
// Image signature
+ @SuppressWarnings("unused")
int signature = LittleEndian.getUShort(pictstream, pos);
pos += LittleEndian.SHORT_SIZE;
// Image type + 0xF018
@@ -392,7 +398,88 @@ public final class HSLFSlideShow extends
}
}
+ /**
+ * This is a helper functions, which is needed for adding new position
dependent records
+ * or finally write the slideshow to a file.
+ *
+ * @param os the stream to write to, if null only the references are
updated
+ * @param interestingRecords a map of interesting records
(PersistPtrHolder and UserEditAtom)
+ * referenced by their RecordType. Only the very last of each
type will be saved to the map.
+ * May be null, if not needed.
+ * @throws IOException
+ */
+ public void updateAndWriteDependantRecords(OutputStream os,
Map<RecordTypes.Type,PositionDependentRecord> interestingRecords)
+ throws IOException {
+ // For position dependent records, hold where they were and now are
+ // As we go along, update, and hand over, to any Position Dependent
+ // records we happen across
+ Hashtable<Integer,Integer> oldToNewPositions = new
Hashtable<Integer,Integer>();
+
+ // First pass - figure out where all the position dependent
+ // records are going to end up, in the new scheme
+ // (Annoyingly, some powerpoint files have PersistPtrHolders
+ // that reference slides after the PersistPtrHolder)
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ for (Record record : _records) {
+ if(record instanceof PositionDependentRecord) {
+ PositionDependentRecord pdr = (PositionDependentRecord)record;
+ int oldPos = pdr.getLastOnDiskOffset();
+ int newPos = baos.size();
+ pdr.setLastOnDiskOffset(newPos);
+ if (oldPos != UNSET_OFFSET) {
+ // new records don't need a mapping, as they aren't in a
relation yet
+
oldToNewPositions.put(Integer.valueOf(oldPos),Integer.valueOf(newPos));
+ }
+ }
+
+ // Dummy write out, so the position winds on properly
+ record.writeOut(baos);
+ }
+ baos = null;
+
+ // For now, we're only handling PositionDependentRecord's that
+ // happen at the top level.
+ // In future, we'll need the handle them everywhere, but that's
+ // a bit trickier
+ UserEditAtom usr = null;
+ for (Record record : _records) {
+ if (record instanceof PositionDependentRecord) {
+ // We've already figured out their new location, and
+ // told them that
+ // Tell them of the positions of the other records though
+ PositionDependentRecord pdr = (PositionDependentRecord)record;
+ pdr.updateOtherRecordReferences(oldToNewPositions);
+
+ // Grab interesting records as they come past
+ // this will only save the very last record of each type
+ RecordTypes.Type saveme = null;
+ int recordType = (int)record.getRecordType();
+ if (recordType ==
RecordTypes.PersistPtrIncrementalBlock.typeID) {
+ saveme = RecordTypes.PersistPtrIncrementalBlock;
+ } else if (recordType == RecordTypes.UserEditAtom.typeID) {
+ saveme = RecordTypes.UserEditAtom;
+ usr = (UserEditAtom)pdr;
+ }
+ if (interestingRecords != null && saveme != null) {
+ interestingRecords.put(saveme,pdr);
+ }
+ }
+
+ // Whatever happens, write out that record tree
+ if (os != null) {
+ record.writeOut(os);
+ }
+ }
+ // Update and write out the Current User atom
+ int oldLastUserEditAtomPos = (int)currentUser.getCurrentEditOffset();
+ Integer newLastUserEditAtomPos =
oldToNewPositions.get(oldLastUserEditAtomPos);
+ if(usr == null || newLastUserEditAtomPos == null ||
usr.getLastOnDiskOffset() != newLastUserEditAtomPos) {
+ throw new HSLFException("Couldn't find the new location of the
last UserEditAtom that used to be at " + oldLastUserEditAtomPos);
+ }
+ currentUser.setCurrentEditOffset(usr.getLastOnDiskOffset());
+ }
+
/**
* Writes out the slideshow file the is represented by an instance
* of this class.
@@ -426,49 +513,13 @@ public final class HSLFSlideShow extends
// Write out the Property Streams
writeProperties(outFS, writtenEntries);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
// For position dependent records, hold where they were and now are
// As we go along, update, and hand over, to any Position Dependent
- // records we happen across
- Hashtable<Integer,Integer> oldToNewPositions = new
Hashtable<Integer,Integer>();
-
- // First pass - figure out where all the position dependent
- // records are going to end up, in the new scheme
- // (Annoyingly, some powerpoing files have PersistPtrHolders
- // that reference slides after the PersistPtrHolder)
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- for(int i=0; i<_records.length; i++) {
- if(_records[i] instanceof PositionDependentRecord) {
- PositionDependentRecord pdr =
(PositionDependentRecord)_records[i];
- int oldPos = pdr.getLastOnDiskOffset();
- int newPos = baos.size();
- pdr.setLastOnDiskOffset(newPos);
-
oldToNewPositions.put(Integer.valueOf(oldPos),Integer.valueOf(newPos));
- //System.out.println(oldPos + " -> " + newPos);
- }
+ // records we happen across
+ updateAndWriteDependantRecords(baos, null);
- // Dummy write out, so the position winds on properly
- _records[i].writeOut(baos);
- }
-
- // No go back through, actually writing ourselves out
- baos.reset();
- for(int i=0; i<_records.length; i++) {
- // For now, we're only handling PositionDependentRecord's that
- // happen at the top level.
- // In future, we'll need the handle them everywhere, but that's
- // a bit trickier
- if(_records[i] instanceof PositionDependentRecord) {
- // We've already figured out their new location, and
- // told them that
- // Tell them of the positions of the other records though
- PositionDependentRecord pdr =
(PositionDependentRecord)_records[i];
- pdr.updateOtherRecordReferences(oldToNewPositions);
- }
-
- // Whatever happens, write out that record tree
- _records[i].writeOut(baos);
- }
// Update our cached copy of the bytes that make up the PPT stream
_docstream = baos.toByteArray();
@@ -476,15 +527,6 @@ public final class HSLFSlideShow extends
ByteArrayInputStream bais = new
ByteArrayInputStream(baos.toByteArray());
outFS.createDocument(bais,"PowerPoint Document");
writtenEntries.add("PowerPoint Document");
-
-
- // Update and write out the Current User atom
- int oldLastUserEditAtomPos = (int)currentUser.getCurrentEditOffset();
- Integer newLastUserEditAtomPos =
(Integer)oldToNewPositions.get(Integer.valueOf(oldLastUserEditAtomPos));
- if(newLastUserEditAtomPos == null) {
- throw new HSLFException("Couldn't find the new location of the
UserEditAtom that used to be at " + oldLastUserEditAtomPos);
- }
- currentUser.setCurrentEditOffset(newLastUserEditAtomPos.intValue());
currentUser.writeToFS(outFS);
writtenEntries.add("Current User");
@@ -506,7 +548,7 @@ public final class HSLFSlideShow extends
// If requested, write out any other streams we spot
if(preserveNodes) {
- copyNodes(directory.getFileSystem(), outFS, writtenEntries);
+ EntryUtils.copyNodes(directory.getFileSystem(), outFS,
writtenEntries);
}
// Send the POIFSFileSystem object out to the underlying stream
@@ -612,9 +654,9 @@ public final class HSLFSlideShow extends
public ObjectData[] getEmbeddedObjects() {
if (_objects == null) {
List<ObjectData> objects = new ArrayList<ObjectData>();
- for (int i = 0; i < _records.length; i++) {
- if (_records[i] instanceof ExOleObjStg) {
- objects.add(new ObjectData((ExOleObjStg) _records[i]));
+ for (Record r : _records) {
+ if (r instanceof ExOleObjStg) {
+ objects.add(new ObjectData((ExOleObjStg)r));
}
}
_objects = objects.toArray(new ObjectData[objects.size()]);
Modified:
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjStg.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjStg.java?rev=1553610&r1=1553609&r2=1553610&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjStg.java
(original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjStg.java
Fri Dec 27 00:22:19 2013
@@ -17,10 +17,14 @@
package org.apache.poi.hslf.record;
-import java.io.*;
-import java.util.zip.InflaterInputStream;
-import java.util.zip.DeflaterOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.Hashtable;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.InflaterInputStream;
import org.apache.poi.util.BoundedInputStream;
import org.apache.poi.util.LittleEndian;
@@ -120,7 +124,7 @@ public class ExOleObjStg extends RecordA
ByteArrayOutputStream out = new ByteArrayOutputStream();
//first four bytes is the length of the raw data
byte[] b = new byte[4];
- LittleEndian.putInt(b, data.length);
+ LittleEndian.putInt(b, 0, data.length);
out.write(b);
DeflaterOutputStream def = new DeflaterOutputStream(out);
Modified:
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java?rev=1553610&r1=1553609&r2=1553610&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java
(original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java
Fri Dec 27 00:22:19 2013
@@ -25,7 +25,12 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.ddf.EscherContainerRecord;
@@ -35,11 +40,43 @@ import org.apache.poi.hpsf.ClassID;
import org.apache.poi.hslf.HSLFSlideShow;
import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
import org.apache.poi.hslf.exceptions.HSLFException;
-import org.apache.poi.hslf.model.*;
+import org.apache.poi.hslf.model.HeadersFooters;
+import org.apache.poi.hslf.model.Hyperlink;
+import org.apache.poi.hslf.model.MovieShape;
import org.apache.poi.hslf.model.Notes;
+import org.apache.poi.hslf.model.PPFont;
+import org.apache.poi.hslf.model.Picture;
+import org.apache.poi.hslf.model.Shape;
import org.apache.poi.hslf.model.Slide;
-import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.model.SlideMaster;
+import org.apache.poi.hslf.model.TitleMaster;
+import org.apache.poi.hslf.record.Document;
+import org.apache.poi.hslf.record.DocumentAtom;
+import org.apache.poi.hslf.record.ExAviMovie;
+import org.apache.poi.hslf.record.ExControl;
+import org.apache.poi.hslf.record.ExEmbed;
+import org.apache.poi.hslf.record.ExEmbedAtom;
+import org.apache.poi.hslf.record.ExHyperlink;
+import org.apache.poi.hslf.record.ExHyperlinkAtom;
+import org.apache.poi.hslf.record.ExMCIMovie;
+import org.apache.poi.hslf.record.ExObjList;
+import org.apache.poi.hslf.record.ExObjListAtom;
+import org.apache.poi.hslf.record.ExOleObjAtom;
+import org.apache.poi.hslf.record.ExOleObjStg;
+import org.apache.poi.hslf.record.ExVideoContainer;
+import org.apache.poi.hslf.record.FontCollection;
+import org.apache.poi.hslf.record.FontEntityAtom;
+import org.apache.poi.hslf.record.HeadersFootersContainer;
+import org.apache.poi.hslf.record.PersistPtrHolder;
+import org.apache.poi.hslf.record.PositionDependentRecord;
+import org.apache.poi.hslf.record.PositionDependentRecordContainer;
+import org.apache.poi.hslf.record.Record;
+import org.apache.poi.hslf.record.RecordContainer;
+import org.apache.poi.hslf.record.RecordTypes;
+import org.apache.poi.hslf.record.SlideListWithText;
import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;
+import org.apache.poi.hslf.record.SlidePersistAtom;
+import org.apache.poi.hslf.record.UserEditAtom;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.POILogFactory;
@@ -58,15 +95,12 @@ public final class SlideShow {
// What we're based on
private HSLFSlideShow _hslfSlideShow;
- // Low level contents, as taken from HSLFSlideShow
- private Record[] _records;
-
// Pointers to the most recent versions of the core records
// (Document, Notes, Slide etc)
private Record[] _mostRecentCoreRecords;
// Lookup between the PersitPtr "sheet" IDs, and the position
// in the mostRecentCoreRecords array
- private Hashtable<Integer,Integer> _sheetIdToCoreRecordsLookup;
+ private Map<Integer,Integer> _sheetIdToCoreRecordsLookup;
// Records that are interesting
private Document _documentRecord;
@@ -97,10 +131,9 @@ public final class SlideShow {
public SlideShow(HSLFSlideShow hslfSlideShow) {
// Get useful things from our base slideshow
_hslfSlideShow = hslfSlideShow;
- _records = _hslfSlideShow.getRecords();
// Handle Parent-aware Records
- for (Record record : _records) {
+ for (Record record : _hslfSlideShow.getRecords()) {
if(record instanceof RecordContainer){
RecordContainer.handleParentAwareRecords((RecordContainer)record);
}
@@ -135,25 +168,23 @@ public final class SlideShow {
*/
private void findMostRecentCoreRecords() {
// To start with, find the most recent in the byte offset domain
- Hashtable<Integer,Integer> mostRecentByBytes = new
Hashtable<Integer,Integer>();
- for (int i = 0; i < _records.length; i++) {
- if (_records[i] instanceof PersistPtrHolder) {
- PersistPtrHolder pph = (PersistPtrHolder)
_records[i];
+ Map<Integer,Integer> mostRecentByBytes = new
HashMap<Integer,Integer>();
+ for (Record record : _hslfSlideShow.getRecords()) {
+ if (record instanceof PersistPtrHolder) {
+ PersistPtrHolder pph = (PersistPtrHolder)
record;
// If we've already seen any of the "slide" IDs
for this
// PersistPtr, remove their old positions
int[] ids = pph.getKnownSlideIDs();
- for (int j = 0; j < ids.length; j++) {
- Integer id = Integer.valueOf(ids[j]);
+ for (int id : ids) {
if (mostRecentByBytes.containsKey(id)) {
mostRecentByBytes.remove(id);
}
}
// Now, update the byte level locations with
their latest values
- Hashtable<Integer,Integer> thisSetOfLocations =
pph.getSlideLocationsLookup();
- for (int j = 0; j < ids.length; j++) {
- Integer id = Integer.valueOf(ids[j]);
+ Map<Integer,Integer> thisSetOfLocations =
pph.getSlideLocationsLookup();
+ for (int id : ids) {
mostRecentByBytes.put(id,
thisSetOfLocations.get(id));
}
}
@@ -165,54 +196,48 @@ public final class SlideShow {
// We'll also want to be able to turn the slide IDs into a
position
// in this array
- _sheetIdToCoreRecordsLookup = new Hashtable<Integer,Integer>();
- int[] allIDs = new int[_mostRecentCoreRecords.length];
- Enumeration<Integer> ids = mostRecentByBytes.keys();
- for (int i = 0; i < allIDs.length; i++) {
- Integer id = ids.nextElement();
- allIDs[i] = id.intValue();
- }
+ _sheetIdToCoreRecordsLookup = new HashMap<Integer,Integer>();
+ Integer[] allIDs = mostRecentByBytes.keySet().toArray(new
Integer[mostRecentByBytes.size()]);
Arrays.sort(allIDs);
for (int i = 0; i < allIDs.length; i++) {
-
_sheetIdToCoreRecordsLookup.put(Integer.valueOf(allIDs[i]), Integer.valueOf(i));
+ _sheetIdToCoreRecordsLookup.put(allIDs[i], i);
}
// Now convert the byte offsets back into record offsets
- for (int i = 0; i < _records.length; i++) {
- if (_records[i] instanceof PositionDependentRecord) {
- PositionDependentRecord pdr =
(PositionDependentRecord) _records[i];
- Integer recordAt =
Integer.valueOf(pdr.getLastOnDiskOffset());
+ for (Record record : _hslfSlideShow.getRecords()) {
+ if (record instanceof PositionDependentRecord) {
+ PositionDependentRecord pdr =
(PositionDependentRecord) record;
+ int recordAt = pdr.getLastOnDiskOffset();
// Is it one we care about?
- for (int j = 0; j < allIDs.length; j++) {
- Integer thisID =
Integer.valueOf(allIDs[j]);
- Integer thatRecordAt =
mostRecentByBytes.get(thisID);
+ for (Integer thisID : allIDs) {
+ int thatRecordAt =
mostRecentByBytes.get(thisID);
- if (thatRecordAt.equals(recordAt)) {
+ if (thatRecordAt == recordAt) {
// Bingo. Now, where do we
store it?
Integer storeAtI =
_sheetIdToCoreRecordsLookup.get(thisID);
int storeAt =
storeAtI.intValue();
// Tell it its Sheet ID, if it
cares
if (pdr instanceof
PositionDependentRecordContainer) {
-
PositionDependentRecordContainer pdrc = (PositionDependentRecordContainer)
_records[i];
-
pdrc.setSheetId(thisID.intValue());
+
PositionDependentRecordContainer pdrc = (PositionDependentRecordContainer)
record;
+ pdrc.setSheetId(thisID);
}
// Finally, save the record
- _mostRecentCoreRecords[storeAt]
= _records[i];
+ _mostRecentCoreRecords[storeAt]
= record;
}
}
}
}
// Now look for the interesting records in there
- for (int i = 0; i < _mostRecentCoreRecords.length; i++) {
+ for (Record record : _mostRecentCoreRecords) {
// Check there really is a record at this number
- if (_mostRecentCoreRecords[i] != null) {
+ if (record != null) {
// Find the Document, and interesting things in
it
- if (_mostRecentCoreRecords[i].getRecordType()
== RecordTypes.Document.typeID) {
- _documentRecord = (Document)
_mostRecentCoreRecords[i];
+ if (record.getRecordType() ==
RecordTypes.Document.typeID) {
+ _documentRecord = (Document) record;
_fonts =
_documentRecord.getEnvironment().getFontCollection();
}
} else {
@@ -296,9 +321,8 @@ public final class SlideShow {
ArrayList<SlideMaster> mmr = new
ArrayList<SlideMaster>();
ArrayList<TitleMaster> tmr = new
ArrayList<TitleMaster>();
- for (int i = 0; i < masterSets.length; i++) {
- Record r = getCoreRecordForSAS(masterSets[i]);
- SlideAtomsSet sas = masterSets[i];
+ for (SlideAtomsSet sas : masterSets) {
+ Record r = getCoreRecordForSAS(sas);
int sheetNo =
sas.getSlidePersistAtom().getSlideIdentifier();
if (r instanceof
org.apache.poi.hslf.record.Slide) {
TitleMaster master = new
TitleMaster((org.apache.poi.hslf.record.Slide) r,
@@ -313,11 +337,8 @@ public final class SlideShow {
}
}
- _masters = new SlideMaster[mmr.size()];
- mmr.toArray(_masters);
-
- _titleMasters = new TitleMaster[tmr.size()];
- tmr.toArray(_titleMasters);
+ _masters = mmr.toArray(new SlideMaster[mmr.size()]);
+ _titleMasters = tmr.toArray(new
TitleMaster[tmr.size()]);
}
// Having sorted out the masters, that leaves the notes and
slides
@@ -326,14 +347,14 @@ public final class SlideShow {
// notesSLWT
org.apache.poi.hslf.record.Notes[] notesRecords;
SlideAtomsSet[] notesSets = new SlideAtomsSet[0];
- Hashtable<Integer,Integer> slideIdToNotes = new
Hashtable<Integer,Integer>();
+ Map<Integer,Integer> slideIdToNotes = new
HashMap<Integer,Integer>();
if (notesSLWT == null) {
// None
notesRecords = new org.apache.poi.hslf.record.Notes[0];
} else {
// Match up the records and the SlideAtomSets
notesSets = notesSLWT.getSlideAtomsSets();
- ArrayList<org.apache.poi.hslf.record.Notes>
notesRecordsL =
+ List<org.apache.poi.hslf.record.Notes> notesRecordsL =
new ArrayList<org.apache.poi.hslf.record.Notes>();
for (int i = 0; i < notesSets.length; i++) {
// Get the right core record
@@ -346,8 +367,8 @@ public final class SlideShow {
// Record the match between slide id
and these notes
SlidePersistAtom spa =
notesSets[i].getSlidePersistAtom();
- Integer slideId =
Integer.valueOf(spa.getSlideIdentifier());
- slideIdToNotes.put(slideId,
Integer.valueOf(i));
+ int slideId = spa.getSlideIdentifier();
+ slideIdToNotes.put(slideId, i);
} else {
logger.log(POILogger.ERROR, "A Notes
SlideAtomSet at " + i
+ " said its record was
at refID "
@@ -686,9 +707,8 @@ public final class SlideShow {
// (Will stay as null if no SlidePersistAtom exists yet in
// the slide, or only master slide's ones do)
SlidePersistAtom prev = null;
- SlideAtomsSet[] sas = slist.getSlideAtomsSets();
- for (int j = 0; j < sas.length; j++) {
- SlidePersistAtom spa = sas[j].getSlidePersistAtom();
+ for (SlideAtomsSet sas : slist.getSlideAtomsSets()) {
+ SlidePersistAtom spa = sas.getSlidePersistAtom();
if (spa.getSlideIdentifier() < 0) {
// This is for a master slide
// Odd, since we only deal with the Slide SLWT
@@ -850,19 +870,16 @@ public final class SlideShow {
* found
*/
public PPFont getFont(int idx) {
- PPFont font = null;
FontCollection fonts =
getDocumentRecord().getEnvironment().getFontCollection();
- Record[] ch = fonts.getChildRecords();
- for (int i = 0; i < ch.length; i++) {
- if (ch[i] instanceof FontEntityAtom) {
- FontEntityAtom atom = (FontEntityAtom) ch[i];
+ for (Record ch : fonts.getChildRecords()) {
+ if (ch instanceof FontEntityAtom) {
+ FontEntityAtom atom = (FontEntityAtom) ch;
if (atom.getFontIndex() == idx) {
- font = new PPFont(atom);
- break;
+ return new PPFont(atom);
}
}
}
- return font;
+ return null;
}
/**
@@ -885,11 +902,10 @@ public final class SlideShow {
boolean ppt2007 = "___PPT12".equals(tag);
HeadersFootersContainer hdd = null;
- Record[] ch = _documentRecord.getChildRecords();
- for (int i = 0; i < ch.length; i++) {
- if (ch[i] instanceof HeadersFootersContainer
- && ((HeadersFootersContainer)
ch[i]).getOptions() == HeadersFootersContainer.SlideHeadersFootersContainer) {
- hdd = (HeadersFootersContainer) ch[i];
+ for (Record ch : _documentRecord.getChildRecords()) {
+ if (ch instanceof HeadersFootersContainer
+ && ((HeadersFootersContainer) ch).getOptions()
== HeadersFootersContainer.SlideHeadersFootersContainer) {
+ hdd = (HeadersFootersContainer) ch;
break;
}
}
@@ -912,11 +928,10 @@ public final class SlideShow {
boolean ppt2007 = "___PPT12".equals(tag);
HeadersFootersContainer hdd = null;
- Record[] ch = _documentRecord.getChildRecords();
- for (int i = 0; i < ch.length; i++) {
- if (ch[i] instanceof HeadersFootersContainer
- && ((HeadersFootersContainer)
ch[i]).getOptions() == HeadersFootersContainer.NotesHeadersFootersContainer) {
- hdd = (HeadersFootersContainer) ch[i];
+ for (Record ch : _documentRecord.getChildRecords()) {
+ if (ch instanceof HeadersFootersContainer
+ && ((HeadersFootersContainer)
ch).getOptions() == HeadersFootersContainer.NotesHeadersFootersContainer) {
+ hdd = (HeadersFootersContainer) ch;
break;
}
}
@@ -1107,37 +1122,23 @@ public final class SlideShow {
}
protected int addPersistentObject(PositionDependentRecord slideRecord) {
- int slideRecordPos =
_hslfSlideShow.appendRootLevelRecord((Record)slideRecord);
- _records = _hslfSlideShow.getRecords();
+ slideRecord.setLastOnDiskOffset(HSLFSlideShow.UNSET_OFFSET);
+ _hslfSlideShow.appendRootLevelRecord((Record)slideRecord);
- // Add the new Slide into the PersistPtr stuff
- int offset = 0;
- int slideOffset = 0;
- PersistPtrHolder ptr = null;
- UserEditAtom usr = null;
- int i = 0;
- for (Record record : _records) {
- // Grab interesting records as they come past
- int recordType = (int)record.getRecordType();
- if (recordType == RecordTypes.PersistPtrIncrementalBlock.typeID) {
- ptr = (PersistPtrHolder)record;
- }
- if (recordType == RecordTypes.UserEditAtom.typeID) {
- usr = (UserEditAtom)record;
- }
+ // For position dependent records, hold where they were and now are
+ // As we go along, update, and hand over, to any Position Dependent
+ // records we happen across
+ Map<RecordTypes.Type,PositionDependentRecord>
interestingRecords =
+ new HashMap<RecordTypes.Type,PositionDependentRecord>();
- if (i++ == slideRecordPos) {
- slideOffset = offset;
- }
-
- try {
- ByteArrayOutputStream out = new
ByteArrayOutputStream();
- record.writeOut(out);
- offset += out.size();
- } catch (IOException e) {
- throw new HSLFException(e);
- }
- }
+ try {
+
_hslfSlideShow.updateAndWriteDependantRecords(null,interestingRecords);
+ } catch (IOException e) {
+ throw new HSLFException(e);
+ }
+
+ PersistPtrHolder ptr =
(PersistPtrHolder)interestingRecords.get(RecordTypes.PersistPtrIncrementalBlock);
+ UserEditAtom usr =
(UserEditAtom)interestingRecords.get(RecordTypes.UserEditAtom);
// persist ID is UserEditAtom.maxPersistWritten + 1
int psrId = usr.getMaxPersistWritten() + 1;
@@ -1149,6 +1150,7 @@ public final class SlideShow {
// Add the new slide into the last PersistPtr
// (Also need to tell it where it is)
+ int slideOffset = slideRecord.getLastOnDiskOffset();
slideRecord.setLastOnDiskOffset(slideOffset);
ptr.addSlideLookup(psrId, slideOffset);
logger.log(POILogger.INFO, "New slide/object ended up at " +
slideOffset);
Added:
poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/HSLFTestDataSamples.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/HSLFTestDataSamples.java?rev=1553610&view=auto
==============================================================================
---
poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/HSLFTestDataSamples.java
(added)
+++
poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/HSLFTestDataSamples.java
Fri Dec 27 00:22:19 2013
@@ -0,0 +1,74 @@
+/* ====================================================================
+ 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;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.hslf.usermodel.SlideShow;
+
+public class HSLFTestDataSamples {
+
+ private static final POIDataSamples _inst =
POIDataSamples.getSlideShowInstance();
+
+ public static InputStream openSampleFileStream(String sampleFileName) {
+ return _inst.openResourceAsStream(sampleFileName);
+ }
+ public static File getSampleFile(String sampleFileName) {
+ return _inst.getFile(sampleFileName);
+ }
+ public static byte[] getTestDataFileContent(String fileName) {
+ return _inst.readFile(fileName);
+ }
+
+ /**
+ * Writes a slideshow to a <tt>ByteArrayOutputStream</tt> and reads it
back
+ * from a <tt>ByteArrayInputStream</tt>.<p/>
+ * Useful for verifying that the serialisation round trip
+ */
+ public static HSLFSlideShow writeOutAndReadBack(HSLFSlideShow original)
{
+ try {
+ ByteArrayOutputStream baos = new
ByteArrayOutputStream(4096);
+ original.write(baos);
+ ByteArrayInputStream bais = new
ByteArrayInputStream(baos.toByteArray());
+ return new HSLFSlideShow(bais);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Writes a slideshow to a <tt>ByteArrayOutputStream</tt> and reads it
back
+ * from a <tt>ByteArrayInputStream</tt>.<p/>
+ * Useful for verifying that the serialisation round trip
+ */
+ public static SlideShow writeOutAndReadBack(SlideShow original) {
+ try {
+ ByteArrayOutputStream baos = new
ByteArrayOutputStream(4096);
+ original.write(baos);
+ ByteArrayInputStream bais = new
ByteArrayInputStream(baos.toByteArray());
+ return new SlideShow(bais);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
Modified:
poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/TestReWrite.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/TestReWrite.java?rev=1553610&r1=1553609&r2=1553610&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/TestReWrite.java
(original)
+++ poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/TestReWrite.java Fri
Dec 27 00:22:19 2013
@@ -18,15 +18,16 @@
package org.apache.poi.hslf;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+
import junit.framework.TestCase;
-import org.apache.poi.hslf.usermodel.SlideShow;
-import org.apache.poi.poifs.filesystem.*;
import org.apache.poi.POIDataSamples;
-
-import java.io.ByteArrayOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.FileNotFoundException;
+import org.apache.poi.hslf.usermodel.SlideShow;
+import org.apache.poi.poifs.filesystem.DocumentEntry;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
/**
* Tests that HSLFSlideShow writes the powerpoint bit of data back out
@@ -160,4 +161,16 @@ public final class TestReWrite extends T
assertEquals(_oData[i], _nData[i]);
}
}
+
+ public void test48593() throws Exception {
+ SlideShow slideShow = new SlideShow();
+ slideShow.createSlide();
+ slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow);
+ slideShow.createSlide();
+ slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow);
+ slideShow.createSlide();
+ slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow);
+ slideShow.createSlide();
+ slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow);
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]