whitespace clean up before fix for BUG-60305

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1767020 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Tim Allison 2016-10-28 13:25:14 +00:00
parent 51b4f2a365
commit 1c2f768b8c

View File

@ -69,64 +69,64 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
// For logging
private POILogger logger = POILogFactory.getLogger(this.getClass());
// Holds metadata on where things are in our document
private CurrentUserAtom currentUser;
// Holds metadata on where things are in our document
private CurrentUserAtom currentUser;
// Low level contents of the file
private byte[] _docstream;
// Low level contents of the file
private byte[] _docstream;
// Low level contents
private Record[] _records;
// Low level contents
private Record[] _records;
// Raw Pictures contained in the pictures stream
private List<HSLFPictureData> _pictures;
// Raw Pictures contained in the pictures stream
private List<HSLFPictureData> _pictures;
// Embedded objects stored in storage records in the document stream, lazily populated.
private HSLFObjectData[] _objects;
/**
* Returns the directory in the underlying POIFSFileSystem for the
* document that is open.
* document that is open.
*/
protected DirectoryNode getPOIFSDirectory() {
return directory;
return directory;
}
/**
* Constructs a Powerpoint document from fileName. Parses the document
* and places all the important stuff into data structures.
*
* @param fileName The name of the file to read.
* @throws IOException if there is a problem while parsing the document.
*/
/**
* Constructs a Powerpoint document from fileName. Parses the document
* and places all the important stuff into data structures.
*
* @param fileName The name of the file to read.
* @throws IOException if there is a problem while parsing the document.
*/
@SuppressWarnings("resource")
public HSLFSlideShowImpl(String fileName) throws IOException {
this(new POIFSFileSystem(new File(fileName)));
}
public HSLFSlideShowImpl(String fileName) throws IOException {
this(new POIFSFileSystem(new File(fileName)));
}
/**
* Constructs a Powerpoint document from an input stream. Parses the
* document and places all the important stuff into data structures.
*
* @param inputStream the source of the data
* @throws IOException if there is a problem while parsing the document.
*/
@SuppressWarnings("resource")
/**
* Constructs a Powerpoint document from an input stream. Parses the
* document and places all the important stuff into data structures.
*
* @param inputStream the source of the data
* @throws IOException if there is a problem while parsing the document.
*/
@SuppressWarnings("resource")
public HSLFSlideShowImpl(InputStream inputStream) throws IOException {
//do Ole stuff
this(new POIFSFileSystem(inputStream));
}
//do Ole stuff
this(new POIFSFileSystem(inputStream));
}
/**
* Constructs a Powerpoint document from a POIFS Filesystem. Parses the
* document and places all the important stuff into data structures.
*
* @param filesystem the POIFS FileSystem to read from
* @throws IOException if there is a problem while parsing the document.
*/
public HSLFSlideShowImpl(POIFSFileSystem filesystem) throws IOException {
this(filesystem.getRoot());
}
/**
* Constructs a Powerpoint document from a POIFS Filesystem. Parses the
* document and places all the important stuff into data structures.
*
* @param filesystem the POIFS FileSystem to read from
* @throws IOException if there is a problem while parsing the document.
*/
public HSLFSlideShowImpl(POIFSFileSystem filesystem) throws IOException {
this(filesystem.getRoot());
}
/**
* Constructs a Powerpoint document from a POIFS Filesystem. Parses the
@ -139,132 +139,130 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
this(filesystem.getRoot());
}
/**
* Constructs a Powerpoint document from a specific point in a
* POIFS Filesystem. Parses the document and places all the
* important stuff into data structures.
*
* @param dir the POIFS directory to read from
* @throws IOException if there is a problem while parsing the document.
*/
public HSLFSlideShowImpl(DirectoryNode dir) throws IOException {
super(handleDualStorage(dir));
/**
* Constructs a Powerpoint document from a specific point in a
* POIFS Filesystem. Parses the document and places all the
* important stuff into data structures.
*
* @param dir the POIFS directory to read from
* @throws IOException if there is a problem while parsing the document.
*/
public HSLFSlideShowImpl(DirectoryNode dir) throws IOException {
super(handleDualStorage(dir));
// First up, grab the "Current User" stream
// We need this before we can detect Encrypted Documents
readCurrentUserStream();
// First up, grab the "Current User" stream
// We need this before we can detect Encrypted Documents
readCurrentUserStream();
// Next up, grab the data that makes up the
// PowerPoint stream
readPowerPointStream();
// Next up, grab the data that makes up the
// PowerPoint stream
readPowerPointStream();
// Now, build records based on the PowerPoint stream
buildRecords();
// Now, build records based on the PowerPoint stream
buildRecords();
// Look for any other streams
readOtherStreams();
}
// Look for any other streams
readOtherStreams();
}
private static DirectoryNode handleDualStorage(DirectoryNode dir) throws IOException {
// when there's a dual storage entry, use it, as the outer document can't be read quite probably ...
String dualName = "PP97_DUALSTORAGE";
if (!dir.hasEntry(dualName)) return dir;
dir = (DirectoryNode)dir.getEntry(dualName);
return dir;
}
private static DirectoryNode handleDualStorage(DirectoryNode dir) throws IOException {
// when there's a dual storage entry, use it, as the outer document can't be read quite probably ...
String dualName = "PP97_DUALSTORAGE";
if (!dir.hasEntry(dualName)) return dir;
dir = (DirectoryNode) dir.getEntry(dualName);
return dir;
}
/**
* Constructs a new, empty, Powerpoint document.
*/
public static final HSLFSlideShowImpl create() {
InputStream is = HSLFSlideShowImpl.class.getResourceAsStream("/org/apache/poi/hslf/data/empty.ppt");
if (is == null) {
throw new HSLFException("Missing resource 'empty.ppt'");
}
try {
try {
return new HSLFSlideShowImpl(is);
} finally {
/**
* Constructs a new, empty, Powerpoint document.
*/
public static final HSLFSlideShowImpl create() {
InputStream is = HSLFSlideShowImpl.class.getResourceAsStream("/org/apache/poi/hslf/data/empty.ppt");
if (is == null) {
throw new HSLFException("Missing resource 'empty.ppt'");
}
try {
try {
return new HSLFSlideShowImpl(is);
} finally {
is.close();
}
} catch (IOException e) {
throw new HSLFException(e);
}
}
} catch (IOException e) {
throw new HSLFException(e);
}
}
/**
* Extracts the main PowerPoint document stream from the
* POI file, ready to be passed
*
* @throws IOException
*/
private void readPowerPointStream() throws IOException
{
// Get the main document stream
DocumentEntry docProps =
(DocumentEntry)directory.getEntry("PowerPoint Document");
/**
* Extracts the main PowerPoint document stream from the
* POI file, ready to be passed
*
* @throws IOException
*/
private void readPowerPointStream() throws IOException {
// Get the main document stream
DocumentEntry docProps =
(DocumentEntry) directory.getEntry("PowerPoint Document");
// Grab the document stream
int len = docProps.getSize();
// Grab the document stream
int len = docProps.getSize();
InputStream is = directory.createDocumentInputStream("PowerPoint Document");
try {
_docstream = IOUtils.toByteArray(is, len);
} finally {
is.close();
}
}
}
/**
* Builds the list of records, based on the contents
* of the PowerPoint stream
*/
private void buildRecords()
{
// The format of records in a powerpoint file are:
// <little endian 2 byte "info">
// <little endian 2 byte "type">
// <little endian 4 byte "length">
// If it has a zero length, following it will be another record
// <xx xx yy yy 00 00 00 00> <xx xx yy yy zz zz zz zz>
// If it has a length, depending on its type it may have children or data
// If it has children, these will follow straight away
// <xx xx yy yy zz zz zz zz <xx xx yy yy zz zz zz zz>>
// If it has data, this will come straigh after, and run for the length
// <xx xx yy yy zz zz zz zz dd dd dd dd dd dd dd>
// All lengths given exclude the 8 byte record header
// (Data records are known as Atoms)
/**
* Builds the list of records, based on the contents
* of the PowerPoint stream
*/
private void buildRecords() {
// The format of records in a powerpoint file are:
// <little endian 2 byte "info">
// <little endian 2 byte "type">
// <little endian 4 byte "length">
// If it has a zero length, following it will be another record
// <xx xx yy yy 00 00 00 00> <xx xx yy yy zz zz zz zz>
// If it has a length, depending on its type it may have children or data
// If it has children, these will follow straight away
// <xx xx yy yy zz zz zz zz <xx xx yy yy zz zz zz zz>>
// If it has data, this will come straigh after, and run for the length
// <xx xx yy yy zz zz zz zz dd dd dd dd dd dd dd>
// All lengths given exclude the 8 byte record header
// (Data records are known as Atoms)
// Document should start with:
// 0F 00 E8 03 ## ## ## ##
// (type 1000 = document, info 00 0f is normal, rest is document length)
// 01 00 E9 03 28 00 00 00
// (type 1001 = document atom, info 00 01 normal, 28 bytes long)
// 80 16 00 00 E0 10 00 00 xx xx xx xx xx xx xx xx
// 05 00 00 00 0A 00 00 00 xx xx xx
// (the contents of the document atom, not sure what it means yet)
// (records then follow)
// Document should start with:
// 0F 00 E8 03 ## ## ## ##
// (type 1000 = document, info 00 0f is normal, rest is document length)
// 01 00 E9 03 28 00 00 00
// (type 1001 = document atom, info 00 01 normal, 28 bytes long)
// 80 16 00 00 E0 10 00 00 xx xx xx xx xx xx xx xx
// 05 00 00 00 0A 00 00 00 xx xx xx
// (the contents of the document atom, not sure what it means yet)
// (records then follow)
// When parsing a document, look to see if you know about that type
// of the current record. If you know it's a type that has children,
// process the record's data area looking for more records
// If you know about the type and it doesn't have children, either do
// something with the data (eg TextRun) or skip over it
// If you don't know about the type, play safe and skip over it (using
// its length to know where the next record will start)
//
// When parsing a document, look to see if you know about that type
// of the current record. If you know it's a type that has children,
// process the record's data area looking for more records
// If you know about the type and it doesn't have children, either do
// something with the data (eg TextRun) or skip over it
// If you don't know about the type, play safe and skip over it (using
// its length to know where the next record will start)
//
_records = read(_docstream, (int)currentUser.getCurrentEditOffset());
}
_records = read(_docstream, (int) currentUser.getCurrentEditOffset());
}
private Record[] read(byte[] docstream, int usrOffset){
private Record[] read(byte[] docstream, int usrOffset) {
//sort found records by offset.
//(it is not necessary but SlideShow.findMostRecentCoreRecords() expects them sorted)
NavigableMap<Integer,Record> records = new TreeMap<Integer,Record>(); // offset -> record
Map<Integer,Integer> persistIds = new HashMap<Integer,Integer>(); // offset -> persistId
NavigableMap<Integer, Record> records = new TreeMap<Integer, Record>(); // offset -> record
Map<Integer, Integer> persistIds = new HashMap<Integer, Integer>(); // offset -> persistId
initRecordOffsets(docstream, usrOffset, records, persistIds);
HSLFSlideShowEncrypted decryptData = new HSLFSlideShowEncrypted(docstream, records);
for (Map.Entry<Integer,Record> entry : records.entrySet()) {
for (Map.Entry<Integer, Record> entry : records.entrySet()) {
Integer offset = entry.getKey();
Record record = entry.getValue();
Integer persistId = persistIds.get(offset);
@ -277,23 +275,23 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
}
if (record instanceof PersistRecord) {
((PersistRecord)record).setPersistId(persistId);
((PersistRecord) record).setPersistId(persistId);
}
}
return records.values().toArray(new Record[records.size()]);
}
private void initRecordOffsets(byte[] docstream, int usrOffset, NavigableMap<Integer,Record> recordMap, Map<Integer,Integer> offset2id) {
while (usrOffset != 0){
private void initRecordOffsets(byte[] docstream, int usrOffset, NavigableMap<Integer, Record> recordMap, Map<Integer, Integer> offset2id) {
while (usrOffset != 0) {
UserEditAtom usr = (UserEditAtom) Record.buildRecordAtOffset(docstream, usrOffset);
recordMap.put(usrOffset, usr);
int psrOffset = usr.getPersistPointersOffset();
PersistPtrHolder ptr = (PersistPtrHolder)Record.buildRecordAtOffset(docstream, psrOffset);
PersistPtrHolder ptr = (PersistPtrHolder) Record.buildRecordAtOffset(docstream, psrOffset);
recordMap.put(psrOffset, ptr);
for(Map.Entry<Integer,Integer> entry : ptr.getSlideLocationsLookup().entrySet()) {
for (Map.Entry<Integer, Integer> entry : ptr.getSlideLocationsLookup().entrySet()) {
Integer offset = entry.getValue();
Integer id = entry.getKey();
recordMap.put(offset, null); // reserve a slot for the record
@ -306,11 +304,11 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
// if the next user edit atom offset is already known, we would go into an endless loop
if (usrOffset > 0 && recordMap.containsKey(usrOffset)) {
// a user edit atom is usually located 36 byte before the smallest known record offset
usrOffset = recordMap.firstKey()-36;
usrOffset = recordMap.firstKey() - 36;
// check that we really are located on a user edit atom
int ver_inst = LittleEndian.getUShort(docstream, usrOffset);
int type = LittleEndian.getUShort(docstream, usrOffset+2);
int len = LittleEndian.getInt(docstream, usrOffset+4);
int type = LittleEndian.getUShort(docstream, usrOffset + 2);
int len = LittleEndian.getInt(docstream, usrOffset + 4);
if (ver_inst == 0 && type == 4085 && (len == 0x1C || len == 0x20)) {
logger.log(POILogger.WARN, "Repairing invalid user edit atom");
usr.setLastUserEditAtomOffset(usrOffset);
@ -324,37 +322,37 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
public DocumentEncryptionAtom getDocumentEncryptionAtom() {
for (Record r : _records) {
if (r instanceof DocumentEncryptionAtom) {
return (DocumentEncryptionAtom)r;
return (DocumentEncryptionAtom) r;
}
}
return null;
}
/**
* Find the "Current User" stream, and load it
*/
private void readCurrentUserStream() {
try {
currentUser = new CurrentUserAtom(directory);
} catch(IOException ie) {
logger.log(POILogger.ERROR, "Error finding Current User Atom:\n" + ie);
currentUser = new CurrentUserAtom();
}
}
/**
* Find the "Current User" stream, and load it
*/
private void readCurrentUserStream() {
try {
currentUser = new CurrentUserAtom(directory);
} catch (IOException ie) {
logger.log(POILogger.ERROR, "Error finding Current User Atom:\n" + ie);
currentUser = new CurrentUserAtom();
}
}
/**
* Find any other streams from the filesystem, and load them
*/
private void readOtherStreams() {
// Currently, there aren't any
}
/**
* Find any other streams from the filesystem, and load them
*/
private void readOtherStreams() {
// Currently, there aren't any
}
/**
* Find and read in pictures contained in this presentation.
* This is lazily called as and when we want to touch pictures.
*/
private void readPictures() throws IOException {
/**
* Find and read in pictures contained in this presentation.
* This is lazily called as and when we want to touch pictures.
*/
private void readPictures() throws IOException {
_pictures = new ArrayList<HSLFPictureData>();
// if the presentation doesn't contain pictures - will use a null set instead
@ -362,14 +360,14 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
HSLFSlideShowEncrypted decryptData = new HSLFSlideShowEncrypted(getDocumentEncryptionAtom());
DocumentEntry entry = (DocumentEntry)directory.getEntry("Pictures");
DocumentEntry entry = (DocumentEntry) directory.getEntry("Pictures");
DocumentInputStream is = directory.createDocumentInputStream(entry);
byte[] pictstream = IOUtils.toByteArray(is, entry.getSize());
is.close();
byte[] pictstream = IOUtils.toByteArray(is, entry.getSize());
is.close();
int pos = 0;
// An empty picture record (length 0) will take up 8 bytes
while (pos <= (pictstream.length-8)) {
// An empty picture record (length 0) will take up 8 bytes
while (pos <= (pictstream.length - 8)) {
int offset = pos;
decryptData.decryptPicture(pictstream, offset);
@ -389,23 +387,23 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
if (!((type == 0xf007) || (type >= 0xf018 && type <= 0xf117)))
break;
// The image size must be 0 or greater
// (0 is allowed, but odd, since we do wind on by the header each
// time, so we won't get stuck)
if(imgsize < 0) {
throw new CorruptPowerPointFileException("The file contains a picture, at position " + _pictures.size() + ", which has a negatively sized data length, so we can't trust any of the picture data");
}
// The image size must be 0 or greater
// (0 is allowed, but odd, since we do wind on by the header each
// time, so we won't get stuck)
if (imgsize < 0) {
throw new CorruptPowerPointFileException("The file contains a picture, at position " + _pictures.size() + ", which has a negatively sized data length, so we can't trust any of the picture data");
}
// If they type (including the bonus 0xF018) is 0, skip it
PictureType pt = PictureType.forNativeID(type - 0xF018);
if (pt == null) {
logger.log(POILogger.ERROR, "Problem reading picture: Invalid image type 0, on picture with length " + imgsize + ".\nYou document will probably become corrupted if you save it!");
logger.log(POILogger.ERROR, "" + pos);
} else {
// Build the PictureData object from the data
// If they type (including the bonus 0xF018) is 0, skip it
PictureType pt = PictureType.forNativeID(type - 0xF018);
if (pt == null) {
logger.log(POILogger.ERROR, "Problem reading picture: Invalid image type 0, on picture with length " + imgsize + ".\nYou document will probably become corrupted if you save it!");
logger.log(POILogger.ERROR, "" + pos);
} else {
// Build the PictureData object from the data
try {
HSLFPictureData pict = HSLFPictureData.create(pt);
pict.setSignature(signature);
HSLFPictureData pict = HSLFPictureData.create(pt);
pict.setSignature(signature);
// Copy the data, ready to pass to PictureData
byte[] imgdata = new byte[imgsize];
@ -414,15 +412,15 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
pict.setOffset(offset);
pict.setIndex(_pictures.size());
_pictures.add(pict);
} catch(IllegalArgumentException e) {
logger.log(POILogger.ERROR, "Problem reading picture: " + e + "\nYou document will probably become corrupted if you save it!");
}
}
_pictures.add(pict);
} catch (IllegalArgumentException e) {
logger.log(POILogger.ERROR, "Problem reading picture: " + e + "\nYou document will probably become corrupted if you save it!");
}
}
pos += imgsize;
}
}
}
/**
* remove duplicated UserEditAtoms and merge PersistPtrHolder, i.e.
@ -438,22 +436,22 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
}
/**
/**
* 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,PositionDependentRecord> interestingRecords)
throws IOException {
*
* @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, 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
Map<Integer,Integer> oldToNewPositions = new HashMap<Integer,Integer>();
Map<Integer, Integer> oldToNewPositions = new HashMap<Integer, Integer>();
// First pass - figure out where all the position dependent
// records are going to end up, in the new scheme
@ -464,29 +462,29 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
CountingOS cos = new CountingOS();
for (Record record : _records) {
// all top level records are position dependent
assert(record instanceof PositionDependentRecord);
PositionDependentRecord pdr = (PositionDependentRecord)record;
assert (record instanceof PositionDependentRecord);
PositionDependentRecord pdr = (PositionDependentRecord) record;
int oldPos = pdr.getLastOnDiskOffset();
int newPos = cos.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(oldPos,newPos);
oldToNewPositions.put(oldPos, newPos);
}
// Grab interesting records as they come past
// this will only save the very last record of each type
RecordTypes saveme = null;
int recordType = (int)record.getRecordType();
int recordType = (int) record.getRecordType();
if (recordType == RecordTypes.PersistPtrIncrementalBlock.typeID) {
saveme = RecordTypes.PersistPtrIncrementalBlock;
ptr = (PersistPtrHolder)pdr;
ptr = (PersistPtrHolder) pdr;
} else if (recordType == RecordTypes.UserEditAtom.typeID) {
saveme = RecordTypes.UserEditAtom;
usr = (UserEditAtom)pdr;
usr = (UserEditAtom) pdr;
}
if (interestingRecords != null && saveme != null) {
interestingRecords.put(saveme,pdr);
interestingRecords.put(saveme, pdr);
}
// Dummy write out, so the position winds on properly
@ -498,19 +496,19 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
throw new HSLFException("UserEditAtom or PersistPtr can't be determined.");
}
Map<Integer,Integer> persistIds = new HashMap<Integer,Integer>();
for (Map.Entry<Integer,Integer> entry : ptr.getSlideLocationsLookup().entrySet()) {
Map<Integer, Integer> persistIds = new HashMap<Integer, Integer>();
for (Map.Entry<Integer, Integer> entry : ptr.getSlideLocationsLookup().entrySet()) {
persistIds.put(oldToNewPositions.get(entry.getValue()), entry.getKey());
}
HSLFSlideShowEncrypted encData = new HSLFSlideShowEncrypted(getDocumentEncryptionAtom());
for (Record record : _records) {
assert(record instanceof PositionDependentRecord);
for (Record record : _records) {
assert (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;
PositionDependentRecord pdr = (PositionDependentRecord) record;
Integer persistId = persistIds.get(pdr.getLastOnDiskOffset());
if (persistId == null) persistId = 0;
@ -526,10 +524,10 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
}
}
encData.close();
encData.close();
// Update and write out the Current User atom
int oldLastUserEditAtomPos = (int)currentUser.getCurrentEditOffset();
int oldLastUserEditAtomPos = (int) currentUser.getCurrentEditOffset();
Integer newLastUserEditAtomPos = oldToNewPositions.get(oldLastUserEditAtomPos);
if (newLastUserEditAtomPos == null || usr.getLastOnDiskOffset() != newLastUserEditAtomPos) {
throw new HSLFException("Couldn't find the new location of the last UserEditAtom that used to be at " + oldLastUserEditAtomPos);
@ -539,17 +537,16 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
/**
* Writes out the slideshow to the currently open file.
*
* <p>
* <p>This will fail (with an {@link IllegalStateException} if the
* slideshow was opened read-only, opened from an {@link InputStream}
* instead of a File, or if this is not the root document. For those cases,
* you must use {@link #write(OutputStream)} or {@link #write(File)} to
* write to a brand new document.
* slideshow was opened read-only, opened from an {@link InputStream}
* instead of a File, or if this is not the root document. For those cases,
* you must use {@link #write(OutputStream)} or {@link #write(File)} to
* write to a brand new document.
*
* @since POI 3.15 beta 3
*
* @throws IOException thrown on errors writing to the file
* @throws IOException thrown on errors writing to the file
* @throws IllegalStateException if this isn't from a writable File
* @since POI 3.15 beta 3
*/
@Override
public void write() throws IOException {
@ -565,10 +562,11 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
/**
* Writes out the slideshow file the is represented by an instance
* of this class.
* of this class.
* <p>This will write out only the common OLE2 streams. If you require all
* streams to be written out, use {@link #write(File, boolean)}
* with <code>preserveNodes</code> set to <code>true</code>.
* streams to be written out, use {@link #write(File, boolean)}
* with <code>preserveNodes</code> set to <code>true</code>.
*
* @param newFile The File to write to.
* @throws IOException If there is an unexpected IOException from writing to the File
*/
@ -577,12 +575,14 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
// Write out, but only the common streams
write(newFile, false);
}
/**
* Writes out the slideshow file the is represented by an instance
* of this class.
* of this class.
* If you require all streams to be written out (eg Marcos, embeded
* documents), then set <code>preserveNodes</code> set to <code>true</code>
* @param newFile The File to write to.
* documents), then set <code>preserveNodes</code> set to <code>true</code>
*
* @param newFile The File to write to.
* @param preserveNodes Should all OLE2 streams be written back out, or only the common ones?
* @throws IOException If there is an unexpected IOException from writing to the File
*/
@ -603,28 +603,31 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
/**
* Writes out the slideshow file the is represented by an instance
* of this class.
* of this class.
* <p>This will write out only the common OLE2 streams. If you require all
* streams to be written out, use {@link #write(OutputStream, boolean)}
* with <code>preserveNodes</code> set to <code>true</code>.
* streams to be written out, use {@link #write(OutputStream, boolean)}
* with <code>preserveNodes</code> set to <code>true</code>.
*
* @param out The OutputStream to write to.
* @throws IOException If there is an unexpected IOException from
* the passed in OutputStream
* the passed in OutputStream
*/
@Override
@Override
public void write(OutputStream out) throws IOException {
// Write out, but only the common streams
write(out, false);
}
/**
* Writes out the slideshow file the is represented by an instance
* of this class.
* of this class.
* If you require all streams to be written out (eg Marcos, embeded
* documents), then set <code>preserveNodes</code> set to <code>true</code>
* @param out The OutputStream to write to.
* documents), then set <code>preserveNodes</code> set to <code>true</code>
*
* @param out The OutputStream to write to.
* @param preserveNodes Should all OLE2 streams be written back out, or only the common ones?
* @throws IOException If there is an unexpected IOException from
* the passed in OutputStream
* the passed in OutputStream
*/
public void write(OutputStream out, boolean preserveNodes) throws IOException {
// Get a new FileSystem to write into
@ -640,10 +643,11 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
outFS.close();
}
}
private void write(NPOIFSFileSystem outFS, boolean copyAllOtherNodes) throws IOException {
// read properties and pictures, with old encryption settings where appropriate
if (_pictures == null) {
readPictures();
readPictures();
}
getDocumentSummaryInformation();
@ -671,7 +675,7 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
// Write the PPT stream into the POIFS layer
ByteArrayInputStream bais = new ByteArrayInputStream(_docstream);
outFS.createOrUpdateDocument(bais,"PowerPoint Document");
outFS.createOrUpdateDocument(bais, "PowerPoint Document");
writtenEntries.add("PowerPoint Document");
currentUser.setEncrypted(encryptedSS.getDocumentEncryptionAtom() != null);
@ -687,7 +691,7 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
encryptedSS.encryptPicture(pict.getBuf(), offset);
}
outFS.createOrUpdateDocument(
new ByteArrayInputStream(pict.getBuf(), 0, pict.size()), "Pictures"
new ByteArrayInputStream(pict.getBuf(), 0, pict.size()), "Pictures"
);
writtenEntries.add("Pictures");
pict.close();
@ -701,31 +705,31 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
/**
* For a given named property entry, either return it or null if
* if it wasn't found
* if it wasn't found
*
* @param setName The property to read
* @return The value of the given property or null if it wasn't found.
* @param setName The property to read
* @return The value of the given property or null if it wasn't found.
*/
protected PropertySet getPropertySet(String setName) {
DocumentEncryptionAtom dea = getDocumentEncryptionAtom();
return (dea == null)
? super.getPropertySet(setName)
: super.getPropertySet(setName, dea.getEncryptionInfo());
? super.getPropertySet(setName)
: super.getPropertySet(setName, dea.getEncryptionInfo());
}
/**
* Writes out the standard Documment Information Properties (HPSF)
* @param outFS the POIFSFileSystem to write the properties into
* @param writtenEntries a list of POIFS entries to add the property names too
*
* @param outFS the POIFSFileSystem to write the properties into
* @param writtenEntries a list of POIFS entries to add the property names too
* @throws IOException if an error when writing to the
* {@link POIFSFileSystem} occurs
* {@link POIFSFileSystem} occurs
*/
protected void writeProperties(NPOIFSFileSystem outFS, List<String> writtenEntries) throws IOException {
super.writeProperties(outFS, writtenEntries);
DocumentEncryptionAtom dea = getDocumentEncryptionAtom();
if (dea != null) {
CryptoAPIEncryptor enc = (CryptoAPIEncryptor)dea.getEncryptionInfo().getEncryptor();
CryptoAPIEncryptor enc = (CryptoAPIEncryptor) dea.getEncryptionInfo().getEncryptor();
try {
enc.getSummaryEntries(outFS.getRoot()); // ignore OutputStream
} catch (IOException e) {
@ -738,94 +742,100 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
/* ******************* adding methods follow ********************* */
/**
* Adds a new root level record, at the end, but before the last
* PersistPtrIncrementalBlock.
*/
public synchronized int appendRootLevelRecord(Record newRecord) {
int addedAt = -1;
Record[] r = new Record[_records.length+1];
boolean added = false;
for(int i=(_records.length-1); i>=0; i--) {
if(added) {
// Just copy over
r[i] = _records[i];
} else {
r[(i+1)] = _records[i];
if(_records[i] instanceof PersistPtrHolder) {
r[i] = newRecord;
added = true;
addedAt = i;
}
}
}
_records = r;
return addedAt;
}
/**
* Adds a new root level record, at the end, but before the last
* PersistPtrIncrementalBlock.
*/
public synchronized int appendRootLevelRecord(Record newRecord) {
int addedAt = -1;
Record[] r = new Record[_records.length + 1];
boolean added = false;
for (int i = (_records.length - 1); i >= 0; i--) {
if (added) {
// Just copy over
r[i] = _records[i];
} else {
r[(i + 1)] = _records[i];
if (_records[i] instanceof PersistPtrHolder) {
r[i] = newRecord;
added = true;
addedAt = i;
}
}
}
_records = r;
return addedAt;
}
/**
* Add a new picture to this presentation.
/**
* Add a new picture to this presentation.
*
* @return offset of this picture in the Pictures stream
*/
public int addPicture(HSLFPictureData img) {
// Process any existing pictures if we haven't yet
if(_pictures == null) {
try {
readPictures();
} catch(IOException e) {
throw new CorruptPowerPointFileException(e.getMessage());
}
}
*/
public int addPicture(HSLFPictureData img) {
// Process any existing pictures if we haven't yet
if (_pictures == null) {
try {
readPictures();
} catch (IOException e) {
throw new CorruptPowerPointFileException(e.getMessage());
}
}
// Add the new picture in
int offset = 0;
if(_pictures.size() > 0) {
HSLFPictureData prev = _pictures.get(_pictures.size() - 1);
offset = prev.getOffset() + prev.getRawData().length + 8;
}
img.setOffset(offset);
img.setIndex(_pictures.size()+1);
_pictures.add(img);
return offset;
}
// Add the new picture in
int offset = 0;
if (_pictures.size() > 0) {
HSLFPictureData prev = _pictures.get(_pictures.size() - 1);
offset = prev.getOffset() + prev.getRawData().length + 8;
}
img.setOffset(offset);
img.setIndex(_pictures.size() + 1);
_pictures.add(img);
return offset;
}
/* ******************* fetching methods follow ********************* */
/**
* Returns an array of all the records found in the slideshow
*/
public Record[] getRecords() { return _records; }
/**
* Returns an array of all the records found in the slideshow
*/
public Record[] getRecords() {
return _records;
}
/**
* Returns an array of the bytes of the file. Only correct after a
* call to open or write - at all other times might be wrong!
*/
public byte[] getUnderlyingBytes() { return _docstream; }
/**
* Returns an array of the bytes of the file. Only correct after a
* call to open or write - at all other times might be wrong!
*/
public byte[] getUnderlyingBytes() {
return _docstream;
}
/**
* Fetch the Current User Atom of the document
*/
public CurrentUserAtom getCurrentUserAtom() { return currentUser; }
/**
* Fetch the Current User Atom of the document
*/
public CurrentUserAtom getCurrentUserAtom() {
return currentUser;
}
/**
* Return list of pictures contained in this presentation
*
* @return list with the read pictures or an empty list if the
* presentation doesn't contain pictures.
*/
public List<HSLFPictureData> getPictureData() {
if(_pictures == null) {
try {
readPictures();
} catch(IOException e) {
throw new CorruptPowerPointFileException(e.getMessage());
}
}
/**
* Return list of pictures contained in this presentation
*
* @return list with the read pictures or an empty list if the
* presentation doesn't contain pictures.
*/
public List<HSLFPictureData> getPictureData() {
if (_pictures == null) {
try {
readPictures();
} catch (IOException e) {
throw new CorruptPowerPointFileException(e.getMessage());
}
}
return Collections.unmodifiableList(_pictures);
}
return Collections.unmodifiableList(_pictures);
}
/**
* Gets embedded object data from the slide show.
@ -837,7 +847,7 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
List<HSLFObjectData> objects = new ArrayList<HSLFObjectData>();
for (Record r : _records) {
if (r instanceof ExOleObjStg) {
objects.add(new HSLFObjectData((ExOleObjStg)r));
objects.add(new HSLFObjectData((ExOleObjStg) r));
}
}
_objects = objects.toArray(new HSLFObjectData[objects.size()]);
@ -862,6 +872,7 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
private static class CountingOS extends OutputStream {
int count = 0;
public void write(int b) throws IOException {
count++;
}